@vritti/api-sdk 0.4.3 → 0.4.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (67) hide show
  1. package/dist/auth.cjs +58 -17
  2. package/dist/auth.cjs.map +1 -1
  3. package/dist/auth.d.cts +1 -1
  4. package/dist/auth.d.ts +1 -1
  5. package/dist/auth.js +58 -17
  6. package/dist/auth.js.map +1 -1
  7. package/dist/cache.cjs +51 -17
  8. package/dist/cache.cjs.map +1 -1
  9. package/dist/cache.js +51 -17
  10. package/dist/cache.js.map +1 -1
  11. package/dist/catalog-resolver.d.cts +2 -2
  12. package/dist/catalog-resolver.d.ts +2 -2
  13. package/dist/{code-pattern-BP4zkNtT.d.cts → code-pattern-DMlbIwwn.d.cts} +3 -3
  14. package/dist/{code-pattern-BP4zkNtT.d.ts → code-pattern-DMlbIwwn.d.ts} +3 -3
  15. package/dist/data-table.cjs +154 -48
  16. package/dist/data-table.cjs.map +1 -1
  17. package/dist/data-table.js +154 -48
  18. package/dist/data-table.js.map +1 -1
  19. package/dist/database.cjs +101 -31
  20. package/dist/database.cjs.map +1 -1
  21. package/dist/database.js +101 -31
  22. package/dist/database.js.map +1 -1
  23. package/dist/decorators.cjs +1 -1
  24. package/dist/decorators.cjs.map +1 -1
  25. package/dist/decorators.d.cts +2 -2
  26. package/dist/decorators.d.ts +2 -2
  27. package/dist/decorators.js +1 -1
  28. package/dist/decorators.js.map +1 -1
  29. package/dist/drizzle-pg-core.cjs +1 -1
  30. package/dist/drizzle-pg-core.cjs.map +1 -1
  31. package/dist/drizzle-pg-core.d.cts +1 -1
  32. package/dist/drizzle-pg-core.d.ts +1 -1
  33. package/dist/drizzle-pg-core.js +1 -1
  34. package/dist/drizzle-pg-core.js.map +1 -1
  35. package/dist/email.cjs +22 -6
  36. package/dist/email.cjs.map +1 -1
  37. package/dist/email.js +22 -6
  38. package/dist/email.js.map +1 -1
  39. package/dist/files.cjs +1 -1
  40. package/dist/files.cjs.map +1 -1
  41. package/dist/files.d.cts +3 -3
  42. package/dist/files.d.ts +3 -3
  43. package/dist/files.js +1 -1
  44. package/dist/files.js.map +1 -1
  45. package/dist/filters.cjs +18 -4
  46. package/dist/filters.cjs.map +1 -1
  47. package/dist/filters.js +18 -4
  48. package/dist/filters.js.map +1 -1
  49. package/dist/index.d.cts +1 -1
  50. package/dist/index.d.ts +1 -1
  51. package/dist/license.d.cts +1 -1
  52. package/dist/license.d.ts +1 -1
  53. package/dist/logger.cjs +49 -15
  54. package/dist/logger.cjs.map +1 -1
  55. package/dist/logger.js +49 -15
  56. package/dist/logger.js.map +1 -1
  57. package/dist/nats.cjs +51 -19
  58. package/dist/nats.cjs.map +1 -1
  59. package/dist/nats.js +50 -18
  60. package/dist/nats.js.map +1 -1
  61. package/dist/root.cjs +44 -12
  62. package/dist/root.cjs.map +1 -1
  63. package/dist/root.js +44 -12
  64. package/dist/root.js.map +1 -1
  65. package/dist/{types-BQY0Aa1p.d.cts → types-VDKSjje5.d.cts} +1 -1
  66. package/dist/{types-BQY0Aa1p.d.ts → types-VDKSjje5.d.ts} +1 -1
  67. package/package.json +38 -38
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/filters/index.ts","../src/filters/error-code.ts","../src/filters/problem-extraction.ts","../src/filters/graphql-format-error.ts","../src/filters/http-exception.filter.ts","../src/exceptions/conflict.exception.ts","../src/exceptions/base-field.exception.ts","../src/filters/pg-error.translator.ts","../src/filters/transport-aware-exception.filter.ts"],"sourcesContent":["// Machine-readable error contract + status mapper (shared across HTTP and GraphQL transports).\n\nexport { ErrorCode, errorCodeFromStatus } from './error-code';\n// GraphQL error shaping (Apollo formatError factory) — composes with TransportAwareExceptionFilter.\nexport {\n createGraphqlFormatError,\n type FormattedErrorExtensions,\n type GraphqlFormatErrorOptions,\n} from './graphql-format-error';\nexport { getHttpStatusTitle, HttpExceptionFilter } from './http-exception.filter';\nexport { TransportAwareExceptionFilter } from './transport-aware-exception.filter';\n// RpcProblemExceptionFilter is exported from '@vritti/api-sdk/nats' (it needs @nestjs/microservices).\n","import { HttpStatus } from '@nestjs/common';\n\nexport enum ErrorCode {\n UNAUTHENTICATED = 'UNAUTHENTICATED',\n FORBIDDEN = 'FORBIDDEN',\n NOT_FOUND = 'NOT_FOUND',\n VALIDATION_FAILED = 'VALIDATION_FAILED',\n CONFLICT = 'CONFLICT',\n RATE_LIMITED = 'RATE_LIMITED',\n BAD_REQUEST = 'BAD_REQUEST',\n INTERNAL = 'INTERNAL',\n}\n\n// Maps an HTTP status code to the canonical ErrorCode so HTTP and GraphQL classify identically.\nexport function errorCodeFromStatus(status: number): ErrorCode {\n switch (status) {\n case HttpStatus.UNAUTHORIZED: // 401\n return ErrorCode.UNAUTHENTICATED;\n case HttpStatus.FORBIDDEN: // 403\n return ErrorCode.FORBIDDEN;\n case HttpStatus.NOT_FOUND: // 404\n return ErrorCode.NOT_FOUND;\n case HttpStatus.BAD_REQUEST: // 400\n case HttpStatus.UNPROCESSABLE_ENTITY: // 422\n return ErrorCode.VALIDATION_FAILED;\n case HttpStatus.CONFLICT: // 409\n return ErrorCode.CONFLICT;\n case HttpStatus.TOO_MANY_REQUESTS: // 429\n return ErrorCode.RATE_LIMITED;\n default:\n // Any other 4xx is a generic bad request; 5xx and unknown collapse to INTERNAL.\n if (status >= 400 && status < 500) {\n return ErrorCode.BAD_REQUEST;\n }\n return ErrorCode.INTERNAL;\n }\n}\n","import { HttpStatus } from '@nestjs/common';\nimport type { FieldError } from '../types/error-response.types';\n\ninterface ProblemExceptionResponse {\n type?: string;\n label?: string;\n detail?: string;\n errors?: FieldError[];\n}\n\ninterface ValidationExceptionResponse {\n message: Array<string | { property: string; constraints: Record<string, string> }>;\n error?: string;\n}\n\ninterface StandardExceptionResponse {\n message: string | string[];\n error?: string;\n}\n\ntype ExceptionResponseObject = ProblemExceptionResponse | ValidationExceptionResponse | StandardExceptionResponse;\n\nexport interface ExtractedProblem {\n type: string;\n label?: string;\n detail?: string;\n errors: FieldError[];\n}\n\n// Converts an HTTP status code to its title string (e.g., 400 → \"Bad Request\")\nexport function getHttpStatusTitle(status: number): string {\n // Find the enum key for the given status code\n const enumKey = Object.entries(HttpStatus).find(([key, value]) => value === status && Number.isNaN(Number(key)))?.[0];\n\n if (!enumKey) {\n return 'Error';\n }\n\n // Convert enum key to title case (e.g., BAD_REQUEST -> Bad Request)\n return enumKey\n .split('_')\n .map((word) => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase())\n .join(' ');\n}\n\n// Extracts field-specific errors from a class-validator ValidationPipe message array, mirroring the RFC 9457 errors[].\nfunction extractValidationFieldErrors(\n message: Array<string | { property: string; constraints: Record<string, string> }>,\n): FieldError[] {\n return message\n .map((msg) => {\n if (typeof msg === 'object' && 'property' in msg && 'constraints' in msg) {\n const constraintValues = Object.values(msg.constraints);\n return {\n field: msg.property,\n message: constraintValues[0] ?? 'Validation failed',\n };\n }\n // Non-field-specific validation messages are ignored here; they belong at the detail level.\n return null;\n })\n .filter((error): error is FieldError => error !== null);\n}\n\n// Parses a NestJS HttpException response body into normalized problem fields across the SDK's three body shapes.\nexport function extractProblemFromResponse(\n exceptionResponse: string | object,\n problemFallbackDetail: string,\n): ExtractedProblem {\n let type = 'about:blank';\n let label: string | undefined;\n let detail: string | undefined;\n let errors: FieldError[] = [];\n\n if (typeof exceptionResponse === 'string') {\n detail = exceptionResponse;\n return { type, label, detail, errors };\n }\n\n if (exceptionResponse !== null && typeof exceptionResponse === 'object') {\n const responseObj = exceptionResponse as ExceptionResponseObject;\n\n // Custom HttpProblemException from @vritti/api-sdk\n if ('type' in responseObj || 'label' in responseObj || 'errors' in responseObj) {\n const problemResponse = responseObj as ProblemExceptionResponse;\n type = problemResponse.type ?? 'about:blank';\n label = problemResponse.label;\n detail = problemResponse.detail ?? problemFallbackDetail;\n errors = problemResponse.errors ?? [];\n }\n // class-validator DTO validation errors\n else if ('message' in responseObj && Array.isArray(responseObj.message)) {\n errors = extractValidationFieldErrors(responseObj.message);\n detail = 'Validation failed';\n }\n // Standard NestJS exceptions\n else if ('message' in responseObj) {\n const message = (responseObj as StandardExceptionResponse).message;\n detail = Array.isArray(message) ? message.join(', ') : message;\n }\n }\n\n return { type, label, detail, errors };\n}\n","import { type ErrorCode, errorCodeFromStatus } from './error-code';\nimport { extractProblemFromResponse, getHttpStatusTitle } from './problem-extraction';\n\n// graphql and @nestjs/graphql are optional peers not installed here, so we declare minimal structural shapes locally.\n\ninterface GraphqlFormattedErrorShape {\n message: string;\n locations?: ReadonlyArray<{ line: number; column: number }>;\n path?: ReadonlyArray<string | number>;\n extensions?: Record<string, unknown>;\n}\n\ninterface GraphqlErrorShape {\n message: string;\n originalError?: unknown;\n extensions?: Record<string, unknown>;\n}\n\ninterface HttpExceptionLike {\n getStatus(): number;\n getResponse(): string | object;\n message: string;\n}\n\nexport interface GraphqlFormatErrorOptions {\n isProduction: boolean;\n getTraceId?: () => string | undefined;\n}\n\nexport interface FormattedErrorExtensions {\n code: ErrorCode;\n traceId?: string;\n timestamp: string;\n fieldErrors?: Array<{ field: string; message: string }>;\n [key: string]: unknown;\n}\n\n// Duck-types a NestJS HttpException without importing @nestjs/common (cross-package-instance safe).\nfunction isHttpExceptionLike(error: unknown): error is HttpExceptionLike {\n return (\n error instanceof Error &&\n typeof (error as { getStatus?: unknown }).getStatus === 'function' &&\n typeof (error as { getResponse?: unknown }).getResponse === 'function'\n );\n}\n\ninterface ProblemLike {\n status?: number;\n statusCode?: number;\n detail?: string;\n message?: string;\n}\n\nfunction isProblemLike(error: unknown): error is ProblemLike {\n if (error == null || typeof error !== 'object') {\n return false;\n }\n const o = error as Record<string, unknown>;\n return typeof o.status === 'number' || typeof o.statusCode === 'number';\n}\n\ninterface ProblemSource {\n status: number;\n response: string | object;\n fallback: string;\n}\n\n// Walks the error chain to find the underlying HttpException or plain RFC 9457 problem via originalError/thrownValue.\nfunction findProblemSource(error: GraphqlErrorShape | undefined): ProblemSource | undefined {\n let current: unknown = error;\n // Bounded walk — guard against cyclic chains.\n for (let depth = 0; current && depth < 10; depth++) {\n if (isHttpExceptionLike(current)) {\n const status = current.getStatus();\n return { status, response: current.getResponse(), fallback: current.message ?? getHttpStatusTitle(status) };\n }\n if (isProblemLike(current)) {\n const status = current.status ?? current.statusCode ?? 500;\n return { status, response: current, fallback: current.detail ?? current.message ?? getHttpStatusTitle(status) };\n }\n const next = current as { originalError?: unknown; thrownValue?: unknown };\n current = next.originalError ?? next.thrownValue;\n }\n return undefined;\n}\n\nconst GENERIC_INTERNAL_MESSAGE = 'Internal server error';\n\n// Builds an Apollo formatError that normalizes every GraphQL error into a stable, transport-consistent shape.\nexport function createGraphqlFormatError(\n opts: GraphqlFormatErrorOptions,\n): (formattedError: GraphqlFormattedErrorShape, error: unknown) => GraphqlFormattedErrorShape {\n const { isProduction, getTraceId } = opts;\n\n return (formattedError, error) => {\n const gqlError = (error ?? undefined) as GraphqlErrorShape | undefined;\n const source = findProblemSource(gqlError);\n\n // Derive status + problem body from the underlying source since Apollo only copies .message and defaults code to INTERNAL.\n let status = 500;\n let detail: string | undefined;\n let label: string | undefined;\n let fieldErrors: Array<{ field: string; message: string }> = [];\n\n if (source) {\n status = source.status;\n const extracted = extractProblemFromResponse(source.response, source.fallback);\n detail = extracted.detail;\n label = extracted.label;\n fieldErrors = extracted.errors;\n }\n\n const code = errorCodeFromStatus(status);\n\n // Prefer the problem detail, then the formatted message; never surface internals for INTERNAL in production.\n let message = detail ?? formattedError.message;\n if (code === 'INTERNAL' && isProduction) {\n message = GENERIC_INTERNAL_MESSAGE;\n }\n\n // Start from Apollo's extensions so any framework-set keys survive, then normalize ours on top.\n const incoming: Record<string, unknown> = { ...(formattedError.extensions ?? {}) };\n\n const traceId = getTraceId?.();\n const timestamp = new Date().toISOString();\n\n const extensions: FormattedErrorExtensions = {\n ...incoming,\n // Always our canonical code — overrides Apollo's default INTERNAL_SERVER_ERROR.\n code,\n ...(traceId !== undefined ? { traceId } : {}),\n timestamp,\n ...(label !== undefined ? { label } : {}),\n ...(fieldErrors.length > 0 ? { fieldErrors } : {}),\n };\n\n if (isProduction) {\n // Strip anything that could leak server internals to clients.\n delete extensions.stacktrace;\n delete extensions.exception;\n delete extensions.originalError;\n }\n\n const result: GraphqlFormattedErrorShape = {\n message,\n extensions,\n };\n // Preserve location/path metadata GraphQL attaches (useful to clients, leaks nothing).\n if (formattedError.locations) result.locations = formattedError.locations;\n if (formattedError.path) result.path = formattedError.path;\n\n return result;\n };\n}\n","import {\n type ArgumentsHost,\n Catch,\n type ExceptionFilter,\n type HttpException,\n HttpStatus,\n Logger,\n} from '@nestjs/common';\nimport type { FastifyReply, FastifyRequest } from 'fastify';\nimport type { ApiErrorResponse, FieldError } from '../types/error-response.types';\nimport { tryTranslatePgError } from './pg-error.translator';\nimport { extractProblemFromResponse, getHttpStatusTitle } from './problem-extraction';\n\nexport { getHttpStatusTitle };\n\n@Catch()\nexport class HttpExceptionFilter implements ExceptionFilter {\n private readonly logger = new Logger(HttpExceptionFilter.name);\n\n catch(exception: unknown, host: ArgumentsHost) {\n const ctx = host.switchToHttp();\n const response = ctx.getResponse<FastifyReply>();\n const request = ctx.getRequest<FastifyRequest>();\n\n // Translate raw Postgres errors (e.g. 23505 unique_violation) into a ConflictException before classifying as 500.\n const translatedPgError = tryTranslatePgError(exception);\n if (translatedPgError) exception = translatedPgError;\n\n let status = HttpStatus.INTERNAL_SERVER_ERROR;\n let type = 'about:blank';\n let label: string | undefined;\n let detail = 'Internal server error';\n let errors: FieldError[] = [];\n\n if (this.isHttpException(exception)) {\n status = exception.getStatus();\n const exceptionResponse = exception.getResponse();\n\n // Reuse the shared extractor so HTTP and GraphQL surface identical problem details.\n const extracted = extractProblemFromResponse(exceptionResponse, exception.message ?? getHttpStatusTitle(status));\n type = extracted.type;\n label = extracted.label;\n // Keep the initial 'Internal server error' when the body matched no known shape (byte-identical HTTP output).\n detail = extracted.detail ?? detail;\n errors = extracted.errors;\n } else if (this.isProblemLikeObject(exception)) {\n const problemObj = exception as Record<string, unknown>;\n const statusCandidate = problemObj.status ?? problemObj.statusCode;\n if (typeof statusCandidate === 'number' && statusCandidate >= 400 && statusCandidate <= 599) {\n status = statusCandidate;\n }\n type = typeof problemObj.type === 'string' ? problemObj.type : 'about:blank';\n label = typeof problemObj.label === 'string' ? problemObj.label : undefined;\n detail =\n typeof problemObj.detail === 'string'\n ? problemObj.detail\n : typeof problemObj.message === 'string'\n ? problemObj.message\n : getHttpStatusTitle(status);\n errors = Array.isArray(problemObj.errors) ? (problemObj.errors as FieldError[]) : [];\n } else if (this.isAxiosError(exception)) {\n // Outgoing HTTP call failures (e.g., service-to-service calls)\n const axiosStatus = exception.response?.status;\n const axiosDetail = exception.response?.data?.message || exception.response?.data?.detail || exception.message;\n const url = exception.config?.url;\n status = HttpStatus.BAD_GATEWAY;\n detail = `Upstream service error${axiosStatus ? ` (${axiosStatus})` : ''}: ${axiosDetail}`;\n this.logger.error(`Upstream API error [${axiosStatus}]: ${axiosDetail} — URL: ${url}`, exception.stack);\n } else {\n // Unknown errors — logged by HttpLoggerInterceptor, no need to log again here\n detail = 'An unexpected error occurred';\n }\n\n const problemDetails: ApiErrorResponse = {\n type,\n title: getHttpStatusTitle(status),\n status,\n ...(label && { label }),\n detail,\n instance: request.url,\n errors,\n };\n\n response.header('Content-Type', 'application/problem+json').status(status).send(problemDetails);\n }\n\n // Duck-type check for HttpException — avoids instanceof failing across pnpm package instances\n private isHttpException(error: unknown): error is HttpException {\n return (\n error instanceof Error &&\n typeof (error as { getStatus?: unknown }).getStatus === 'function' &&\n typeof (error as { getResponse?: unknown }).getResponse === 'function'\n );\n }\n\n // Duck-type check for AxiosError without importing axios\n private isAxiosError(error: unknown): error is Error & {\n isAxiosError: true;\n response?: { status?: number; data?: Record<string, unknown> };\n config?: { url?: string };\n } {\n return error instanceof Error && (error as { isAxiosError?: boolean }).isAxiosError === true;\n }\n\n private isProblemLikeObject(error: unknown): error is Record<string, unknown> {\n if (!error || typeof error !== 'object') return false;\n const obj = error as Record<string, unknown>;\n return (\n typeof obj.status === 'number' ||\n typeof obj.statusCode === 'number' ||\n typeof obj.detail === 'string' ||\n Array.isArray(obj.errors)\n );\n }\n}\n","import { HttpStatus } from '@nestjs/common';\nimport { HttpProblemException, type ProblemOptions } from './base-field.exception';\n\nexport class ConflictException extends HttpProblemException {\n constructor(detailOrOptions?: string | ProblemOptions) {\n super(detailOrOptions ?? 'Conflict', HttpStatus.CONFLICT);\n }\n}\n","import { HttpException, HttpStatus } from '@nestjs/common';\nimport type { FieldError } from '../types/error-response.types';\n\n// Re-export FieldError for backwards compatibility\nexport type { FieldError } from '../types/error-response.types';\n\nexport interface ProblemOptions {\n type?: string;\n label?: string;\n detail?: string;\n errors?: FieldError[];\n}\n\nexport abstract class HttpProblemException extends HttpException {\n constructor(detailOrOptions: string | ProblemOptions, httpStatus: HttpStatus) {\n const options = typeof detailOrOptions === 'string' ? { detail: detailOrOptions } : detailOrOptions;\n\n super(\n {\n type: options.type ?? 'about:blank',\n label: options.label,\n detail: options.detail,\n errors: options.errors ?? [],\n },\n httpStatus,\n );\n }\n}\n","import { ConflictException } from '../exceptions/conflict.exception';\n\nconst PG_UNIQUE_VIOLATION = '23505';\n\nexport type PgErrorShape = {\n code?: string;\n message?: string;\n constraint?: string;\n table?: string;\n schema?: string;\n column?: string;\n detail?: string;\n hint?: string;\n};\n\n// Returns a ConflictException for a Postgres unique-violation error, otherwise undefined.\nexport function tryTranslatePgError(error: unknown): ConflictException | undefined {\n const pgError = findPgError(error);\n if (!pgError) return undefined;\n const { code, constraint, table, detail } = pgError;\n if (code !== PG_UNIQUE_VIOLATION) return undefined;\n return new ConflictException({\n label: 'Duplicate Entry',\n detail: detail?.trim() || 'A record with these values already exists.',\n errors: [],\n ...(constraint || table ? { meta: { constraint, table } } : {}),\n });\n}\n\n// Walks up to N levels of `.cause` looking for a pg-shaped error (has SQLSTATE `code`), capping depth.\nexport function findPgError(error: unknown, depth = 0): PgErrorShape | undefined {\n if (!error || typeof error !== 'object' || depth > 5) return undefined;\n const candidate = error as PgErrorShape & { cause?: unknown };\n if (typeof candidate.code === 'string') return candidate;\n return findPgError(candidate.cause, depth + 1);\n}\n","import { type ArgumentsHost, Catch, type ExceptionFilter } from '@nestjs/common';\nimport { HttpExceptionFilter } from './http-exception.filter';\n\n@Catch()\nexport class TransportAwareExceptionFilter implements ExceptionFilter {\n private readonly httpFilter = new HttpExceptionFilter();\n\n catch(exception: unknown, host: ArgumentsHost): void {\n if (host.getType() !== 'http') {\n throw exception;\n }\n this.httpFilter.catch(exception, host);\n }\n}\n"],"mappings":"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","names":["ErrorCode","errorCodeFromStatus","status","HttpStatus","UNAUTHORIZED","FORBIDDEN","NOT_FOUND","BAD_REQUEST","UNPROCESSABLE_ENTITY","CONFLICT","TOO_MANY_REQUESTS","import_common","getHttpStatusTitle","status","enumKey","Object","entries","HttpStatus","find","key","value","Number","isNaN","split","map","word","charAt","toUpperCase","slice","toLowerCase","join","extractValidationFieldErrors","message","msg","constraintValues","values","constraints","field","property","filter","error","extractProblemFromResponse","exceptionResponse","problemFallbackDetail","type","label","detail","errors","responseObj","problemResponse","Array","isArray","isHttpExceptionLike","error","Error","getStatus","getResponse","isProblemLike","o","status","statusCode","findProblemSource","current","depth","response","fallback","message","getHttpStatusTitle","detail","next","originalError","thrownValue","undefined","GENERIC_INTERNAL_MESSAGE","createGraphqlFormatError","opts","isProduction","getTraceId","formattedError","gqlError","source","label","fieldErrors","extracted","extractProblemFromResponse","errors","code","errorCodeFromStatus","incoming","extensions","traceId","timestamp","Date","toISOString","length","stacktrace","exception","result","locations","path","import_common","import_common","import_common","HttpProblemException","HttpException","detailOrOptions","httpStatus","options","detail","type","label","errors","ConflictException","HttpProblemException","detailOrOptions","HttpStatus","CONFLICT","PG_UNIQUE_VIOLATION","tryTranslatePgError","error","pgError","findPgError","undefined","code","constraint","table","detail","ConflictException","label","trim","errors","meta","depth","candidate","cause","HttpExceptionFilter","logger","Logger","name","catch","exception","host","ctx","switchToHttp","response","getResponse","request","getRequest","translatedPgError","tryTranslatePgError","status","HttpStatus","INTERNAL_SERVER_ERROR","type","label","detail","errors","isHttpException","getStatus","exceptionResponse","extracted","extractProblemFromResponse","message","getHttpStatusTitle","isProblemLikeObject","problemObj","statusCandidate","statusCode","undefined","Array","isArray","isAxiosError","axiosStatus","axiosDetail","data","url","config","BAD_GATEWAY","error","stack","problemDetails","title","instance","header","send","Error","obj","import_common","TransportAwareExceptionFilter","httpFilter","HttpExceptionFilter","catch","exception","host","getType"]}
1
+ {"version":3,"sources":["../src/filters/index.ts","../src/filters/error-code.ts","../src/filters/problem-extraction.ts","../src/filters/graphql-format-error.ts","../src/filters/http-exception.filter.ts","../src/exceptions/conflict.exception.ts","../src/exceptions/base-field.exception.ts","../src/filters/pg-error.translator.ts","../src/filters/transport-aware-exception.filter.ts"],"sourcesContent":["// Machine-readable error contract + status mapper (shared across HTTP and GraphQL transports).\n\nexport { ErrorCode, errorCodeFromStatus } from './error-code';\n// GraphQL error shaping (Apollo formatError factory) — composes with TransportAwareExceptionFilter.\nexport {\n createGraphqlFormatError,\n type FormattedErrorExtensions,\n type GraphqlFormatErrorOptions,\n} from './graphql-format-error';\nexport { getHttpStatusTitle, HttpExceptionFilter } from './http-exception.filter';\nexport { TransportAwareExceptionFilter } from './transport-aware-exception.filter';\n// RpcProblemExceptionFilter is exported from '@vritti/api-sdk/nats' (it needs @nestjs/microservices).\n","import { HttpStatus } from '@nestjs/common';\n\nexport enum ErrorCode {\n UNAUTHENTICATED = 'UNAUTHENTICATED',\n FORBIDDEN = 'FORBIDDEN',\n NOT_FOUND = 'NOT_FOUND',\n VALIDATION_FAILED = 'VALIDATION_FAILED',\n CONFLICT = 'CONFLICT',\n RATE_LIMITED = 'RATE_LIMITED',\n BAD_REQUEST = 'BAD_REQUEST',\n INTERNAL = 'INTERNAL',\n}\n\n// Maps an HTTP status code to the canonical ErrorCode so HTTP and GraphQL classify identically.\nexport function errorCodeFromStatus(status: number): ErrorCode {\n switch (status) {\n case HttpStatus.UNAUTHORIZED: // 401\n return ErrorCode.UNAUTHENTICATED;\n case HttpStatus.FORBIDDEN: // 403\n return ErrorCode.FORBIDDEN;\n case HttpStatus.NOT_FOUND: // 404\n return ErrorCode.NOT_FOUND;\n case HttpStatus.BAD_REQUEST: // 400\n case HttpStatus.UNPROCESSABLE_ENTITY: // 422\n return ErrorCode.VALIDATION_FAILED;\n case HttpStatus.CONFLICT: // 409\n return ErrorCode.CONFLICT;\n case HttpStatus.TOO_MANY_REQUESTS: // 429\n return ErrorCode.RATE_LIMITED;\n default:\n // Any other 4xx is a generic bad request; 5xx and unknown collapse to INTERNAL.\n if (status >= 400 && status < 500) {\n return ErrorCode.BAD_REQUEST;\n }\n return ErrorCode.INTERNAL;\n }\n}\n","import { HttpStatus } from '@nestjs/common';\nimport type { FieldError } from '../types/error-response.types';\n\ninterface ProblemExceptionResponse {\n type?: string;\n label?: string;\n detail?: string;\n errors?: FieldError[];\n}\n\ninterface ValidationExceptionResponse {\n message: Array<string | { property: string; constraints: Record<string, string> }>;\n error?: string;\n}\n\ninterface StandardExceptionResponse {\n message: string | string[];\n error?: string;\n}\n\ntype ExceptionResponseObject = ProblemExceptionResponse | ValidationExceptionResponse | StandardExceptionResponse;\n\nexport interface ExtractedProblem {\n type: string;\n label?: string;\n detail?: string;\n errors: FieldError[];\n}\n\n// Converts an HTTP status code to its title string (e.g., 400 → \"Bad Request\")\nexport function getHttpStatusTitle(status: number): string {\n // Find the enum key for the given status code\n const enumKey = Object.entries(HttpStatus).find(([key, value]) => value === status && Number.isNaN(Number(key)))?.[0];\n\n if (!enumKey) {\n return 'Error';\n }\n\n // Convert enum key to title case (e.g., BAD_REQUEST -> Bad Request)\n return enumKey\n .split('_')\n .map((word) => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase())\n .join(' ');\n}\n\n// Extracts field-specific errors from a class-validator ValidationPipe message array, mirroring the RFC 9457 errors[].\nfunction extractValidationFieldErrors(\n message: Array<string | { property: string; constraints: Record<string, string> }>,\n): FieldError[] {\n return message\n .map((msg) => {\n if (typeof msg === 'object' && 'property' in msg && 'constraints' in msg) {\n const constraintValues = Object.values(msg.constraints);\n return {\n field: msg.property,\n message: constraintValues[0] ?? 'Validation failed',\n };\n }\n // Non-field-specific validation messages are ignored here; they belong at the detail level.\n return null;\n })\n .filter((error): error is FieldError => error !== null);\n}\n\n// Parses a NestJS HttpException response body into normalized problem fields across the SDK's three body shapes.\nexport function extractProblemFromResponse(\n exceptionResponse: string | object,\n problemFallbackDetail: string,\n): ExtractedProblem {\n let type = 'about:blank';\n let label: string | undefined;\n let detail: string | undefined;\n let errors: FieldError[] = [];\n\n if (typeof exceptionResponse === 'string') {\n detail = exceptionResponse;\n return { type, label, detail, errors };\n }\n\n if (exceptionResponse !== null && typeof exceptionResponse === 'object') {\n const responseObj = exceptionResponse as ExceptionResponseObject;\n\n // Custom HttpProblemException from @vritti/api-sdk\n if ('type' in responseObj || 'label' in responseObj || 'errors' in responseObj) {\n const problemResponse = responseObj as ProblemExceptionResponse;\n type = problemResponse.type ?? 'about:blank';\n label = problemResponse.label;\n detail = problemResponse.detail ?? problemFallbackDetail;\n errors = problemResponse.errors ?? [];\n }\n // class-validator DTO validation errors\n else if ('message' in responseObj && Array.isArray(responseObj.message)) {\n errors = extractValidationFieldErrors(responseObj.message);\n detail = 'Validation failed';\n }\n // Standard NestJS exceptions\n else if ('message' in responseObj) {\n const message = (responseObj as StandardExceptionResponse).message;\n detail = Array.isArray(message) ? message.join(', ') : message;\n }\n }\n\n return { type, label, detail, errors };\n}\n","import { type ErrorCode, errorCodeFromStatus } from './error-code';\nimport { extractProblemFromResponse, getHttpStatusTitle } from './problem-extraction';\n\n// graphql and @nestjs/graphql are optional peers not installed here, so we declare minimal structural shapes locally.\n\ninterface GraphqlFormattedErrorShape {\n message: string;\n locations?: ReadonlyArray<{ line: number; column: number }>;\n path?: ReadonlyArray<string | number>;\n extensions?: Record<string, unknown>;\n}\n\ninterface GraphqlErrorShape {\n message: string;\n originalError?: unknown;\n extensions?: Record<string, unknown>;\n}\n\ninterface HttpExceptionLike {\n getStatus(): number;\n getResponse(): string | object;\n message: string;\n}\n\nexport interface GraphqlFormatErrorOptions {\n isProduction: boolean;\n getTraceId?: () => string | undefined;\n}\n\nexport interface FormattedErrorExtensions {\n code: ErrorCode;\n traceId?: string;\n timestamp: string;\n fieldErrors?: Array<{ field: string; message: string }>;\n [key: string]: unknown;\n}\n\n// Duck-types a NestJS HttpException without importing @nestjs/common (cross-package-instance safe).\nfunction isHttpExceptionLike(error: unknown): error is HttpExceptionLike {\n return (\n error instanceof Error &&\n typeof (error as { getStatus?: unknown }).getStatus === 'function' &&\n typeof (error as { getResponse?: unknown }).getResponse === 'function'\n );\n}\n\ninterface ProblemLike {\n status?: number;\n statusCode?: number;\n detail?: string;\n message?: string;\n}\n\nfunction isProblemLike(error: unknown): error is ProblemLike {\n if (error == null || typeof error !== 'object') {\n return false;\n }\n const o = error as Record<string, unknown>;\n return typeof o.status === 'number' || typeof o.statusCode === 'number';\n}\n\ninterface ProblemSource {\n status: number;\n response: string | object;\n fallback: string;\n}\n\n// Walks the error chain to find the underlying HttpException or plain RFC 9457 problem via originalError/thrownValue.\nfunction findProblemSource(error: GraphqlErrorShape | undefined): ProblemSource | undefined {\n let current: unknown = error;\n // Bounded walk — guard against cyclic chains.\n for (let depth = 0; current && depth < 10; depth++) {\n if (isHttpExceptionLike(current)) {\n const status = current.getStatus();\n return { status, response: current.getResponse(), fallback: current.message ?? getHttpStatusTitle(status) };\n }\n if (isProblemLike(current)) {\n const status = current.status ?? current.statusCode ?? 500;\n return { status, response: current, fallback: current.detail ?? current.message ?? getHttpStatusTitle(status) };\n }\n const next = current as { originalError?: unknown; thrownValue?: unknown };\n current = next.originalError ?? next.thrownValue;\n }\n return undefined;\n}\n\nconst GENERIC_INTERNAL_MESSAGE = 'Internal server error';\n\n// Builds an Apollo formatError that normalizes every GraphQL error into a stable, transport-consistent shape.\nexport function createGraphqlFormatError(\n opts: GraphqlFormatErrorOptions,\n): (formattedError: GraphqlFormattedErrorShape, error: unknown) => GraphqlFormattedErrorShape {\n const { isProduction, getTraceId } = opts;\n\n return (formattedError, error) => {\n const gqlError = (error ?? undefined) as GraphqlErrorShape | undefined;\n const source = findProblemSource(gqlError);\n\n // Derive status + problem body from the underlying source since Apollo only copies .message and defaults code to INTERNAL.\n let status = 500;\n let detail: string | undefined;\n let label: string | undefined;\n let fieldErrors: Array<{ field: string; message: string }> = [];\n\n if (source) {\n status = source.status;\n const extracted = extractProblemFromResponse(source.response, source.fallback);\n detail = extracted.detail;\n label = extracted.label;\n fieldErrors = extracted.errors;\n }\n\n const code = errorCodeFromStatus(status);\n\n // Prefer the problem detail, then the formatted message; never surface internals for INTERNAL in production.\n let message = detail ?? formattedError.message;\n if (code === 'INTERNAL' && isProduction) {\n message = GENERIC_INTERNAL_MESSAGE;\n }\n\n // Start from Apollo's extensions so any framework-set keys survive, then normalize ours on top.\n const incoming: Record<string, unknown> = { ...(formattedError.extensions ?? {}) };\n\n const traceId = getTraceId?.();\n const timestamp = new Date().toISOString();\n\n const extensions: FormattedErrorExtensions = {\n ...incoming,\n // Always our canonical code — overrides Apollo's default INTERNAL_SERVER_ERROR.\n code,\n ...(traceId !== undefined ? { traceId } : {}),\n timestamp,\n ...(label !== undefined ? { label } : {}),\n ...(fieldErrors.length > 0 ? { fieldErrors } : {}),\n };\n\n if (isProduction) {\n // Strip anything that could leak server internals to clients.\n delete extensions.stacktrace;\n delete extensions.exception;\n delete extensions.originalError;\n }\n\n const result: GraphqlFormattedErrorShape = {\n message,\n extensions,\n };\n // Preserve location/path metadata GraphQL attaches (useful to clients, leaks nothing).\n if (formattedError.locations) result.locations = formattedError.locations;\n if (formattedError.path) result.path = formattedError.path;\n\n return result;\n };\n}\n","import {\n type ArgumentsHost,\n Catch,\n type ExceptionFilter,\n type HttpException,\n HttpStatus,\n Logger,\n} from '@nestjs/common';\nimport type { FastifyReply, FastifyRequest } from 'fastify';\nimport type { ApiErrorResponse, FieldError } from '../types/error-response.types';\nimport { tryTranslatePgError } from './pg-error.translator';\nimport { extractProblemFromResponse, getHttpStatusTitle } from './problem-extraction';\n\nexport { getHttpStatusTitle };\n\n@Catch()\nexport class HttpExceptionFilter implements ExceptionFilter {\n private readonly logger = new Logger(HttpExceptionFilter.name);\n\n catch(exception: unknown, host: ArgumentsHost) {\n const ctx = host.switchToHttp();\n const response = ctx.getResponse<FastifyReply>();\n const request = ctx.getRequest<FastifyRequest>();\n\n // Translate raw Postgres errors (e.g. 23505 unique_violation) into a ConflictException before classifying as 500.\n const translatedPgError = tryTranslatePgError(exception);\n if (translatedPgError) exception = translatedPgError;\n\n let status = HttpStatus.INTERNAL_SERVER_ERROR;\n let type = 'about:blank';\n let label: string | undefined;\n let detail = 'Internal server error';\n let errors: FieldError[] = [];\n\n if (this.isHttpException(exception)) {\n status = exception.getStatus();\n const exceptionResponse = exception.getResponse();\n\n // Reuse the shared extractor so HTTP and GraphQL surface identical problem details.\n const extracted = extractProblemFromResponse(exceptionResponse, exception.message ?? getHttpStatusTitle(status));\n type = extracted.type;\n label = extracted.label;\n // Keep the initial 'Internal server error' when the body matched no known shape (byte-identical HTTP output).\n detail = extracted.detail ?? detail;\n errors = extracted.errors;\n } else if (this.isProblemLikeObject(exception)) {\n const problemObj = exception as Record<string, unknown>;\n const statusCandidate = problemObj.status ?? problemObj.statusCode;\n if (typeof statusCandidate === 'number' && statusCandidate >= 400 && statusCandidate <= 599) {\n status = statusCandidate;\n }\n type = typeof problemObj.type === 'string' ? problemObj.type : 'about:blank';\n label = typeof problemObj.label === 'string' ? problemObj.label : undefined;\n detail =\n typeof problemObj.detail === 'string'\n ? problemObj.detail\n : typeof problemObj.message === 'string'\n ? problemObj.message\n : getHttpStatusTitle(status);\n errors = Array.isArray(problemObj.errors) ? (problemObj.errors as FieldError[]) : [];\n } else if (this.isAxiosError(exception)) {\n // Outgoing HTTP call failures (e.g., service-to-service calls)\n const axiosStatus = exception.response?.status;\n const axiosDetail = exception.response?.data?.message || exception.response?.data?.detail || exception.message;\n const url = exception.config?.url;\n status = HttpStatus.BAD_GATEWAY;\n detail = `Upstream service error${axiosStatus ? ` (${axiosStatus})` : ''}: ${axiosDetail}`;\n this.logger.error(`Upstream API error [${axiosStatus}]: ${axiosDetail} — URL: ${url}`, exception.stack);\n } else {\n // Unknown errors — logged by HttpLoggerInterceptor, no need to log again here\n detail = 'An unexpected error occurred';\n }\n\n const problemDetails: ApiErrorResponse = {\n type,\n title: getHttpStatusTitle(status),\n status,\n ...(label && { label }),\n detail,\n instance: request.url,\n errors,\n };\n\n response.header('Content-Type', 'application/problem+json').status(status).send(problemDetails);\n }\n\n // Duck-type check for HttpException — avoids instanceof failing across pnpm package instances\n private isHttpException(error: unknown): error is HttpException {\n return (\n error instanceof Error &&\n typeof (error as { getStatus?: unknown }).getStatus === 'function' &&\n typeof (error as { getResponse?: unknown }).getResponse === 'function'\n );\n }\n\n // Duck-type check for AxiosError without importing axios\n private isAxiosError(error: unknown): error is Error & {\n isAxiosError: true;\n response?: { status?: number; data?: Record<string, unknown> };\n config?: { url?: string };\n } {\n return error instanceof Error && (error as { isAxiosError?: boolean }).isAxiosError === true;\n }\n\n private isProblemLikeObject(error: unknown): error is Record<string, unknown> {\n if (!error || typeof error !== 'object') return false;\n const obj = error as Record<string, unknown>;\n return (\n typeof obj.status === 'number' ||\n typeof obj.statusCode === 'number' ||\n typeof obj.detail === 'string' ||\n Array.isArray(obj.errors)\n );\n }\n}\n","import { HttpStatus } from '@nestjs/common';\nimport { HttpProblemException, type ProblemOptions } from './base-field.exception';\n\nexport class ConflictException extends HttpProblemException {\n constructor(detailOrOptions?: string | ProblemOptions) {\n super(detailOrOptions ?? 'Conflict', HttpStatus.CONFLICT);\n }\n}\n","import { HttpException, HttpStatus } from '@nestjs/common';\nimport type { FieldError } from '../types/error-response.types';\n\n// Re-export FieldError for backwards compatibility\nexport type { FieldError } from '../types/error-response.types';\n\nexport interface ProblemOptions {\n type?: string;\n label?: string;\n detail?: string;\n errors?: FieldError[];\n}\n\nexport abstract class HttpProblemException extends HttpException {\n constructor(detailOrOptions: string | ProblemOptions, httpStatus: HttpStatus) {\n const options = typeof detailOrOptions === 'string' ? { detail: detailOrOptions } : detailOrOptions;\n\n super(\n {\n type: options.type ?? 'about:blank',\n label: options.label,\n detail: options.detail,\n errors: options.errors ?? [],\n },\n httpStatus,\n );\n }\n}\n","import { ConflictException } from '../exceptions/conflict.exception';\n\nconst PG_UNIQUE_VIOLATION = '23505';\n\nexport type PgErrorShape = {\n code?: string;\n message?: string;\n constraint?: string;\n table?: string;\n schema?: string;\n column?: string;\n detail?: string;\n hint?: string;\n};\n\n// Returns a ConflictException for a Postgres unique-violation error, otherwise undefined.\nexport function tryTranslatePgError(error: unknown): ConflictException | undefined {\n const pgError = findPgError(error);\n if (!pgError) return undefined;\n const { code, constraint, table, detail } = pgError;\n if (code !== PG_UNIQUE_VIOLATION) return undefined;\n return new ConflictException({\n label: 'Duplicate Entry',\n detail: detail?.trim() || 'A record with these values already exists.',\n errors: [],\n ...(constraint || table ? { meta: { constraint, table } } : {}),\n });\n}\n\n// Walks up to N levels of `.cause` looking for a pg-shaped error (has SQLSTATE `code`), capping depth.\nexport function findPgError(error: unknown, depth = 0): PgErrorShape | undefined {\n if (!error || typeof error !== 'object' || depth > 5) return undefined;\n const candidate = error as PgErrorShape & { cause?: unknown };\n if (typeof candidate.code === 'string') return candidate;\n return findPgError(candidate.cause, depth + 1);\n}\n","import { type ArgumentsHost, Catch, type ExceptionFilter } from '@nestjs/common';\nimport { HttpExceptionFilter } from './http-exception.filter';\n\n@Catch()\nexport class TransportAwareExceptionFilter implements ExceptionFilter {\n private readonly httpFilter = new HttpExceptionFilter();\n\n catch(exception: unknown, host: ArgumentsHost): void {\n if (host.getType() !== 'http') {\n throw exception;\n }\n this.httpFilter.catch(exception, host);\n }\n}\n"],"mappings":"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","names":["ErrorCode","errorCodeFromStatus","status","HttpStatus","UNAUTHORIZED","FORBIDDEN","NOT_FOUND","BAD_REQUEST","UNPROCESSABLE_ENTITY","CONFLICT","TOO_MANY_REQUESTS","import_common","getHttpStatusTitle","status","enumKey","Object","entries","HttpStatus","find","key","value","Number","isNaN","split","map","word","charAt","toUpperCase","slice","toLowerCase","join","extractValidationFieldErrors","message","msg","constraintValues","values","constraints","field","property","filter","error","extractProblemFromResponse","exceptionResponse","problemFallbackDetail","type","label","detail","errors","responseObj","problemResponse","Array","isArray","isHttpExceptionLike","error","Error","getStatus","getResponse","isProblemLike","o","status","statusCode","findProblemSource","current","depth","response","fallback","message","getHttpStatusTitle","detail","next","originalError","thrownValue","undefined","GENERIC_INTERNAL_MESSAGE","createGraphqlFormatError","opts","isProduction","getTraceId","formattedError","gqlError","source","label","fieldErrors","extracted","extractProblemFromResponse","errors","code","errorCodeFromStatus","incoming","extensions","traceId","timestamp","Date","toISOString","length","stacktrace","exception","result","locations","path","import_common","import_common","import_common","HttpProblemException","HttpException","detailOrOptions","httpStatus","options","detail","type","label","errors","ConflictException","HttpProblemException","detailOrOptions","HttpStatus","CONFLICT","PG_UNIQUE_VIOLATION","tryTranslatePgError","error","pgError","findPgError","undefined","code","constraint","table","detail","ConflictException","label","trim","errors","meta","depth","candidate","cause","HttpExceptionFilter","logger","Logger","name","catch","exception","host","ctx","switchToHttp","response","getResponse","request","getRequest","translatedPgError","tryTranslatePgError","status","HttpStatus","INTERNAL_SERVER_ERROR","type","label","detail","errors","isHttpException","getStatus","exceptionResponse","extracted","extractProblemFromResponse","message","getHttpStatusTitle","isProblemLikeObject","problemObj","statusCandidate","statusCode","undefined","Array","isArray","isAxiosError","axiosStatus","axiosDetail","data","url","config","BAD_GATEWAY","error","stack","problemDetails","title","instance","header","send","Error","obj","import_common","TransportAwareExceptionFilter","httpFilter","HttpExceptionFilter","catch","exception","host","getType"]}
package/dist/filters.js CHANGED
@@ -262,8 +262,15 @@ __name(findPgError, "findPgError");
262
262
  // src/filters/http-exception.filter.ts
