@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/frameworks/elysia/index.ts","../../../src/backend/frameworks/elysia/routing.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/onion-layers/domain/exceptions/domain.error.ts","../../../src/backend/core/onion-layers/app/exceptions/use-case.error.ts","../../../src/backend/core/onion-layers/app/exceptions/not-found.error.ts","../../../src/backend/core/onion-layers/app/exceptions/conflict.error.ts","../../../src/backend/core/onion-layers/app/exceptions/unprocessable.error.ts","../../../src/backend/core/onion-layers/infra/exceptions/infra.error.ts","../../../src/backend/core/onion-layers/presentation/exceptions/controller.error.ts","../../../src/backend/core/onion-layers/presentation/exceptions/access-denied.error.ts","../../../src/backend/core/onion-layers/presentation/exceptions/invalid-request.error.ts","../../../src/backend/frameworks/elysia/map-error-to-response.ts","../../../src/backend/frameworks/elysia/error-handler.ts"],"sourcesContent":["export {\n registerElysiaRoutes,\n type HttpController,\n type ElysiaMiddleware,\n type RouteInputOrArray,\n type RegisterRoutesOptions,\n} from './routing';\nexport {\n mapErrorToResponse,\n type ErrorResponseBody,\n type MappedErrorResponse,\n} from './map-error-to-response';\nexport { onionErrorHandler } from './error-handler';\n","import type { Elysia, Handler } from 'elysia';\nimport type { BaseDto } from '../../core/global/classes/base-dto.class';\nimport type { Controller } from '../../core/onion-layers/presentation/interfaces/types/controller.type';\nimport type { HttpRequest } from '../../core/onion-layers/presentation/interfaces/types/http/http-request';\nimport type { HttpResponse } from '../../core/onion-layers/presentation/interfaces/types/http/http-response';\nimport type { RouteInput } from '../../core/onion-layers/presentation/routing';\n\n/**\n * Supported HTTP methods in Elysia.\n */\ntype HttpMethod = 'get' | 'post' | 'put' | 'patch' | 'delete' | 'options' | 'head';\n\n/**\n * Controller that works with a validated request DTO and returns HttpResponse.\n */\nexport type HttpController<TRequestDto extends BaseDto<unknown> = BaseDto<unknown>> = Controller<\n TRequestDto,\n HttpResponse\n>;\n\n/**\n * Elysia beforeHandle middleware type.\n * Returns undefined to continue, or a Response to short-circuit.\n */\nexport type ElysiaMiddleware = (context: {\n body: unknown;\n headers: Record<string, string | undefined>;\n query: Record<string, string | undefined>;\n params: Record<string, string>;\n}) => Response | undefined | Promise<Response | undefined>;\n\n/**\n * Converts `{param}` to Elysia's `:param` format.\n */\nfunction toElysiaPath(path: string): string {\n return path.replace(/\\{([^}]+)\\}/g, ':$1');\n}\n\n/**\n * Extracts HttpRequest from Elysia context.\n */\nfunction extractRequest(context: {\n body: unknown;\n headers: Record<string, string | undefined>;\n query: Record<string, string | undefined>;\n params: Record<string, string>;\n}): HttpRequest {\n const headers: Record<string, string> = {};\n for (const [key, value] of Object.entries(context.headers)) {\n if (value != null) {\n headers[key.toLowerCase()] = value;\n }\n }\n\n const queryParams: Record<string, string | string[]> = {};\n for (const [key, value] of Object.entries(context.query)) {\n if (value != null) {\n queryParams[key] = value;\n }\n }\n\n return {\n body: context.body,\n headers,\n queryParams,\n pathParams: context.params,\n };\n}\n\n/**\n * Creates Elysia response from HttpResponse.\n */\nfunction createResponse(response: HttpResponse): Response {\n const headers: Record<string, string> = {\n 'Content-Type': 'application/json',\n };\n\n if (response.headers) {\n for (const [key, value] of Object.entries(response.headers)) {\n if (value != null) {\n headers[key] = String(value);\n }\n }\n }\n\n if (response.body === undefined || response.body === null) {\n return new Response(null, {\n status: response.statusCode,\n headers,\n });\n }\n\n if (typeof response.body === 'string') {\n headers['Content-Type'] = 'text/plain';\n return new Response(response.body, {\n status: response.statusCode,\n headers,\n });\n }\n\n return new Response(JSON.stringify(response.body), {\n status: response.statusCode,\n headers,\n });\n}\n\n/**\n * Route input type that accepts either a single route or an array of routes.\n */\nexport type RouteInputOrArray = RouteInput | RouteInput[];\n\n/**\n * Options for registering routes.\n */\nexport interface RegisterRoutesOptions {\n /**\n * Prefix to apply to all routes in this registration.\n *\n * @example\n * ```typescript\n * registerElysiaRoutes(app, userRoutes, {\n * prefix: '/api/v1',\n * });\n * // Routes will be: /api/v1/users, /api/v1/users/:id, etc.\n * ```\n */\n prefix?: string;\n\n /**\n * Middlewares (beforeHandle hooks) to apply to all routes in this registration.\n * These run before the controller handler.\n *\n * @example\n * ```typescript\n * registerElysiaRoutes(app, userRoutes, {\n * middlewares: [\n * ({ headers }) => {\n * if (!headers.authorization) {\n * return new Response('Unauthorized', { status: 401 });\n * }\n * },\n * ],\n * });\n * ```\n */\n middlewares?: ElysiaMiddleware[];\n}\n\n/**\n * Registers routes onto an Elysia app.\n *\n * Accepts either a single route or an array of routes. Can be called multiple\n * times to register routes from different domains/modules.\n *\n * @param app - The Elysia app instance (passed by reference)\n * @param routes - A single route or an array of routes to register\n * @param options - Optional configuration including prefix\n *\n * @example Single route\n * ```typescript\n * const app = new Elysia();\n *\n * registerElysiaRoutes(app, {\n * metadata: { path: '/health', method: 'GET' },\n * controller: healthController,\n * });\n * ```\n *\n * @example Multiple routes\n * ```typescript\n * const app = new Elysia();\n *\n * registerElysiaRoutes(app, [\n * { metadata: { path: '/users', method: 'POST' }, controller: createUserController },\n * { metadata: { path: '/users/{id}', method: 'GET' }, controller: getUserController },\n * { metadata: { path: '/users/{id}', method: 'DELETE' }, controller: deleteUserController },\n * ]);\n * ```\n *\n * @example With prefix\n * ```typescript\n * registerElysiaRoutes(app, userRoutes, {\n * prefix: '/api/v1',\n * });\n * ```\n *\n * @example With middlewares\n * ```typescript\n * registerElysiaRoutes(app, protectedRoutes, {\n * middlewares: [\n * ({ headers }) => {\n * if (!headers.authorization) {\n * return new Response('Unauthorized', { status: 401 });\n * }\n * },\n * ],\n * });\n * ```\n *\n * @example Registering from multiple domains\n * ```typescript\n * const app = new Elysia();\n *\n * // Public routes\n * registerElysiaRoutes(app, publicRoutes);\n *\n * // API routes with prefix\n * registerElysiaRoutes(app, userRoutes, { prefix: '/api' });\n * registerElysiaRoutes(app, orderRoutes, { prefix: '/api' });\n *\n * export default app;\n * ```\n */\nexport function registerElysiaRoutes(\n app: Elysia,\n routes: RouteInputOrArray,\n options?: RegisterRoutesOptions,\n): void {\n const routeArray = Array.isArray(routes) ? routes : [routes];\n const prefix = options?.prefix ?? '';\n const middlewares = options?.middlewares ?? [];\n\n for (const { metadata, controller, requestDtoFactory } of routeArray) {\n const path = prefix + toElysiaPath(metadata.path);\n const method = metadata.method.toLowerCase() as HttpMethod;\n\n const handler: Handler = async (context) => {\n // Run middlewares first (beforeHandle pattern)\n for (const middleware of middlewares) {\n const result = await middleware(context);\n if (result !== undefined) return result;\n }\n\n const rawRequest = extractRequest(context as Parameters<typeof extractRequest>[0]);\n const requestDto = requestDtoFactory(rawRequest);\n const responseDto = await controller.execute(requestDto);\n return createResponse(responseDto.data);\n };\n\n switch (method) {\n case 'get':\n app.get(path, handler);\n break;\n case 'post':\n app.post(path, handler);\n break;\n case 'put':\n app.put(path, handler);\n break;\n case 'patch':\n app.patch(path, handler);\n break;\n case 'delete':\n app.delete(path, handler);\n break;\n case 'options':\n app.options(path, handler);\n break;\n case 'head':\n app.head(path, handler);\n break;\n default:\n throw new Error(`Unsupported HTTP method: ${method}`);\n }\n }\n}\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","import { CodedError } from '../../../global/exceptions/coded-error.error';\nimport { ErrorCodes, type DomainErrorCode } from '../../../global/exceptions/error-codes.const';\n\n/**\n * Base error class for domain layer failures.\n *\n * Domain errors represent violations of business rules, invariants,\n * or aggregate consistency. They originate from the core domain logic\n * and should be caught and handled by the application layer.\n *\n * **When to throw:**\n * - Business rule violations (e.g., \"Cannot withdraw more than balance\")\n * - Invariant violations (e.g., \"Email format invalid\")\n * - Aggregate consistency failures\n *\n * **Child classes:**\n * - {@link InvariantViolationError} - Value object or entity invariant failures\n * - {@link PartialLoadError} - Incomplete aggregate reconstitution\n *\n * @example\n * ```typescript\n * if (account.balance < amount) {\n * throw new DomainError({\n * message: 'Insufficient funds for withdrawal',\n * code: 'INSUFFICIENT_FUNDS',\n * });\n * }\n * ```\n */\nexport class DomainError extends CodedError {\n /**\n * Creates a new DomainError instance.\n *\n * @param options - Error configuration\n * @param options.message - Human-readable error description\n * @param options.code - Machine-readable error code (default: 'DOMAIN_ERROR')\n * @param options.cause - Optional underlying error\n */\n constructor({\n message,\n code = ErrorCodes.Domain.DOMAIN_ERROR,\n cause,\n }: {\n message: string;\n code?: DomainErrorCode | string;\n cause?: unknown;\n }) {\n super({ message, code, cause });\n }\n\n /**\n * Creates a DomainError from a caught error.\n *\n * @param cause - The original caught error\n * @returns A new DomainError instance with the cause attached\n */\n static override fromError(cause: unknown): DomainError {\n return new DomainError({\n message: cause instanceof Error ? cause.message : 'Domain error',\n cause,\n });\n }\n}\n","import { CodedError } from '../../../global/exceptions/coded-error.error';\nimport { ErrorCodes, type AppErrorCode } from '../../../global/exceptions/error-codes.const';\n\n/**\n * Base error class for application layer (use case) failures.\n *\n * Use case errors represent failures in the application's business logic\n * orchestration, such as resource conflicts, missing entities, or\n * unprocessable requests. They bridge domain errors to the presentation layer.\n *\n * **When to throw:**\n * - Resource not found (e.g., \"User with ID X not found\")\n * - Conflict states (e.g., \"Email already registered\")\n * - Unprocessable business operations\n *\n * **Child classes:**\n * - {@link ConflictError} - Resource state conflicts (HTTP 409)\n * - {@link NotFoundError} - Resource not found (HTTP 404)\n * - {@link UnprocessableError} - Valid but unprocessable request (HTTP 422)\n *\n * @example\n * ```typescript\n * const user = await this.userRepo.findById(id);\n * if (!user) {\n * throw new NotFoundError({\n * message: `User with ID ${id} not found`,\n * code: 'USER_NOT_FOUND',\n * });\n * }\n * ```\n */\nexport class UseCaseError extends CodedError {\n /**\n * Creates a new UseCaseError instance.\n *\n * @param options - Error configuration\n * @param options.message - Human-readable error description\n * @param options.code - Machine-readable error code (default: 'USE_CASE_ERROR')\n * @param options.cause - Optional underlying error\n */\n constructor({\n message,\n code = ErrorCodes.App.USE_CASE_ERROR,\n cause,\n }: {\n message: string;\n code?: AppErrorCode | string;\n cause?: unknown;\n }) {\n super({ message, code, cause });\n }\n\n /**\n * Creates a UseCaseError from a caught error.\n *\n * @param cause - The original caught error\n * @returns A new UseCaseError instance with the cause attached\n */\n static override fromError(cause: unknown): UseCaseError {\n return new UseCaseError({\n message: cause instanceof Error ? cause.message : 'Use case error',\n cause,\n });\n }\n}\n","import { ErrorCodes, type AppErrorCode } from '../../../global/exceptions/error-codes.const';\nimport { UseCaseError } from './use-case.error';\n\n/**\n * Error thrown when a requested resource does not exist.\n *\n * Indicates that the entity or resource referenced by the request\n * could not be found in the system.\n *\n * **When to throw:**\n * - Entity lookup by ID returns null\n * - Referenced resource doesn't exist\n * - Parent entity for a child operation not found\n *\n * @example\n * ```typescript\n * const user = await this.userRepo.findById(userId);\n * if (!user) {\n * throw new NotFoundError({\n * message: `User with ID ${userId} not found`,\n * code: 'USER_NOT_FOUND',\n * });\n * }\n * ```\n *\n * @extends UseCaseError\n */\nexport class NotFoundError extends UseCaseError {\n /**\n * Creates a new NotFoundError instance.\n *\n * @param options - Error configuration\n * @param options.message - Description of what was not found\n * @param options.code - Machine-readable error code (default: 'NOT_FOUND')\n * @param options.cause - Optional underlying error\n */\n constructor({\n message,\n code = ErrorCodes.App.NOT_FOUND,\n cause,\n }: {\n message: string;\n code?: AppErrorCode | string;\n cause?: unknown;\n }) {\n super({ message, code, cause });\n }\n\n /**\n * Creates a NotFoundError from a caught error.\n *\n * @param cause - The original caught error\n * @returns A new NotFoundError instance with the cause attached\n */\n static override fromError(cause: unknown): NotFoundError {\n return new NotFoundError({\n message: cause instanceof Error ? cause.message : 'Resource not found',\n cause,\n });\n }\n}\n","import { ErrorCodes, type AppErrorCode } from '../../../global/exceptions/error-codes.const';\nimport { UseCaseError } from './use-case.error';\n\n/**\n * Error thrown when an operation conflicts with existing state.\n *\n * Indicates that the requested operation cannot be completed because\n * it would violate uniqueness constraints or cause state conflicts.\n *\n * **When to throw:**\n * - Duplicate unique field (e.g., email already registered)\n * - Optimistic locking conflict (stale version)\n * - Concurrent modification detected\n *\n * @example\n * ```typescript\n * const existing = await this.userRepo.findByEmail(email);\n * if (existing) {\n * throw new ConflictError({\n * message: 'Email already registered',\n * code: 'EMAIL_ALREADY_EXISTS',\n * });\n * }\n * ```\n *\n * @extends UseCaseError\n */\nexport class ConflictError extends UseCaseError {\n /**\n * Creates a new ConflictError instance.\n *\n * @param options - Error configuration\n * @param options.message - Description of the conflict\n * @param options.code - Machine-readable error code (default: 'CONFLICT')\n * @param options.cause - Optional underlying error\n */\n constructor({\n message,\n code = ErrorCodes.App.CONFLICT,\n cause,\n }: {\n message: string;\n code?: AppErrorCode | string;\n cause?: unknown;\n }) {\n super({ message, code, cause });\n }\n\n /**\n * Creates a ConflictError from a caught error.\n *\n * @param cause - The original caught error\n * @returns A new ConflictError instance with the cause attached\n */\n static override fromError(cause: unknown): ConflictError {\n return new ConflictError({\n message: cause instanceof Error ? cause.message : 'Conflict error',\n cause,\n });\n }\n}\n","import { ErrorCodes, type AppErrorCode } from '../../../global/exceptions/error-codes.const';\nimport { UseCaseError } from './use-case.error';\n\n/**\n * Error thrown when a request is valid but cannot be processed.\n *\n * The request is syntactically correct and passes validation, but\n * business logic prevents the operation from being completed.\n *\n * **When to throw:**\n * - Business rule prevents operation (e.g., insufficient balance)\n * - Invalid state transition (e.g., canceling a completed order)\n * - Preconditions not met for the operation\n *\n * @example\n * ```typescript\n * if (account.balance < amount) {\n * throw new UnprocessableError({\n * message: 'Insufficient balance for withdrawal',\n * code: 'INSUFFICIENT_BALANCE',\n * });\n * }\n * ```\n *\n * @extends UseCaseError\n */\nexport class UnprocessableError extends UseCaseError {\n /**\n * Creates a new UnprocessableError instance.\n *\n * @param options - Error configuration\n * @param options.message - Description of why the request cannot be processed\n * @param options.code - Machine-readable error code (default: 'UNPROCESSABLE')\n * @param options.cause - Optional underlying error\n */\n constructor({\n message,\n code = ErrorCodes.App.UNPROCESSABLE,\n cause,\n }: {\n message: string;\n code?: AppErrorCode | string;\n cause?: unknown;\n }) {\n super({ message, code, cause });\n }\n\n /**\n * Creates an UnprocessableError from a caught error.\n *\n * @param cause - The original caught error\n * @returns A new UnprocessableError instance with the cause attached\n */\n static override fromError(cause: unknown): UnprocessableError {\n return new UnprocessableError({\n message: cause instanceof Error ? cause.message : 'Unprocessable request',\n cause,\n });\n }\n}\n","import { CodedError } from '../../../global/exceptions/coded-error.error';\nimport { ErrorCodes, type InfraErrorCode } from '../../../global/exceptions/error-codes.const';\n\n/**\n * Base error class for infrastructure layer failures.\n *\n * Infrastructure errors represent failures in external dependencies\n * such as databases, network services, file systems, or third-party APIs.\n * They are automatically created by {@link BaseOutboundAdapter} when\n * repository or gateway methods fail.\n *\n * **When to throw:**\n * - Database connection or query failures\n * - Network timeouts or connection errors\n * - External API failures\n * - File system errors\n *\n * **Child classes:**\n * - {@link DbError} - Database operation failures\n * - {@link NetworkError} - Network connectivity issues\n * - {@link TimeoutError} - Operation timeout\n * - {@link ExternalServiceError} - Third-party service failures\n *\n * @example\n * ```typescript\n * // In a repository extending BaseOutboundAdapter\n * protected override createInfraError(error: unknown, methodName: string): InfraError {\n * return new DbError({\n * message: `Database error in ${methodName}`,\n * cause: error,\n * });\n * }\n * ```\n */\nexport class InfraError extends CodedError {\n /**\n * Creates a new InfraError instance.\n *\n * @param options - Error configuration\n * @param options.message - Human-readable error description\n * @param options.code - Machine-readable error code (default: 'INFRA_ERROR')\n * @param options.cause - Optional underlying error\n */\n constructor({\n message,\n code = ErrorCodes.Infra.INFRA_ERROR,\n cause,\n }: {\n message: string;\n code?: InfraErrorCode | string;\n cause?: unknown;\n }) {\n super({ message, code, cause });\n }\n\n /**\n * Creates an InfraError from a caught error.\n *\n * @param cause - The original caught error\n * @returns A new InfraError instance with the cause attached\n */\n static override fromError(cause: unknown): InfraError {\n return new InfraError({\n message: cause instanceof Error ? cause.message : 'Infrastructure 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';\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';\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 { 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 { CodedError } from '../../core/global/exceptions/coded-error.error';\nimport { ObjectValidationError } from '../../core/global/exceptions/object-validation.error';\nimport { DomainError } from '../../core/onion-layers/domain/exceptions/domain.error';\nimport { UseCaseError } from '../../core/onion-layers/app/exceptions/use-case.error';\nimport { NotFoundError } from '../../core/onion-layers/app/exceptions/not-found.error';\nimport { ConflictError } from '../../core/onion-layers/app/exceptions/conflict.error';\nimport { UnprocessableError } from '../../core/onion-layers/app/exceptions/unprocessable.error';\nimport { InfraError } from '../../core/onion-layers/infra/exceptions/infra.error';\nimport { ControllerError } from '../../core/onion-layers/presentation/exceptions/controller.error';\nimport { AccessDeniedError } from '../../core/onion-layers/presentation/exceptions/access-denied.error';\nimport { InvalidRequestError } from '../../core/onion-layers/presentation/exceptions/invalid-request.error';\n\n/**\n * Error item for field-level validation errors.\n */\ninterface ErrorItem {\n item: string;\n message: string;\n}\n\n/**\n * Standard error response body.\n */\nexport interface ErrorResponseBody {\n message: string;\n errorCode: string;\n errorItems?: ErrorItem[];\n}\n\n/**\n * Mapped error response with status code and body.\n */\nexport interface MappedErrorResponse {\n statusCode: number;\n body: ErrorResponseBody;\n}\n\n/**\n * Maps our error hierarchy to HTTP status codes and response bodies.\n *\n * Mapping strategy:\n * - `ObjectValidationError` → 400 Bad Request\n * - `InvalidRequestError` → 400 Bad Request\n * - `AccessDeniedError` → 403 Forbidden\n * - `NotFoundError` → 404 Not Found\n * - `ConflictError` → 409 Conflict\n * - `UnprocessableError` → 422 Unprocessable Entity\n * - `UseCaseError` (other) → 400 Bad Request\n * - `DomainError` → 500 Internal Server Error (masked)\n * - `InfraError` → 500 Internal Server Error (masked)\n * - `ControllerError` → 500 Internal Server Error (masked)\n * - Unknown → 500 Internal Server Error (masked)\n *\n * **Security Note:** Domain and infrastructure errors are masked to avoid\n * leaking internal implementation details.\n *\n * @param error - The error to map\n * @returns Mapped error response with status code and body\n */\nexport function mapErrorToResponse(error: unknown): MappedErrorResponse {\n // Validation errors → 400 Bad Request\n if (error instanceof ObjectValidationError) {\n return {\n statusCode: 400,\n body: {\n message: error.message,\n errorCode: error.code,\n errorItems: error.validationErrors.map((e) => ({\n item: e.field,\n message: e.message,\n })),\n },\n };\n }\n\n if (error instanceof InvalidRequestError) {\n return {\n statusCode: 400,\n body: {\n message: error.message,\n errorCode: error.code,\n errorItems: error.validationErrors.map((e) => ({\n item: e.field,\n message: e.message,\n })),\n },\n };\n }\n\n // Access control → 403 Forbidden\n if (error instanceof AccessDeniedError) {\n return {\n statusCode: 403,\n body: {\n message: error.message,\n errorCode: error.code,\n },\n };\n }\n\n // Use case errors → specific HTTP status codes\n if (error instanceof NotFoundError) {\n return {\n statusCode: 404,\n body: {\n message: error.message,\n errorCode: error.code,\n },\n };\n }\n\n if (error instanceof ConflictError) {\n return {\n statusCode: 409,\n body: {\n message: error.message,\n errorCode: error.code,\n },\n };\n }\n\n if (error instanceof UnprocessableError) {\n return {\n statusCode: 422,\n body: {\n message: error.message,\n errorCode: error.code,\n },\n };\n }\n\n // Other use case errors → 400 Bad Request\n if (error instanceof UseCaseError) {\n return {\n statusCode: 400,\n body: {\n message: error.message,\n errorCode: error.code,\n },\n };\n }\n\n // Domain errors → 500 Internal Server Error (masked)\n if (error instanceof DomainError) {\n return {\n statusCode: 500,\n body: {\n message: 'An unexpected error occurred',\n errorCode: 'INTERNAL_ERROR',\n },\n };\n }\n\n // Infrastructure errors → 500 Internal Server Error (masked)\n if (error instanceof InfraError) {\n return {\n statusCode: 500,\n body: {\n message: 'An unexpected error occurred',\n errorCode: 'INTERNAL_ERROR',\n },\n };\n }\n\n // Controller errors → 500 Internal Server Error (masked)\n if (error instanceof ControllerError) {\n return {\n statusCode: 500,\n body: {\n message: 'An unexpected error occurred',\n errorCode: 'INTERNAL_ERROR',\n },\n };\n }\n\n // CodedError (catch-all for known errors) → 500 (masked)\n if (error instanceof CodedError) {\n return {\n statusCode: 500,\n body: {\n message: 'An unexpected error occurred',\n errorCode: 'INTERNAL_ERROR',\n },\n };\n }\n\n // Unknown errors → 500 Internal Server Error (masked)\n return {\n statusCode: 500,\n body: {\n message: 'An unexpected error occurred',\n errorCode: 'INTERNAL_ERROR',\n },\n };\n}\n","import { mapErrorToResponse } from './map-error-to-response';\n\n/**\n * Elysia error handler that maps domain errors to HTTP responses.\n *\n * Apply this to your Elysia app using `.onError()` to automatically\n * convert domain/use-case errors to appropriate HTTP responses.\n *\n * @example\n * ```typescript\n * import { Elysia } from 'elysia';\n * import { registerElysiaRoutes, onionErrorHandler } from '@cosmneo/onion-lasagna/backend/frameworks/elysia';\n *\n * const app = new Elysia()\n * .onError(onionErrorHandler)\n * .get('/health', () => ({ status: 'ok' }));\n *\n * registerElysiaRoutes(app, routes);\n *\n * export default app;\n * ```\n *\n * @example With custom error logging\n * ```typescript\n * const app = new Elysia()\n * .onError(({ error, code, ...context }) => {\n * // Log the error\n * console.error('Error occurred:', error);\n *\n * // Use the onion error handler\n * return onionErrorHandler({ error, code, ...context });\n * });\n * ```\n */\nexport function onionErrorHandler({ error }: { error: unknown }): Response {\n const { statusCode, body } = mapErrorToResponse(error);\n\n return new Response(JSON.stringify(body), {\n status: statusCode,\n headers: { 'Content-Type': 'application/json' },\n });\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACkCA,SAAS,aAAa,MAAsB;AAC1C,SAAO,KAAK,QAAQ,gBAAgB,KAAK;AAC3C;AAKA,SAAS,eAAe,SAKR;AACd,QAAM,UAAkC,CAAC;AACzC,aAAW,CAAC,KAAK,KAAK,KAAK,OAAO,QAAQ,QAAQ,OAAO,GAAG;AAC1D,QAAI,SAAS,MAAM;AACjB,cAAQ,IAAI,YAAY,CAAC,IAAI;AAAA,IAC/B;AAAA,EACF;AAEA,QAAM,cAAiD,CAAC;AACxD,aAAW,CAAC,KAAK,KAAK,KAAK,OAAO,QAAQ,QAAQ,KAAK,GAAG;AACxD,QAAI,SAAS,MAAM;AACjB,kBAAY,GAAG,IAAI;AAAA,IACrB;AAAA,EACF;AAEA,SAAO;AAAA,IACL,MAAM,QAAQ;AAAA,IACd;AAAA,IACA;AAAA,IACA,YAAY,QAAQ;AAAA,EACtB;AACF;AAKA,SAAS,eAAe,UAAkC;AACxD,QAAM,UAAkC;AAAA,IACtC,gBAAgB;AAAA,EAClB;AAEA,MAAI,SAAS,SAAS;AACpB,eAAW,CAAC,KAAK,KAAK,KAAK,OAAO,QAAQ,SAAS,OAAO,GAAG;AAC3D,UAAI,SAAS,MAAM;AACjB,gBAAQ,GAAG,IAAI,OAAO,KAAK;AAAA,MAC7B;AAAA,IACF;AAAA,EACF;AAEA,MAAI,SAAS,SAAS,UAAa,SAAS,SAAS,MAAM;AACzD,WAAO,IAAI,SAAS,MAAM;AAAA,MACxB,QAAQ,SAAS;AAAA,MACjB;AAAA,IACF,CAAC;AAAA,EACH;AAEA,MAAI,OAAO,SAAS,SAAS,UAAU;AACrC,YAAQ,cAAc,IAAI;AAC1B,WAAO,IAAI,SAAS,SAAS,MAAM;AAAA,MACjC,QAAQ,SAAS;AAAA,MACjB;AAAA,IACF,CAAC;AAAA,EACH;AAEA,SAAO,IAAI,SAAS,KAAK,UAAU,SAAS,IAAI,GAAG;AAAA,IACjD,QAAQ,SAAS;AAAA,IACjB;AAAA,EACF,CAAC;AACH;AA6GO,SAAS,qBACd,KACA,QACA,SACM;AACN,QAAM,aAAa,MAAM,QAAQ,MAAM,IAAI,SAAS,CAAC,MAAM;AAC3D,QAAM,SAAS,SAAS,UAAU;AAClC,QAAM,cAAc,SAAS,eAAe,CAAC;AAE7C,aAAW,EAAE,UAAU,YAAY,kBAAkB,KAAK,YAAY;AACpE,UAAM,OAAO,SAAS,aAAa,SAAS,IAAI;AAChD,UAAM,SAAS,SAAS,OAAO,YAAY;AAE3C,UAAM,UAAmB,OAAO,YAAY;AAE1C,iBAAW,cAAc,aAAa;AACpC,cAAM,SAAS,MAAM,WAAW,OAAO;AACvC,YAAI,WAAW,OAAW,QAAO;AAAA,MACnC;AAEA,YAAM,aAAa,eAAe,OAA+C;AACjF,YAAM,aAAa,kBAAkB,UAAU;AAC/C,YAAM,cAAc,MAAM,WAAW,QAAQ,UAAU;AACvD,aAAO,eAAe,YAAY,IAAI;AAAA,IACxC;AAEA,YAAQ,QAAQ;AAAA,MACd,KAAK;AACH,YAAI,IAAI,MAAM,OAAO;AACrB;AAAA,MACF,KAAK;AACH,YAAI,KAAK,MAAM,OAAO;AACtB;AAAA,MACF,KAAK;AACH,YAAI,IAAI,MAAM,OAAO;AACrB;AAAA,MACF,KAAK;AACH,YAAI,MAAM,MAAM,OAAO;AACvB;AAAA,MACF,KAAK;AACH,YAAI,OAAO,MAAM,OAAO;AACxB;AAAA,MACF,KAAK;AACH,YAAI,QAAQ,MAAM,OAAO;AACzB;AAAA,MACF,KAAK;AACH,YAAI,KAAK,MAAM,OAAO;AACtB;AAAA,MACF;AACE,cAAM,IAAI,MAAM,4BAA4B,MAAM,EAAE;AAAA,IACxD;AAAA,EACF;AACF;;;ACxOO,IAAe,aAAf,cAAkC,MAAM;AAAA;AAAA,EAE7B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUhB,YAAY;AAAA,IACV;AAAA,IACA;AAAA,IACA;AAAA,EACF,GAIG;AACD,UAAM,OAAO;AACb,SAAK,OAAO,KAAK,YAAY;AAC7B,SAAK,OAAO;AACZ,QAAI,UAAU,QAAW;AACvB,aAAO,eAAe,MAAM,SAAS;AAAA,QACnC,OAAO;AAAA,QACP,UAAU;AAAA,QACV,YAAY;AAAA,QACZ,cAAc;AAAA,MAChB,CAAC;AAAA,IACH;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAwBA,OAAO,UAAU,QAA6B;AAC5C,UAAM,IAAI,MAAM,GAAG,KAAK,IAAI,8CAA8C;AAAA,EAC5E;AACF;;;ACrEO,IAAM,aAAa;AAAA;AAAA;AAAA;AAAA;AAAA,EAKxB,QAAQ;AAAA;AAAA,IAEN,cAAc;AAAA;AAAA,IAEd,qBAAqB;AAAA;AAAA,IAErB,cAAc;AAAA,EAChB;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,KAAK;AAAA;AAAA,IAEH,gBAAgB;AAAA;AAAA,IAEhB,WAAW;AAAA;AAAA,IAEX,UAAU;AAAA;AAAA,IAEV,eAAe;AAAA,EACjB;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,OAAO;AAAA;AAAA,IAEL,aAAa;AAAA;AAAA,IAEb,UAAU;AAAA;AAAA,IAEV,eAAe;AAAA;AAAA,IAEf,eAAe;AAAA;AAAA,IAEf,wBAAwB;AAAA,EAC1B;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,cAAc;AAAA;AAAA,IAEZ,kBAAkB;AAAA;AAAA,IAElB,eAAe;AAAA;AAAA,IAEf,iBAAiB;AAAA,EACnB;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,QAAQ;AAAA;AAAA,IAEN,yBAAyB;AAAA,EAC3B;AACF;;;AC3DO,IAAM,wBAAN,MAAM,+BAA8B,WAAW;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQpD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAWA,YAAY;AAAA,IACV;AAAA,IACA,OAAO,WAAW,OAAO;AAAA,IACzB;AAAA,IACA;AAAA,EACF,GAKG;AACD,UAAM,EAAE,SAAS,MAAM,MAAM,CAAC;AAC9B,SAAK,mBAAmB;AAAA,EAC1B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,OAAgB,UAAU,OAAuC;AAC/D,WAAO,IAAI,uBAAsB;AAAA,MAC/B,SAAS,iBAAiB,QAAQ,MAAM,UAAU;AAAA,MAClD;AAAA,MACA,kBAAkB,CAAC;AAAA,IACrB,CAAC;AAAA,EACH;AACF;;;ACjDO,IAAM,cAAN,MAAM,qBAAoB,WAAW;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAS1C,YAAY;AAAA,IACV;AAAA,IACA,OAAO,WAAW,OAAO;AAAA,IACzB;AAAA,EACF,GAIG;AACD,UAAM,EAAE,SAAS,MAAM,MAAM,CAAC;AAAA,EAChC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,OAAgB,UAAU,OAA6B;AACrD,WAAO,IAAI,aAAY;AAAA,MACrB,SAAS,iBAAiB,QAAQ,MAAM,UAAU;AAAA,MAClD;AAAA,IACF,CAAC;AAAA,EACH;AACF;;;AC/BO,IAAM,eAAN,MAAM,sBAAqB,WAAW;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAS3C,YAAY;AAAA,IACV;AAAA,IACA,OAAO,WAAW,IAAI;AAAA,IACtB;AAAA,EACF,GAIG;AACD,UAAM,EAAE,SAAS,MAAM,MAAM,CAAC;AAAA,EAChC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,OAAgB,UAAU,OAA8B;AACtD,WAAO,IAAI,cAAa;AAAA,MACtB,SAAS,iBAAiB,QAAQ,MAAM,UAAU;AAAA,MAClD;AAAA,IACF,CAAC;AAAA,EACH;AACF;;;ACrCO,IAAM,gBAAN,MAAM,uBAAsB,aAAa;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAS9C,YAAY;AAAA,IACV;AAAA,IACA,OAAO,WAAW,IAAI;AAAA,IACtB;AAAA,EACF,GAIG;AACD,UAAM,EAAE,SAAS,MAAM,MAAM,CAAC;AAAA,EAChC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,OAAgB,UAAU,OAA+B;AACvD,WAAO,IAAI,eAAc;AAAA,MACvB,SAAS,iBAAiB,QAAQ,MAAM,UAAU;AAAA,MAClD;AAAA,IACF,CAAC;AAAA,EACH;AACF;;;ACjCO,IAAM,gBAAN,MAAM,uBAAsB,aAAa;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAS9C,YAAY;AAAA,IACV;AAAA,IACA,OAAO,WAAW,IAAI;AAAA,IACtB;AAAA,EACF,GAIG;AACD,UAAM,EAAE,SAAS,MAAM,MAAM,CAAC;AAAA,EAChC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,OAAgB,UAAU,OAA+B;AACvD,WAAO,IAAI,eAAc;AAAA,MACvB,SAAS,iBAAiB,QAAQ,MAAM,UAAU;AAAA,MAClD;AAAA,IACF,CAAC;AAAA,EACH;AACF;;;AClCO,IAAM,qBAAN,MAAM,4BAA2B,aAAa;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASnD,YAAY;AAAA,IACV;AAAA,IACA,OAAO,WAAW,IAAI;AAAA,IACtB;AAAA,EACF,GAIG;AACD,UAAM,EAAE,SAAS,MAAM,MAAM,CAAC;AAAA,EAChC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,OAAgB,UAAU,OAAoC;AAC5D,WAAO,IAAI,oBAAmB;AAAA,MAC5B,SAAS,iBAAiB,QAAQ,MAAM,UAAU;AAAA,MAClD;AAAA,IACF,CAAC;AAAA,EACH;AACF;;;ACzBO,IAAM,aAAN,MAAM,oBAAmB,WAAW;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASzC,YAAY;AAAA,IACV;AAAA,IACA,OAAO,WAAW,MAAM;AAAA,IACxB;AAAA,EACF,GAIG;AACD,UAAM,EAAE,SAAS,MAAM,MAAM,CAAC;AAAA,EAChC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,OAAgB,UAAU,OAA4B;AACpD,WAAO,IAAI,YAAW;AAAA,MACpB,SAAS,iBAAiB,QAAQ,MAAM,UAAU;AAAA,MAClD;AAAA,IACF,CAAC;AAAA,EACH;AACF;;;ACpCO,IAAM,kBAAN,MAAM,yBAAwB,WAAW;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAS9C,YAAY;AAAA,IACV;AAAA,IACA,OAAO,WAAW,aAAa;AAAA,IAC/B;AAAA,EACF,GAIG;AACD,UAAM,EAAE,SAAS,MAAM,MAAM,CAAC;AAAA,EAChC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,OAAgB,UAAU,OAAiC;AACzD,WAAO,IAAI,iBAAgB;AAAA,MACzB,SAAS,iBAAiB,QAAQ,MAAM,UAAU;AAAA,MAClD;AAAA,IACF,CAAC;AAAA,EACH;AACF;;;ACvBO,IAAM,oBAAN,MAAM,2BAA0B,WAAW;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAShD,YAAY;AAAA,IACV;AAAA,IACA,OAAO,WAAW,aAAa;AAAA,IAC/B;AAAA,EACF,GAIG;AACD,UAAM,EAAE,SAAS,MAAM,MAAM,CAAC;AAAA,EAChC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,OAAgB,UAAU,OAAmC;AAC3D,WAAO,IAAI,mBAAkB;AAAA,MAC3B,SAAS,iBAAiB,QAAQ,MAAM,UAAU;AAAA,MAClD;AAAA,IACF,CAAC;AAAA,EACH;AACF;;;ACjCO,IAAM,sBAAN,MAAM,6BAA4B,WAAW;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQzC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAWT,YAAY;AAAA,IACV;AAAA,IACA,OAAO,WAAW,aAAa;AAAA,IAC/B;AAAA,IACA;AAAA,EACF,GAKG;AACD,UAAM,EAAE,SAAS,MAAM,MAAM,CAAC;AAC9B,SAAK,mBAAmB;AAAA,EAC1B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,OAAgB,UAAU,OAAqC;AAC7D,WAAO,IAAI,qBAAoB;AAAA,MAC7B,SAAS,iBAAiB,QAAQ,MAAM,UAAU;AAAA,MAClD;AAAA,MACA,kBAAkB,CAAC;AAAA,IACrB,CAAC;AAAA,EACH;AACF;;;AC7BO,SAAS,mBAAmB,OAAqC;AAEtE,MAAI,iBAAiB,uBAAuB;AAC1C,WAAO;AAAA,MACL,YAAY;AAAA,MACZ,MAAM;AAAA,QACJ,SAAS,MAAM;AAAA,QACf,WAAW,MAAM;AAAA,QACjB,YAAY,MAAM,iBAAiB,IAAI,CAAC,OAAO;AAAA,UAC7C,MAAM,EAAE;AAAA,UACR,SAAS,EAAE;AAAA,QACb,EAAE;AAAA,MACJ;AAAA,IACF;AAAA,EACF;AAEA,MAAI,iBAAiB,qBAAqB;AACxC,WAAO;AAAA,MACL,YAAY;AAAA,MACZ,MAAM;AAAA,QACJ,SAAS,MAAM;AAAA,QACf,WAAW,MAAM;AAAA,QACjB,YAAY,MAAM,iBAAiB,IAAI,CAAC,OAAO;AAAA,UAC7C,MAAM,EAAE;AAAA,UACR,SAAS,EAAE;AAAA,QACb,EAAE;AAAA,MACJ;AAAA,IACF;AAAA,EACF;AAGA,MAAI,iBAAiB,mBAAmB;AACtC,WAAO;AAAA,MACL,YAAY;AAAA,MACZ,MAAM;AAAA,QACJ,SAAS,MAAM;AAAA,QACf,WAAW,MAAM;AAAA,MACnB;AAAA,IACF;AAAA,EACF;AAGA,MAAI,iBAAiB,eAAe;AAClC,WAAO;AAAA,MACL,YAAY;AAAA,MACZ,MAAM;AAAA,QACJ,SAAS,MAAM;AAAA,QACf,WAAW,MAAM;AAAA,MACnB;AAAA,IACF;AAAA,EACF;AAEA,MAAI,iBAAiB,eAAe;AAClC,WAAO;AAAA,MACL,YAAY;AAAA,MACZ,MAAM;AAAA,QACJ,SAAS,MAAM;AAAA,QACf,WAAW,MAAM;AAAA,MACnB;AAAA,IACF;AAAA,EACF;AAEA,MAAI,iBAAiB,oBAAoB;AACvC,WAAO;AAAA,MACL,YAAY;AAAA,MACZ,MAAM;AAAA,QACJ,SAAS,MAAM;AAAA,QACf,WAAW,MAAM;AAAA,MACnB;AAAA,IACF;AAAA,EACF;AAGA,MAAI,iBAAiB,cAAc;AACjC,WAAO;AAAA,MACL,YAAY;AAAA,MACZ,MAAM;AAAA,QACJ,SAAS,MAAM;AAAA,QACf,WAAW,MAAM;AAAA,MACnB;AAAA,IACF;AAAA,EACF;AAGA,MAAI,iBAAiB,aAAa;AAChC,WAAO;AAAA,MACL,YAAY;AAAA,MACZ,MAAM;AAAA,QACJ,SAAS;AAAA,QACT,WAAW;AAAA,MACb;AAAA,IACF;AAAA,EACF;AAGA,MAAI,iBAAiB,YAAY;AAC/B,WAAO;AAAA,MACL,YAAY;AAAA,MACZ,MAAM;AAAA,QACJ,SAAS;AAAA,QACT,WAAW;AAAA,MACb;AAAA,IACF;AAAA,EACF;AAGA,MAAI,iBAAiB,iBAAiB;AACpC,WAAO;AAAA,MACL,YAAY;AAAA,MACZ,MAAM;AAAA,QACJ,SAAS;AAAA,QACT,WAAW;AAAA,MACb;AAAA,IACF;AAAA,EACF;AAGA,MAAI,iBAAiB,YAAY;AAC/B,WAAO;AAAA,MACL,YAAY;AAAA,MACZ,MAAM;AAAA,QACJ,SAAS;AAAA,QACT,WAAW;AAAA,MACb;AAAA,IACF;AAAA,EACF;AAGA,SAAO;AAAA,IACL,YAAY;AAAA,IACZ,MAAM;AAAA,MACJ,SAAS;AAAA,MACT,WAAW;AAAA,IACb;AAAA,EACF;AACF;;;AChKO,SAAS,kBAAkB,EAAE,MAAM,GAAiC;AACzE,QAAM,EAAE,YAAY,KAAK,IAAI,mBAAmB,KAAK;AAErD,SAAO,IAAI,SAAS,KAAK,UAAU,IAAI,GAAG;AAAA,IACxC,QAAQ;AAAA,IACR,SAAS,EAAE,gBAAgB,mBAAmB;AAAA,EAChD,CAAC;AACH;","names":[]}
@@ -0,0 +1,208 @@
1
+ import { Elysia } from 'elysia';
2
+ import { B as BaseDto } from '../../base-dto.class-D7W9iqoU.cjs';
3
+ import { C as Controller, a as HttpResponse } from '../../http-response-BAhi8lF4.cjs';
4
+ import { R as RouteInput } from '../../routing.type-DF2BIL7x.cjs';
5
+
6
+ /**
7
+ * Controller that works with a validated request DTO and returns HttpResponse.
8
+ */
9
+ type HttpController<TRequestDto extends BaseDto<unknown> = BaseDto<unknown>> = Controller<TRequestDto, HttpResponse>;
10
+ /**
11
+ * Elysia beforeHandle middleware type.
12
+ * Returns undefined to continue, or a Response to short-circuit.
13
+ */
14
+ type ElysiaMiddleware = (context: {
15
+ body: unknown;
16
+ headers: Record<string, string | undefined>;
17
+ query: Record<string, string | undefined>;
18
+ params: Record<string, string>;
19
+ }) => Response | undefined | Promise<Response | undefined>;
20
+ /**
21
+ * Route input type that accepts either a single route or an array of routes.
22
+ */
23
+ type RouteInputOrArray = RouteInput | RouteInput[];
24
+ /**
25
+ * Options for registering routes.
26
+ */
27
+ interface RegisterRoutesOptions {
28
+ /**
29
+ * Prefix to apply to all routes in this registration.
30
+ *
31
+ * @example
32
+ * ```typescript
33
+ * registerElysiaRoutes(app, userRoutes, {
34
+ * prefix: '/api/v1',
35
+ * });
36
+ * // Routes will be: /api/v1/users, /api/v1/users/:id, etc.
37
+ * ```
38
+ */
39
+ prefix?: string;
40
+ /**
41
+ * Middlewares (beforeHandle hooks) to apply to all routes in this registration.
42
+ * These run before the controller handler.
43
+ *
44
+ * @example
45
+ * ```typescript
46
+ * registerElysiaRoutes(app, userRoutes, {
47
+ * middlewares: [
48
+ * ({ headers }) => {
49
+ * if (!headers.authorization) {
50
+ * return new Response('Unauthorized', { status: 401 });
51
+ * }
52
+ * },
53
+ * ],
54
+ * });
55
+ * ```
56
+ */
57
+ middlewares?: ElysiaMiddleware[];
58
+ }
59
+ /**
60
+ * Registers routes onto an Elysia app.
61
+ *
62
+ * Accepts either a single route or an array of routes. Can be called multiple
63
+ * times to register routes from different domains/modules.
64
+ *
65
+ * @param app - The Elysia app instance (passed by reference)
66
+ * @param routes - A single route or an array of routes to register
67
+ * @param options - Optional configuration including prefix
68
+ *
69
+ * @example Single route
70
+ * ```typescript
71
+ * const app = new Elysia();
72
+ *
73
+ * registerElysiaRoutes(app, {
74
+ * metadata: { path: '/health', method: 'GET' },
75
+ * controller: healthController,
76
+ * });
77
+ * ```
78
+ *
79
+ * @example Multiple routes
80
+ * ```typescript
81
+ * const app = new Elysia();
82
+ *
83
+ * registerElysiaRoutes(app, [
84
+ * { metadata: { path: '/users', method: 'POST' }, controller: createUserController },
85
+ * { metadata: { path: '/users/{id}', method: 'GET' }, controller: getUserController },
86
+ * { metadata: { path: '/users/{id}', method: 'DELETE' }, controller: deleteUserController },
87
+ * ]);
88
+ * ```
89
+ *
90
+ * @example With prefix
91
+ * ```typescript
92
+ * registerElysiaRoutes(app, userRoutes, {
93
+ * prefix: '/api/v1',
94
+ * });
95
+ * ```
96
+ *
97
+ * @example With middlewares
98
+ * ```typescript
99
+ * registerElysiaRoutes(app, protectedRoutes, {
100
+ * middlewares: [
101
+ * ({ headers }) => {
102
+ * if (!headers.authorization) {
103
+ * return new Response('Unauthorized', { status: 401 });
104
+ * }
105
+ * },
106
+ * ],
107
+ * });
108
+ * ```
109
+ *
110
+ * @example Registering from multiple domains
111
+ * ```typescript
112
+ * const app = new Elysia();
113
+ *
114
+ * // Public routes
115
+ * registerElysiaRoutes(app, publicRoutes);
116
+ *
117
+ * // API routes with prefix
118
+ * registerElysiaRoutes(app, userRoutes, { prefix: '/api' });
119
+ * registerElysiaRoutes(app, orderRoutes, { prefix: '/api' });
120
+ *
121
+ * export default app;
122
+ * ```
123
+ */
124
+ declare function registerElysiaRoutes(app: Elysia, routes: RouteInputOrArray, options?: RegisterRoutesOptions): void;
125
+
126
+ /**
127
+ * Error item for field-level validation errors.
128
+ */
129
+ interface ErrorItem {
130
+ item: string;
131
+ message: string;
132
+ }
133
+ /**
134
+ * Standard error response body.
135
+ */
136
+ interface ErrorResponseBody {
137
+ message: string;
138
+ errorCode: string;
139
+ errorItems?: ErrorItem[];
140
+ }
141
+ /**
142
+ * Mapped error response with status code and body.
143
+ */
144
+ interface MappedErrorResponse {
145
+ statusCode: number;
146
+ body: ErrorResponseBody;
147
+ }
148
+ /**
149
+ * Maps our error hierarchy to HTTP status codes and response bodies.
150
+ *
151
+ * Mapping strategy:
152
+ * - `ObjectValidationError` → 400 Bad Request
153
+ * - `InvalidRequestError` → 400 Bad Request
154
+ * - `AccessDeniedError` → 403 Forbidden
155
+ * - `NotFoundError` → 404 Not Found
156
+ * - `ConflictError` → 409 Conflict
157
+ * - `UnprocessableError` → 422 Unprocessable Entity
158
+ * - `UseCaseError` (other) → 400 Bad Request
159
+ * - `DomainError` → 500 Internal Server Error (masked)
160
+ * - `InfraError` → 500 Internal Server Error (masked)
161
+ * - `ControllerError` → 500 Internal Server Error (masked)
162
+ * - Unknown → 500 Internal Server Error (masked)
163
+ *
164
+ * **Security Note:** Domain and infrastructure errors are masked to avoid
165
+ * leaking internal implementation details.
166
+ *
167
+ * @param error - The error to map
168
+ * @returns Mapped error response with status code and body
169
+ */
170
+ declare function mapErrorToResponse(error: unknown): MappedErrorResponse;
171
+
172
+ /**
173
+ * Elysia error handler that maps domain errors to HTTP responses.
174
+ *
175
+ * Apply this to your Elysia app using `.onError()` to automatically
176
+ * convert domain/use-case errors to appropriate HTTP responses.
177
+ *
178
+ * @example
179
+ * ```typescript
180
+ * import { Elysia } from 'elysia';
181
+ * import { registerElysiaRoutes, onionErrorHandler } from '@cosmneo/onion-lasagna/backend/frameworks/elysia';
182
+ *
183
+ * const app = new Elysia()
184
+ * .onError(onionErrorHandler)
185
+ * .get('/health', () => ({ status: 'ok' }));
186
+ *
187
+ * registerElysiaRoutes(app, routes);
188
+ *
189
+ * export default app;
190
+ * ```
191
+ *
192
+ * @example With custom error logging
193
+ * ```typescript
194
+ * const app = new Elysia()
195
+ * .onError(({ error, code, ...context }) => {
196
+ * // Log the error
197
+ * console.error('Error occurred:', error);
198
+ *
199
+ * // Use the onion error handler
200
+ * return onionErrorHandler({ error, code, ...context });
201
+ * });
202
+ * ```
203
+ */
204
+ declare function onionErrorHandler({ error }: {
205
+ error: unknown;
206
+ }): Response;
207
+
208
+ export { type ElysiaMiddleware, type ErrorResponseBody, type HttpController, type MappedErrorResponse, type RegisterRoutesOptions, type RouteInputOrArray, mapErrorToResponse, onionErrorHandler, registerElysiaRoutes };
@@ -0,0 +1,208 @@
1
+ import { Elysia } from 'elysia';
2
+ import { B as BaseDto } from '../../base-dto.class-D7W9iqoU.js';
3
+ import { C as Controller, a as HttpResponse } from '../../http-response-BAhi8lF4.js';
4
+ import { R as RouteInput } from '../../routing.type-DB4pt-d9.js';
5
+
6
+ /**
7
+ * Controller that works with a validated request DTO and returns HttpResponse.
8
+ */
9
+ type HttpController<TRequestDto extends BaseDto<unknown> = BaseDto<unknown>> = Controller<TRequestDto, HttpResponse>;
10
+ /**
11
+ * Elysia beforeHandle middleware type.
12
+ * Returns undefined to continue, or a Response to short-circuit.
13
+ */
14
+ type ElysiaMiddleware = (context: {
15
+ body: unknown;
16
+ headers: Record<string, string | undefined>;
17
+ query: Record<string, string | undefined>;
18
+ params: Record<string, string>;
19
+ }) => Response | undefined | Promise<Response | undefined>;
20
+ /**
21
+ * Route input type that accepts either a single route or an array of routes.
22
+ */
23
+ type RouteInputOrArray = RouteInput | RouteInput[];
24
+ /**
25
+ * Options for registering routes.
26
+ */
27
+ interface RegisterRoutesOptions {
28
+ /**
29
+ * Prefix to apply to all routes in this registration.
30
+ *
31
+ * @example
32
+ * ```typescript
33
+ * registerElysiaRoutes(app, userRoutes, {
34
+ * prefix: '/api/v1',
35
+ * });
36
+ * // Routes will be: /api/v1/users, /api/v1/users/:id, etc.
37
+ * ```
38
+ */
39
+ prefix?: string;
40
+ /**
41
+ * Middlewares (beforeHandle hooks) to apply to all routes in this registration.
42
+ * These run before the controller handler.
43
+ *
44
+ * @example
45
+ * ```typescript
46
+ * registerElysiaRoutes(app, userRoutes, {
47
+ * middlewares: [
48
+ * ({ headers }) => {
49
+ * if (!headers.authorization) {
50
+ * return new Response('Unauthorized', { status: 401 });
51
+ * }
52
+ * },
53
+ * ],
54
+ * });
55
+ * ```
56
+ */
57
+ middlewares?: ElysiaMiddleware[];
58
+ }
59
+ /**
60
+ * Registers routes onto an Elysia app.
61
+ *
62
+ * Accepts either a single route or an array of routes. Can be called multiple
63
+ * times to register routes from different domains/modules.
64
+ *
65
+ * @param app - The Elysia app instance (passed by reference)
66
+ * @param routes - A single route or an array of routes to register
67
+ * @param options - Optional configuration including prefix
68
+ *
69
+ * @example Single route
70
+ * ```typescript
71
+ * const app = new Elysia();
72
+ *
73
+ * registerElysiaRoutes(app, {
74
+ * metadata: { path: '/health', method: 'GET' },
75
+ * controller: healthController,
76
+ * });
77
+ * ```
78
+ *
79
+ * @example Multiple routes
80
+ * ```typescript
81
+ * const app = new Elysia();
82
+ *
83
+ * registerElysiaRoutes(app, [
84
+ * { metadata: { path: '/users', method: 'POST' }, controller: createUserController },
85
+ * { metadata: { path: '/users/{id}', method: 'GET' }, controller: getUserController },
86
+ * { metadata: { path: '/users/{id}', method: 'DELETE' }, controller: deleteUserController },
87
+ * ]);
88
+ * ```
89
+ *
90
+ * @example With prefix
91
+ * ```typescript
92
+ * registerElysiaRoutes(app, userRoutes, {
93
+ * prefix: '/api/v1',
94
+ * });
95
+ * ```
96
+ *
97
+ * @example With middlewares
98
+ * ```typescript
99
+ * registerElysiaRoutes(app, protectedRoutes, {
100
+ * middlewares: [
101
+ * ({ headers }) => {
102
+ * if (!headers.authorization) {
103
+ * return new Response('Unauthorized', { status: 401 });
104
+ * }
105
+ * },
106
+ * ],
107
+ * });
108
+ * ```
109
+ *
110
+ * @example Registering from multiple domains
111
+ * ```typescript
112
+ * const app = new Elysia();
113
+ *
114
+ * // Public routes
115
+ * registerElysiaRoutes(app, publicRoutes);
116
+ *
117
+ * // API routes with prefix
118
+ * registerElysiaRoutes(app, userRoutes, { prefix: '/api' });
119
+ * registerElysiaRoutes(app, orderRoutes, { prefix: '/api' });
120
+ *
121
+ * export default app;
122
+ * ```
123
+ */
124
+ declare function registerElysiaRoutes(app: Elysia, routes: RouteInputOrArray, options?: RegisterRoutesOptions): void;
125
+
126
+ /**
127
+ * Error item for field-level validation errors.
128
+ */
129
+ interface ErrorItem {
130
+ item: string;
131
+ message: string;
132
+ }
133
+ /**
134
+ * Standard error response body.
135
+ */
136
+ interface ErrorResponseBody {
137
+ message: string;
138
+ errorCode: string;
139
+ errorItems?: ErrorItem[];
140
+ }
141
+ /**
142
+ * Mapped error response with status code and body.
143
+ */
144
+ interface MappedErrorResponse {
145
+ statusCode: number;
146
+ body: ErrorResponseBody;
147
+ }
148
+ /**
149
+ * Maps our error hierarchy to HTTP status codes and response bodies.
150
+ *
151
+ * Mapping strategy:
152
+ * - `ObjectValidationError` → 400 Bad Request
153
+ * - `InvalidRequestError` → 400 Bad Request
154
+ * - `AccessDeniedError` → 403 Forbidden
155
+ * - `NotFoundError` → 404 Not Found
156
+ * - `ConflictError` → 409 Conflict
157
+ * - `UnprocessableError` → 422 Unprocessable Entity
158
+ * - `UseCaseError` (other) → 400 Bad Request
159
+ * - `DomainError` → 500 Internal Server Error (masked)
160
+ * - `InfraError` → 500 Internal Server Error (masked)
161
+ * - `ControllerError` → 500 Internal Server Error (masked)
162
+ * - Unknown → 500 Internal Server Error (masked)
163
+ *
164
+ * **Security Note:** Domain and infrastructure errors are masked to avoid
165
+ * leaking internal implementation details.
166
+ *
167
+ * @param error - The error to map
168
+ * @returns Mapped error response with status code and body
169
+ */
170
+ declare function mapErrorToResponse(error: unknown): MappedErrorResponse;
171
+
172
+ /**
173
+ * Elysia error handler that maps domain errors to HTTP responses.
174
+ *
175
+ * Apply this to your Elysia app using `.onError()` to automatically
176
+ * convert domain/use-case errors to appropriate HTTP responses.
177
+ *
178
+ * @example
179
+ * ```typescript
180
+ * import { Elysia } from 'elysia';
181
+ * import { registerElysiaRoutes, onionErrorHandler } from '@cosmneo/onion-lasagna/backend/frameworks/elysia';
182
+ *
183
+ * const app = new Elysia()
184
+ * .onError(onionErrorHandler)
185
+ * .get('/health', () => ({ status: 'ok' }));
186
+ *
187
+ * registerElysiaRoutes(app, routes);
188
+ *
189
+ * export default app;
190
+ * ```
191
+ *
192
+ * @example With custom error logging
193
+ * ```typescript
194
+ * const app = new Elysia()
195
+ * .onError(({ error, code, ...context }) => {
196
+ * // Log the error
197
+ * console.error('Error occurred:', error);
198
+ *
199
+ * // Use the onion error handler
200
+ * return onionErrorHandler({ error, code, ...context });
201
+ * });
202
+ * ```
203
+ */
204
+ declare function onionErrorHandler({ error }: {
205
+ error: unknown;
206
+ }): Response;
207
+
208
+ export { type ElysiaMiddleware, type ErrorResponseBody, type HttpController, type MappedErrorResponse, type RegisterRoutesOptions, type RouteInputOrArray, mapErrorToResponse, onionErrorHandler, registerElysiaRoutes };