diff --git a/.github/workflows/pull_request.yaml b/.github/workflows/pull_request.yaml index 1f56324..59f8177 100644 --- a/.github/workflows/pull_request.yaml +++ b/.github/workflows/pull_request.yaml @@ -25,6 +25,8 @@ jobs: name: Specification drift - task: check-pack name: Packaging and type resolution + - task: //#knip + name: Unused code report steps: - name: Check out repository uses: actions/checkout@v6 diff --git a/apps/jobnik-manager/package.json b/apps/jobnik-manager/package.json index 10887ab..6a7ce01 100644 --- a/apps/jobnik-manager/package.json +++ b/apps/jobnik-manager/package.json @@ -81,12 +81,10 @@ "devDependencies": { "@faker-js/faker": "^10.5.0", "@map-colonies/eslint-config": "^9.0.0", - "@map-colonies/infra-copilot-instructions": "^1.2.0", "@map-colonies/prettier-config": "^1.0.0", "@map-colonies/tsconfig": "^2.0.0", "@opentelemetry/sdk-trace-node": "^1.30.1", "@types/compression": "^1.7.5", - "@types/config": "^3.3.5", "@types/date-fns": "^2.5.3", "@types/express": "^4.17.17", "@types/express-serve-static-core": "^4.19.8", @@ -105,11 +103,9 @@ "eslint": "^10.0.0", "get-port-please": "^3.2.0", "is-ci": "^4.1.0", - "jest-create-mock-instance": "^2.0.0", "jest-extended": "^7.0.0", "jest-openapi": "^0.14.2", "prettier": "^3.9.5", - "pretty-quick": "^4.1.1", "prisma": "^6.19.0", "prisma-json-types-generator": "^3.6.2", "rimraf": "^6.1.2", diff --git a/apps/jobnik-manager/src/common/constants.ts b/apps/jobnik-manager/src/common/constants.ts index 8836a0a..2a97dd1 100644 --- a/apps/jobnik-manager/src/common/constants.ts +++ b/apps/jobnik-manager/src/common/constants.ts @@ -8,7 +8,6 @@ type SuccessMessagesObj = { }; export const SERVICE_NAME = readPackageJsonSync().name ?? 'unknown_service'; -export const DEFAULT_SERVER_PORT = 80; export const DB_CONNECTION_TIMEOUT = 20000; export const TX_TIMEOUT_MS = 30000; export const NODE_VERSION = process.versions.node; diff --git a/apps/jobnik-manager/src/common/dependencyRegistration.ts b/apps/jobnik-manager/src/common/dependencyRegistration.ts index 273c7a1..94455e3 100644 --- a/apps/jobnik-manager/src/common/dependencyRegistration.ts +++ b/apps/jobnik-manager/src/common/dependencyRegistration.ts @@ -3,7 +3,7 @@ import { container as defaultContainer } from 'tsyringe'; type Constructor = new (...args: unknown[]) => T; -export type Providers = ValueProvider | FactoryProvider | ClassProvider | Constructor; +type Providers = ValueProvider | FactoryProvider | ClassProvider | Constructor; export interface InjectionObject { token: InjectionToken; diff --git a/apps/jobnik-manager/src/common/errors.ts b/apps/jobnik-manager/src/common/errors.ts index 4351d9f..b319a1f 100644 --- a/apps/jobnik-manager/src/common/errors.ts +++ b/apps/jobnik-manager/src/common/errors.ts @@ -1,4 +1,4 @@ -import type { JobOperationStatus, StageOperationStatus, TaskOperationStatus } from '@src/db/prisma/generated/client'; +import type { JobOperationStatus, StageOperationStatus, TaskOperationStatus } from '@prismaClient'; export const prismaKnownErrors = { /**An operation failed because it depends on one or more records that were required but not found. {cause} */ diff --git a/apps/jobnik-manager/src/common/interfaces.ts b/apps/jobnik-manager/src/common/interfaces.ts deleted file mode 100644 index 455054c..0000000 --- a/apps/jobnik-manager/src/common/interfaces.ts +++ /dev/null @@ -1,4 +0,0 @@ -export interface IConfig { - get: (setting: string) => T; - has: (setting: string) => boolean; -} diff --git a/apps/jobnik-manager/src/common/semconv.ts b/apps/jobnik-manager/src/common/semconv.ts index dd7f880..b5809f8 100644 --- a/apps/jobnik-manager/src/common/semconv.ts +++ b/apps/jobnik-manager/src/common/semconv.ts @@ -1,48 +1,15 @@ // OpenTelemetry Messaging Semantic Conventions // Source: https://opentelemetry.io/docs/specs/semconv/messaging/messaging-spans/ +// Only the attributes this service actually sets on spans are kept here. -// Operation name of the messaging operation (e.g., 'send', 'ack', 'nack') -export const ATTR_MESSAGING_OPERATION_NAME = 'messaging.operation.name'; // Messaging system identifier (e.g., 'kafka', 'rabbitmq', 'aws_sqs') export const ATTR_MESSAGING_SYSTEM = 'messaging.system'; -// The type of the messaging operation (e.g., 'create', 'send', 'receive', 'process', 'settle') -export const ATTR_MESSAGING_OPERATION_TYPE = 'messaging.operation.type'; -// Unique identifier for the client that consumes or produces a message -export const ATTR_MESSAGING_CLIENT_ID = 'messaging.client.id'; -// Name of the consumer group -export const ATTR_MESSAGING_CONSUMER_GROUP_NAME = 'messaging.consumer.group.name'; // Name of the message destination (queue, topic, etc.) export const ATTR_MESSAGING_DESTINATION_NAME = 'messaging.destination.name'; -// Boolean: true if the destination is anonymous (unnamed or auto-generated) -export const ATTR_MESSAGING_DESTINATION_ANONYMOUS = 'messaging.destination.anonymous'; -// Boolean: true if the destination is temporary -export const ATTR_MESSAGING_DESTINATION_TEMPORARY = 'messaging.destination.temporary'; -// Low-cardinality template for the destination name -export const ATTR_MESSAGING_DESTINATION_TEMPLATE = 'messaging.destination.template'; -// Name of the destination subscription (if applicable) -export const ATTR_MESSAGING_DESTINATION_SUBSCRIPTION_NAME = 'messaging.destination.subscription.name'; -// Identifier of the partition (if applicable) -export const ATTR_MESSAGING_DESTINATION_PARTITION_ID = 'messaging.destination.partition.id'; -// Number of messages in a batch operation -export const ATTR_MESSAGING_BATCH_MESSAGE_COUNT = 'messaging.batch.message_count'; // Message ID (string, unique per message) export const ATTR_MESSAGING_MESSAGE_ID = 'messaging.message.id'; // Conversation ID (correlation ID) export const ATTR_MESSAGING_MESSAGE_CONVERSATION_ID = 'messaging.message.conversation_id'; -// Size of the message body in bytes -export const ATTR_MESSAGING_MESSAGE_BODY_SIZE = 'messaging.message.body.size'; -// Size of the message envelope (body + metadata) in bytes -export const ATTR_MESSAGING_MESSAGE_ENVELOPE_SIZE = 'messaging.message.envelope.size'; -// Peer address of the messaging intermediary node -export const ATTR_NETWORK_PEER_ADDRESS = 'network.peer.address'; -// Peer port of the messaging intermediary node -export const ATTR_NETWORK_PEER_PORT = 'network.peer.port'; -// Server address (domain, IP, or socket) -export const ATTR_SERVER_ADDRESS = 'server.address'; -// Server port number -export const ATTR_SERVER_PORT = 'server.port'; -// Error type if the messaging operation failed -export const ATTR_ERROR_TYPE = 'error.type'; // Runtime name of the process (e.g., 'nodejs', 'python', 'java') export const ATTR_PROCESS_RUNTIME_NAME = 'process.runtime.name'; // Runtime version of the process (e.g., 'nodejs 14.17.0') diff --git a/apps/jobnik-manager/src/common/utils/error-express-handler.ts b/apps/jobnik-manager/src/common/utils/error-express-handler.ts index f4fde08..dca5612 100644 --- a/apps/jobnik-manager/src/common/utils/error-express-handler.ts +++ b/apps/jobnik-manager/src/common/utils/error-express-handler.ts @@ -10,7 +10,7 @@ import { StatusCodes, getReasonPhrase } from 'http-status-codes'; * @property {StatusCodes} [statusCode] - The HTTP status code for the error response * @property {StatusCodes} [status] - Alternative property for HTTP status code */ -export interface HttpError extends Error { +interface HttpError extends Error { statusCode?: StatusCodes; status?: StatusCodes; code?: string; @@ -20,7 +20,7 @@ export interface HttpError extends Error { * Represents the structure of the error returned by the middleware. * stacktrace is only included in the response in development mode. */ -export interface ErrorResponse { +interface ErrorResponse { message: string; stacktrace?: string; code: string; diff --git a/apps/jobnik-manager/src/common/utils/pagination.ts b/apps/jobnik-manager/src/common/utils/pagination.ts index 2dc33f9..7cf23f7 100644 --- a/apps/jobnik-manager/src/common/utils/pagination.ts +++ b/apps/jobnik-manager/src/common/utils/pagination.ts @@ -10,8 +10,8 @@ interface PaginableDelegate { count: (args: never) => Prisma.PrismaPromise; } -export const DEFAULT_PAGE = 1; -export const DEFAULT_PAGE_SIZE = 10; +const DEFAULT_PAGE = 1; +const DEFAULT_PAGE_SIZE = 10; export interface PaginatedResult { total: number; diff --git a/apps/jobnik-manager/src/common/utils/promiseTimeout.ts b/apps/jobnik-manager/src/common/utils/promiseTimeout.ts index 7f6255c..1ead48b 100644 --- a/apps/jobnik-manager/src/common/utils/promiseTimeout.ts +++ b/apps/jobnik-manager/src/common/utils/promiseTimeout.ts @@ -1,4 +1,4 @@ -export class TimeoutError extends Error {} +class TimeoutError extends Error {} export const promiseTimeout = async (ms: number, promise: Promise): Promise => { // Create a promise that rejects in milliseconds diff --git a/apps/jobnik-manager/src/common/utils/tracingHelpers.ts b/apps/jobnik-manager/src/common/utils/tracingHelpers.ts index 0c23463..0478b00 100644 --- a/apps/jobnik-manager/src/common/utils/tracingHelpers.ts +++ b/apps/jobnik-manager/src/common/utils/tracingHelpers.ts @@ -1,11 +1,12 @@ import { context, propagation } from '@opentelemetry/api'; -export const DEFAULT_TRACEPARENT = '00-00000000000000000000000000000000-0000000000000000-00'; -export interface Carrier { +interface Carrier { traceparent?: string; tracestate?: string; } +export const DEFAULT_TRACEPARENT = '00-00000000000000000000000000000000-0000000000000000-00'; + /** * Type that ensures traceparent is required and tracestate is nullable */ @@ -44,9 +45,3 @@ export function resolveTraceContext(payload: OptionalTraceContext): ResolvedTrac tracestate: traceContext.tracestate ?? null, }; } - -/** - * Type helper that transforms a payload with optional trace context into one with required trace context. - * This ensures type safety when passing data to Prisma which requires these fields. - */ -export type WithRequiredTraceContext = Omit & ResolvedTraceContext; diff --git a/apps/jobnik-manager/src/jobs/models/models.ts b/apps/jobnik-manager/src/jobs/models/models.ts index 3bfc389..c089212 100644 --- a/apps/jobnik-manager/src/jobs/models/models.ts +++ b/apps/jobnik-manager/src/jobs/models/models.ts @@ -3,7 +3,6 @@ import type { Prisma } from '@prismaClient'; type JobModel = components['schemas']['job']; type JobCreateModel = components['schemas']['createJobPayload']; -type JobGetParams = components['parameters']; type JobFindCriteriaArg = operations['findJobsV1']['parameters']['query']; type JobsPaginatedResponse = components['schemas']['jobsPaginatedResponse']; @@ -15,4 +14,4 @@ type JobPrismaObject = Prisma.JobGetPay include: { stage: IncludeStages }; }>; -export type { JobModel, JobCreateModel, JobGetParams, JobFindCriteriaArg, JobPrismaObject, JobsPaginatedResponse }; +export type { JobModel, JobCreateModel, JobFindCriteriaArg, JobPrismaObject, JobsPaginatedResponse }; diff --git a/apps/jobnik-manager/src/stages/models/helper.ts b/apps/jobnik-manager/src/stages/models/helper.ts index 55055be..0ef6227 100644 --- a/apps/jobnik-manager/src/stages/models/helper.ts +++ b/apps/jobnik-manager/src/stages/models/helper.ts @@ -95,5 +95,3 @@ export { defaultStatusCounts, taskOperationStatusWithTotal, }; - -export type { StagePersistedSnapshot }; diff --git a/apps/jobnik-manager/src/stages/models/models.ts b/apps/jobnik-manager/src/stages/models/models.ts index b0841cf..d60cff8 100644 --- a/apps/jobnik-manager/src/stages/models/models.ts +++ b/apps/jobnik-manager/src/stages/models/models.ts @@ -1,4 +1,3 @@ -import type { Snapshot } from 'xstate'; import type { components, operations } from 'jobnik-openapi'; import type { Prisma, TaskOperationStatus } from '@prismaClient'; import type { JobPrismaObject } from '@src/jobs/models/models'; @@ -6,7 +5,6 @@ import type { PrismaTransaction } from '@src/db/types'; type StageModel = components['schemas']['getStageResponse']; type StageCreateModel = components['schemas']['createStagePayloadRequest']; -type StageCreateBody = StageCreateModel & { jobId: string; xstate: Snapshot }; type StageSummary = components['schemas']['summary']; type StageFindCriteriaArg = operations['getStagesV1']['parameters']['query']; type StagesPaginatedResponse = components['schemas']['stagesPaginatedResponse']; @@ -42,7 +40,6 @@ export type { StageFindCriteriaArg, StageCreateModel, StagePrismaObject, - StageCreateBody, UpdateSummaryCount, StageIncludingJob, StageEntityOptions, diff --git a/apps/jobnik-manager/src/tasks/models/taskStateMachine.ts b/apps/jobnik-manager/src/tasks/models/taskStateMachine.ts index ba95228..111442a 100644 --- a/apps/jobnik-manager/src/tasks/models/taskStateMachine.ts +++ b/apps/jobnik-manager/src/tasks/models/taskStateMachine.ts @@ -80,4 +80,3 @@ function updateTaskMachineState(status: TaskOperationStatus, xstate: PrismaJson. } export { taskStateMachine, updateTaskMachineState }; -export type { changeStatusOperations }; diff --git a/apps/jobnik-manager/tests/configurations/unit/jest.config.js b/apps/jobnik-manager/tests/configurations/unit/jest.config.js deleted file mode 100644 index 7f834c2..0000000 --- a/apps/jobnik-manager/tests/configurations/unit/jest.config.js +++ /dev/null @@ -1,44 +0,0 @@ -const { pathsToModuleNameMapper } = require('ts-jest'); -const { compilerOptions } = require('../../../tsconfig.json'); - -/** @type {import('jest').Config} */ -module.exports = { - transform: { - '^.+\\.ts$': ['@swc/jest'], - }, - moduleNameMapper: pathsToModuleNameMapper(compilerOptions.paths, { prefix: '/' }), - testMatch: ['/tests/unit/**/*.spec.ts'], - coverageReporters: ['text', 'html'], - collectCoverage: true, - collectCoverageFrom: [ - '/src/**/*.ts', - '!*/node_modules/', - '!/vendor/**', - '!*/common/**', - '!**/controllers/**', - '!**/routes/**', - '!/src/*', - '!/src/db/createConnection.ts', - '!/src/db/prisma/generated/client/**', - '!/src/**/models/models.ts', - '!/src/**/models/metrics.ts', - ], - - setupFilesAfterEnv: ['jest-extended/all'], - coverageDirectory: '/coverage', - reporters: [ - 'default', - ['jest-html-reporters', { multipleReportsUnitePath: './reports', pageTitle: 'unit', publicPath: './reports', filename: 'unit.html' }], - ], - rootDir: '../../../.', - setupFiles: ['/tests/configurations/jest.setup.ts'], - testEnvironment: 'node', - coverageThreshold: { - global: { - branches: 80, - functions: 80, - lines: 80, - statements: -10, - }, - }, -}; diff --git a/apps/jobnik-manager/tests/unit/data.ts b/apps/jobnik-manager/tests/unit/data.ts index cd4fb49..b47386d 100644 --- a/apps/jobnik-manager/tests/unit/data.ts +++ b/apps/jobnik-manager/tests/unit/data.ts @@ -29,18 +29,14 @@ failedStageActor.send({ type: 'pend' }); failedStageActor.send({ type: 'process' }); failedStageActor.send({ type: 'fail' }); -const waitingStageActor = createActor(stageStateMachine).start(); -waitingStageActor.send({ type: 'wait' }); - const retriedTaskActor = createActor(taskStateMachine).start(); retriedTaskActor.send({ type: 'pend' }); retriedTaskActor.send({ type: 'process' }); retriedTaskActor.send({ type: 'retry' }); -export const jobId = faker.string.uuid(); -export const stageId = faker.string.uuid(); -export const anotherStageId = faker.string.uuid(); +const stageId = faker.string.uuid(); +export const jobId = faker.string.uuid(); export const jobEntityWithoutStages = createJobEntity({ id: jobId }); export const stageEntity = createStageEntity({ id: stageId, jobId, data: { name: 'someStage' } }); @@ -55,7 +51,6 @@ export const inProgressStageXstatePersistentSnapshot = runningStageActor.getPers export const abortedStageXstatePersistentSnapshot = abortedStageActor.getPersistedSnapshot(); export const pendingStageXstatePersistentSnapshot = pendingStageActor.getPersistedSnapshot(); export const failedStageXstatePersistentSnapshot = failedStageActor.getPersistedSnapshot(); -export const waitingStageXstatePersistentSnapshot = waitingStageActor.getPersistedSnapshot(); export const retryTaskXstatePersistentSnapshot = retriedTaskActor.getPersistedSnapshot(); export const completedStageXstatePersistentSnapshot = completedStageActor.getPersistedSnapshot(); diff --git a/apps/jobnik-manager/tests/unit/generator.ts b/apps/jobnik-manager/tests/unit/generator.ts index f802840..e5cd4db 100644 --- a/apps/jobnik-manager/tests/unit/generator.ts +++ b/apps/jobnik-manager/tests/unit/generator.ts @@ -4,7 +4,6 @@ import type { Prisma, Stage, Task } from '@prismaClient'; import { JobOperationStatus, Priority, StageOperationStatus, TaskOperationStatus } from '@prismaClient'; import type { findAndLockTask } from '@src/db/prisma/generated/client/sql'; import { jobStateMachine } from '@src/jobs/models/jobStateMachine'; -import type { JobCreateModel } from '@src/jobs/models/models'; import { stageStateMachine } from '@src/stages/models/stageStateMachine'; import type { TaskPrismaObject } from '@src/tasks/models/models'; import { taskStateMachine } from '@src/tasks/models/taskStateMachine'; @@ -22,12 +21,6 @@ export interface StageWithTasks extends Prisma.StageGetPayload): JobWithStages { const jobEntity = { creationTime: new Date(), diff --git a/e2e/package.json b/e2e/package.json index 5efc25e..2df5e9b 100644 --- a/e2e/package.json +++ b/e2e/package.json @@ -3,7 +3,6 @@ "version": "1.0.0", "private": true, "description": "e2e test for the Jobnik platform", - "main": "index.js", "scripts": { "e2e": "vitest run", "e2e:watch": "vitest watch", diff --git a/knip.json b/knip.json index 3134bd3..2f44cd4 100644 --- a/knip.json +++ b/knip.json @@ -1,4 +1,28 @@ { "$schema": "https://unpkg.com/knip@6/schema.json", - "ignoreDependencies": ["@commitlint/cli", "prettier", "pretty-quick"] + "workspaces": { + "apps/jobnik-manager": { + "entry": ["src/instrumentation.mts"], + "ignore": ["src/db/prisma/generated/**", "src/common/generated/**"], + "ignoreUnresolved": ["./instrumentation.mjs"], + "ignoreDependencies": [ + "@map-colonies/prettier-config", + "@types/express-serve-static-core", + "@types/multer", + "@types/swagger-ui-express", + "@prismaClient" + ] + }, + "packages/jobnik-openapi": { + "ignoreDependencies": ["@map-colonies/prettier-config"] + }, + "packages/jobnik-sdk": { + "entry": ["tests/**/*.test-d.ts"], + "ignore": ["src/types/openapi.ts"], + "ignoreDependencies": ["@map-colonies/prettier-config"] + }, + "e2e": { + "ignoreDependencies": ["jobnik-manager"] + } + } } diff --git a/package.json b/package.json index 80f3da0..771ee79 100644 --- a/package.json +++ b/package.json @@ -28,6 +28,7 @@ "devDependencies": { "@commitlint/cli": "^21.2.2", "@commitlint/config-pnpm-scopes": "^21.2.0", + "@commitlint/types": "^21.2.0", "@map-colonies/commitlint-config": "^2.0.1", "@map-colonies/prettier-config": "^1.0.0", "husky": "^9.1.7", diff --git a/packages/jobnik-sdk/package.json b/packages/jobnik-sdk/package.json index 726aa20..ac5ad8d 100644 --- a/packages/jobnik-sdk/package.json +++ b/packages/jobnik-sdk/package.json @@ -68,11 +68,9 @@ "jest-extended": "^6.0.0", "jobnik-openapi": "workspace:*", "prettier": "^3.5.3", - "pretty-quick": "^4.1.1", "prom-client": "^15.1.3", "publint": "^0.3.24", "rimraf": "^6.0.1", - "typedoc": "^0.28.12", "typescript": "^5.8.2", "vitest": "^4.0.15" }, @@ -80,14 +78,12 @@ "@map-colonies/read-pkg": "^2.0.0", "@map-colonies/semantic-conventions": "^1.0.0", "@readme/openapi-parser": "^4.0.1", - "date-fns": "^4.1.0", "http-status-codes": "^2.3.0", "openapi-fetch": "^0.14.0", "openapi-types": "^12.1.3", "openapi-typescript-helpers": "^0.0.15", "opossum": "^9.0.0", - "undici": "^7.19.1", - "yaml": "^2.8.1" + "undici": "^7.19.1" }, "peerDependencies": { "@opentelemetry/api": "^1.9.0", diff --git a/packages/jobnik-sdk/src/api/middlewares/common.ts b/packages/jobnik-sdk/src/api/middlewares/common.ts index 81b93de..32d0a8a 100644 --- a/packages/jobnik-sdk/src/api/middlewares/common.ts +++ b/packages/jobnik-sdk/src/api/middlewares/common.ts @@ -1,69 +1,4 @@ -const PATH_SEGMENT_MIN_COUNT = 2; // Minimum segments for resource extraction (e.g., /jobs/{id}) - export interface ErrorContext { readonly url: string; readonly method: string; } - -/** - * Extracts resource information from URL path for better 404 error messages - */ -export const extractResourceInfo = (url: string): { resourceType: string; resourceId: string } => { - const urlPath = new URL(url).pathname; - const pathSegments = urlPath.split('/').filter(Boolean); - - let resourceType = 'Resource'; - let resourceId = 'unknown'; - - // For Job Manager Service API: /jobs/{id}, /stages/{id}, /tasks/{id} - if (pathSegments.length >= PATH_SEGMENT_MIN_COUNT) { - const typeSegment = pathSegments[pathSegments.length - PATH_SEGMENT_MIN_COUNT]; // e.g., 'jobs', 'stages', 'tasks' - const idSegment = pathSegments[pathSegments.length - 1]; // e.g., job ID - - if (typeSegment !== undefined && typeSegment.length > 0) { - // Convert plural to singular and capitalize - resourceType = typeSegment.endsWith('s') - ? // eslint-disable-next-line @typescript-eslint/no-magic-numbers - typeSegment.slice(0, -1).charAt(0).toUpperCase() + typeSegment.slice(1, -1) - : typeSegment.charAt(0).toUpperCase() + typeSegment.slice(1); - } - - if (idSegment !== undefined && idSegment.length > 0) { - resourceId = idSegment; - } - } - - return { resourceType, resourceId }; -}; - -/** - * Parses error response body to extract error message from Job Manager Service - */ -export const parseErrorResponse = async (response: Response, context: ErrorContext): Promise => { - const { url, method } = context; - let errorMessage = `HTTP ${response.status} error for ${method} ${url}`; - - try { - const responseText = await response.clone().text(); - if (responseText) { - try { - const errorBody = JSON.parse(responseText) as { message?: string }; - - // Extract message from Job Manager Service error response format - if (errorBody.message !== undefined && typeof errorBody.message === 'string') { - errorMessage = `${errorMessage}: ${errorBody.message}`; - } - } catch { - // If JSON parsing fails, include raw response text if it's short enough - const MAX_ERROR_TEXT_LENGTH = 200; - if (responseText.length <= MAX_ERROR_TEXT_LENGTH) { - errorMessage = `${errorMessage}: ${responseText}`; - } - } - } - } catch { - // Ignore errors when trying to read response body - } - - return errorMessage; -}; diff --git a/packages/jobnik-sdk/src/clients/index.ts b/packages/jobnik-sdk/src/clients/index.ts index d070160..e00fc25 100644 --- a/packages/jobnik-sdk/src/clients/index.ts +++ b/packages/jobnik-sdk/src/clients/index.ts @@ -1,2 +1 @@ export { Producer } from './producer'; -export { Consumer } from './consumer'; diff --git a/packages/jobnik-sdk/src/network/httpClient.ts b/packages/jobnik-sdk/src/network/httpClient.ts index b5835d5..21e5d63 100644 --- a/packages/jobnik-sdk/src/network/httpClient.ts +++ b/packages/jobnik-sdk/src/network/httpClient.ts @@ -204,4 +204,4 @@ export function createRetryAgent(options: HttpClientOptions = {}, logger: Logger return retryAgent; } -export type { HttpClientOptions, RetryOptions }; +export type { HttpClientOptions }; diff --git a/packages/jobnik-sdk/src/telemetry/logger.ts b/packages/jobnik-sdk/src/telemetry/logger.ts index b8571d4..c26ca35 100644 --- a/packages/jobnik-sdk/src/telemetry/logger.ts +++ b/packages/jobnik-sdk/src/telemetry/logger.ts @@ -1,7 +1,7 @@ /** * @inline */ -export interface LogFn { +interface LogFn { (obj: object, ...args: unknown[]): void; (obj: object, msg: string, ...args: unknown[]): void; (msg: string, ...args: unknown[]): void; diff --git a/packages/jobnik-sdk/src/telemetry/metrics-utils.ts b/packages/jobnik-sdk/src/telemetry/metrics-utils.ts index 47711f1..63a0d9b 100644 --- a/packages/jobnik-sdk/src/telemetry/metrics-utils.ts +++ b/packages/jobnik-sdk/src/telemetry/metrics-utils.ts @@ -83,15 +83,3 @@ export function categorizeError(error: unknown): 'timeout' | 'handler_error' | ' // Default to handler error (application code failure) return 'handler_error'; } - -/** - * Categorizes retry reasons for HTTP client metrics. - */ -export function categorizeRetryReason(error: unknown): 'status_code' | 'timeout' | 'network_error' { - if (error instanceof Error) { - const message = error.message.toLowerCase(); - if (message.includes('timeout')) return 'timeout'; - if (message.includes('network') || message.includes('fetch') || message.includes('econnreset')) return 'network_error'; - } - return 'status_code'; -} diff --git a/packages/jobnik-sdk/src/telemetry/semconv.ts b/packages/jobnik-sdk/src/telemetry/semconv.ts index daa9c86..72feb63 100644 --- a/packages/jobnik-sdk/src/telemetry/semconv.ts +++ b/packages/jobnik-sdk/src/telemetry/semconv.ts @@ -1,45 +1,16 @@ // OpenTelemetry Messaging Semantic Conventions // Source: https://opentelemetry.io/docs/specs/semconv/messaging/messaging-spans/ +// Only the attributes this SDK actually sets on spans are kept here. -// Operation name of the messaging operation (e.g., 'send', 'ack', 'nack') -export const ATTR_MESSAGING_OPERATION_NAME = 'messaging.operation.name'; // Messaging system identifier (e.g., 'kafka', 'rabbitmq', 'aws_sqs') export const ATTR_MESSAGING_SYSTEM = 'messaging.system'; -// The type of the messaging operation (e.g., 'create', 'send', 'receive', 'process', 'settle') -export const ATTR_MESSAGING_OPERATION_TYPE = 'messaging.operation.type'; // Unique identifier for the client that consumes or produces a message export const ATTR_MESSAGING_CLIENT_ID = 'messaging.client.id'; -// Name of the consumer group -export const ATTR_MESSAGING_CONSUMER_GROUP_NAME = 'messaging.consumer.group.name'; // Name of the message destination (queue, topic, etc.) export const ATTR_MESSAGING_DESTINATION_NAME = 'messaging.destination.name'; -// Boolean: true if the destination is anonymous (unnamed or auto-generated) -export const ATTR_MESSAGING_DESTINATION_ANONYMOUS = 'messaging.destination.anonymous'; -// Boolean: true if the destination is temporary -export const ATTR_MESSAGING_DESTINATION_TEMPORARY = 'messaging.destination.temporary'; -// Low-cardinality template for the destination name -export const ATTR_MESSAGING_DESTINATION_TEMPLATE = 'messaging.destination.template'; -// Name of the destination subscription (if applicable) -export const ATTR_MESSAGING_DESTINATION_SUBSCRIPTION_NAME = 'messaging.destination.subscription.name'; -// Identifier of the partition (if applicable) -export const ATTR_MESSAGING_DESTINATION_PARTITION_ID = 'messaging.destination.partition.id'; // Number of messages in a batch operation export const ATTR_MESSAGING_BATCH_MESSAGE_COUNT = 'messaging.batch.message_count'; // Message ID (string, unique per message) export const ATTR_MESSAGING_MESSAGE_ID = 'messaging.message.id'; // Conversation ID (correlation ID) export const ATTR_MESSAGING_MESSAGE_CONVERSATION_ID = 'messaging.message.conversation_id'; -// Size of the message body in bytes -export const ATTR_MESSAGING_MESSAGE_BODY_SIZE = 'messaging.message.body.size'; -// Size of the message envelope (body + metadata) in bytes -export const ATTR_MESSAGING_MESSAGE_ENVELOPE_SIZE = 'messaging.message.envelope.size'; -// Peer address of the messaging intermediary node -export const ATTR_NETWORK_PEER_ADDRESS = 'network.peer.address'; -// Peer port of the messaging intermediary node -export const ATTR_NETWORK_PEER_PORT = 'network.peer.port'; -// Server address (domain, IP, or socket) -export const ATTR_SERVER_ADDRESS = 'server.address'; -// Server port number -export const ATTR_SERVER_PORT = 'server.port'; -// Error type if the messaging operation failed -export const ATTR_ERROR_TYPE = 'error.type'; diff --git a/packages/jobnik-sdk/src/telemetry/trace.ts b/packages/jobnik-sdk/src/telemetry/trace.ts index 4710391..3588c1c 100644 --- a/packages/jobnik-sdk/src/telemetry/trace.ts +++ b/packages/jobnik-sdk/src/telemetry/trace.ts @@ -1,5 +1,5 @@ import { hostname } from 'node:os'; -import { Span, SpanOptions, SpanStatusCode, trace, context, SpanContext, propagation } from '@opentelemetry/api'; +import { Span, SpanOptions, SpanStatusCode, trace, SpanContext } from '@opentelemetry/api'; import { readPackageJsonSync } from '@map-colonies/read-pkg'; import { Logger } from '../types'; import { ATTR_MESSAGING_CLIENT_ID, ATTR_MESSAGING_SYSTEM } from './semconv'; @@ -9,46 +9,12 @@ const packageJson = readPackageJsonSync(); const SDK_INSTRUMENTATION_SCOPE = packageJson.name ?? 'unknown-sdk'; const SDK_VERSION = packageJson.version ?? 'unknown-version'; -export const DEFAULT_SPAN_CONTEXT: SpanContext = { - traceId: '00000000000000000000000000000000', - spanId: '0000000000000000', - traceFlags: 0, -}; - -export const BASE_ATTRIBUTES = { - [ATTR_MESSAGING_SYSTEM]: 'jobnik', - [ATTR_MESSAGING_CLIENT_ID]: hostname(), -}; - -export function getSpanContext(carrier: unknown): SpanContext | undefined { - const remoteContext = propagation.extract(context.active(), carrier); - return trace.getSpanContext(remoteContext); -} - -export async function withSpan(spanName: string, spanOptions: SpanOptions, logger: Logger, fn: (span: Span) => Promise): Promise { - if (spanOptions.attributes) { - spanOptions.attributes = { ...BASE_ATTRIBUTES, ...spanOptions.attributes }; - } else { - spanOptions.attributes = structuredClone(BASE_ATTRIBUTES); - } - return tracer.startActiveSpan(spanName, spanOptions, async (span) => { - try { - const result = await fn(span); - handleSpanOnSuccess(span); - return result; - } catch (error) { - handleSpanOnError(span, error); - throw error; - } - }); -} - /** * Ends the given span with status OK * @param span span to be ended * @group Tracing Utilities */ -export const handleSpanOnSuccess = (span: Span | undefined): void => { +const handleSpanOnSuccess = (span: Span | undefined): void => { if (!span) { return; } @@ -63,7 +29,7 @@ export const handleSpanOnSuccess = (span: Span | undefined): void => { * @param error error to be recorded * @group Tracing Utilities */ -export const handleSpanOnError = (span: Span | undefined, error?: unknown): void => { +const handleSpanOnError = (span: Span | undefined, error?: unknown): void => { if (!span) { return; } @@ -77,6 +43,35 @@ export const handleSpanOnError = (span: Span | undefined, error?: unknown): void span.end(); }; +export const DEFAULT_SPAN_CONTEXT: SpanContext = { + traceId: '00000000000000000000000000000000', + spanId: '0000000000000000', + traceFlags: 0, +}; + +export const BASE_ATTRIBUTES = { + [ATTR_MESSAGING_SYSTEM]: 'jobnik', + [ATTR_MESSAGING_CLIENT_ID]: hostname(), +}; + +export async function withSpan(spanName: string, spanOptions: SpanOptions, logger: Logger, fn: (span: Span) => Promise): Promise { + if (spanOptions.attributes) { + spanOptions.attributes = { ...BASE_ATTRIBUTES, ...spanOptions.attributes }; + } else { + spanOptions.attributes = structuredClone(BASE_ATTRIBUTES); + } + return tracer.startActiveSpan(spanName, spanOptions, async (span) => { + try { + const result = await fn(span); + handleSpanOnSuccess(span); + return result; + } catch (error) { + handleSpanOnError(span, error); + throw error; + } + }); +} + /** * @remarks * The tracer instance for the SDK. diff --git a/packages/jobnik-sdk/src/types/brands.ts b/packages/jobnik-sdk/src/types/brands.ts index 30882cd..7d36021 100644 --- a/packages/jobnik-sdk/src/types/brands.ts +++ b/packages/jobnik-sdk/src/types/brands.ts @@ -1,6 +1,6 @@ declare const brand: unique symbol; -export type Brand = T & { [brand]: Brand }; +type Brand = T & { [brand]: Brand }; /** * Branded type for job identifiers. diff --git a/packages/jobnik-sdk/src/types/task.ts b/packages/jobnik-sdk/src/types/task.ts index ee68fe0..6e5a2fa 100644 --- a/packages/jobnik-sdk/src/types/task.ts +++ b/packages/jobnik-sdk/src/types/task.ts @@ -11,8 +11,6 @@ export interface TaskData { data: TaskPayload; } -export type ValidTaskType = Extract | (string & {}); - export type InferTaskData> = StageType extends Extract ? StageTypes[StageType]['task'] : TaskData; diff --git a/packages/jobnik-sdk/src/types/utils.ts b/packages/jobnik-sdk/src/types/utils.ts index 6afdd3c..2b51d3f 100644 --- a/packages/jobnik-sdk/src/types/utils.ts +++ b/packages/jobnik-sdk/src/types/utils.ts @@ -1,5 +1,3 @@ export type Prettify = { [K in keyof T]: T[K]; } & {}; - -export type IndexerType = string | number | symbol; diff --git a/packages/jobnik-sdk/typedoc.json b/packages/jobnik-sdk/typedoc.json deleted file mode 100644 index 87e78ff..0000000 --- a/packages/jobnik-sdk/typedoc.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "entryPoints": ["src/index.ts"], - "out": "docs", - "excludeInternal": true, - "tsconfig": "tsconfig.build.json" -} diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 4e0bb02..08f6b48 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -17,6 +17,9 @@ importers: '@commitlint/config-pnpm-scopes': specifier: ^21.2.0 version: 21.2.2 + '@commitlint/types': + specifier: ^21.2.0 + version: 21.2.0 '@map-colonies/commitlint-config': specifier: ^2.0.1 version: 2.0.1 @@ -138,9 +141,6 @@ importers: '@map-colonies/eslint-config': specifier: ^9.0.0 version: 9.0.0(@typescript-eslint/utils@8.67.0(eslint@10.9.0(jiti@2.7.0))(typescript@5.9.3))(@vitest/eslint-plugin@1.6.27(@typescript-eslint/eslint-plugin@8.67.0(@typescript-eslint/parser@8.67.0(eslint@10.9.0(jiti@2.7.0))(typescript@5.9.3))(eslint@10.9.0(jiti@2.7.0))(typescript@5.9.3))(eslint@10.9.0(jiti@2.7.0))(typescript@5.9.3)(vitest@4.1.11))(eslint@10.9.0(jiti@2.7.0))(typescript@5.9.3) - '@map-colonies/infra-copilot-instructions': - specifier: ^1.2.0 - version: 1.2.0 '@map-colonies/prettier-config': specifier: ^1.0.0 version: 1.0.0 @@ -153,9 +153,6 @@ importers: '@types/compression': specifier: ^1.7.5 version: 1.8.1 - '@types/config': - specifier: ^3.3.5 - version: 3.3.5 '@types/date-fns': specifier: ^2.5.3 version: 2.6.3 @@ -210,9 +207,6 @@ importers: is-ci: specifier: ^4.1.0 version: 4.1.0 - jest-create-mock-instance: - specifier: ^2.0.0 - version: 2.0.0 jest-extended: specifier: ^7.0.0 version: 7.0.0(typescript@5.9.3) @@ -222,9 +216,6 @@ importers: prettier: specifier: ^3.9.5 version: 3.9.6 - pretty-quick: - specifier: ^4.1.1 - version: 4.2.2(prettier@3.9.6) prisma: specifier: ^6.19.0 version: 6.19.3(typescript@5.9.3) @@ -361,9 +352,6 @@ importers: '@readme/openapi-parser': specifier: ^4.0.1 version: 4.1.2(openapi-types@12.1.3) - date-fns: - specifier: ^4.1.0 - version: 4.4.0 http-status-codes: specifier: ^2.3.0 version: 2.3.0 @@ -382,9 +370,6 @@ importers: undici: specifier: 7.19.1 version: 7.19.1 - yaml: - specifier: ^2.8.1 - version: 2.9.0 devDependencies: '@arethetypeswrong/cli': specifier: ^0.18.5 @@ -437,9 +422,6 @@ importers: prettier: specifier: ^3.5.3 version: 3.9.6 - pretty-quick: - specifier: ^4.1.1 - version: 4.2.2(prettier@3.9.6) prom-client: specifier: ^15.1.3 version: 15.1.3 @@ -449,9 +431,6 @@ importers: rimraf: specifier: ^6.0.1 version: 6.1.3 - typedoc: - specifier: ^0.28.12 - version: 0.28.20(typescript@5.9.3) typescript: specifier: ^5.8.2 version: 5.9.3 @@ -889,9 +868,6 @@ packages: resolution: {integrity: sha512-3RQHgEtvL1Frl/d1cSreo7qhJ3Gk1OdNUai/CtZ8G+wYeRQnJih3s9xJ9/kgYekPQRdwgh0HXRPqMlzWGwivIQ==} engines: {node: ^20.19.0 || ^22.13.0 || ^23.5.0 || >=24.0.0, npm: '>=10'} - '@gerrit0/mini-shiki@3.23.0': - resolution: {integrity: sha512-bEMORlG0cqdjVyCEuU0cDQbORWX+kYCeo0kV1lbxF5bt4r7SID2l9bqsxJEM0zndaxpOUT7riCyIVEuqq/Ynxg==} - '@godaddy/terminus@4.12.1': resolution: {integrity: sha512-Tm+wVu1/V37uZXcT7xOhzdpFoovQReErff8x3y82k6YyWa1gzxWBjTyrx4G2enjEqoXPnUUmJ3MOmwH+TiP6Sw==} @@ -1040,10 +1016,6 @@ packages: resolution: {integrity: sha512-qtuKfNOE9WmEkLD175SI26xO+X8mloxlTE8JrR/gypaqIa8+XdGYNynDKrQK+83t5vMfToMLXhTzmGtT8HgXAg==} engines: {node: '>=24'} - '@map-colonies/infra-copilot-instructions@1.2.0': - resolution: {integrity: sha512-iFoU10Vq6xqLAXZvpnFmgqMh667ae3PueKiE7KT8g5x+vFSJ1W2HJjHzeScqditI1l9a7Xxmpw6GmldGi2s6WA==} - engines: {node: '>=20'} - '@map-colonies/js-logger@4.1.0': resolution: {integrity: sha512-iPFEkV6OiO9iD0dRhDhr4k3h44izqTZtW/cxKQXzW6SVeIRTyLYm2Myh9Za6AHAywrs7DZMWygAFhMfuxV76mA==} engines: {node: '>=24'} @@ -2285,21 +2257,6 @@ packages: '@scarf/scarf@1.4.0': resolution: {integrity: sha512-xxeapPiUXdZAE3che6f3xogoJPeZgig6omHEy1rIY5WVsB3H2BHNnZH+gHG6x91SCWyQCzWGsuL2Hh3ClO5/qQ==} - '@shikijs/engine-oniguruma@3.23.0': - resolution: {integrity: sha512-1nWINwKXxKKLqPibT5f4pAFLej9oZzQTsby8942OTlsJzOBZ0MWKiwzMsd+jhzu8YPCHAswGnnN1YtQfirL35g==} - - '@shikijs/langs@3.23.0': - resolution: {integrity: sha512-2Ep4W3Re5aB1/62RSYQInK9mM3HsLeB91cHqznAJMuylqjzNVAVCMnNWRHFtcNHXsoNRayP9z1qj4Sq3nMqYXg==} - - '@shikijs/themes@3.23.0': - resolution: {integrity: sha512-5qySYa1ZgAT18HR/ypENL9cUSGOeI2x+4IvYJu4JgVJdizn6kG4ia5Q1jDEOi7gTbN4RbuYtmHh0W3eccOrjMA==} - - '@shikijs/types@3.23.0': - resolution: {integrity: sha512-3JZ5HXOZfYjsYSk0yPwBrkupyYSLpAE26Qc0HLghhZNGTZg/SKxXIIgoxOpmmeQP0RRSDJTk1/vPfw9tbw+jSQ==} - - '@shikijs/vscode-textmate@10.0.2': - resolution: {integrity: sha512-83yeghZ2xxin3Nj8z1NMd/NCuca+gsYXswywDy5bHvwlWL8tpTQmzGeUuHd9FC3E/SBEMvzJRwWEOz5gGes9Qg==} - '@simple-libs/child-process-utils@2.0.0': resolution: {integrity: sha512-dvNoRKLijXnD0XoJAz94pbNuB5GQgDr55UhpSPhffDkTT0Cmcqh9jSCOtwfT2d4H6MI9E7c4SgtMuJXZ6F3c6A==} engines: {node: '>=22'} @@ -2372,9 +2329,6 @@ packages: '@types/compression@1.8.1': resolution: {integrity: sha512-kCFuWS0ebDbmxs0AXYn6e2r2nrGAb5KwQhknjSPSPgJcGd8+HVSILlUyFhGqML2gk39HcG7D1ydW9/qpYkN00Q==} - '@types/config@3.3.5': - resolution: {integrity: sha512-itq2HtXQBrNUKwMNZnb9mBRE3T99VYCdl1gjST9rq+9kFaB1iMMGuDeZnP88qid73DnpAMKH9ZolqDpS1Lz7+w==} - '@types/connect@3.4.38': resolution: {integrity: sha512-K6uROf1LD88uDQqJCktA4yzL1YYAK6NgfsI0v/mTgyPKWsX1CnJ0XPSDhViejru1GcRkLWb8RlzFYJRqGUbaug==} @@ -2400,9 +2354,6 @@ packages: '@types/express@4.17.25': resolution: {integrity: sha512-dVd04UKsfpINUnK0yBoYHDF3xu7xVH4BuDotC/xGuycx4CgbP48X/KF/586bcObxT0HENHXEU8Nqtu6NR+eKhw==} - '@types/hast@3.0.5': - resolution: {integrity: sha512-rp/ezSWaD1m44dPKICGhiskI13nVr7qTloFwDa/IYkhhf5nzwP+zIQcIJh3WIFSBOy/H1PzB40jPjMDksN4F+g==} - '@types/http-errors@2.0.5': resolution: {integrity: sha512-r8Tayk8HJnX0FztbZN7oVqGccWgw98T/0neJphO91KkmOzug1KkofZURD4UaD5uH8AqcFLfdPErnBod0u71/qg==} @@ -2499,9 +2450,6 @@ packages: '@types/tough-cookie@4.0.5': resolution: {integrity: sha512-/Ad8+nIOV7Rl++6f1BdKxFSMgmoqEoYbHRpPcx3JEfv8VRsQe9Z4mCXeJBzxs7mbHY/XOZZuXlRNfhpVPbs6ZA==} - '@types/unist@3.0.3': - resolution: {integrity: sha512-ko/gIFJRv177XgZsZcBwnqJN5x/Gien8qNOn0D5bQU/zAzVf9Zt3BlcUiLqhV9y4ARk0GbT3tnUiPNgnTXzc/Q==} - '@types/yargs-parser@21.0.3': resolution: {integrity: sha512-I4q9QU9MQv4oEOz4tAHJtNz1cwuLxn2F3xcc2iV5WdqLPpUnj30aUuxt1mAxYTG+oe8CZMV/+6rU4S4gRDzqtQ==} @@ -3455,10 +3403,6 @@ packages: end-of-stream@1.4.5: resolution: {integrity: sha512-ooEGc6HP26xXq/N+GCGOT0JKCLDGrq2bQUZrQ7gyrJiZANJ/8YDTxTpQBXGMn+WbIQXNVpyWymm7KYVICQnyOg==} - entities@4.5.0: - resolution: {integrity: sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==} - engines: {node: '>=0.12'} - env-paths@2.2.1: resolution: {integrity: sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==} engines: {node: '>=6'} @@ -4046,9 +3990,6 @@ packages: resolution: {integrity: sha512-HGYWWS/ehqTV3xN10i23tkPkpH46MLCIMFNCaaKNavAXTF1RkqxawEPtnjnGZ6XKSInBKkiOA5BKS+aZiY3AvA==} engines: {node: '>=8'} - jest-create-mock-instance@2.0.0: - resolution: {integrity: sha512-gW3H87m8hF72JMFPMEorF2jnEyV31XpaOYtDqeRNSwFT73+MNZvbUKQfCbdixxOrCCppToSPmi9gGygIzms6Eg==} - jest-diff@26.6.2: resolution: {integrity: sha512-6m+9Z3Gv9wN0WFVasqjCL/06+EFCMTqDEUl/b87HYK2rAPTyfz4ZIuSlPhY51PIQRWx5TaxeF1qmXKe9gfN3sA==} engines: {node: '>= 10.14.2'} @@ -4190,9 +4131,6 @@ packages: lines-and-columns@1.2.4: resolution: {integrity: sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==} - linkify-it@5.0.2: - resolution: {integrity: sha512-ONTm2jCMAVZjgQa/Fy1kScXsuOoF5NPTsoFBdE1KVIZ2vAh/r9+Bqo+0jINCBYnavTPQZz38QzFTme79ENoN3Q==} - locate-path@6.0.0: resolution: {integrity: sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==} engines: {node: '>=10'} @@ -4227,9 +4165,6 @@ packages: resolution: {integrity: sha512-4pfM1Ff0x50o0tQwb5ucw/RzNyD0/YJME6IVcStalZuMWxdt3sR3huStTtxz4PUmvZfRguvDejasvQ2kifR11g==} engines: {node: 20 || >=22} - lunr@2.3.9: - resolution: {integrity: sha512-zTU3DaZaF3Rt9rhN3uBMGQD3dD2/vFQqnvZCDv4dl5iOzq2IZQqTxu90r4E5J+nP70J3ilqVCrbho2eWaeW8Ow==} - magic-string@0.30.21: resolution: {integrity: sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==} @@ -4240,10 +4175,6 @@ packages: resolution: {integrity: sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw==} engines: {node: '>=10'} - markdown-it@14.3.0: - resolution: {integrity: sha512-RCEsPjR+sr0x+AuYp601tKTkgFG4YEPLCzHST3cQ/fhlJkqAkz1L2/Qbp1j9qw5SBwQHFBoW8+hoN5xssOF0Tw==} - hasBin: true - marked-terminal@7.3.0: resolution: {integrity: sha512-t4rBvPsHc57uE/2nJOLmMbZCQ4tgAccAED3ngXQqW6g+TxA488JzJ+FK3lQkzBQOI1mRV/r/Kq+1ZlJ4D0owQw==} engines: {node: '>=16.0.0'} @@ -4264,9 +4195,6 @@ packages: resolution: {integrity: sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==} engines: {node: '>= 0.4'} - mdurl@2.1.0: - resolution: {integrity: sha512-1+HBaOx0zi/dQWht8rNv9MYf9qqpqL/kxI0hXImU6Y547zM6Sni8BQibt7ifgMcYtQg41ao3Ivd6cnSM86inpg==} - media-typer@0.3.0: resolution: {integrity: sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==} engines: {node: '>= 0.6'} @@ -4805,10 +4733,6 @@ packages: pump@3.0.4: resolution: {integrity: sha512-VS7sjc6KR7e1ukRFhQSY5LM2uBWAUPiOPa/A3mkKmiMwSmRFUITt0xuj+/lesgnCv+dPIEYlkzrcyXgquIHMcA==} - punycode.js@2.3.1: - resolution: {integrity: sha512-uxFIHU0YlHYhDQtV4R9J6a52SLx28BCjT+4ieh7IGbgwVJWO+km431c4yRlREUAsAmt/uMjQUyQHNEPf0M39CA==} - engines: {node: '>=6'} - punycode@2.3.1: resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==} engines: {node: '>=6'} @@ -5312,13 +5236,6 @@ packages: typedarray@0.0.6: resolution: {integrity: sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA==} - typedoc@0.28.20: - resolution: {integrity: sha512-uSKqkh8Cr48vllnEy+jdaAgOeR6Y+QCBW7usgUsKj7gJEfR7stw9U/fE49LBnj2tPRKPY0c0EBJSWe9Appmplg==} - engines: {node: '>= 18', pnpm: '>= 10'} - hasBin: true - peerDependencies: - typescript: 5.0.x || 5.1.x || 5.2.x || 5.3.x || 5.4.x || 5.5.x || 5.6.x || 5.7.x || 5.8.x || 5.9.x || 6.0.x - typeof@1.0.0: resolution: {integrity: sha512-Pze0mIxYXhaJdpw1ayMzOA7rtGr1OmsTY/Z+FWtRKIqXFz6aoDLjqdbWE/tcIBSC8nhnVXiRrEXujodR/xiFAA==} @@ -5344,9 +5261,6 @@ packages: engines: {node: '>=16.20.0'} hasBin: true - uc.micro@2.1.0: - resolution: {integrity: sha512-ARDJmphmdvUk6Glw7y9DQ2bFkKBHwQHLi2lsaH6PPmz/Ka9sFOBsBluozhDltWmnv9u/cF6Rt87znRTPV+yp/A==} - unbash@4.0.10: resolution: {integrity: sha512-b7zoBQvpWp0vuN5q2vK2RRBR2SvuruQAs50DApdDveBSn3eSYd84IaHodFqQIMlvY9K2VnyBUEXgwOBuGU9GBg==} engines: {node: '>=14'} @@ -6060,14 +5974,6 @@ snapshots: '@faker-js/faker@10.6.0': {} - '@gerrit0/mini-shiki@3.23.0': - dependencies: - '@shikijs/engine-oniguruma': 3.23.0 - '@shikijs/langs': 3.23.0 - '@shikijs/themes': 3.23.0 - '@shikijs/types': 3.23.0 - '@shikijs/vscode-textmate': 10.0.2 - '@godaddy/terminus@4.12.1': dependencies: stoppable: 1.1.0 @@ -6230,8 +6136,6 @@ snapshots: http-status-codes: 2.3.0 pino-http: 11.0.0 - '@map-colonies/infra-copilot-instructions@1.2.0': {} - '@map-colonies/js-logger@4.1.0(@opentelemetry/api@1.9.1)': dependencies: '@map-colonies/read-pkg': 2.0.0 @@ -7637,26 +7541,6 @@ snapshots: '@scarf/scarf@1.4.0': {} - '@shikijs/engine-oniguruma@3.23.0': - dependencies: - '@shikijs/types': 3.23.0 - '@shikijs/vscode-textmate': 10.0.2 - - '@shikijs/langs@3.23.0': - dependencies: - '@shikijs/types': 3.23.0 - - '@shikijs/themes@3.23.0': - dependencies: - '@shikijs/types': 3.23.0 - - '@shikijs/types@3.23.0': - dependencies: - '@shikijs/vscode-textmate': 10.0.2 - '@types/hast': 3.0.5 - - '@shikijs/vscode-textmate@10.0.2': {} - '@simple-libs/child-process-utils@2.0.0': dependencies: '@simple-libs/stream-utils': 2.0.0 @@ -7717,8 +7601,6 @@ snapshots: '@types/express': 4.17.25 '@types/node': 25.9.5 - '@types/config@3.3.5': {} - '@types/connect@3.4.38': dependencies: '@types/node': 24.13.3 @@ -7749,10 +7631,6 @@ snapshots: '@types/qs': 6.15.1 '@types/serve-static': 1.15.10 - '@types/hast@3.0.5': - dependencies: - '@types/unist': 3.0.3 - '@types/http-errors@2.0.5': {} '@types/istanbul-lib-coverage@2.0.6': {} @@ -7880,8 +7758,6 @@ snapshots: '@types/tough-cookie@4.0.5': {} - '@types/unist@3.0.3': {} - '@types/yargs-parser@21.0.3': {} '@types/yargs@15.0.20': @@ -8172,7 +8048,7 @@ snapshots: obug: 2.1.4 std-env: 4.2.0 tinyrainbow: 3.1.1 - vitest: 4.1.11(@opentelemetry/api@1.9.1)(@types/node@24.13.3)(@vitest/coverage-v8@4.1.11)(@vitest/ui@4.1.11)(vite@7.3.6(@types/node@24.13.3)(jiti@2.7.0)(yaml@2.9.0)) + vitest: 4.1.11(@opentelemetry/api@1.9.1)(@types/node@25.9.5)(@vitest/coverage-v8@4.1.11)(@vitest/ui@4.1.11)(vite@7.3.6(@types/node@25.9.5)(jiti@2.7.0)(yaml@2.9.0)) '@vitest/eslint-plugin@1.6.27(@typescript-eslint/eslint-plugin@8.67.0(@typescript-eslint/parser@8.67.0(eslint@10.9.0(jiti@2.7.0))(typescript@5.9.3))(eslint@10.9.0(jiti@2.7.0))(typescript@5.9.3))(eslint@10.9.0(jiti@2.7.0))(typescript@5.9.3)(vitest@4.1.11)': dependencies: @@ -8285,7 +8161,7 @@ snapshots: sirv: 3.0.2 tinyglobby: 0.2.17 tinyrainbow: 3.1.1 - vitest: 4.1.11(@opentelemetry/api@1.9.1)(@types/node@24.13.3)(@vitest/coverage-v8@4.1.11)(@vitest/ui@4.1.11)(vite@7.3.6(@types/node@24.13.3)(jiti@2.7.0)(yaml@2.9.0)) + vitest: 4.1.11(@opentelemetry/api@1.9.1)(@types/node@25.9.5)(@vitest/coverage-v8@4.1.11)(@vitest/ui@4.1.11)(vite@7.3.6(@types/node@25.9.5)(jiti@2.7.0)(yaml@2.9.0)) '@vitest/utils@3.2.7': dependencies: @@ -8812,8 +8688,6 @@ snapshots: dependencies: once: 1.4.0 - entities@4.5.0: {} - env-paths@2.2.1: {} environment@1.1.0: {} @@ -9555,8 +9429,6 @@ snapshots: html-escaper: 2.0.2 istanbul-lib-report: 3.0.1 - jest-create-mock-instance@2.0.0: {} - jest-diff@26.6.2: dependencies: chalk: 4.1.2 @@ -9690,10 +9562,6 @@ snapshots: lines-and-columns@1.2.4: {} - linkify-it@5.0.2: - dependencies: - uc.micro: 2.1.0 - locate-path@6.0.0: dependencies: p-locate: 5.0.0 @@ -9719,8 +9587,6 @@ snapshots: lru-cache@11.5.2: {} - lunr@2.3.9: {} - magic-string@0.30.21: dependencies: '@jridgewell/sourcemap-codec': 1.5.5 @@ -9735,15 +9601,6 @@ snapshots: dependencies: semver: 7.8.5 - markdown-it@14.3.0: - dependencies: - argparse: 2.0.1 - entities: 4.5.0 - linkify-it: 5.0.2 - mdurl: 2.1.0 - punycode.js: 2.3.1 - uc.micro: 2.1.0 - marked-terminal@7.3.0(marked@9.1.6): dependencies: ansi-escapes: 7.3.0 @@ -9761,8 +9618,6 @@ snapshots: math-intrinsics@1.1.0: {} - mdurl@2.1.0: {} - media-typer@0.3.0: {} media-typer@1.1.1: {} @@ -10383,8 +10238,6 @@ snapshots: end-of-stream: 1.4.5 once: 1.4.0 - punycode.js@2.3.1: {} - punycode@2.3.1: {} pure-rand@6.1.0: {} @@ -10917,15 +10770,6 @@ snapshots: typedarray@0.0.6: {} - typedoc@0.28.20(typescript@5.9.3): - dependencies: - '@gerrit0/mini-shiki': 3.23.0 - lunr: 2.3.9 - markdown-it: 14.3.0 - minimatch: 10.2.6 - typescript: 5.9.3 - yaml: 2.9.0 - typeof@1.0.0: {} typescript-eslint@8.67.0(eslint@10.9.0(jiti@2.7.0))(typescript@5.9.3): @@ -10977,8 +10821,6 @@ snapshots: '@typescript/typescript-win32-arm64': 7.0.2 '@typescript/typescript-win32-x64': 7.0.2 - uc.micro@2.1.0: {} - unbash@4.0.10: {} undici-types@7.18.2: {} diff --git a/turbo.json b/turbo.json index ebc1c2d..866d968 100644 --- a/turbo.json +++ b/turbo.json @@ -56,6 +56,10 @@ "check-dist": { "dependsOn": ["build"], "outputs": [] + }, + "//#knip": { + "dependsOn": [], + "outputLogs": "errors-only" } } }