@cosmneo/onion-lasagna 0.1.0

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 (97) hide show
  1. package/dist/backend/core/global.cjs +283 -0
  2. package/dist/backend/core/global.cjs.map +1 -0
  3. package/dist/backend/core/global.d.cts +294 -0
  4. package/dist/backend/core/global.d.ts +294 -0
  5. package/dist/backend/core/global.js +39 -0
  6. package/dist/backend/core/global.js.map +1 -0
  7. package/dist/backend/core/onion-layers.cjs +2302 -0
  8. package/dist/backend/core/onion-layers.cjs.map +1 -0
  9. package/dist/backend/core/onion-layers.d.cts +1675 -0
  10. package/dist/backend/core/onion-layers.d.ts +1675 -0
  11. package/dist/backend/core/onion-layers.js +1158 -0
  12. package/dist/backend/core/onion-layers.js.map +1 -0
  13. package/dist/backend/core/presentation.cjs +573 -0
  14. package/dist/backend/core/presentation.cjs.map +1 -0
  15. package/dist/backend/core/presentation.d.cts +5 -0
  16. package/dist/backend/core/presentation.d.ts +5 -0
  17. package/dist/backend/core/presentation.js +28 -0
  18. package/dist/backend/core/presentation.js.map +1 -0
  19. package/dist/backend/core/validators/arktype.cjs +947 -0
  20. package/dist/backend/core/validators/arktype.cjs.map +1 -0
  21. package/dist/backend/core/validators/arktype.d.cts +188 -0
  22. package/dist/backend/core/validators/arktype.d.ts +188 -0
  23. package/dist/backend/core/validators/arktype.js +287 -0
  24. package/dist/backend/core/validators/arktype.js.map +1 -0
  25. package/dist/backend/core/validators/typebox.cjs +939 -0
  26. package/dist/backend/core/validators/typebox.cjs.map +1 -0
  27. package/dist/backend/core/validators/typebox.d.cts +189 -0
  28. package/dist/backend/core/validators/typebox.d.ts +189 -0
  29. package/dist/backend/core/validators/typebox.js +281 -0
  30. package/dist/backend/core/validators/typebox.js.map +1 -0
  31. package/dist/backend/core/validators/valibot.cjs +942 -0
  32. package/dist/backend/core/validators/valibot.cjs.map +1 -0
  33. package/dist/backend/core/validators/valibot.d.cts +160 -0
  34. package/dist/backend/core/validators/valibot.d.ts +160 -0
  35. package/dist/backend/core/validators/valibot.js +294 -0
  36. package/dist/backend/core/validators/valibot.js.map +1 -0
  37. package/dist/backend/core/validators/zod.cjs +934 -0
  38. package/dist/backend/core/validators/zod.cjs.map +1 -0
  39. package/dist/backend/core/validators/zod.d.cts +188 -0
  40. package/dist/backend/core/validators/zod.d.ts +188 -0
  41. package/dist/backend/core/validators/zod.js +278 -0
  42. package/dist/backend/core/validators/zod.js.map +1 -0
  43. package/dist/backend/frameworks/elysia.cjs +715 -0
  44. package/dist/backend/frameworks/elysia.cjs.map +1 -0
  45. package/dist/backend/frameworks/elysia.d.cts +208 -0
  46. package/dist/backend/frameworks/elysia.d.ts +208 -0
  47. package/dist/backend/frameworks/elysia.js +251 -0
  48. package/dist/backend/frameworks/elysia.js.map +1 -0
  49. package/dist/backend/frameworks/fastify.cjs +677 -0
  50. package/dist/backend/frameworks/fastify.cjs.map +1 -0
  51. package/dist/backend/frameworks/fastify.d.cts +201 -0
  52. package/dist/backend/frameworks/fastify.d.ts +201 -0
  53. package/dist/backend/frameworks/fastify.js +213 -0
  54. package/dist/backend/frameworks/fastify.js.map +1 -0
  55. package/dist/backend/frameworks/hono.cjs +715 -0
  56. package/dist/backend/frameworks/hono.cjs.map +1 -0
  57. package/dist/backend/frameworks/hono.d.cts +163 -0
  58. package/dist/backend/frameworks/hono.d.ts +163 -0
  59. package/dist/backend/frameworks/hono.js +249 -0
  60. package/dist/backend/frameworks/hono.js.map +1 -0
  61. package/dist/backend/frameworks/nestjs.cjs +260 -0
  62. package/dist/backend/frameworks/nestjs.cjs.map +1 -0
  63. package/dist/backend/frameworks/nestjs.d.cts +168 -0
  64. package/dist/backend/frameworks/nestjs.d.ts +168 -0
  65. package/dist/backend/frameworks/nestjs.js +193 -0
  66. package/dist/backend/frameworks/nestjs.js.map +1 -0
  67. package/dist/base-dto.class-D7W9iqoU.d.cts +146 -0
  68. package/dist/base-dto.class-D7W9iqoU.d.ts +146 -0
  69. package/dist/base-uuid-v7.vo-BPGEIWLM.d.ts +799 -0
  70. package/dist/base-uuid-v7.vo-BjqKX44G.d.cts +799 -0
  71. package/dist/chunk-74IKUOSE.js +116 -0
  72. package/dist/chunk-74IKUOSE.js.map +1 -0
  73. package/dist/chunk-BKZOLGQW.js +29 -0
  74. package/dist/chunk-BKZOLGQW.js.map +1 -0
  75. package/dist/chunk-CGZBV6BD.js +54 -0
  76. package/dist/chunk-CGZBV6BD.js.map +1 -0
  77. package/dist/chunk-DDAHJZVK.js +258 -0
  78. package/dist/chunk-DDAHJZVK.js.map +1 -0
  79. package/dist/chunk-MQD5GXMT.js +171 -0
  80. package/dist/chunk-MQD5GXMT.js.map +1 -0
  81. package/dist/chunk-OKFXZHBC.js +43 -0
  82. package/dist/chunk-OKFXZHBC.js.map +1 -0
  83. package/dist/chunk-RLLWYFPI.js +168 -0
  84. package/dist/chunk-RLLWYFPI.js.map +1 -0
  85. package/dist/chunk-VCHFXT5W.js +425 -0
  86. package/dist/chunk-VCHFXT5W.js.map +1 -0
  87. package/dist/chunk-ZWLYNGO3.js +40 -0
  88. package/dist/chunk-ZWLYNGO3.js.map +1 -0
  89. package/dist/http-response-BAhi8lF4.d.cts +124 -0
  90. package/dist/http-response-BAhi8lF4.d.ts +124 -0
  91. package/dist/index-DingXh7B.d.cts +1187 -0
  92. package/dist/index-tOH7XBa3.d.ts +1187 -0
  93. package/dist/routing.type-DB4pt-d9.d.ts +184 -0
  94. package/dist/routing.type-DF2BIL7x.d.cts +184 -0
  95. package/dist/validation-error.type-kD4_qNZ9.d.cts +199 -0
  96. package/dist/validation-error.type-kD4_qNZ9.d.ts +199 -0
  97. package/package.json +191 -0
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/backend/core/onion-layers/presentation/index.ts","../../../src/backend/core/global/exceptions/coded-error.error.ts","../../../src/backend/core/global/exceptions/error-codes.const.ts","../../../src/backend/core/global/exceptions/object-validation.error.ts","../../../src/backend/core/global/utils/wrap-error.util.ts","../../../src/backend/core/onion-layers/presentation/exceptions/controller.error.ts","../../../src/backend/core/onion-layers/presentation/exceptions/invalid-request.error.ts","../../../src/backend/core/onion-layers/presentation/classes/base-controller.class.ts","../../../src/backend/core/onion-layers/presentation/exceptions/access-denied.error.ts","../../../src/backend/core/onion-layers/presentation/classes/guarded-controller.class.ts","../../../src/backend/core/onion-layers/presentation/interfaces/types/metadata/system-metadata.type.ts","../../../src/backend/core/onion-layers/presentation/routing/compute-route-path.util.ts","../../../src/backend/core/onion-layers/presentation/utils/http-response.util.ts"],"sourcesContent":["export * from './classes';\nexport * from './exceptions';\nexport * from './interfaces';\nexport * from './routing';\nexport * from './utils';\n","import type { ErrorCode } from './error-codes.const';\n\n/**\n * Base error class for all application errors with a machine-readable code.\n *\n * Abstract class that extends the native `Error` with:\n * - A `code` property for programmatic error handling\n * - Optional `cause` for error chaining (ES2022 compatible)\n * - A `fromError` static factory pattern for error transformation\n *\n * **Why abstract:** Prevents non-declarative error usage. All errors must\n * be explicitly defined as subclasses to ensure consistent error taxonomy.\n *\n * @example Subclass implementation\n * ```typescript\n * class DbError extends InfraError {\n * static override fromError(cause: unknown): DbError {\n * return new DbError({\n * message: cause instanceof Error ? cause.message : 'Database error',\n * cause,\n * });\n * }\n * }\n * ```\n *\n * @example Usage with wrapErrorAsync\n * ```typescript\n * await wrapErrorAsync(\n * () => this.db.query(...),\n * DbError.fromError,\n * );\n * ```\n */\nexport abstract class CodedError extends Error {\n /** Machine-readable error code for programmatic handling. */\n public readonly code: ErrorCode | string;\n\n /**\n * Creates a new CodedError instance.\n *\n * @param options - Error configuration\n * @param options.message - Human-readable error message\n * @param options.code - Machine-readable error code from ErrorCodes registry or custom string\n * @param options.cause - Optional underlying error that caused this error\n */\n constructor({\n message,\n code,\n cause,\n }: {\n message: string;\n code: ErrorCode | string;\n cause?: unknown;\n }) {\n super(message);\n this.name = this.constructor.name;\n this.code = code;\n if (cause !== undefined) {\n Object.defineProperty(this, 'cause', {\n value: cause,\n writable: false,\n enumerable: false,\n configurable: true,\n });\n }\n }\n\n /**\n * Factory method to create a typed error from a caught error.\n *\n * Subclasses should override this to provide proper error transformation.\n * Designed for use with {@link wrapErrorAsync} and {@link wrapError}.\n *\n * @param _cause - The original caught error\n * @returns A new CodedError instance\n * @throws {Error} If not overridden by subclass\n *\n * @example\n * ```typescript\n * class NotFoundError extends UseCaseError {\n * static override fromError(cause: unknown): NotFoundError {\n * return new NotFoundError({\n * message: 'Resource not found',\n * cause,\n * });\n * }\n * }\n * ```\n */\n static fromError(_cause: unknown): CodedError {\n throw new Error(`${this.name}.fromError() must be implemented by subclass`);\n }\n}\n","/**\n * Centralized registry of all error codes used across the application.\n *\n * Error codes are grouped by architectural layer to maintain clear boundaries\n * and make it easy to identify where an error originated.\n *\n * @example Using error codes in custom errors\n * ```typescript\n * import { ErrorCodes } from '@cosmneo/onion-lasagna/backend/core/global';\n *\n * throw new NotFoundError({\n * message: 'User not found',\n * code: ErrorCodes.App.NOT_FOUND,\n * });\n * ```\n *\n * @example Checking error codes programmatically\n * ```typescript\n * if (error.code === ErrorCodes.App.NOT_FOUND) {\n * // Handle not found case\n * }\n * ```\n */\nexport const ErrorCodes = {\n /**\n * Domain layer error codes.\n * Used for business rule violations and invariant failures.\n */\n Domain: {\n /** Generic domain error */\n DOMAIN_ERROR: 'DOMAIN_ERROR',\n /** Business invariant was violated */\n INVARIANT_VIOLATION: 'INVARIANT_VIOLATION',\n /** Aggregate was partially loaded (missing required relations) */\n PARTIAL_LOAD: 'PARTIAL_LOAD',\n },\n\n /**\n * Application layer (use case) error codes.\n * Used for orchestration failures and business operation errors.\n */\n App: {\n /** Generic use case error */\n USE_CASE_ERROR: 'USE_CASE_ERROR',\n /** Requested resource was not found */\n NOT_FOUND: 'NOT_FOUND',\n /** Resource state conflict (e.g., duplicate, already exists) */\n CONFLICT: 'CONFLICT',\n /** Request is valid but cannot be processed due to business rules */\n UNPROCESSABLE: 'UNPROCESSABLE',\n },\n\n /**\n * Infrastructure layer error codes.\n * Used for data access, external services, and I/O failures.\n */\n Infra: {\n /** Generic infrastructure error */\n INFRA_ERROR: 'INFRA_ERROR',\n /** Database operation failed */\n DB_ERROR: 'DB_ERROR',\n /** Network connectivity or communication error */\n NETWORK_ERROR: 'NETWORK_ERROR',\n /** Operation timed out */\n TIMEOUT_ERROR: 'TIMEOUT_ERROR',\n /** External/third-party service error */\n EXTERNAL_SERVICE_ERROR: 'EXTERNAL_SERVICE_ERROR',\n },\n\n /**\n * Presentation layer error codes.\n * Used for controller, request handling, and authorization errors.\n */\n Presentation: {\n /** Generic controller error */\n CONTROLLER_ERROR: 'CONTROLLER_ERROR',\n /** Request denied due to authorization failure */\n ACCESS_DENIED: 'ACCESS_DENIED',\n /** Request validation failed (malformed input) */\n INVALID_REQUEST: 'INVALID_REQUEST',\n },\n\n /**\n * Global/cross-cutting error codes.\n * Used for validation and other cross-layer concerns.\n */\n Global: {\n /** Object/schema validation failed */\n OBJECT_VALIDATION_ERROR: 'OBJECT_VALIDATION_ERROR',\n },\n} as const;\n\n/**\n * Type representing all possible domain error codes.\n */\nexport type DomainErrorCode = (typeof ErrorCodes.Domain)[keyof typeof ErrorCodes.Domain];\n\n/**\n * Type representing all possible application error codes.\n */\nexport type AppErrorCode = (typeof ErrorCodes.App)[keyof typeof ErrorCodes.App];\n\n/**\n * Type representing all possible infrastructure error codes.\n */\nexport type InfraErrorCode = (typeof ErrorCodes.Infra)[keyof typeof ErrorCodes.Infra];\n\n/**\n * Type representing all possible presentation error codes.\n */\nexport type PresentationErrorCode =\n (typeof ErrorCodes.Presentation)[keyof typeof ErrorCodes.Presentation];\n\n/**\n * Type representing all possible global error codes.\n */\nexport type GlobalErrorCode = (typeof ErrorCodes.Global)[keyof typeof ErrorCodes.Global];\n\n/**\n * Union type of all error codes across all layers.\n *\n * Use this when you need to accept any valid error code.\n *\n * @example\n * ```typescript\n * function logError(code: ErrorCode, message: string) {\n * console.error(`[${code}] ${message}`);\n * }\n * ```\n */\nexport type ErrorCode =\n | DomainErrorCode\n | AppErrorCode\n | InfraErrorCode\n | PresentationErrorCode\n | GlobalErrorCode;\n","import { CodedError } from './coded-error.error';\nimport { ErrorCodes, type GlobalErrorCode } from './error-codes.const';\nimport type { ValidationError } from '../interfaces/types/validation-error.type';\n\n/**\n * Error thrown when object validation fails.\n *\n * Contains structured validation errors with field paths and messages,\n * making it easy to report specific validation failures to clients.\n * Thrown by all validator implementations (Zod, ArkType, TypeBox, Valibot).\n *\n * **Flow:**\n * 1. Validator throws `ObjectValidationError` with field-level errors\n * 2. Controller catches and converts to {@link InvalidRequestError}\n * 3. HTTP layer maps to 400 Bad Request with error details\n *\n * @example\n * ```typescript\n * try {\n * const dto = CreateUserDto.create(invalidData);\n * } catch (error) {\n * if (error instanceof ObjectValidationError) {\n * console.log(error.validationErrors);\n * // [\n * // { field: 'email', message: 'Invalid email format' },\n * // { field: 'age', message: 'Must be a positive number' }\n * // ]\n * }\n * }\n * ```\n */\nexport class ObjectValidationError extends CodedError {\n /**\n * Array of field-level validation errors.\n *\n * Each entry contains:\n * - `field`: Dot-notation path to the invalid field (e.g., 'user.email')\n * - `message`: Human-readable validation failure message\n */\n validationErrors: ValidationError[];\n\n /**\n * Creates a new ObjectValidationError instance.\n *\n * @param options - Error configuration\n * @param options.message - Human-readable summary message\n * @param options.code - Machine-readable error code (default: 'OBJECT_VALIDATION_ERROR')\n * @param options.cause - Optional underlying error from validation library\n * @param options.validationErrors - Array of field-level validation errors\n */\n constructor({\n message,\n code = ErrorCodes.Global.OBJECT_VALIDATION_ERROR,\n cause,\n validationErrors,\n }: {\n message: string;\n code?: GlobalErrorCode | string;\n cause?: unknown;\n validationErrors: ValidationError[];\n }) {\n super({ message, code, cause });\n this.validationErrors = validationErrors;\n }\n\n /**\n * Creates an ObjectValidationError from a caught error.\n *\n * @param cause - The original caught error\n * @returns A new ObjectValidationError instance with the cause attached\n */\n static override fromError(cause: unknown): ObjectValidationError {\n return new ObjectValidationError({\n message: cause instanceof Error ? cause.message : 'Validation failed',\n cause,\n validationErrors: [],\n });\n }\n}\n","/**\n * Error wrapping utilities for boundary error handling.\n *\n * Provides functions to wrap code execution with error transformation,\n * converting caught errors into typed Error instances.\n * Useful at layer boundaries (infra, use case, controller) to normalize errors.\n *\n * @example Wrapping async database calls\n * ```typescript\n * const user = await wrapErrorAsync(\n * () => this.db.query('SELECT * FROM users WHERE id = ?', [id]),\n * (cause) => new DbError({ message: 'Failed to fetch user', cause }),\n * );\n * ```\n *\n * @example Wrapping sync operations\n * ```typescript\n * const parsed = wrapError(\n * () => JSON.parse(data),\n * (cause) => new InvariantViolationError({\n * message: 'Invalid JSON format',\n * cause,\n * }),\n * );\n * ```\n *\n * @module\n */\n\n/**\n * Factory function that creates an Error from a caught error.\n *\n * @typeParam E - The specific Error subclass to create\n * @param cause - The original caught error\n * @returns A new Error instance\n */\nexport type ErrorFactory<E extends Error> = (cause: unknown) => E;\n\n/**\n * Wraps a synchronous function with error transformation.\n *\n * Executes the provided function and catches any thrown errors,\n * transforming them using the error factory.\n *\n * @typeParam T - The return type of the wrapped function\n * @typeParam E - The Error subclass to throw on error\n * @param fn - The function to execute\n * @param errorFactory - Factory to create the typed error from the caught error\n * @returns The result of the function if successful\n * @throws {E} The transformed error if the function throws\n *\n * @example\n * ```typescript\n * const config = wrapError(\n * () => JSON.parse(configString),\n * (cause) => new InvariantViolationError({\n * message: 'Invalid configuration format',\n * code: 'CONFIG_PARSE_ERROR',\n * cause,\n * }),\n * );\n * ```\n */\nexport function wrapError<T, E extends Error>(fn: () => T, errorFactory: ErrorFactory<E>): T {\n try {\n return fn();\n } catch (error) {\n throw errorFactory(error);\n }\n}\n\n/**\n * Wraps an asynchronous function with error transformation.\n *\n * Executes the provided async function and catches any thrown errors,\n * transforming them using the error factory.\n *\n * @typeParam T - The return type of the wrapped function\n * @typeParam E - The Error subclass to throw on error\n * @param fn - The async function to execute\n * @param errorFactory - Factory to create the typed error from the caught error\n * @returns A promise resolving to the result if successful\n * @throws {E} The transformed error if the function throws\n *\n * @example Repository usage\n * ```typescript\n * async findById(id: string): Promise<User | null> {\n * return wrapErrorAsync(\n * () => this.db.users.findUnique({ where: { id } }),\n * (cause) => new DbError({\n * message: `Failed to find user by ID: ${id}`,\n * cause,\n * }),\n * );\n * }\n * ```\n *\n * @example External service usage\n * ```typescript\n * async sendEmail(to: string, body: string): Promise<void> {\n * await wrapErrorAsync(\n * () => this.emailClient.send({ to, body }),\n * (cause) => new ExternalServiceError({\n * message: 'Email delivery failed',\n * code: 'EMAIL_SEND_FAILED',\n * cause,\n * }),\n * );\n * }\n * ```\n */\nexport async function wrapErrorAsync<T, E extends Error>(\n fn: () => Promise<T>,\n errorFactory: ErrorFactory<E>,\n): Promise<T> {\n try {\n return await fn();\n } catch (error) {\n throw errorFactory(error);\n }\n}\n\n/**\n * Constructor type for error classes (including abstract classes).\n *\n * Used to specify error types that should pass through without transformation.\n */\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport type ErrorConstructor = abstract new (...args: any[]) => Error;\n\n/**\n * Wraps a synchronous function with conditional error transformation.\n *\n * Executes the provided function and catches any thrown errors.\n * Errors matching any of the passthrough types are re-thrown as-is.\n * All other errors are transformed using the error factory.\n *\n * @typeParam T - The return type of the wrapped function\n * @typeParam E - The Error subclass to throw for unknown errors\n * @param fn - The function to execute\n * @param errorFactory - Factory to create the typed error from unknown errors\n * @param passthroughTypes - Array of error classes to re-throw without transformation\n * @returns The result of the function if successful\n * @throws The original error if it matches a passthrough type\n * @throws {E} The transformed error for unknown error types\n *\n * @example Controller boundary\n * ```typescript\n * const result = wrapErrorUnless(\n * () => this.requestMapper(input),\n * (cause) => new ControllerError({ message: 'Mapping failed', cause }),\n * [CodedError],\n * );\n * ```\n */\nexport function wrapErrorUnless<T, E extends Error>(\n fn: () => T,\n errorFactory: ErrorFactory<E>,\n passthroughTypes: ErrorConstructor[],\n): T {\n try {\n return fn();\n } catch (error) {\n if (passthroughTypes.some((Type) => error instanceof Type)) {\n throw error;\n }\n throw errorFactory(error);\n }\n}\n\n/**\n * Wraps an asynchronous function with conditional error transformation.\n *\n * Executes the provided async function and catches any thrown errors.\n * Errors matching any of the passthrough types are re-thrown as-is.\n * All other errors are transformed using the error factory.\n *\n * @typeParam T - The return type of the wrapped function\n * @typeParam E - The Error subclass to throw for unknown errors\n * @param fn - The async function to execute\n * @param errorFactory - Factory to create the typed error from unknown errors\n * @param passthroughTypes - Array of error classes to re-throw without transformation\n * @returns A promise resolving to the result if successful\n * @throws The original error if it matches a passthrough type\n * @throws {E} The transformed error for unknown error types\n *\n * @example Use case boundary\n * ```typescript\n * return wrapErrorUnlessAsync(\n * () => this.handle(input),\n * (cause) => new UseCaseError({ message: 'Unexpected error', cause }),\n * [ObjectValidationError, UseCaseError, DomainError, InfraError],\n * );\n * ```\n *\n * @example Controller boundary\n * ```typescript\n * return wrapErrorUnlessAsync(\n * async () => {\n * const result = await this.useCase.execute(input);\n * return this.responseMapper(result);\n * },\n * (cause) => new ControllerError({ message: 'Controller failed', cause }),\n * [CodedError],\n * );\n * ```\n */\nexport async function wrapErrorUnlessAsync<T, E extends Error>(\n fn: () => Promise<T>,\n errorFactory: ErrorFactory<E>,\n passthroughTypes: ErrorConstructor[],\n): Promise<T> {\n try {\n return await fn();\n } catch (error) {\n if (passthroughTypes.some((Type) => error instanceof Type)) {\n throw error;\n }\n throw errorFactory(error);\n }\n}\n","import { CodedError } from '../../../global/exceptions/coded-error.error';\nimport {\n ErrorCodes,\n type PresentationErrorCode,\n} from '../../../global/exceptions/error-codes.const';\n\n/**\n * Base error class for presentation layer (controller) failures.\n *\n * Controller errors represent failures in request handling,\n * such as access control violations or malformed requests.\n * They are the outermost error layer and typically map to HTTP responses.\n *\n * **When to throw:**\n * - Access control failures (unauthorized/forbidden)\n * - Request validation failures\n * - Unexpected controller execution errors\n *\n * **Child classes:**\n * - {@link AccessDeniedError} - Authorization failures (HTTP 403)\n * - {@link InvalidRequestError} - Request validation failures (HTTP 400)\n *\n * @example\n * ```typescript\n * // Thrown automatically by BaseController for unexpected errors\n * throw new ControllerError({\n * message: 'Controller execution failed',\n * cause: originalError,\n * });\n * ```\n */\nexport class ControllerError extends CodedError {\n /**\n * Creates a new ControllerError instance.\n *\n * @param options - Error configuration\n * @param options.message - Human-readable error description\n * @param options.code - Machine-readable error code (default: 'CONTROLLER_ERROR')\n * @param options.cause - Optional underlying error\n */\n constructor({\n message,\n code = ErrorCodes.Presentation.CONTROLLER_ERROR,\n cause,\n }: {\n message: string;\n code?: PresentationErrorCode | string;\n cause?: unknown;\n }) {\n super({ message, code, cause });\n }\n\n /**\n * Creates a ControllerError from a caught error.\n *\n * @param cause - The original caught error\n * @returns A new ControllerError instance with the cause attached\n */\n static override fromError(cause: unknown): ControllerError {\n return new ControllerError({\n message: cause instanceof Error ? cause.message : 'Controller error',\n cause,\n });\n }\n}\n","import { CodedError } from '../../../global/exceptions/coded-error.error';\nimport {\n ErrorCodes,\n type PresentationErrorCode,\n} from '../../../global/exceptions/error-codes.const';\nimport type { ValidationError } from '../../../global/interfaces/types/validation-error.type';\n\n/**\n * Error thrown when request validation fails at the controller level.\n *\n * Contains structured validation errors with field paths and messages,\n * converted from {@link ObjectValidationError} by {@link BaseController}.\n * Provides detailed feedback about which fields failed validation.\n *\n * **When thrown:**\n * - Request DTO validation fails\n * - Malformed request data\n * - Missing required fields\n *\n * @example\n * ```typescript\n * // Automatically thrown by BaseController when DTO validation fails\n * // The validationErrors array contains field-level details:\n * // [\n * // { field: 'email', message: 'Invalid email format' },\n * // { field: 'age', message: 'Must be a positive number' }\n * // ]\n * ```\n *\n * @example Manual usage\n * ```typescript\n * throw new InvalidRequestError({\n * message: 'Request validation failed',\n * validationErrors: [\n * { field: 'username', message: 'Username is required' },\n * ],\n * });\n * ```\n *\n * @extends CodedError\n */\nexport class InvalidRequestError extends CodedError {\n /**\n * Array of field-level validation errors.\n *\n * Each entry contains:\n * - `field`: Dot-notation path to the invalid field\n * - `message`: Human-readable validation failure message\n */\n readonly validationErrors: ValidationError[];\n\n /**\n * Creates a new InvalidRequestError instance.\n *\n * @param options - Error configuration\n * @param options.message - Summary of the validation failure\n * @param options.code - Machine-readable error code (default: 'INVALID_REQUEST')\n * @param options.cause - Optional underlying error\n * @param options.validationErrors - Array of field-level validation errors\n */\n constructor({\n message,\n code = ErrorCodes.Presentation.INVALID_REQUEST,\n cause,\n validationErrors,\n }: {\n message: string;\n code?: PresentationErrorCode | string;\n cause?: unknown;\n validationErrors: ValidationError[];\n }) {\n super({ message, code, cause });\n this.validationErrors = validationErrors;\n }\n\n /**\n * Creates an InvalidRequestError from a caught error.\n *\n * @param cause - The original caught error\n * @returns A new InvalidRequestError instance with the cause attached\n */\n static override fromError(cause: unknown): InvalidRequestError {\n return new InvalidRequestError({\n message: cause instanceof Error ? cause.message : 'Invalid request',\n cause,\n validationErrors: [],\n });\n }\n}\n","import type { BaseInboundPort } from '../../app/interfaces/ports/base-inbound.port';\nimport type { BaseDto } from '../../../global/classes/base-dto.class';\nimport { CodedError } from '../../../global/exceptions/coded-error.error';\nimport { ObjectValidationError } from '../../../global/exceptions/object-validation.error';\nimport { wrapErrorUnless, wrapErrorUnlessAsync } from '../../../global/utils/wrap-error.util';\nimport { ControllerError } from '../exceptions/controller.error';\nimport { InvalidRequestError } from '../exceptions/invalid-request.error';\n\n/**\n * Configuration for creating a BaseController instance.\n *\n * All types must be DTOs (extending BaseDto) to ensure validation at every boundary:\n * - TRequestDto: Validated HTTP request (body, headers, params, query)\n * - TResponseDto: Validated HTTP response structure\n * - TInDto: Validated use case input\n * - TOutDto: Validated use case output\n *\n * @typeParam TRequestDto - Validated request DTO from the framework layer\n * @typeParam TResponseDto - Validated response DTO to return to the framework\n * @typeParam TInDto - Input DTO type for the use case\n * @typeParam TOutDto - Output DTO type from the use case\n */\nexport interface BaseControllerConfig<\n TRequestDto extends BaseDto<unknown>,\n TResponseDto extends BaseDto<unknown>,\n TInDto extends BaseDto<unknown>,\n TOutDto extends BaseDto<unknown>,\n> {\n /** Maps the validated request DTO to a use case input DTO. */\n requestMapper: (request: TRequestDto) => TInDto;\n /** The use case to execute. */\n useCase: BaseInboundPort<TInDto, TOutDto>;\n /** Maps the use case output DTO to a validated response DTO. */\n responseMapper: (output: TOutDto) => TResponseDto;\n}\n\n/**\n * Base controller implementing the request/response pipeline.\n *\n * Orchestrates the flow: `requestDto → mapRequest → executeUseCase → mapResponse → responseDto`\n *\n * All boundaries are validated DTOs:\n * - Input: TRequestDto (validated by framework layer before controller)\n * - Use case input: TInDto (validated by mapRequest)\n * - Use case output: TOutDto (validated by use case)\n * - Output: TResponseDto (validated by mapResponse)\n *\n * Features:\n * - Converts {@link ObjectValidationError} to {@link InvalidRequestError}\n * - Passes through known {@link CodedError} types\n * - Wraps unknown errors in {@link ControllerError}\n *\n * Architecture:\n * - {@link execute} - Public entry point with error wrapping (do not override)\n * - {@link pipeline} - Protected pipeline orchestration (override for custom flow)\n * - {@link mapRequest} - Request-to-input transformation\n * - {@link executeUseCase} - Use case execution\n * - {@link mapResponse} - Output-to-response transformation\n *\n * @typeParam TRequestDto - Validated request DTO from the framework layer\n * @typeParam TResponseDto - Validated response DTO to return to the framework\n * @typeParam TInDto - Input DTO type for the use case\n * @typeParam TOutDto - Output DTO type from the use case\n *\n * @example Basic usage\n * ```typescript\n * const controller = BaseController.create({\n * requestMapper: (req) => CreateUserInputDto.create(req.data),\n * useCase: createUserUseCase,\n * responseMapper: (output) => CreateUserResponseDto.create({ id: output.data.id }),\n * });\n *\n * // Framework layer creates the request DTO\n * const requestDto = CreateUserRequestDto.create(httpRequest);\n * const responseDto = await controller.execute(requestDto);\n * ```\n *\n * @example Custom controller overriding pipeline\n * ```typescript\n * class LoggingController extends BaseController<...> {\n * protected override async pipeline(input: TRequestDto): Promise<TResponseDto> {\n * console.log('Request received:', input);\n * const result = await super.pipeline(input);\n * console.log('Response:', result);\n * return result;\n * }\n * }\n * ```\n *\n * @example Custom controller overriding individual methods\n * ```typescript\n * class CachingController extends BaseController<...> {\n * private cache = new Map();\n *\n * protected override async executeUseCase(input: TInDto): Promise<TOutDto> {\n * const key = JSON.stringify(input.data);\n * if (this.cache.has(key)) return this.cache.get(key);\n * const result = await super.executeUseCase(input);\n * this.cache.set(key, result);\n * return result;\n * }\n * }\n * ```\n */\nexport class BaseController<\n TRequestDto extends BaseDto<unknown>,\n TResponseDto extends BaseDto<unknown>,\n TInDto extends BaseDto<unknown>,\n TOutDto extends BaseDto<unknown>,\n> {\n /**\n * Creates a new BaseController instance.\n *\n * @param requestMapper - Function to map request DTO to use case input DTO\n * @param useCase - The use case port to execute\n * @param responseMapper - Function to map use case output DTO to response DTO\n */\n constructor(\n protected readonly requestMapper: (request: TRequestDto) => TInDto,\n protected readonly useCase: BaseInboundPort<TInDto, TOutDto>,\n protected readonly responseMapper: (output: TOutDto) => TResponseDto,\n ) {}\n\n /**\n * Factory method to create a controller from a configuration object.\n *\n * @param config - Controller configuration\n * @returns A new BaseController instance\n */\n static create<\n TRequestDto extends BaseDto<unknown>,\n TResponseDto extends BaseDto<unknown>,\n TInDto extends BaseDto<unknown>,\n TOutDto extends BaseDto<unknown>,\n >(\n config: BaseControllerConfig<TRequestDto, TResponseDto, TInDto, TOutDto>,\n ): BaseController<TRequestDto, TResponseDto, TInDto, TOutDto> {\n return new BaseController(config.requestMapper, config.useCase, config.responseMapper);\n }\n\n /**\n * Executes the controller pipeline with error wrapping.\n *\n * This is the public entry point that ensures consistent error handling.\n * All errors are wrapped in {@link ControllerError} unless they extend {@link CodedError}.\n *\n * **Do not override this method.** Override {@link pipeline} instead for custom pipeline logic.\n *\n * @param input - The validated request DTO\n * @returns Promise resolving to the validated response DTO\n * @throws {InvalidRequestError} When request mapping/validation fails\n * @throws {ControllerError} When an unexpected error occurs\n * @throws {CodedError} When use case throws a known error type\n */\n async execute(input: TRequestDto): Promise<TResponseDto> {\n return wrapErrorUnlessAsync(\n () => this.pipeline(input),\n (cause) =>\n new ControllerError({\n message: cause instanceof Error ? cause.message : 'Controller execution failed',\n cause,\n }),\n [CodedError],\n );\n }\n\n /**\n * Runs the controller pipeline.\n *\n * Orchestrates: `mapRequest → executeUseCase → mapResponse`\n *\n * Override this method to customize the entire pipeline flow, or override\n * individual protected methods ({@link mapRequest}, {@link executeUseCase},\n * {@link mapResponse}) for more granular control.\n *\n * @param input - The validated request DTO\n * @returns Promise resolving to the validated response DTO\n */\n protected async pipeline(input: TRequestDto): Promise<TResponseDto> {\n const mappedInput = this.mapRequest(input);\n const result = await this.executeUseCase(mappedInput);\n return this.mapResponse(result);\n }\n\n /**\n * Maps the request DTO to a use case input DTO.\n *\n * Override to add custom pre-processing, logging, or transformation logic.\n * The default implementation uses the configured `requestMapper` and converts\n * {@link ObjectValidationError} to {@link InvalidRequestError}.\n *\n * @param input - The validated request DTO\n * @returns The use case input DTO\n * @throws {InvalidRequestError} When validation fails\n * @throws {ControllerError} When mapping fails unexpectedly\n */\n protected mapRequest(input: TRequestDto): TInDto {\n return wrapErrorUnless(\n () => this.requestMapper(input),\n (cause) => {\n if (cause instanceof ObjectValidationError) {\n return new InvalidRequestError({\n message: cause.message,\n cause,\n validationErrors: cause.validationErrors,\n });\n }\n return new ControllerError({\n message: cause instanceof Error ? cause.message : 'Request mapping failed',\n cause,\n });\n },\n [CodedError],\n );\n }\n\n /**\n * Executes the use case with the mapped input.\n *\n * Override to add custom logic around use case execution, such as:\n * - Logging/tracing\n * - Caching\n * - Retry logic\n * - Multi-use-case orchestration\n *\n * @param input - The use case input DTO\n * @returns Promise resolving to the use case output DTO\n */\n protected async executeUseCase(input: TInDto): Promise<TOutDto> {\n return this.useCase.execute(input);\n }\n\n /**\n * Maps the use case output DTO to a response DTO.\n *\n * Override to add custom post-processing, logging, or transformation logic.\n * The default implementation uses the configured `responseMapper`.\n *\n * @param output - The use case output DTO\n * @returns The response DTO\n * @throws {ControllerError} When mapping or validation fails\n */\n protected mapResponse(output: TOutDto): TResponseDto {\n return wrapErrorUnless(\n () => this.responseMapper(output),\n (cause) =>\n new ControllerError({\n message:\n cause instanceof ObjectValidationError\n ? 'Response validation failed'\n : cause instanceof Error\n ? cause.message\n : 'Response mapping failed',\n cause,\n }),\n [CodedError],\n );\n }\n}\n","import { CodedError } from '../../../global/exceptions/coded-error.error';\nimport {\n ErrorCodes,\n type PresentationErrorCode,\n} from '../../../global/exceptions/error-codes.const';\n\n/**\n * Error thrown when access to a resource is denied.\n *\n * Indicates that the requester does not have permission to perform\n * the requested operation. Thrown by {@link GuardedController} when\n * an access guard returns `isAllowed: false`.\n *\n * **When thrown:**\n * - Access guard denies the request\n * - User lacks required permissions\n * - Resource ownership check fails\n *\n * @example GuardedController usage\n * ```typescript\n * const controller = GuardedController.create({\n * accessGuard: (req) => ({\n * isAllowed: req.user?.role === 'admin',\n * reason: 'Admin access required',\n * }),\n * // ... other config\n * });\n * ```\n *\n * @example Manual usage\n * ```typescript\n * if (!user.canAccess(resource)) {\n * throw new AccessDeniedError({\n * message: 'You do not have access to this resource',\n * code: 'RESOURCE_ACCESS_DENIED',\n * });\n * }\n * ```\n *\n * @extends CodedError\n */\nexport class AccessDeniedError extends CodedError {\n /**\n * Creates a new AccessDeniedError instance.\n *\n * @param options - Error configuration\n * @param options.message - Description of why access was denied\n * @param options.code - Machine-readable error code (default: 'ACCESS_DENIED')\n * @param options.cause - Optional underlying error\n */\n constructor({\n message,\n code = ErrorCodes.Presentation.ACCESS_DENIED,\n cause,\n }: {\n message: string;\n code?: PresentationErrorCode | string;\n cause?: unknown;\n }) {\n super({ message, code, cause });\n }\n\n /**\n * Creates an AccessDeniedError from a caught error.\n *\n * @param cause - The original caught error\n * @returns A new AccessDeniedError instance with the cause attached\n */\n static override fromError(cause: unknown): AccessDeniedError {\n return new AccessDeniedError({\n message: cause instanceof Error ? cause.message : 'Access denied',\n cause,\n });\n }\n}\n","import type { AccessGuard } from '../interfaces/types/access-guard.type';\nimport type { AccessGuardResult } from '../interfaces/types/access-guard-result.type';\nimport type { BaseInboundPort } from '../../app/interfaces/ports/base-inbound.port';\nimport type { BaseDto } from '../../../global/classes/base-dto.class';\nimport { BaseController } from './base-controller.class';\nimport { AccessDeniedError } from '../exceptions/access-denied.error';\n\n/**\n * Configuration for creating a GuardedController instance.\n *\n * All types must be DTOs (extending BaseDto) to ensure validation at every boundary.\n *\n * @typeParam TRequestDto - Validated request DTO from the framework layer\n * @typeParam TResponseDto - Validated response DTO to return to the framework\n * @typeParam TInDto - Input DTO type for the use case\n * @typeParam TOutDto - Output DTO type from the use case\n */\nexport interface GuardedControllerConfig<\n TRequestDto extends BaseDto<unknown>,\n TResponseDto extends BaseDto<unknown>,\n TInDto extends BaseDto<unknown>,\n TOutDto extends BaseDto<unknown>,\n> {\n /** Maps the validated request DTO to a use case input DTO. */\n requestMapper: (request: TRequestDto) => TInDto;\n /** The use case to execute. */\n useCase: BaseInboundPort<TInDto, TOutDto>;\n /** Maps the use case output DTO to a validated response DTO. */\n responseMapper: (output: TOutDto) => TResponseDto;\n /** Optional access guard; defaults to allowing all requests. */\n accessGuard?: AccessGuard<TRequestDto>;\n}\n\n/**\n * Creates a type-safe default access guard that allows all requests.\n * @internal\n */\nfunction createAllowAllGuard<T>(): AccessGuard<T> {\n return async (): Promise<AccessGuardResult> => ({\n isAllowed: true,\n });\n}\n\n/**\n * Controller with access control.\n *\n * Extends {@link BaseController} with an access guard that runs before\n * the pipeline. If the guard denies access, an {@link AccessDeniedError}\n * is thrown.\n *\n * All types must be DTOs (extending BaseDto) to ensure validation at every boundary.\n *\n * @typeParam TRequestDto - Validated request DTO from the framework layer\n * @typeParam TResponseDto - Validated response DTO to return to the framework\n * @typeParam TInDto - Input DTO type for the use case\n * @typeParam TOutDto - Output DTO type from the use case\n *\n * @example\n * ```typescript\n * const controller = GuardedController.create({\n * requestMapper: (req) => UpdateUserInputDto.create(req.data),\n * useCase: updateUserUseCase,\n * responseMapper: (output) => UpdateUserResponseDto.create(output.data),\n * accessGuard: async (req) => ({\n * isAllowed: req.data.user?.role === 'admin',\n * reason: 'Admin access required',\n * }),\n * });\n * ```\n */\nexport class GuardedController<\n TRequestDto extends BaseDto<unknown>,\n TResponseDto extends BaseDto<unknown>,\n TInDto extends BaseDto<unknown>,\n TOutDto extends BaseDto<unknown>,\n> extends BaseController<TRequestDto, TResponseDto, TInDto, TOutDto> {\n /** The access guard function for this controller. */\n protected readonly accessGuard: AccessGuard<TRequestDto>;\n\n /**\n * Creates a new GuardedController instance.\n *\n * @param requestMapper - Function to map request DTO to use case input DTO\n * @param useCase - The use case port to execute\n * @param responseMapper - Function to map use case output DTO to response DTO\n * @param accessGuard - Optional access guard; defaults to allowing all\n */\n constructor(\n requestMapper: (request: TRequestDto) => TInDto,\n useCase: BaseInboundPort<TInDto, TOutDto>,\n responseMapper: (output: TOutDto) => TResponseDto,\n accessGuard?: AccessGuard<TRequestDto>,\n ) {\n super(requestMapper, useCase, responseMapper);\n this.accessGuard = accessGuard ?? createAllowAllGuard<TRequestDto>();\n }\n\n /**\n * Factory method to create a guarded controller from a configuration object.\n *\n * @param config - Controller configuration including optional access guard\n * @returns A new GuardedController instance\n */\n static override create<\n TRequestDto extends BaseDto<unknown>,\n TResponseDto extends BaseDto<unknown>,\n TInDto extends BaseDto<unknown>,\n TOutDto extends BaseDto<unknown>,\n >(\n config: GuardedControllerConfig<TRequestDto, TResponseDto, TInDto, TOutDto>,\n ): GuardedController<TRequestDto, TResponseDto, TInDto, TOutDto> {\n return new GuardedController(\n config.requestMapper,\n config.useCase,\n config.responseMapper,\n config.accessGuard,\n );\n }\n\n /**\n * Runs the controller pipeline with access control.\n *\n * Checks the access guard before executing the pipeline.\n * If denied, throws {@link AccessDeniedError}.\n *\n * @param input - The validated request DTO\n * @returns Promise resolving to the validated response DTO\n * @throws {AccessDeniedError} When access guard denies the request\n */\n protected override async pipeline(input: TRequestDto): Promise<TResponseDto> {\n await this.checkAccess(input);\n return super.pipeline(input);\n }\n\n /**\n * Checks access using the configured guard.\n *\n * Override to customize access control logic.\n *\n * @param input - The validated request DTO\n * @throws {AccessDeniedError} When access is denied\n */\n protected async checkAccess(input: TRequestDto): Promise<void> {\n const result = await this.accessGuard(input);\n if (!result.isAllowed) {\n throw new AccessDeniedError({\n message: result.reason ?? 'Access denied',\n });\n }\n }\n}\n","/**\n * System metadata.\n *\n * Top-level metadata for the whole API surface (\"the system\"), sitting above\n * individual services/resources/endpoints.\n *\n * This is intentionally stable and serializable so it can be consumed by tools\n * (OpenAPI generation, docs, code generation).\n */\n\n// ═══════════════════════════════════════════════════════════════════════════════\n// Auth Scheme Types\n// ═══════════════════════════════════════════════════════════════════════════════\n\n/**\n * API Key authentication scheme (header, query, or cookie).\n */\nexport interface ApiKeyAuthScheme {\n type: 'apiKey';\n in: 'header' | 'query' | 'cookie';\n /** Header/query/cookie parameter name, e.g. 'x-api-key' */\n name: string;\n description?: string;\n}\n\n/**\n * HTTP Bearer authentication scheme.\n */\nexport interface HttpBearerAuthScheme {\n type: 'http';\n scheme: 'bearer';\n bearerFormat?: string;\n description?: string;\n}\n\n/**\n * HTTP Basic authentication scheme.\n */\nexport interface HttpBasicAuthScheme {\n type: 'http';\n scheme: 'basic';\n description?: string;\n}\n\n/**\n * Union of all supported authentication schemes.\n */\nexport type AuthScheme = ApiKeyAuthScheme | HttpBearerAuthScheme | HttpBasicAuthScheme;\n\n// ═══════════════════════════════════════════════════════════════════════════════\n// System Metadata Type\n// ═══════════════════════════════════════════════════════════════════════════════\n\nexport interface SystemMetadata {\n // ═══════════════════════════════════════════════════════════════════════════\n // IDENTITY (required — routing, logging, code generation)\n // ═══════════════════════════════════════════════════════════════════════════\n\n /**\n * Stable system identifier.\n *\n * Recommendation: kebab-case.\n * Example: `acmp-connector`\n */\n id: string;\n\n /**\n * Short identifier for compact displays/logging.\n *\n * Example: `acmp`\n */\n shortId: string;\n\n /**\n * Human-readable system name.\n *\n * Example: `ACMP Connector`\n */\n name: string;\n\n /**\n * Human-readable description.\n */\n description?: string;\n\n /**\n * System/API version (SemVer recommended).\n *\n * Example: `1.0.0`\n */\n version: string;\n\n // ═══════════════════════════════════════════════════════════════════════════\n // DOMAIN (system-specific — servers, auth)\n // ═══════════════════════════════════════════════════════════════════════════\n\n /**\n * Default servers for the API.\n * Used by OpenAPI generation and client configuration.\n */\n servers?: {\n url: string;\n description?: string;\n }[];\n\n /**\n * Authentication configuration.\n */\n auth?: {\n /**\n * Whether endpoints should be considered secure by default.\n * @default true\n */\n secureByDefault?: boolean;\n\n /**\n * Available authentication schemes.\n *\n * Keyed by scheme name (must be unique within the system).\n * Example: `{ apiKeyAuth: { type: 'apiKey', in: 'header', name: 'x-api-key' } }`\n */\n schemes: Record<string, AuthScheme>;\n\n /**\n * Default security requirements (applies to all secure endpoints).\n *\n * OpenAPI semantics:\n * - Array is OR (any requirement can satisfy)\n * - Object is AND (all schemes required together)\n *\n * Example: `[{ apiKeyAuth: [] }]`\n */\n defaultSecurity?: Record<string, string[]>[];\n };\n\n // ═══════════════════════════════════════════════════════════════════════════\n // OPENAPI (optional — documentation generation)\n // Override pattern: openApi.xxx overrides base xxx\n // ═══════════════════════════════════════════════════════════════════════════\n\n /**\n * OpenAPI-specific overrides for global spec generation.\n */\n openApi?: {\n /**\n * OpenAPI info.title.\n * Overrides `name` if set.\n */\n title?: string;\n\n /**\n * OpenAPI info.description.\n * Overrides `description` if set.\n */\n description?: string;\n\n /**\n * OpenAPI info.termsOfService URL.\n */\n termsOfService?: string;\n\n /**\n * OpenAPI info.contact.\n */\n contact?: {\n name?: string;\n url?: string;\n email?: string;\n };\n\n /**\n * OpenAPI info.license.\n */\n license?: {\n name: string;\n url?: string;\n };\n };\n}\n\n// ═══════════════════════════════════════════════════════════════════════════════\n// Utility Types\n// ═══════════════════════════════════════════════════════════════════════════════\n\n/**\n * Extracts the scheme names (keys) from a SystemMetadata constant.\n *\n * @example\n * const systemMeta = { auth: { schemes: { apiKeyAuth: {...}, bearerAuth: {...} } } } as const;\n * type Names = SchemeNamesOf<typeof systemMeta>; // 'apiKeyAuth' | 'bearerAuth'\n */\nexport type SchemeNamesOf<TSystem> = TSystem extends {\n auth: { schemes: infer S };\n}\n ? keyof S & string\n : never;\n\n/**\n * Creates a typed OpenAPI security requirement array from scheme names.\n *\n * @example\n * type Req = SecurityRequirementOf<'apiKeyAuth' | 'bearerAuth'>;\n * // Array<Partial<Record<'apiKeyAuth' | 'bearerAuth', string[]>>>\n */\nexport type SecurityRequirementOf<TSchemeNames extends string> = Partial<\n Record<TSchemeNames, string[]>\n>[];\n\n// ═══════════════════════════════════════════════════════════════════════════════\n// Helper Function\n// ═══════════════════════════════════════════════════════════════════════════════\n\n/**\n * Input type for defineSystemMetadata helper (with generic auth).\n */\ntype SystemMetadataInput<TSchemeNames extends string> = Omit<SystemMetadata, 'auth'> & {\n auth?: {\n secureByDefault?: boolean;\n schemes: Record<TSchemeNames, AuthScheme>;\n defaultSecurity?: Partial<Record<TSchemeNames, string[]>>[];\n };\n};\n\n/**\n * Defines system metadata with fully-typed `defaultSecurity`.\n *\n * Infers scheme names from the `schemes` object and validates that\n * `defaultSecurity` only references existing scheme names.\n *\n * @example\n * export const systemMetadata = defineSystemMetadata({\n * id: 'my-api',\n * shortId: 'api',\n * name: 'My API',\n * version: '1.0.0',\n * auth: {\n * schemes: {\n * apiKeyAuth: { type: 'apiKey', in: 'header', name: 'x-api-key' },\n * },\n * defaultSecurity: [{ apiKeyAuth: [] }], // ✅ Valid\n * // defaultSecurity: [{ typoAuth: [] }], // ❌ TypeScript error!\n * },\n * });\n */\nexport function defineSystemMetadata<const TSchemeNames extends string>(\n metadata: SystemMetadataInput<TSchemeNames>,\n): SystemMetadataInput<TSchemeNames> & SystemMetadata {\n return metadata as SystemMetadataInput<TSchemeNames> & SystemMetadata;\n}\n","import type { HttpEndpointMetadata } from '../interfaces/types/metadata/http-endpoint-metadata.type';\nimport type { ResourceMetadata } from '../interfaces/types/metadata/resource-metadata.type';\nimport type { ServiceMetadata } from '../interfaces/types/metadata/service-metadata.type';\n\n/**\n * Normalizes a path segment by removing leading/trailing slashes.\n */\nfunction trimSlashes(segment: string): string {\n return segment.replace(/^\\/+|\\/+$/g, '');\n}\n\n/**\n * Computes the full route path from service, resource, and endpoint metadata.\n *\n * Handles path normalization:\n * - Ensures leading slash\n * - Joins segments with single slashes\n * - Removes trailing slash (except for root)\n *\n * @example\n * ```typescript\n * computeRoutePath(\n * { basePath: '/user-service' },\n * { path: '/users' },\n * { path: '/{id}' }\n * ); // => '/user-service/users/{id}'\n * ```\n */\nexport function computeRoutePath(\n service: Pick<ServiceMetadata, 'basePath'>,\n resource: Pick<ResourceMetadata, 'path'>,\n endpoint: Pick<HttpEndpointMetadata, 'path'>,\n): string {\n const segments = [service.basePath, resource.path, endpoint.path]\n .map(trimSlashes)\n .filter((s) => s.length > 0);\n\n if (segments.length === 0) {\n return '/';\n }\n\n return '/' + segments.join('/');\n}\n","import type { HttpResponse } from '../interfaces/types/http/http-response';\n\n/**\n * Type guard to validate that a value is a valid HttpResponse.\n *\n * Checks that the value has the required `statusCode` property as a number.\n * This is used to validate controller outputs before passing to response mappers.\n *\n * @param value - The value to check\n * @returns True if the value is a valid HttpResponse\n *\n * @example\n * ```typescript\n * const output = controller.execute(input);\n * if (!isHttpResponse(output)) {\n * throw new Error('Controller must return an HttpResponse');\n * }\n * ```\n */\nexport function isHttpResponse(value: unknown): value is HttpResponse {\n return (\n typeof value === 'object' &&\n value !== null &&\n 'statusCode' in value &&\n typeof (value as { statusCode: unknown }).statusCode === 'number'\n );\n}\n\n/**\n * Asserts that a value is a valid HttpResponse.\n *\n * Throws a descriptive error if the value is not a valid HttpResponse,\n * making it easier to debug controller output issues.\n *\n * @param value - The value to validate\n * @param context - Optional context for the error message (e.g., 'mapOutput')\n * @throws Error if the value is not a valid HttpResponse\n *\n * @example\n * ```typescript\n * const output = controller.execute(input);\n * assertHttpResponse(output, 'controller output');\n * // Now TypeScript knows output is HttpResponse\n * ```\n */\nexport function assertHttpResponse(\n value: unknown,\n context = 'value',\n): asserts value is HttpResponse {\n if (!isHttpResponse(value)) {\n const actualType = value === null ? 'null' : value === undefined ? 'undefined' : typeof value;\n const hasStatusCode = typeof value === 'object' && value !== null && 'statusCode' in value;\n\n let message = `Expected ${context} to be an HttpResponse with a numeric statusCode, `;\n\n if (hasStatusCode) {\n const statusCodeType = typeof (value as { statusCode: unknown })['statusCode'];\n message += `but statusCode was ${statusCodeType}`;\n } else {\n message += `but got ${actualType}`;\n }\n\n throw new Error(message);\n }\n}\n"],"mappings":"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","names":[]}
@@ -0,0 +1,5 @@
1
+ export { A as AccessDeniedError, d as AccessGuard, e as AccessGuardResult, l as ApiKeyAuthScheme, o as AuthScheme, b as BaseController, a as BaseControllerConfig, C as ControllerError, E as EnhancedHttpRequest, f as EnhancedRequest, c as GuardedController, G as GuardedControllerConfig, n as HttpBasicAuthScheme, m as HttpBearerAuthScheme, j as HttpEndpointMetadata, k as HttpEndpointMetadataFor, H as HttpEndpointMethod, h as HttpEndpointOpenApi, i as HttpEndpointOpenApiFor, g as HttpSuccessStatus, I as InvalidRequestError, R as ResourceMetadata, q as SchemeNamesOf, r as SecurityRequirementOf, S as ServiceMetadata, p as SystemMetadata, v as assertHttpResponse, t as computeRoutePath, s as defineSystemMetadata, u as isHttpResponse } from '../../index-DingXh7B.cjs';
2
+ export { C as Controller, H as HttpRequest, a as HttpResponse } from '../../http-response-BAhi8lF4.cjs';
3
+ export { H as HttpMethod, b as RequestDtoFactory, R as RouteInput, a as RouteMetadata } from '../../routing.type-DF2BIL7x.cjs';
4
+ import '../../base-dto.class-D7W9iqoU.cjs';
5
+ import '../../validation-error.type-kD4_qNZ9.cjs';
@@ -0,0 +1,5 @@
1
+ export { A as AccessDeniedError, d as AccessGuard, e as AccessGuardResult, l as ApiKeyAuthScheme, o as AuthScheme, b as BaseController, a as BaseControllerConfig, C as ControllerError, E as EnhancedHttpRequest, f as EnhancedRequest, c as GuardedController, G as GuardedControllerConfig, n as HttpBasicAuthScheme, m as HttpBearerAuthScheme, j as HttpEndpointMetadata, k as HttpEndpointMetadataFor, H as HttpEndpointMethod, h as HttpEndpointOpenApi, i as HttpEndpointOpenApiFor, g as HttpSuccessStatus, I as InvalidRequestError, R as ResourceMetadata, q as SchemeNamesOf, r as SecurityRequirementOf, S as ServiceMetadata, p as SystemMetadata, v as assertHttpResponse, t as computeRoutePath, s as defineSystemMetadata, u as isHttpResponse } from '../../index-tOH7XBa3.js';
2
+ export { C as Controller, H as HttpRequest, a as HttpResponse } from '../../http-response-BAhi8lF4.js';
3
+ export { H as HttpMethod, b as RequestDtoFactory, R as RouteInput, a as RouteMetadata } from '../../routing.type-DB4pt-d9.js';
4
+ import '../../base-dto.class-D7W9iqoU.js';
5
+ import '../../validation-error.type-kD4_qNZ9.js';
@@ -0,0 +1,28 @@
1
+ import {
2
+ BaseController,
3
+ GuardedController,
4
+ assertHttpResponse,
5
+ computeRoutePath,
6
+ defineSystemMetadata,
7
+ isHttpResponse
8
+ } from "../../chunk-DDAHJZVK.js";
9
+ import "../../chunk-OKFXZHBC.js";
10
+ import {
11
+ AccessDeniedError,
12
+ ControllerError,
13
+ InvalidRequestError
14
+ } from "../../chunk-74IKUOSE.js";
15
+ import "../../chunk-MQD5GXMT.js";
16
+ import "../../chunk-CGZBV6BD.js";
17
+ export {
18
+ AccessDeniedError,
19
+ BaseController,
20
+ ControllerError,
21
+ GuardedController,
22
+ InvalidRequestError,
23
+ assertHttpResponse,
24
+ computeRoutePath,
25
+ defineSystemMetadata,
26
+ isHttpResponse
27
+ };
28
+ //# sourceMappingURL=presentation.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}