263
263
  function _ts_decorate(decorators, target, key, desc) {
264
264
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
265
- if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
266
- else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
265
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") {
266
+ r = Reflect.decorate(decorators, target, key, desc);
267
+ } else {
268
+ for (var i = decorators.length - 1; i >= 0; i--) {
269
+ if (d = decorators[i]) {
270
+ r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
271
+ }
272
+ }
273
+ }
267
274
  return c > 3 && r && Object.defineProperty(target, key, r), r;
268
275
  }
269
276
  __name(_ts_decorate, "_ts_decorate");
@@ -346,8 +353,15 @@ HttpExceptionFilter = _ts_decorate([
346
353
  import { Catch as Catch2 } from "@nestjs/common";
347
354
  function _ts_decorate2(decorators, target, key, desc) {
348
355
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
349
- if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
350
- else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
356
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") {
357
+ r = Reflect.decorate(decorators, target, key, desc);
358
+ } else {
359
+ for (var i = decorators.length - 1; i >= 0; i--) {
360
+ if (d = decorators[i]) {
361
+ r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
362
+ }
363
+ }
364
+ }
351
365
  return c > 3 && r && Object.defineProperty(target, key, r), r;
352
366
  }
353
367
  __name(_ts_decorate2, "_ts_decorate");
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/filters/error-code.ts","../src/filters/problem-extraction.ts","../src/filters/graphql-format-error.ts","../src/filters/http-exception.filter.ts","../src/exceptions/conflict.exception.ts","../src/exceptions/base-field.exception.ts","../src/filters/pg-error.translator.ts","../src/filters/transport-aware-exception.filter.ts"],"sourcesContent":["import { HttpStatus } from '@nestjs/common';\n\nexport enum ErrorCode {\n UNAUTHENTICATED = 'UNAUTHENTICATED',\n FORBIDDEN = 'FORBIDDEN',\n NOT_FOUND = 'NOT_FOUND',\n VALIDATION_FAILED = 'VALIDATION_FAILED',\n CONFLICT = 'CONFLICT',\n RATE_LIMITED = 'RATE_LIMITED',\n BAD_REQUEST = 'BAD_REQUEST',\n INTERNAL = 'INTERNAL',\n}\n\n// Maps an HTTP status code to the canonical ErrorCode so HTTP and GraphQL classify identically.\nexport function errorCodeFromStatus(status: number): ErrorCode {\n switch (status) {\n case HttpStatus.UNAUTHORIZED: // 401\n return ErrorCode.UNAUTHENTICATED;\n case HttpStatus.FORBIDDEN: // 403\n return ErrorCode.FORBIDDEN;\n case HttpStatus.NOT_FOUND: // 404\n return ErrorCode.NOT_FOUND;\n case HttpStatus.BAD_REQUEST: // 400\n case HttpStatus.UNPROCESSABLE_ENTITY: // 422\n return ErrorCode.VALIDATION_FAILED;\n case HttpStatus.CONFLICT: // 409\n return ErrorCode.CONFLICT;\n case HttpStatus.TOO_MANY_REQUESTS: // 429\n return ErrorCode.RATE_LIMITED;\n default:\n // Any other 4xx is a generic bad request; 5xx and unknown collapse to INTERNAL.\n if (status >= 400 && status < 500) {\n return ErrorCode.BAD_REQUEST;\n }\n return ErrorCode.INTERNAL;\n }\n}\n","import { HttpStatus } from '@nestjs/common';\nimport type { FieldError } from '../types/error-response.types';\n\ninterface ProblemExceptionResponse {\n type?: string;\n label?: string;\n detail?: string;\n errors?: FieldError[];\n}\n\ninterface ValidationExceptionResponse {\n message: Array<string | { property: string; constraints: Record<string, string> }>;\n error?: string;\n}\n\ninterface StandardExceptionResponse {\n message: string | string[];\n error?: string;\n}\n\ntype ExceptionResponseObject = ProblemExceptionResponse | ValidationExceptionResponse | StandardExceptionResponse;\n\nexport interface ExtractedProblem {\n type: string;\n label?: string;\n detail?: string;\n errors: FieldError[];\n}\n\n// Converts an HTTP status code to its title string (e.g., 400 → \"Bad Request\")\nexport function getHttpStatusTitle(status: number): string {\n // Find the enum key for the given status code\n const enumKey = Object.entries(HttpStatus).find(([key, value]) => value === status && Number.isNaN(Number(key)))?.[0];\n\n if (!enumKey) {\n return 'Error';\n }\n\n // Convert enum key to title case (e.g., BAD_REQUEST -> Bad Request)\n return enumKey\n .split('_')\n .map((word) => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase())\n .join(' ');\n}\n\n// Extracts field-specific errors from a class-validator ValidationPipe message array, mirroring the RFC 9457 errors[].\nfunction extractValidationFieldErrors(\n message: Array<string | { property: string; constraints: Record<string, string> }>,\n): FieldError[] {\n return message\n .map((msg) => {\n if (typeof msg === 'object' && 'property' in msg && 'constraints' in msg) {\n const constraintValues = Object.values(msg.constraints);\n return {\n field: msg.property,\n message: constraintValues[0] ?? 'Validation failed',\n };\n }\n // Non-field-specific validation messages are ignored here; they belong at the detail level.\n return null;\n })\n .filter((error): error is FieldError => error !== null);\n}\n\n// Parses a NestJS HttpException response body into normalized problem fields across the SDK's three body shapes.\nexport function extractProblemFromResponse(\n exceptionResponse: string | object,\n problemFallbackDetail: string,\n): ExtractedProblem {\n let type = 'about:blank';\n let label: string | undefined;\n let detail: string | undefined;\n let errors: FieldError[] = [];\n\n if (typeof exceptionResponse === 'string') {\n detail = exceptionResponse;\n return { type, label, detail, errors };\n }\n\n if (exceptionResponse !== null && typeof exceptionResponse === 'object') {\n const responseObj = exceptionResponse as ExceptionResponseObject;\n\n // Custom HttpProblemException from @vritti/api-sdk\n if ('type' in responseObj || 'label' in responseObj || 'errors' in responseObj) {\n const problemResponse = responseObj as ProblemExceptionResponse;\n type = problemResponse.type ?? 'about:blank';\n label = problemResponse.label;\n detail = problemResponse.detail ?? problemFallbackDetail;\n errors = problemResponse.errors ?? [];\n }\n // class-validator DTO validation errors\n else if ('message' in responseObj && Array.isArray(responseObj.message)) {\n errors = extractValidationFieldErrors(responseObj.message);\n detail = 'Validation failed';\n }\n // Standard NestJS exceptions\n else if ('message' in responseObj) {\n const message = (responseObj as StandardExceptionResponse).message;\n detail = Array.isArray(message) ? message.join(', ') : message;\n }\n }\n\n return { type, label, detail, errors };\n}\n","import { type ErrorCode, errorCodeFromStatus } from './error-code';\nimport { extractProblemFromResponse, getHttpStatusTitle } from './problem-extraction';\n\n// graphql and @nestjs/graphql are optional peers not installed here, so we declare minimal structural shapes locally.\n\ninterface GraphqlFormattedErrorShape {\n message: string;\n locations?: ReadonlyArray<{ line: number; column: number }>;\n path?: ReadonlyArray<string | number>;\n extensions?: Record<string, unknown>;\n}\n\ninterface GraphqlErrorShape {\n message: string;\n originalError?: unknown;\n extensions?: Record<string, unknown>;\n}\n\ninterface HttpExceptionLike {\n getStatus(): number;\n getResponse(): string | object;\n message: string;\n}\n\nexport interface GraphqlFormatErrorOptions {\n isProduction: boolean;\n getTraceId?: () => string | undefined;\n}\n\nexport interface FormattedErrorExtensions {\n code: ErrorCode;\n traceId?: string;\n timestamp: string;\n fieldErrors?: Array<{ field: string; message: string }>;\n [key: string]: unknown;\n}\n\n// Duck-types a NestJS HttpException without importing @nestjs/common (cross-package-instance safe).\nfunction isHttpExceptionLike(error: unknown): error is HttpExceptionLike {\n return (\n error instanceof Error &&\n typeof (error as { getStatus?: unknown }).getStatus === 'function' &&\n typeof (error as { getResponse?: unknown }).getResponse === 'function'\n );\n}\n\ninterface ProblemLike {\n status?: number;\n statusCode?: number;\n detail?: string;\n message?: string;\n}\n\nfunction isProblemLike(error: unknown): error is ProblemLike {\n if (error == null || typeof error !== 'object') {\n return false;\n }\n const o = error as Record<string, unknown>;\n return typeof o.status === 'number' || typeof o.statusCode === 'number';\n}\n\ninterface ProblemSource {\n status: number;\n response: string | object;\n fallback: string;\n}\n\n// Walks the error chain to find the underlying HttpException or plain RFC 9457 problem via originalError/thrownValue.\nfunction findProblemSource(error: GraphqlErrorShape | undefined): ProblemSource | undefined {\n let current: unknown = error;\n // Bounded walk — guard against cyclic chains.\n for (let depth = 0; current && depth < 10; depth++) {\n if (isHttpExceptionLike(current)) {\n const status = current.getStatus();\n return { status, response: current.getResponse(), fallback: current.message ?? getHttpStatusTitle(status) };\n }\n if (isProblemLike(current)) {\n const status = current.status ?? current.statusCode ?? 500;\n return { status, response: current, fallback: current.detail ?? current.message ?? getHttpStatusTitle(status) };\n }\n const next = current as { originalError?: unknown; thrownValue?: unknown };\n current = next.originalError ?? next.thrownValue;\n }\n return undefined;\n}\n\nconst GENERIC_INTERNAL_MESSAGE = 'Internal server error';\n\n// Builds an Apollo formatError that normalizes every GraphQL error into a stable, transport-consistent shape.\nexport function createGraphqlFormatError(\n opts: GraphqlFormatErrorOptions,\n): (formattedError: GraphqlFormattedErrorShape, error: unknown) => GraphqlFormattedErrorShape {\n const { isProduction, getTraceId } = opts;\n\n return (formattedError, error) => {\n const gqlError = (error ?? undefined) as GraphqlErrorShape | undefined;\n const source = findProblemSource(gqlError);\n\n // Derive status + problem body from the underlying source since Apollo only copies .message and defaults code to INTERNAL.\n let status = 500;\n let detail: string | undefined;\n let label: string | undefined;\n let fieldErrors: Array<{ field: string; message: string }> = [];\n\n if (source) {\n status = source.status;\n const extracted = extractProblemFromResponse(source.response, source.fallback);\n detail = extracted.detail;\n label = extracted.label;\n fieldErrors = extracted.errors;\n }\n\n const code = errorCodeFromStatus(status);\n\n // Prefer the problem detail, then the formatted message; never surface internals for INTERNAL in production.\n let message = detail ?? formattedError.message;\n if (code === 'INTERNAL' && isProduction) {\n message = GENERIC_INTERNAL_MESSAGE;\n }\n\n // Start from Apollo's extensions so any framework-set keys survive, then normalize ours on top.\n const incoming: Record<string, unknown> = { ...(formattedError.extensions ?? {}) };\n\n const traceId = getTraceId?.();\n const timestamp = new Date().toISOString();\n\n const extensions: FormattedErrorExtensions = {\n ...incoming,\n // Always our canonical code — overrides Apollo's default INTERNAL_SERVER_ERROR.\n code,\n ...(traceId !== undefined ? { traceId } : {}),\n timestamp,\n ...(label !== undefined ? { label } : {}),\n ...(fieldErrors.length > 0 ? { fieldErrors } : {}),\n };\n\n if (isProduction) {\n // Strip anything that could leak server internals to clients.\n delete extensions.stacktrace;\n delete extensions.exception;\n delete extensions.originalError;\n }\n\n const result: GraphqlFormattedErrorShape = {\n message,\n extensions,\n };\n // Preserve location/path metadata GraphQL attaches (useful to clients, leaks nothing).\n if (formattedError.locations) result.locations = formattedError.locations;\n if (formattedError.path) result.path = formattedError.path;\n\n return result;\n };\n}\n","import {\n type ArgumentsHost,\n Catch,\n type ExceptionFilter,\n type HttpException,\n HttpStatus,\n Logger,\n} from '@nestjs/common';\nimport type { FastifyReply, FastifyRequest } from 'fastify';\nimport type { ApiErrorResponse, FieldError } from '../types/error-response.types';\nimport { tryTranslatePgError } from './pg-error.translator';\nimport { extractProblemFromResponse, getHttpStatusTitle } from './problem-extraction';\n\nexport { getHttpStatusTitle };\n\n@Catch()\nexport class HttpExceptionFilter implements ExceptionFilter {\n private readonly logger = new Logger(HttpExceptionFilter.name);\n\n catch(exception: unknown, host: ArgumentsHost) {\n const ctx = host.switchToHttp();\n const response = ctx.getResponse<FastifyReply>();\n const request = ctx.getRequest<FastifyRequest>();\n\n // Translate raw Postgres errors (e.g. 23505 unique_violation) into a ConflictException before classifying as 500.\n const translatedPgError = tryTranslatePgError(exception);\n if (translatedPgError) exception = translatedPgError;\n\n let status = HttpStatus.INTERNAL_SERVER_ERROR;\n let type = 'about:blank';\n let label: string | undefined;\n let detail = 'Internal server error';\n let errors: FieldError[] = [];\n\n if (this.isHttpException(exception)) {\n status = exception.getStatus();\n const exceptionResponse = exception.getResponse();\n\n // Reuse the shared extractor so HTTP and GraphQL surface identical problem details.\n const extracted = extractProblemFromResponse(exceptionResponse, exception.message ?? getHttpStatusTitle(status));\n type = extracted.type;\n label = extracted.label;\n // Keep the initial 'Internal server error' when the body matched no known shape (byte-identical HTTP output).\n detail = extracted.detail ?? detail;\n errors = extracted.errors;\n } else if (this.isProblemLikeObject(exception)) {\n const problemObj = exception as Record<string, unknown>;\n const statusCandidate = problemObj.status ?? problemObj.statusCode;\n if (typeof statusCandidate === 'number' && statusCandidate >= 400 && statusCandidate <= 599) {\n status = statusCandidate;\n }\n type = typeof problemObj.type === 'string' ? problemObj.type : 'about:blank';\n label = typeof problemObj.label === 'string' ? problemObj.label : undefined;\n detail =\n typeof problemObj.detail === 'string'\n ? problemObj.detail\n : typeof problemObj.message === 'string'\n ? problemObj.message\n : getHttpStatusTitle(status);\n errors = Array.isArray(problemObj.errors) ? (problemObj.errors as FieldError[]) : [];\n } else if (this.isAxiosError(exception)) {\n // Outgoing HTTP call failures (e.g., service-to-service calls)\n const axiosStatus = exception.response?.status;\n const axiosDetail = exception.response?.data?.message || exception.response?.data?.detail || exception.message;\n const url = exception.config?.url;\n status = HttpStatus.BAD_GATEWAY;\n detail = `Upstream service error${axiosStatus ? ` (${axiosStatus})` : ''}: ${axiosDetail}`;\n this.logger.error(`Upstream API error [${axiosStatus}]: ${axiosDetail} — URL: ${url}`, exception.stack);\n } else {\n // Unknown errors — logged by HttpLoggerInterceptor, no need to log again here\n detail = 'An unexpected error occurred';\n }\n\n const problemDetails: ApiErrorResponse = {\n type,\n title: getHttpStatusTitle(status),\n status,\n ...(label && { label }),\n detail,\n instance: request.url,\n errors,\n };\n\n response.header('Content-Type', 'application/problem+json').status(status).send(problemDetails);\n }\n\n // Duck-type check for HttpException — avoids instanceof failing across pnpm package instances\n private isHttpException(error: unknown): error is HttpException {\n return (\n error instanceof Error &&\n typeof (error as { getStatus?: unknown }).getStatus === 'function' &&\n typeof (error as { getResponse?: unknown }).getResponse === 'function'\n );\n }\n\n // Duck-type check for AxiosError without importing axios\n private isAxiosError(error: unknown): error is Error & {\n isAxiosError: true;\n response?: { status?: number; data?: Record<string, unknown> };\n config?: { url?: string };\n } {\n return error instanceof Error && (error as { isAxiosError?: boolean }).isAxiosError === true;\n }\n\n private isProblemLikeObject(error: unknown): error is Record<string, unknown> {\n if (!error || typeof error !== 'object') return false;\n const obj = error as Record<string, unknown>;\n return (\n typeof obj.status === 'number' ||\n typeof obj.statusCode === 'number' ||\n typeof obj.detail === 'string' ||\n Array.isArray(obj.errors)\n );\n }\n}\n","import { HttpStatus } from '@nestjs/common';\nimport { HttpProblemException, type ProblemOptions } from './base-field.exception';\n\nexport class ConflictException extends HttpProblemException {\n constructor(detailOrOptions?: string | ProblemOptions) {\n super(detailOrOptions ?? 'Conflict', HttpStatus.CONFLICT);\n }\n}\n","import { HttpException, HttpStatus } from '@nestjs/common';\nimport type { FieldError } from '../types/error-response.types';\n\n// Re-export FieldError for backwards compatibility\nexport type { FieldError } from '../types/error-response.types';\n\nexport interface ProblemOptions {\n type?: string;\n label?: string;\n detail?: string;\n errors?: FieldError[];\n}\n\nexport abstract class HttpProblemException extends HttpException {\n constructor(detailOrOptions: string | ProblemOptions, httpStatus: HttpStatus) {\n const options = typeof detailOrOptions === 'string' ? { detail: detailOrOptions } : detailOrOptions;\n\n super(\n {\n type: options.type ?? 'about:blank',\n label: options.label,\n detail: options.detail,\n errors: options.errors ?? [],\n },\n httpStatus,\n );\n }\n}\n","import { ConflictException } from '../exceptions/conflict.exception';\n\nconst PG_UNIQUE_VIOLATION = '23505';\n\nexport type PgErrorShape = {\n code?: string;\n message?: string;\n constraint?: string;\n table?: string;\n schema?: string;\n column?: string;\n detail?: string;\n hint?: string;\n};\n\n// Returns a ConflictException for a Postgres unique-violation error, otherwise undefined.\nexport function tryTranslatePgError(error: unknown): ConflictException | undefined {\n const pgError = findPgError(error);\n if (!pgError) return undefined;\n const { code, constraint, table, detail } = pgError;\n if (code !== PG_UNIQUE_VIOLATION) return undefined;\n return new ConflictException({\n label: 'Duplicate Entry',\n detail: detail?.trim() || 'A record with these values already exists.',\n errors: [],\n ...(constraint || table ? { meta: { constraint, table } } : {}),\n });\n}\n\n// Walks up to N levels of `.cause` looking for a pg-shaped error (has SQLSTATE `code`), capping depth.\nexport function findPgError(error: unknown, depth = 0): PgErrorShape | undefined {\n if (!error || typeof error !== 'object' || depth > 5) return undefined;\n const candidate = error as PgErrorShape & { cause?: unknown };\n if (typeof candidate.code === 'string') return candidate;\n return findPgError(candidate.cause, depth + 1);\n}\n","import { type ArgumentsHost, Catch, type ExceptionFilter } from '@nestjs/common';\nimport { HttpExceptionFilter } from './http-exception.filter';\n\n@Catch()\nexport class TransportAwareExceptionFilter implements ExceptionFilter {\n private readonly httpFilter = new HttpExceptionFilter();\n\n catch(exception: unknown, host: ArgumentsHost): void {\n if (host.getType() !== 'http') {\n throw exception;\n }\n this.httpFilter.catch(exception, host);\n }\n}\n"],"mappings":";;;;AAAA,SAASA,kBAAkB;AAEpB,IAAKC,YAAAA,0BAAAA,YAAAA;;;;;;;;;SAAAA;;AAYL,SAASC,oBAAoBC,QAAc;AAChD,UAAQA,QAAAA;IACN,KAAKC,WAAWC;AACd,aAAA;IACF,KAAKD,WAAWE;AACd,aAAA;IACF,KAAKF,WAAWG;AACd,aAAA;IACF,KAAKH,WAAWI;IAChB,KAAKJ,WAAWK;AACd,aAAA;IACF,KAAKL,WAAWM;AACd,aAAA;IACF,KAAKN,WAAWO;AACd,aAAA;IACF;AAEE,UAAIR,UAAU,OAAOA,SAAS,KAAK;AACjC,eAAA;MACF;AACA,aAAA;EACJ;AACF;AAtBgBD;;;ACdhB,SAASU,cAAAA,mBAAkB;AA8BpB,SAASC,mBAAmBC,QAAc;AAE/C,QAAMC,UAAUC,OAAOC,QAAQC,WAAAA,EAAYC,KAAK,CAAC,CAACC,KAAKC,KAAAA,MAAWA,UAAUP,UAAUQ,OAAOC,MAAMD,OAAOF,GAAAA,CAAAA,CAAAA,IAAS,CAAA;AAEnH,MAAI,CAACL,SAAS;AACZ,WAAO;EACT;AAGA,SAAOA,QACJS,MAAM,GAAA,EACNC,IAAI,CAACC,SAASA,KAAKC,OAAO,CAAA,EAAGC,YAAW,IAAKF,KAAKG,MAAM,CAAA,EAAGC,YAAW,CAAA,EACtEC,KAAK,GAAA;AACV;AAbgBlB;AAgBhB,SAASmB,6BACPC,SAAkF;AAElF,SAAOA,QACJR,IAAI,CAACS,QAAAA;AACJ,QAAI,OAAOA,QAAQ,YAAY,cAAcA,OAAO,iBAAiBA,KAAK;AACxE,YAAMC,mBAAmBnB,OAAOoB,OAAOF,IAAIG,WAAW;AACtD,aAAO;QACLC,OAAOJ,IAAIK;QACXN,SAASE,iBAAiB,CAAA,KAAM;MAClC;IACF;AAEA,WAAO;EACT,CAAA,EACCK,OAAO,CAACC,UAA+BA,UAAU,IAAA;AACtD;AAhBST;AAmBF,SAASU,2BACdC,mBACAC,uBAA6B;AAE7B,MAAIC,OAAO;AACX,MAAIC;AACJ,MAAIC;AACJ,MAAIC,SAAuB,CAAA;AAE3B,MAAI,OAAOL,sBAAsB,UAAU;AACzCI,aAASJ;AACT,WAAO;MAAEE;MAAMC;MAAOC;MAAQC;IAAO;EACvC;AAEA,MAAIL,sBAAsB,QAAQ,OAAOA,sBAAsB,UAAU;AACvE,UAAMM,cAAcN;AAGpB,QAAI,UAAUM,eAAe,WAAWA,eAAe,YAAYA,aAAa;AAC9E,YAAMC,kBAAkBD;AACxBJ,aAAOK,gBAAgBL,QAAQ;AAC/BC,cAAQI,gBAAgBJ;AACxBC,eAASG,gBAAgBH,UAAUH;AACnCI,eAASE,gBAAgBF,UAAU,CAAA;IACrC,WAES,aAAaC,eAAeE,MAAMC,QAAQH,YAAYhB,OAAO,GAAG;AACvEe,eAAShB,6BAA6BiB,YAAYhB,OAAO;AACzDc,eAAS;IACX,WAES,aAAaE,aAAa;AACjC,YAAMhB,UAAWgB,YAA0ChB;AAC3Dc,eAASI,MAAMC,QAAQnB,OAAAA,IAAWA,QAAQF,KAAK,IAAA,IAAQE;IACzD;EACF;AAEA,SAAO;IAAEY;IAAMC;IAAOC;IAAQC;EAAO;AACvC;AAtCgBN;;;AC3BhB,SAASW,oBAAoBC,OAAc;AACzC,SACEA,iBAAiBC,SACjB,OAAQD,MAAkCE,cAAc,cACxD,OAAQF,MAAoCG,gBAAgB;AAEhE;AANSJ;AAeT,SAASK,cAAcJ,OAAc;AACnC,MAAIA,SAAS,QAAQ,OAAOA,UAAU,UAAU;AAC9C,WAAO;EACT;AACA,QAAMK,IAAIL;AACV,SAAO,OAAOK,EAAEC,WAAW,YAAY,OAAOD,EAAEE,eAAe;AACjE;AANSH;AAeT,SAASI,kBAAkBR,OAAoC;AAC7D,MAAIS,UAAmBT;AAEvB,WAASU,QAAQ,GAAGD,WAAWC,QAAQ,IAAIA,SAAS;AAClD,QAAIX,oBAAoBU,OAAAA,GAAU;AAChC,YAAMH,SAASG,QAAQP,UAAS;AAChC,aAAO;QAAEI;QAAQK,UAAUF,QAAQN,YAAW;QAAIS,UAAUH,QAAQI,WAAWC,mBAAmBR,MAAAA;MAAQ;IAC5G;AACA,QAAIF,cAAcK,OAAAA,GAAU;AAC1B,YAAMH,SAASG,QAAQH,UAAUG,QAAQF,cAAc;AACvD,aAAO;QAAED;QAAQK,UAAUF;QAASG,UAAUH,QAAQM,UAAUN,QAAQI,WAAWC,mBAAmBR,MAAAA;MAAQ;IAChH;AACA,UAAMU,OAAOP;AACbA,cAAUO,KAAKC,iBAAiBD,KAAKE;EACvC;AACA,SAAOC;AACT;AAhBSX;AAkBT,IAAMY,2BAA2B;AAG1B,SAASC,yBACdC,MAA+B;AAE/B,QAAM,EAAEC,cAAcC,WAAU,IAAKF;AAErC,SAAO,CAACG,gBAAgBzB,UAAAA;AACtB,UAAM0B,WAAY1B,SAASmB;AAC3B,UAAMQ,SAASnB,kBAAkBkB,QAAAA;AAGjC,QAAIpB,SAAS;AACb,QAAIS;AACJ,QAAIa;AACJ,QAAIC,cAAyD,CAAA;AAE7D,QAAIF,QAAQ;AACVrB,eAASqB,OAAOrB;AAChB,YAAMwB,YAAYC,2BAA2BJ,OAAOhB,UAAUgB,OAAOf,QAAQ;AAC7EG,eAASe,UAAUf;AACnBa,cAAQE,UAAUF;AAClBC,oBAAcC,UAAUE;IAC1B;AAEA,UAAMC,OAAOC,oBAAoB5B,MAAAA;AAGjC,QAAIO,UAAUE,UAAUU,eAAeZ;AACvC,QAAIoB,SAAS,cAAcV,cAAc;AACvCV,gBAAUO;IACZ;AAGA,UAAMe,WAAoC;MAAE,GAAIV,eAAeW,cAAc,CAAC;IAAG;AAEjF,UAAMC,UAAUb,aAAAA;AAChB,UAAMc,aAAY,oBAAIC,KAAAA,GAAOC,YAAW;AAExC,UAAMJ,aAAuC;MAC3C,GAAGD;;MAEHF;MACA,GAAII,YAAYlB,SAAY;QAAEkB;MAAQ,IAAI,CAAC;MAC3CC;MACA,GAAIV,UAAUT,SAAY;QAAES;MAAM,IAAI,CAAC;MACvC,GAAIC,YAAYY,SAAS,IAAI;QAAEZ;MAAY,IAAI,CAAC;IAClD;AAEA,QAAIN,cAAc;AAEhB,aAAOa,WAAWM;AAClB,aAAON,WAAWO;AAClB,aAAOP,WAAWnB;IACpB;AAEA,UAAM2B,SAAqC;MACzC/B;MACAuB;IACF;AAEA,QAAIX,eAAeoB,UAAWD,QAAOC,YAAYpB,eAAeoB;AAChE,QAAIpB,eAAeqB,KAAMF,QAAOE,OAAOrB,eAAeqB;AAEtD,WAAOF;EACT;AACF;AAhEgBvB;;;ACzFhB,SAEE0B,OAGAC,cAAAA,aACAC,cACK;;;ACPP,SAASC,cAAAA,mBAAkB;;;ACA3B,SAASC,qBAAiC;AAanC,IAAeC,uBAAf,cAA4CC,cAAAA;EAbnD,OAamDA;;;EACjD,YAAYC,iBAA0CC,YAAwB;AAC5E,UAAMC,UAAU,OAAOF,oBAAoB,WAAW;MAAEG,QAAQH;IAAgB,IAAIA;AAEpF,UACE;MACEI,MAAMF,QAAQE,QAAQ;MACtBC,OAAOH,QAAQG;MACfF,QAAQD,QAAQC;MAChBG,QAAQJ,QAAQI,UAAU,CAAA;IAC5B,GACAL,UAAAA;EAEJ;AACF;;;ADxBO,IAAMM,oBAAN,cAAgCC,qBAAAA;EAHvC,OAGuCA;;;EACrC,YAAYC,iBAA2C;AACrD,UAAMA,mBAAmB,YAAYC,YAAWC,QAAQ;EAC1D;AACF;;;AELA,IAAMC,sBAAsB;AAcrB,SAASC,oBAAoBC,OAAc;AAChD,QAAMC,UAAUC,YAAYF,KAAAA;AAC5B,MAAI,CAACC,QAAS,QAAOE;AACrB,QAAM,EAAEC,MAAMC,YAAYC,OAAOC,OAAM,IAAKN;AAC5C,MAAIG,SAASN,oBAAqB,QAAOK;AACzC,SAAO,IAAIK,kBAAkB;IAC3BC,OAAO;IACPF,QAAQA,QAAQG,KAAAA,KAAU;IAC1BC,QAAQ,CAAA;IACR,GAAIN,cAAcC,QAAQ;MAAEM,MAAM;QAAEP;QAAYC;MAAM;IAAE,IAAI,CAAC;EAC/D,CAAA;AACF;AAXgBP;AAcT,SAASG,YAAYF,OAAgBa,QAAQ,GAAC;AACnD,MAAI,CAACb,SAAS,OAAOA,UAAU,YAAYa,QAAQ,EAAG,QAAOV;AAC7D,QAAMW,YAAYd;AAClB,MAAI,OAAOc,UAAUV,SAAS,SAAU,QAAOU;AAC/C,SAAOZ,YAAYY,UAAUC,OAAOF,QAAQ,CAAA;AAC9C;AALgBX;A;;;;;;;;;AHdT,IAAMc,sBAAN,MAAMA,qBAAAA;SAAAA;;;EACMC,SAAS,IAAIC,OAAOF,qBAAoBG,IAAI;EAE7DC,MAAMC,WAAoBC,MAAqB;AAC7C,UAAMC,MAAMD,KAAKE,aAAY;AAC7B,UAAMC,WAAWF,IAAIG,YAAW;AAChC,UAAMC,UAAUJ,IAAIK,WAAU;AAG9B,UAAMC,oBAAoBC,oBAAoBT,SAAAA;AAC9C,QAAIQ,kBAAmBR,aAAYQ;AAEnC,QAAIE,SAASC,YAAWC;AACxB,QAAIC,OAAO;AACX,QAAIC;AACJ,QAAIC,SAAS;AACb,QAAIC,SAAuB,CAAA;AAE3B,QAAI,KAAKC,gBAAgBjB,SAAAA,GAAY;AACnCU,eAASV,UAAUkB,UAAS;AAC5B,YAAMC,oBAAoBnB,UAAUK,YAAW;AAG/C,YAAMe,YAAYC,2BAA2BF,mBAAmBnB,UAAUsB,WAAWC,mBAAmBb,MAAAA,CAAAA;AACxGG,aAAOO,UAAUP;AACjBC,cAAQM,UAAUN;AAElBC,eAASK,UAAUL,UAAUA;AAC7BC,eAASI,UAAUJ;IACrB,WAAW,KAAKQ,oBAAoBxB,SAAAA,GAAY;AAC9C,YAAMyB,aAAazB;AACnB,YAAM0B,kBAAkBD,WAAWf,UAAUe,WAAWE;AACxD,UAAI,OAAOD,oBAAoB,YAAYA,mBAAmB,OAAOA,mBAAmB,KAAK;AAC3FhB,iBAASgB;MACX;AACAb,aAAO,OAAOY,WAAWZ,SAAS,WAAWY,WAAWZ,OAAO;AAC/DC,cAAQ,OAAOW,WAAWX,UAAU,WAAWW,WAAWX,QAAQc;AAClEb,eACE,OAAOU,WAAWV,WAAW,WACzBU,WAAWV,SACX,OAAOU,WAAWH,YAAY,WAC5BG,WAAWH,UACXC,mBAAmBb,MAAAA;AAC3BM,eAASa,MAAMC,QAAQL,WAAWT,MAAM,IAAKS,WAAWT,SAA0B,CAAA;IACpF,WAAW,KAAKe,aAAa/B,SAAAA,GAAY;AAEvC,YAAMgC,cAAchC,UAAUI,UAAUM;AACxC,YAAMuB,cAAcjC,UAAUI,UAAU8B,MAAMZ,WAAWtB,UAAUI,UAAU8B,MAAMnB,UAAUf,UAAUsB;AACvG,YAAMa,MAAMnC,UAAUoC,QAAQD;AAC9BzB,eAASC,YAAW0B;AACpBtB,eAAS,yBAAyBiB,cAAc,KAAKA,WAAAA,MAAiB,EAAA,KAAOC,WAAAA;AAC7E,WAAKrC,OAAO0C,MAAM,uBAAuBN,WAAAA,MAAiBC,WAAAA,gBAAsBE,GAAAA,IAAOnC,UAAUuC,KAAK;IACxG,OAAO;AAELxB,eAAS;IACX;AAEA,UAAMyB,iBAAmC;MACvC3B;MACA4B,OAAOlB,mBAAmBb,MAAAA;MAC1BA;MACA,GAAII,SAAS;QAAEA;MAAM;MACrBC;MACA2B,UAAUpC,QAAQ6B;MAClBnB;IACF;AAEAZ,aAASuC,OAAO,gBAAgB,0BAAA,EAA4BjC,OAAOA,MAAAA,EAAQkC,KAAKJ,cAAAA;EAClF;;EAGQvB,gBAAgBqB,OAAwC;AAC9D,WACEA,iBAAiBO,SACjB,OAAQP,MAAkCpB,cAAc,cACxD,OAAQoB,MAAoCjC,gBAAgB;EAEhE;;EAGQ0B,aAAaO,OAInB;AACA,WAAOA,iBAAiBO,SAAUP,MAAqCP,iBAAiB;EAC1F;EAEQP,oBAAoBc,OAAkD;AAC5E,QAAI,CAACA,SAAS,OAAOA,UAAU,SAAU,QAAO;AAChD,UAAMQ,MAAMR;AACZ,WACE,OAAOQ,IAAIpC,WAAW,YACtB,OAAOoC,IAAInB,eAAe,YAC1B,OAAOmB,IAAI/B,WAAW,YACtBc,MAAMC,QAAQgB,IAAI9B,MAAM;EAE5B;AACF;;;;;;AIlHA,SAA6B+B,SAAAA,cAAmC;;;;;;;;AAIzD,IAAMC,gCAAN,MAAMA;SAAAA;;;EACMC,aAAa,IAAIC,oBAAAA;EAElCC,MAAMC,WAAoBC,MAA2B;AACnD,QAAIA,KAAKC,QAAO,MAAO,QAAQ;AAC7B,YAAMF;IACR;AACA,SAAKH,WAAWE,MAAMC,WAAWC,IAAAA;EACnC;AACF;;;;","names":["HttpStatus","ErrorCode","errorCodeFromStatus","status","HttpStatus","UNAUTHORIZED","FORBIDDEN","NOT_FOUND","BAD_REQUEST","UNPROCESSABLE_ENTITY","CONFLICT","TOO_MANY_REQUESTS","HttpStatus","getHttpStatusTitle","status","enumKey","Object","entries","HttpStatus","find","key","value","Number","isNaN","split","map","word","charAt","toUpperCase","slice","toLowerCase","join","extractValidationFieldErrors","message","msg","constraintValues","values","constraints","field","property","filter","error","extractProblemFromResponse","exceptionResponse","problemFallbackDetail","type","label","detail","errors","responseObj","problemResponse","Array","isArray","isHttpExceptionLike","error","Error","getStatus","getResponse","isProblemLike","o","status","statusCode","findProblemSource","current","depth","response","fallback","message","getHttpStatusTitle","detail","next","originalError","thrownValue","undefined","GENERIC_INTERNAL_MESSAGE","createGraphqlFormatError","opts","isProduction","getTraceId","formattedError","gqlError","source","label","fieldErrors","extracted","extractProblemFromResponse","errors","code","errorCodeFromStatus","incoming","extensions","traceId","timestamp","Date","toISOString","length","stacktrace","exception","result","locations","path","Catch","HttpStatus","Logger","HttpStatus","HttpException","HttpProblemException","HttpException","detailOrOptions","httpStatus","options","detail","type","label","errors","ConflictException","HttpProblemException","detailOrOptions","HttpStatus","CONFLICT","PG_UNIQUE_VIOLATION","tryTranslatePgError","error","pgError","findPgError","undefined","code","constraint","table","detail","ConflictException","label","trim","errors","meta","depth","candidate","cause","HttpExceptionFilter","logger","Logger","name","catch","exception","host","ctx","switchToHttp","response","getResponse","request","getRequest","translatedPgError","tryTranslatePgError","status","HttpStatus","INTERNAL_SERVER_ERROR","type","label","detail","errors","isHttpException","getStatus","exceptionResponse","extracted","extractProblemFromResponse","message","getHttpStatusTitle","isProblemLikeObject","problemObj","statusCandidate","statusCode","undefined","Array","isArray","isAxiosError","axiosStatus","axiosDetail","data","url","config","BAD_GATEWAY","error","stack","problemDetails","title","instance","header","send","Error","obj","Catch","TransportAwareExceptionFilter","httpFilter","HttpExceptionFilter","catch","exception","host","getType"]}
1
+ {"version":3,"sources":["../src/filters/error-code.ts","../src/filters/problem-extraction.ts","../src/filters/graphql-format-error.ts","../src/filters/http-exception.filter.ts","../src/exceptions/conflict.exception.ts","../src/exceptions/base-field.exception.ts","../src/filters/pg-error.translator.ts","../src/filters/transport-aware-exception.filter.ts"],"sourcesContent":["import { HttpStatus } from '@nestjs/common';\n\nexport enum ErrorCode {\n UNAUTHENTICATED = 'UNAUTHENTICATED',\n FORBIDDEN = 'FORBIDDEN',\n NOT_FOUND = 'NOT_FOUND',\n VALIDATION_FAILED = 'VALIDATION_FAILED',\n CONFLICT = 'CONFLICT',\n RATE_LIMITED = 'RATE_LIMITED',\n BAD_REQUEST = 'BAD_REQUEST',\n INTERNAL = 'INTERNAL',\n}\n\n// Maps an HTTP status code to the canonical ErrorCode so HTTP and GraphQL classify identically.\nexport function errorCodeFromStatus(status: number): ErrorCode {\n switch (status) {\n case HttpStatus.UNAUTHORIZED: // 401\n return ErrorCode.UNAUTHENTICATED;\n case HttpStatus.FORBIDDEN: // 403\n return ErrorCode.FORBIDDEN;\n case HttpStatus.NOT_FOUND: // 404\n return ErrorCode.NOT_FOUND;\n case HttpStatus.BAD_REQUEST: // 400\n case HttpStatus.UNPROCESSABLE_ENTITY: // 422\n return ErrorCode.VALIDATION_FAILED;\n case HttpStatus.CONFLICT: // 409\n return ErrorCode.CONFLICT;\n case HttpStatus.TOO_MANY_REQUESTS: // 429\n return ErrorCode.RATE_LIMITED;\n default:\n // Any other 4xx is a generic bad request; 5xx and unknown collapse to INTERNAL.\n if (status >= 400 && status < 500) {\n return ErrorCode.BAD_REQUEST;\n }\n return ErrorCode.INTERNAL;\n }\n}\n","import { HttpStatus } from '@nestjs/common';\nimport type { FieldError } from '../types/error-response.types';\n\ninterface ProblemExceptionResponse {\n type?: string;\n label?: string;\n detail?: string;\n errors?: FieldError[];\n}\n\ninterface ValidationExceptionResponse {\n message: Array<string | { property: string; constraints: Record<string, string> }>;\n error?: string;\n}\n\ninterface StandardExceptionResponse {\n message: string | string[];\n error?: string;\n}\n\ntype ExceptionResponseObject = ProblemExceptionResponse | ValidationExceptionResponse | StandardExceptionResponse;\n\nexport interface ExtractedProblem {\n type: string;\n label?: string;\n detail?: string;\n errors: FieldError[];\n}\n\n// Converts an HTTP status code to its title string (e.g., 400 → \"Bad Request\")\nexport function getHttpStatusTitle(status: number): string {\n // Find the enum key for the given status code\n const enumKey = Object.entries(HttpStatus).find(([key, value]) => value === status && Number.isNaN(Number(key)))?.[0];\n\n if (!enumKey) {\n return 'Error';\n }\n\n // Convert enum key to title case (e.g., BAD_REQUEST -> Bad Request)\n return enumKey\n .split('_')\n .map((word) => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase())\n .join(' ');\n}\n\n// Extracts field-specific errors from a class-validator ValidationPipe message array, mirroring the RFC 9457 errors[].\nfunction extractValidationFieldErrors(\n message: Array<string | { property: string; constraints: Record<string, string> }>,\n): FieldError[] {\n return message\n .map((msg) => {\n if (typeof msg === 'object' && 'property' in msg && 'constraints' in msg) {\n const constraintValues = Object.values(msg.constraints);\n return {\n field: msg.property,\n message: constraintValues[0] ?? 'Validation failed',\n };\n }\n // Non-field-specific validation messages are ignored here; they belong at the detail level.\n return null;\n })\n .filter((error): error is FieldError => error !== null);\n}\n\n// Parses a NestJS HttpException response body into normalized problem fields across the SDK's three body shapes.\nexport function extractProblemFromResponse(\n exceptionResponse: string | object,\n problemFallbackDetail: string,\n): ExtractedProblem {\n let type = 'about:blank';\n let label: string | undefined;\n let detail: string | undefined;\n let errors: FieldError[] = [];\n\n if (typeof exceptionResponse === 'string') {\n detail = exceptionResponse;\n return { type, label, detail, errors };\n }\n\n if (exceptionResponse !== null && typeof exceptionResponse === 'object') {\n const responseObj = exceptionResponse as ExceptionResponseObject;\n\n // Custom HttpProblemException from @vritti/api-sdk\n if ('type' in responseObj || 'label' in responseObj || 'errors' in responseObj) {\n const problemResponse = responseObj as ProblemExceptionResponse;\n type = problemResponse.type ?? 'about:blank';\n label = problemResponse.label;\n detail = problemResponse.detail ?? problemFallbackDetail;\n errors = problemResponse.errors ?? [];\n }\n // class-validator DTO validation errors\n else if ('message' in responseObj && Array.isArray(responseObj.message)) {\n errors = extractValidationFieldErrors(responseObj.message);\n detail = 'Validation failed';\n }\n // Standard NestJS exceptions\n else if ('message' in responseObj) {\n const message = (responseObj as StandardExceptionResponse).message;\n detail = Array.isArray(message) ? message.join(', ') : message;\n }\n }\n\n return { type, label, detail, errors };\n}\n","import { type ErrorCode, errorCodeFromStatus } from './error-code';\nimport { extractProblemFromResponse, getHttpStatusTitle } from './problem-extraction';\n\n// graphql and @nestjs/graphql are optional peers not installed here, so we declare minimal structural shapes locally.\n\ninterface GraphqlFormattedErrorShape {\n message: string;\n locations?: ReadonlyArray<{ line: number; column: number }>;\n path?: ReadonlyArray<string | number>;\n extensions?: Record<string, unknown>;\n}\n\ninterface GraphqlErrorShape {\n message: string;\n originalError?: unknown;\n extensions?: Record<string, unknown>;\n}\n\ninterface HttpExceptionLike {\n getStatus(): number;\n getResponse(): string | object;\n message: string;\n}\n\nexport interface GraphqlFormatErrorOptions {\n isProduction: boolean;\n getTraceId?: () => string | undefined;\n}\n\nexport interface FormattedErrorExtensions {\n code: ErrorCode;\n traceId?: string;\n timestamp: string;\n fieldErrors?: Array<{ field: string; message: string }>;\n [key: string]: unknown;\n}\n\n// Duck-types a NestJS HttpException without importing @nestjs/common (cross-package-instance safe).\nfunction isHttpExceptionLike(error: unknown): error is HttpExceptionLike {\n return (\n error instanceof Error &&\n typeof (error as { getStatus?: unknown }).getStatus === 'function' &&\n typeof (error as { getResponse?: unknown }).getResponse === 'function'\n );\n}\n\ninterface ProblemLike {\n status?: number;\n statusCode?: number;\n detail?: string;\n message?: string;\n}\n\nfunction isProblemLike(error: unknown): error is ProblemLike {\n if (error == null || typeof error !== 'object') {\n return false;\n }\n const o = error as Record<string, unknown>;\n return typeof o.status === 'number' || typeof o.statusCode === 'number';\n}\n\ninterface ProblemSource {\n status: number;\n response: string | object;\n fallback: string;\n}\n\n// Walks the error chain to find the underlying HttpException or plain RFC 9457 problem via originalError/thrownValue.\nfunction findProblemSource(error: GraphqlErrorShape | undefined): ProblemSource | undefined {\n let current: unknown = error;\n // Bounded walk — guard against cyclic chains.\n for (let depth = 0; current && depth < 10; depth++) {\n if (isHttpExceptionLike(current)) {\n const status = current.getStatus();\n return { status, response: current.getResponse(), fallback: current.message ?? getHttpStatusTitle(status) };\n }\n if (isProblemLike(current)) {\n const status = current.status ?? current.statusCode ?? 500;\n return { status, response: current, fallback: current.detail ?? current.message ?? getHttpStatusTitle(status) };\n }\n const next = current as { originalError?: unknown; thrownValue?: unknown };\n current = next.originalError ?? next.thrownValue;\n }\n return undefined;\n}\n\nconst GENERIC_INTERNAL_MESSAGE = 'Internal server error';\n\n// Builds an Apollo formatError that normalizes every GraphQL error into a stable, transport-consistent shape.\nexport function createGraphqlFormatError(\n opts: GraphqlFormatErrorOptions,\n): (formattedError: GraphqlFormattedErrorShape, error: unknown) => GraphqlFormattedErrorShape {\n const { isProduction, getTraceId } = opts;\n\n return (formattedError, error) => {\n const gqlError = (error ?? undefined) as GraphqlErrorShape | undefined;\n const source = findProblemSource(gqlError);\n\n // Derive status + problem body from the underlying source since Apollo only copies .message and defaults code to INTERNAL.\n let status = 500;\n let detail: string | undefined;\n let label: string | undefined;\n let fieldErrors: Array<{ field: string; message: string }> = [];\n\n if (source) {\n status = source.status;\n const extracted = extractProblemFromResponse(source.response, source.fallback);\n detail = extracted.detail;\n label = extracted.label;\n fieldErrors = extracted.errors;\n }\n\n const code = errorCodeFromStatus(status);\n\n // Prefer the problem detail, then the formatted message; never surface internals for INTERNAL in production.\n let message = detail ?? formattedError.message;\n if (code === 'INTERNAL' && isProduction) {\n message = GENERIC_INTERNAL_MESSAGE;\n }\n\n // Start from Apollo's extensions so any framework-set keys survive, then normalize ours on top.\n const incoming: Record<string, unknown> = { ...(formattedError.extensions ?? {}) };\n\n const traceId = getTraceId?.();\n const timestamp = new Date().toISOString();\n\n const extensions: FormattedErrorExtensions = {\n ...incoming,\n // Always our canonical code — overrides Apollo's default INTERNAL_SERVER_ERROR.\n code,\n ...(traceId !== undefined ? { traceId } : {}),\n timestamp,\n ...(label !== undefined ? { label } : {}),\n ...(fieldErrors.length > 0 ? { fieldErrors } : {}),\n };\n\n if (isProduction) {\n // Strip anything that could leak server internals to clients.\n delete extensions.stacktrace;\n delete extensions.exception;\n delete extensions.originalError;\n }\n\n const result: GraphqlFormattedErrorShape = {\n message,\n extensions,\n };\n // Preserve location/path metadata GraphQL attaches (useful to clients, leaks nothing).\n if (formattedError.locations) result.locations = formattedError.locations;\n if (formattedError.path) result.path = formattedError.path;\n\n return result;\n };\n}\n","import {\n type ArgumentsHost,\n Catch,\n type ExceptionFilter,\n type HttpException,\n HttpStatus,\n Logger,\n} from '@nestjs/common';\nimport type { FastifyReply, FastifyRequest } from 'fastify';\nimport type { ApiErrorResponse, FieldError } from '../types/error-response.types';\nimport { tryTranslatePgError } from './pg-error.translator';\nimport { extractProblemFromResponse, getHttpStatusTitle } from './problem-extraction';\n\nexport { getHttpStatusTitle };\n\n@Catch()\nexport class HttpExceptionFilter implements ExceptionFilter {\n private readonly logger = new Logger(HttpExceptionFilter.name);\n\n catch(exception: unknown, host: ArgumentsHost) {\n const ctx = host.switchToHttp();\n const response = ctx.getResponse<FastifyReply>();\n const request = ctx.getRequest<FastifyRequest>();\n\n // Translate raw Postgres errors (e.g. 23505 unique_violation) into a ConflictException before classifying as 500.\n const translatedPgError = tryTranslatePgError(exception);\n if (translatedPgError) exception = translatedPgError;\n\n let status = HttpStatus.INTERNAL_SERVER_ERROR;\n let type = 'about:blank';\n let label: string | undefined;\n let detail = 'Internal server error';\n let errors: FieldError[] = [];\n\n if (this.isHttpException(exception)) {\n status = exception.getStatus();\n const exceptionResponse = exception.getResponse();\n\n // Reuse the shared extractor so HTTP and GraphQL surface identical problem details.\n const extracted = extractProblemFromResponse(exceptionResponse, exception.message ?? getHttpStatusTitle(status));\n type = extracted.type;\n label = extracted.label;\n // Keep the initial 'Internal server error' when the body matched no known shape (byte-identical HTTP output).\n detail = extracted.detail ?? detail;\n errors = extracted.errors;\n } else if (this.isProblemLikeObject(exception)) {\n const problemObj = exception as Record<string, unknown>;\n const statusCandidate = problemObj.status ?? problemObj.statusCode;\n if (typeof statusCandidate === 'number' && statusCandidate >= 400 && statusCandidate <= 599) {\n status = statusCandidate;\n }\n type = typeof problemObj.type === 'string' ? problemObj.type : 'about:blank';\n label = typeof problemObj.label === 'string' ? problemObj.label : undefined;\n detail =\n typeof problemObj.detail === 'string'\n ? problemObj.detail\n : typeof problemObj.message === 'string'\n ? problemObj.message\n : getHttpStatusTitle(status);\n errors = Array.isArray(problemObj.errors) ? (problemObj.errors as FieldError[]) : [];\n } else if (this.isAxiosError(exception)) {\n // Outgoing HTTP call failures (e.g., service-to-service calls)\n const axiosStatus = exception.response?.status;\n const axiosDetail = exception.response?.data?.message || exception.response?.data?.detail || exception.message;\n const url = exception.config?.url;\n status = HttpStatus.BAD_GATEWAY;\n detail = `Upstream service error${axiosStatus ? ` (${axiosStatus})` : ''}: ${axiosDetail}`;\n this.logger.error(`Upstream API error [${axiosStatus}]: ${axiosDetail} — URL: ${url}`, exception.stack);\n } else {\n // Unknown errors — logged by HttpLoggerInterceptor, no need to log again here\n detail = 'An unexpected error occurred';\n }\n\n const problemDetails: ApiErrorResponse = {\n type,\n title: getHttpStatusTitle(status),\n status,\n ...(label && { label }),\n detail,\n instance: request.url,\n errors,\n };\n\n response.header('Content-Type', 'application/problem+json').status(status).send(problemDetails);\n }\n\n // Duck-type check for HttpException — avoids instanceof failing across pnpm package instances\n private isHttpException(error: unknown): error is HttpException {\n return (\n error instanceof Error &&\n typeof (error as { getStatus?: unknown }).getStatus === 'function' &&\n typeof (error as { getResponse?: unknown }).getResponse === 'function'\n );\n }\n\n // Duck-type check for AxiosError without importing axios\n private isAxiosError(error: unknown): error is Error & {\n isAxiosError: true;\n response?: { status?: number; data?: Record<string, unknown> };\n config?: { url?: string };\n } {\n return error instanceof Error && (error as { isAxiosError?: boolean }).isAxiosError === true;\n }\n\n private isProblemLikeObject(error: unknown): error is Record<string, unknown> {\n if (!error || typeof error !== 'object') return false;\n const obj = error as Record<string, unknown>;\n return (\n typeof obj.status === 'number' ||\n typeof obj.statusCode === 'number' ||\n typeof obj.detail === 'string' ||\n Array.isArray(obj.errors)\n );\n }\n}\n","import { HttpStatus } from '@nestjs/common';\nimport { HttpProblemException, type ProblemOptions } from './base-field.exception';\n\nexport class ConflictException extends HttpProblemException {\n constructor(detailOrOptions?: string | ProblemOptions) {\n super(detailOrOptions ?? 'Conflict', HttpStatus.CONFLICT);\n }\n}\n","import { HttpException, HttpStatus } from '@nestjs/common';\nimport type { FieldError } from '../types/error-response.types';\n\n// Re-export FieldError for backwards compatibility\nexport type { FieldError } from '../types/error-response.types';\n\nexport interface ProblemOptions {\n type?: string;\n label?: string;\n detail?: string;\n errors?: FieldError[];\n}\n\nexport abstract class HttpProblemException extends HttpException {\n constructor(detailOrOptions: string | ProblemOptions, httpStatus: HttpStatus) {\n const options = typeof detailOrOptions === 'string' ? { detail: detailOrOptions } : detailOrOptions;\n\n super(\n {\n type: options.type ?? 'about:blank',\n label: options.label,\n detail: options.detail,\n errors: options.errors ?? [],\n },\n httpStatus,\n );\n }\n}\n","import { ConflictException } from '../exceptions/conflict.exception';\n\nconst PG_UNIQUE_VIOLATION = '23505';\n\nexport type PgErrorShape = {\n code?: string;\n message?: string;\n constraint?: string;\n table?: string;\n schema?: string;\n column?: string;\n detail?: string;\n hint?: string;\n};\n\n// Returns a ConflictException for a Postgres unique-violation error, otherwise undefined.\nexport function tryTranslatePgError(error: unknown): ConflictException | undefined {\n const pgError = findPgError(error);\n if (!pgError) return undefined;\n const { code, constraint, table, detail } = pgError;\n if (code !== PG_UNIQUE_VIOLATION) return undefined;\n return new ConflictException({\n label: 'Duplicate Entry',\n detail: detail?.trim() || 'A record with these values already exists.',\n errors: [],\n ...(constraint || table ? { meta: { constraint, table } } : {}),\n });\n}\n\n// Walks up to N levels of `.cause` looking for a pg-shaped error (has SQLSTATE `code`), capping depth.\nexport function findPgError(error: unknown, depth = 0): PgErrorShape | undefined {\n if (!error || typeof error !== 'object' || depth > 5) return undefined;\n const candidate = error as PgErrorShape & { cause?: unknown };\n if (typeof candidate.code === 'string') return candidate;\n return findPgError(candidate.cause, depth + 1);\n}\n","import { type ArgumentsHost, Catch, type ExceptionFilter } from '@nestjs/common';\nimport { HttpExceptionFilter } from './http-exception.filter';\n\n@Catch()\nexport class TransportAwareExceptionFilter implements ExceptionFilter {\n private readonly httpFilter = new HttpExceptionFilter();\n\n catch(exception: unknown, host: ArgumentsHost): void {\n if (host.getType() !== 'http') {\n throw exception;\n }\n this.httpFilter.catch(exception, host);\n }\n}\n"],"mappings":";;;;AAAA,SAASA,kBAAkB;AAEpB,IAAKC,YAAAA,0BAAAA,YAAAA;;;;;;;;;SAAAA;;AAYL,SAASC,oBAAoBC,QAAc;AAChD,UAAQA,QAAAA;IACN,KAAKC,WAAWC;AACd,aAAA;IACF,KAAKD,WAAWE;AACd,aAAA;IACF,KAAKF,WAAWG;AACd,aAAA;IACF,KAAKH,WAAWI;IAChB,KAAKJ,WAAWK;AACd,aAAA;IACF,KAAKL,WAAWM;AACd,aAAA;IACF,KAAKN,WAAWO;AACd,aAAA;IACF;AAEE,UAAIR,UAAU,OAAOA,SAAS,KAAK;AACjC,eAAA;MACF;AACA,aAAA;EACJ;AACF;AAtBgBD;;;ACdhB,SAASU,cAAAA,mBAAkB;AA8BpB,SAASC,mBAAmBC,QAAc;AAE/C,QAAMC,UAAUC,OAAOC,QAAQC,WAAAA,EAAYC,KAAK,CAAC,CAACC,KAAKC,KAAAA,MAAWA,UAAUP,UAAUQ,OAAOC,MAAMD,OAAOF,GAAAA,CAAAA,CAAAA,IAAS,CAAA;AAEnH,MAAI,CAACL,SAAS;AACZ,WAAO;EACT;AAGA,SAAOA,QACJS,MAAM,GAAA,EACNC,IAAI,CAACC,SAASA,KAAKC,OAAO,CAAA,EAAGC,YAAW,IAAKF,KAAKG,MAAM,CAAA,EAAGC,YAAW,CAAA,EACtEC,KAAK,GAAA;AACV;AAbgBlB;AAgBhB,SAASmB,6BACPC,SAAkF;AAElF,SAAOA,QACJR,IAAI,CAACS,QAAAA;AACJ,QAAI,OAAOA,QAAQ,YAAY,cAAcA,OAAO,iBAAiBA,KAAK;AACxE,YAAMC,mBAAmBnB,OAAOoB,OAAOF,IAAIG,WAAW;AACtD,aAAO;QACLC,OAAOJ,IAAIK;QACXN,SAASE,iBAAiB,CAAA,KAAM;MAClC;IACF;AAEA,WAAO;EACT,CAAA,EACCK,OAAO,CAACC,UAA+BA,UAAU,IAAA;AACtD;AAhBST;AAmBF,SAASU,2BACdC,mBACAC,uBAA6B;AAE7B,MAAIC,OAAO;AACX,MAAIC;AACJ,MAAIC;AACJ,MAAIC,SAAuB,CAAA;AAE3B,MAAI,OAAOL,sBAAsB,UAAU;AACzCI,aAASJ;AACT,WAAO;MAAEE;MAAMC;MAAOC;MAAQC;IAAO;EACvC;AAEA,MAAIL,sBAAsB,QAAQ,OAAOA,sBAAsB,UAAU;AACvE,UAAMM,cAAcN;AAGpB,QAAI,UAAUM,eAAe,WAAWA,eAAe,YAAYA,aAAa;AAC9E,YAAMC,kBAAkBD;AACxBJ,aAAOK,gBAAgBL,QAAQ;AAC/BC,cAAQI,gBAAgBJ;AACxBC,eAASG,gBAAgBH,UAAUH;AACnCI,eAASE,gBAAgBF,UAAU,CAAA;IACrC,WAES,aAAaC,eAAeE,MAAMC,QAAQH,YAAYhB,OAAO,GAAG;AACvEe,eAAShB,6BAA6BiB,YAAYhB,OAAO;AACzDc,eAAS;IACX,WAES,aAAaE,aAAa;AACjC,YAAMhB,UAAWgB,YAA0ChB;AAC3Dc,eAASI,MAAMC,QAAQnB,OAAAA,IAAWA,QAAQF,KAAK,IAAA,IAAQE;IACzD;EACF;AAEA,SAAO;IAAEY;IAAMC;IAAOC;IAAQC;EAAO;AACvC;AAtCgBN;;;AC3BhB,SAASW,oBAAoBC,OAAc;AACzC,SACEA,iBAAiBC,SACjB,OAAQD,MAAkCE,cAAc,cACxD,OAAQF,MAAoCG,gBAAgB;AAEhE;AANSJ;AAeT,SAASK,cAAcJ,OAAc;AACnC,MAAIA,SAAS,QAAQ,OAAOA,UAAU,UAAU;AAC9C,WAAO;EACT;AACA,QAAMK,IAAIL;AACV,SAAO,OAAOK,EAAEC,WAAW,YAAY,OAAOD,EAAEE,eAAe;AACjE;AANSH;AAeT,SAASI,kBAAkBR,OAAoC;AAC7D,MAAIS,UAAmBT;AAEvB,WAASU,QAAQ,GAAGD,WAAWC,QAAQ,IAAIA,SAAS;AAClD,QAAIX,oBAAoBU,OAAAA,GAAU;AAChC,YAAMH,SAASG,QAAQP,UAAS;AAChC,aAAO;QAAEI;QAAQK,UAAUF,QAAQN,YAAW;QAAIS,UAAUH,QAAQI,WAAWC,mBAAmBR,MAAAA;MAAQ;IAC5G;AACA,QAAIF,cAAcK,OAAAA,GAAU;AAC1B,YAAMH,SAASG,QAAQH,UAAUG,QAAQF,cAAc;AACvD,aAAO;QAAED;QAAQK,UAAUF;QAASG,UAAUH,QAAQM,UAAUN,QAAQI,WAAWC,mBAAmBR,MAAAA;MAAQ;IAChH;AACA,UAAMU,OAAOP;AACbA,cAAUO,KAAKC,iBAAiBD,KAAKE;EACvC;AACA,SAAOC;AACT;AAhBSX;AAkBT,IAAMY,2BAA2B;AAG1B,SAASC,yBACdC,MAA+B;AAE/B,QAAM,EAAEC,cAAcC,WAAU,IAAKF;AAErC,SAAO,CAACG,gBAAgBzB,UAAAA;AACtB,UAAM0B,WAAY1B,SAASmB;AAC3B,UAAMQ,SAASnB,kBAAkBkB,QAAAA;AAGjC,QAAIpB,SAAS;AACb,QAAIS;AACJ,QAAIa;AACJ,QAAIC,cAAyD,CAAA;AAE7D,QAAIF,QAAQ;AACVrB,eAASqB,OAAOrB;AAChB,YAAMwB,YAAYC,2BAA2BJ,OAAOhB,UAAUgB,OAAOf,QAAQ;AAC7EG,eAASe,UAAUf;AACnBa,cAAQE,UAAUF;AAClBC,oBAAcC,UAAUE;IAC1B;AAEA,UAAMC,OAAOC,oBAAoB5B,MAAAA;AAGjC,QAAIO,UAAUE,UAAUU,eAAeZ;AACvC,QAAIoB,SAAS,cAAcV,cAAc;AACvCV,gBAAUO;IACZ;AAGA,UAAMe,WAAoC;MAAE,GAAIV,eAAeW,cAAc,CAAC;IAAG;AAEjF,UAAMC,UAAUb,aAAAA;AAChB,UAAMc,aAAY,oBAAIC,KAAAA,GAAOC,YAAW;AAExC,UAAMJ,aAAuC;MAC3C,GAAGD;;MAEHF;MACA,GAAII,YAAYlB,SAAY;QAAEkB;MAAQ,IAAI,CAAC;MAC3CC;MACA,GAAIV,UAAUT,SAAY;QAAES;MAAM,IAAI,CAAC;MACvC,GAAIC,YAAYY,SAAS,IAAI;QAAEZ;MAAY,IAAI,CAAC;IAClD;AAEA,QAAIN,cAAc;AAEhB,aAAOa,WAAWM;AAClB,aAAON,WAAWO;AAClB,aAAOP,WAAWnB;IACpB;AAEA,UAAM2B,SAAqC;MACzC/B;MACAuB;IACF;AAEA,QAAIX,eAAeoB,UAAWD,QAAOC,YAAYpB,eAAeoB;AAChE,QAAIpB,eAAeqB,KAAMF,QAAOE,OAAOrB,eAAeqB;AAEtD,WAAOF;EACT;AACF;AAhEgBvB;;;ACzFhB,SAEE0B,OAGAC,cAAAA,aACAC,cACK;;;ACPP,SAASC,cAAAA,mBAAkB;;;ACA3B,SAASC,qBAAiC;AAanC,IAAeC,uBAAf,cAA4CC,cAAAA;EAbnD,OAamDA;;;EACjD,YAAYC,iBAA0CC,YAAwB;AAC5E,UAAMC,UAAU,OAAOF,oBAAoB,WAAW;MAAEG,QAAQH;IAAgB,IAAIA;AAEpF,UACE;MACEI,MAAMF,QAAQE,QAAQ;MACtBC,OAAOH,QAAQG;MACfF,QAAQD,QAAQC;MAChBG,QAAQJ,QAAQI,UAAU,CAAA;IAC5B,GACAL,UAAAA;EAEJ;AACF;;;ADxBO,IAAMM,oBAAN,cAAgCC,qBAAAA;EAHvC,OAGuCA;;;EACrC,YAAYC,iBAA2C;AACrD,UAAMA,mBAAmB,YAAYC,YAAWC,QAAQ;EAC1D;AACF;;;AELA,IAAMC,sBAAsB;AAcrB,SAASC,oBAAoBC,OAAc;AAChD,QAAMC,UAAUC,YAAYF,KAAAA;AAC5B,MAAI,CAACC,QAAS,QAAOE;AACrB,QAAM,EAAEC,MAAMC,YAAYC,OAAOC,OAAM,IAAKN;AAC5C,MAAIG,SAASN,oBAAqB,QAAOK;AACzC,SAAO,IAAIK,kBAAkB;IAC3BC,OAAO;IACPF,QAAQA,QAAQG,KAAAA,KAAU;IAC1BC,QAAQ,CAAA;IACR,GAAIN,cAAcC,QAAQ;MAAEM,MAAM;QAAEP;QAAYC;MAAM;IAAE,IAAI,CAAC;EAC/D,CAAA;AACF;AAXgBP;AAcT,SAASG,YAAYF,OAAgBa,QAAQ,GAAC;AACnD,MAAI,CAACb,SAAS,OAAOA,UAAU,YAAYa,QAAQ,EAAG,QAAOV;AAC7D,QAAMW,YAAYd;AAClB,MAAI,OAAOc,UAAUV,SAAS,SAAU,QAAOU;AAC/C,SAAOZ,YAAYY,UAAUC,OAAOF,QAAQ,CAAA;AAC9C;AALgBX;A;;;;;;;;;;;;;;;;AHdT,IAAMc,sBAAN,MAAMA,qBAAAA;SAAAA;;;EACMC,SAAS,IAAIC,OAAOF,qBAAoBG,IAAI;EAE7DC,MAAMC,WAAoBC,MAAqB;AAC7C,UAAMC,MAAMD,KAAKE,aAAY;AAC7B,UAAMC,WAAWF,IAAIG,YAAW;AAChC,UAAMC,UAAUJ,IAAIK,WAAU;AAG9B,UAAMC,oBAAoBC,oBAAoBT,SAAAA;AAC9C,QAAIQ,kBAAmBR,aAAYQ;AAEnC,QAAIE,SAASC,YAAWC;AACxB,QAAIC,OAAO;AACX,QAAIC;AACJ,QAAIC,SAAS;AACb,QAAIC,SAAuB,CAAA;AAE3B,QAAI,KAAKC,gBAAgBjB,SAAAA,GAAY;AACnCU,eAASV,UAAUkB,UAAS;AAC5B,YAAMC,oBAAoBnB,UAAUK,YAAW;AAG/C,YAAMe,YAAYC,2BAA2BF,mBAAmBnB,UAAUsB,WAAWC,mBAAmBb,MAAAA,CAAAA;AACxGG,aAAOO,UAAUP;AACjBC,cAAQM,UAAUN;AAElBC,eAASK,UAAUL,UAAUA;AAC7BC,eAASI,UAAUJ;IACrB,WAAW,KAAKQ,oBAAoBxB,SAAAA,GAAY;AAC9C,YAAMyB,aAAazB;AACnB,YAAM0B,kBAAkBD,WAAWf,UAAUe,WAAWE;AACxD,UAAI,OAAOD,oBAAoB,YAAYA,mBAAmB,OAAOA,mBAAmB,KAAK;AAC3FhB,iBAASgB;MACX;AACAb,aAAO,OAAOY,WAAWZ,SAAS,WAAWY,WAAWZ,OAAO;AAC/DC,cAAQ,OAAOW,WAAWX,UAAU,WAAWW,WAAWX,QAAQc;AAClEb,eACE,OAAOU,WAAWV,WAAW,WACzBU,WAAWV,SACX,OAAOU,WAAWH,YAAY,WAC5BG,WAAWH,UACXC,mBAAmBb,MAAAA;AAC3BM,eAASa,MAAMC,QAAQL,WAAWT,MAAM,IAAKS,WAAWT,SAA0B,CAAA;IACpF,WAAW,KAAKe,aAAa/B,SAAAA,GAAY;AAEvC,YAAMgC,cAAchC,UAAUI,UAAUM;AACxC,YAAMuB,cAAcjC,UAAUI,UAAU8B,MAAMZ,WAAWtB,UAAUI,UAAU8B,MAAMnB,UAAUf,UAAUsB;AACvG,YAAMa,MAAMnC,UAAUoC,QAAQD;AAC9BzB,eAASC,YAAW0B;AACpBtB,eAAS,yBAAyBiB,cAAc,KAAKA,WAAAA,MAAiB,EAAA,KAAOC,WAAAA;AAC7E,WAAKrC,OAAO0C,MAAM,uBAAuBN,WAAAA,MAAiBC,WAAAA,gBAAsBE,GAAAA,IAAOnC,UAAUuC,KAAK;IACxG,OAAO;AAELxB,eAAS;IACX;AAEA,UAAMyB,iBAAmC;MACvC3B;MACA4B,OAAOlB,mBAAmBb,MAAAA;MAC1BA;MACA,GAAII,SAAS;QAAEA;MAAM;MACrBC;MACA2B,UAAUpC,QAAQ6B;MAClBnB;IACF;AAEAZ,aAASuC,OAAO,gBAAgB,0BAAA,EAA4BjC,OAAOA,MAAAA,EAAQkC,KAAKJ,cAAAA;EAClF;;EAGQvB,gBAAgBqB,OAAwC;AAC9D,WACEA,iBAAiBO,SACjB,OAAQP,MAAkCpB,cAAc,cACxD,OAAQoB,MAAoCjC,gBAAgB;EAEhE;;EAGQ0B,aAAaO,OAInB;AACA,WAAOA,iBAAiBO,SAAUP,MAAqCP,iBAAiB;EAC1F;EAEQP,oBAAoBc,OAAkD;AAC5E,QAAI,CAACA,SAAS,OAAOA,UAAU,SAAU,QAAO;AAChD,UAAMQ,MAAMR;AACZ,WACE,OAAOQ,IAAIpC,WAAW,YACtB,OAAOoC,IAAInB,eAAe,YAC1B,OAAOmB,IAAI/B,WAAW,YACtBc,MAAMC,QAAQgB,IAAI9B,MAAM;EAE5B;AACF;;;;;;AIlHA,SAA6B+B,SAAAA,cAAmC;;;;;;;;;;;;;;;AAIzD,IAAMC,gCAAN,MAAMA;SAAAA;;;EACMC,aAAa,IAAIC,oBAAAA;EAElCC,MAAMC,WAAoBC,MAA2B;AACnD,QAAIA,KAAKC,QAAO,MAAO,QAAQ;AAC7B,YAAMF;IACR;AACA,SAAKH,WAAWE,MAAMC,WAAWC,IAAAA;EACnC;AACF;;;;","names":["HttpStatus","ErrorCode","errorCodeFromStatus","status","HttpStatus","UNAUTHORIZED","FORBIDDEN","NOT_FOUND","BAD_REQUEST","UNPROCESSABLE_ENTITY","CONFLICT","TOO_MANY_REQUESTS","HttpStatus","getHttpStatusTitle","status","enumKey","Object","entries","HttpStatus","find","key","value","Number","isNaN","split","map","word","charAt","toUpperCase","slice","toLowerCase","join","extractValidationFieldErrors","message","msg","constraintValues","values","constraints","field","property","filter","error","extractProblemFromResponse","exceptionResponse","problemFallbackDetail","type","label","detail","errors","responseObj","problemResponse","Array","isArray","isHttpExceptionLike","error","Error","getStatus","getResponse","isProblemLike","o","status","statusCode","findProblemSource","current","depth","response","fallback","message","getHttpStatusTitle","detail","next","originalError","thrownValue","undefined","GENERIC_INTERNAL_MESSAGE","createGraphqlFormatError","opts","isProduction","getTraceId","formattedError","gqlError","source","label","fieldErrors","extracted","extractProblemFromResponse","errors","code","errorCodeFromStatus","incoming","extensions","traceId","timestamp","Date","toISOString","length","stacktrace","exception","result","locations","path","Catch","HttpStatus","Logger","HttpStatus","HttpException","HttpProblemException","HttpException","detailOrOptions","httpStatus","options","detail","type","label","errors","ConflictException","HttpProblemException","detailOrOptions","HttpStatus","CONFLICT","PG_UNIQUE_VIOLATION","tryTranslatePgError","error","pgError","findPgError","undefined","code","constraint","table","detail","ConflictException","label","trim","errors","meta","depth","candidate","cause","HttpExceptionFilter","logger","Logger","name","catch","exception","host","ctx","switchToHttp","response","getResponse","request","getRequest","translatedPgError","tryTranslatePgError","status","HttpStatus","INTERNAL_SERVER_ERROR","type","label","detail","errors","isHttpException","getStatus","exceptionResponse","extracted","extractProblemFromResponse","message","getHttpStatusTitle","isProblemLikeObject","problemObj","statusCandidate","statusCode","undefined","Array","isArray","isAxiosError","axiosStatus","axiosDetail","data","url","config","BAD_GATEWAY","error","stack","problemDetails","title","instance","header","send","Error","obj","Catch","TransportAwareExceptionFilter","httpFilter","HttpExceptionFilter","catch","exception","host","getType"]}
package/dist/index.d.cts CHANGED
@@ -149,4 +149,4 @@ declare module 'fastify' {
149
149
  }
150
150
  }
