@cosmneo/onion-lasagna 0.2.0 → 0.2.1

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 (45) hide show
  1. package/dist/{chunk-GGSAAZPM.js → chunk-AUMHMWDD.js} +19 -20
  2. package/dist/chunk-AUMHMWDD.js.map +1 -0
  3. package/dist/chunk-H5TNDC5U.js +138 -0
  4. package/dist/chunk-H5TNDC5U.js.map +1 -0
  5. package/dist/chunk-MF2JDREK.js +168 -0
  6. package/dist/chunk-MF2JDREK.js.map +1 -0
  7. package/dist/{chunk-PUVAB3JX.js → chunk-XIRJ73IO.js} +38 -36
  8. package/dist/chunk-XIRJ73IO.js.map +1 -0
  9. package/dist/{chunk-DS7TE6KZ.js → chunk-XP6PLTV2.js} +11 -3
  10. package/dist/chunk-XP6PLTV2.js.map +1 -0
  11. package/dist/global.js +3 -3
  12. package/dist/http/index.cjs +563 -93
  13. package/dist/http/index.cjs.map +1 -1
  14. package/dist/http/index.d.cts +4 -3
  15. package/dist/http/index.d.ts +4 -3
  16. package/dist/http/index.js +30 -12
  17. package/dist/http/openapi/index.cjs +43 -35
  18. package/dist/http/openapi/index.cjs.map +1 -1
  19. package/dist/http/openapi/index.d.cts +8 -34
  20. package/dist/http/openapi/index.d.ts +8 -34
  21. package/dist/http/openapi/index.js +2 -2
  22. package/dist/http/route/index.cjs +106 -9
  23. package/dist/http/route/index.cjs.map +1 -1
  24. package/dist/http/route/index.d.cts +133 -227
  25. package/dist/http/route/index.d.ts +133 -227
  26. package/dist/http/route/index.js +5 -2
  27. package/dist/http/server/index.cjs +24 -19
  28. package/dist/http/server/index.cjs.map +1 -1
  29. package/dist/http/server/index.d.cts +1 -1
  30. package/dist/http/server/index.d.ts +1 -1
  31. package/dist/http/server/index.js +2 -2
  32. package/dist/http/shared/index.cjs.map +1 -1
  33. package/dist/http/shared/index.d.cts +10 -14
  34. package/dist/http/shared/index.d.ts +10 -14
  35. package/dist/http/shared/index.js +11 -127
  36. package/dist/http/shared/index.js.map +1 -1
  37. package/dist/index.js +6 -6
  38. package/dist/{router-definition.type-ynBhT16T.d.cts → router-definition.type-BElX-Pl4.d.cts} +169 -256
  39. package/dist/{router-definition.type-DORVlLNk.d.ts → router-definition.type-DxG8ncJZ.d.ts} +169 -256
  40. package/package.json +1 -1
  41. package/dist/chunk-BZULBF4N.js +0 -82
  42. package/dist/chunk-BZULBF4N.js.map +0 -1
  43. package/dist/chunk-DS7TE6KZ.js.map +0 -1
  44. package/dist/chunk-GGSAAZPM.js.map +0 -1
  45. package/dist/chunk-PUVAB3JX.js.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/presentation/http/index.ts","../../src/presentation/http/route/define-route.ts","../../src/presentation/http/route/types/path-params.type.ts","../../src/presentation/http/route/types/router-definition.type.ts","../../src/presentation/http/route/define-router.ts","../../src/presentation/http/schema/types/validation.type.ts","../../src/presentation/http/schema/types/schema-adapter.type.ts","../../src/presentation/http/server/types.ts","../../src/global/exceptions/coded-error.error.ts","../../src/global/exceptions/error-codes.const.ts","../../src/presentation/exceptions/invalid-request.error.ts","../../src/presentation/exceptions/controller.error.ts","../../src/app/exceptions/use-case.error.ts","../../src/app/exceptions/unauthorized.error.ts","../../src/global/utils/wrap-error.util.ts","../../src/presentation/http/server/create-server-routes.ts","../../src/presentation/http/server/server-routes-builder.ts","../../src/presentation/http/openapi/generate.ts"],"sourcesContent":["/**\n * @fileoverview Unified Route System\n *\n * A comprehensive system for defining routes that powers:\n * - Type-safe client generation\n * - Server-side route registration with automatic validation\n * - OpenAPI specification generation\n *\n * @module unified\n *\n * @example Complete workflow\n * ```typescript\n * // 1. Define schemas (in infra layer)\n * import { z } from 'zod';\n * import { zodSchema } from '@cosmneo/onion-lasagna/http/schema/zod';\n *\n * const userSchema = zodSchema(z.object({\n * id: z.string().uuid(),\n * name: z.string().min(1).max(100),\n * email: z.string().email(),\n * }));\n *\n * // 2. Define routes\n * import { defineRoute, defineRouter } from '@cosmneo/onion-lasagna/http';\n *\n * const getUser = defineRoute({\n * method: 'GET',\n * path: '/api/users/:userId',\n * responses: {\n * 200: { description: 'User found', schema: userSchema },\n * 404: { description: 'User not found' },\n * },\n * docs: { summary: 'Get a user by ID', tags: ['Users'] },\n * });\n *\n * const api = defineRouter({\n * users: { get: getUser, list: listUsers, create: createUser },\n * });\n *\n * // 3. Create client (frontend)\n * import { createClient } from '@cosmneo/onion-lasagna-client';\n *\n * const client = createClient(api, { baseUrl: 'http://localhost:3000' });\n * const user = await client.users.get({ pathParams: { userId: '123' } });\n *\n * // 4. Create server routes (backend)\n * import { serverRoutes } from '@cosmneo/onion-lasagna/http/server';\n *\n * const routes = serverRoutes(api)\n * .handle('users.get', {\n * handler: async (req) => {\n * const user = await db.users.findById(req.pathParams.userId);\n * return user\n * ? { status: 200, body: user }\n * : { status: 404, body: { error: 'Not found' } };\n * },\n * })\n * .build();\n *\n * // 5. Generate OpenAPI (documentation)\n * import { generateOpenAPI } from '@cosmneo/onion-lasagna/http/openapi';\n *\n * const spec = generateOpenAPI(api, {\n * info: { title: 'My API', version: '1.0.0' },\n * });\n * ```\n */\n\n// ============================================================================\n// Route Definition\n// ============================================================================\n\nexport { defineRoute } from './route/define-route';\nexport { defineRouter, mergeRouters } from './route/define-router';\nexport type { DefineRouterOptions } from './route/define-router';\n\n// Route types\nexport type {\n HttpMethod,\n HttpStatusCode,\n ContentType,\n PathParams,\n HasPathParams,\n ExtractPathParamNames,\n RouteDefinition,\n RouteDefinitionInput,\n RequestBodyConfig,\n QueryParamsConfig,\n PathParamsConfig,\n HeadersConfig,\n ResponseConfig,\n ResponsesConfig,\n RouteDocumentation,\n RouterConfig,\n RouterDefinition,\n RouterEntry,\n RouterKeys,\n GetRoute,\n FlattenRouter,\n DeepMergeTwo,\n DeepMergeAll,\n PrettifyDeep,\n InferRouteBody,\n InferRouteQuery,\n InferRoutePathParams,\n InferRouteHeaders,\n InferRouteResponse,\n InferRouteSuccessResponse,\n InferRouteMethod,\n InferRoutePath,\n} from './route/types';\n\nexport {\n isRouteDefinition,\n isRouterDefinition,\n collectRoutes,\n buildPath,\n normalizePath,\n pathToRegex,\n getPathParamNames,\n hasPathParams,\n} from './route/types';\n\n// ============================================================================\n// Schema\n// ============================================================================\n\nexport type {\n SchemaAdapter,\n JsonSchema,\n JsonSchemaOptions,\n ValidationResult,\n ValidationIssue,\n ValidationSuccess,\n ValidationFailure,\n InferOutput,\n InferInput,\n} from './schema/types';\n\nexport {\n isSchemaAdapter,\n isValidationSuccess,\n isValidationFailure,\n createPassthroughAdapter,\n createRejectingAdapter,\n} from './schema/types';\n\n// Schema adapters are exported from submodules:\n// - @cosmneo/onion-lasagna/http/schema/zod\n// - @cosmneo/onion-lasagna/http/schema/typebox\n\n// ============================================================================\n// Server\n// ============================================================================\n\nexport { serverRoutes } from './server/server-routes-builder';\nexport type {\n ServerRoutesBuilder,\n MissingHandlersError,\n BuilderHandlerConfig,\n} from './server/server-routes-builder';\nexport type {\n UseCasePort,\n ValidatedRequest,\n HandlerContext,\n HandlerResponse,\n RouteHandlerConfig,\n MiddlewareFunction,\n ServerRoutesConfig,\n CreateServerRoutesOptions,\n UnifiedRouteInput,\n RawHttpRequest,\n} from './server/types';\n\n// ============================================================================\n// OpenAPI\n// ============================================================================\n\nexport { generateOpenAPI } from './openapi/generate';\nexport type {\n OpenAPIConfig,\n OpenAPISpec,\n OpenAPIInfo,\n OpenAPIServer,\n OpenAPISecurityScheme,\n OpenAPITag,\n} from './openapi/types';\n","/**\n * @fileoverview Factory function for creating route definitions.\n *\n * The `defineRoute` function is the main entry point for defining routes\n * in the unified system. It provides type inference and validation\n * for route configurations.\n *\n * @module unified/route/define-route\n */\n\nimport type { SchemaAdapter, InferOutput } from '../schema/types';\nimport type { HttpMethod, ResponsesConfig, RouteDefinition, PathParams } from './types';\n\n// ============================================================================\n// Input Types\n// ============================================================================\n\n/**\n * Request body configuration input.\n */\ninterface BodyInput<TSchema extends SchemaAdapter> {\n readonly schema: TSchema;\n readonly contentType?: string;\n readonly required?: boolean;\n readonly description?: string;\n}\n\n/**\n * Query parameters configuration input.\n */\ninterface QueryInput<TSchema extends SchemaAdapter> {\n readonly schema: TSchema;\n readonly description?: string;\n}\n\n/**\n * Path parameters configuration input.\n */\ninterface ParamsInput<TSchema extends SchemaAdapter> {\n readonly schema: TSchema;\n readonly description?: string;\n}\n\n/**\n * Headers configuration input.\n */\ninterface HeadersInput<TSchema extends SchemaAdapter> {\n readonly schema: TSchema;\n readonly description?: string;\n}\n\n/**\n * Context configuration input.\n * Used to validate and type context data from middleware (e.g., JWT payload).\n */\ninterface ContextInput<TSchema extends SchemaAdapter> {\n readonly schema: TSchema;\n readonly description?: string;\n}\n\n/**\n * Response configuration input.\n */\ninterface ResponseInput<TSchema extends SchemaAdapter | undefined = undefined> {\n readonly description: string;\n readonly schema?: TSchema;\n readonly contentType?: string;\n}\n\n/**\n * Complete input for defineRoute.\n */\ninterface DefineRouteInput<\n TMethod extends HttpMethod,\n TPath extends string,\n TBody extends SchemaAdapter | undefined = undefined,\n TQuery extends SchemaAdapter | undefined = undefined,\n TParams extends SchemaAdapter | undefined = undefined,\n THeaders extends SchemaAdapter | undefined = undefined,\n TContext extends SchemaAdapter | undefined = undefined,\n TResponses extends Record<number, ResponseInput<SchemaAdapter | undefined>> = Record<\n number,\n never\n >,\n> {\n readonly method: TMethod;\n readonly path: TPath;\n readonly request?: {\n readonly body?: TBody extends SchemaAdapter ? BodyInput<TBody> : undefined;\n readonly query?: TQuery extends SchemaAdapter ? QueryInput<TQuery> : undefined;\n readonly params?: TParams extends SchemaAdapter ? ParamsInput<TParams> : undefined;\n readonly headers?: THeaders extends SchemaAdapter ? HeadersInput<THeaders> : undefined;\n readonly context?: TContext extends SchemaAdapter ? ContextInput<TContext> : undefined;\n };\n readonly responses: TResponses;\n readonly docs?: {\n readonly summary?: string;\n readonly description?: string;\n readonly tags?: readonly string[];\n readonly operationId?: string;\n readonly deprecated?: boolean;\n readonly security?: readonly Record<string, readonly string[]>[];\n readonly externalDocs?: {\n readonly url: string;\n readonly description?: string;\n };\n };\n}\n\n// ============================================================================\n// Output Types\n// ============================================================================\n\n/**\n * Converts response inputs to response config type.\n */\ntype ToResponsesConfig<T extends Record<number, ResponseInput<SchemaAdapter | undefined>>> = {\n [K in keyof T]: T[K] extends ResponseInput<infer TSchema>\n ? {\n description: string;\n schema: TSchema extends SchemaAdapter ? TSchema : undefined;\n contentType?: string;\n }\n : never;\n};\n\n// ============================================================================\n// Factory Function\n// ============================================================================\n\n/**\n * Creates a route definition from the provided configuration.\n *\n * This is the main entry point for defining routes in the unified system.\n * The resulting definition can be used for:\n * - Type-safe client generation\n * - Server-side route registration\n * - OpenAPI specification generation\n *\n * @param input - Route configuration\n * @returns A frozen RouteDefinition object with full type information\n *\n * @example Basic GET route\n * ```typescript\n * import { defineRoute } from '@cosmneo/onion-lasagna/http';\n * import { zodSchema, z } from '@cosmneo/onion-lasagna/http/schema/zod';\n *\n * const listUsers = defineRoute({\n * method: 'GET',\n * path: '/api/users',\n * request: {\n * query: {\n * schema: zodSchema(z.object({\n * page: z.coerce.number().optional().default(1),\n * limit: z.coerce.number().optional().default(20),\n * })),\n * },\n * },\n * responses: {\n * 200: {\n * description: 'List of users',\n * schema: zodSchema(z.object({\n * users: z.array(z.object({\n * id: z.string(),\n * name: z.string(),\n * })),\n * total: z.number(),\n * })),\n * },\n * },\n * docs: {\n * summary: 'List all users',\n * tags: ['Users'],\n * },\n * });\n * ```\n *\n * @example POST route with path parameters\n * ```typescript\n * const createTask = defineRoute({\n * method: 'POST',\n * path: '/api/projects/:projectId/tasks',\n * request: {\n * body: {\n * schema: zodSchema(z.object({\n * title: z.string().min(1).max(200),\n * description: z.string().optional(),\n * })),\n * },\n * },\n * responses: {\n * 201: {\n * description: 'Task created',\n * schema: zodSchema(z.object({\n * id: z.string().uuid(),\n * title: z.string(),\n * projectId: z.string(),\n * createdAt: z.string().datetime(),\n * })),\n * },\n * 400: {\n * description: 'Invalid request',\n * },\n * 404: {\n * description: 'Project not found',\n * },\n * },\n * docs: {\n * summary: 'Create a new task',\n * tags: ['Tasks'],\n * operationId: 'createTask',\n * },\n * });\n * ```\n */\nexport function defineRoute<\n TMethod extends HttpMethod,\n TPath extends string,\n TBody extends SchemaAdapter | undefined = undefined,\n TQuery extends SchemaAdapter | undefined = undefined,\n TParams extends SchemaAdapter | undefined = undefined,\n THeaders extends SchemaAdapter | undefined = undefined,\n TContext extends SchemaAdapter | undefined = undefined,\n TResponses extends Record<number, ResponseInput<SchemaAdapter | undefined>> = Record<\n number,\n never\n >,\n>(\n input: DefineRouteInput<TMethod, TPath, TBody, TQuery, TParams, THeaders, TContext, TResponses>,\n): RouteDefinition<\n TMethod,\n TPath,\n TBody extends SchemaAdapter ? InferOutput<TBody> : undefined,\n TQuery extends SchemaAdapter ? InferOutput<TQuery> : undefined,\n TParams extends SchemaAdapter ? InferOutput<TParams> : PathParams<TPath>,\n THeaders extends SchemaAdapter ? InferOutput<THeaders> : undefined,\n TContext extends SchemaAdapter ? InferOutput<TContext> : undefined,\n ToResponsesConfig<TResponses> & ResponsesConfig\n> {\n const definition = {\n method: input.method,\n path: input.path,\n request: {\n body: input.request?.body ?? undefined,\n query: input.request?.query ?? undefined,\n params: input.request?.params ?? undefined,\n headers: input.request?.headers ?? undefined,\n context: input.request?.context ?? undefined,\n },\n responses: input.responses as ToResponsesConfig<TResponses> & ResponsesConfig,\n docs: {\n summary: input.docs?.summary,\n description: input.docs?.description,\n tags: input.docs?.tags,\n operationId: input.docs?.operationId,\n deprecated: input.docs?.deprecated ?? false,\n security: input.docs?.security,\n externalDocs: input.docs?.externalDocs,\n },\n _types: undefined as unknown,\n } as RouteDefinition<\n TMethod,\n TPath,\n TBody extends SchemaAdapter ? InferOutput<TBody> : undefined,\n TQuery extends SchemaAdapter ? InferOutput<TQuery> : undefined,\n TParams extends SchemaAdapter ? InferOutput<TParams> : PathParams<TPath>,\n THeaders extends SchemaAdapter ? InferOutput<THeaders> : undefined,\n TContext extends SchemaAdapter ? InferOutput<TContext> : undefined,\n ToResponsesConfig<TResponses> & ResponsesConfig\n >;\n\n // Freeze the definition to prevent accidental mutation\n return Object.freeze(definition);\n}\n","/**\n * @fileoverview Path parameter extraction types.\n *\n * These types enable TypeScript to extract path parameter names from\n * URL path templates at compile time, providing full type safety for\n * path parameters in routes.\n *\n * @module unified/route/types/path-params\n */\n\n/**\n * Extracts parameter names from a path template string.\n *\n * Supports both `:param` and `{param}` syntaxes for maximum compatibility\n * with different routing conventions.\n *\n * @example Colon syntax (Express-style)\n * ```typescript\n * type Params = ExtractPathParamNames<'/users/:userId/posts/:postId'>;\n * // 'userId' | 'postId'\n * ```\n *\n * @example Brace syntax (OpenAPI-style)\n * ```typescript\n * type Params = ExtractPathParamNames<'/users/{userId}/posts/{postId}'>;\n * // 'userId' | 'postId'\n * ```\n *\n * @example No parameters\n * ```typescript\n * type Params = ExtractPathParamNames<'/users'>;\n * // never\n * ```\n */\nexport type ExtractPathParamNames<T extends string> =\n // Match :param followed by more path\n T extends `${string}:${infer Param}/${infer Rest}`\n ? Param | ExtractPathParamNames<`/${Rest}`>\n : // Match :param at end\n T extends `${string}:${infer Param}`\n ? Param\n : // Match {param} followed by more path\n T extends `${string}{${infer Param}}/${infer Rest}`\n ? Param | ExtractPathParamNames<`/${Rest}`>\n : // Match {param} at end\n T extends `${string}{${infer Param}}`\n ? Param\n : never;\n\n/**\n * Creates an object type with all path parameters as string properties.\n *\n * @example\n * ```typescript\n * type Params = PathParams<'/projects/:projectId/tasks/:taskId'>;\n * // { projectId: string; taskId: string }\n *\n * type NoParams = PathParams<'/projects'>;\n * // Record<string, never> (empty object type)\n * ```\n */\nexport type PathParams<T extends string> =\n ExtractPathParamNames<T> extends never\n ? Record<string, never>\n : Record<ExtractPathParamNames<T>, string>;\n\n/**\n * Checks if a path has any parameters.\n *\n * @example\n * ```typescript\n * type HasParams = HasPathParams<'/users/:id'>; // true\n * type NoParams = HasPathParams<'/users'>; // false\n * ```\n */\nexport type HasPathParams<T extends string> = ExtractPathParamNames<T> extends never ? false : true;\n\n/**\n * Converts a path template with parameters to a regex pattern.\n * This is used internally for route matching.\n *\n * @example\n * ```typescript\n * pathToRegex('/users/:id/posts/:postId')\n * // /^\\/users\\/([^\\/]+)\\/posts\\/([^\\/]+)\\/?$/\n * ```\n */\nexport function pathToRegex(path: string): RegExp {\n const pattern = path\n // Escape special regex characters except : and {}\n .replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&')\n // Replace :param with capture group\n .replace(/:([a-zA-Z_][a-zA-Z0-9_]*)/g, '([^/]+)')\n // Replace {param} with capture group\n .replace(/\\\\\\{([a-zA-Z_][a-zA-Z0-9_]*)\\\\\\}/g, '([^/]+)');\n\n return new RegExp(`^${pattern}/?$`);\n}\n\n/**\n * Extracts parameter names from a path string at runtime.\n *\n * @example\n * ```typescript\n * getPathParamNames('/users/:userId/posts/:postId')\n * // ['userId', 'postId']\n * ```\n */\nexport function getPathParamNames(path: string): string[] {\n // eslint-disable-next-line @typescript-eslint/no-non-null-assertion -- regex capture group always exists\n const colonParams = [...path.matchAll(/:([a-zA-Z_][a-zA-Z0-9_]*)/g)].map((m) => m[1]!);\n // eslint-disable-next-line @typescript-eslint/no-non-null-assertion -- regex capture group always exists\n const braceParams = [...path.matchAll(/\\{([a-zA-Z_][a-zA-Z0-9_]*)\\}/g)].map((m) => m[1]!);\n return [...colonParams, ...braceParams];\n}\n\n/**\n * Checks if a path has any parameters at runtime.\n */\nexport function hasPathParams(path: string): boolean {\n return /:([a-zA-Z_][a-zA-Z0-9_]*)/.test(path) || /\\{([a-zA-Z_][a-zA-Z0-9_]*)\\}/.test(path);\n}\n\n/**\n * Replaces path parameters with actual values.\n *\n * @example\n * ```typescript\n * buildPath('/users/:userId/posts/:postId', { userId: '123', postId: '456' })\n * // '/users/123/posts/456'\n *\n * buildPath('/users/{userId}', { userId: '123' })\n * // '/users/123'\n * ```\n */\nexport function buildPath(template: string, params: Record<string, string>): string {\n let result = template;\n\n // Replace :param syntax\n for (const [key, value] of Object.entries(params)) {\n result = result.replace(`:${key}`, encodeURIComponent(value));\n result = result.replace(`{${key}}`, encodeURIComponent(value));\n }\n\n return result;\n}\n\n/**\n * Normalizes a path template to use consistent :param syntax.\n *\n * @example\n * ```typescript\n * normalizePath('/users/{userId}')\n * // '/users/:userId'\n * ```\n */\nexport function normalizePath(path: string): string {\n return path.replace(/\\{([a-zA-Z_][a-zA-Z0-9_]*)\\}/g, ':$1');\n}\n","/**\n * @fileoverview Router definition types for grouping routes.\n *\n * A router is a hierarchical grouping of routes that enables:\n * - Organized API structure\n * - Nested client method generation\n * - Grouped OpenAPI tags\n *\n * @module unified/route/types/router-definition\n */\n\nimport type { RouteDefinition, ResponsesConfig } from './route-definition.type';\nimport type { HttpMethod } from './http.type';\n\n// ============================================================================\n// Router Types\n// ============================================================================\n\n/**\n * A router entry can be either a route definition or a nested router.\n * Uses permissive types to allow any valid route definition.\n */\nexport type RouterEntry =\n | RouteDefinition<\n HttpMethod,\n string,\n unknown,\n unknown,\n unknown,\n unknown,\n unknown,\n ResponsesConfig\n >\n | RouterConfig;\n\n/**\n * Configuration for a router (group of routes).\n */\nexport interface RouterConfig {\n readonly [key: string]: RouterEntry;\n}\n\n/**\n * A fully defined router.\n */\nexport interface RouterDefinition<T extends RouterConfig = RouterConfig> {\n /**\n * The routes and nested routers in this router.\n */\n readonly routes: T;\n\n /**\n * Base path prefix for all routes in this router.\n */\n readonly basePath?: string;\n\n /**\n * Default tags for all routes in this router.\n */\n readonly tags?: readonly string[];\n\n /**\n * Marker to identify this as a router.\n * @internal\n */\n readonly _isRouter: true;\n}\n\n// ============================================================================\n// Type Guards\n// ============================================================================\n\n/**\n * Checks if a value is a RouteDefinition.\n */\nexport function isRouteDefinition(value: unknown): value is RouteDefinition {\n return (\n typeof value === 'object' &&\n value !== null &&\n 'method' in value &&\n 'path' in value &&\n 'responses' in value &&\n '_types' in value\n );\n}\n\n/**\n * Checks if a value is a RouterDefinition.\n */\nexport function isRouterDefinition(value: unknown): value is RouterDefinition {\n return (\n typeof value === 'object' &&\n value !== null &&\n '_isRouter' in value &&\n (value as RouterDefinition)._isRouter === true\n );\n}\n\n// ============================================================================\n// Utility Types\n// ============================================================================\n\n/**\n * Flattens a router into a map of path keys to route definitions.\n *\n * @example\n * ```typescript\n * const router = defineRouter({\n * users: {\n * list: listUsersRoute,\n * get: getUserRoute,\n * },\n * posts: {\n * create: createPostRoute,\n * },\n * });\n *\n * type Flat = FlattenRouter<typeof router>;\n * // {\n * // 'users.list': typeof listUsersRoute,\n * // 'users.get': typeof getUserRoute,\n * // 'posts.create': typeof createPostRoute,\n * // }\n * ```\n */\nexport type FlattenRouter<\n T extends RouterConfig,\n Prefix extends string = '',\n> = T extends RouterConfig\n ? {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n [K in keyof T]: T[K] extends RouteDefinition<any, any, any, any, any, any, any, any>\n ? { [P in `${Prefix}${K & string}`]: T[K] }\n : T[K] extends RouterConfig\n ? FlattenRouter<T[K], `${Prefix}${K & string}.`>\n : never;\n }[keyof T] extends infer U\n ? // eslint-disable-next-line @typescript-eslint/no-explicit-any\n U extends Record<string, RouteDefinition<any, any, any, any, any, any, any, any>>\n ? U\n : never\n : never\n : never;\n\n/**\n * Gets all route keys from a router.\n *\n * @example\n * ```typescript\n * type Keys = RouterKeys<typeof router>;\n * // 'users.list' | 'users.get' | 'posts.create'\n * ```\n */\nexport type RouterKeys<T extends RouterConfig, Prefix extends string = ''> = T extends RouterConfig\n ? {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n [K in keyof T]: T[K] extends RouteDefinition<any, any, any, any, any, any, any, any>\n ? `${Prefix}${K & string}`\n : T[K] extends RouterConfig\n ? RouterKeys<T[K], `${Prefix}${K & string}.`>\n : never;\n }[keyof T]\n : never;\n\n/**\n * Gets a route by its dotted key path.\n *\n * @example\n * ```typescript\n * type UserGet = GetRoute<typeof router, 'users.get'>;\n * // typeof getUserRoute\n * ```\n */\nexport type GetRoute<\n T extends RouterConfig,\n K extends string,\n> = K extends `${infer Head}.${infer Tail}`\n ? Head extends keyof T\n ? T[Head] extends RouterConfig\n ? GetRoute<T[Head], Tail>\n : never\n : never\n : K extends keyof T\n ? // eslint-disable-next-line @typescript-eslint/no-explicit-any\n T[K] extends RouteDefinition<any, any, any, any, any, any, any, any>\n ? T[K]\n : never\n : never;\n\n// ============================================================================\n// Deep Merge Types\n// ============================================================================\n\n/**\n * Deep-merges two router configs at the type level.\n *\n * - If both sides are sub-routers (extend RouterConfig), recurse.\n * - Otherwise last-one-wins (B overrides A).\n * - RouteDefinition does NOT extend RouterConfig (it has `method`, `path`, etc.)\n * so the conditional correctly distinguishes leaves from sub-routers.\n */\nexport type DeepMergeTwo<A extends RouterConfig, B extends RouterConfig> = {\n readonly [K in keyof A | keyof B]: K extends keyof A\n ? K extends keyof B\n ? A[K] extends RouterConfig\n ? B[K] extends RouterConfig\n ? DeepMergeTwo<A[K], B[K]>\n : B[K]\n : B[K]\n : A[K]\n : K extends keyof B\n ? B[K]\n : never;\n};\n\n/**\n * Recursively deep-merges N router configs left-to-right.\n */\nexport type DeepMergeAll<T extends readonly RouterConfig[]> = T extends readonly [\n infer Only extends RouterConfig,\n]\n ? Only\n : T extends readonly [\n infer First extends RouterConfig,\n infer Second extends RouterConfig,\n ...infer Rest extends readonly RouterConfig[],\n ]\n ? DeepMergeAll<[DeepMergeTwo<First, Second>, ...Rest]>\n : RouterConfig;\n\n/**\n * Recursively flattens complex types for clean IDE hover display.\n * Applied at return sites (not inside recursion) so DTS emit stays fast —\n * TypeScript only resolves when concrete types are provided.\n *\n * Works with any recursive object type: router configs, client types,\n * React Query hooks, etc. Functions and primitives pass through unchanged.\n */\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport type PrettifyDeep<T> = T extends (...args: any[]) => any\n ? T\n : T extends object\n ? { readonly [K in keyof T]: PrettifyDeep<T[K]> }\n : T;\n\n/**\n * Collects all routes from a router into an array.\n */\nexport function collectRoutes(\n config: RouterConfig,\n basePath = '',\n): { key: string; route: RouteDefinition }[] {\n const routes: { key: string; route: RouteDefinition }[] = [];\n\n for (const [key, value] of Object.entries(config)) {\n const fullKey = basePath ? `${basePath}.${key}` : key;\n\n if (isRouteDefinition(value)) {\n routes.push({ key: fullKey, route: value });\n } else if (isRouterDefinition(value)) {\n routes.push(...collectRoutes(value.routes, fullKey));\n } else if (typeof value === 'object' && value !== null) {\n routes.push(...collectRoutes(value as RouterConfig, fullKey));\n }\n }\n\n return routes;\n}\n","/**\n * @fileoverview Factory function for creating router definitions.\n *\n * The `defineRouter` function groups routes into a hierarchical structure\n * that enables organized API clients, OpenAPI tag grouping, and structured\n * server route registration.\n *\n * @module unified/route/define-router\n */\n\nimport type { RouterConfig, RouterDefinition, DeepMergeTwo, DeepMergeAll } from './types';\nimport { isRouteDefinition, isRouterDefinition } from './types';\n\n/**\n * Options for router definition.\n */\nexport interface DefineRouterOptions {\n /**\n * Base path prefix for all routes in this router.\n * Will be prepended to all route paths.\n *\n * @example\n * ```typescript\n * defineRouter({ ... }, { basePath: '/api/v1' })\n * ```\n */\n readonly basePath?: string;\n\n /**\n * Default tags for all routes in this router.\n * Will be merged with route-specific tags.\n */\n readonly tags?: readonly string[];\n}\n\n/**\n * Creates a router definition from a configuration object.\n *\n * A router is a hierarchical grouping of routes that provides:\n * - Organized API structure with nested namespaces\n * - Typed client method generation\n * - OpenAPI tag grouping\n * - Server route registration\n *\n * @param routes - Object containing routes and nested routers\n * @param options - Optional router configuration\n * @returns A frozen RouterDefinition object\n *\n * @example Basic router\n * ```typescript\n * import { defineRouter } from '@cosmneo/onion-lasagna/http';\n *\n * const api = defineRouter({\n * users: {\n * list: listUsersRoute,\n * get: getUserRoute,\n * create: createUserRoute,\n * update: updateUserRoute,\n * delete: deleteUserRoute,\n * },\n * posts: {\n * list: listPostsRoute,\n * get: getPostRoute,\n * create: createPostRoute,\n * },\n * });\n *\n * // Client usage:\n * // client.users.list({ query: { page: 1 } })\n * // client.users.get({ params: { id: '123' } })\n * // client.posts.create({ body: { title: 'Hello' } })\n * ```\n *\n * @example Nested routers\n * ```typescript\n * const projectRouter = defineRouter({\n * list: listProjectsRoute,\n * get: getProjectRoute,\n * tasks: {\n * list: listTasksRoute,\n * create: createTaskRoute,\n * update: updateTaskRoute,\n * },\n * members: {\n * list: listMembersRoute,\n * add: addMemberRoute,\n * remove: removeMemberRoute,\n * },\n * });\n *\n * const api = defineRouter({\n * projects: projectRouter.routes,\n * users: userRouter.routes,\n * });\n *\n * // Client usage:\n * // client.projects.tasks.create({ params: { projectId: '123' }, body: { ... } })\n * ```\n *\n * @example With base path and tags\n * ```typescript\n * const adminApi = defineRouter({\n * users: {\n * list: listUsersRoute,\n * ban: banUserRoute,\n * },\n * analytics: {\n * dashboard: getDashboardRoute,\n * reports: getReportsRoute,\n * },\n * }, {\n * basePath: '/admin',\n * tags: ['Admin'],\n * });\n * ```\n */\nexport function defineRouter<T extends RouterConfig>(\n routes: T,\n options?: DefineRouterOptions,\n): RouterDefinition<T> {\n const definition: RouterDefinition<T> = {\n routes,\n basePath: options?.basePath,\n tags: options?.tags,\n _isRouter: true,\n };\n\n // Deep freeze the router definition\n return deepFreeze(definition);\n}\n\n/**\n * Deep freezes an object and all its nested objects.\n */\nfunction deepFreeze<T extends object>(obj: T): T {\n // Get all property names\n const propNames = Object.getOwnPropertyNames(obj) as (keyof T)[];\n\n // Freeze properties before freezing self\n for (const name of propNames) {\n const value = obj[name];\n if (value && typeof value === 'object' && !Object.isFrozen(value)) {\n deepFreeze(value);\n }\n }\n\n return Object.freeze(obj);\n}\n\n// ============================================================================\n// mergeRouters — variadic deep merge\n// ============================================================================\n\ntype RouterInput<T extends RouterConfig> = T | RouterDefinition<T>;\n\n/** Extracts the raw RouterConfig from either a plain config or a RouterDefinition. */\nfunction extractRoutes<T extends RouterConfig>(input: RouterInput<T>): T {\n return isRouterDefinition(input) ? input.routes : input;\n}\n\n/** Returns true if `value` is a plain sub-router object (not a RouteDefinition, not a RouterDefinition). */\nfunction isSubRouter(value: unknown): value is RouterConfig {\n return (\n typeof value === 'object' &&\n value !== null &&\n !isRouteDefinition(value) &&\n !isRouterDefinition(value)\n );\n}\n\n/** Recursively deep-merges two router configs. Sub-routers are merged; leaves are overwritten. */\nfunction deepMergeConfigs(a: RouterConfig, b: RouterConfig): RouterConfig {\n const result: Record<string, unknown> = { ...a };\n\n for (const key of Object.keys(b)) {\n const aVal = result[key];\n const bVal = b[key];\n\n if (isSubRouter(aVal) && isSubRouter(bVal)) {\n result[key] = deepMergeConfigs(aVal, bVal);\n } else {\n result[key] = bVal;\n }\n }\n\n return result as RouterConfig;\n}\n\n// Overloads for 2–8 routers (clean IDE experience)\n\n/**\n * Merges multiple routers into a single router with deep merge.\n *\n * Overlapping sub-router keys are recursively merged instead of overwritten.\n * Leaf routes (RouteDefinition) use last-one-wins semantics.\n *\n * @example\n * ```typescript\n * const api = mergeRouters(\n * userRouter,\n * organizationRouter,\n * feedbackRouter,\n * );\n * // If all three define `users`, their sub-routes are deep-merged.\n * ```\n */\nexport function mergeRouters<T1 extends RouterConfig, T2 extends RouterConfig>(\n r1: RouterInput<T1>,\n r2: RouterInput<T2>,\n): RouterDefinition<DeepMergeTwo<T1, T2>>;\nexport function mergeRouters<\n T1 extends RouterConfig,\n T2 extends RouterConfig,\n T3 extends RouterConfig,\n>(\n r1: RouterInput<T1>,\n r2: RouterInput<T2>,\n r3: RouterInput<T3>,\n): RouterDefinition<DeepMergeAll<[T1, T2, T3]>>;\nexport function mergeRouters<\n T1 extends RouterConfig,\n T2 extends RouterConfig,\n T3 extends RouterConfig,\n T4 extends RouterConfig,\n>(\n r1: RouterInput<T1>,\n r2: RouterInput<T2>,\n r3: RouterInput<T3>,\n r4: RouterInput<T4>,\n): RouterDefinition<DeepMergeAll<[T1, T2, T3, T4]>>;\nexport function mergeRouters<\n T1 extends RouterConfig,\n T2 extends RouterConfig,\n T3 extends RouterConfig,\n T4 extends RouterConfig,\n T5 extends RouterConfig,\n>(\n r1: RouterInput<T1>,\n r2: RouterInput<T2>,\n r3: RouterInput<T3>,\n r4: RouterInput<T4>,\n r5: RouterInput<T5>,\n): RouterDefinition<DeepMergeAll<[T1, T2, T3, T4, T5]>>;\nexport function mergeRouters<\n T1 extends RouterConfig,\n T2 extends RouterConfig,\n T3 extends RouterConfig,\n T4 extends RouterConfig,\n T5 extends RouterConfig,\n T6 extends RouterConfig,\n>(\n r1: RouterInput<T1>,\n r2: RouterInput<T2>,\n r3: RouterInput<T3>,\n r4: RouterInput<T4>,\n r5: RouterInput<T5>,\n r6: RouterInput<T6>,\n): RouterDefinition<DeepMergeAll<[T1, T2, T3, T4, T5, T6]>>;\nexport function mergeRouters<\n T1 extends RouterConfig,\n T2 extends RouterConfig,\n T3 extends RouterConfig,\n T4 extends RouterConfig,\n T5 extends RouterConfig,\n T6 extends RouterConfig,\n T7 extends RouterConfig,\n>(\n r1: RouterInput<T1>,\n r2: RouterInput<T2>,\n r3: RouterInput<T3>,\n r4: RouterInput<T4>,\n r5: RouterInput<T5>,\n r6: RouterInput<T6>,\n r7: RouterInput<T7>,\n): RouterDefinition<DeepMergeAll<[T1, T2, T3, T4, T5, T6, T7]>>;\nexport function mergeRouters<\n T1 extends RouterConfig,\n T2 extends RouterConfig,\n T3 extends RouterConfig,\n T4 extends RouterConfig,\n T5 extends RouterConfig,\n T6 extends RouterConfig,\n T7 extends RouterConfig,\n T8 extends RouterConfig,\n>(\n r1: RouterInput<T1>,\n r2: RouterInput<T2>,\n r3: RouterInput<T3>,\n r4: RouterInput<T4>,\n r5: RouterInput<T5>,\n r6: RouterInput<T6>,\n r7: RouterInput<T7>,\n r8: RouterInput<T8>,\n): RouterDefinition<DeepMergeAll<[T1, T2, T3, T4, T5, T6, T7, T8]>>;\n\n// Variadic fallback for 9+\nexport function mergeRouters(\n ...routers: RouterInput<RouterConfig>[]\n): RouterDefinition<RouterConfig>;\n\n// Implementation\nexport function mergeRouters(\n ...routers: RouterInput<RouterConfig>[]\n): RouterDefinition<RouterConfig> {\n const merged = routers.map(extractRoutes).reduce(deepMergeConfigs);\n return defineRouter(merged);\n}\n","/**\n * @fileoverview Validation result types for schema adapters.\n *\n * These types represent the outcome of schema validation operations,\n * providing a consistent interface across all validation libraries.\n *\n * @module unified/schema/types/validation\n */\n\n/**\n * Represents a single validation error with path and message.\n */\nexport interface ValidationIssue {\n /**\n * Path to the invalid value in the data structure.\n * Empty array indicates the root value is invalid.\n *\n * @example ['body', 'user', 'email'] - nested object path\n * @example ['items', '0', 'name'] - array element path\n * @example [] - root level error\n */\n readonly path: readonly string[];\n\n /**\n * Human-readable error message describing the validation failure.\n */\n readonly message: string;\n\n /**\n * Optional error code for programmatic handling.\n * Codes are library-specific but follow common patterns:\n * - 'required' - missing required field\n * - 'type' - wrong type\n * - 'format' - invalid format (email, uuid, etc.)\n * - 'minimum' / 'maximum' - number out of range\n * - 'minLength' / 'maxLength' - string length violation\n * - 'pattern' - regex pattern mismatch\n * - 'enum' - value not in allowed list\n */\n readonly code?: string;\n\n /**\n * Expected type or value (when available).\n */\n readonly expected?: string;\n\n /**\n * Received type or value (when available).\n */\n readonly received?: string;\n}\n\n/**\n * Successful validation result containing the validated and typed data.\n */\nexport interface ValidationSuccess<T> {\n readonly success: true;\n readonly data: T;\n}\n\n/**\n * Failed validation result containing all validation issues.\n */\nexport interface ValidationFailure {\n readonly success: false;\n readonly issues: readonly ValidationIssue[];\n}\n\n/**\n * Result of a schema validation operation.\n * Discriminated union that allows type-safe handling of success/failure cases.\n *\n * @example\n * ```typescript\n * const result = schema.validate(data);\n * if (result.success) {\n * // result.data is typed as T\n * console.log(result.data);\n * } else {\n * // result.issues contains validation errors\n * console.log(result.issues);\n * }\n * ```\n */\nexport type ValidationResult<T> = ValidationSuccess<T> | ValidationFailure;\n\n/**\n * Type guard to check if a validation result is successful.\n */\nexport function isValidationSuccess<T>(\n result: ValidationResult<T>,\n): result is ValidationSuccess<T> {\n return result.success === true;\n}\n\n/**\n * Type guard to check if a validation result is a failure.\n */\nexport function isValidationFailure<T>(result: ValidationResult<T>): result is ValidationFailure {\n return result.success === false;\n}\n","/**\n * @fileoverview Schema adapter interface for validation library abstraction.\n *\n * The SchemaAdapter interface provides a unified API for working with\n * different validation libraries (Zod, TypeBox, Valibot, ArkType).\n * Each adapter wraps a library-specific schema and provides:\n * - Runtime validation\n * - JSON Schema conversion for OpenAPI\n * - TypeScript type inference via phantom types\n *\n * @module unified/schema/types/schema-adapter\n */\n\nimport type { JsonSchema } from './json-schema.type';\nimport type { ValidationResult } from './validation.type';\n\n/**\n * Schema adapter interface that abstracts validation library specifics.\n *\n * This interface is the core abstraction that enables the unified route\n * system to work with any validation library. Implementations wrap a\n * library-specific schema (Zod, TypeBox, etc.) and provide a consistent API.\n *\n * @typeParam TOutput - The TypeScript type of successfully validated data.\n * For schemas with transforms, this is the output type.\n * @typeParam TInput - The TypeScript type expected as input (before transforms).\n * Defaults to TOutput for schemas without transforms.\n *\n * @example Creating an adapter (using Zod)\n * ```typescript\n * import { z } from 'zod';\n * import { zodSchema } from '@cosmneo/onion-lasagna/http/schema/zod';\n *\n * const userSchema = zodSchema(z.object({\n * name: z.string().min(1),\n * email: z.string().email(),\n * }));\n *\n * // Validate data\n * const result = userSchema.validate(input);\n * if (result.success) {\n * // result.data is typed as { name: string; email: string }\n * }\n *\n * // Get JSON Schema for OpenAPI\n * const jsonSchema = userSchema.toJsonSchema();\n * ```\n */\nexport interface SchemaAdapter<TOutput = unknown, TInput = TOutput> {\n /**\n * Validates unknown data against the schema.\n *\n * This method performs full validation including:\n * - Type checking\n * - Constraint validation (min/max, patterns, etc.)\n * - Nested object/array validation\n * - Custom validations defined in the schema\n *\n * For schemas with transforms, the returned data will be the transformed value.\n *\n * @param data - Unknown data to validate\n * @returns Validation result with typed data on success or issues on failure\n *\n * @example\n * ```typescript\n * const result = schema.validate({ name: 'John', age: 25 });\n * if (result.success) {\n * console.log(result.data.name); // TypeScript knows this is a string\n * } else {\n * console.log(result.issues); // Array of validation errors\n * }\n * ```\n */\n validate(data: unknown): ValidationResult<TOutput>;\n\n /**\n * Converts the schema to JSON Schema format for OpenAPI generation.\n *\n * The returned schema should be compatible with JSON Schema Draft 7\n * and OpenAPI 3.0/3.1 specifications. Complex schemas with transforms\n * or refinements may produce simplified JSON Schema representations.\n *\n * @param options - Optional configuration for schema generation\n * @returns JSON Schema representation of this schema\n *\n * @example\n * ```typescript\n * const jsonSchema = schema.toJsonSchema();\n * // {\n * // type: 'object',\n * // properties: {\n * // name: { type: 'string', minLength: 1 },\n * // email: { type: 'string', format: 'email' }\n * // },\n * // required: ['name', 'email']\n * // }\n * ```\n */\n toJsonSchema(options?: JsonSchemaOptions): JsonSchema;\n\n /**\n * Phantom type marker for output type inference.\n * This property is never accessed at runtime - it exists only for TypeScript.\n *\n * @internal\n */\n readonly _output: TOutput;\n\n /**\n * Phantom type marker for input type inference.\n * This property is never accessed at runtime - it exists only for TypeScript.\n * Useful for schemas with transforms where input and output types differ.\n *\n * @internal\n */\n readonly _input: TInput;\n\n /**\n * Optional: Reference to the underlying schema for advanced use cases.\n * The type depends on the validation library being used.\n *\n * @internal\n */\n readonly _schema?: unknown;\n}\n\n/**\n * Options for JSON Schema generation.\n */\nexport interface JsonSchemaOptions {\n /**\n * Strategy for handling $ref references.\n * - 'none': Inline all schemas, no $refs\n * - 'root': Create $refs only at the root level\n * - 'all': Use $refs wherever possible (most compact)\n *\n * @default 'none'\n */\n readonly refStrategy?: 'none' | 'root' | 'all';\n\n /**\n * Base path for $ref references.\n * @default '#/$defs/'\n */\n readonly basePath?: string;\n\n /**\n * Custom definitions to include in the schema.\n */\n readonly definitions?: Record<string, JsonSchema>;\n\n /**\n * Whether to include schema metadata (title, description, etc.).\n * @default true\n */\n readonly includeMetadata?: boolean;\n}\n\n/**\n * Infers the output type from a SchemaAdapter.\n *\n * @example\n * ```typescript\n * const userSchema = zodSchema(z.object({ name: z.string() }));\n * type User = InferOutput<typeof userSchema>;\n * // { name: string }\n * ```\n */\nexport type InferOutput<T extends SchemaAdapter<unknown, unknown>> =\n T extends SchemaAdapter<infer O, unknown> ? O : never;\n\n/**\n * Infers the input type from a SchemaAdapter.\n * For schemas without transforms, this is the same as InferOutput.\n *\n * @example\n * ```typescript\n * const dateSchema = zodSchema(z.string().transform(s => new Date(s)));\n * type DateInput = InferInput<typeof dateSchema>;\n * // string (the input before transform)\n * type DateOutput = InferOutput<typeof dateSchema>;\n * // Date (the output after transform)\n * ```\n */\nexport type InferInput<T extends SchemaAdapter<unknown, unknown>> =\n T extends SchemaAdapter<unknown, infer I> ? I : never;\n\n/**\n * Type guard to check if a value is a SchemaAdapter.\n */\nexport function isSchemaAdapter(value: unknown): value is SchemaAdapter {\n return (\n typeof value === 'object' &&\n value !== null &&\n 'validate' in value &&\n typeof (value as SchemaAdapter).validate === 'function' &&\n 'toJsonSchema' in value &&\n typeof (value as SchemaAdapter).toJsonSchema === 'function'\n );\n}\n\n/**\n * Creates a schema adapter that always passes validation.\n * Useful for routes that accept any input.\n *\n * @example\n * ```typescript\n * const anySchema = createPassthroughAdapter<unknown>();\n * anySchema.validate(anything); // always succeeds\n * ```\n */\nexport function createPassthroughAdapter<T = unknown>(): SchemaAdapter<T, T> {\n return {\n validate: (data) => ({ success: true, data: data as T }),\n toJsonSchema: () => ({}),\n _output: undefined as T,\n _input: undefined as T,\n };\n}\n\n/**\n * Creates a schema adapter that always fails validation with a message.\n * Useful for deprecating routes or marking them as not accepting input.\n *\n * @example\n * ```typescript\n * const noBodySchema = createRejectingAdapter('This endpoint does not accept a request body');\n * ```\n */\nexport function createRejectingAdapter<T = never>(message: string): SchemaAdapter<T, T> {\n return {\n validate: () => ({\n success: false,\n issues: [{ path: [], message }],\n }),\n toJsonSchema: () => ({ not: {} }),\n _output: undefined as T,\n _input: undefined as T,\n };\n}\n","/**\n * @fileoverview Server types for the unified route system.\n *\n * @module unified/server/types\n */\n\nimport type {\n HttpMethod,\n RouteDefinition,\n RouterConfig,\n RouterKeys,\n GetRoute,\n} from '../route/types';\n\n// ============================================================================\n// Validated Request\n// ============================================================================\n\n/**\n * A validated request with typed data.\n * This is what handlers receive after validation passes.\n */\nexport interface ValidatedRequest<TRoute extends RouteDefinition> {\n /**\n * Validated request body.\n */\n readonly body: TRoute['_types']['body'];\n\n /**\n * Validated query parameters.\n */\n readonly query: TRoute['_types']['query'];\n\n /**\n * Validated path parameters.\n */\n readonly pathParams: TRoute['_types']['pathParams'];\n\n /**\n * Validated headers.\n */\n readonly headers: TRoute['_types']['headers'];\n\n /**\n * Raw request object for advanced use cases.\n */\n readonly raw: {\n readonly method: string;\n readonly url: string;\n readonly headers: Record<string, string>;\n };\n}\n\n/**\n * Typed context based on route definition.\n * If the route defines a context schema, this will be the validated type.\n * Otherwise, it falls back to the generic HandlerContext.\n */\nexport type TypedContext<TRoute extends RouteDefinition> =\n TRoute['_types']['context'] extends undefined ? HandlerContext : TRoute['_types']['context'];\n\n// ============================================================================\n// Handler Types\n// ============================================================================\n\n/**\n * Context passed to handlers.\n * Can be extended with custom context via serverRoutes options.\n */\nexport interface HandlerContext {\n /**\n * Request ID for tracing.\n */\n readonly requestId?: string;\n\n /**\n * Additional context data.\n */\n readonly [key: string]: unknown;\n}\n\n/**\n * Response from a handler.\n */\nexport interface HandlerResponse<TData = unknown> {\n /**\n * HTTP status code.\n */\n readonly status: number;\n\n /**\n * Response body.\n */\n readonly body?: TData;\n\n /**\n * Response headers.\n */\n readonly headers?: Record<string, string>;\n}\n\n// ============================================================================\n// Use Case Port\n// ============================================================================\n\n/**\n * Use case port interface for unified routes.\n *\n * This is a simplified version that accepts any input/output types (plain objects).\n * It's structurally compatible with `BaseInboundPort`, so existing use case\n * implementations work without changes.\n *\n * @typeParam TInput - Input type (plain object or void for no input)\n * @typeParam TOutput - Output type (plain object or void for no output)\n *\n * @example\n * ```typescript\n * // Define plain types for use case contracts\n * type CreateProjectInput = {\n * name: string;\n * description?: string;\n * };\n *\n * type CreateProjectOutput = {\n * projectId: string;\n * };\n *\n * // Use case implements this interface\n * class CreateProjectUseCase implements UseCasePort<CreateProjectInput, CreateProjectOutput> {\n * async execute(input: CreateProjectInput): Promise<CreateProjectOutput> {\n * // ... implementation\n * return { projectId: '...' };\n * }\n * }\n * ```\n */\n\nexport interface UseCasePort<TInput = void, TOutput = void> {\n execute(input?: TInput): Promise<TOutput>;\n}\n\n// ============================================================================\n// Server Configuration\n// ============================================================================\n\n/**\n * Handler configuration for a single route.\n *\n * Mirrors the BaseController pattern with three components:\n * - `requestMapper`: Maps validated HTTP request to use case input\n * - `useCase`: The use case to execute\n * - `responseMapper`: Maps use case output to HTTP response\n *\n * @typeParam TRoute - The route definition type\n * @typeParam TInput - Use case input type (plain object)\n * @typeParam TOutput - Use case output type (plain object)\n *\n * @example\n * ```typescript\n * const config: RouteHandlerConfig<typeof createProjectRoute, CreateProjectInput, CreateProjectOutput> = {\n * requestMapper: (req) => ({\n * name: req.body.name,\n * description: req.body.description,\n * }),\n * useCase: createProjectUseCase,\n * responseMapper: (out) => ({\n * status: 201,\n * body: { projectId: out.projectId },\n * }),\n * };\n * ```\n */\n\nexport interface RouteHandlerConfig<TRoute extends RouteDefinition, TInput = void, TOutput = void> {\n /**\n * Maps the validated HTTP request to use case input.\n * The request has already been validated by the route's schemas.\n * Context is typed based on the route's context schema (if defined).\n */\n readonly requestMapper: (req: ValidatedRequest<TRoute>, ctx: TypedContext<TRoute>) => TInput;\n\n /**\n * The use case to execute.\n * Can be any object with an `execute` method matching `UseCasePort`.\n */\n readonly useCase: UseCasePort<TInput, TOutput>;\n\n /**\n * Maps the use case output to an HTTP response.\n * Determines the status code and response body.\n */\n readonly responseMapper: (output: TOutput) => HandlerResponse;\n\n /**\n * Middleware to run before the handler.\n */\n readonly middleware?: readonly MiddlewareFunction[];\n}\n\n/**\n * Middleware function type.\n */\nexport type MiddlewareFunction = (\n request: unknown,\n context: HandlerContext,\n next: () => Promise<HandlerResponse>,\n) => Promise<HandlerResponse>;\n\n// ============================================================================\n// Simple Handler Types\n// ============================================================================\n\n/**\n * Simple handler function that directly returns a response.\n * Use this for simple routes that don't need the use case pattern.\n */\nexport type SimpleHandlerFn<TRoute extends RouteDefinition> = (\n req: ValidatedRequest<TRoute>,\n ctx: TypedContext<TRoute>,\n) => Promise<HandlerResponse> | HandlerResponse;\n\n/**\n * Configuration for a simple handler (no use case).\n */\nexport interface SimpleHandlerConfig<TRoute extends RouteDefinition> {\n readonly handler: SimpleHandlerFn<TRoute>;\n readonly middleware?: readonly MiddlewareFunction[];\n}\n\n/**\n * Union of all handler config types.\n * Used internally to store handlers in the builder.\n */\nexport type AnyHandlerConfig<TRoute extends RouteDefinition, TInput = unknown, TOutput = unknown> =\n | RouteHandlerConfig<TRoute, TInput, TOutput>\n | SimpleHandlerConfig<TRoute>;\n\n/**\n * Type guard to check if config is a simple handler.\n */\nexport function isSimpleHandlerConfig(\n config: AnyHandlerConfig<RouteDefinition, unknown, unknown>,\n): config is SimpleHandlerConfig<RouteDefinition> {\n return 'handler' in config && typeof config.handler === 'function';\n}\n\n/**\n * Configuration mapping route keys to handlers.\n *\n * Each route key maps to a `RouteHandlerConfig` with:\n * - The route definition for that key (provides request/response types)\n * - User-defined input/output types for the use case\n *\n * The `TInput` and `TOutput` types are inferred from the `useCase` property,\n * so you don't need to specify them explicitly.\n */\n// TInput/TOutput are user-defined per route - any is required for heterogeneous route configs\nexport type ServerRoutesConfig<T extends RouterConfig> = {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n [K in RouterKeys<T>]: RouteHandlerConfig<GetRoute<T, K>, any, any>;\n};\n\n/**\n * Options for creating server routes.\n */\nexport interface CreateServerRoutesOptions {\n /**\n * Global middleware to run before all handlers.\n */\n readonly middleware?: readonly MiddlewareFunction[];\n\n /**\n * Whether to validate incoming requests against route schemas.\n * When enabled, invalid requests throw InvalidRequestError.\n * @default true\n */\n readonly validateRequest?: boolean;\n\n /**\n * Whether to validate outgoing responses against route schemas.\n * When enabled, invalid responses throw ControllerError.\n * Useful for catching bugs and ensuring API contract compliance.\n * @default true\n */\n readonly validateResponse?: boolean;\n\n /**\n * Context factory to create handler context.\n */\n readonly createContext?: (rawRequest: unknown) => HandlerContext;\n\n /**\n * Allow partial handler configuration (not all routes need handlers).\n * When true, missing handlers are silently skipped.\n * When false (default), missing handlers throw an error.\n * @default false\n * @internal Used by builder pattern's buildPartial()\n */\n readonly allowPartial?: boolean;\n}\n\n// ============================================================================\n// Route Input (for framework adapters)\n// ============================================================================\n\n/**\n * Route input compatible with framework adapters.\n * This is the output of serverRoutes().build().\n */\nexport interface UnifiedRouteInput {\n /**\n * HTTP method.\n */\n readonly method: HttpMethod;\n\n /**\n * URL path pattern.\n */\n readonly path: string;\n\n /**\n * Handler function.\n */\n readonly handler: (\n rawRequest: RawHttpRequest,\n context?: HandlerContext,\n ) => Promise<HandlerResponse>;\n\n /**\n * Route metadata for documentation.\n */\n readonly metadata: {\n readonly operationId?: string;\n readonly summary?: string;\n readonly description?: string;\n readonly tags?: readonly string[];\n readonly deprecated?: boolean;\n };\n}\n\n/**\n * Raw HTTP request from the framework.\n */\nexport interface RawHttpRequest {\n readonly method: string;\n readonly url: string;\n readonly headers: Record<string, string | string[] | undefined>;\n readonly body?: unknown;\n readonly query?: Record<string, string | string[] | undefined>;\n readonly params?: Record<string, string>;\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/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 /** Authorization denied - user lacks permission for this operation */\n FORBIDDEN: 'FORBIDDEN',\n /** Authentication required or invalid - user is not authenticated */\n UNAUTHORIZED: 'UNAUTHORIZED',\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 '../../global/exceptions/coded-error.error';\nimport { ErrorCodes, type PresentationErrorCode } 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 '../../global/exceptions/coded-error.error';\nimport { ErrorCodes, type PresentationErrorCode } 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 { 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 authentication is required or invalid.\n *\n * Indicates that the user is not authenticated or their authentication\n * credentials are invalid/expired. This is different from `ForbiddenError`\n * which is for authenticated users who lack permission.\n *\n * **When to throw:**\n * - User is not logged in but authentication is required\n * - Authentication token is missing, invalid, or expired\n * - Session has been invalidated\n * - API key is invalid or revoked\n *\n * **Difference from ForbiddenError:**\n * - `UnauthorizedError` (401) = Not authenticated (who are you?)\n * - `ForbiddenError` (403) = Authenticated but not authorized (you can't do this)\n *\n * @example Missing authentication\n * ```typescript\n * protected async authorize(input: Input): Promise<AuthContext> {\n * if (!input.userId) {\n * throw new UnauthorizedError({ message: 'Authentication required' });\n * }\n *\n * const user = await this.userRepo.findById(input.userId);\n * if (!user) {\n * throw new UnauthorizedError({ message: 'Invalid user credentials' });\n * }\n *\n * return { user };\n * }\n * ```\n *\n * @example Token validation\n * ```typescript\n * if (!token || isTokenExpired(token)) {\n * throw new UnauthorizedError({\n * message: 'Session expired, please log in again',\n * code: 'SESSION_EXPIRED',\n * });\n * }\n * ```\n *\n * @extends UseCaseError\n */\nexport class UnauthorizedError extends UseCaseError {\n /**\n * Creates a new UnauthorizedError instance.\n *\n * @param options - Error configuration\n * @param options.message - Description of why authentication failed\n * @param options.code - Machine-readable error code (default: 'UNAUTHORIZED')\n * @param options.cause - Optional underlying error\n */\n constructor({\n message,\n code = ErrorCodes.App.UNAUTHORIZED,\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 UnauthorizedError from a caught error.\n *\n * @param cause - The original caught error\n * @returns A new UnauthorizedError instance with the cause attached\n */\n static override fromError(cause: unknown): UnauthorizedError {\n return new UnauthorizedError({\n message: cause instanceof Error ? cause.message : 'Authentication required',\n cause,\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","/**\n * @fileoverview Internal implementation for creating server routes with auto-validation.\n *\n * Generates server-side route handlers from a router definition.\n * Each handler automatically validates incoming requests and outgoing\n * responses against the route's schemas.\n *\n * @module unified/server/create-server-routes\n * @internal\n */\n\nimport type { SchemaAdapter, ValidationIssue } from '../schema/types';\nimport type { RouterConfig, RouterDefinition, RouteDefinition } from '../route/types';\nimport { isRouterDefinition, collectRoutes, normalizePath } from '../route/types';\nimport type {\n AnyHandlerConfig,\n CreateServerRoutesOptions,\n HandlerContext,\n HandlerResponse,\n RawHttpRequest,\n UnifiedRouteInput,\n ValidatedRequest,\n} from './types';\nimport { isSimpleHandlerConfig } from './types';\nimport { InvalidRequestError } from '../../exceptions/invalid-request.error';\nimport { ControllerError } from '../../exceptions/controller.error';\nimport { UnauthorizedError } from '../../../app/exceptions/unauthorized.error';\nimport { wrapError } from '../../../global/utils/wrap-error.util';\n\n/**\n * Internal implementation for creating server routes.\n * Used by the builder pattern (serverRoutes).\n *\n * @internal\n */\nexport function createServerRoutesInternal<T extends RouterConfig>(\n router: T | RouterDefinition<T>,\n handlers: Record<string, AnyHandlerConfig<RouteDefinition, unknown, unknown>>,\n options?: CreateServerRoutesOptions,\n): UnifiedRouteInput[] {\n const routes = isRouterDefinition(router) ? router.routes : router;\n const collectedRoutes = collectRoutes(routes);\n\n // Sort routes by specificity: static segments before parameterized\n // This ensures /api/users/me is registered before /api/users/:userId\n const sortedRoutes = sortRoutesBySpecificity(collectedRoutes);\n\n const result: UnifiedRouteInput[] = [];\n\n // Default validation options to true, allowPartial to false\n const resolvedOptions: CreateServerRoutesOptions = {\n ...options,\n validateRequest: options?.validateRequest ?? true,\n validateResponse: options?.validateResponse ?? true,\n allowPartial: options?.allowPartial ?? false,\n };\n\n for (const { key, route } of sortedRoutes) {\n const handlerConfig = handlers[key] as AnyHandlerConfig<RouteDefinition, any, any> | undefined;\n\n if (!handlerConfig) {\n if (resolvedOptions.allowPartial) {\n // Skip routes without handlers when allowPartial is true\n continue;\n }\n throw new Error(\n `Missing handler for route \"${key}\". All routes must have a handler configuration.`,\n );\n }\n\n result.push(createRouteHandler(route, handlerConfig, resolvedOptions));\n }\n\n return result;\n}\n\n/**\n * Sorts routes by path specificity to ensure correct route matching.\n *\n * Static path segments are sorted before parameterized segments at each position.\n * This ensures that `/api/users/me` is registered before `/api/users/:userId`,\n * preventing the parameterized route from incorrectly matching the static path.\n *\n * @example\n * Given routes:\n * - /api/users/:userId (parameterized)\n * - /api/users/me (static)\n *\n * After sorting:\n * - /api/users/me (registered first - matches exactly)\n * - /api/users/:userId (registered second - catches remaining)\n */\nfunction sortRoutesBySpecificity<T extends { route: { path: string } }>(routes: T[]): T[] {\n return [...routes].sort((a, b) => {\n const aSegments = a.route.path.split('/').filter(Boolean);\n const bSegments = b.route.path.split('/').filter(Boolean);\n\n const maxLen = Math.max(aSegments.length, bSegments.length);\n\n for (let i = 0; i < maxLen; i++) {\n const aSeg = aSegments[i];\n const bSeg = bSegments[i];\n\n // Missing segment (shorter path) - shorter paths first for same prefix\n if (aSeg === undefined && bSeg !== undefined) return -1;\n if (aSeg !== undefined && bSeg === undefined) return 1;\n if (aSeg === undefined || bSeg === undefined) return 0;\n\n // Check if segment is parameterized (supports both :param and {param} formats)\n const aIsParam = aSeg.startsWith(':') || (aSeg.startsWith('{') && aSeg.endsWith('}'));\n const bIsParam = bSeg.startsWith(':') || (bSeg.startsWith('{') && bSeg.endsWith('}'));\n\n // Static segments come before parameterized segments\n if (!aIsParam && bIsParam) return -1;\n if (aIsParam && !bIsParam) return 1;\n\n // Both static or both parameterized - compare alphabetically for stable sorting\n const cmp = aSeg.localeCompare(bSeg);\n if (cmp !== 0) return cmp;\n }\n\n return 0;\n });\n}\n\n/**\n * Creates a single route handler with validation.\n *\n * Supports two handler patterns:\n * - Simple handler: handler(req, ctx) → response\n * - Use case pattern: requestMapper → useCase.execute → responseMapper\n */\nfunction createRouteHandler(\n route: RouteDefinition,\n // TInput/TOutput are user-defined and erased at this level - any is required for type compatibility\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n config: AnyHandlerConfig<RouteDefinition, any, any>,\n options: CreateServerRoutesOptions,\n): UnifiedRouteInput {\n const middleware = config.middleware ?? [];\n const globalMiddleware = options?.middleware ?? [];\n const allMiddleware = [...globalMiddleware, ...middleware];\n\n const shouldValidateRequest = options.validateRequest ?? true;\n const shouldValidateResponse = options.validateResponse ?? true;\n\n return {\n method: route.method,\n path: normalizePath(route.path),\n metadata: {\n operationId: route.docs.operationId,\n summary: route.docs.summary,\n description: route.docs.description,\n tags: route.docs.tags as string[],\n deprecated: route.docs.deprecated,\n },\n handler: async (rawRequest: RawHttpRequest, ctx?: HandlerContext): Promise<HandlerResponse> => {\n // Create context\n const rawContext: HandlerContext = options?.createContext\n ? options.createContext(rawRequest)\n : (ctx ?? { requestId: generateRequestId() });\n\n // Validate context (if schema defined)\n // Context validation failures are treated as authentication errors (401)\n // because context typically carries auth data (user, session, token).\n // A missing or invalid context means the caller is not properly authenticated.\n const validatedContext: unknown = route.request.context?.schema\n ? wrapError(\n () => {\n const result = validateContextData(route, rawContext);\n if (!result.success) {\n const errors = result.errors ?? [];\n throw new InvalidRequestError({\n message: 'Context validation failed',\n validationErrors: errors.map((e) => ({\n field: e.path.join('.'),\n message: e.message,\n })),\n });\n }\n return result.data;\n },\n () => new UnauthorizedError({ message: 'Authentication required' }),\n )\n : rawContext;\n\n // Validate request (if enabled)\n // Use internal type since specific route types are erased in this function\n let validatedRequest: ValidatedRequestInternal;\n\n if (shouldValidateRequest) {\n const validationResult = validateRequestData(route, rawRequest);\n\n if (!validationResult.success) {\n const errors = validationResult.errors ?? [];\n throw new InvalidRequestError({\n message: 'Request validation failed',\n validationErrors: errors.map((e) => ({\n field: e.path.join('.'),\n message: e.message,\n })),\n });\n }\n\n const data = validationResult.data ?? {};\n\n validatedRequest = {\n body: data.body,\n query: data.query,\n pathParams: data.pathParams,\n headers: data.headers,\n raw: {\n method: rawRequest.method,\n url: rawRequest.url,\n headers: normalizeHeaders(rawRequest.headers),\n },\n };\n } else {\n // Skip validation - pass through normalized data\n\n validatedRequest = {\n body: rawRequest.body,\n query: normalizeQuery(rawRequest.query),\n pathParams: normalizePathParams(rawRequest.params),\n headers: normalizeHeaders(rawRequest.headers),\n raw: {\n method: rawRequest.method,\n url: rawRequest.url,\n headers: normalizeHeaders(rawRequest.headers),\n },\n };\n }\n\n // Execute the pipeline based on handler type\n // Errors from the use case/handler propagate to the framework's error handler\n const executePipeline = async (): Promise<HandlerResponse> => {\n if (isSimpleHandlerConfig(config)) {\n // Simple handler: direct call\n return config.handler(\n validatedRequest as unknown as ValidatedRequest<RouteDefinition>,\n validatedContext as HandlerContext,\n );\n } else {\n // Use case handler: requestMapper → useCase → responseMapper\n const { requestMapper, useCase, responseMapper } = config;\n\n // Map request to use case input\n // Cast is safe: ValidatedRequestInternal has same shape as ValidatedRequest<TRoute>\n // Type erasure in this function requires the cast for TypeScript\n // validatedContext is typed correctly based on route's context schema\n const input = requestMapper(\n validatedRequest as unknown as ValidatedRequest<RouteDefinition>,\n validatedContext as HandlerContext,\n );\n\n // Execute use case\n const output = await useCase.execute(input);\n\n // Map output to HTTP response\n return responseMapper(output);\n }\n };\n\n let response: HandlerResponse;\n\n if (allMiddleware.length === 0) {\n response = await executePipeline();\n } else {\n // Build middleware chain\n // Note: Middleware receives the raw context before validation\n let index = 0;\n const next = async (): Promise<HandlerResponse> => {\n if (index >= allMiddleware.length) {\n return executePipeline();\n }\n // eslint-disable-next-line @typescript-eslint/no-non-null-assertion -- index bounds checked above\n const mw = allMiddleware[index++]!;\n return mw(rawRequest, rawContext, next);\n };\n\n response = await next();\n }\n\n // Always validate status code (must be 100-599)\n validateStatusCode(response.status);\n\n // Validate response schema (if enabled)\n if (shouldValidateResponse) {\n const responseValidationResult = validateResponseData(route, response);\n\n if (!responseValidationResult.success) {\n const errors = responseValidationResult.errors ?? [];\n throw new ControllerError({\n message: 'Response validation failed',\n code: 'RESPONSE_VALIDATION_ERROR',\n cause: new Error(errors.map((e) => `${e.path.join('.')}: ${e.message}`).join('; ')),\n });\n }\n }\n\n return response;\n },\n };\n}\n\n/**\n * Validates request data against route schemas.\n */\nfunction validateRequestData(\n route: RouteDefinition,\n rawRequest: RawHttpRequest,\n): ValidationResultInternal {\n const errors: ValidationIssue[] = [];\n const data: {\n body?: unknown;\n query?: unknown;\n pathParams?: unknown;\n headers?: unknown;\n } = {};\n\n // Validate body\n if (route.request.body?.schema) {\n const result = (route.request.body.schema as SchemaAdapter).validate(rawRequest.body);\n if (result.success) {\n data.body = result.data;\n } else {\n errors.push(\n ...result.issues.map((issue) => ({\n ...issue,\n path: ['body', ...issue.path],\n })),\n );\n }\n }\n\n // Validate query\n if (route.request.query?.schema) {\n const queryObj = normalizeQuery(rawRequest.query);\n const result = (route.request.query.schema as SchemaAdapter).validate(queryObj);\n if (result.success) {\n data.query = result.data;\n } else {\n errors.push(\n ...result.issues.map((issue) => ({\n ...issue,\n path: ['query', ...issue.path],\n })),\n );\n }\n }\n\n // Validate path params\n if (route.request.params?.schema) {\n const result = (route.request.params.schema as SchemaAdapter).validate(rawRequest.params ?? {});\n if (result.success) {\n data.pathParams = result.data;\n } else {\n errors.push(\n ...result.issues.map((issue) => ({\n ...issue,\n path: ['pathParams', ...issue.path],\n })),\n );\n }\n } else {\n // Normalize raw params if no schema (ensure all values are strings)\n data.pathParams = normalizePathParams(rawRequest.params);\n }\n\n // Validate headers\n if (route.request.headers?.schema) {\n const headersObj = normalizeHeaders(rawRequest.headers);\n const result = (route.request.headers.schema as SchemaAdapter).validate(headersObj);\n if (result.success) {\n data.headers = result.data;\n } else {\n errors.push(\n ...result.issues.map((issue) => ({\n ...issue,\n path: ['headers', ...issue.path],\n })),\n );\n }\n }\n\n if (errors.length > 0) {\n return { success: false, errors };\n }\n\n return { success: true, data };\n}\n\n/**\n * Validates response data against route response schemas.\n */\nfunction validateResponseData(\n route: RouteDefinition,\n response: HandlerResponse,\n): ValidationResultInternal {\n const statusCode = String(response.status);\n const responses = route.responses as Record<string, { schema?: SchemaAdapter } | undefined>;\n const responseConfig = responses[statusCode];\n\n // No schema defined for this status code - skip validation\n if (!responseConfig) {\n return { success: true };\n }\n\n const schema = responseConfig.schema;\n\n // No schema in the response config - skip validation\n if (!schema) {\n return { success: true };\n }\n\n // Validate response body against schema\n const result = schema.validate(response.body);\n\n if (result.success) {\n return { success: true };\n }\n\n // Prefix errors with 'response.' for clarity\n const errors = result.issues.map((issue) => ({\n ...issue,\n path: ['response', ...issue.path],\n }));\n\n return { success: false, errors };\n}\n\n/**\n * Validates context data against route context schema.\n */\nfunction validateContextData(\n route: RouteDefinition,\n context: HandlerContext,\n): ContextValidationResultInternal {\n const contextSchema = route.request.context?.schema as SchemaAdapter | undefined;\n\n // No context schema defined - skip validation\n if (!contextSchema) {\n return { success: true, data: context };\n }\n\n // Validate context against schema\n const result = contextSchema.validate(context);\n\n if (result.success) {\n return { success: true, data: result.data };\n }\n\n // Prefix errors with 'context.' for clarity\n const errors = result.issues.map((issue) => ({\n ...issue,\n path: ['context', ...issue.path],\n }));\n\n return { success: false, errors };\n}\n\ninterface ValidationResultInternal {\n success: boolean;\n errors?: ValidationIssue[];\n data?: {\n body?: unknown;\n query?: unknown;\n pathParams?: unknown;\n headers?: unknown;\n };\n}\n\ninterface ContextValidationResultInternal {\n success: boolean;\n errors?: ValidationIssue[];\n data?: unknown;\n}\n\n/**\n * Internal validated request type with unknown fields.\n * Used inside createRouteHandler where specific types are erased.\n * The requestMapper receives the properly typed ValidatedRequest<TRoute>.\n */\ninterface ValidatedRequestInternal {\n readonly body: unknown;\n readonly query: unknown;\n readonly pathParams: unknown;\n readonly headers: unknown;\n readonly raw: {\n readonly method: string;\n readonly url: string;\n readonly headers: Record<string, string>;\n };\n}\n\n/**\n * Validates that an HTTP status code is in the valid range (100-599).\n *\n * @throws {ControllerError} If the status code is invalid\n */\nfunction validateStatusCode(status: number): void {\n if (!Number.isInteger(status) || status < 100 || status > 599) {\n throw new ControllerError({\n message: `Invalid HTTP status code: ${status}. Status must be an integer between 100 and 599.`,\n code: 'INVALID_STATUS_CODE',\n });\n }\n}\n\n/**\n * Normalizes query parameters, preserving arrays for duplicate keys.\n *\n * When a query parameter appears multiple times (e.g., `?tag=a&tag=b`),\n * the framework provides an array. This function preserves that array\n * so schema validation can properly validate array vs single-value params.\n *\n * Empty strings are allowed (e.g., `?flag=` results in `{ flag: '' }`).\n * Undefined values are filtered out from arrays.\n */\nfunction normalizeQuery(\n query?: Record<string, string | string[] | undefined>,\n): Record<string, string | string[]> {\n if (!query) return {};\n\n const result: Record<string, string | string[]> = {};\n for (const [key, value] of Object.entries(query)) {\n if (value === undefined) continue;\n\n if (Array.isArray(value)) {\n // Filter out undefined values but preserve the array structure\n const definedValues = value.filter((v): v is string => v !== undefined);\n if (definedValues.length === 1 && definedValues[0] !== undefined) {\n // Single value in array - unwrap for convenience\n result[key] = definedValues[0];\n } else if (definedValues.length > 1) {\n // Multiple values - preserve as array for schema validation\n result[key] = definedValues;\n }\n // Empty array (all undefined) - skip this key\n } else {\n result[key] = value;\n }\n }\n return result;\n}\n\n/**\n * Normalizes path parameters to ensure all values are non-empty strings.\n *\n * @throws {InvalidRequestError} If any path parameter is empty\n */\nfunction normalizePathParams(params?: Record<string, string>): Record<string, string> {\n if (!params) return {};\n\n const result: Record<string, string> = {};\n const emptyParams: string[] = [];\n\n for (const [key, value] of Object.entries(params)) {\n if (value !== undefined) {\n const stringValue = String(value);\n if (stringValue === '') {\n emptyParams.push(key);\n } else {\n result[key] = stringValue;\n }\n }\n }\n\n // Throw error for empty path params instead of silently filtering\n if (emptyParams.length > 0) {\n throw new InvalidRequestError({\n message: 'Path parameters cannot be empty',\n validationErrors: emptyParams.map((param) => ({\n field: `pathParams.${param}`,\n message: 'Path parameter cannot be empty',\n })),\n });\n }\n\n return result;\n}\n\n/**\n * Normalizes headers to a flat object.\n *\n * Per RFC 7230, multiple header values are joined with \", \" (comma + space).\n * Headers are lowercased for consistency.\n */\nfunction normalizeHeaders(\n headers: Record<string, string | string[] | undefined>,\n): Record<string, string> {\n const result: Record<string, string> = {};\n for (const [key, value] of Object.entries(headers)) {\n if (value === undefined) continue;\n\n if (Array.isArray(value)) {\n // Filter undefined values and join per RFC 7230\n const definedValues = value.filter((v): v is string => v !== undefined);\n if (definedValues.length > 0) {\n result[key.toLowerCase()] = definedValues.join(', ');\n }\n } else {\n result[key.toLowerCase()] = value;\n }\n }\n return result;\n}\n\n/**\n * Generates a unique request ID using crypto-secure UUID.\n */\nfunction generateRequestId(): string {\n return `req_${crypto.randomUUID()}`;\n}\n","/**\n * @fileoverview Builder pattern for creating type-safe server routes.\n *\n * The `serverRoutes` function returns a builder that provides 100% type inference\n * for all handler parameters - no manual type annotations required.\n *\n * @module unified/server/server-routes-builder\n */\n\nimport type { RouterConfig, RouterDefinition, GetRoute, RouterKeys } from '../route/types';\nimport type {\n AnyHandlerConfig,\n CreateServerRoutesOptions,\n HandlerResponse,\n MiddlewareFunction,\n RouteHandlerConfig,\n SimpleHandlerConfig,\n SimpleHandlerFn,\n TypedContext,\n UnifiedRouteInput,\n UseCasePort,\n ValidatedRequest,\n} from './types';\nimport { createServerRoutesInternal } from './create-server-routes';\nimport type { RouteDefinition } from '../route/types';\n\n// ============================================================================\n// Builder Types\n// ============================================================================\n\n/**\n * Error type displayed when attempting to build() with missing handlers.\n * The `___missingRoutes` property shows which routes are missing.\n */\nexport interface MissingHandlersError<TMissing extends string> {\n /**\n * This error indicates that not all routes have handlers.\n * Use buildPartial() to build with only the defined handlers,\n * or add handlers for the missing routes.\n */\n (options?: never): never;\n /** Routes that are missing handlers */\n readonly ___missingRoutes: TMissing;\n}\n\n/**\n * Handler configuration for the builder pattern.\n * Identical to RouteHandlerConfig but with proper TypedContext.\n */\nexport interface BuilderHandlerConfig<TRoute extends RouteDefinition, TInput, TOutput> {\n /**\n * Maps the validated HTTP request to use case input.\n * Both `req` and `ctx` are fully typed based on route schemas.\n */\n readonly requestMapper: (req: ValidatedRequest<TRoute>, ctx: TypedContext<TRoute>) => TInput;\n\n /**\n * The use case to execute.\n */\n readonly useCase: UseCasePort<TInput, TOutput>;\n\n /**\n * Maps the use case output to an HTTP response.\n */\n readonly responseMapper: (output: TOutput) => HandlerResponse;\n\n /**\n * Middleware to run before the handler.\n */\n readonly middleware?: readonly MiddlewareFunction[];\n}\n\n/**\n * Builder interface for creating type-safe server routes.\n *\n * Each `.handle()` call captures the specific route type and provides\n * full type inference for requestMapper, useCase, and responseMapper.\n *\n * @typeParam T - The router configuration type\n * @typeParam THandled - Union of route keys that have handlers (accumulates)\n *\n * @example\n * ```typescript\n * const routes = serverRoutes(projectRouter)\n * .handle('projects.create', {\n * requestMapper: (req, ctx) => ({\n * name: req.body.name, // Fully typed!\n * createdBy: ctx.userId, // Fully typed!\n * }),\n * useCase: createProjectUseCase,\n * responseMapper: (output) => ({\n * status: 201 as const,\n * body: { projectId: output.projectId },\n * }),\n * })\n * .handle('projects.list', { ... })\n * .build();\n * ```\n */\nexport interface ServerRoutesBuilder<T extends RouterConfig, THandled extends string = never> {\n /**\n * Register a simple handler for a route.\n * The handler receives validated request and context, returns response directly.\n *\n * @param key - The route key (e.g., 'projects.get')\n * @param handlerOrConfig - Simple handler function or configuration with handler and optional middleware\n * @returns A new builder with the route key added to handled routes\n */\n handle<K extends Exclude<RouterKeys<T>, THandled>>(\n key: K,\n handlerOrConfig: SimpleHandlerFn<GetRoute<T, K>> | SimpleHandlerConfig<GetRoute<T, K>>,\n ): ServerRoutesBuilder<T, THandled | K>;\n\n /**\n * Register a handler using the use case pattern.\n * Follows: requestMapper → useCase.execute() → responseMapper\n *\n * @param key - The route key (e.g., 'projects.create')\n * @param config - Handler configuration with requestMapper, useCase, responseMapper\n * @returns A new builder with the route key added to handled routes\n */\n handleWithUseCase<K extends Exclude<RouterKeys<T>, THandled>, TInput, TOutput>(\n key: K,\n config: BuilderHandlerConfig<GetRoute<T, K>, TInput, TOutput>,\n ): ServerRoutesBuilder<T, THandled | K>;\n\n /**\n * Build the routes array for framework registration.\n *\n * This method is only available when ALL routes have handlers.\n * If some routes are missing handlers, use `buildPartial()` instead.\n *\n * @param options - Optional configuration (validation, middleware)\n * @returns Array of route inputs for framework registration\n *\n * @throws {Error} At compile time if routes are missing (type error)\n */\n build: [Exclude<RouterKeys<T>, THandled>] extends [never]\n ? (options?: CreateServerRoutesOptions) => UnifiedRouteInput[]\n : MissingHandlersError<Exclude<RouterKeys<T>, THandled>>;\n\n /**\n * Build routes for only the defined handlers.\n *\n * Use this when you only want to register handlers for some routes,\n * not all routes in the router. No compile-time enforcement.\n *\n * @param options - Optional configuration (validation, middleware)\n * @returns Array of route inputs for framework registration\n */\n buildPartial(options?: CreateServerRoutesOptions): UnifiedRouteInput[];\n}\n\n// ============================================================================\n// Builder Implementation\n// ============================================================================\n\n/**\n * Internal builder implementation.\n *\n * Uses an immutable pattern where each handle() call returns a new\n * builder instance with the updated handlers map.\n */\nclass ServerRoutesBuilderImpl<T extends RouterConfig, THandled extends string = never> {\n private readonly router: T | RouterDefinition<T>;\n private readonly handlers: Map<string, AnyHandlerConfig<RouteDefinition, unknown, unknown>>;\n\n constructor(\n router: T | RouterDefinition<T>,\n handlers?: Map<string, AnyHandlerConfig<RouteDefinition, unknown, unknown>>,\n ) {\n this.router = router;\n this.handlers = handlers ?? new Map();\n }\n\n handle<K extends Exclude<RouterKeys<T>, THandled>>(\n key: K,\n handlerOrConfig: SimpleHandlerFn<GetRoute<T, K>> | SimpleHandlerConfig<GetRoute<T, K>>,\n ): ServerRoutesBuilder<T, THandled | K> {\n // Normalize function to config object\n const config: SimpleHandlerConfig<RouteDefinition> =\n typeof handlerOrConfig === 'function'\n ? { handler: handlerOrConfig as SimpleHandlerFn<RouteDefinition> }\n : (handlerOrConfig as SimpleHandlerConfig<RouteDefinition>);\n\n const newHandlers = new Map(this.handlers);\n newHandlers.set(key as string, config);\n\n return new ServerRoutesBuilderImpl<T, THandled | K>(\n this.router,\n newHandlers,\n ) as unknown as ServerRoutesBuilder<T, THandled | K>;\n }\n\n handleWithUseCase<K extends Exclude<RouterKeys<T>, THandled>, TInput, TOutput>(\n key: K,\n config: BuilderHandlerConfig<GetRoute<T, K>, TInput, TOutput>,\n ): ServerRoutesBuilder<T, THandled | K> {\n // Create new handlers map (immutable pattern)\n const newHandlers = new Map(this.handlers);\n newHandlers.set(key as string, config as RouteHandlerConfig<RouteDefinition, unknown, unknown>);\n\n // Return new builder with updated type\n // Cast through unknown is safe: the type system tracks THandled | K through the interface\n // The conditional type on `build` cannot be proven at compile time, hence the cast\n return new ServerRoutesBuilderImpl<T, THandled | K>(\n this.router,\n newHandlers,\n ) as unknown as ServerRoutesBuilder<T, THandled | K>;\n }\n\n // The build method's type is determined by the interface conditional type\n // At runtime, it always works the same way - the conditional type only affects compile-time\n build(options?: CreateServerRoutesOptions): UnifiedRouteInput[] {\n return createServerRoutesInternal(this.router, Object.fromEntries(this.handlers), options);\n }\n\n buildPartial(options?: CreateServerRoutesOptions): UnifiedRouteInput[] {\n return createServerRoutesInternal(this.router, Object.fromEntries(this.handlers), {\n ...options,\n allowPartial: true,\n });\n }\n}\n\n// ============================================================================\n// Public API\n// ============================================================================\n\n/**\n * Creates a type-safe server routes builder for a router.\n *\n * The builder pattern provides 100% type inference for all handler parameters:\n * - `req.body`, `req.query`, `req.pathParams`, `req.headers` are typed from route schemas\n * - `ctx` is typed from the route's context schema\n * - `output` in responseMapper is typed from the use case\n *\n * @param router - Router definition or router config\n * @returns Builder for registering handlers\n *\n * @example Basic usage\n * ```typescript\n * import { serverRoutes } from '@cosmneo/onion-lasagna/http/server';\n * import { projectRouter } from './router';\n *\n * const routes = serverRoutes(projectRouter)\n * .handle('projects.create', {\n * requestMapper: (req, ctx) => ({\n * name: req.body.name,\n * createdBy: ctx.userId,\n * }),\n * useCase: createProjectUseCase,\n * responseMapper: (output) => ({\n * status: 201 as const,\n * body: { projectId: output.projectId },\n * }),\n * })\n * .handle('projects.list', {\n * requestMapper: (req) => ({\n * page: req.query.page ?? 1,\n * limit: req.query.limit ?? 20,\n * }),\n * useCase: listProjectsUseCase,\n * responseMapper: (output) => ({\n * status: 200 as const,\n * body: output.projects,\n * }),\n * })\n * .build();\n *\n * // Register with framework\n * registerHonoRoutes(app, routes);\n * ```\n *\n * @example Partial build (only some routes)\n * ```typescript\n * const routes = serverRoutes(projectRouter)\n * .handle('projects.create', { ... })\n * // Skip other routes\n * .buildPartial(); // No type error even with missing routes\n * ```\n *\n * @example With options\n * ```typescript\n * const routes = serverRoutes(projectRouter)\n * .handle('projects.create', { ... })\n * .handle('projects.list', { ... })\n * .build({\n * validateRequest: true,\n * validateResponse: process.env.NODE_ENV !== 'production',\n * middleware: [loggingMiddleware],\n * });\n * ```\n */\nexport function serverRoutes<T extends RouterConfig>(\n router: T | RouterDefinition<T>,\n): ServerRoutesBuilder<T, never> {\n // Cast through unknown is safe: initial builder has no handlers (THandled = never)\n return new ServerRoutesBuilderImpl(router) as unknown as ServerRoutesBuilder<T, never>;\n}\n","/**\n * @fileoverview OpenAPI specification generation from router definitions.\n *\n * The `generateOpenAPI` function creates a complete OpenAPI 3.1 specification\n * from a router definition. All route schemas are converted to JSON Schema\n * and included in the specification.\n *\n * @module unified/openapi/generate\n */\n\nimport type { JsonSchema, SchemaAdapter } from '../schema/types';\nimport type { RouterConfig, RouterDefinition, RouteDefinition } from '../route/types';\nimport { isRouterDefinition, collectRoutes, getPathParamNames } from '../route/types';\nimport type {\n OpenAPIConfig,\n OpenAPISpec,\n OpenAPIPaths,\n OpenAPIPathItem,\n OpenAPIOperation,\n OpenAPIParameter,\n OpenAPIRequestBody,\n OpenAPIResponses,\n OpenAPIResponse,\n OpenAPITag,\n} from './types';\n\n/**\n * Checks if a value is a valid JSON schema structure.\n *\n * A valid JSON schema must be an object and have at least one of:\n * - `type` property (primitive or object types)\n * - `$ref` property (reference to another schema)\n * - `oneOf`, `anyOf`, `allOf` (composition)\n * - `properties` (object schema without explicit type)\n * - `items` (array schema without explicit type)\n * - `enum` (enumeration)\n * - `const` (constant value)\n *\n * @param value - The value to check\n * @returns True if value appears to be a valid JSON schema\n */\nfunction isValidJsonSchema(value: unknown): value is JsonSchema {\n if (!value || typeof value !== 'object' || Array.isArray(value)) {\n return false;\n }\n\n const schema = value as Record<string, unknown>;\n\n // Check for valid JSON schema indicators\n return (\n 'type' in schema ||\n '$ref' in schema ||\n 'oneOf' in schema ||\n 'anyOf' in schema ||\n 'allOf' in schema ||\n 'properties' in schema ||\n 'items' in schema ||\n 'enum' in schema ||\n 'const' in schema\n );\n}\n\n/**\n * Generates an OpenAPI specification from a router definition.\n *\n * This function walks the router structure, extracts JSON schemas from\n * all route definitions, and builds a complete OpenAPI 3.1 specification.\n *\n * @param router - Router definition or router config\n * @param config - OpenAPI configuration (info, servers, security, etc.)\n * @returns Complete OpenAPI specification\n *\n * @example Basic usage\n * ```typescript\n * import { generateOpenAPI } from '@cosmneo/onion-lasagna/http/openapi';\n * import { api } from './routes';\n *\n * const spec = generateOpenAPI(api, {\n * info: {\n * title: 'My API',\n * version: '1.0.0',\n * description: 'A comprehensive API for managing resources',\n * },\n * servers: [\n * { url: 'http://localhost:3000', description: 'Development' },\n * { url: 'https://api.example.com', description: 'Production' },\n * ],\n * });\n *\n * // Serve the spec\n * app.get('/openapi.json', (c) => c.json(spec));\n * ```\n *\n * @example With security\n * ```typescript\n * const spec = generateOpenAPI(api, {\n * info: { title: 'Secure API', version: '1.0.0' },\n * securitySchemes: {\n * bearerAuth: {\n * type: 'http',\n * scheme: 'bearer',\n * bearerFormat: 'JWT',\n * },\n * apiKey: {\n * type: 'apiKey',\n * in: 'header',\n * name: 'X-API-Key',\n * },\n * },\n * security: [{ bearerAuth: [] }],\n * });\n * ```\n *\n * @example With custom tags\n * ```typescript\n * const spec = generateOpenAPI(api, {\n * info: { title: 'Tagged API', version: '1.0.0' },\n * tags: [\n * { name: 'Users', description: 'User management operations' },\n * { name: 'Posts', description: 'Blog post operations' },\n * { name: 'Admin', description: 'Administrative operations' },\n * ],\n * });\n * ```\n */\nexport function generateOpenAPI<T extends RouterConfig>(\n router: T | RouterDefinition<T>,\n config: OpenAPIConfig,\n): OpenAPISpec {\n const routes = isRouterDefinition(router) ? router.routes : router;\n const collectedRoutes = collectRoutes(routes);\n\n // Build paths\n const paths: OpenAPIPaths = {};\n const allTags = new Set<string>();\n\n for (const { route } of collectedRoutes) {\n const openAPIPath = convertToOpenAPIPath(route.path);\n\n if (!paths[openAPIPath]) {\n paths[openAPIPath] = {};\n }\n\n const operation = buildOperation(route);\n const method = route.method.toLowerCase() as keyof OpenAPIPathItem;\n\n (paths[openAPIPath] as Record<string, OpenAPIOperation>)[method] = operation;\n\n // Collect tags\n if (operation.tags) {\n for (const tag of operation.tags) {\n allTags.add(tag);\n }\n }\n }\n\n // Build the specification\n const spec: OpenAPISpec = {\n openapi: config.openapi ?? '3.1.0',\n info: config.info,\n paths,\n };\n\n // Add optional sections\n if (config.servers && config.servers.length > 0) {\n (spec as { servers: typeof config.servers }).servers = config.servers;\n }\n\n if (config.securitySchemes && Object.keys(config.securitySchemes).length > 0) {\n (spec as { components: { securitySchemes: typeof config.securitySchemes } }).components = {\n securitySchemes: config.securitySchemes,\n };\n }\n\n if (config.security && config.security.length > 0) {\n (spec as { security: typeof config.security }).security = config.security;\n }\n\n // Merge custom tags with collected tags\n const tags: OpenAPITag[] = config.tags ? [...config.tags] : [];\n for (const tagName of allTags) {\n if (!tags.some((t) => t.name === tagName)) {\n tags.push({ name: tagName });\n }\n }\n if (tags.length > 0) {\n (spec as unknown as { tags: OpenAPITag[] }).tags = tags;\n }\n\n if (config.externalDocs) {\n (spec as { externalDocs: typeof config.externalDocs }).externalDocs = config.externalDocs;\n }\n\n return spec;\n}\n\n/**\n * Converts a path with :param to OpenAPI {param} format.\n */\nfunction convertToOpenAPIPath(path: string): string {\n return path.replace(/:([a-zA-Z_][a-zA-Z0-9_]*)/g, '{$1}');\n}\n\n/**\n * Builds an OpenAPI operation from a route definition.\n */\nfunction buildOperation(route: RouteDefinition): OpenAPIOperation {\n const operation: OpenAPIOperation = {\n responses: buildResponses(route),\n };\n\n // Add documentation\n if (route.docs.operationId) {\n (operation as { operationId: string }).operationId = route.docs.operationId;\n }\n\n if (route.docs.summary) {\n (operation as { summary: string }).summary = route.docs.summary;\n }\n\n if (route.docs.description) {\n (operation as { description: string }).description = route.docs.description;\n }\n\n if (route.docs.tags && route.docs.tags.length > 0) {\n (operation as { tags: readonly string[] }).tags = route.docs.tags;\n }\n\n if (route.docs.deprecated) {\n (operation as { deprecated: boolean }).deprecated = true;\n }\n\n if (route.docs.security && route.docs.security.length > 0) {\n (operation as { security: typeof route.docs.security }).security = route.docs.security;\n }\n\n if (route.docs.externalDocs) {\n (operation as { externalDocs: typeof route.docs.externalDocs }).externalDocs =\n route.docs.externalDocs;\n }\n\n // Add parameters\n const parameters = buildParameters(route);\n if (parameters.length > 0) {\n (operation as unknown as { parameters: OpenAPIParameter[] }).parameters = parameters;\n }\n\n // Add request body\n if (route.request.body) {\n (operation as { requestBody: OpenAPIRequestBody }).requestBody = buildRequestBody(route);\n }\n\n return operation;\n}\n\n/**\n * Builds OpenAPI parameters from route.\n */\nfunction buildParameters(route: RouteDefinition): OpenAPIParameter[] {\n const parameters: OpenAPIParameter[] = [];\n\n // Path parameters\n const pathParamNames = getPathParamNames(route.path);\n for (const name of pathParamNames) {\n const param: OpenAPIParameter = {\n name,\n in: 'path',\n required: true,\n schema: { type: 'string' },\n };\n\n // If we have a params schema, try to get more info\n if (route.request.params?.schema) {\n const jsonSchema = (route.request.params.schema as SchemaAdapter).toJsonSchema();\n if (jsonSchema.properties && typeof jsonSchema.properties === 'object') {\n const propSchema = (jsonSchema.properties as Record<string, unknown>)[name];\n if (isValidJsonSchema(propSchema)) {\n (param as { schema: JsonSchema }).schema = propSchema;\n }\n }\n }\n\n parameters.push(param);\n }\n\n // Query parameters\n if (route.request.query?.schema) {\n const querySchema = (route.request.query.schema as SchemaAdapter).toJsonSchema();\n\n if (querySchema.properties && typeof querySchema.properties === 'object') {\n const requiredFields = new Set(\n Array.isArray(querySchema.required) ? querySchema.required : [],\n );\n\n for (const [name, propSchema] of Object.entries(\n querySchema.properties as Record<string, unknown>,\n )) {\n // Skip invalid schema structures\n if (!isValidJsonSchema(propSchema)) {\n continue;\n }\n\n const param: OpenAPIParameter = {\n name,\n in: 'query',\n required: requiredFields.has(name),\n schema: propSchema,\n };\n\n // Add description if present\n if ('description' in propSchema && typeof propSchema.description === 'string') {\n (param as { description: string }).description = propSchema.description;\n }\n\n parameters.push(param);\n }\n }\n }\n\n // Header parameters\n if (route.request.headers?.schema) {\n const headersSchema = (route.request.headers.schema as SchemaAdapter).toJsonSchema();\n\n if (headersSchema.properties && typeof headersSchema.properties === 'object') {\n const requiredFields = new Set(\n Array.isArray(headersSchema.required) ? headersSchema.required : [],\n );\n\n for (const [name, propSchema] of Object.entries(\n headersSchema.properties as Record<string, unknown>,\n )) {\n // Skip invalid schema structures\n if (!isValidJsonSchema(propSchema)) {\n continue;\n }\n\n const param: OpenAPIParameter = {\n name,\n in: 'header',\n required: requiredFields.has(name),\n schema: propSchema,\n };\n\n parameters.push(param);\n }\n }\n }\n\n return parameters;\n}\n\n/**\n * Builds OpenAPI request body from route.\n */\nfunction buildRequestBody(route: RouteDefinition): OpenAPIRequestBody {\n // eslint-disable-next-line @typescript-eslint/no-non-null-assertion -- caller checks body exists\n const bodyConfig = route.request.body!;\n const contentType = bodyConfig.contentType ?? 'application/json';\n\n const requestBody: OpenAPIRequestBody = {\n required: bodyConfig.required !== false,\n content: {\n [contentType]: {\n schema: (bodyConfig.schema as SchemaAdapter).toJsonSchema(),\n },\n },\n };\n\n if (bodyConfig.description) {\n (requestBody as { description: string }).description = bodyConfig.description;\n }\n\n return requestBody;\n}\n\n/**\n * Builds OpenAPI responses from route.\n */\nfunction buildResponses(route: RouteDefinition): OpenAPIResponses {\n const responses: OpenAPIResponses = {};\n\n for (const [statusCode, responseConfig] of Object.entries(route.responses)) {\n if (!responseConfig || typeof responseConfig !== 'object') continue;\n\n const response: OpenAPIResponse = {\n description:\n (responseConfig as { description?: string }).description ?? `Response ${statusCode}`,\n };\n\n const schema = (responseConfig as { schema?: SchemaAdapter }).schema;\n if (schema) {\n const contentType =\n (responseConfig as { contentType?: string }).contentType ?? 'application/json';\n (response as { content: Record<string, { schema: object }> }).content = {\n [contentType]: {\n schema: schema.toJsonSchema(),\n },\n };\n }\n\n responses[statusCode] = response;\n }\n\n // Ensure at least a default response exists\n if (Object.keys(responses).length === 0) {\n responses['200'] = { description: 'Successful response' };\n }\n\n return responses;\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../../src/presentation/http/index.ts","../../src/presentation/http/schema/types/validation.type.ts","../../src/presentation/http/schema/types/schema-adapter.type.ts","../../src/presentation/http/route/define-route.ts","../../src/presentation/http/route/types/path-params.type.ts","../../src/presentation/http/route/types/router-definition.type.ts","../../src/presentation/http/route/define-router.ts","../../src/presentation/http/route/utils.ts","../../src/presentation/http/server/types.ts","../../src/global/exceptions/coded-error.error.ts","../../src/global/exceptions/error-codes.const.ts","../../src/presentation/exceptions/invalid-request.error.ts","../../src/presentation/exceptions/controller.error.ts","../../src/app/exceptions/use-case.error.ts","../../src/app/exceptions/unauthorized.error.ts","../../src/global/utils/wrap-error.util.ts","../../src/presentation/http/server/create-server-routes.ts","../../src/presentation/http/server/server-routes-builder.ts","../../src/presentation/http/openapi/generate.ts","../../src/global/exceptions/object-validation.error.ts","../../src/domain/exceptions/domain.error.ts","../../src/app/exceptions/not-found.error.ts","../../src/app/exceptions/conflict.error.ts","../../src/app/exceptions/unprocessable.error.ts","../../src/app/exceptions/forbidden.error.ts","../../src/infra/exceptions/infra.error.ts","../../src/presentation/exceptions/access-denied.error.ts","../../src/presentation/http/shared/error-mapping.ts"],"sourcesContent":["/**\n * @fileoverview Unified Route System (v2 — flat API)\n *\n * A comprehensive system for defining routes that powers:\n * - Type-safe client generation\n * - Server-side route registration with automatic validation\n * - OpenAPI specification generation\n *\n * @module unified\n *\n * @example Complete workflow\n * ```typescript\n * // 1. Define schemas (in infra layer)\n * import { z } from 'zod';\n * import { zodSchema } from '@cosmneo/onion-lasagna-zod';\n *\n * const userSchema = zodSchema(z.object({\n * id: z.string().uuid(),\n * name: z.string().min(1).max(100),\n * email: z.string().email(),\n * }));\n *\n * // 2. Define routes (flat API)\n * import { defineRoute, defineRouter } from '@cosmneo/onion-lasagna/http';\n *\n * const getUser = defineRoute({\n * method: 'GET',\n * path: '/api/users/:userId',\n * response: userSchema,\n * docs: { summary: 'Get a user by ID', tags: ['Users'] },\n * });\n *\n * const api = defineRouter({\n * users: { get: getUser, list: listUsers, create: createUser },\n * });\n *\n * // 3. Create client (frontend)\n * import { createClient } from '@cosmneo/onion-lasagna-client';\n *\n * const client = createClient(api, { baseUrl: 'http://localhost:3000' });\n * const user = await client.users.get({ pathParams: { userId: '123' } });\n *\n * // 4. Create server routes (backend)\n * import { serverRoutes } from '@cosmneo/onion-lasagna/http/server';\n *\n * const routes = serverRoutes(api)\n * .handle('users.get', async (req) => {\n * const user = await db.users.findById(req.pathParams.userId);\n * return user\n * ? { status: 200, body: user }\n * : { status: 404, body: { error: 'Not found' } };\n * })\n * .build();\n *\n * // 5. Generate OpenAPI (documentation)\n * import { generateOpenAPI } from '@cosmneo/onion-lasagna/http/openapi';\n *\n * const spec = generateOpenAPI(api, {\n * info: { title: 'My API', version: '1.0.0' },\n * });\n * ```\n */\n\n// ============================================================================\n// Route Definition\n// ============================================================================\n\nexport { defineRoute } from './route/define-route';\nexport { defineRouter, mergeRouters } from './route/define-router';\nexport type { DefineRouterOptions } from './route/define-router';\nexport { generateOperationId } from './route/utils';\n\n// Route types\nexport type {\n HttpMethod,\n HttpStatusCode,\n ContentType,\n PathParams,\n HasPathParams,\n ExtractPathParamNames,\n RouteDefinition,\n RouteDocumentation,\n RouterConfig,\n RouterDefinition,\n RouterEntry,\n RouterKeys,\n GetRoute,\n FlattenRouter,\n DeepMergeTwo,\n DeepMergeAll,\n PrettifyDeep,\n InferRouteBody,\n InferRouteQuery,\n InferRoutePathParams,\n InferRouteHeaders,\n InferRouteContext,\n InferRouteResponse,\n InferRouteMethod,\n InferRoutePath,\n} from './route/types';\n\nexport {\n isRouteDefinition,\n isRouterDefinition,\n collectRoutes,\n buildPath,\n normalizePath,\n pathToRegex,\n getPathParamNames,\n hasPathParams,\n} from './route/types';\n\n// ============================================================================\n// Schema\n// ============================================================================\n\nexport type {\n SchemaAdapter,\n JsonSchema,\n JsonSchemaOptions,\n ValidationResult,\n ValidationIssue,\n ValidationSuccess,\n ValidationFailure,\n InferOutput,\n InferInput,\n} from './schema/types';\n\nexport {\n isSchemaAdapter,\n isValidationSuccess,\n isValidationFailure,\n createPassthroughAdapter,\n createRejectingAdapter,\n} from './schema/types';\n\n// ============================================================================\n// Server\n// ============================================================================\n\nexport { serverRoutes } from './server/server-routes-builder';\nexport type {\n ServerRoutesBuilder,\n MissingHandlersError,\n BuilderHandlerConfig,\n} from './server/server-routes-builder';\nexport type {\n UseCasePort,\n ValidatedRequest,\n TypedContext,\n HandlerContext,\n HandlerResponse,\n RouteHandlerConfig,\n MiddlewareFunction,\n ServerRoutesConfig,\n CreateServerRoutesOptions,\n UnifiedRouteInput,\n RawHttpRequest,\n} from './server/types';\n\n// ============================================================================\n// OpenAPI\n// ============================================================================\n\nexport { generateOpenAPI } from './openapi/generate';\nexport type {\n OpenAPIConfig,\n OpenAPISpec,\n OpenAPIInfo,\n OpenAPIServer,\n OpenAPISecurityScheme,\n OpenAPITag,\n} from './openapi/types';\n\n// ============================================================================\n// Shared (Error Mapping)\n// ============================================================================\n\nexport {\n mapErrorToHttpResponse,\n getHttpStatusCode,\n shouldMaskError,\n createErrorResponseBody,\n isErrorType,\n hasValidationErrors,\n} from './shared/error-mapping';\nexport type { ErrorItem, ErrorResponseBody, MappedErrorResponse } from './shared/types';\n","/**\n * @fileoverview Validation result types for schema adapters.\n *\n * These types represent the outcome of schema validation operations,\n * providing a consistent interface across all validation libraries.\n *\n * @module unified/schema/types/validation\n */\n\n/**\n * Represents a single validation error with path and message.\n */\nexport interface ValidationIssue {\n /**\n * Path to the invalid value in the data structure.\n * Empty array indicates the root value is invalid.\n *\n * @example ['body', 'user', 'email'] - nested object path\n * @example ['items', '0', 'name'] - array element path\n * @example [] - root level error\n */\n readonly path: readonly string[];\n\n /**\n * Human-readable error message describing the validation failure.\n */\n readonly message: string;\n\n /**\n * Optional error code for programmatic handling.\n * Codes are library-specific but follow common patterns:\n * - 'required' - missing required field\n * - 'type' - wrong type\n * - 'format' - invalid format (email, uuid, etc.)\n * - 'minimum' / 'maximum' - number out of range\n * - 'minLength' / 'maxLength' - string length violation\n * - 'pattern' - regex pattern mismatch\n * - 'enum' - value not in allowed list\n */\n readonly code?: string;\n\n /**\n * Expected type or value (when available).\n */\n readonly expected?: string;\n\n /**\n * Received type or value (when available).\n */\n readonly received?: string;\n}\n\n/**\n * Successful validation result containing the validated and typed data.\n */\nexport interface ValidationSuccess<T> {\n readonly success: true;\n readonly data: T;\n}\n\n/**\n * Failed validation result containing all validation issues.\n */\nexport interface ValidationFailure {\n readonly success: false;\n readonly issues: readonly ValidationIssue[];\n}\n\n/**\n * Result of a schema validation operation.\n * Discriminated union that allows type-safe handling of success/failure cases.\n *\n * @example\n * ```typescript\n * const result = schema.validate(data);\n * if (result.success) {\n * // result.data is typed as T\n * console.log(result.data);\n * } else {\n * // result.issues contains validation errors\n * console.log(result.issues);\n * }\n * ```\n */\nexport type ValidationResult<T> = ValidationSuccess<T> | ValidationFailure;\n\n/**\n * Type guard to check if a validation result is successful.\n */\nexport function isValidationSuccess<T>(\n result: ValidationResult<T>,\n): result is ValidationSuccess<T> {\n return result.success === true;\n}\n\n/**\n * Type guard to check if a validation result is a failure.\n */\nexport function isValidationFailure<T>(result: ValidationResult<T>): result is ValidationFailure {\n return result.success === false;\n}\n","/**\n * @fileoverview Schema adapter interface for validation library abstraction.\n *\n * The SchemaAdapter interface provides a unified API for working with\n * different validation libraries (Zod, TypeBox, Valibot, ArkType).\n * Each adapter wraps a library-specific schema and provides:\n * - Runtime validation\n * - JSON Schema conversion for OpenAPI\n * - TypeScript type inference via phantom types\n *\n * @module unified/schema/types/schema-adapter\n */\n\nimport type { JsonSchema } from './json-schema.type';\nimport type { ValidationResult } from './validation.type';\n\n/**\n * Schema adapter interface that abstracts validation library specifics.\n *\n * This interface is the core abstraction that enables the unified route\n * system to work with any validation library. Implementations wrap a\n * library-specific schema (Zod, TypeBox, etc.) and provide a consistent API.\n *\n * @typeParam TOutput - The TypeScript type of successfully validated data.\n * For schemas with transforms, this is the output type.\n * @typeParam TInput - The TypeScript type expected as input (before transforms).\n * Defaults to TOutput for schemas without transforms.\n *\n * @example Creating an adapter (using Zod)\n * ```typescript\n * import { z } from 'zod';\n * import { zodSchema } from '@cosmneo/onion-lasagna/http/schema/zod';\n *\n * const userSchema = zodSchema(z.object({\n * name: z.string().min(1),\n * email: z.string().email(),\n * }));\n *\n * // Validate data\n * const result = userSchema.validate(input);\n * if (result.success) {\n * // result.data is typed as { name: string; email: string }\n * }\n *\n * // Get JSON Schema for OpenAPI\n * const jsonSchema = userSchema.toJsonSchema();\n * ```\n */\nexport interface SchemaAdapter<TOutput = unknown, TInput = TOutput> {\n /**\n * Validates unknown data against the schema.\n *\n * This method performs full validation including:\n * - Type checking\n * - Constraint validation (min/max, patterns, etc.)\n * - Nested object/array validation\n * - Custom validations defined in the schema\n *\n * For schemas with transforms, the returned data will be the transformed value.\n *\n * @param data - Unknown data to validate\n * @returns Validation result with typed data on success or issues on failure\n *\n * @example\n * ```typescript\n * const result = schema.validate({ name: 'John', age: 25 });\n * if (result.success) {\n * console.log(result.data.name); // TypeScript knows this is a string\n * } else {\n * console.log(result.issues); // Array of validation errors\n * }\n * ```\n */\n validate(data: unknown): ValidationResult<TOutput>;\n\n /**\n * Converts the schema to JSON Schema format for OpenAPI generation.\n *\n * The returned schema should be compatible with JSON Schema Draft 7\n * and OpenAPI 3.0/3.1 specifications. Complex schemas with transforms\n * or refinements may produce simplified JSON Schema representations.\n *\n * @param options - Optional configuration for schema generation\n * @returns JSON Schema representation of this schema\n *\n * @example\n * ```typescript\n * const jsonSchema = schema.toJsonSchema();\n * // {\n * // type: 'object',\n * // properties: {\n * // name: { type: 'string', minLength: 1 },\n * // email: { type: 'string', format: 'email' }\n * // },\n * // required: ['name', 'email']\n * // }\n * ```\n */\n toJsonSchema(options?: JsonSchemaOptions): JsonSchema;\n\n /**\n * Phantom type marker for output type inference.\n * This property is never accessed at runtime - it exists only for TypeScript.\n *\n * @internal\n */\n readonly _output: TOutput;\n\n /**\n * Phantom type marker for input type inference.\n * This property is never accessed at runtime - it exists only for TypeScript.\n * Useful for schemas with transforms where input and output types differ.\n *\n * @internal\n */\n readonly _input: TInput;\n\n /**\n * Optional: Reference to the underlying schema for advanced use cases.\n * The type depends on the validation library being used.\n *\n * @internal\n */\n readonly _schema?: unknown;\n}\n\n/**\n * Options for JSON Schema generation.\n */\nexport interface JsonSchemaOptions {\n /**\n * Strategy for handling $ref references.\n * - 'none': Inline all schemas, no $refs\n * - 'root': Create $refs only at the root level\n * - 'all': Use $refs wherever possible (most compact)\n *\n * @default 'none'\n */\n readonly refStrategy?: 'none' | 'root' | 'all';\n\n /**\n * Base path for $ref references.\n * @default '#/$defs/'\n */\n readonly basePath?: string;\n\n /**\n * Custom definitions to include in the schema.\n */\n readonly definitions?: Record<string, JsonSchema>;\n\n /**\n * Whether to include schema metadata (title, description, etc.).\n * @default true\n */\n readonly includeMetadata?: boolean;\n}\n\n/**\n * Infers the output type from a SchemaAdapter.\n *\n * @example\n * ```typescript\n * const userSchema = zodSchema(z.object({ name: z.string() }));\n * type User = InferOutput<typeof userSchema>;\n * // { name: string }\n * ```\n */\nexport type InferOutput<T extends SchemaAdapter<unknown, unknown>> =\n T extends SchemaAdapter<infer O, unknown> ? O : never;\n\n/**\n * Infers the input type from a SchemaAdapter.\n * For schemas without transforms, this is the same as InferOutput.\n *\n * @example\n * ```typescript\n * const dateSchema = zodSchema(z.string().transform(s => new Date(s)));\n * type DateInput = InferInput<typeof dateSchema>;\n * // string (the input before transform)\n * type DateOutput = InferOutput<typeof dateSchema>;\n * // Date (the output after transform)\n * ```\n */\nexport type InferInput<T extends SchemaAdapter<unknown, unknown>> =\n T extends SchemaAdapter<unknown, infer I> ? I : never;\n\n/**\n * Type guard to check if a value is a SchemaAdapter.\n */\nexport function isSchemaAdapter(value: unknown): value is SchemaAdapter {\n return (\n typeof value === 'object' &&\n value !== null &&\n 'validate' in value &&\n typeof (value as SchemaAdapter).validate === 'function' &&\n 'toJsonSchema' in value &&\n typeof (value as SchemaAdapter).toJsonSchema === 'function'\n );\n}\n\n/**\n * Creates a schema adapter that always passes validation.\n * Useful for routes that accept any input.\n *\n * @example\n * ```typescript\n * const anySchema = createPassthroughAdapter<unknown>();\n * anySchema.validate(anything); // always succeeds\n * ```\n */\nexport function createPassthroughAdapter<T = unknown>(): SchemaAdapter<T, T> {\n return {\n validate: (data) => ({ success: true, data: data as T }),\n toJsonSchema: () => ({}),\n _output: undefined as T,\n _input: undefined as T,\n };\n}\n\n/**\n * Creates a schema adapter that always fails validation with a message.\n * Useful for deprecating routes or marking them as not accepting input.\n *\n * @example\n * ```typescript\n * const noBodySchema = createRejectingAdapter('This endpoint does not accept a request body');\n * ```\n */\nexport function createRejectingAdapter<T = never>(message: string): SchemaAdapter<T, T> {\n return {\n validate: () => ({\n success: false,\n issues: [{ path: [], message }],\n }),\n toJsonSchema: () => ({ not: {} }),\n _output: undefined as T,\n _input: undefined as T,\n };\n}\n","/**\n * @fileoverview Factory function for creating route definitions (v2).\n *\n * The `defineRoute` function is the main entry point for defining routes.\n * Request schemas are grouped under a `request` field, while responses\n * are defined via the `responses` field with per-status-code config.\n *\n * Each schema field accepts either a bare `SchemaAdapter` or an object with\n * metadata: `{ schema, description?, contentType?, required? }`.\n *\n * The success response type is inferred from the first 2xx status with a schema.\n *\n * @module unified/route/define-route\n */\n\nimport type { SchemaAdapter, InferOutput } from '../schema/types';\nimport { isSchemaAdapter } from '../schema/types';\nimport type {\n HttpMethod,\n RouteDefinition,\n PathParams,\n SchemaFieldInput,\n RouteFieldMeta,\n ResponseFieldConfig,\n ResponsesDefinition,\n ExtractSuccessSchema,\n} from './types';\n\n// ============================================================================\n// Input Types\n// ============================================================================\n\n/**\n * Complete input for defineRoute.\n *\n * @example GET with query and response\n * ```typescript\n * defineRoute({\n * method: 'GET',\n * path: '/api/users',\n * request: {\n * query: zodSchema(z.object({ page: z.coerce.number().default(1) })),\n * },\n * responses: {\n * 200: { schema: zodSchema(userListSchema) },\n * },\n * docs: { summary: 'List users', tags: ['Users'] },\n * })\n * ```\n *\n * @example POST with body and multiple statuses\n * ```typescript\n * defineRoute({\n * method: 'POST',\n * path: '/api/users',\n * request: {\n * body: zodSchema(createUserSchema),\n * },\n * responses: {\n * 201: { schema: zodSchema(userSchema), description: 'Created' },\n * 400: { description: 'Validation error' },\n * 409: { description: 'Email already in use' },\n * },\n * })\n * ```\n *\n * @example DELETE with 204\n * ```typescript\n * defineRoute({\n * method: 'DELETE',\n * path: '/api/users/:userId',\n * responses: {\n * 204: { description: 'User deleted' },\n * 404: { description: 'User not found' },\n * },\n * })\n * ```\n */\ninterface DefineRouteInput<\n TMethod extends HttpMethod,\n TPath extends string,\n TBody extends SchemaAdapter | undefined = undefined,\n TQuery extends SchemaAdapter | undefined = undefined,\n TParams extends SchemaAdapter | undefined = undefined,\n THeaders extends SchemaAdapter | undefined = undefined,\n TContext extends SchemaAdapter | undefined = undefined,\n TResponses extends ResponsesDefinition | undefined = undefined,\n> {\n /** HTTP method for this route. */\n readonly method: TMethod;\n\n /** URL path pattern with optional parameters (`:param` or `{param}`). */\n readonly path: TPath;\n\n /** Request schemas (body, query, params, headers, context). */\n readonly request?: {\n /** Request body schema (or `{ schema, description?, contentType?, required? }`). */\n readonly body?: TBody extends SchemaAdapter ? SchemaFieldInput<TBody> : TBody;\n\n /** Query parameters schema (or `{ schema, description? }`). */\n readonly query?: TQuery extends SchemaAdapter ? SchemaFieldInput<TQuery> : TQuery;\n\n /** Path parameters schema (or `{ schema, description? }`). If omitted, inferred from path template. */\n readonly params?: TParams extends SchemaAdapter ? SchemaFieldInput<TParams> : TParams;\n\n /** Headers schema (or `{ schema, description? }`). */\n readonly headers?: THeaders extends SchemaAdapter ? SchemaFieldInput<THeaders> : THeaders;\n\n /** Context schema (or `{ schema, description? }`). */\n readonly context?: TContext extends SchemaAdapter ? SchemaFieldInput<TContext> : TContext;\n };\n\n /**\n * Per-status response definitions.\n *\n * Each key is an HTTP status code. Each value can have:\n * - `schema` — response body schema (drives type inference for 2xx)\n * - `description` — OpenAPI response description\n * - `contentType` — response content type (default: `application/json`)\n */\n readonly responses?: TResponses;\n\n /** OpenAPI documentation. */\n readonly docs?: {\n readonly summary?: string;\n readonly description?: string;\n readonly tags?: readonly string[];\n readonly operationId?: string;\n readonly deprecated?: boolean;\n readonly security?: readonly Record<string, readonly string[]>[];\n readonly externalDocs?: {\n readonly url: string;\n readonly description?: string;\n };\n };\n}\n\n// ============================================================================\n// Helpers\n// ============================================================================\n\n/**\n * Extracts the SchemaAdapter from a field that may be bare or wrapped in config.\n */\nfunction extractSchema<T extends SchemaAdapter>(\n field: SchemaFieldInput<T> | undefined,\n): T | undefined {\n if (field == null) return undefined;\n if (isSchemaAdapter(field)) return field as T;\n return (field as { schema: T }).schema;\n}\n\n/**\n * Extracts metadata from a field config, if it was passed as an object.\n */\nfunction extractMeta(\n field: SchemaFieldInput | undefined,\n): { description?: string; contentType?: string; required?: boolean } | undefined {\n if (field == null || isSchemaAdapter(field)) return undefined;\n const config = field as { description?: string; contentType?: string; required?: boolean };\n if (config.description == null && config.contentType == null && config.required == null) {\n return undefined;\n }\n return {\n description: config.description,\n contentType: config.contentType,\n required: config.required,\n };\n}\n\n/**\n * Normalizes responses record keys to strings.\n */\nfunction normalizeResponses(\n responses: Record<string | number, ResponseFieldConfig>,\n): Record<string, ResponseFieldConfig> {\n const result: Record<string, ResponseFieldConfig> = {};\n for (const [key, value] of Object.entries(responses)) {\n result[String(key)] = value;\n }\n return result;\n}\n\n// ============================================================================\n// Return type helpers\n// ============================================================================\n\ntype ResolveBody<T> = T extends SchemaAdapter ? InferOutput<T> : undefined;\ntype ResolveQuery<T> = T extends SchemaAdapter ? InferOutput<T> : undefined;\ntype ResolveParams<T, TPath extends string> = T extends SchemaAdapter\n ? InferOutput<T>\n : PathParams<TPath>;\ntype ResolveHeaders<T> = T extends SchemaAdapter ? InferOutput<T> : undefined;\ntype ResolveContext<T> = T extends SchemaAdapter ? InferOutput<T> : undefined;\n\ntype ResolveResponse<T> = T extends ResponsesDefinition\n ? ExtractSuccessSchema<T> extends SchemaAdapter\n ? InferOutput<ExtractSuccessSchema<T>>\n : undefined\n : undefined;\n\n// ============================================================================\n// Factory Function\n// ============================================================================\n\n/**\n * Creates a route definition from the provided configuration.\n *\n * This is the main entry point for defining routes. The resulting definition\n * can be used for type-safe client generation, server-side route registration,\n * and OpenAPI specification generation.\n *\n * @param input - Route configuration with request schemas and responses\n * @returns A frozen RouteDefinition object with full type information\n */\nexport function defineRoute<\n TMethod extends HttpMethod,\n TPath extends string,\n TBody extends SchemaAdapter | undefined = undefined,\n TQuery extends SchemaAdapter | undefined = undefined,\n TParams extends SchemaAdapter | undefined = undefined,\n THeaders extends SchemaAdapter | undefined = undefined,\n TContext extends SchemaAdapter | undefined = undefined,\n TResponses extends ResponsesDefinition | undefined = undefined,\n>(\n input: DefineRouteInput<TMethod, TPath, TBody, TQuery, TParams, THeaders, TContext, TResponses>,\n): RouteDefinition<\n TMethod,\n TPath,\n ResolveBody<TBody>,\n ResolveQuery<TQuery>,\n ResolveParams<TParams, TPath>,\n ResolveHeaders<THeaders>,\n ResolveContext<TContext>,\n ResolveResponse<TResponses>\n> {\n const req = input.request;\n\n // Build _meta from any config-wrapped fields\n const bodyMeta = extractMeta(req?.body as SchemaFieldInput | undefined);\n const queryMeta = extractMeta(req?.query as SchemaFieldInput | undefined);\n const paramsMeta = extractMeta(req?.params as SchemaFieldInput | undefined);\n const headersMeta = extractMeta(req?.headers as SchemaFieldInput | undefined);\n const contextMeta = extractMeta(req?.context as SchemaFieldInput | undefined);\n\n const _meta: RouteFieldMeta = {\n ...(bodyMeta ? { body: bodyMeta } : {}),\n ...(queryMeta ? { query: { description: queryMeta.description } } : {}),\n ...(paramsMeta ? { params: { description: paramsMeta.description } } : {}),\n ...(headersMeta ? { headers: { description: headersMeta.description } } : {}),\n ...(contextMeta ? { context: { description: contextMeta.description } } : {}),\n };\n\n const definition = {\n method: input.method,\n path: input.path,\n request: {\n body: extractSchema(req?.body as SchemaFieldInput | undefined) ?? undefined,\n query: extractSchema(req?.query as SchemaFieldInput | undefined) ?? undefined,\n params: extractSchema(req?.params as SchemaFieldInput | undefined) ?? undefined,\n headers: extractSchema(req?.headers as SchemaFieldInput | undefined) ?? undefined,\n context: extractSchema(req?.context as SchemaFieldInput | undefined) ?? undefined,\n },\n responses: input.responses ? normalizeResponses(input.responses) : undefined,\n docs: {\n summary: input.docs?.summary,\n description: input.docs?.description,\n tags: input.docs?.tags,\n operationId: input.docs?.operationId,\n deprecated: input.docs?.deprecated ?? false,\n security: input.docs?.security,\n externalDocs: input.docs?.externalDocs,\n },\n _meta,\n _types: undefined as unknown,\n };\n\n return Object.freeze(definition) as RouteDefinition<\n TMethod,\n TPath,\n ResolveBody<TBody>,\n ResolveQuery<TQuery>,\n ResolveParams<TParams, TPath>,\n ResolveHeaders<THeaders>,\n ResolveContext<TContext>,\n ResolveResponse<TResponses>\n >;\n}\n","/**\n * @fileoverview Path parameter extraction types.\n *\n * These types enable TypeScript to extract path parameter names from\n * URL path templates at compile time, providing full type safety for\n * path parameters in routes.\n *\n * @module unified/route/types/path-params\n */\n\n/**\n * Extracts parameter names from a path template string.\n *\n * Supports both `:param` and `{param}` syntaxes for maximum compatibility\n * with different routing conventions.\n *\n * @example Colon syntax (Express-style)\n * ```typescript\n * type Params = ExtractPathParamNames<'/users/:userId/posts/:postId'>;\n * // 'userId' | 'postId'\n * ```\n *\n * @example Brace syntax (OpenAPI-style)\n * ```typescript\n * type Params = ExtractPathParamNames<'/users/{userId}/posts/{postId}'>;\n * // 'userId' | 'postId'\n * ```\n *\n * @example No parameters\n * ```typescript\n * type Params = ExtractPathParamNames<'/users'>;\n * // never\n * ```\n */\nexport type ExtractPathParamNames<T extends string> =\n // Match :param followed by more path\n T extends `${string}:${infer Param}/${infer Rest}`\n ? Param | ExtractPathParamNames<`/${Rest}`>\n : // Match :param at end\n T extends `${string}:${infer Param}`\n ? Param\n : // Match {param} followed by more path\n T extends `${string}{${infer Param}}/${infer Rest}`\n ? Param | ExtractPathParamNames<`/${Rest}`>\n : // Match {param} at end\n T extends `${string}{${infer Param}}`\n ? Param\n : never;\n\n/**\n * Creates an object type with all path parameters as string properties.\n *\n * @example\n * ```typescript\n * type Params = PathParams<'/projects/:projectId/tasks/:taskId'>;\n * // { projectId: string; taskId: string }\n *\n * type NoParams = PathParams<'/projects'>;\n * // Record<string, never> (empty object type)\n * ```\n */\nexport type PathParams<T extends string> =\n ExtractPathParamNames<T> extends never\n ? Record<string, never>\n : Record<ExtractPathParamNames<T>, string>;\n\n/**\n * Checks if a path has any parameters.\n *\n * @example\n * ```typescript\n * type HasParams = HasPathParams<'/users/:id'>; // true\n * type NoParams = HasPathParams<'/users'>; // false\n * ```\n */\nexport type HasPathParams<T extends string> = ExtractPathParamNames<T> extends never ? false : true;\n\n/**\n * Converts a path template with parameters to a regex pattern.\n * This is used internally for route matching.\n *\n * @example\n * ```typescript\n * pathToRegex('/users/:id/posts/:postId')\n * // /^\\/users\\/([^\\/]+)\\/posts\\/([^\\/]+)\\/?$/\n * ```\n */\nexport function pathToRegex(path: string): RegExp {\n const pattern = path\n // Escape special regex characters except : and {}\n .replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&')\n // Replace :param with capture group\n .replace(/:([a-zA-Z_][a-zA-Z0-9_]*)/g, '([^/]+)')\n // Replace {param} with capture group\n .replace(/\\\\\\{([a-zA-Z_][a-zA-Z0-9_]*)\\\\\\}/g, '([^/]+)');\n\n return new RegExp(`^${pattern}/?$`);\n}\n\n/**\n * Extracts parameter names from a path string at runtime.\n *\n * @example\n * ```typescript\n * getPathParamNames('/users/:userId/posts/:postId')\n * // ['userId', 'postId']\n * ```\n */\nexport function getPathParamNames(path: string): string[] {\n // eslint-disable-next-line @typescript-eslint/no-non-null-assertion -- regex capture group always exists\n const colonParams = [...path.matchAll(/:([a-zA-Z_][a-zA-Z0-9_]*)/g)].map((m) => m[1]!);\n // eslint-disable-next-line @typescript-eslint/no-non-null-assertion -- regex capture group always exists\n const braceParams = [...path.matchAll(/\\{([a-zA-Z_][a-zA-Z0-9_]*)\\}/g)].map((m) => m[1]!);\n return [...colonParams, ...braceParams];\n}\n\n/**\n * Checks if a path has any parameters at runtime.\n */\nexport function hasPathParams(path: string): boolean {\n return /:([a-zA-Z_][a-zA-Z0-9_]*)/.test(path) || /\\{([a-zA-Z_][a-zA-Z0-9_]*)\\}/.test(path);\n}\n\n/**\n * Replaces path parameters with actual values.\n *\n * @example\n * ```typescript\n * buildPath('/users/:userId/posts/:postId', { userId: '123', postId: '456' })\n * // '/users/123/posts/456'\n *\n * buildPath('/users/{userId}', { userId: '123' })\n * // '/users/123'\n * ```\n */\nexport function buildPath(template: string, params: Record<string, string>): string {\n let result = template;\n\n // Replace :param syntax\n for (const [key, value] of Object.entries(params)) {\n result = result.replace(`:${key}`, encodeURIComponent(value));\n result = result.replace(`{${key}}`, encodeURIComponent(value));\n }\n\n return result;\n}\n\n/**\n * Normalizes a path template to use consistent :param syntax.\n *\n * @example\n * ```typescript\n * normalizePath('/users/{userId}')\n * // '/users/:userId'\n * ```\n */\nexport function normalizePath(path: string): string {\n return path.replace(/\\{([a-zA-Z_][a-zA-Z0-9_]*)\\}/g, ':$1');\n}\n","/**\n * @fileoverview Router definition types for grouping routes.\n *\n * A router is a hierarchical grouping of routes that enables:\n * - Organized API structure\n * - Nested client method generation\n * - Grouped OpenAPI tags\n *\n * @module unified/route/types/router-definition\n */\n\nimport type { RouteDefinition } from './route-definition.type';\nimport type { HttpMethod } from './http.type';\nimport type { SchemaAdapter } from '../../schema/types';\n\n// ============================================================================\n// Router Types\n// ============================================================================\n\n/**\n * A router entry can be a route definition, a nested router config, or a router definition.\n */\nexport type RouterEntry =\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n | RouteDefinition<HttpMethod, string, unknown, unknown, unknown, unknown, unknown, any>\n | RouterConfig\n | RouterDefinition;\n\n/**\n * Configuration for a router (group of routes).\n */\nexport interface RouterConfig {\n readonly [key: string]: RouterEntry;\n}\n\n/**\n * Router-level defaults applied to all child routes.\n */\nexport interface RouterDefaults {\n /**\n * Default tags for all routes in this router.\n * Merged with route-specific tags.\n */\n readonly tags?: readonly string[];\n\n /**\n * Default context schema for all routes in this router.\n * Applied to routes that don't define their own context.\n */\n readonly context?: SchemaAdapter;\n}\n\n/**\n * A fully defined router.\n */\nexport interface RouterDefinition<T extends RouterConfig = RouterConfig> {\n /**\n * The routes and nested routers in this router.\n */\n readonly routes: T;\n\n /**\n * Base path prefix for all routes in this router.\n */\n readonly basePath?: string;\n\n /**\n * Default values applied to all child routes.\n */\n readonly defaults?: RouterDefaults;\n\n /**\n * Marker to identify this as a router.\n * @internal\n */\n readonly _isRouter: true;\n}\n\n// ============================================================================\n// Type Guards\n// ============================================================================\n\n/**\n * Checks if a value is a RouteDefinition.\n */\nexport function isRouteDefinition(value: unknown): value is RouteDefinition {\n return (\n typeof value === 'object' &&\n value !== null &&\n 'method' in value &&\n 'path' in value &&\n '_types' in value\n );\n}\n\n/**\n * Checks if a value is a RouterDefinition.\n */\nexport function isRouterDefinition(value: unknown): value is RouterDefinition {\n return (\n typeof value === 'object' &&\n value !== null &&\n '_isRouter' in value &&\n (value as RouterDefinition)._isRouter === true\n );\n}\n\n// ============================================================================\n// Utility Types\n// ============================================================================\n\n/**\n * Flattens a router into a map of path keys to route definitions.\n */\nexport type FlattenRouter<\n T extends RouterConfig,\n Prefix extends string = '',\n> = T extends RouterConfig\n ? {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n [K in keyof T]: T[K] extends RouteDefinition<any, any, any, any, any, any, any, any>\n ? { [P in `${Prefix}${K & string}`]: T[K] }\n : T[K] extends RouterConfig\n ? FlattenRouter<T[K], `${Prefix}${K & string}.`>\n : never;\n }[keyof T] extends infer U\n ? // eslint-disable-next-line @typescript-eslint/no-explicit-any\n U extends Record<string, RouteDefinition<any, any, any, any, any, any, any, any>>\n ? U\n : never\n : never\n : never;\n\n/**\n * Gets all route keys from a router.\n */\nexport type RouterKeys<T extends RouterConfig, Prefix extends string = ''> = T extends RouterConfig\n ? {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n [K in keyof T]: T[K] extends RouteDefinition<any, any, any, any, any, any, any, any>\n ? `${Prefix}${K & string}`\n : T[K] extends RouterConfig\n ? RouterKeys<T[K], `${Prefix}${K & string}.`>\n : never;\n }[keyof T]\n : never;\n\n/**\n * Gets a route by its dotted key path.\n */\nexport type GetRoute<\n T extends RouterConfig,\n K extends string,\n> = K extends `${infer Head}.${infer Tail}`\n ? Head extends keyof T\n ? T[Head] extends RouterConfig\n ? GetRoute<T[Head], Tail>\n : never\n : never\n : K extends keyof T\n ? // eslint-disable-next-line @typescript-eslint/no-explicit-any\n T[K] extends RouteDefinition<any, any, any, any, any, any, any, any>\n ? T[K]\n : never\n : never;\n\n// ============================================================================\n// Deep Merge Types\n// ============================================================================\n\n/**\n * Deep-merges two router configs at the type level.\n */\nexport type DeepMergeTwo<A extends RouterConfig, B extends RouterConfig> = {\n readonly [K in keyof A | keyof B]: K extends keyof A\n ? K extends keyof B\n ? A[K] extends RouterConfig\n ? B[K] extends RouterConfig\n ? DeepMergeTwo<A[K], B[K]>\n : B[K]\n : B[K]\n : A[K]\n : K extends keyof B\n ? B[K]\n : never;\n};\n\n/**\n * Recursively deep-merges N router configs left-to-right.\n */\nexport type DeepMergeAll<T extends readonly RouterConfig[]> = T extends readonly [\n infer Only extends RouterConfig,\n]\n ? Only\n : T extends readonly [\n infer First extends RouterConfig,\n infer Second extends RouterConfig,\n ...infer Rest extends readonly RouterConfig[],\n ]\n ? DeepMergeAll<[DeepMergeTwo<First, Second>, ...Rest]>\n : RouterConfig;\n\n/**\n * Recursively flattens complex types for clean IDE hover display.\n */\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport type PrettifyDeep<T> = T extends (...args: any[]) => any\n ? T\n : T extends object\n ? { readonly [K in keyof T]: PrettifyDeep<T[K]> }\n : T;\n\n/**\n * Collects all routes from a router into an array.\n */\nexport function collectRoutes(\n config: RouterConfig,\n basePath = '',\n): { key: string; route: RouteDefinition }[] {\n const routes: { key: string; route: RouteDefinition }[] = [];\n\n for (const [key, value] of Object.entries(config)) {\n const fullKey = basePath ? `${basePath}.${key}` : key;\n\n if (isRouteDefinition(value)) {\n routes.push({ key: fullKey, route: value });\n } else if (isRouterDefinition(value)) {\n routes.push(...collectRoutes(value.routes, fullKey));\n } else if (typeof value === 'object' && value !== null) {\n routes.push(...collectRoutes(value as RouterConfig, fullKey));\n }\n }\n\n return routes;\n}\n","/**\n * @fileoverview Factory function for creating router definitions.\n *\n * The `defineRouter` function groups routes into a hierarchical structure\n * with optional router-level defaults for context and tags.\n *\n * @module unified/route/define-router\n */\n\nimport type {\n RouterConfig,\n RouterDefaults,\n RouterDefinition,\n RouteDefinition,\n DeepMergeTwo,\n DeepMergeAll,\n} from './types';\nimport { isRouteDefinition, isRouterDefinition } from './types';\n\n/**\n * Options for router definition.\n */\nexport interface DefineRouterOptions {\n /**\n * Base path prefix for all routes in this router.\n * Will be prepended to all route paths.\n */\n readonly basePath?: string;\n\n /**\n * Default values applied to all child routes.\n *\n * @example\n * ```typescript\n * defineRouter({\n * list: listUsersRoute,\n * get: getUserRoute,\n * }, {\n * defaults: {\n * context: zodSchema(executionContextSchema),\n * tags: ['Users'],\n * },\n * })\n * ```\n */\n readonly defaults?: RouterDefaults;\n}\n\n/**\n * Creates a router definition from a configuration object.\n *\n * A router is a hierarchical grouping of routes that provides:\n * - Organized API structure with nested namespaces\n * - Typed client method generation\n * - OpenAPI tag grouping\n * - Router-level defaults for context and tags\n *\n * @param routes - Object containing routes and nested routers\n * @param options - Optional router configuration\n * @returns A frozen RouterDefinition object\n *\n * @example Basic router\n * ```typescript\n * const api = defineRouter({\n * users: {\n * list: listUsersRoute,\n * get: getUserRoute,\n * create: createUserRoute,\n * },\n * });\n * ```\n *\n * @example With router-level defaults\n * ```typescript\n * const api = defineRouter({\n * list: listUsersRoute,\n * get: getUserRoute,\n * }, {\n * basePath: '/api/v1',\n * defaults: {\n * context: zodSchema(executionContextSchema),\n * tags: ['Users'],\n * },\n * });\n * // Context is applied to all routes that don't define their own.\n * // Tags are merged with each route's existing tags.\n * ```\n */\nexport function defineRouter<T extends RouterConfig>(\n routes: T,\n options?: DefineRouterOptions,\n): RouterDefinition<T> {\n const defaults = options?.defaults;\n\n // Apply defaults to routes if context or tags are provided\n const processedRoutes =\n defaults?.context || defaults?.tags ? (applyRouterDefaults(routes, defaults) as T) : routes;\n\n const definition: RouterDefinition<T> = {\n routes: processedRoutes,\n basePath: options?.basePath,\n defaults,\n _isRouter: true,\n };\n\n // Deep freeze the router definition\n return deepFreeze(definition);\n}\n\n/**\n * Recursively applies router-level defaults to all routes in the tree.\n */\nfunction applyRouterDefaults(routes: RouterConfig, defaults: RouterDefaults): RouterConfig {\n const result: Record<string, unknown> = {};\n\n for (const [key, value] of Object.entries(routes)) {\n if (isRouteDefinition(value)) {\n result[key] = applyDefaultsToRoute(value, defaults);\n } else if (isRouterDefinition(value)) {\n result[key] = {\n ...value,\n routes: applyRouterDefaults(value.routes, defaults),\n };\n } else if (typeof value === 'object' && value !== null) {\n result[key] = applyRouterDefaults(value as RouterConfig, defaults);\n }\n }\n\n return result as RouterConfig;\n}\n\n/**\n * Applies router-level defaults to a single route definition.\n */\nfunction applyDefaultsToRoute(route: RouteDefinition, defaults: RouterDefaults): RouteDefinition {\n const needsContext = defaults.context && !route.request.context;\n const needsTags = defaults.tags && defaults.tags.length > 0;\n\n if (!needsContext && !needsTags) return route;\n\n return Object.freeze({\n ...route,\n request: {\n ...route.request,\n context: route.request.context ?? defaults.context ?? undefined,\n },\n docs: {\n ...route.docs,\n tags: mergeTags(defaults.tags, route.docs.tags),\n },\n }) as RouteDefinition;\n}\n\n/**\n * Merges router-level tags with route-level tags, avoiding duplicates.\n */\nfunction mergeTags(\n routerTags?: readonly string[],\n routeTags?: readonly string[],\n): readonly string[] | undefined {\n if (!routerTags || routerTags.length === 0) return routeTags;\n if (!routeTags || routeTags.length === 0) return routerTags;\n\n // Merge, preserving order: router tags first, then route-specific tags (no duplicates)\n const merged = [...routerTags];\n for (const tag of routeTags) {\n if (!merged.includes(tag)) {\n merged.push(tag);\n }\n }\n return merged;\n}\n\n/**\n * Deep freezes an object and all its nested objects.\n */\nfunction deepFreeze<T extends object>(obj: T): T {\n const propNames = Object.getOwnPropertyNames(obj) as (keyof T)[];\n\n for (const name of propNames) {\n const value = obj[name];\n if (value && typeof value === 'object' && !Object.isFrozen(value)) {\n deepFreeze(value);\n }\n }\n\n return Object.freeze(obj);\n}\n\n// ============================================================================\n// mergeRouters — variadic deep merge\n// ============================================================================\n\ntype RouterInput<T extends RouterConfig> = T | RouterDefinition<T>;\n\n/** Extracts the raw RouterConfig from either a plain config or a RouterDefinition. */\nfunction extractRoutes<T extends RouterConfig>(input: RouterInput<T>): T {\n return isRouterDefinition(input) ? input.routes : input;\n}\n\n/** Returns true if `value` is a plain sub-router object (not a RouteDefinition, not a RouterDefinition). */\nfunction isSubRouter(value: unknown): value is RouterConfig {\n return (\n typeof value === 'object' &&\n value !== null &&\n !isRouteDefinition(value) &&\n !isRouterDefinition(value)\n );\n}\n\n/** Recursively deep-merges two router configs. Sub-routers are merged; leaves are overwritten. */\nfunction deepMergeConfigs(a: RouterConfig, b: RouterConfig): RouterConfig {\n const result: Record<string, unknown> = { ...a };\n\n for (const key of Object.keys(b)) {\n const aVal = result[key];\n const bVal = b[key];\n\n if (isSubRouter(aVal) && isSubRouter(bVal)) {\n result[key] = deepMergeConfigs(aVal, bVal);\n } else {\n result[key] = bVal;\n }\n }\n\n return result as RouterConfig;\n}\n\n// Overloads for 2–8 routers (clean IDE experience)\nexport function mergeRouters<T1 extends RouterConfig, T2 extends RouterConfig>(\n r1: RouterInput<T1>,\n r2: RouterInput<T2>,\n): RouterDefinition<DeepMergeTwo<T1, T2>>;\nexport function mergeRouters<\n T1 extends RouterConfig,\n T2 extends RouterConfig,\n T3 extends RouterConfig,\n>(\n r1: RouterInput<T1>,\n r2: RouterInput<T2>,\n r3: RouterInput<T3>,\n): RouterDefinition<DeepMergeAll<[T1, T2, T3]>>;\nexport function mergeRouters<\n T1 extends RouterConfig,\n T2 extends RouterConfig,\n T3 extends RouterConfig,\n T4 extends RouterConfig,\n>(\n r1: RouterInput<T1>,\n r2: RouterInput<T2>,\n r3: RouterInput<T3>,\n r4: RouterInput<T4>,\n): RouterDefinition<DeepMergeAll<[T1, T2, T3, T4]>>;\nexport function mergeRouters<\n T1 extends RouterConfig,\n T2 extends RouterConfig,\n T3 extends RouterConfig,\n T4 extends RouterConfig,\n T5 extends RouterConfig,\n>(\n r1: RouterInput<T1>,\n r2: RouterInput<T2>,\n r3: RouterInput<T3>,\n r4: RouterInput<T4>,\n r5: RouterInput<T5>,\n): RouterDefinition<DeepMergeAll<[T1, T2, T3, T4, T5]>>;\nexport function mergeRouters<\n T1 extends RouterConfig,\n T2 extends RouterConfig,\n T3 extends RouterConfig,\n T4 extends RouterConfig,\n T5 extends RouterConfig,\n T6 extends RouterConfig,\n>(\n r1: RouterInput<T1>,\n r2: RouterInput<T2>,\n r3: RouterInput<T3>,\n r4: RouterInput<T4>,\n r5: RouterInput<T5>,\n r6: RouterInput<T6>,\n): RouterDefinition<DeepMergeAll<[T1, T2, T3, T4, T5, T6]>>;\nexport function mergeRouters<\n T1 extends RouterConfig,\n T2 extends RouterConfig,\n T3 extends RouterConfig,\n T4 extends RouterConfig,\n T5 extends RouterConfig,\n T6 extends RouterConfig,\n T7 extends RouterConfig,\n>(\n r1: RouterInput<T1>,\n r2: RouterInput<T2>,\n r3: RouterInput<T3>,\n r4: RouterInput<T4>,\n r5: RouterInput<T5>,\n r6: RouterInput<T6>,\n r7: RouterInput<T7>,\n): RouterDefinition<DeepMergeAll<[T1, T2, T3, T4, T5, T6, T7]>>;\nexport function mergeRouters<\n T1 extends RouterConfig,\n T2 extends RouterConfig,\n T3 extends RouterConfig,\n T4 extends RouterConfig,\n T5 extends RouterConfig,\n T6 extends RouterConfig,\n T7 extends RouterConfig,\n T8 extends RouterConfig,\n>(\n r1: RouterInput<T1>,\n r2: RouterInput<T2>,\n r3: RouterInput<T3>,\n r4: RouterInput<T4>,\n r5: RouterInput<T5>,\n r6: RouterInput<T6>,\n r7: RouterInput<T7>,\n r8: RouterInput<T8>,\n): RouterDefinition<DeepMergeAll<[T1, T2, T3, T4, T5, T6, T7, T8]>>;\n\n// Variadic fallback for 9+\nexport function mergeRouters(\n ...routers: RouterInput<RouterConfig>[]\n): RouterDefinition<RouterConfig>;\n\n// Implementation\nexport function mergeRouters(\n ...routers: RouterInput<RouterConfig>[]\n): RouterDefinition<RouterConfig> {\n const merged = routers.map(extractRoutes).reduce(deepMergeConfigs);\n return defineRouter(merged);\n}\n","/**\n * @fileoverview Route utility functions.\n *\n * @module unified/route/utils\n */\n\n/**\n * Generates an operationId from a router key path.\n *\n * Converts dotted key paths to camelCase:\n * - `\"users.list\"` → `\"usersList\"`\n * - `\"organizations.members.get\"` → `\"organizationsMembersGet\"`\n *\n * @param key - The dotted router key path\n * @returns A camelCase operationId string\n */\nexport function generateOperationId(key: string): string {\n return key\n .split('.')\n .map((segment, index) =>\n index === 0 ? segment : segment.charAt(0).toUpperCase() + segment.slice(1),\n )\n .join('');\n}\n","/**\n * @fileoverview Server types for the unified route system.\n *\n * @module unified/server/types\n */\n\nimport type {\n HttpMethod,\n RouteDefinition,\n RouterConfig,\n RouterKeys,\n GetRoute,\n} from '../route/types';\n\n// ============================================================================\n// Validated Request\n// ============================================================================\n\n/**\n * A validated request with typed data.\n * This is what handlers receive after validation passes.\n */\nexport interface ValidatedRequest<TRoute extends RouteDefinition> {\n /**\n * Validated request body.\n */\n readonly body: TRoute['_types']['body'];\n\n /**\n * Validated query parameters.\n */\n readonly query: TRoute['_types']['query'];\n\n /**\n * Validated path parameters.\n */\n readonly pathParams: TRoute['_types']['pathParams'];\n\n /**\n * Validated headers.\n */\n readonly headers: TRoute['_types']['headers'];\n\n /**\n * Raw request object for advanced use cases.\n */\n readonly raw: {\n readonly method: string;\n readonly url: string;\n readonly headers: Record<string, string>;\n };\n}\n\n/**\n * Typed context based on route definition.\n * If the route defines a context schema, this will be the validated type.\n * Otherwise, it falls back to the generic HandlerContext.\n */\nexport type TypedContext<TRoute extends RouteDefinition> =\n TRoute['_types']['context'] extends undefined ? HandlerContext : TRoute['_types']['context'];\n\n// ============================================================================\n// Handler Types\n// ============================================================================\n\n/**\n * Context passed to handlers.\n * Can be extended with custom context via serverRoutes options.\n */\nexport interface HandlerContext {\n /**\n * Request ID for tracing.\n */\n readonly requestId?: string;\n\n /**\n * Additional context data.\n */\n readonly [key: string]: unknown;\n}\n\n/**\n * Response from a handler.\n */\nexport interface HandlerResponse<TData = unknown> {\n /**\n * HTTP status code.\n */\n readonly status: number;\n\n /**\n * Response body.\n */\n readonly body?: TData;\n\n /**\n * Response headers.\n */\n readonly headers?: Record<string, string>;\n}\n\n// ============================================================================\n// Use Case Port\n// ============================================================================\n\n/**\n * Use case port interface for unified routes.\n *\n * This is a simplified version that accepts any input/output types (plain objects).\n * It's structurally compatible with `BaseInboundPort`, so existing use case\n * implementations work without changes.\n *\n * @typeParam TInput - Input type (plain object or void for no input)\n * @typeParam TOutput - Output type (plain object or void for no output)\n *\n * @example\n * ```typescript\n * // Define plain types for use case contracts\n * type CreateProjectInput = {\n * name: string;\n * description?: string;\n * };\n *\n * type CreateProjectOutput = {\n * projectId: string;\n * };\n *\n * // Use case implements this interface\n * class CreateProjectUseCase implements UseCasePort<CreateProjectInput, CreateProjectOutput> {\n * async execute(input: CreateProjectInput): Promise<CreateProjectOutput> {\n * // ... implementation\n * return { projectId: '...' };\n * }\n * }\n * ```\n */\n\nexport interface UseCasePort<TInput = void, TOutput = void> {\n execute(input?: TInput): Promise<TOutput>;\n}\n\n// ============================================================================\n// Server Configuration\n// ============================================================================\n\n/**\n * Handler configuration for a single route.\n *\n * Mirrors the BaseController pattern with three components:\n * - `requestMapper`: Maps validated HTTP request to use case input\n * - `useCase`: The use case to execute\n * - `responseMapper`: Maps use case output to HTTP response\n *\n * @typeParam TRoute - The route definition type\n * @typeParam TInput - Use case input type (plain object)\n * @typeParam TOutput - Use case output type (plain object)\n *\n * @example\n * ```typescript\n * const config: RouteHandlerConfig<typeof createProjectRoute, CreateProjectInput, CreateProjectOutput> = {\n * requestMapper: (req) => ({\n * name: req.body.name,\n * description: req.body.description,\n * }),\n * useCase: createProjectUseCase,\n * responseMapper: (out) => ({\n * status: 201,\n * body: { projectId: out.projectId },\n * }),\n * };\n * ```\n */\n\nexport interface RouteHandlerConfig<TRoute extends RouteDefinition, TInput = void, TOutput = void> {\n /**\n * Maps the validated HTTP request to use case input.\n * The request has already been validated by the route's schemas.\n * Context is typed based on the route's context schema (if defined).\n */\n readonly requestMapper: (req: ValidatedRequest<TRoute>, ctx: TypedContext<TRoute>) => TInput;\n\n /**\n * The use case to execute.\n * Can be any object with an `execute` method matching `UseCasePort`.\n */\n readonly useCase: UseCasePort<TInput, TOutput>;\n\n /**\n * Maps the use case output to an HTTP response.\n * Determines the status code and response body.\n */\n readonly responseMapper: (output: TOutput) => HandlerResponse;\n\n /**\n * Middleware to run before the handler.\n */\n readonly middleware?: readonly MiddlewareFunction[];\n}\n\n/**\n * Middleware function type.\n */\nexport type MiddlewareFunction = (\n request: unknown,\n context: HandlerContext,\n next: () => Promise<HandlerResponse>,\n) => Promise<HandlerResponse>;\n\n// ============================================================================\n// Simple Handler Types\n// ============================================================================\n\n/**\n * Simple handler function that directly returns a response.\n * Use this for simple routes that don't need the use case pattern.\n */\nexport type SimpleHandlerFn<TRoute extends RouteDefinition> = (\n req: ValidatedRequest<TRoute>,\n ctx: TypedContext<TRoute>,\n) => Promise<HandlerResponse> | HandlerResponse;\n\n/**\n * Configuration for a simple handler (no use case).\n */\nexport interface SimpleHandlerConfig<TRoute extends RouteDefinition> {\n readonly handler: SimpleHandlerFn<TRoute>;\n readonly middleware?: readonly MiddlewareFunction[];\n}\n\n/**\n * Union of all handler config types.\n * Used internally to store handlers in the builder.\n */\nexport type AnyHandlerConfig<TRoute extends RouteDefinition, TInput = unknown, TOutput = unknown> =\n | RouteHandlerConfig<TRoute, TInput, TOutput>\n | SimpleHandlerConfig<TRoute>;\n\n/**\n * Type guard to check if config is a simple handler.\n */\nexport function isSimpleHandlerConfig(\n config: AnyHandlerConfig<RouteDefinition, unknown, unknown>,\n): config is SimpleHandlerConfig<RouteDefinition> {\n return 'handler' in config && typeof config.handler === 'function';\n}\n\n/**\n * Configuration mapping route keys to handlers.\n *\n * Each route key maps to a `RouteHandlerConfig` with:\n * - The route definition for that key (provides request/response types)\n * - User-defined input/output types for the use case\n *\n * The `TInput` and `TOutput` types are inferred from the `useCase` property,\n * so you don't need to specify them explicitly.\n */\n// TInput/TOutput are user-defined per route - any is required for heterogeneous route configs\nexport type ServerRoutesConfig<T extends RouterConfig> = {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n [K in RouterKeys<T>]: RouteHandlerConfig<GetRoute<T, K>, any, any>;\n};\n\n/**\n * Options for creating server routes.\n */\nexport interface CreateServerRoutesOptions {\n /**\n * Global middleware to run before all handlers.\n */\n readonly middleware?: readonly MiddlewareFunction[];\n\n /**\n * Whether to validate incoming requests against route schemas.\n * When enabled, invalid requests throw InvalidRequestError.\n * @default true\n */\n readonly validateRequest?: boolean;\n\n /**\n * Whether to validate outgoing responses against route schemas.\n * When enabled, invalid responses throw ControllerError.\n * Useful for catching bugs and ensuring API contract compliance.\n * @default true\n */\n readonly validateResponse?: boolean;\n\n /**\n * Context factory to create handler context.\n */\n readonly createContext?: (rawRequest: unknown) => HandlerContext;\n\n /**\n * Allow partial handler configuration (not all routes need handlers).\n * When true, missing handlers are silently skipped.\n * When false (default), missing handlers throw an error.\n * @default false\n * @internal Used by builder pattern's buildPartial()\n */\n readonly allowPartial?: boolean;\n}\n\n// ============================================================================\n// Route Input (for framework adapters)\n// ============================================================================\n\n/**\n * Route input compatible with framework adapters.\n * This is the output of serverRoutes().build().\n */\nexport interface UnifiedRouteInput {\n /**\n * HTTP method.\n */\n readonly method: HttpMethod;\n\n /**\n * URL path pattern.\n */\n readonly path: string;\n\n /**\n * Handler function.\n */\n readonly handler: (\n rawRequest: RawHttpRequest,\n context?: HandlerContext,\n ) => Promise<HandlerResponse>;\n\n /**\n * Route metadata for documentation.\n */\n readonly metadata: {\n readonly operationId?: string;\n readonly summary?: string;\n readonly description?: string;\n readonly tags?: readonly string[];\n readonly deprecated?: boolean;\n };\n}\n\n/**\n * Raw HTTP request from the framework.\n */\nexport interface RawHttpRequest {\n readonly method: string;\n readonly url: string;\n readonly headers: Record<string, string | string[] | undefined>;\n readonly body?: unknown;\n readonly query?: Record<string, string | string[] | undefined>;\n readonly params?: Record<string, string>;\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/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 /** Authorization denied - user lacks permission for this operation */\n FORBIDDEN: 'FORBIDDEN',\n /** Authentication required or invalid - user is not authenticated */\n UNAUTHORIZED: 'UNAUTHORIZED',\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 '../../global/exceptions/coded-error.error';\nimport { ErrorCodes, type PresentationErrorCode } 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 '../../global/exceptions/coded-error.error';\nimport { ErrorCodes, type PresentationErrorCode } 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 { 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 authentication is required or invalid.\n *\n * Indicates that the user is not authenticated or their authentication\n * credentials are invalid/expired. This is different from `ForbiddenError`\n * which is for authenticated users who lack permission.\n *\n * **When to throw:**\n * - User is not logged in but authentication is required\n * - Authentication token is missing, invalid, or expired\n * - Session has been invalidated\n * - API key is invalid or revoked\n *\n * **Difference from ForbiddenError:**\n * - `UnauthorizedError` (401) = Not authenticated (who are you?)\n * - `ForbiddenError` (403) = Authenticated but not authorized (you can't do this)\n *\n * @example Missing authentication\n * ```typescript\n * protected async authorize(input: Input): Promise<AuthContext> {\n * if (!input.userId) {\n * throw new UnauthorizedError({ message: 'Authentication required' });\n * }\n *\n * const user = await this.userRepo.findById(input.userId);\n * if (!user) {\n * throw new UnauthorizedError({ message: 'Invalid user credentials' });\n * }\n *\n * return { user };\n * }\n * ```\n *\n * @example Token validation\n * ```typescript\n * if (!token || isTokenExpired(token)) {\n * throw new UnauthorizedError({\n * message: 'Session expired, please log in again',\n * code: 'SESSION_EXPIRED',\n * });\n * }\n * ```\n *\n * @extends UseCaseError\n */\nexport class UnauthorizedError extends UseCaseError {\n /**\n * Creates a new UnauthorizedError instance.\n *\n * @param options - Error configuration\n * @param options.message - Description of why authentication failed\n * @param options.code - Machine-readable error code (default: 'UNAUTHORIZED')\n * @param options.cause - Optional underlying error\n */\n constructor({\n message,\n code = ErrorCodes.App.UNAUTHORIZED,\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 UnauthorizedError from a caught error.\n *\n * @param cause - The original caught error\n * @returns A new UnauthorizedError instance with the cause attached\n */\n static override fromError(cause: unknown): UnauthorizedError {\n return new UnauthorizedError({\n message: cause instanceof Error ? cause.message : 'Authentication required',\n cause,\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","/**\n * @fileoverview Internal implementation for creating server routes with auto-validation.\n *\n * Generates server-side route handlers from a router definition.\n * Each handler automatically validates incoming requests and outgoing\n * responses against the route's schemas.\n *\n * @module unified/server/create-server-routes\n * @internal\n */\n\nimport type { SchemaAdapter, ValidationIssue } from '../schema/types';\nimport type { RouterConfig, RouterDefinition, RouteDefinition } from '../route/types';\nimport { isRouterDefinition, collectRoutes, normalizePath } from '../route/types';\nimport type {\n AnyHandlerConfig,\n CreateServerRoutesOptions,\n HandlerContext,\n HandlerResponse,\n RawHttpRequest,\n UnifiedRouteInput,\n ValidatedRequest,\n} from './types';\nimport { isSimpleHandlerConfig } from './types';\nimport { InvalidRequestError } from '../../exceptions/invalid-request.error';\nimport { ControllerError } from '../../exceptions/controller.error';\nimport { UnauthorizedError } from '../../../app/exceptions/unauthorized.error';\nimport { wrapError } from '../../../global/utils/wrap-error.util';\nimport { generateOperationId } from '../route/utils';\n\n/**\n * Internal implementation for creating server routes.\n * Used by the builder pattern (serverRoutes).\n *\n * @internal\n */\nexport function createServerRoutesInternal<T extends RouterConfig>(\n router: T | RouterDefinition<T>,\n handlers: Record<string, AnyHandlerConfig<RouteDefinition, unknown, unknown>>,\n options?: CreateServerRoutesOptions,\n): UnifiedRouteInput[] {\n const routes = isRouterDefinition(router) ? router.routes : router;\n const collectedRoutes = collectRoutes(routes);\n\n // Sort routes by specificity: static segments before parameterized\n // This ensures /api/users/me is registered before /api/users/:userId\n const sortedRoutes = sortRoutesBySpecificity(collectedRoutes);\n\n const result: UnifiedRouteInput[] = [];\n\n // Default validation options to true, allowPartial to false\n const resolvedOptions: CreateServerRoutesOptions = {\n ...options,\n validateRequest: options?.validateRequest ?? true,\n validateResponse: options?.validateResponse ?? true,\n allowPartial: options?.allowPartial ?? false,\n };\n\n for (const { key, route } of sortedRoutes) {\n const handlerConfig = handlers[key] as AnyHandlerConfig<RouteDefinition, any, any> | undefined;\n\n if (!handlerConfig) {\n if (resolvedOptions.allowPartial) {\n // Skip routes without handlers when allowPartial is true\n continue;\n }\n throw new Error(\n `Missing handler for route \"${key}\". All routes must have a handler configuration.`,\n );\n }\n\n result.push(createRouteHandler(key, route, handlerConfig, resolvedOptions));\n }\n\n return result;\n}\n\n/**\n * Sorts routes by path specificity to ensure correct route matching.\n *\n * Static path segments are sorted before parameterized segments at each position.\n * This ensures that `/api/users/me` is registered before `/api/users/:userId`,\n * preventing the parameterized route from incorrectly matching the static path.\n *\n * @example\n * Given routes:\n * - /api/users/:userId (parameterized)\n * - /api/users/me (static)\n *\n * After sorting:\n * - /api/users/me (registered first - matches exactly)\n * - /api/users/:userId (registered second - catches remaining)\n */\nfunction sortRoutesBySpecificity<T extends { route: { path: string } }>(routes: T[]): T[] {\n return [...routes].sort((a, b) => {\n const aSegments = a.route.path.split('/').filter(Boolean);\n const bSegments = b.route.path.split('/').filter(Boolean);\n\n const maxLen = Math.max(aSegments.length, bSegments.length);\n\n for (let i = 0; i < maxLen; i++) {\n const aSeg = aSegments[i];\n const bSeg = bSegments[i];\n\n // Missing segment (shorter path) - shorter paths first for same prefix\n if (aSeg === undefined && bSeg !== undefined) return -1;\n if (aSeg !== undefined && bSeg === undefined) return 1;\n if (aSeg === undefined || bSeg === undefined) return 0;\n\n // Check if segment is parameterized (supports both :param and {param} formats)\n const aIsParam = aSeg.startsWith(':') || (aSeg.startsWith('{') && aSeg.endsWith('}'));\n const bIsParam = bSeg.startsWith(':') || (bSeg.startsWith('{') && bSeg.endsWith('}'));\n\n // Static segments come before parameterized segments\n if (!aIsParam && bIsParam) return -1;\n if (aIsParam && !bIsParam) return 1;\n\n // Both static or both parameterized - compare alphabetically for stable sorting\n const cmp = aSeg.localeCompare(bSeg);\n if (cmp !== 0) return cmp;\n }\n\n return 0;\n });\n}\n\n/**\n * Creates a single route handler with validation.\n *\n * Supports two handler patterns:\n * - Simple handler: handler(req, ctx) → response\n * - Use case pattern: requestMapper → useCase.execute → responseMapper\n */\nfunction createRouteHandler(\n key: string,\n route: RouteDefinition,\n // TInput/TOutput are user-defined and erased at this level - any is required for type compatibility\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n config: AnyHandlerConfig<RouteDefinition, any, any>,\n options: CreateServerRoutesOptions,\n): UnifiedRouteInput {\n const middleware = config.middleware ?? [];\n const globalMiddleware = options?.middleware ?? [];\n const allMiddleware = [...globalMiddleware, ...middleware];\n\n const shouldValidateRequest = options.validateRequest ?? true;\n const shouldValidateResponse = options.validateResponse ?? true;\n\n return {\n method: route.method,\n path: normalizePath(route.path),\n metadata: {\n operationId: route.docs.operationId ?? generateOperationId(key),\n summary: route.docs.summary,\n description: route.docs.description,\n tags: route.docs.tags as string[],\n deprecated: route.docs.deprecated,\n },\n handler: async (rawRequest: RawHttpRequest, ctx?: HandlerContext): Promise<HandlerResponse> => {\n // Create context\n const rawContext: HandlerContext = options?.createContext\n ? options.createContext(rawRequest)\n : (ctx ?? { requestId: generateRequestId() });\n\n // Validate context (if schema defined)\n // Context validation failures are treated as authentication errors (401)\n // because context typically carries auth data (user, session, token).\n // A missing or invalid context means the caller is not properly authenticated.\n const validatedContext: unknown = route.request.context\n ? wrapError(\n () => {\n const result = validateContextData(route, rawContext);\n if (!result.success) {\n const errors = result.errors ?? [];\n throw new InvalidRequestError({\n message: 'Context validation failed',\n validationErrors: errors.map((e) => ({\n field: e.path.join('.'),\n message: e.message,\n })),\n });\n }\n return result.data;\n },\n () => new UnauthorizedError({ message: 'Authentication required' }),\n )\n : rawContext;\n\n // Validate request (if enabled)\n // Use internal type since specific route types are erased in this function\n let validatedRequest: ValidatedRequestInternal;\n\n if (shouldValidateRequest) {\n const validationResult = validateRequestData(route, rawRequest);\n\n if (!validationResult.success) {\n const errors = validationResult.errors ?? [];\n throw new InvalidRequestError({\n message: 'Request validation failed',\n validationErrors: errors.map((e) => ({\n field: e.path.join('.'),\n message: e.message,\n })),\n });\n }\n\n const data = validationResult.data ?? {};\n\n validatedRequest = {\n body: data.body,\n query: data.query,\n pathParams: data.pathParams,\n headers: data.headers,\n raw: {\n method: rawRequest.method,\n url: rawRequest.url,\n headers: normalizeHeaders(rawRequest.headers),\n },\n };\n } else {\n // Skip validation - pass through normalized data\n\n validatedRequest = {\n body: rawRequest.body,\n query: normalizeQuery(rawRequest.query),\n pathParams: normalizePathParams(rawRequest.params),\n headers: normalizeHeaders(rawRequest.headers),\n raw: {\n method: rawRequest.method,\n url: rawRequest.url,\n headers: normalizeHeaders(rawRequest.headers),\n },\n };\n }\n\n // Execute the pipeline based on handler type\n // Errors from the use case/handler propagate to the framework's error handler\n const executePipeline = async (): Promise<HandlerResponse> => {\n if (isSimpleHandlerConfig(config)) {\n // Simple handler: direct call\n return config.handler(\n validatedRequest as unknown as ValidatedRequest<RouteDefinition>,\n validatedContext as HandlerContext,\n );\n } else {\n // Use case handler: requestMapper → useCase → responseMapper\n const { requestMapper, useCase, responseMapper } = config;\n\n // Map request to use case input\n // Cast is safe: ValidatedRequestInternal has same shape as ValidatedRequest<TRoute>\n // Type erasure in this function requires the cast for TypeScript\n // validatedContext is typed correctly based on route's context schema\n const input = requestMapper(\n validatedRequest as unknown as ValidatedRequest<RouteDefinition>,\n validatedContext as HandlerContext,\n );\n\n // Execute use case\n const output = await useCase.execute(input);\n\n // Map output to HTTP response\n return responseMapper(output);\n }\n };\n\n let response: HandlerResponse;\n\n if (allMiddleware.length === 0) {\n response = await executePipeline();\n } else {\n // Build middleware chain\n // Note: Middleware receives the raw context before validation\n let index = 0;\n const next = async (): Promise<HandlerResponse> => {\n if (index >= allMiddleware.length) {\n return executePipeline();\n }\n // eslint-disable-next-line @typescript-eslint/no-non-null-assertion -- index bounds checked above\n const mw = allMiddleware[index++]!;\n return mw(rawRequest, rawContext, next);\n };\n\n response = await next();\n }\n\n // Always validate status code (must be 100-599)\n validateStatusCode(response.status);\n\n // Validate response schema (if enabled)\n if (shouldValidateResponse) {\n const responseValidationResult = validateResponseData(route, response);\n\n if (!responseValidationResult.success) {\n const errors = responseValidationResult.errors ?? [];\n throw new ControllerError({\n message: 'Response validation failed',\n code: 'RESPONSE_VALIDATION_ERROR',\n cause: new Error(errors.map((e) => `${e.path.join('.')}: ${e.message}`).join('; ')),\n });\n }\n }\n\n return response;\n },\n };\n}\n\n/**\n * Validates request data against route request schemas.\n */\nfunction validateRequestData(\n route: RouteDefinition,\n rawRequest: RawHttpRequest,\n): ValidationResultInternal {\n const errors: ValidationIssue[] = [];\n const data: {\n body?: unknown;\n query?: unknown;\n pathParams?: unknown;\n headers?: unknown;\n } = {};\n\n // Validate body\n if (route.request.body) {\n const result = (route.request.body as SchemaAdapter).validate(rawRequest.body);\n if (result.success) {\n data.body = result.data;\n } else {\n errors.push(\n ...result.issues.map((issue) => ({\n ...issue,\n path: ['body', ...issue.path],\n })),\n );\n }\n }\n\n // Validate query\n if (route.request.query) {\n const queryObj = normalizeQuery(rawRequest.query);\n const result = (route.request.query as SchemaAdapter).validate(queryObj);\n if (result.success) {\n data.query = result.data;\n } else {\n errors.push(\n ...result.issues.map((issue) => ({\n ...issue,\n path: ['query', ...issue.path],\n })),\n );\n }\n }\n\n // Validate path params\n if (route.request.params) {\n const result = (route.request.params as SchemaAdapter).validate(rawRequest.params ?? {});\n if (result.success) {\n data.pathParams = result.data;\n } else {\n errors.push(\n ...result.issues.map((issue) => ({\n ...issue,\n path: ['pathParams', ...issue.path],\n })),\n );\n }\n } else {\n // Normalize raw params if no schema (ensure all values are strings)\n data.pathParams = normalizePathParams(rawRequest.params);\n }\n\n // Validate headers\n if (route.request.headers) {\n const headersObj = normalizeHeaders(rawRequest.headers);\n const result = (route.request.headers as SchemaAdapter).validate(headersObj);\n if (result.success) {\n data.headers = result.data;\n } else {\n errors.push(\n ...result.issues.map((issue) => ({\n ...issue,\n path: ['headers', ...issue.path],\n })),\n );\n }\n }\n\n if (errors.length > 0) {\n return { success: false, errors };\n }\n\n return { success: true, data };\n}\n\n/**\n * Validates response data against the route's response schema.\n *\n * Looks up the matching status code in `route.responses` and validates\n * the response body against its schema, if one is defined.\n */\nfunction validateResponseData(\n route: RouteDefinition,\n response: HandlerResponse,\n): ValidationResultInternal {\n if (!route.responses) {\n return { success: true };\n }\n\n const entry = route.responses[String(response.status)];\n const schema = entry?.schema as SchemaAdapter | undefined;\n\n if (!schema) {\n return { success: true };\n }\n\n const result = schema.validate(response.body);\n\n if (result.success) {\n return { success: true };\n }\n\n const errors = result.issues.map((issue) => ({\n ...issue,\n path: ['response', ...issue.path],\n }));\n\n return { success: false, errors };\n}\n\n/**\n * Validates context data against route context schema.\n */\nfunction validateContextData(\n route: RouteDefinition,\n context: HandlerContext,\n): ContextValidationResultInternal {\n const contextSchema = route.request.context as SchemaAdapter | undefined;\n\n // No context schema defined - skip validation\n if (!contextSchema) {\n return { success: true, data: context };\n }\n\n // Validate context against schema\n const result = contextSchema.validate(context);\n\n if (result.success) {\n return { success: true, data: result.data };\n }\n\n // Prefix errors with 'context.' for clarity\n const errors = result.issues.map((issue) => ({\n ...issue,\n path: ['context', ...issue.path],\n }));\n\n return { success: false, errors };\n}\n\ninterface ValidationResultInternal {\n success: boolean;\n errors?: ValidationIssue[];\n data?: {\n body?: unknown;\n query?: unknown;\n pathParams?: unknown;\n headers?: unknown;\n };\n}\n\ninterface ContextValidationResultInternal {\n success: boolean;\n errors?: ValidationIssue[];\n data?: unknown;\n}\n\n/**\n * Internal validated request type with unknown fields.\n * Used inside createRouteHandler where specific types are erased.\n * The requestMapper receives the properly typed ValidatedRequest<TRoute>.\n */\ninterface ValidatedRequestInternal {\n readonly body: unknown;\n readonly query: unknown;\n readonly pathParams: unknown;\n readonly headers: unknown;\n readonly raw: {\n readonly method: string;\n readonly url: string;\n readonly headers: Record<string, string>;\n };\n}\n\n/**\n * Validates that an HTTP status code is in the valid range (100-599).\n *\n * @throws {ControllerError} If the status code is invalid\n */\nfunction validateStatusCode(status: number): void {\n if (!Number.isInteger(status) || status < 100 || status > 599) {\n throw new ControllerError({\n message: `Invalid HTTP status code: ${status}. Status must be an integer between 100 and 599.`,\n code: 'INVALID_STATUS_CODE',\n });\n }\n}\n\n/**\n * Normalizes query parameters, preserving arrays for duplicate keys.\n *\n * When a query parameter appears multiple times (e.g., `?tag=a&tag=b`),\n * the framework provides an array. This function preserves that array\n * so schema validation can properly validate array vs single-value params.\n *\n * Empty strings are allowed (e.g., `?flag=` results in `{ flag: '' }`).\n * Undefined values are filtered out from arrays.\n */\nfunction normalizeQuery(\n query?: Record<string, string | string[] | undefined>,\n): Record<string, string | string[]> {\n if (!query) return {};\n\n const result: Record<string, string | string[]> = {};\n for (const [key, value] of Object.entries(query)) {\n if (value === undefined) continue;\n\n if (Array.isArray(value)) {\n // Filter out undefined values but preserve the array structure\n const definedValues = value.filter((v): v is string => v !== undefined);\n if (definedValues.length === 1 && definedValues[0] !== undefined) {\n // Single value in array - unwrap for convenience\n result[key] = definedValues[0];\n } else if (definedValues.length > 1) {\n // Multiple values - preserve as array for schema validation\n result[key] = definedValues;\n }\n // Empty array (all undefined) - skip this key\n } else {\n result[key] = value;\n }\n }\n return result;\n}\n\n/**\n * Normalizes path parameters to ensure all values are non-empty strings.\n *\n * @throws {InvalidRequestError} If any path parameter is empty\n */\nfunction normalizePathParams(params?: Record<string, string>): Record<string, string> {\n if (!params) return {};\n\n const result: Record<string, string> = {};\n const emptyParams: string[] = [];\n\n for (const [key, value] of Object.entries(params)) {\n if (value !== undefined) {\n const stringValue = String(value);\n if (stringValue === '') {\n emptyParams.push(key);\n } else {\n result[key] = stringValue;\n }\n }\n }\n\n // Throw error for empty path params instead of silently filtering\n if (emptyParams.length > 0) {\n throw new InvalidRequestError({\n message: 'Path parameters cannot be empty',\n validationErrors: emptyParams.map((param) => ({\n field: `pathParams.${param}`,\n message: 'Path parameter cannot be empty',\n })),\n });\n }\n\n return result;\n}\n\n/**\n * Normalizes headers to a flat object.\n *\n * Per RFC 7230, multiple header values are joined with \", \" (comma + space).\n * Headers are lowercased for consistency.\n */\nfunction normalizeHeaders(\n headers: Record<string, string | string[] | undefined>,\n): Record<string, string> {\n const result: Record<string, string> = {};\n for (const [key, value] of Object.entries(headers)) {\n if (value === undefined) continue;\n\n if (Array.isArray(value)) {\n // Filter undefined values and join per RFC 7230\n const definedValues = value.filter((v): v is string => v !== undefined);\n if (definedValues.length > 0) {\n result[key.toLowerCase()] = definedValues.join(', ');\n }\n } else {\n result[key.toLowerCase()] = value;\n }\n }\n return result;\n}\n\n/**\n * Generates a unique request ID using crypto-secure UUID.\n */\nfunction generateRequestId(): string {\n return `req_${crypto.randomUUID()}`;\n}\n","/**\n * @fileoverview Builder pattern for creating type-safe server routes.\n *\n * The `serverRoutes` function returns a builder that provides 100% type inference\n * for all handler parameters - no manual type annotations required.\n *\n * @module unified/server/server-routes-builder\n */\n\nimport type { RouterConfig, RouterDefinition, GetRoute, RouterKeys } from '../route/types';\nimport type {\n AnyHandlerConfig,\n CreateServerRoutesOptions,\n HandlerResponse,\n MiddlewareFunction,\n RouteHandlerConfig,\n SimpleHandlerConfig,\n SimpleHandlerFn,\n TypedContext,\n UnifiedRouteInput,\n UseCasePort,\n ValidatedRequest,\n} from './types';\nimport { createServerRoutesInternal } from './create-server-routes';\nimport type { RouteDefinition } from '../route/types';\n\n// ============================================================================\n// Builder Types\n// ============================================================================\n\n/**\n * Error type displayed when attempting to build() with missing handlers.\n * The `___missingRoutes` property shows which routes are missing.\n */\nexport interface MissingHandlersError<TMissing extends string> {\n /**\n * This error indicates that not all routes have handlers.\n * Use buildPartial() to build with only the defined handlers,\n * or add handlers for the missing routes.\n */\n (options?: never): never;\n /** Routes that are missing handlers */\n readonly ___missingRoutes: TMissing;\n}\n\n/**\n * Handler configuration for the builder pattern.\n * Identical to RouteHandlerConfig but with proper TypedContext.\n */\nexport interface BuilderHandlerConfig<TRoute extends RouteDefinition, TInput, TOutput> {\n /**\n * Maps the validated HTTP request to use case input.\n * Both `req` and `ctx` are fully typed based on route schemas.\n */\n readonly requestMapper: (req: ValidatedRequest<TRoute>, ctx: TypedContext<TRoute>) => TInput;\n\n /**\n * The use case to execute.\n */\n readonly useCase: UseCasePort<TInput, TOutput>;\n\n /**\n * Maps the use case output to an HTTP response.\n */\n readonly responseMapper: (output: TOutput) => HandlerResponse;\n\n /**\n * Middleware to run before the handler.\n */\n readonly middleware?: readonly MiddlewareFunction[];\n}\n\n/**\n * Builder interface for creating type-safe server routes.\n *\n * Each `.handle()` call captures the specific route type and provides\n * full type inference for requestMapper, useCase, and responseMapper.\n *\n * @typeParam T - The router configuration type\n * @typeParam THandled - Union of route keys that have handlers (accumulates)\n *\n * @example\n * ```typescript\n * const routes = serverRoutes(projectRouter)\n * .handle('projects.create', {\n * requestMapper: (req, ctx) => ({\n * name: req.body.name, // Fully typed!\n * createdBy: ctx.userId, // Fully typed!\n * }),\n * useCase: createProjectUseCase,\n * responseMapper: (output) => ({\n * status: 201 as const,\n * body: { projectId: output.projectId },\n * }),\n * })\n * .handle('projects.list', { ... })\n * .build();\n * ```\n */\nexport interface ServerRoutesBuilder<T extends RouterConfig, THandled extends string = never> {\n /**\n * Register a simple handler for a route.\n * The handler receives validated request and context, returns response directly.\n *\n * @param key - The route key (e.g., 'projects.get')\n * @param handlerOrConfig - Simple handler function or configuration with handler and optional middleware\n * @returns A new builder with the route key added to handled routes\n */\n handle<K extends Exclude<RouterKeys<T>, THandled>>(\n key: K,\n handlerOrConfig: SimpleHandlerFn<GetRoute<T, K>> | SimpleHandlerConfig<GetRoute<T, K>>,\n ): ServerRoutesBuilder<T, THandled | K>;\n\n /**\n * Register a handler using the use case pattern.\n * Follows: requestMapper → useCase.execute() → responseMapper\n *\n * @param key - The route key (e.g., 'projects.create')\n * @param config - Handler configuration with requestMapper, useCase, responseMapper\n * @returns A new builder with the route key added to handled routes\n */\n handleWithUseCase<K extends Exclude<RouterKeys<T>, THandled>, TInput, TOutput>(\n key: K,\n config: BuilderHandlerConfig<GetRoute<T, K>, TInput, TOutput>,\n ): ServerRoutesBuilder<T, THandled | K>;\n\n /**\n * Build the routes array for framework registration.\n *\n * This method is only available when ALL routes have handlers.\n * If some routes are missing handlers, use `buildPartial()` instead.\n *\n * @param options - Optional configuration (validation, middleware)\n * @returns Array of route inputs for framework registration\n *\n * @throws {Error} At compile time if routes are missing (type error)\n */\n build: [Exclude<RouterKeys<T>, THandled>] extends [never]\n ? (options?: CreateServerRoutesOptions) => UnifiedRouteInput[]\n : MissingHandlersError<Exclude<RouterKeys<T>, THandled>>;\n\n /**\n * Build routes for only the defined handlers.\n *\n * Use this when you only want to register handlers for some routes,\n * not all routes in the router. No compile-time enforcement.\n *\n * @param options - Optional configuration (validation, middleware)\n * @returns Array of route inputs for framework registration\n */\n buildPartial(options?: CreateServerRoutesOptions): UnifiedRouteInput[];\n}\n\n// ============================================================================\n// Builder Implementation\n// ============================================================================\n\n/**\n * Internal builder implementation.\n *\n * Uses an immutable pattern where each handle() call returns a new\n * builder instance with the updated handlers map.\n */\nclass ServerRoutesBuilderImpl<T extends RouterConfig, THandled extends string = never> {\n private readonly router: T | RouterDefinition<T>;\n private readonly handlers: Map<string, AnyHandlerConfig<RouteDefinition, unknown, unknown>>;\n\n constructor(\n router: T | RouterDefinition<T>,\n handlers?: Map<string, AnyHandlerConfig<RouteDefinition, unknown, unknown>>,\n ) {\n this.router = router;\n this.handlers = handlers ?? new Map();\n }\n\n handle<K extends Exclude<RouterKeys<T>, THandled>>(\n key: K,\n handlerOrConfig: SimpleHandlerFn<GetRoute<T, K>> | SimpleHandlerConfig<GetRoute<T, K>>,\n ): ServerRoutesBuilder<T, THandled | K> {\n // Normalize function to config object\n const config: SimpleHandlerConfig<RouteDefinition> =\n typeof handlerOrConfig === 'function'\n ? { handler: handlerOrConfig as SimpleHandlerFn<RouteDefinition> }\n : (handlerOrConfig as SimpleHandlerConfig<RouteDefinition>);\n\n const newHandlers = new Map(this.handlers);\n newHandlers.set(key as string, config);\n\n return new ServerRoutesBuilderImpl<T, THandled | K>(\n this.router,\n newHandlers,\n ) as unknown as ServerRoutesBuilder<T, THandled | K>;\n }\n\n handleWithUseCase<K extends Exclude<RouterKeys<T>, THandled>, TInput, TOutput>(\n key: K,\n config: BuilderHandlerConfig<GetRoute<T, K>, TInput, TOutput>,\n ): ServerRoutesBuilder<T, THandled | K> {\n // Create new handlers map (immutable pattern)\n const newHandlers = new Map(this.handlers);\n newHandlers.set(key as string, config as RouteHandlerConfig<RouteDefinition, unknown, unknown>);\n\n // Return new builder with updated type\n // Cast through unknown is safe: the type system tracks THandled | K through the interface\n // The conditional type on `build` cannot be proven at compile time, hence the cast\n return new ServerRoutesBuilderImpl<T, THandled | K>(\n this.router,\n newHandlers,\n ) as unknown as ServerRoutesBuilder<T, THandled | K>;\n }\n\n // The build method's type is determined by the interface conditional type\n // At runtime, it always works the same way - the conditional type only affects compile-time\n build(options?: CreateServerRoutesOptions): UnifiedRouteInput[] {\n return createServerRoutesInternal(this.router, Object.fromEntries(this.handlers), options);\n }\n\n buildPartial(options?: CreateServerRoutesOptions): UnifiedRouteInput[] {\n return createServerRoutesInternal(this.router, Object.fromEntries(this.handlers), {\n ...options,\n allowPartial: true,\n });\n }\n}\n\n// ============================================================================\n// Public API\n// ============================================================================\n\n/**\n * Creates a type-safe server routes builder for a router.\n *\n * The builder pattern provides 100% type inference for all handler parameters:\n * - `req.body`, `req.query`, `req.pathParams`, `req.headers` are typed from route schemas\n * - `ctx` is typed from the route's context schema\n * - `output` in responseMapper is typed from the use case\n *\n * @param router - Router definition or router config\n * @returns Builder for registering handlers\n *\n * @example Basic usage\n * ```typescript\n * import { serverRoutes } from '@cosmneo/onion-lasagna/http/server';\n * import { projectRouter } from './router';\n *\n * const routes = serverRoutes(projectRouter)\n * .handle('projects.create', {\n * requestMapper: (req, ctx) => ({\n * name: req.body.name,\n * createdBy: ctx.userId,\n * }),\n * useCase: createProjectUseCase,\n * responseMapper: (output) => ({\n * status: 201 as const,\n * body: { projectId: output.projectId },\n * }),\n * })\n * .handle('projects.list', {\n * requestMapper: (req) => ({\n * page: req.query.page ?? 1,\n * limit: req.query.limit ?? 20,\n * }),\n * useCase: listProjectsUseCase,\n * responseMapper: (output) => ({\n * status: 200 as const,\n * body: output.projects,\n * }),\n * })\n * .build();\n *\n * // Register with framework\n * registerHonoRoutes(app, routes);\n * ```\n *\n * @example Partial build (only some routes)\n * ```typescript\n * const routes = serverRoutes(projectRouter)\n * .handle('projects.create', { ... })\n * // Skip other routes\n * .buildPartial(); // No type error even with missing routes\n * ```\n *\n * @example With options\n * ```typescript\n * const routes = serverRoutes(projectRouter)\n * .handle('projects.create', { ... })\n * .handle('projects.list', { ... })\n * .build({\n * validateRequest: true,\n * validateResponse: process.env.NODE_ENV !== 'production',\n * middleware: [loggingMiddleware],\n * });\n * ```\n */\nexport function serverRoutes<T extends RouterConfig>(\n router: T | RouterDefinition<T>,\n): ServerRoutesBuilder<T, never> {\n // Cast through unknown is safe: initial builder has no handlers (THandled = never)\n return new ServerRoutesBuilderImpl(router) as unknown as ServerRoutesBuilder<T, never>;\n}\n","/**\n * @fileoverview OpenAPI specification generation from router definitions (v2 — flat API).\n *\n * The `generateOpenAPI` function creates a complete OpenAPI 3.1 specification\n * from a router definition. All route schemas are converted to JSON Schema\n * and included in the specification.\n *\n * Schemas are read from `route.request` (body, query, params, headers) and\n * per-status response schemas from `route.responses`.\n *\n * @module unified/openapi/generate\n */\n\nimport type { JsonSchema, SchemaAdapter } from '../schema/types';\nimport type { RouterConfig, RouterDefinition, RouteDefinition } from '../route/types';\nimport { isRouterDefinition, collectRoutes, getPathParamNames } from '../route/types';\nimport { generateOperationId } from '../route/utils';\nimport type {\n OpenAPIConfig,\n OpenAPISpec,\n OpenAPIPaths,\n OpenAPIPathItem,\n OpenAPIOperation,\n OpenAPIParameter,\n OpenAPIRequestBody,\n OpenAPIResponses,\n OpenAPITag,\n} from './types';\n\n/**\n * Checks if a value is a valid JSON schema structure.\n *\n * A valid JSON schema must be an object and have at least one of:\n * - `type` property (primitive or object types)\n * - `$ref` property (reference to another schema)\n * - `oneOf`, `anyOf`, `allOf` (composition)\n * - `properties` (object schema without explicit type)\n * - `items` (array schema without explicit type)\n * - `enum` (enumeration)\n * - `const` (constant value)\n *\n * @param value - The value to check\n * @returns True if value appears to be a valid JSON schema\n */\nfunction isValidJsonSchema(value: unknown): value is JsonSchema {\n if (!value || typeof value !== 'object' || Array.isArray(value)) {\n return false;\n }\n\n const schema = value as Record<string, unknown>;\n\n // Check for valid JSON schema indicators\n return (\n 'type' in schema ||\n '$ref' in schema ||\n 'oneOf' in schema ||\n 'anyOf' in schema ||\n 'allOf' in schema ||\n 'properties' in schema ||\n 'items' in schema ||\n 'enum' in schema ||\n 'const' in schema\n );\n}\n\n/**\n * Generates an OpenAPI specification from a router definition.\n *\n * This function walks the router structure, extracts JSON schemas from\n * all route definitions, and builds a complete OpenAPI 3.1 specification.\n *\n * Operation IDs are auto-generated from the router key path when not\n * explicitly specified in the route docs.\n *\n * @param router - Router definition or router config\n * @param config - OpenAPI configuration (info, servers, security, etc.)\n * @returns Complete OpenAPI specification\n *\n * @example Basic usage\n * ```typescript\n * import { generateOpenAPI } from '@cosmneo/onion-lasagna/http/openapi';\n * import { api } from './routes';\n *\n * const spec = generateOpenAPI(api, {\n * info: {\n * title: 'My API',\n * version: '1.0.0',\n * description: 'A comprehensive API for managing resources',\n * },\n * servers: [\n * { url: 'http://localhost:3000', description: 'Development' },\n * { url: 'https://api.example.com', description: 'Production' },\n * ],\n * });\n *\n * // Serve the spec\n * app.get('/openapi.json', (c) => c.json(spec));\n * ```\n */\nexport function generateOpenAPI<T extends RouterConfig>(\n router: T | RouterDefinition<T>,\n config: OpenAPIConfig,\n): OpenAPISpec {\n const routes = isRouterDefinition(router) ? router.routes : router;\n const collectedRoutes = collectRoutes(routes);\n\n // Build paths\n const paths: OpenAPIPaths = {};\n const allTags = new Set<string>();\n\n for (const { key, route } of collectedRoutes) {\n const openAPIPath = convertToOpenAPIPath(route.path);\n\n if (!paths[openAPIPath]) {\n paths[openAPIPath] = {};\n }\n\n const operation = buildOperation(key, route);\n const method = route.method.toLowerCase() as keyof OpenAPIPathItem;\n\n (paths[openAPIPath] as Record<string, OpenAPIOperation>)[method] = operation;\n\n // Collect tags\n if (operation.tags) {\n for (const tag of operation.tags) {\n allTags.add(tag);\n }\n }\n }\n\n // Build the specification\n const spec: OpenAPISpec = {\n openapi: config.openapi ?? '3.1.0',\n info: config.info,\n paths,\n };\n\n // Add optional sections\n if (config.servers && config.servers.length > 0) {\n (spec as { servers: typeof config.servers }).servers = config.servers;\n }\n\n if (config.securitySchemes && Object.keys(config.securitySchemes).length > 0) {\n (spec as { components: { securitySchemes: typeof config.securitySchemes } }).components = {\n securitySchemes: config.securitySchemes,\n };\n }\n\n if (config.security && config.security.length > 0) {\n (spec as { security: typeof config.security }).security = config.security;\n }\n\n // Merge custom tags with collected tags\n const tags: OpenAPITag[] = config.tags ? [...config.tags] : [];\n for (const tagName of allTags) {\n if (!tags.some((t) => t.name === tagName)) {\n tags.push({ name: tagName });\n }\n }\n if (tags.length > 0) {\n (spec as unknown as { tags: OpenAPITag[] }).tags = tags;\n }\n\n if (config.externalDocs) {\n (spec as { externalDocs: typeof config.externalDocs }).externalDocs = config.externalDocs;\n }\n\n return spec;\n}\n\n/**\n * Converts a path with :param to OpenAPI {param} format.\n */\nfunction convertToOpenAPIPath(path: string): string {\n return path.replace(/:([a-zA-Z_][a-zA-Z0-9_]*)/g, '{$1}');\n}\n\n/**\n * Builds an OpenAPI operation from a route definition.\n * Auto-generates operationId from the key if not explicitly set.\n */\nfunction buildOperation(key: string, route: RouteDefinition): OpenAPIOperation {\n const operation: OpenAPIOperation = {\n responses: buildResponses(route),\n };\n\n // operationId: use explicit or auto-generate from router key\n const operationId = route.docs.operationId ?? generateOperationId(key);\n (operation as { operationId: string }).operationId = operationId;\n\n if (route.docs.summary) {\n (operation as { summary: string }).summary = route.docs.summary;\n }\n\n if (route.docs.description) {\n (operation as { description: string }).description = route.docs.description;\n }\n\n if (route.docs.tags && route.docs.tags.length > 0) {\n (operation as { tags: readonly string[] }).tags = route.docs.tags;\n }\n\n if (route.docs.deprecated) {\n (operation as { deprecated: boolean }).deprecated = true;\n }\n\n if (route.docs.security && route.docs.security.length > 0) {\n (operation as { security: typeof route.docs.security }).security = route.docs.security;\n }\n\n if (route.docs.externalDocs) {\n (operation as { externalDocs: typeof route.docs.externalDocs }).externalDocs =\n route.docs.externalDocs;\n }\n\n // Add parameters\n const parameters = buildParameters(route);\n if (parameters.length > 0) {\n (operation as unknown as { parameters: OpenAPIParameter[] }).parameters = parameters;\n }\n\n // Add request body\n if (route.request.body) {\n (operation as { requestBody: OpenAPIRequestBody }).requestBody = buildRequestBody(route);\n }\n\n return operation;\n}\n\n/**\n * Builds OpenAPI parameters from route request schemas.\n */\nfunction buildParameters(route: RouteDefinition): OpenAPIParameter[] {\n const parameters: OpenAPIParameter[] = [];\n\n // Path parameters\n const pathParamNames = getPathParamNames(route.path);\n for (const name of pathParamNames) {\n const param: OpenAPIParameter = {\n name,\n in: 'path',\n required: true,\n schema: { type: 'string' },\n };\n\n // If we have a params schema, try to get more info\n if (route.request.params) {\n const jsonSchema = (route.request.params as SchemaAdapter).toJsonSchema();\n if (jsonSchema.properties && typeof jsonSchema.properties === 'object') {\n const propSchema = (jsonSchema.properties as Record<string, unknown>)[name];\n if (isValidJsonSchema(propSchema)) {\n (param as { schema: JsonSchema }).schema = propSchema;\n }\n }\n }\n\n parameters.push(param);\n }\n\n // Query parameters\n if (route.request.query) {\n const querySchema = (route.request.query as SchemaAdapter).toJsonSchema();\n\n if (querySchema.properties && typeof querySchema.properties === 'object') {\n const requiredFields = new Set(\n Array.isArray(querySchema.required) ? querySchema.required : [],\n );\n\n for (const [name, propSchema] of Object.entries(\n querySchema.properties as Record<string, unknown>,\n )) {\n // Skip invalid schema structures\n if (!isValidJsonSchema(propSchema)) {\n continue;\n }\n\n const param: OpenAPIParameter = {\n name,\n in: 'query',\n required: requiredFields.has(name),\n schema: propSchema,\n };\n\n // Add description if present\n if ('description' in propSchema && typeof propSchema.description === 'string') {\n (param as { description: string }).description = propSchema.description;\n }\n\n parameters.push(param);\n }\n }\n }\n\n // Header parameters\n if (route.request.headers) {\n const headersSchema = (route.request.headers as SchemaAdapter).toJsonSchema();\n\n if (headersSchema.properties && typeof headersSchema.properties === 'object') {\n const requiredFields = new Set(\n Array.isArray(headersSchema.required) ? headersSchema.required : [],\n );\n\n for (const [name, propSchema] of Object.entries(\n headersSchema.properties as Record<string, unknown>,\n )) {\n // Skip invalid schema structures\n if (!isValidJsonSchema(propSchema)) {\n continue;\n }\n\n const param: OpenAPIParameter = {\n name,\n in: 'header',\n required: requiredFields.has(name),\n schema: propSchema,\n };\n\n parameters.push(param);\n }\n }\n }\n\n return parameters;\n}\n\n/**\n * Builds OpenAPI request body from route.\n * Reads metadata (contentType, required, description) from `route._meta.body`.\n */\nfunction buildRequestBody(route: RouteDefinition): OpenAPIRequestBody {\n const bodySchema = route.request.body as SchemaAdapter;\n const meta = route._meta?.body;\n\n const contentType = meta?.contentType ?? 'application/json';\n\n const requestBody: OpenAPIRequestBody = {\n required: meta?.required !== false,\n content: {\n [contentType]: {\n schema: bodySchema.toJsonSchema(),\n },\n },\n };\n\n if (meta?.description) {\n (requestBody as { description: string }).description = meta.description;\n }\n\n return requestBody;\n}\n\n/**\n * Builds OpenAPI responses from route.\n *\n * Each status code in `route.responses` gets its own entry with\n * description, schema, and content type. If no responses are defined,\n * a default `200` entry is generated.\n */\nfunction buildResponses(route: RouteDefinition): OpenAPIResponses {\n const responses: OpenAPIResponses = {};\n\n if (route.responses && Object.keys(route.responses).length > 0) {\n for (const [statusCode, config] of Object.entries(route.responses)) {\n const description = config.description ?? `Response ${statusCode}`;\n\n if (config.schema) {\n const contentType = config.contentType ?? 'application/json';\n responses[statusCode] = {\n description,\n content: {\n [contentType]: {\n schema: (config.schema as SchemaAdapter).toJsonSchema(),\n },\n },\n };\n } else {\n responses[statusCode] = { description };\n }\n }\n } else {\n responses['200'] = { description: 'Successful response' };\n }\n\n return responses;\n}\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 { 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 { ErrorCodes, type AppErrorCode } from '../../global/exceptions/error-codes.const';\nimport { UseCaseError } from './use-case.error';\n\n/**\n * Error thrown when authorization for an operation is denied.\n *\n * Indicates that the user is authenticated but lacks permission to perform\n * the requested operation. Commonly thrown from the `authorize()` method\n * of use cases when access checks fail.\n *\n * **When to throw:**\n * - User doesn't own the resource they're trying to modify\n * - User lacks required role or permission\n * - Organization/tenant isolation violation\n * - Business rule restricts the operation for this user\n *\n * **Difference from AccessDeniedError:**\n * - `ForbiddenError` is an application layer error (use case authorization)\n * - `AccessDeniedError` is a presentation layer error (controller/guard level)\n *\n * @example Use case authorization\n * ```typescript\n * class UpdateActivityUseCase extends BaseInboundAdapter<Input, Output, AuthContext> {\n * protected async authorize(input: Input): Promise<AuthContext> {\n * const activity = await this.activityRepo.findById(input.activityId);\n * if (!activity) {\n * throw new NotFoundError({ message: 'Activity not found' });\n * }\n * if (activity.organizationId !== input.organizationId) {\n * throw new ForbiddenError({\n * message: 'Not authorized to modify this activity',\n * code: 'ACTIVITY_ACCESS_DENIED',\n * });\n * }\n * return { activity };\n * }\n * }\n * ```\n *\n * @example Role-based authorization\n * ```typescript\n * if (!user.roles.includes('admin')) {\n * throw new ForbiddenError({\n * message: 'Admin role required for this operation',\n * });\n * }\n * ```\n *\n * @extends UseCaseError\n */\nexport class ForbiddenError extends UseCaseError {\n /**\n * Creates a new ForbiddenError instance.\n *\n * @param options - Error configuration\n * @param options.message - Description of why authorization was denied\n * @param options.code - Machine-readable error code (default: 'FORBIDDEN')\n * @param options.cause - Optional underlying error\n */\n constructor({\n message,\n code = ErrorCodes.App.FORBIDDEN,\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 ForbiddenError from a caught error.\n *\n * @param cause - The original caught error\n * @returns A new ForbiddenError instance with the cause attached\n */\n static override fromError(cause: unknown): ForbiddenError {\n return new ForbiddenError({\n message: cause instanceof Error ? cause.message : 'Operation forbidden',\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 { ErrorCodes, type PresentationErrorCode } 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","/**\n * @fileoverview Centralized error mapping for HTTP frameworks.\n *\n * Provides a single source of truth for mapping onion-lasagna errors\n * to HTTP status codes and response bodies.\n *\n * @module http/shared/error-mapping\n */\n\nimport { CodedError } from '../../../global/exceptions/coded-error.error';\nimport { ObjectValidationError } from '../../../global/exceptions/object-validation.error';\nimport { DomainError } from '../../../domain/exceptions/domain.error';\nimport { UseCaseError } from '../../../app/exceptions/use-case.error';\nimport { NotFoundError } from '../../../app/exceptions/not-found.error';\nimport { ConflictError } from '../../../app/exceptions/conflict.error';\nimport { UnprocessableError } from '../../../app/exceptions/unprocessable.error';\nimport { ForbiddenError } from '../../../app/exceptions/forbidden.error';\nimport { UnauthorizedError } from '../../../app/exceptions/unauthorized.error';\nimport { InfraError } from '../../../infra/exceptions/infra.error';\nimport { ControllerError } from '../../exceptions/controller.error';\nimport { AccessDeniedError } from '../../exceptions/access-denied.error';\nimport { InvalidRequestError } from '../../exceptions/invalid-request.error';\nimport type { ErrorResponseBody, MappedErrorResponse } from './types';\n\n// ============================================================================\n// Constants and Interfaces\n// ============================================================================\n\n/**\n * Default masked error response for internal errors.\n */\nconst MASKED_ERROR_BODY: ErrorResponseBody = {\n message: 'An unexpected error occurred',\n errorCode: 'INTERNAL_ERROR',\n};\n\n/**\n * Known internal error type names that should be masked.\n */\nconst INTERNAL_ERROR_TYPES = [\n 'DomainError',\n 'InfraError',\n 'ControllerError',\n 'NetworkError',\n 'PersistenceError',\n 'ExternalServiceError',\n 'InvariantViolationError',\n];\n\n/**\n * Validation error item structure.\n */\ninterface ValidationErrorInput {\n field: string;\n message: string;\n}\n\n/**\n * Validation error structure for string-based checking.\n */\ninterface ValidationErrorItem {\n field: string;\n message: string;\n}\n\n/**\n * Interface for errors with validation items.\n */\ninterface ErrorWithValidation {\n message: string;\n code: string;\n validationErrors: ValidationErrorItem[];\n}\n\n/**\n * Interface for coded errors.\n */\ninterface CodedErrorLike {\n message: string;\n code: string;\n}\n\n// ============================================================================\n// String-based type checking helpers (for bundled code compatibility)\n// ============================================================================\n\n/**\n * Checks if error matches a specific error type by checking its constructor name.\n * This approach avoids issues with multiple class instances in bundled code.\n * Handles both original names and tsup's mangled names (prefixed with _).\n *\n * @param error - The error to check\n * @param typeName - The error type name to match\n * @returns True if error matches the type name\n */\nexport function isErrorType(error: unknown, typeName: string): error is CodedErrorLike {\n if (!error || typeof error !== 'object') return false;\n // Guard against objects without constructor (e.g., Object.create(null))\n const constructor = Object.prototype.hasOwnProperty.call(error, 'constructor')\n ? (error as { constructor?: { name?: string } }).constructor\n : Object.getPrototypeOf(error)?.constructor;\n if (!constructor) return false;\n const name = constructor.name;\n // Check both the original name and the mangled name (tsup prefixes with _)\n return name === typeName || name === `_${typeName}`;\n}\n\n/**\n * Checks if error has validation errors array.\n *\n * @param error - The error to check\n * @returns True if error has validationErrors property\n */\nexport function hasValidationErrors(error: unknown): error is ErrorWithValidation {\n if (!error || typeof error !== 'object') return false;\n return (\n 'validationErrors' in error && Array.isArray((error as ErrorWithValidation).validationErrors)\n );\n}\n\n// ============================================================================\n// Response body builders\n// ============================================================================\n\n/**\n * Builds a validation error response body from error details.\n *\n * @param message - The error message\n * @param code - The error code\n * @param validationErrors - Array of field validation errors\n * @returns Error response body with errorItems\n */\nfunction buildValidationErrorBody(\n message: string,\n code: string,\n validationErrors: readonly ValidationErrorInput[],\n): ErrorResponseBody {\n return {\n message,\n errorCode: code,\n errorItems: validationErrors.map((e) => ({\n item: e.field,\n message: e.message,\n })),\n };\n}\n\n/**\n * Builds a simple error response body from error details.\n *\n * @param message - The error message\n * @param code - The error code\n * @returns Error response body\n */\nfunction buildSimpleErrorBody(message: string, code: string): ErrorResponseBody {\n return {\n message,\n errorCode: code,\n };\n}\n\n// ============================================================================\n// Primary error mapping functions (with bundled code fallback)\n// ============================================================================\n\n/**\n * Maps an error to the appropriate HTTP status code.\n * Uses instanceof first, then falls back to name-based checking for bundled code.\n *\n * @param error - The error to map\n * @returns HTTP status code\n */\nexport function getHttpStatusCode(error: unknown): number {\n // Try instanceof first (faster)\n if (error instanceof ObjectValidationError) return 400;\n if (error instanceof InvalidRequestError) return 400;\n if (error instanceof UnauthorizedError) return 401;\n if (error instanceof ForbiddenError) return 403;\n if (error instanceof AccessDeniedError) return 403;\n if (error instanceof NotFoundError) return 404;\n if (error instanceof ConflictError) return 409;\n if (error instanceof UnprocessableError) return 422;\n if (error instanceof UseCaseError) return 400;\n\n // Fall back to name-based checking for bundled code (e.g., _NotFoundError)\n if (isErrorType(error, 'ObjectValidationError')) return 400;\n if (isErrorType(error, 'InvalidRequestError')) return 400;\n if (isErrorType(error, 'UnauthorizedError')) return 401;\n if (isErrorType(error, 'ForbiddenError')) return 403;\n if (isErrorType(error, 'AccessDeniedError')) return 403;\n if (isErrorType(error, 'NotFoundError')) return 404;\n if (isErrorType(error, 'ConflictError')) return 409;\n if (isErrorType(error, 'UnprocessableError')) return 422;\n if (isErrorType(error, 'UseCaseError')) return 400;\n\n return 500;\n}\n\n/**\n * Checks if an error should have its details masked in the response.\n *\n * Security-sensitive errors (domain, infrastructure, controller) are masked\n * to prevent leaking implementation details.\n * Uses instanceof first, then falls back to name-based checking for bundled code.\n *\n * @param error - The error to check\n * @returns True if error details should be hidden\n */\nexport function shouldMaskError(error: unknown): boolean {\n // Try instanceof first (faster)\n if (\n error instanceof DomainError ||\n error instanceof InfraError ||\n error instanceof ControllerError\n ) {\n return true;\n }\n\n // Fall back to name-based checking for bundled code\n for (const errorType of INTERNAL_ERROR_TYPES) {\n if (isErrorType(error, errorType)) {\n return true;\n }\n }\n\n return false;\n}\n\n/**\n * Creates the response body for an error.\n * Uses instanceof first, then falls back to name-based checking for bundled code.\n *\n * @param error - The error to create body for\n * @returns Error response body\n */\nexport function createErrorResponseBody(error: unknown): ErrorResponseBody {\n // Masked errors - hide internal details\n if (shouldMaskError(error)) {\n return MASKED_ERROR_BODY;\n }\n\n // Validation errors - include field details (try instanceof first)\n if (error instanceof ObjectValidationError) {\n return buildValidationErrorBody(error.message, error.code, error.validationErrors);\n }\n if (error instanceof InvalidRequestError) {\n return buildValidationErrorBody(error.message, error.code, error.validationErrors);\n }\n\n // Validation errors - fall back to name-based checking for bundled code\n if (isErrorType(error, 'ObjectValidationError') && hasValidationErrors(error)) {\n return buildValidationErrorBody(error.message, error.code, error.validationErrors);\n }\n if (isErrorType(error, 'InvalidRequestError') && hasValidationErrors(error)) {\n return buildValidationErrorBody(error.message, error.code, error.validationErrors);\n }\n\n // Other coded errors - expose message and code (try instanceof first)\n if (error instanceof CodedError) {\n return buildSimpleErrorBody(error.message, error.code);\n }\n\n // Other coded errors - fall back to name-based checking\n if (isErrorType(error, 'CodedError')) {\n return buildSimpleErrorBody(error.message, error.code);\n }\n\n // Check for any error with message and code properties\n if (\n error &&\n typeof error === 'object' &&\n 'message' in error &&\n 'code' in error &&\n typeof (error as CodedErrorLike).message === 'string' &&\n typeof (error as CodedErrorLike).code === 'string'\n ) {\n return buildSimpleErrorBody((error as CodedErrorLike).message, (error as CodedErrorLike).code);\n }\n\n // Unknown errors - mask\n return MASKED_ERROR_BODY;\n}\n\n/**\n * Maps an error to a complete HTTP response structure.\n *\n * Mapping strategy (checked in order):\n * 1. `ObjectValidationError` / `InvalidRequestError` → 400 Bad Request (with field errors)\n * 2. `UseCaseError` → 400 Bad Request\n * 3. `UnauthorizedError` → 401 Unauthorized\n * 4. `ForbiddenError` / `AccessDeniedError` → 403 Forbidden\n * 5. `NotFoundError` → 404 Not Found\n * 6. `ConflictError` → 409 Conflict\n * 7. `UnprocessableError` → 422 Unprocessable Entity\n * 8. `DomainError` / `InfraError` / `ControllerError` → 500 Internal Server Error (masked)\n * 9. Unknown → 500 Internal Server Error (masked)\n *\n * @param error - The error to map\n * @returns Mapped error response with status and body\n */\nexport function mapErrorToHttpResponse(error: unknown): MappedErrorResponse {\n return {\n status: getHttpStatusCode(error),\n body: createErrorResponseBody(error),\n };\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACyFO,SAAS,oBACd,QACgC;AAChC,SAAO,OAAO,YAAY;AAC5B;AAKO,SAAS,oBAAuB,QAA0D;AAC/F,SAAO,OAAO,YAAY;AAC5B;;;AC0FO,SAAS,gBAAgB,OAAwC;AACtE,SACE,OAAO,UAAU,YACjB,UAAU,QACV,cAAc,SACd,OAAQ,MAAwB,aAAa,cAC7C,kBAAkB,SAClB,OAAQ,MAAwB,iBAAiB;AAErD;AAYO,SAAS,2BAA6D;AAC3E,SAAO;AAAA,IACL,UAAU,CAAC,UAAU,EAAE,SAAS,MAAM,KAAgB;AAAA,IACtD,cAAc,OAAO,CAAC;AAAA,IACtB,SAAS;AAAA,IACT,QAAQ;AAAA,EACV;AACF;AAWO,SAAS,uBAAkC,SAAsC;AACtF,SAAO;AAAA,IACL,UAAU,OAAO;AAAA,MACf,SAAS;AAAA,MACT,QAAQ,CAAC,EAAE,MAAM,CAAC,GAAG,QAAQ,CAAC;AAAA,IAChC;AAAA,IACA,cAAc,OAAO,EAAE,KAAK,CAAC,EAAE;AAAA,IAC/B,SAAS;AAAA,IACT,QAAQ;AAAA,EACV;AACF;;;AC/FA,SAAS,cACP,OACe;AACf,MAAI,SAAS,KAAM,QAAO;AAC1B,MAAI,gBAAgB,KAAK,EAAG,QAAO;AACnC,SAAQ,MAAwB;AAClC;AAKA,SAAS,YACP,OACgF;AAChF,MAAI,SAAS,QAAQ,gBAAgB,KAAK,EAAG,QAAO;AACpD,QAAM,SAAS;AACf,MAAI,OAAO,eAAe,QAAQ,OAAO,eAAe,QAAQ,OAAO,YAAY,MAAM;AACvF,WAAO;AAAA,EACT;AACA,SAAO;AAAA,IACL,aAAa,OAAO;AAAA,IACpB,aAAa,OAAO;AAAA,IACpB,UAAU,OAAO;AAAA,EACnB;AACF;AAKA,SAAS,mBACP,WACqC;AACrC,QAAM,SAA8C,CAAC;AACrD,aAAW,CAAC,KAAK,KAAK,KAAK,OAAO,QAAQ,SAAS,GAAG;AACpD,WAAO,OAAO,GAAG,CAAC,IAAI;AAAA,EACxB;AACA,SAAO;AACT;AAkCO,SAAS,YAUd,OAUA;AACA,QAAM,MAAM,MAAM;AAGlB,QAAM,WAAW,YAAY,KAAK,IAAoC;AACtE,QAAM,YAAY,YAAY,KAAK,KAAqC;AACxE,QAAM,aAAa,YAAY,KAAK,MAAsC;AAC1E,QAAM,cAAc,YAAY,KAAK,OAAuC;AAC5E,QAAM,cAAc,YAAY,KAAK,OAAuC;AAE5E,QAAM,QAAwB;AAAA,IAC5B,GAAI,WAAW,EAAE,MAAM,SAAS,IAAI,CAAC;AAAA,IACrC,GAAI,YAAY,EAAE,OAAO,EAAE,aAAa,UAAU,YAAY,EAAE,IAAI,CAAC;AAAA,IACrE,GAAI,aAAa,EAAE,QAAQ,EAAE,aAAa,WAAW,YAAY,EAAE,IAAI,CAAC;AAAA,IACxE,GAAI,cAAc,EAAE,SAAS,EAAE,aAAa,YAAY,YAAY,EAAE,IAAI,CAAC;AAAA,IAC3E,GAAI,cAAc,EAAE,SAAS,EAAE,aAAa,YAAY,YAAY,EAAE,IAAI,CAAC;AAAA,EAC7E;AAEA,QAAM,aAAa;AAAA,IACjB,QAAQ,MAAM;AAAA,IACd,MAAM,MAAM;AAAA,IACZ,SAAS;AAAA,MACP,MAAM,cAAc,KAAK,IAAoC,KAAK;AAAA,MAClE,OAAO,cAAc,KAAK,KAAqC,KAAK;AAAA,MACpE,QAAQ,cAAc,KAAK,MAAsC,KAAK;AAAA,MACtE,SAAS,cAAc,KAAK,OAAuC,KAAK;AAAA,MACxE,SAAS,cAAc,KAAK,OAAuC,KAAK;AAAA,IAC1E;AAAA,IACA,WAAW,MAAM,YAAY,mBAAmB,MAAM,SAAS,IAAI;AAAA,IACnE,MAAM;AAAA,MACJ,SAAS,MAAM,MAAM;AAAA,MACrB,aAAa,MAAM,MAAM;AAAA,MACzB,MAAM,MAAM,MAAM;AAAA,MAClB,aAAa,MAAM,MAAM;AAAA,MACzB,YAAY,MAAM,MAAM,cAAc;AAAA,MACtC,UAAU,MAAM,MAAM;AAAA,MACtB,cAAc,MAAM,MAAM;AAAA,IAC5B;AAAA,IACA;AAAA,IACA,QAAQ;AAAA,EACV;AAEA,SAAO,OAAO,OAAO,UAAU;AAUjC;;;ACxMO,SAAS,YAAY,MAAsB;AAChD,QAAM,UAAU,KAEb,QAAQ,uBAAuB,MAAM,EAErC,QAAQ,8BAA8B,SAAS,EAE/C,QAAQ,qCAAqC,SAAS;AAEzD,SAAO,IAAI,OAAO,IAAI,OAAO,KAAK;AACpC;AAWO,SAAS,kBAAkB,MAAwB;AAExD,QAAM,cAAc,CAAC,GAAG,KAAK,SAAS,4BAA4B,CAAC,EAAE,IAAI,CAAC,MAAM,EAAE,CAAC,CAAE;AAErF,QAAM,cAAc,CAAC,GAAG,KAAK,SAAS,+BAA+B,CAAC,EAAE,IAAI,CAAC,MAAM,EAAE,CAAC,CAAE;AACxF,SAAO,CAAC,GAAG,aAAa,GAAG,WAAW;AACxC;AAKO,SAAS,cAAc,MAAuB;AACnD,SAAO,4BAA4B,KAAK,IAAI,KAAK,+BAA+B,KAAK,IAAI;AAC3F;AAcO,SAAS,UAAU,UAAkB,QAAwC;AAClF,MAAI,SAAS;AAGb,aAAW,CAAC,KAAK,KAAK,KAAK,OAAO,QAAQ,MAAM,GAAG;AACjD,aAAS,OAAO,QAAQ,IAAI,GAAG,IAAI,mBAAmB,KAAK,CAAC;AAC5D,aAAS,OAAO,QAAQ,IAAI,GAAG,KAAK,mBAAmB,KAAK,CAAC;AAAA,EAC/D;AAEA,SAAO;AACT;AAWO,SAAS,cAAc,MAAsB;AAClD,SAAO,KAAK,QAAQ,iCAAiC,KAAK;AAC5D;;;ACzEO,SAAS,kBAAkB,OAA0C;AAC1E,SACE,OAAO,UAAU,YACjB,UAAU,QACV,YAAY,SACZ,UAAU,SACV,YAAY;AAEhB;AAKO,SAAS,mBAAmB,OAA2C;AAC5E,SACE,OAAO,UAAU,YACjB,UAAU,QACV,eAAe,SACd,MAA2B,cAAc;AAE9C;AA8GO,SAAS,cACd,QACA,WAAW,IACgC;AAC3C,QAAM,SAAoD,CAAC;AAE3D,aAAW,CAAC,KAAK,KAAK,KAAK,OAAO,QAAQ,MAAM,GAAG;AACjD,UAAM,UAAU,WAAW,GAAG,QAAQ,IAAI,GAAG,KAAK;AAElD,QAAI,kBAAkB,KAAK,GAAG;AAC5B,aAAO,KAAK,EAAE,KAAK,SAAS,OAAO,MAAM,CAAC;AAAA,IAC5C,WAAW,mBAAmB,KAAK,GAAG;AACpC,aAAO,KAAK,GAAG,cAAc,MAAM,QAAQ,OAAO,CAAC;AAAA,IACrD,WAAW,OAAO,UAAU,YAAY,UAAU,MAAM;AACtD,aAAO,KAAK,GAAG,cAAc,OAAuB,OAAO,CAAC;AAAA,IAC9D;AAAA,EACF;AAEA,SAAO;AACT;;;AClJO,SAAS,aACd,QACA,SACqB;AACrB,QAAM,WAAW,SAAS;AAG1B,QAAM,kBACJ,UAAU,WAAW,UAAU,OAAQ,oBAAoB,QAAQ,QAAQ,IAAU;AAEvF,QAAM,aAAkC;AAAA,IACtC,QAAQ;AAAA,IACR,UAAU,SAAS;AAAA,IACnB;AAAA,IACA,WAAW;AAAA,EACb;AAGA,SAAO,WAAW,UAAU;AAC9B;AAKA,SAAS,oBAAoB,QAAsB,UAAwC;AACzF,QAAM,SAAkC,CAAC;AAEzC,aAAW,CAAC,KAAK,KAAK,KAAK,OAAO,QAAQ,MAAM,GAAG;AACjD,QAAI,kBAAkB,KAAK,GAAG;AAC5B,aAAO,GAAG,IAAI,qBAAqB,OAAO,QAAQ;AAAA,IACpD,WAAW,mBAAmB,KAAK,GAAG;AACpC,aAAO,GAAG,IAAI;AAAA,QACZ,GAAG;AAAA,QACH,QAAQ,oBAAoB,MAAM,QAAQ,QAAQ;AAAA,MACpD;AAAA,IACF,WAAW,OAAO,UAAU,YAAY,UAAU,MAAM;AACtD,aAAO,GAAG,IAAI,oBAAoB,OAAuB,QAAQ;AAAA,IACnE;AAAA,EACF;AAEA,SAAO;AACT;AAKA,SAAS,qBAAqB,OAAwB,UAA2C;AAC/F,QAAM,eAAe,SAAS,WAAW,CAAC,MAAM,QAAQ;AACxD,QAAM,YAAY,SAAS,QAAQ,SAAS,KAAK,SAAS;AAE1D,MAAI,CAAC,gBAAgB,CAAC,UAAW,QAAO;AAExC,SAAO,OAAO,OAAO;AAAA,IACnB,GAAG;AAAA,IACH,SAAS;AAAA,MACP,GAAG,MAAM;AAAA,MACT,SAAS,MAAM,QAAQ,WAAW,SAAS,WAAW;AAAA,IACxD;AAAA,IACA,MAAM;AAAA,MACJ,GAAG,MAAM;AAAA,MACT,MAAM,UAAU,SAAS,MAAM,MAAM,KAAK,IAAI;AAAA,IAChD;AAAA,EACF,CAAC;AACH;AAKA,SAAS,UACP,YACA,WAC+B;AAC/B,MAAI,CAAC,cAAc,WAAW,WAAW,EAAG,QAAO;AACnD,MAAI,CAAC,aAAa,UAAU,WAAW,EAAG,QAAO;AAGjD,QAAM,SAAS,CAAC,GAAG,UAAU;AAC7B,aAAW,OAAO,WAAW;AAC3B,QAAI,CAAC,OAAO,SAAS,GAAG,GAAG;AACzB,aAAO,KAAK,GAAG;AAAA,IACjB;AAAA,EACF;AACA,SAAO;AACT;AAKA,SAAS,WAA6B,KAAW;AAC/C,QAAM,YAAY,OAAO,oBAAoB,GAAG;AAEhD,aAAW,QAAQ,WAAW;AAC5B,UAAM,QAAQ,IAAI,IAAI;AACtB,QAAI,SAAS,OAAO,UAAU,YAAY,CAAC,OAAO,SAAS,KAAK,GAAG;AACjE,iBAAW,KAAK;AAAA,IAClB;AAAA,EACF;AAEA,SAAO,OAAO,OAAO,GAAG;AAC1B;AASA,SAAS,cAAsC,OAA0B;AACvE,SAAO,mBAAmB,KAAK,IAAI,MAAM,SAAS;AACpD;AAGA,SAAS,YAAY,OAAuC;AAC1D,SACE,OAAO,UAAU,YACjB,UAAU,QACV,CAAC,kBAAkB,KAAK,KACxB,CAAC,mBAAmB,KAAK;AAE7B;AAGA,SAAS,iBAAiB,GAAiB,GAA+B;AACxE,QAAM,SAAkC,EAAE,GAAG,EAAE;AAE/C,aAAW,OAAO,OAAO,KAAK,CAAC,GAAG;AAChC,UAAM,OAAO,OAAO,GAAG;AACvB,UAAM,OAAO,EAAE,GAAG;AAElB,QAAI,YAAY,IAAI,KAAK,YAAY,IAAI,GAAG;AAC1C,aAAO,GAAG,IAAI,iBAAiB,MAAM,IAAI;AAAA,IAC3C,OAAO;AACL,aAAO,GAAG,IAAI;AAAA,IAChB;AAAA,EACF;AAEA,SAAO;AACT;AAkGO,SAAS,gBACX,SAC6B;AAChC,QAAM,SAAS,QAAQ,IAAI,aAAa,EAAE,OAAO,gBAAgB;AACjE,SAAO,aAAa,MAAM;AAC5B;;;ACzTO,SAAS,oBAAoB,KAAqB;AACvD,SAAO,IACJ,MAAM,GAAG,EACT;AAAA,IAAI,CAAC,SAAS,UACb,UAAU,IAAI,UAAU,QAAQ,OAAO,CAAC,EAAE,YAAY,IAAI,QAAQ,MAAM,CAAC;AAAA,EAC3E,EACC,KAAK,EAAE;AACZ;;;ACyNO,SAAS,sBACd,QACgD;AAChD,SAAO,aAAa,UAAU,OAAO,OAAO,YAAY;AAC1D;;;ACnNO,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;AAAA,IAEf,WAAW;AAAA;AAAA,IAEX,cAAc;AAAA,EAChB;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;;;ACxDO,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;;;ACzDO,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;;;AC9BO,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;;;AChBO,IAAM,oBAAN,MAAM,2BAA0B,aAAa;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASlD,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,OAAmC;AAC3D,WAAO,IAAI,mBAAkB;AAAA,MAC3B,SAAS,iBAAiB,QAAQ,MAAM,UAAU;AAAA,MAClD;AAAA,IACF,CAAC;AAAA,EACH;AACF;;;AClBO,SAAS,UAA8B,IAAa,cAAkC;AAC3F,MAAI;AACF,WAAO,GAAG;AAAA,EACZ,SAAS,OAAO;AACd,UAAM,aAAa,KAAK;AAAA,EAC1B;AACF;;;ACjCO,SAAS,2BACd,QACA,UACA,SACqB;AACrB,QAAM,SAAS,mBAAmB,MAAM,IAAI,OAAO,SAAS;AAC5D,QAAM,kBAAkB,cAAc,MAAM;AAI5C,QAAM,eAAe,wBAAwB,eAAe;AAE5D,QAAM,SAA8B,CAAC;AAGrC,QAAM,kBAA6C;AAAA,IACjD,GAAG;AAAA,IACH,iBAAiB,SAAS,mBAAmB;AAAA,IAC7C,kBAAkB,SAAS,oBAAoB;AAAA,IAC/C,cAAc,SAAS,gBAAgB;AAAA,EACzC;AAEA,aAAW,EAAE,KAAK,MAAM,KAAK,cAAc;AACzC,UAAM,gBAAgB,SAAS,GAAG;AAElC,QAAI,CAAC,eAAe;AAClB,UAAI,gBAAgB,cAAc;AAEhC;AAAA,MACF;AACA,YAAM,IAAI;AAAA,QACR,8BAA8B,GAAG;AAAA,MACnC;AAAA,IACF;AAEA,WAAO,KAAK,mBAAmB,KAAK,OAAO,eAAe,eAAe,CAAC;AAAA,EAC5E;AAEA,SAAO;AACT;AAkBA,SAAS,wBAA+D,QAAkB;AACxF,SAAO,CAAC,GAAG,MAAM,EAAE,KAAK,CAAC,GAAG,MAAM;AAChC,UAAM,YAAY,EAAE,MAAM,KAAK,MAAM,GAAG,EAAE,OAAO,OAAO;AACxD,UAAM,YAAY,EAAE,MAAM,KAAK,MAAM,GAAG,EAAE,OAAO,OAAO;AAExD,UAAM,SAAS,KAAK,IAAI,UAAU,QAAQ,UAAU,MAAM;AAE1D,aAAS,IAAI,GAAG,IAAI,QAAQ,KAAK;AAC/B,YAAM,OAAO,UAAU,CAAC;AACxB,YAAM,OAAO,UAAU,CAAC;AAGxB,UAAI,SAAS,UAAa,SAAS,OAAW,QAAO;AACrD,UAAI,SAAS,UAAa,SAAS,OAAW,QAAO;AACrD,UAAI,SAAS,UAAa,SAAS,OAAW,QAAO;AAGrD,YAAM,WAAW,KAAK,WAAW,GAAG,KAAM,KAAK,WAAW,GAAG,KAAK,KAAK,SAAS,GAAG;AACnF,YAAM,WAAW,KAAK,WAAW,GAAG,KAAM,KAAK,WAAW,GAAG,KAAK,KAAK,SAAS,GAAG;AAGnF,UAAI,CAAC,YAAY,SAAU,QAAO;AAClC,UAAI,YAAY,CAAC,SAAU,QAAO;AAGlC,YAAM,MAAM,KAAK,cAAc,IAAI;AACnC,UAAI,QAAQ,EAAG,QAAO;AAAA,IACxB;AAEA,WAAO;AAAA,EACT,CAAC;AACH;AASA,SAAS,mBACP,KACA,OAGA,QACA,SACmB;AACnB,QAAM,aAAa,OAAO,cAAc,CAAC;AACzC,QAAM,mBAAmB,SAAS,cAAc,CAAC;AACjD,QAAM,gBAAgB,CAAC,GAAG,kBAAkB,GAAG,UAAU;AAEzD,QAAM,wBAAwB,QAAQ,mBAAmB;AACzD,QAAM,yBAAyB,QAAQ,oBAAoB;AAE3D,SAAO;AAAA,IACL,QAAQ,MAAM;AAAA,IACd,MAAM,cAAc,MAAM,IAAI;AAAA,IAC9B,UAAU;AAAA,MACR,aAAa,MAAM,KAAK,eAAe,oBAAoB,GAAG;AAAA,MAC9D,SAAS,MAAM,KAAK;AAAA,MACpB,aAAa,MAAM,KAAK;AAAA,MACxB,MAAM,MAAM,KAAK;AAAA,MACjB,YAAY,MAAM,KAAK;AAAA,IACzB;AAAA,IACA,SAAS,OAAO,YAA4B,QAAmD;AAE7F,YAAM,aAA6B,SAAS,gBACxC,QAAQ,cAAc,UAAU,IAC/B,OAAO,EAAE,WAAW,kBAAkB,EAAE;AAM7C,YAAM,mBAA4B,MAAM,QAAQ,UAC5C;AAAA,QACE,MAAM;AACJ,gBAAM,SAAS,oBAAoB,OAAO,UAAU;AACpD,cAAI,CAAC,OAAO,SAAS;AACnB,kBAAM,SAAS,OAAO,UAAU,CAAC;AACjC,kBAAM,IAAI,oBAAoB;AAAA,cAC5B,SAAS;AAAA,cACT,kBAAkB,OAAO,IAAI,CAAC,OAAO;AAAA,gBACnC,OAAO,EAAE,KAAK,KAAK,GAAG;AAAA,gBACtB,SAAS,EAAE;AAAA,cACb,EAAE;AAAA,YACJ,CAAC;AAAA,UACH;AACA,iBAAO,OAAO;AAAA,QAChB;AAAA,QACA,MAAM,IAAI,kBAAkB,EAAE,SAAS,0BAA0B,CAAC;AAAA,MACpE,IACA;AAIJ,UAAI;AAEJ,UAAI,uBAAuB;AACzB,cAAM,mBAAmB,oBAAoB,OAAO,UAAU;AAE9D,YAAI,CAAC,iBAAiB,SAAS;AAC7B,gBAAM,SAAS,iBAAiB,UAAU,CAAC;AAC3C,gBAAM,IAAI,oBAAoB;AAAA,YAC5B,SAAS;AAAA,YACT,kBAAkB,OAAO,IAAI,CAAC,OAAO;AAAA,cACnC,OAAO,EAAE,KAAK,KAAK,GAAG;AAAA,cACtB,SAAS,EAAE;AAAA,YACb,EAAE;AAAA,UACJ,CAAC;AAAA,QACH;AAEA,cAAM,OAAO,iBAAiB,QAAQ,CAAC;AAEvC,2BAAmB;AAAA,UACjB,MAAM,KAAK;AAAA,UACX,OAAO,KAAK;AAAA,UACZ,YAAY,KAAK;AAAA,UACjB,SAAS,KAAK;AAAA,UACd,KAAK;AAAA,YACH,QAAQ,WAAW;AAAA,YACnB,KAAK,WAAW;AAAA,YAChB,SAAS,iBAAiB,WAAW,OAAO;AAAA,UAC9C;AAAA,QACF;AAAA,MACF,OAAO;AAGL,2BAAmB;AAAA,UACjB,MAAM,WAAW;AAAA,UACjB,OAAO,eAAe,WAAW,KAAK;AAAA,UACtC,YAAY,oBAAoB,WAAW,MAAM;AAAA,UACjD,SAAS,iBAAiB,WAAW,OAAO;AAAA,UAC5C,KAAK;AAAA,YACH,QAAQ,WAAW;AAAA,YACnB,KAAK,WAAW;AAAA,YAChB,SAAS,iBAAiB,WAAW,OAAO;AAAA,UAC9C;AAAA,QACF;AAAA,MACF;AAIA,YAAM,kBAAkB,YAAsC;AAC5D,YAAI,sBAAsB,MAAM,GAAG;AAEjC,iBAAO,OAAO;AAAA,YACZ;AAAA,YACA;AAAA,UACF;AAAA,QACF,OAAO;AAEL,gBAAM,EAAE,eAAe,SAAS,eAAe,IAAI;AAMnD,gBAAM,QAAQ;AAAA,YACZ;AAAA,YACA;AAAA,UACF;AAGA,gBAAM,SAAS,MAAM,QAAQ,QAAQ,KAAK;AAG1C,iBAAO,eAAe,MAAM;AAAA,QAC9B;AAAA,MACF;AAEA,UAAI;AAEJ,UAAI,cAAc,WAAW,GAAG;AAC9B,mBAAW,MAAM,gBAAgB;AAAA,MACnC,OAAO;AAGL,YAAI,QAAQ;AACZ,cAAM,OAAO,YAAsC;AACjD,cAAI,SAAS,cAAc,QAAQ;AACjC,mBAAO,gBAAgB;AAAA,UACzB;AAEA,gBAAM,KAAK,cAAc,OAAO;AAChC,iBAAO,GAAG,YAAY,YAAY,IAAI;AAAA,QACxC;AAEA,mBAAW,MAAM,KAAK;AAAA,MACxB;AAGA,yBAAmB,SAAS,MAAM;AAGlC,UAAI,wBAAwB;AAC1B,cAAM,2BAA2B,qBAAqB,OAAO,QAAQ;AAErE,YAAI,CAAC,yBAAyB,SAAS;AACrC,gBAAM,SAAS,yBAAyB,UAAU,CAAC;AACnD,gBAAM,IAAI,gBAAgB;AAAA,YACxB,SAAS;AAAA,YACT,MAAM;AAAA,YACN,OAAO,IAAI,MAAM,OAAO,IAAI,CAAC,MAAM,GAAG,EAAE,KAAK,KAAK,GAAG,CAAC,KAAK,EAAE,OAAO,EAAE,EAAE,KAAK,IAAI,CAAC;AAAA,UACpF,CAAC;AAAA,QACH;AAAA,MACF;AAEA,aAAO;AAAA,IACT;AAAA,EACF;AACF;AAKA,SAAS,oBACP,OACA,YAC0B;AAC1B,QAAM,SAA4B,CAAC;AACnC,QAAM,OAKF,CAAC;AAGL,MAAI,MAAM,QAAQ,MAAM;AACtB,UAAM,SAAU,MAAM,QAAQ,KAAuB,SAAS,WAAW,IAAI;AAC7E,QAAI,OAAO,SAAS;AAClB,WAAK,OAAO,OAAO;AAAA,IACrB,OAAO;AACL,aAAO;AAAA,QACL,GAAG,OAAO,OAAO,IAAI,CAAC,WAAW;AAAA,UAC/B,GAAG;AAAA,UACH,MAAM,CAAC,QAAQ,GAAG,MAAM,IAAI;AAAA,QAC9B,EAAE;AAAA,MACJ;AAAA,IACF;AAAA,EACF;AAGA,MAAI,MAAM,QAAQ,OAAO;AACvB,UAAM,WAAW,eAAe,WAAW,KAAK;AAChD,UAAM,SAAU,MAAM,QAAQ,MAAwB,SAAS,QAAQ;AACvE,QAAI,OAAO,SAAS;AAClB,WAAK,QAAQ,OAAO;AAAA,IACtB,OAAO;AACL,aAAO;AAAA,QACL,GAAG,OAAO,OAAO,IAAI,CAAC,WAAW;AAAA,UAC/B,GAAG;AAAA,UACH,MAAM,CAAC,SAAS,GAAG,MAAM,IAAI;AAAA,QAC/B,EAAE;AAAA,MACJ;AAAA,IACF;AAAA,EACF;AAGA,MAAI,MAAM,QAAQ,QAAQ;AACxB,UAAM,SAAU,MAAM,QAAQ,OAAyB,SAAS,WAAW,UAAU,CAAC,CAAC;AACvF,QAAI,OAAO,SAAS;AAClB,WAAK,aAAa,OAAO;AAAA,IAC3B,OAAO;AACL,aAAO;AAAA,QACL,GAAG,OAAO,OAAO,IAAI,CAAC,WAAW;AAAA,UAC/B,GAAG;AAAA,UACH,MAAM,CAAC,cAAc,GAAG,MAAM,IAAI;AAAA,QACpC,EAAE;AAAA,MACJ;AAAA,IACF;AAAA,EACF,OAAO;AAEL,SAAK,aAAa,oBAAoB,WAAW,MAAM;AAAA,EACzD;AAGA,MAAI,MAAM,QAAQ,SAAS;AACzB,UAAM,aAAa,iBAAiB,WAAW,OAAO;AACtD,UAAM,SAAU,MAAM,QAAQ,QAA0B,SAAS,UAAU;AAC3E,QAAI,OAAO,SAAS;AAClB,WAAK,UAAU,OAAO;AAAA,IACxB,OAAO;AACL,aAAO;AAAA,QACL,GAAG,OAAO,OAAO,IAAI,CAAC,WAAW;AAAA,UAC/B,GAAG;AAAA,UACH,MAAM,CAAC,WAAW,GAAG,MAAM,IAAI;AAAA,QACjC,EAAE;AAAA,MACJ;AAAA,IACF;AAAA,EACF;AAEA,MAAI,OAAO,SAAS,GAAG;AACrB,WAAO,EAAE,SAAS,OAAO,OAAO;AAAA,EAClC;AAEA,SAAO,EAAE,SAAS,MAAM,KAAK;AAC/B;AAQA,SAAS,qBACP,OACA,UAC0B;AAC1B,MAAI,CAAC,MAAM,WAAW;AACpB,WAAO,EAAE,SAAS,KAAK;AAAA,EACzB;AAEA,QAAM,QAAQ,MAAM,UAAU,OAAO,SAAS,MAAM,CAAC;AACrD,QAAM,SAAS,OAAO;AAEtB,MAAI,CAAC,QAAQ;AACX,WAAO,EAAE,SAAS,KAAK;AAAA,EACzB;AAEA,QAAM,SAAS,OAAO,SAAS,SAAS,IAAI;AAE5C,MAAI,OAAO,SAAS;AAClB,WAAO,EAAE,SAAS,KAAK;AAAA,EACzB;AAEA,QAAM,SAAS,OAAO,OAAO,IAAI,CAAC,WAAW;AAAA,IAC3C,GAAG;AAAA,IACH,MAAM,CAAC,YAAY,GAAG,MAAM,IAAI;AAAA,EAClC,EAAE;AAEF,SAAO,EAAE,SAAS,OAAO,OAAO;AAClC;AAKA,SAAS,oBACP,OACA,SACiC;AACjC,QAAM,gBAAgB,MAAM,QAAQ;AAGpC,MAAI,CAAC,eAAe;AAClB,WAAO,EAAE,SAAS,MAAM,MAAM,QAAQ;AAAA,EACxC;AAGA,QAAM,SAAS,cAAc,SAAS,OAAO;AAE7C,MAAI,OAAO,SAAS;AAClB,WAAO,EAAE,SAAS,MAAM,MAAM,OAAO,KAAK;AAAA,EAC5C;AAGA,QAAM,SAAS,OAAO,OAAO,IAAI,CAAC,WAAW;AAAA,IAC3C,GAAG;AAAA,IACH,MAAM,CAAC,WAAW,GAAG,MAAM,IAAI;AAAA,EACjC,EAAE;AAEF,SAAO,EAAE,SAAS,OAAO,OAAO;AAClC;AAyCA,SAAS,mBAAmB,QAAsB;AAChD,MAAI,CAAC,OAAO,UAAU,MAAM,KAAK,SAAS,OAAO,SAAS,KAAK;AAC7D,UAAM,IAAI,gBAAgB;AAAA,MACxB,SAAS,6BAA6B,MAAM;AAAA,MAC5C,MAAM;AAAA,IACR,CAAC;AAAA,EACH;AACF;AAYA,SAAS,eACP,OACmC;AACnC,MAAI,CAAC,MAAO,QAAO,CAAC;AAEpB,QAAM,SAA4C,CAAC;AACnD,aAAW,CAAC,KAAK,KAAK,KAAK,OAAO,QAAQ,KAAK,GAAG;AAChD,QAAI,UAAU,OAAW;AAEzB,QAAI,MAAM,QAAQ,KAAK,GAAG;AAExB,YAAM,gBAAgB,MAAM,OAAO,CAAC,MAAmB,MAAM,MAAS;AACtE,UAAI,cAAc,WAAW,KAAK,cAAc,CAAC,MAAM,QAAW;AAEhE,eAAO,GAAG,IAAI,cAAc,CAAC;AAAA,MAC/B,WAAW,cAAc,SAAS,GAAG;AAEnC,eAAO,GAAG,IAAI;AAAA,MAChB;AAAA,IAEF,OAAO;AACL,aAAO,GAAG,IAAI;AAAA,IAChB;AAAA,EACF;AACA,SAAO;AACT;AAOA,SAAS,oBAAoB,QAAyD;AACpF,MAAI,CAAC,OAAQ,QAAO,CAAC;AAErB,QAAM,SAAiC,CAAC;AACxC,QAAM,cAAwB,CAAC;AAE/B,aAAW,CAAC,KAAK,KAAK,KAAK,OAAO,QAAQ,MAAM,GAAG;AACjD,QAAI,UAAU,QAAW;AACvB,YAAM,cAAc,OAAO,KAAK;AAChC,UAAI,gBAAgB,IAAI;AACtB,oBAAY,KAAK,GAAG;AAAA,MACtB,OAAO;AACL,eAAO,GAAG,IAAI;AAAA,MAChB;AAAA,IACF;AAAA,EACF;AAGA,MAAI,YAAY,SAAS,GAAG;AAC1B,UAAM,IAAI,oBAAoB;AAAA,MAC5B,SAAS;AAAA,MACT,kBAAkB,YAAY,IAAI,CAAC,WAAW;AAAA,QAC5C,OAAO,cAAc,KAAK;AAAA,QAC1B,SAAS;AAAA,MACX,EAAE;AAAA,IACJ,CAAC;AAAA,EACH;AAEA,SAAO;AACT;AAQA,SAAS,iBACP,SACwB;AACxB,QAAM,SAAiC,CAAC;AACxC,aAAW,CAAC,KAAK,KAAK,KAAK,OAAO,QAAQ,OAAO,GAAG;AAClD,QAAI,UAAU,OAAW;AAEzB,QAAI,MAAM,QAAQ,KAAK,GAAG;AAExB,YAAM,gBAAgB,MAAM,OAAO,CAAC,MAAmB,MAAM,MAAS;AACtE,UAAI,cAAc,SAAS,GAAG;AAC5B,eAAO,IAAI,YAAY,CAAC,IAAI,cAAc,KAAK,IAAI;AAAA,MACrD;AAAA,IACF,OAAO;AACL,aAAO,IAAI,YAAY,CAAC,IAAI;AAAA,IAC9B;AAAA,EACF;AACA,SAAO;AACT;AAKA,SAAS,oBAA4B;AACnC,SAAO,OAAO,OAAO,WAAW,CAAC;AACnC;;;AChcA,IAAM,0BAAN,MAAM,yBAAiF;AAAA,EACpE;AAAA,EACA;AAAA,EAEjB,YACE,QACA,UACA;AACA,SAAK,SAAS;AACd,SAAK,WAAW,YAAY,oBAAI,IAAI;AAAA,EACtC;AAAA,EAEA,OACE,KACA,iBACsC;AAEtC,UAAM,SACJ,OAAO,oBAAoB,aACvB,EAAE,SAAS,gBAAoD,IAC9D;AAEP,UAAM,cAAc,IAAI,IAAI,KAAK,QAAQ;AACzC,gBAAY,IAAI,KAAe,MAAM;AAErC,WAAO,IAAI;AAAA,MACT,KAAK;AAAA,MACL;AAAA,IACF;AAAA,EACF;AAAA,EAEA,kBACE,KACA,QACsC;AAEtC,UAAM,cAAc,IAAI,IAAI,KAAK,QAAQ;AACzC,gBAAY,IAAI,KAAe,MAA+D;AAK9F,WAAO,IAAI;AAAA,MACT,KAAK;AAAA,MACL;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA,EAIA,MAAM,SAA0D;AAC9D,WAAO,2BAA2B,KAAK,QAAQ,OAAO,YAAY,KAAK,QAAQ,GAAG,OAAO;AAAA,EAC3F;AAAA,EAEA,aAAa,SAA0D;AACrE,WAAO,2BAA2B,KAAK,QAAQ,OAAO,YAAY,KAAK,QAAQ,GAAG;AAAA,MAChF,GAAG;AAAA,MACH,cAAc;AAAA,IAChB,CAAC;AAAA,EACH;AACF;AAuEO,SAAS,aACd,QAC+B;AAE/B,SAAO,IAAI,wBAAwB,MAAM;AAC3C;;;AC/PA,SAAS,kBAAkB,OAAqC;AAC9D,MAAI,CAAC,SAAS,OAAO,UAAU,YAAY,MAAM,QAAQ,KAAK,GAAG;AAC/D,WAAO;AAAA,EACT;AAEA,QAAM,SAAS;AAGf,SACE,UAAU,UACV,UAAU,UACV,WAAW,UACX,WAAW,UACX,WAAW,UACX,gBAAgB,UAChB,WAAW,UACX,UAAU,UACV,WAAW;AAEf;AAoCO,SAAS,gBACd,QACA,QACa;AACb,QAAM,SAAS,mBAAmB,MAAM,IAAI,OAAO,SAAS;AAC5D,QAAM,kBAAkB,cAAc,MAAM;AAG5C,QAAM,QAAsB,CAAC;AAC7B,QAAM,UAAU,oBAAI,IAAY;AAEhC,aAAW,EAAE,KAAK,MAAM,KAAK,iBAAiB;AAC5C,UAAM,cAAc,qBAAqB,MAAM,IAAI;AAEnD,QAAI,CAAC,MAAM,WAAW,GAAG;AACvB,YAAM,WAAW,IAAI,CAAC;AAAA,IACxB;AAEA,UAAM,YAAY,eAAe,KAAK,KAAK;AAC3C,UAAM,SAAS,MAAM,OAAO,YAAY;AAExC,IAAC,MAAM,WAAW,EAAuC,MAAM,IAAI;AAGnE,QAAI,UAAU,MAAM;AAClB,iBAAW,OAAO,UAAU,MAAM;AAChC,gBAAQ,IAAI,GAAG;AAAA,MACjB;AAAA,IACF;AAAA,EACF;AAGA,QAAM,OAAoB;AAAA,IACxB,SAAS,OAAO,WAAW;AAAA,IAC3B,MAAM,OAAO;AAAA,IACb;AAAA,EACF;AAGA,MAAI,OAAO,WAAW,OAAO,QAAQ,SAAS,GAAG;AAC/C,IAAC,KAA4C,UAAU,OAAO;AAAA,EAChE;AAEA,MAAI,OAAO,mBAAmB,OAAO,KAAK,OAAO,eAAe,EAAE,SAAS,GAAG;AAC5E,IAAC,KAA4E,aAAa;AAAA,MACxF,iBAAiB,OAAO;AAAA,IAC1B;AAAA,EACF;AAEA,MAAI,OAAO,YAAY,OAAO,SAAS,SAAS,GAAG;AACjD,IAAC,KAA8C,WAAW,OAAO;AAAA,EACnE;AAGA,QAAM,OAAqB,OAAO,OAAO,CAAC,GAAG,OAAO,IAAI,IAAI,CAAC;AAC7D,aAAW,WAAW,SAAS;AAC7B,QAAI,CAAC,KAAK,KAAK,CAAC,MAAM,EAAE,SAAS,OAAO,GAAG;AACzC,WAAK,KAAK,EAAE,MAAM,QAAQ,CAAC;AAAA,IAC7B;AAAA,EACF;AACA,MAAI,KAAK,SAAS,GAAG;AACnB,IAAC,KAA2C,OAAO;AAAA,EACrD;AAEA,MAAI,OAAO,cAAc;AACvB,IAAC,KAAsD,eAAe,OAAO;AAAA,EAC/E;AAEA,SAAO;AACT;AAKA,SAAS,qBAAqB,MAAsB;AAClD,SAAO,KAAK,QAAQ,8BAA8B,MAAM;AAC1D;AAMA,SAAS,eAAe,KAAa,OAA0C;AAC7E,QAAM,YAA8B;AAAA,IAClC,WAAW,eAAe,KAAK;AAAA,EACjC;AAGA,QAAM,cAAc,MAAM,KAAK,eAAe,oBAAoB,GAAG;AACrE,EAAC,UAAsC,cAAc;AAErD,MAAI,MAAM,KAAK,SAAS;AACtB,IAAC,UAAkC,UAAU,MAAM,KAAK;AAAA,EAC1D;AAEA,MAAI,MAAM,KAAK,aAAa;AAC1B,IAAC,UAAsC,cAAc,MAAM,KAAK;AAAA,EAClE;AAEA,MAAI,MAAM,KAAK,QAAQ,MAAM,KAAK,KAAK,SAAS,GAAG;AACjD,IAAC,UAA0C,OAAO,MAAM,KAAK;AAAA,EAC/D;AAEA,MAAI,MAAM,KAAK,YAAY;AACzB,IAAC,UAAsC,aAAa;AAAA,EACtD;AAEA,MAAI,MAAM,KAAK,YAAY,MAAM,KAAK,SAAS,SAAS,GAAG;AACzD,IAAC,UAAuD,WAAW,MAAM,KAAK;AAAA,EAChF;AAEA,MAAI,MAAM,KAAK,cAAc;AAC3B,IAAC,UAA+D,eAC9D,MAAM,KAAK;AAAA,EACf;AAGA,QAAM,aAAa,gBAAgB,KAAK;AACxC,MAAI,WAAW,SAAS,GAAG;AACzB,IAAC,UAA4D,aAAa;AAAA,EAC5E;AAGA,MAAI,MAAM,QAAQ,MAAM;AACtB,IAAC,UAAkD,cAAc,iBAAiB,KAAK;AAAA,EACzF;AAEA,SAAO;AACT;AAKA,SAAS,gBAAgB,OAA4C;AACnE,QAAM,aAAiC,CAAC;AAGxC,QAAM,iBAAiB,kBAAkB,MAAM,IAAI;AACnD,aAAW,QAAQ,gBAAgB;AACjC,UAAM,QAA0B;AAAA,MAC9B;AAAA,MACA,IAAI;AAAA,MACJ,UAAU;AAAA,MACV,QAAQ,EAAE,MAAM,SAAS;AAAA,IAC3B;AAGA,QAAI,MAAM,QAAQ,QAAQ;AACxB,YAAM,aAAc,MAAM,QAAQ,OAAyB,aAAa;AACxE,UAAI,WAAW,cAAc,OAAO,WAAW,eAAe,UAAU;AACtE,cAAM,aAAc,WAAW,WAAuC,IAAI;AAC1E,YAAI,kBAAkB,UAAU,GAAG;AACjC,UAAC,MAAiC,SAAS;AAAA,QAC7C;AAAA,MACF;AAAA,IACF;AAEA,eAAW,KAAK,KAAK;AAAA,EACvB;AAGA,MAAI,MAAM,QAAQ,OAAO;AACvB,UAAM,cAAe,MAAM,QAAQ,MAAwB,aAAa;AAExE,QAAI,YAAY,cAAc,OAAO,YAAY,eAAe,UAAU;AACxE,YAAM,iBAAiB,IAAI;AAAA,QACzB,MAAM,QAAQ,YAAY,QAAQ,IAAI,YAAY,WAAW,CAAC;AAAA,MAChE;AAEA,iBAAW,CAAC,MAAM,UAAU,KAAK,OAAO;AAAA,QACtC,YAAY;AAAA,MACd,GAAG;AAED,YAAI,CAAC,kBAAkB,UAAU,GAAG;AAClC;AAAA,QACF;AAEA,cAAM,QAA0B;AAAA,UAC9B;AAAA,UACA,IAAI;AAAA,UACJ,UAAU,eAAe,IAAI,IAAI;AAAA,UACjC,QAAQ;AAAA,QACV;AAGA,YAAI,iBAAiB,cAAc,OAAO,WAAW,gBAAgB,UAAU;AAC7E,UAAC,MAAkC,cAAc,WAAW;AAAA,QAC9D;AAEA,mBAAW,KAAK,KAAK;AAAA,MACvB;AAAA,IACF;AAAA,EACF;AAGA,MAAI,MAAM,QAAQ,SAAS;AACzB,UAAM,gBAAiB,MAAM,QAAQ,QAA0B,aAAa;AAE5E,QAAI,cAAc,cAAc,OAAO,cAAc,eAAe,UAAU;AAC5E,YAAM,iBAAiB,IAAI;AAAA,QACzB,MAAM,QAAQ,cAAc,QAAQ,IAAI,cAAc,WAAW,CAAC;AAAA,MACpE;AAEA,iBAAW,CAAC,MAAM,UAAU,KAAK,OAAO;AAAA,QACtC,cAAc;AAAA,MAChB,GAAG;AAED,YAAI,CAAC,kBAAkB,UAAU,GAAG;AAClC;AAAA,QACF;AAEA,cAAM,QAA0B;AAAA,UAC9B;AAAA,UACA,IAAI;AAAA,UACJ,UAAU,eAAe,IAAI,IAAI;AAAA,UACjC,QAAQ;AAAA,QACV;AAEA,mBAAW,KAAK,KAAK;AAAA,MACvB;AAAA,IACF;AAAA,EACF;AAEA,SAAO;AACT;AAMA,SAAS,iBAAiB,OAA4C;AACpE,QAAM,aAAa,MAAM,QAAQ;AACjC,QAAM,OAAO,MAAM,OAAO;AAE1B,QAAM,cAAc,MAAM,eAAe;AAEzC,QAAM,cAAkC;AAAA,IACtC,UAAU,MAAM,aAAa;AAAA,IAC7B,SAAS;AAAA,MACP,CAAC,WAAW,GAAG;AAAA,QACb,QAAQ,WAAW,aAAa;AAAA,MAClC;AAAA,IACF;AAAA,EACF;AAEA,MAAI,MAAM,aAAa;AACrB,IAAC,YAAwC,cAAc,KAAK;AAAA,EAC9D;AAEA,SAAO;AACT;AASA,SAAS,eAAe,OAA0C;AAChE,QAAM,YAA8B,CAAC;AAErC,MAAI,MAAM,aAAa,OAAO,KAAK,MAAM,SAAS,EAAE,SAAS,GAAG;AAC9D,eAAW,CAAC,YAAY,MAAM,KAAK,OAAO,QAAQ,MAAM,SAAS,GAAG;AAClE,YAAM,cAAc,OAAO,eAAe,YAAY,UAAU;AAEhE,UAAI,OAAO,QAAQ;AACjB,cAAM,cAAc,OAAO,eAAe;AAC1C,kBAAU,UAAU,IAAI;AAAA,UACtB;AAAA,UACA,SAAS;AAAA,YACP,CAAC,WAAW,GAAG;AAAA,cACb,QAAS,OAAO,OAAyB,aAAa;AAAA,YACxD;AAAA,UACF;AAAA,QACF;AAAA,MACF,OAAO;AACL,kBAAU,UAAU,IAAI,EAAE,YAAY;AAAA,MACxC;AAAA,IACF;AAAA,EACF,OAAO;AACL,cAAU,KAAK,IAAI,EAAE,aAAa,sBAAsB;AAAA,EAC1D;AAEA,SAAO;AACT;;;ACjWO,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;;;ACnCO,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;;;ACTO,IAAM,iBAAN,MAAM,wBAAuB,aAAa;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAS/C,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,OAAgC;AACxD,WAAO,IAAI,gBAAe;AAAA,MACxB,SAAS,iBAAiB,QAAQ,MAAM,UAAU;AAAA,MAClD;AAAA,IACF,CAAC;AAAA,EACH;AACF;;;ACjDO,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;;;AC7BO,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;;;ACxCA,IAAM,oBAAuC;AAAA,EAC3C,SAAS;AAAA,EACT,WAAW;AACb;AAKA,IAAM,uBAAuB;AAAA,EAC3B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAgDO,SAAS,YAAY,OAAgB,UAA2C;AACrF,MAAI,CAAC,SAAS,OAAO,UAAU,SAAU,QAAO;AAEhD,QAAM,cAAc,OAAO,UAAU,eAAe,KAAK,OAAO,aAAa,IACxE,MAA8C,cAC/C,OAAO,eAAe,KAAK,GAAG;AAClC,MAAI,CAAC,YAAa,QAAO;AACzB,QAAM,OAAO,YAAY;AAEzB,SAAO,SAAS,YAAY,SAAS,IAAI,QAAQ;AACnD;AAQO,SAAS,oBAAoB,OAA8C;AAChF,MAAI,CAAC,SAAS,OAAO,UAAU,SAAU,QAAO;AAChD,SACE,sBAAsB,SAAS,MAAM,QAAS,MAA8B,gBAAgB;AAEhG;AAcA,SAAS,yBACP,SACA,MACA,kBACmB;AACnB,SAAO;AAAA,IACL;AAAA,IACA,WAAW;AAAA,IACX,YAAY,iBAAiB,IAAI,CAAC,OAAO;AAAA,MACvC,MAAM,EAAE;AAAA,MACR,SAAS,EAAE;AAAA,IACb,EAAE;AAAA,EACJ;AACF;AASA,SAAS,qBAAqB,SAAiB,MAAiC;AAC9E,SAAO;AAAA,IACL;AAAA,IACA,WAAW;AAAA,EACb;AACF;AAaO,SAAS,kBAAkB,OAAwB;AAExD,MAAI,iBAAiB,sBAAuB,QAAO;AACnD,MAAI,iBAAiB,oBAAqB,QAAO;AACjD,MAAI,iBAAiB,kBAAmB,QAAO;AAC/C,MAAI,iBAAiB,eAAgB,QAAO;AAC5C,MAAI,iBAAiB,kBAAmB,QAAO;AAC/C,MAAI,iBAAiB,cAAe,QAAO;AAC3C,MAAI,iBAAiB,cAAe,QAAO;AAC3C,MAAI,iBAAiB,mBAAoB,QAAO;AAChD,MAAI,iBAAiB,aAAc,QAAO;AAG1C,MAAI,YAAY,OAAO,uBAAuB,EAAG,QAAO;AACxD,MAAI,YAAY,OAAO,qBAAqB,EAAG,QAAO;AACtD,MAAI,YAAY,OAAO,mBAAmB,EAAG,QAAO;AACpD,MAAI,YAAY,OAAO,gBAAgB,EAAG,QAAO;AACjD,MAAI,YAAY,OAAO,mBAAmB,EAAG,QAAO;AACpD,MAAI,YAAY,OAAO,eAAe,EAAG,QAAO;AAChD,MAAI,YAAY,OAAO,eAAe,EAAG,QAAO;AAChD,MAAI,YAAY,OAAO,oBAAoB,EAAG,QAAO;AACrD,MAAI,YAAY,OAAO,cAAc,EAAG,QAAO;AAE/C,SAAO;AACT;AAYO,SAAS,gBAAgB,OAAyB;AAEvD,MACE,iBAAiB,eACjB,iBAAiB,cACjB,iBAAiB,iBACjB;AACA,WAAO;AAAA,EACT;AAGA,aAAW,aAAa,sBAAsB;AAC5C,QAAI,YAAY,OAAO,SAAS,GAAG;AACjC,aAAO;AAAA,IACT;AAAA,EACF;AAEA,SAAO;AACT;AASO,SAAS,wBAAwB,OAAmC;AAEzE,MAAI,gBAAgB,KAAK,GAAG;AAC1B,WAAO;AAAA,EACT;AAGA,MAAI,iBAAiB,uBAAuB;AAC1C,WAAO,yBAAyB,MAAM,SAAS,MAAM,MAAM,MAAM,gBAAgB;AAAA,EACnF;AACA,MAAI,iBAAiB,qBAAqB;AACxC,WAAO,yBAAyB,MAAM,SAAS,MAAM,MAAM,MAAM,gBAAgB;AAAA,EACnF;AAGA,MAAI,YAAY,OAAO,uBAAuB,KAAK,oBAAoB,KAAK,GAAG;AAC7E,WAAO,yBAAyB,MAAM,SAAS,MAAM,MAAM,MAAM,gBAAgB;AAAA,EACnF;AACA,MAAI,YAAY,OAAO,qBAAqB,KAAK,oBAAoB,KAAK,GAAG;AAC3E,WAAO,yBAAyB,MAAM,SAAS,MAAM,MAAM,MAAM,gBAAgB;AAAA,EACnF;AAGA,MAAI,iBAAiB,YAAY;AAC/B,WAAO,qBAAqB,MAAM,SAAS,MAAM,IAAI;AAAA,EACvD;AAGA,MAAI,YAAY,OAAO,YAAY,GAAG;AACpC,WAAO,qBAAqB,MAAM,SAAS,MAAM,IAAI;AAAA,EACvD;AAGA,MACE,SACA,OAAO,UAAU,YACjB,aAAa,SACb,UAAU,SACV,OAAQ,MAAyB,YAAY,YAC7C,OAAQ,MAAyB,SAAS,UAC1C;AACA,WAAO,qBAAsB,MAAyB,SAAU,MAAyB,IAAI;AAAA,EAC/F;AAGA,SAAO;AACT;AAmBO,SAAS,uBAAuB,OAAqC;AAC1E,SAAO;AAAA,IACL,QAAQ,kBAAkB,KAAK;AAAA,IAC/B,MAAM,wBAAwB,KAAK;AAAA,EACrC;AACF;","names":[]}