151
151
 
152
- export { type AuthConfig as A, type CookieConfig as C, type DecodedAccessToken as D, type GuardConfig as G, type OnAuthenticatedCallback as O, RequestService as R, type TokenExpiry as T, TokenType as a, type DecodedRefreshToken as b, type AccessTokenPayload as c, AUTH_CONFIG as d, AUTH_CONFIG_DEFAULTS as e, type CookieSerializeOptions as f, type RefreshTokenPayload as g, type TokenExpiryString as h };
152
+ export { type AuthConfig as A, type CookieConfig as C, type DecodedAccessToken as D, type GuardConfig as G, type OnAuthenticatedCallback as O, RequestService as R, type TokenExpiry as T, TokenType as a, type DecodedRefreshToken as b, AUTH_CONFIG as c, AUTH_CONFIG_DEFAULTS as d, type AccessTokenPayload as e, type CookieSerializeOptions as f, type RefreshTokenPayload as g, type TokenExpiryString as h };
package/dist/index.d.ts CHANGED
@@ -149,4 +149,4 @@ declare module 'fastify' {
149
149
  }
150
150
  }
151
151
 
152
- export { type AuthConfig as A, type CookieConfig as C, type DecodedAccessToken as D, type GuardConfig as G, type OnAuthenticatedCallback as O, RequestService as R, type TokenExpiry as T, TokenType as a, type DecodedRefreshToken as b, type AccessTokenPayload as c, AUTH_CONFIG as d, AUTH_CONFIG_DEFAULTS as e, type CookieSerializeOptions as f, type RefreshTokenPayload as g, type TokenExpiryString as h };
152
+ export { type AuthConfig as A, type CookieConfig as C, type DecodedAccessToken as D, type GuardConfig as G, type OnAuthenticatedCallback as O, RequestService as R, type TokenExpiry as T, TokenType as a, type DecodedRefreshToken as b, AUTH_CONFIG as c, AUTH_CONFIG_DEFAULTS as d, type AccessTokenPayload as e, type CookieSerializeOptions as f, type RefreshTokenPayload as g, type TokenExpiryString as h };
@@ -1,4 +1,4 @@
1
- import { V as VersionSnapshot } from './types-BQY0Aa1p.cjs';
1
+ import { V as VersionSnapshot } from './types-VDKSjje5.cjs';
2
2
  export { S as SignedDocument } from './document-BoS0NIbf.cjs';
3
3
 
4
4
  declare function hashSnapshot(value: unknown): string;
package/dist/license.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { V as VersionSnapshot } from './types-BQY0Aa1p.js';
1
+ import { V as VersionSnapshot } from './types-VDKSjje5.js';
2
2
  export { S as SignedDocument } from './document-BoS0NIbf.js';
3
3
 
4
4
  declare function hashSnapshot(value: unknown): string;
package/dist/logger.cjs CHANGED
@@ -106,13 +106,22 @@ __name(addCorrelationIdToResponse, "addCorrelationIdToResponse");
106
106
  // src/logger/services/logger.service.ts
107
107
  function _ts_decorate(decorators, target, key, desc) {
108
108
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
109
- if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
110
- else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
109
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") {
110
+ r = Reflect.decorate(decorators, target, key, desc);
111
+ } else {
112
+ for (var i = decorators.length - 1; i >= 0; i--) {
113
+ if (d = decorators[i]) {
114
+ r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
115
+ }
116
+ }
117
+ }
111
118
  return c > 3 && r && Object.defineProperty(target, key, r), r;
112
119
  }
113
120
  __name(_ts_decorate, "_ts_decorate");
114
- function _ts_metadata(k, v) {
115
- if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
121
+ function _ts_metadata(metadataKey, metadataValue) {
122
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") {
123
+ return Reflect.metadata(metadataKey, metadataValue);
124
+ }
116
125
  }
117
126
  __name(_ts_metadata, "_ts_metadata");
118
127
  function _ts_param(paramIndex, decorator) {
@@ -326,13 +335,22 @@ LoggerService = _ts_decorate([
326
335
  // src/logger/interceptors/http-logger.interceptor.ts
327
336
  function _ts_decorate2(decorators, target, key, desc) {
328
337
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
329
- if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
330
- else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
338
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") {
339
+ r = Reflect.decorate(decorators, target, key, desc);
340
+ } else {
341
+ for (var i = decorators.length - 1; i >= 0; i--) {
342
+ if (d = decorators[i]) {
343
+ r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
344
+ }
345
+ }
346
+ }
331
347
  return c > 3 && r && Object.defineProperty(target, key, r), r;
332
348
  }
333
349
  __name(_ts_decorate2, "_ts_decorate");
334
- function _ts_metadata2(k, v) {
335
- if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
350
+ function _ts_metadata2(metadataKey, metadataValue) {
351
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") {
352
+ return Reflect.metadata(metadataKey, metadataValue);
353
+ }
336
354
  }
337
355
  __name(_ts_metadata2, "_ts_metadata");
338
356
  function _ts_param2(paramIndex, decorator) {
@@ -468,13 +486,22 @@ var import_common6 = require("@nestjs/common");
468
486
  var import_common5 = require("@nestjs/common");
469
487
  function _ts_decorate3(decorators, target, key, desc) {
470
488
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
471
- if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
472
- else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
489
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") {
490
+ r = Reflect.decorate(decorators, target, key, desc);
491
+ } else {
492
+ for (var i = decorators.length - 1; i >= 0; i--) {
493
+ if (d = decorators[i]) {
494
+ r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
495
+ }
496
+ }
497
+ }
473
498
  return c > 3 && r && Object.defineProperty(target, key, r), r;
474
499
  }
475
500
  __name(_ts_decorate3, "_ts_decorate");
476
- function _ts_metadata3(k, v) {
477
- if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
501
+ function _ts_metadata3(metadataKey, metadataValue) {
502
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") {
503
+ return Reflect.metadata(metadataKey, metadataValue);
504
+ }
478
505
  }
479
506
  __name(_ts_metadata3, "_ts_metadata");
480
507
  var CorrelationIdMiddleware = class {
@@ -524,12 +551,19 @@ CorrelationIdMiddleware = _ts_decorate3([
524
551
  // src/logger/logger.module.ts
525
552
  function _ts_decorate4(decorators, target, key, desc) {
526
553
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
527
- if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
528
- else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
554
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") {
555
+ r = Reflect.decorate(decorators, target, key, desc);
556
+ } else {
557
+ for (var i = decorators.length - 1; i >= 0; i--) {
558
+ if (d = decorators[i]) {
559
+ r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
560
+ }
561
+ }
562
+ }
529
563
  return c > 3 && r && Object.defineProperty(target, key, r), r;
530
564
  }
531
565
  __name(_ts_decorate4, "_ts_decorate");
532
- var LOGGER_MODULE_OPTIONS = Symbol("LOGGER_MODULE_OPTIONS");
566
+ var LOGGER_MODULE_OPTIONS = /* @__PURE__ */ Symbol("LOGGER_MODULE_OPTIONS");
533
567
  var DEFAULT_LOGGER_OPTIONS = {
534
568
  provider: "winston",
535
569
  enableCorrelationId: true,