@forklaunch/core 3.1.0 → 3.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.
- package/bin/gateway-mock/routes/email.mjs +91 -4
- package/lib/http/emailClient.d.ts +48 -1
- package/lib/http/emailClient.d.ts.map +1 -1
- package/lib/http/index.d.ts +1 -0
- package/lib/http/index.d.ts.map +1 -1
- package/lib/http/index.js +307 -96
- package/lib/http/index.js.map +1 -1
- package/lib/http/index.mjs +266 -58
- package/lib/http/index.mjs.map +1 -1
- package/lib/http/instanceGateway.d.ts +10 -6
- package/lib/http/instanceGateway.d.ts.map +1 -1
- package/lib/http/middleware/request/enrichDetails.middleware.d.ts.map +1 -1
- package/lib/http/modelGatewayClient.d.ts +13 -12
- package/lib/http/modelGatewayClient.d.ts.map +1 -1
- package/lib/http/smsClient.d.ts +2 -2
- package/lib/http/smsClient.d.ts.map +1 -1
- package/lib/http/telemetry/auditLogger.d.ts +5 -1
- package/lib/http/telemetry/auditLogger.d.ts.map +1 -1
- package/lib/http/telemetry/requestAudit.d.ts +30 -0
- package/lib/http/telemetry/requestAudit.d.ts.map +1 -0
- package/lib/http/voiceClient.d.ts +4 -4
- package/lib/http/voiceClient.d.ts.map +1 -1
- package/lib/http/whatsappClient.d.ts +5 -5
- package/lib/persistence/complianceChanges.d.ts +30 -0
- package/lib/persistence/complianceChanges.d.ts.map +1 -0
- package/lib/persistence/compliancePropertyBuilder.d.ts.map +1 -1
- package/lib/persistence/compliantField.d.ts +41 -8
- package/lib/persistence/compliantField.d.ts.map +1 -1
- package/lib/persistence/defineComplianceEntity.d.ts.map +1 -1
- package/lib/persistence/index.d.ts +2 -1
- package/lib/persistence/index.d.ts.map +1 -1
- package/lib/persistence/index.js +156 -19
- package/lib/persistence/index.js.map +1 -1
- package/lib/persistence/index.mjs +154 -19
- package/lib/persistence/index.mjs.map +1 -1
- package/package.json +10 -10
package/lib/http/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/http/index.ts","../../src/http/middleware/request/cors.middleware.ts","../../src/http/router/expressLikeRouter.ts","../../src/http/guards/hasPermissionChecks.ts","../../src/http/guards/hasRoleChecks.ts","../../src/http/guards/hasScopeChecks.ts","../../src/http/guards/isForklaunchRouter.ts","../../src/http/guards/isConstrainedForklaunchRouter.ts","../../src/http/guards/isExpressLikeSchemaHandler.ts","../../src/http/guards/isForklaunchExpressLikeRouter.ts","../../src/http/guards/isSdkHandler.ts","../../src/http/guards/isTypedHandler.ts","../../src/http/middleware/request/createContext.middleware.ts","../../src/http/telemetry/constants.ts","../../src/http/telemetry/openTelemetryCollector.ts","../../src/http/guards/isForklaunchRequest.ts","../../src/http/telemetry/pinoLogger.ts","../../src/http/guards/isLoggerMeta.ts","../../src/http/router/discriminateBody.ts","../../src/http/router/routerSharedLogic.ts","../../src/http/guards/hasVersionedSchema.ts","../../src/http/guards/isHmacMethod.ts","../../src/http/guards/isPathParamContractDetails.ts","../../src/http/guards/isHttpContractDetails.ts","../../src/http/middleware/request/auth.middleware.ts","../../src/http/discriminateAuthMethod.ts","../../src/http/createHmacToken.ts","../../src/http/guards/isBasicAuthMethod.ts","../../src/http/guards/isJwtAuthMethod.ts","../../src/http/guards/hasFeatureChecks.ts","../../src/http/guards/hasSubscriptionChecks.ts","../../src/http/middleware/request/authLogContext.ts","../../src/http/middleware/request/enrichDetails.middleware.ts","../../src/http/middleware/request/parse.middleware.ts","../../src/http/guards/hasSend.ts","../../src/http/guards/isRequestShape.ts","../../src/http/application/expressLikeApplication.ts","../../src/http/cluster/isPortBound.ts","../../src/http/generateHmacAuthHeaders.ts","../../src/http/instanceGateway.ts","../../src/http/modelGatewayClient.ts","../../src/http/previewModelGatewayClient.ts","../../src/http/emailClient.ts","../../src/http/smsClient.ts","../../src/http/whatsappClient.ts","../../src/http/voiceClient.ts","../../src/http/paymentsClient.ts","../../src/http/guards/isPath.ts","../../src/http/handlers/typedHandler.ts","../../src/http/handlers/delete.ts","../../src/http/handlers/get.ts","../../src/http/handlers/head.ts","../../src/http/handlers/middleware.ts","../../src/http/handlers/options.ts","../../src/http/handlers/patch.ts","../../src/http/handlers/post.ts","../../src/http/handlers/put.ts","../../src/http/handlers/trace.ts","../../src/http/handlers/typedAuthHandler.ts","../../src/http/httpStatusCodes.ts","../../src/http/mcpGenerator/mcpGenerator.ts","../../src/http/router/unpackRouters.ts","../../src/http/middleware/response/parse.middleware.ts","../../src/http/guards/isResponseCompiledSchema.ts","../../src/http/middleware/response/enrichExpressLikeSend.middleware.ts","../../src/http/telemetry/recordMetric.ts","../../src/http/openApiV3Generator/openApiV3Generator.ts","../../src/http/telemetry/auditLogger.ts","../../src/http/telemetry/evaluateTelemetryOptions.ts","../../src/http/telemetry/metricsDefinition.ts","../../src/http/rateLimit/rateLimiter.ts"],"sourcesContent":["export type { ParsedQs } from 'qs';\nexport * from './application/expressLikeApplication';\nexport * from './cluster/cluster.types';\nexport * from './cluster/isPortBound';\nexport * from './createHmacToken';\nexport * from './generateHmacAuthHeaders';\nexport * from './instanceGateway';\nexport * from './modelGatewayClient';\nexport * from './previewModelGatewayClient';\nexport * from './emailClient';\nexport * from './smsClient';\nexport * from './whatsappClient';\nexport * from './voiceClient';\nexport * from './paymentsClient';\nexport * from './discriminateAuthMethod';\nexport * from './guards/isForklaunchRequest';\nexport * from './guards/isForklaunchRouter';\nexport * from './handlers/delete';\nexport * from './handlers/get';\nexport * from './handlers/head';\nexport * from './handlers/middleware';\nexport * from './handlers/options';\nexport * from './handlers/patch';\nexport * from './handlers/post';\nexport * from './handlers/put';\nexport * from './handlers/trace';\nexport * from './handlers/typedAuthHandler';\nexport * from './handlers/typedHandler';\nexport * from './httpStatusCodes';\nexport * from './interfaces/expressLikeRouter.interface';\nexport * from './mcpGenerator/mcpGenerator';\nexport * from './middleware/request/createContext.middleware';\nexport * from './middleware/response/enrichExpressLikeSend.middleware';\nexport * from './openApiV3Generator/openApiV3Generator';\nexport * from './router/discriminateBody';\nexport * from './router/expressLikeRouter';\nexport * from './telemetry/auditLogger';\nexport * from './telemetry/constants';\nexport * from './telemetry/evaluateTelemetryOptions';\nexport * from './telemetry/metricsDefinition';\nexport * from './telemetry/openTelemetryCollector';\nexport * from './telemetry/pinoLogger';\nexport * from './telemetry/recordMetric';\nexport * from './types/apiDefinition.types';\nexport * from './types/contractDetails.types';\nexport * from './types/docsConfiguration.types';\nexport * from './types/expressLikeOptions';\nexport * from './types/expressLikeRouter.types';\nexport * from './types/openTelemetryCollector.types';\nexport * from './types/router.types';\nexport * from './rateLimit/index';\nexport * from './types/sdk.types';\nexport { MapToSdk } from './types/sdk.types';\nexport * from './types/typedHandler.types';\n","import corsMiddleware, { CorsOptions } from 'cors';\nimport { ParsedQs } from 'qs';\nimport {\n ForklaunchBaseRequest,\n ForklaunchNextFunction,\n ForklaunchResHeaders,\n ForklaunchResponse\n} from '../../types/apiDefinition.types';\nimport { ParamsDictionary } from '../../types/contractDetails.types';\n\n/**\n * Cors middleware handler\n *\n * @param req - Express-like request object\n * @param res - Express-like response object\n * @param next - Express-like next function\n */\nexport function cors<\n P extends ParamsDictionary,\n ResBodyMap extends Record<number, unknown>,\n ReqBody extends Record<string, unknown>,\n ReqQuery extends ParsedQs,\n ReqHeaders extends Record<string, string>,\n ResHeaders extends Record<string, unknown>,\n LocalsObj extends Record<string, unknown>\n>(corsOptions: CorsOptions) {\n return (\n req: ForklaunchBaseRequest<P, ReqBody, ReqQuery, ReqHeaders>,\n res: ForklaunchResponse<\n unknown,\n ResBodyMap,\n ForklaunchResHeaders & ResHeaders,\n LocalsObj,\n never\n >,\n next?: ForklaunchNextFunction\n ) => {\n if (req.method === 'OPTIONS') {\n res.cors = true;\n }\n if (!res.getHeader) {\n res.getHeader = (key: string) => {\n return res.getHeaders()[key] as string | string[] | undefined;\n };\n }\n corsMiddleware(corsOptions)(\n req as typeof req & { headers: Record<string, string> },\n res,\n next ?? (() => {})\n );\n };\n}\n","import { AnySchemaValidator, SchemaValidator } from '@forklaunch/validator';\nimport { ParsedQs } from 'qs';\n\nimport {\n EmptyObject,\n hashString,\n Prettify,\n PrettyCamelCase,\n safeStringify,\n sanitizePathSlashes,\n SanitizePathSlashes,\n toPrettyCamelCase,\n toRecord,\n TypeSafeFunction\n} from '@forklaunch/common';\nimport { hasPermissionChecks } from '../guards/hasPermissionChecks';\nimport { hasRoleChecks } from '../guards/hasRoleChecks';\nimport { hasScopeChecks } from '../guards/hasScopeChecks';\nimport { isConstrainedForklaunchRouter } from '../guards/isConstrainedForklaunchRouter';\nimport { isExpressLikeSchemaHandler } from '../guards/isExpressLikeSchemaHandler';\nimport { isForklaunchExpressLikeRouter } from '../guards/isForklaunchExpressLikeRouter';\nimport { isForklaunchRouter } from '../guards/isForklaunchRouter';\nimport { isSdkHandler } from '../guards/isSdkHandler';\nimport { isTypedHandler } from '../guards/isTypedHandler';\nimport {\n ExpressLikeRouter,\n NestableRouterBasedHandler,\n PathBasedHandler,\n PathOrMiddlewareBasedHandler\n} from '../interfaces/expressLikeRouter.interface';\nimport { createContext } from '../middleware/request/createContext.middleware';\nimport { OpenTelemetryCollector } from '../telemetry/openTelemetryCollector';\nimport {\n ExpressLikeHandler,\n ExpressLikeSchemaHandler,\n LiveSdkFunction,\n LiveTypeFunction,\n VersionedRequests,\n VersionedResponses\n} from '../types/apiDefinition.types';\nimport {\n Body,\n HeadersObject,\n Method,\n ParamsDictionary,\n ParamsObject,\n PathParamHttpContractDetails,\n QueryObject,\n ResponsesObject,\n SchemaAuthMethods,\n SessionObject,\n VersionSchema\n} from '../types/contractDetails.types';\nimport { ExpressLikeRouterOptions } from '../types/expressLikeOptions';\nimport {\n ContractDetailsOrMiddlewareOrTypedHandler,\n LiveTypeRouteDefinition,\n MiddlewareOrMiddlewareWithTypedHandler,\n TypedMiddlewareDefinition,\n TypedNestableMiddlewareDefinition\n} from '../types/expressLikeRouter.types';\nimport { MetricsDefinition } from '../types/openTelemetryCollector.types';\nimport {\n ConstrainedForklaunchRouter,\n ForklaunchRoute,\n ForklaunchRouter\n} from '../types/router.types';\nimport { FetchFunction, SdkHandlerObject } from '../types/sdk.types';\nimport { discriminateBody } from './discriminateBody';\nimport {\n compileRouteSchemas,\n resolveContractDetailsAndHandlers,\n resolveRouteMiddlewares,\n validateContractDetails\n} from './routerSharedLogic';\n\n/**\n * Extracts route middleware and handlers from route registration arguments.\n * This is a port function that converts typed handlers into Express middleware\n * without actually registering them on a router.\n *\n * @template SV - The schema validator type.\n * @template Name - The route name.\n * @template ContractMethod - The HTTP method.\n * @template Path - The route path.\n * @template P - The type of request parameters.\n * @template ResBodyMap - The type of response body map.\n * @template ReqBody - The type of request body.\n * @template ReqQuery - The type of request query.\n * @template ReqHeaders - The type of request headers.\n * @template ResHeaders - The type of response headers.\n * @template LocalsObj - The type of local variables.\n * @template VersionedApi - The versioned API schema.\n * @template RouterSession - The router session type.\n * @template BaseRequest - The base request type.\n * @template BaseResponse - The base response type.\n * @template NextFunction - The next function type.\n * @template Auth - The auth schema.\n * @template RouterHandler - The router handler type.\n * @param {object} params - The parameters for extracting route handlers.\n * @param {ContractMethod} params.method - The HTTP method.\n * @param {Path} params.path - The route path.\n * @param {string} params.basePath - The base path for the router.\n * @param {SV} params.schemaValidator - The schema validator.\n * @param {ContractDetailsOrMiddlewareOrTypedHandler<SV, Name, ContractMethod, Path, P, ResBodyMap, ReqBody, ReqQuery, ReqHeaders, ResHeaders, LocalsObj, VersionedApi, BaseRequest, BaseResponse, NextFunction, RouterSession, Auth>} params.contractDetailsOrMiddlewareOrTypedHandler - The contract details or typed handler.\n * @param {MiddlewareOrMiddlewareWithTypedHandler<SV, Name, ContractMethod, Path, P, ResBodyMap, ReqBody, ReqQuery, ReqHeaders, ResHeaders, LocalsObj, VersionedApi, BaseRequest, BaseResponse, NextFunction, RouterSession, Auth>[]} params.middlewareOrMiddlewareAndTypedHandler - Additional middleware or typed handlers.\n * @param {OpenTelemetryCollector<MetricsDefinition>} params.openTelemetryCollector - The OpenTelemetry collector.\n * @param {RouterHandler[]} params.postEnrichMiddleware - Additional middleware to run after enrichment.\n * @param {ExpressLikeRouterOptions<SV, RouterSession> | undefined} params.routerOptions - Router options.\n * @returns {{ middlewares: RouterHandler[]; controllerHandler: ExpressLikeHandler<SV, P, ResBodyMap, ReqBody, ReqQuery, ReqHeaders, ResHeaders, LocalsObj, VersionedRequests, VersionedResponses, RouterSession, BaseRequest, BaseResponse, NextFunction> }} - The extracted middlewares and controller handler.\n */\nexport function extractRouteHandlers<\n SV extends AnySchemaValidator,\n Name extends string,\n ContractMethod extends Method,\n Path extends `/${string}`,\n P extends ParamsObject<SV>,\n ResBodyMap extends ResponsesObject<SV>,\n ReqBody extends Body<SV>,\n ReqQuery extends QueryObject<SV>,\n ReqHeaders extends HeadersObject<SV>,\n ResHeaders extends HeadersObject<SV>,\n LocalsObj extends Record<string, unknown>,\n VersionedApi extends VersionSchema<SV, ContractMethod>,\n RouterSession extends SessionObject<SV>,\n BaseRequest,\n BaseResponse,\n NextFunction,\n Auth extends SchemaAuthMethods<\n SV,\n P,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n VersionedApi,\n BaseRequest\n >,\n RouterHandler\n>(params: {\n method: ContractMethod;\n path: Path;\n basePath: string;\n schemaValidator: SV;\n contractDetailsOrMiddlewareOrTypedHandler: ContractDetailsOrMiddlewareOrTypedHandler<\n SV,\n Name,\n ContractMethod,\n Path,\n P,\n ResBodyMap,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n ResHeaders,\n LocalsObj,\n VersionedApi,\n BaseRequest,\n BaseResponse,\n NextFunction,\n RouterSession,\n Auth\n >;\n middlewareOrMiddlewareAndTypedHandler: MiddlewareOrMiddlewareWithTypedHandler<\n SV,\n Name,\n ContractMethod,\n Path,\n P,\n ResBodyMap,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n ResHeaders,\n LocalsObj,\n VersionedApi,\n BaseRequest,\n BaseResponse,\n NextFunction,\n RouterSession,\n Auth\n >[];\n openTelemetryCollector?: OpenTelemetryCollector<MetricsDefinition>;\n postEnrichMiddleware?: RouterHandler[];\n routerOptions?: ExpressLikeRouterOptions<SV, RouterSession>;\n}): {\n middlewares: RouterHandler[];\n controllerHandler: ExpressLikeSchemaHandler<\n SV,\n P,\n ResBodyMap,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n ResHeaders,\n LocalsObj,\n VersionedApi,\n RouterSession,\n BaseRequest,\n BaseResponse,\n NextFunction\n >;\n} {\n const schemaValidator = params.schemaValidator as SV & SchemaValidator;\n\n const { contractDetails, handlers } = resolveContractDetailsAndHandlers<\n SV,\n Name,\n ContractMethod,\n Path,\n P,\n ResBodyMap,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n ResHeaders,\n LocalsObj,\n VersionedApi,\n RouterSession,\n BaseRequest,\n BaseResponse,\n NextFunction,\n Auth\n >(\n params.contractDetailsOrMiddlewareOrTypedHandler,\n params.middlewareOrMiddlewareAndTypedHandler\n );\n\n validateContractDetails(contractDetails, schemaValidator);\n\n const { requestSchema, responseSchemas } = compileRouteSchemas(\n contractDetails,\n schemaValidator\n );\n\n const { middlewares, controllerHandler } = resolveRouteMiddlewares<\n SV,\n Name,\n ContractMethod,\n Path,\n P,\n ResBodyMap,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n ResHeaders,\n LocalsObj,\n VersionedApi,\n RouterSession,\n BaseRequest,\n BaseResponse,\n NextFunction,\n Auth,\n RouterHandler\n >({\n basePath: params.basePath,\n path: params.path,\n contractDetails,\n requestSchema,\n responseSchemas,\n openTelemetryCollector: params.openTelemetryCollector,\n routerOptions: params.routerOptions,\n postEnrichMiddleware: params.postEnrichMiddleware ?? [],\n handlers,\n includeCreateContext: false\n });\n\n return {\n middlewares: [\n createContext(schemaValidator) as RouterHandler,\n ...middlewares\n ],\n controllerHandler\n };\n}\n\n/**\n * A class that represents an Express-like router.\n */\n/**\n * Process-level signal handlers belong to the process, not to each router.\n *\n * These used to be registered inside the router constructor, so every router an\n * application created added four more listeners to `process`. A service with\n * eleven routers therefore tripped Node's warning at startup:\n *\n * MaxListenersExceededWarning: Possible EventEmitter memory leak detected.\n * 11 unhandledRejection listeners added to [process].\n *\n * The warning was the visible half. The rest: the listener array grew with\n * router count, and on a single unhandled rejection EVERY registered handler\n * ran — logging the same error once per router and each calling\n * `process.exit(1)`.\n *\n * Installing once keeps the behaviour identical from the outside: the first\n * router to be constructed provides the collector, and there is exactly one\n * handler per signal no matter how many routers follow.\n */\nlet processHandlersInstalled = false;\n\nfunction installProcessHandlers(\n openTelemetryCollector: OpenTelemetryCollector<MetricsDefinition>\n): void {\n if (processHandlersInstalled) {\n return;\n }\n processHandlersInstalled = true;\n\n process.on('uncaughtException', (err) => {\n openTelemetryCollector.error(`Uncaught exception: ${err}`);\n process.exit(1);\n });\n process.on('unhandledRejection', (reason) => {\n openTelemetryCollector.error(`Unhandled rejection: ${reason}`);\n process.exit(1);\n });\n\n process.on('exit', () => {\n openTelemetryCollector.info('Shutting down application');\n });\n process.on('SIGINT', () => {\n openTelemetryCollector.info('Shutting down application');\n process.exit(0);\n });\n}\n\n/**\n * Test-only. Lets a suite assert the handlers install exactly once across many\n * routers without leaking state into the next test.\n */\nexport function resetProcessHandlersForTesting(): void {\n processHandlersInstalled = false;\n}\n\nexport class ForklaunchExpressLikeRouter<\n SV extends AnySchemaValidator,\n BasePath extends `/${string}`,\n RouterHandler,\n Internal extends ExpressLikeRouter<RouterHandler, Internal>,\n BaseRequest,\n BaseResponse,\n NextFunction,\n RouterSession extends SessionObject<SV>,\n FetchMap extends Record<string, unknown> = EmptyObject,\n Sdk extends Record<string, unknown> = EmptyObject\n> implements ConstrainedForklaunchRouter<SV, RouterHandler> {\n requestHandler!: RouterHandler;\n routers: ForklaunchRouter<SV>[] = [];\n routes: ForklaunchRoute<SV>[] = [];\n\n _fetchMap: FetchMap = {} as FetchMap;\n sdk: Sdk = {} as Sdk;\n\n sdkPaths: Record<string, string> = {};\n\n constructor(\n readonly basePath: BasePath,\n readonly schemaValidator: SV,\n readonly internal: Internal,\n readonly postEnrichMiddleware: RouterHandler[],\n readonly openTelemetryCollector: OpenTelemetryCollector<MetricsDefinition>,\n readonly routerOptions?: ExpressLikeRouterOptions<SV, RouterSession>\n ) {\n if (\n process.env.NODE_ENV !== 'test' &&\n !process.env.VITEST &&\n process.env.FORKLAUNCH_MODE !== 'openapi'\n ) {\n installProcessHandlers(this.openTelemetryCollector);\n }\n\n this.internal.use(createContext(this.schemaValidator) as RouterHandler);\n }\n\n /**\n * Resolves middlewares based on the contract details.\n *\n * @param {PathParamHttpContractDetails<SV> | HttpContractDetails<SV>} contractDetails - The contract details.\n * @returns {MiddlewareHandler<SV>[]} - The resolved middlewares.\n */\n\n /**\n * Parses and runs the controller handler with error handling.\n *\n * @template P - The type of request parameters.\n * @template ResBodyMap - The type of response body.\n * @template ReqBody - The type of request body.\n * @template ReqQuery - The type of request query.\n * @template LocalsObj - The type of local variables.\n * @template StatusCode - The type of status code.\n * @param {MiddlewareHandler<SV, P, ResBodyMap | string, ReqBody, ReqQuery, LocalsObj, StatusCode>} requestHandler - The request handler.\n * @returns {ExpressMiddlewareHandler} - The Express request handler.\n */\n #parseAndRunControllerHandler<\n P extends ParamsDictionary,\n ResBodyMap extends Record<number, unknown>,\n ReqBody extends Record<string, unknown>,\n ReqQuery extends ParsedQs,\n ReqHeaders extends Record<string, string>,\n ResHeaders extends Record<string, string>,\n LocalsObj extends Record<string, unknown>,\n VersionedReqs extends VersionedRequests,\n VersionedResps extends VersionedResponses,\n RouterSession extends Record<string, unknown>\n >(\n requestHandler: ExpressLikeHandler<\n SV,\n P,\n ResBodyMap,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n ResHeaders,\n LocalsObj,\n VersionedReqs,\n VersionedResps,\n RouterSession,\n BaseRequest,\n BaseResponse,\n NextFunction\n >\n ): ExpressLikeHandler<\n SV,\n P,\n ResBodyMap,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n ResHeaders,\n LocalsObj,\n VersionedReqs,\n VersionedResps,\n RouterSession,\n BaseRequest,\n BaseResponse,\n NextFunction\n > {\n return async (req, res, next) => {\n if (!requestHandler) {\n throw new Error('Controller handler is not defined');\n }\n\n try {\n await requestHandler(req, res, next);\n } catch (error) {\n if (next && typeof next === 'function') {\n next(error as Error);\n } else {\n throw error;\n }\n }\n };\n }\n\n /**\n * Extracts the controller handler from the provided handlers.\n *\n * @template P - The type of request parameters.\n * @template ResBodyMap - The type of response body.\n * @template ReqBody - The type of request body.\n * @template ReqQuery - The type of request query.\n * @template LocalsObj - The type of local variables.\n * @param {MiddlewareHandler<SV, P, ResBodyMap, ReqBody, ReqQuery, LocalsObj>[]} handlers - The provided handlers.\n * @returns {MiddlewareHandler<SV, P, ResBodyMap, ReqBody, ReqQuery, LocalsObj>} - The extracted controller handler.\n * @throws {Error} - Throws an error if the last argument is not a handler.\n */\n\n /**\n * Fetches a route from the route map and executes it with the given parameters.\n *\n * @template Path - The path type that extends keyof _fetchMap and string.\n * @param {Path} path - The route path\n * @param {Parameters<_fetchMap[Path]>[1]} [requestInit] - Optional request initialization parameters.\n * @returns {Promise<ReturnType<_fetchMap[Path]>>} - The result of executing the route handler.\n */\n fetch: FetchFunction<this['_fetchMap']> = async <\n Path extends keyof this['_fetchMap'],\n Method extends keyof this['_fetchMap'][Path],\n Version extends keyof this['_fetchMap'][Path][Method]\n >(\n path: Path,\n ...reqInit: this['_fetchMap'][Path][Method] extends TypeSafeFunction\n ? 'GET' extends keyof this['_fetchMap'][Path]\n ? this['_fetchMap'][Path]['GET'] extends TypeSafeFunction\n ? Parameters<this['_fetchMap'][Path]['GET']>[1] extends\n | {\n body: unknown;\n }\n | { query: unknown }\n | { params: unknown }\n | { headers: unknown }\n | { version: unknown }\n ? [\n reqInit: Omit<\n Parameters<this['_fetchMap'][Path][Method]>[1],\n 'method'\n > & {\n method: Method;\n }\n ]\n : [\n reqInit?: Omit<\n Parameters<this['_fetchMap'][Path][Method]>[1],\n 'method'\n > & {\n method: Method;\n }\n ]\n : [\n reqInit: Omit<\n Parameters<this['_fetchMap'][Path][Method]>[1],\n 'method'\n > & {\n method: Method;\n }\n ]\n : [\n reqInit: Omit<\n Parameters<this['_fetchMap'][Path][Method]>[1],\n 'method'\n > & {\n method: Method;\n }\n ]\n : this['_fetchMap'][Path][Method] extends Record<string, TypeSafeFunction>\n ? [\n reqInit: Omit<\n Parameters<this['_fetchMap'][Path][Method][Version]>[0],\n 'method' | 'version'\n > & {\n method: Method;\n version: Version;\n }\n ]\n : [{ method: Method }]\n ) => {\n const method = reqInit[0]?.method;\n const version =\n reqInit[0] != null && 'version' in reqInit[0]\n ? reqInit[0].version\n : undefined;\n\n return (\n (version\n ? this._fetchMap[path][method ?? ('GET' as Method)][version]\n : this._fetchMap[path][method ?? ('GET' as Method)]) as (\n route: string,\n request?: unknown\n ) => unknown\n )(\n path as string,\n reqInit[0]\n // reqInit\n ) as this['_fetchMap'][Path][Method] extends TypeSafeFunction\n ? Awaited<ReturnType<this['_fetchMap'][Path][Method]>>\n : this['_fetchMap'][Path][Method] extends Record<string, TypeSafeFunction>\n ? Awaited<ReturnType<this['_fetchMap'][Path][Method][Version]>>\n : never;\n };\n\n /**\n * Executes request locally, applying parameters\n *\n * @param handlers {ExpressLikeHandler<SV>}\n * @param controllerHandler\n * @returns\n */\n #localParamRequest<Middleware, Route extends string>(\n middlewares: Middleware[],\n controllerHandler: Middleware,\n contractDetails: PathParamHttpContractDetails<SV>,\n requestSchema: unknown,\n responseSchemas: unknown,\n version?: string\n ) {\n return async (\n route: SanitizePathSlashes<Route>,\n request?: {\n params?: Record<string, unknown>;\n query?: Record<string, unknown>;\n headers?: Record<string, unknown>;\n body?: Record<string, unknown>;\n executeMiddlewares?: boolean;\n }\n ) => {\n let statusCode: number | undefined;\n let responseMessage: unknown;\n const responseHeaders: Record<string, unknown> = {};\n const resEventHandlers: Record<string, ((...args: unknown[]) => void)[]> =\n {};\n\n const req = {\n params: request?.params ?? {},\n query: request?.query ?? {},\n headers: request?.headers ?? {},\n body:\n discriminateBody(this.schemaValidator, request?.body)?.schema ?? {},\n path: route,\n originalPath: route,\n method: 'GET',\n version,\n schemaValidator: this.schemaValidator,\n contractDetails,\n requestSchema,\n openTelemetryCollector: this.openTelemetryCollector,\n _globalOptions: () => this.routerOptions,\n context: {\n correlationId: 'local-fetch-' + Date.now(),\n span: undefined\n },\n _rawBody: undefined as unknown,\n _parsedVersions: undefined as unknown\n };\n\n const res = {\n statusCode: 200,\n status: (code: number) => {\n statusCode = code;\n res.statusCode = code;\n return res;\n },\n send: (message: string) => {\n responseMessage = message;\n resEventHandlers['finish']?.forEach((handler) => handler());\n },\n json: (body: Record<string, unknown>) => {\n responseMessage = body;\n resEventHandlers['finish']?.forEach((handler) => handler());\n },\n jsonp: (body: Record<string, unknown>) => {\n responseMessage = body;\n resEventHandlers['finish']?.forEach((handler) => handler());\n },\n setHeader: (key: string, value: string) => {\n responseHeaders[key] = value;\n return res;\n },\n getHeader: (key: string) => responseHeaders[key],\n type: (contentType: string) => {\n responseHeaders['content-type'] = contentType;\n return res;\n },\n sseEmitter: (\n generator: () => AsyncGenerator<Record<string, unknown>>\n ) => {\n responseMessage = generator();\n },\n on: (event: string, handler: (...args: unknown[]) => void) => {\n if (!resEventHandlers[event]) {\n resEventHandlers[event] = [];\n }\n resEventHandlers[event].push(handler);\n return res;\n },\n responseSchemas,\n version\n };\n\n const executeMiddlewares = request?.executeMiddlewares ?? false;\n\n if (executeMiddlewares && middlewares.length > 0) {\n const allHandlers = [...middlewares];\n let cursor = allHandlers.shift() as (\n req_: typeof req,\n resp_: typeof res,\n next: (err?: Error) => Promise<void> | void\n ) => Promise<void> | void;\n\n if (cursor) {\n for (const fn of allHandlers) {\n await cursor(req, res, (err?: Error) => {\n if (err) {\n throw err;\n }\n cursor = fn as (\n req_: typeof req,\n resp_: typeof res,\n next: (err?: Error) => Promise<void> | void\n ) => Promise<void> | void;\n });\n }\n await cursor(req, res, async (err?: Error) => {\n if (err) {\n throw err;\n }\n });\n }\n }\n\n const cHandler = controllerHandler as (\n req_: typeof req,\n resp_: typeof res,\n next: (err?: Error) => Promise<void> | void\n ) => void;\n await cHandler(req, res, (err?: Error) => {\n if (err) {\n throw err;\n }\n });\n\n return {\n code: Number(statusCode),\n response: responseMessage,\n headers: responseHeaders\n };\n };\n }\n\n registerRoute<\n Name extends string,\n ContractMethod extends Method,\n Path extends `/${string}`,\n P extends ParamsObject<SV>,\n ResBodyMap extends ResponsesObject<SV>,\n ReqBody extends Body<SV>,\n ReqQuery extends QueryObject<SV>,\n ReqHeaders extends HeadersObject<SV>,\n ResHeaders extends HeadersObject<SV>,\n LocalsObj extends Record<string, unknown>,\n VersionedApi extends VersionSchema<SV, ContractMethod>,\n Auth extends SchemaAuthMethods<\n SV,\n P,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n VersionedApi,\n BaseRequest\n >\n >(\n method: ContractMethod,\n path: Path,\n registrationMethod: PathBasedHandler<RouterHandler>,\n contractDetailsOrMiddlewareOrTypedHandler: ContractDetailsOrMiddlewareOrTypedHandler<\n SV,\n Name,\n ContractMethod,\n Path,\n P,\n ResBodyMap,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n ResHeaders,\n LocalsObj,\n VersionedApi,\n BaseRequest,\n BaseResponse,\n NextFunction,\n RouterSession,\n Auth\n >,\n ...middlewareOrMiddlewareAndTypedHandler: MiddlewareOrMiddlewareWithTypedHandler<\n SV,\n Name,\n ContractMethod,\n Path,\n P,\n ResBodyMap,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n ResHeaders,\n LocalsObj,\n VersionedApi,\n BaseRequest,\n BaseResponse,\n NextFunction,\n RouterSession,\n Auth\n >[]\n ): this & {\n _fetchMap: Prettify<\n FetchMap extends Record<\n SanitizePathSlashes<`${BasePath}${Path}`>,\n unknown\n >\n ? FetchMap &\n Record<\n SanitizePathSlashes<`${BasePath}${Path}`>,\n FetchMap[SanitizePathSlashes<`${BasePath}${Path}`>] &\n Record<\n Uppercase<ContractMethod>,\n LiveTypeFunction<\n SV,\n SanitizePathSlashes<`${BasePath}${Path}`>,\n P,\n ResBodyMap,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n ResHeaders,\n ContractMethod,\n VersionedApi,\n Auth\n >\n >\n >\n : FetchMap &\n Record<\n SanitizePathSlashes<`${BasePath}${Path}`>,\n Record<\n Uppercase<ContractMethod>,\n LiveTypeFunction<\n SV,\n SanitizePathSlashes<`${BasePath}${Path}`>,\n P,\n ResBodyMap,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n ResHeaders,\n ContractMethod,\n VersionedApi,\n Auth\n >\n >\n >\n >;\n sdk: Prettify<\n Sdk &\n Record<\n PrettyCamelCase<\n Name extends string\n ? Name\n : SanitizePathSlashes<`${BasePath}${Path}`>\n >,\n LiveSdkFunction<\n SV,\n P,\n ResBodyMap,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n ResHeaders,\n VersionedApi,\n Auth\n >\n >\n >;\n } {\n // in this case, we know that the first argument is the typedHandler. As a result, we only use defined handlers\n const { contractDetails, handlers } = resolveContractDetailsAndHandlers<\n SV,\n Name,\n ContractMethod,\n Path,\n P,\n ResBodyMap,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n ResHeaders,\n LocalsObj,\n VersionedApi,\n RouterSession,\n BaseRequest,\n BaseResponse,\n NextFunction,\n Auth\n >(\n contractDetailsOrMiddlewareOrTypedHandler,\n middlewareOrMiddlewareAndTypedHandler\n );\n\n validateContractDetails(contractDetails, this.schemaValidator);\n\n this.routes.push({\n basePath: this.basePath,\n path,\n method,\n contractDetails: contractDetails as PathParamHttpContractDetails<SV>\n });\n\n const { requestSchema, responseSchemas } = compileRouteSchemas(\n contractDetails,\n this.schemaValidator\n );\n\n const { middlewares, controllerHandler } = resolveRouteMiddlewares<\n SV,\n Name,\n ContractMethod,\n Path,\n P,\n ResBodyMap,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n ResHeaders,\n LocalsObj,\n VersionedApi,\n RouterSession,\n BaseRequest,\n BaseResponse,\n NextFunction,\n Auth,\n RouterHandler\n >({\n basePath: this.basePath,\n path,\n contractDetails,\n requestSchema,\n responseSchemas,\n openTelemetryCollector: this.openTelemetryCollector,\n routerOptions: this.routerOptions,\n postEnrichMiddleware: this.postEnrichMiddleware,\n includeCreateContext: false,\n handlers,\n router: this\n });\n\n registrationMethod.bind(this.internal)(\n path,\n ...(middlewares as RouterHandler[]),\n this.#parseAndRunControllerHandler(controllerHandler) as RouterHandler\n );\n\n toRecord(this._fetchMap)[sanitizePathSlashes(`${this.basePath}${path}`)] = {\n ...(this._fetchMap[sanitizePathSlashes(`${this.basePath}${path}`)] ?? {}),\n [method.toUpperCase()]: contractDetails.versions\n ? Object.fromEntries(\n Object.keys(contractDetails.versions).map((version) => [\n version,\n this.#localParamRequest(\n middlewares as RouterHandler[],\n controllerHandler as RouterHandler,\n contractDetails as PathParamHttpContractDetails<SV>,\n requestSchema,\n responseSchemas,\n version\n )\n ])\n )\n : this.#localParamRequest(\n middlewares as RouterHandler[],\n controllerHandler as RouterHandler,\n contractDetails as PathParamHttpContractDetails<SV>,\n requestSchema,\n responseSchemas\n )\n };\n\n const contractDetailsName = contractDetails.name;\n if (contractDetailsName) {\n toRecord(this.sdk)[toPrettyCamelCase(contractDetailsName)] =\n contractDetails.versions\n ? Object.fromEntries(\n Object.keys(contractDetails.versions).map((version) => [\n version,\n (req: {\n params?: Record<string, unknown>;\n query?: Record<string, unknown>;\n headers?: Record<string, unknown>;\n body?: Record<string, unknown>;\n }) =>\n this.#localParamRequest(\n middlewares as RouterHandler[],\n controllerHandler as RouterHandler,\n contractDetails as PathParamHttpContractDetails<SV>,\n requestSchema,\n responseSchemas,\n version\n )(`${this.basePath}${path}`, req)\n ])\n )\n : (req: {\n params?: Record<string, unknown>;\n query?: Record<string, unknown>;\n headers?: Record<string, unknown>;\n body?: Record<string, unknown>;\n }) =>\n this.#localParamRequest(\n middlewares as RouterHandler[],\n controllerHandler as RouterHandler,\n contractDetails as PathParamHttpContractDetails<SV>,\n requestSchema,\n responseSchemas\n )(`${this.basePath}${path}`, req);\n }\n return this as this & {\n _fetchMap: FetchMap extends Record<\n SanitizePathSlashes<`${BasePath}${Path}`>,\n unknown\n >\n ? FetchMap &\n Record<\n SanitizePathSlashes<`${BasePath}${Path}`>,\n FetchMap[SanitizePathSlashes<`${BasePath}${Path}`>] &\n Record<\n Uppercase<ContractMethod>,\n LiveTypeFunction<\n SV,\n SanitizePathSlashes<`${BasePath}${Path}`>,\n P,\n ResBodyMap,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n ResHeaders,\n ContractMethod,\n VersionedApi,\n Auth\n >\n >\n >\n : FetchMap &\n Record<\n SanitizePathSlashes<`${BasePath}${Path}`>,\n Record<\n Uppercase<ContractMethod>,\n LiveTypeFunction<\n SV,\n SanitizePathSlashes<`${BasePath}${Path}`>,\n P,\n ResBodyMap,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n ResHeaders,\n ContractMethod,\n VersionedApi,\n Auth\n >\n >\n >;\n sdk: Sdk &\n Record<\n PrettyCamelCase<\n Name extends string\n ? Name\n : SanitizePathSlashes<`${BasePath}${Path}`>\n >,\n LiveSdkFunction<\n SV,\n P,\n ResBodyMap,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n ResHeaders,\n VersionedApi,\n Auth\n >\n >;\n };\n }\n\n #extractHandlers<\n Name extends string,\n Path extends `/${string}`,\n P extends ParamsObject<SV>,\n ResBodyMap extends ResponsesObject<SV>,\n ReqBody extends Body<SV>,\n ReqQuery extends QueryObject<SV>,\n ReqHeaders extends HeadersObject<SV>,\n ResHeaders extends HeadersObject<SV>,\n LocalsObj extends Record<string, unknown>,\n ArrayReturnType,\n VersionedApi extends VersionSchema<SV, 'middleware'>,\n Auth extends SchemaAuthMethods<\n SV,\n P,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n VersionedApi,\n BaseRequest\n >\n >(\n handlers: (\n | MiddlewareOrMiddlewareWithTypedHandler<\n SV,\n Name,\n 'middleware',\n Path,\n P,\n ResBodyMap,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n ResHeaders,\n LocalsObj,\n VersionedApi,\n BaseRequest,\n BaseResponse,\n NextFunction,\n RouterSession,\n Auth\n >\n | ConstrainedForklaunchRouter<SV, RouterHandler>\n | RouterHandler\n )[],\n processMiddleware?: (handler: unknown) => RouterHandler | Internal\n ) {\n const last = handlers.pop();\n let finalHandlers = last ? [last] : [];\n if (\n isTypedHandler<\n SV,\n Name,\n 'middleware',\n Path,\n P,\n ResBodyMap,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n ResHeaders,\n LocalsObj,\n VersionedApi,\n BaseRequest,\n BaseResponse,\n NextFunction,\n Auth\n >(last)\n ) {\n finalHandlers = last.handlers;\n }\n\n handlers.forEach((handler) => {\n if (\n isTypedHandler<\n SV,\n Name,\n 'middleware',\n Path,\n P,\n ResBodyMap,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n ResHeaders,\n LocalsObj,\n VersionedApi,\n BaseRequest,\n BaseResponse,\n NextFunction,\n Auth\n >(handler)\n ) {\n throw new Error(\n 'Only the last argument supplied to this function can be a typed handler. Please use only middleware.'\n );\n }\n });\n\n const middleware = processMiddleware\n ? handlers.map(processMiddleware)\n : (handlers as ArrayReturnType[]);\n\n return [...middleware, ...finalHandlers] as ArrayReturnType[];\n }\n\n #extractMiddlewareFromEnrichedTypedHandlerArray<\n Name extends string,\n Path extends `/${string}`,\n P extends ParamsObject<SV>,\n ResBodyMap extends ResponsesObject<SV>,\n ReqBody extends Body<SV>,\n ReqQuery extends QueryObject<SV>,\n ReqHeaders extends HeadersObject<SV>,\n ResHeaders extends HeadersObject<SV>,\n LocalsObj extends Record<string, unknown>,\n VersionedApi extends VersionSchema<SV, 'middleware'>,\n Auth extends SchemaAuthMethods<\n SV,\n P,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n VersionedApi,\n BaseRequest\n >\n >(\n handlers: (\n | MiddlewareOrMiddlewareWithTypedHandler<\n SV,\n Name,\n 'middleware',\n Path,\n P,\n ResBodyMap,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n ResHeaders,\n LocalsObj,\n VersionedApi,\n BaseRequest,\n BaseResponse,\n NextFunction,\n RouterSession,\n Auth\n >\n | RouterHandler\n )[]\n ) {\n return this.#extractHandlers<\n Name,\n Path,\n P,\n ResBodyMap,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n ResHeaders,\n LocalsObj,\n RouterHandler,\n VersionedApi,\n Auth\n >(handlers);\n }\n\n #extractNestableMiddlewareFromEnrichedTypedHandlerArray<\n Name extends string,\n Path extends `/${string}`,\n P extends ParamsObject<SV>,\n ResBodyMap extends ResponsesObject<SV>,\n ReqBody extends Body<SV>,\n ReqQuery extends QueryObject<SV>,\n ReqHeaders extends HeadersObject<SV>,\n ResHeaders extends HeadersObject<SV>,\n LocalsObj extends Record<string, unknown>,\n VersionedApi extends VersionSchema<SV, 'middleware'>,\n Auth extends SchemaAuthMethods<\n SV,\n P,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n VersionedApi,\n BaseRequest\n >\n >(\n handlers: (\n | MiddlewareOrMiddlewareWithTypedHandler<\n SV,\n Name,\n 'middleware',\n Path,\n P,\n ResBodyMap,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n ResHeaders,\n LocalsObj,\n VersionedApi,\n BaseRequest,\n BaseResponse,\n NextFunction,\n RouterSession,\n Auth\n >\n | ConstrainedForklaunchRouter<SV, RouterHandler>\n )[]\n ) {\n return this.#extractHandlers<\n Name,\n Path,\n P,\n ResBodyMap,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n ResHeaders,\n LocalsObj,\n RouterHandler | Internal,\n VersionedApi,\n Auth\n >(handlers, (handler) => {\n if (\n isForklaunchExpressLikeRouter<\n SV,\n Path,\n RouterHandler,\n Internal,\n BaseRequest,\n BaseResponse,\n NextFunction,\n FetchMap,\n Sdk\n >(handler)\n ) {\n this.addRouterToSdk(handler);\n return handler.internal;\n }\n return handler as RouterHandler;\n });\n }\n\n #processTypedHandlerOrMiddleware<\n Name extends string,\n Path extends `/${string}`,\n P extends ParamsObject<SV>,\n ResBodyMap extends ResponsesObject<SV>,\n ReqBody extends Body<SV>,\n ReqQuery extends QueryObject<SV>,\n ReqHeaders extends HeadersObject<SV>,\n ResHeaders extends HeadersObject<SV>,\n LocalsObj extends Record<string, unknown>,\n VersionedApi extends VersionSchema<SV, 'middleware'>,\n Auth extends SchemaAuthMethods<\n SV,\n P,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n VersionedApi,\n BaseRequest\n >\n >(\n handler:\n | ContractDetailsOrMiddlewareOrTypedHandler<\n SV,\n Name,\n 'middleware',\n Path,\n P,\n ResBodyMap,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n ResHeaders,\n LocalsObj,\n VersionedApi,\n BaseRequest,\n BaseResponse,\n NextFunction,\n RouterSession,\n Auth\n >\n | RouterHandler\n | undefined,\n middleware: RouterHandler[]\n ) {\n if (\n isTypedHandler<\n SV,\n Name,\n 'middleware',\n Path,\n P,\n ResBodyMap,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n ResHeaders,\n LocalsObj,\n VersionedApi,\n BaseRequest,\n BaseResponse,\n NextFunction,\n Auth\n >(handler)\n ) {\n middleware.push(...(handler.handlers as RouterHandler[]));\n } else if (isExpressLikeSchemaHandler(handler)) {\n middleware.push(handler as RouterHandler);\n }\n }\n\n #extractMiddlewareAsRouterHandlers<\n Name extends string,\n Path extends `/${string}`,\n P extends ParamsObject<SV>,\n ResBodyMap extends ResponsesObject<SV>,\n ReqBody extends Body<SV>,\n ReqQuery extends QueryObject<SV>,\n ReqHeaders extends HeadersObject<SV>,\n ResHeaders extends HeadersObject<SV>,\n LocalsObj extends Record<string, unknown>,\n VersionedApi extends VersionSchema<SV, 'middleware'>,\n Auth extends SchemaAuthMethods<\n SV,\n P,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n VersionedApi,\n BaseRequest\n >\n >(\n contractDetailsOrMiddlewareOrTypedHandler:\n | ContractDetailsOrMiddlewareOrTypedHandler<\n SV,\n Name,\n 'middleware',\n Path,\n P,\n ResBodyMap,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n ResHeaders,\n LocalsObj,\n VersionedApi,\n BaseRequest,\n BaseResponse,\n NextFunction,\n RouterSession,\n Auth\n >\n | RouterHandler\n | undefined,\n middlewareOrMiddlewareWithTypedHandler: (\n | MiddlewareOrMiddlewareWithTypedHandler<\n SV,\n Name,\n 'middleware',\n Path,\n P,\n ResBodyMap,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n ResHeaders,\n LocalsObj,\n VersionedApi,\n BaseRequest,\n BaseResponse,\n NextFunction,\n RouterSession,\n Auth\n >\n | RouterHandler\n )[]\n ) {\n const middleware: RouterHandler[] = [];\n\n this.#processTypedHandlerOrMiddleware<\n Name,\n Path,\n P,\n ResBodyMap,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n ResHeaders,\n LocalsObj,\n VersionedApi,\n Auth\n >(contractDetailsOrMiddlewareOrTypedHandler, middleware);\n\n middleware.push(\n ...this.#extractMiddlewareFromEnrichedTypedHandlerArray<\n Name,\n Path,\n P,\n ResBodyMap,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n ResHeaders,\n LocalsObj,\n VersionedApi,\n Auth\n >(middlewareOrMiddlewareWithTypedHandler)\n );\n\n return middleware;\n }\n\n #extractNestableMiddlewareAsRouterHandlers<\n Name extends string,\n Path extends `/${string}`,\n P extends ParamsObject<SV>,\n ResBodyMap extends ResponsesObject<SV>,\n ReqBody extends Body<SV>,\n ReqQuery extends QueryObject<SV>,\n ReqHeaders extends HeadersObject<SV>,\n ResHeaders extends HeadersObject<SV>,\n LocalsObj extends Record<string, unknown>,\n VersionedApi extends VersionSchema<SV, 'middleware'>,\n Auth extends SchemaAuthMethods<\n SV,\n P,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n VersionedApi,\n BaseRequest\n >\n >(\n contractDetailsOrMiddlewareOrTypedHandler:\n | ContractDetailsOrMiddlewareOrTypedHandler<\n SV,\n Name,\n 'middleware',\n Path,\n P,\n ResBodyMap,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n ResHeaders,\n LocalsObj,\n VersionedApi,\n BaseRequest,\n BaseResponse,\n NextFunction,\n RouterSession,\n Auth\n >\n | ConstrainedForklaunchRouter<SV, RouterHandler>\n | undefined,\n middlewareOrMiddlewareWithTypedHandler: (\n | MiddlewareOrMiddlewareWithTypedHandler<\n SV,\n Name,\n 'middleware',\n Path,\n P,\n ResBodyMap,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n ResHeaders,\n LocalsObj,\n VersionedApi,\n BaseRequest,\n BaseResponse,\n NextFunction,\n RouterSession,\n Auth\n >\n | ConstrainedForklaunchRouter<SV, RouterHandler>\n )[]\n ) {\n const middleware: (RouterHandler | Internal)[] = [];\n\n this.#processTypedHandlerOrMiddleware<\n Name,\n Path,\n P,\n ResBodyMap,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n ResHeaders,\n LocalsObj,\n VersionedApi,\n Auth\n >(\n contractDetailsOrMiddlewareOrTypedHandler as ContractDetailsOrMiddlewareOrTypedHandler<\n SV,\n Name,\n 'middleware',\n Path,\n P,\n ResBodyMap,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n ResHeaders,\n LocalsObj,\n VersionedApi,\n BaseRequest,\n BaseResponse,\n NextFunction,\n RouterSession,\n Auth\n >,\n middleware as RouterHandler[]\n );\n\n if (\n isForklaunchExpressLikeRouter<\n SV,\n Path,\n RouterHandler,\n Internal,\n BaseRequest,\n BaseResponse,\n NextFunction,\n FetchMap,\n Sdk\n >(contractDetailsOrMiddlewareOrTypedHandler)\n ) {\n this.addRouterToSdk(contractDetailsOrMiddlewareOrTypedHandler);\n middleware.push(contractDetailsOrMiddlewareOrTypedHandler.internal);\n }\n\n middleware.push(\n ...this.#extractNestableMiddlewareFromEnrichedTypedHandlerArray<\n Name,\n Path,\n P,\n ResBodyMap,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n ResHeaders,\n LocalsObj,\n VersionedApi,\n Auth\n >(middlewareOrMiddlewareWithTypedHandler)\n );\n\n return middleware;\n }\n\n registerMiddlewareHandler<\n Name extends string,\n Path extends `/${string}`,\n P extends ParamsObject<SV>,\n ResBodyMap extends ResponsesObject<SV>,\n ReqBody extends Body<SV>,\n ReqQuery extends QueryObject<SV>,\n ReqHeaders extends HeadersObject<SV>,\n ResHeaders extends HeadersObject<SV>,\n LocalsObj extends Record<string, unknown>,\n VersionedApi extends VersionSchema<SV, 'middleware'>,\n Auth extends SchemaAuthMethods<\n SV,\n P,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n VersionedApi,\n BaseRequest\n >\n >(\n registrationMethod: PathOrMiddlewareBasedHandler<RouterHandler>,\n pathOrContractDetailsOrMiddlewareOrTypedHandler:\n | Path\n | ContractDetailsOrMiddlewareOrTypedHandler<\n SV,\n Name,\n 'middleware',\n Path,\n P,\n ResBodyMap,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n ResHeaders,\n LocalsObj,\n VersionedApi,\n BaseRequest,\n BaseResponse,\n NextFunction,\n RouterSession,\n Auth\n >\n | RouterHandler,\n contractDetailsOrMiddlewareOrTypedHandler?:\n | ContractDetailsOrMiddlewareOrTypedHandler<\n SV,\n Name,\n 'middleware',\n Path,\n P,\n ResBodyMap,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n ResHeaders,\n LocalsObj,\n VersionedApi,\n BaseRequest,\n BaseResponse,\n NextFunction,\n RouterSession,\n Auth\n >\n | RouterHandler,\n ...middlewareOrMiddlewareWithTypedHandler: (\n | MiddlewareOrMiddlewareWithTypedHandler<\n SV,\n Name,\n 'middleware',\n Path,\n P,\n ResBodyMap,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n ResHeaders,\n LocalsObj,\n VersionedApi,\n BaseRequest,\n BaseResponse,\n NextFunction,\n RouterSession,\n Auth\n >\n | RouterHandler\n )[]\n ): this {\n const middleware: RouterHandler[] = [];\n\n if (typeof pathOrContractDetailsOrMiddlewareOrTypedHandler === 'string') {\n middleware.push(\n ...this.#extractMiddlewareAsRouterHandlers<\n Name,\n Path,\n P,\n ResBodyMap,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n ResHeaders,\n LocalsObj,\n VersionedApi,\n Auth\n >(\n contractDetailsOrMiddlewareOrTypedHandler,\n middlewareOrMiddlewareWithTypedHandler\n )\n );\n const path = pathOrContractDetailsOrMiddlewareOrTypedHandler;\n registrationMethod.bind(this.internal)(path, ...middleware);\n } else {\n middleware.push(\n ...this.#extractMiddlewareAsRouterHandlers<\n Name,\n Path,\n P,\n ResBodyMap,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n ResHeaders,\n LocalsObj,\n VersionedApi,\n Auth\n >(\n pathOrContractDetailsOrMiddlewareOrTypedHandler,\n (\n (isExpressLikeSchemaHandler<\n SV,\n 'middleware',\n P,\n ResBodyMap,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n ResHeaders,\n LocalsObj,\n VersionedApi,\n RouterSession,\n BaseRequest,\n BaseResponse,\n NextFunction\n >(contractDetailsOrMiddlewareOrTypedHandler) ||\n isTypedHandler<\n SV,\n Name,\n 'middleware',\n Path,\n P,\n ResBodyMap,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n ResHeaders,\n LocalsObj,\n VersionedApi,\n BaseRequest,\n BaseResponse,\n NextFunction,\n Auth\n >(contractDetailsOrMiddlewareOrTypedHandler)\n ? [contractDetailsOrMiddlewareOrTypedHandler]\n : []) as (\n | MiddlewareOrMiddlewareWithTypedHandler<\n SV,\n Name,\n 'middleware',\n Path,\n P,\n ResBodyMap,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n ResHeaders,\n LocalsObj,\n VersionedApi,\n BaseRequest,\n BaseResponse,\n NextFunction,\n RouterSession,\n Auth\n >\n | RouterHandler\n )[]\n ).concat(middlewareOrMiddlewareWithTypedHandler)\n )\n );\n registrationMethod.bind(this.internal)(...middleware);\n }\n return this;\n }\n\n private addRouterToSdk(\n router: ConstrainedForklaunchRouter<SV, RouterHandler>\n ) {\n Object.entries(router._fetchMap).map(\n ([key, value]) =>\n (toRecord(this._fetchMap)[\n sanitizePathSlashes(`${this.basePath}${key}`)\n ] = value)\n );\n\n const existingSdk =\n this.sdk[router.sdkName ?? toPrettyCamelCase(router.basePath)];\n toRecord(this.sdk)[router.sdkName ?? toPrettyCamelCase(router.basePath)] = {\n ...(typeof existingSdk === 'object' ? existingSdk : {}),\n ...router.sdk\n };\n }\n\n registerNestableMiddlewareHandler<\n Name extends string,\n Path extends `/${string}`,\n P extends ParamsObject<SV>,\n ResBodyMap extends ResponsesObject<SV>,\n ReqBody extends Body<SV>,\n ReqQuery extends QueryObject<SV>,\n ReqHeaders extends HeadersObject<SV>,\n ResHeaders extends HeadersObject<SV>,\n LocalsObj extends Record<string, unknown>,\n VersionedApi extends VersionSchema<SV, 'middleware'>,\n const SessionSchema extends SessionObject<SV>,\n Auth extends SchemaAuthMethods<\n SV,\n P,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n VersionedApi,\n BaseRequest\n >\n >(\n registrationMethod: NestableRouterBasedHandler<RouterHandler, Internal>,\n pathOrContractDetailsOrMiddlewareOrTypedHandler:\n | Path\n | ContractDetailsOrMiddlewareOrTypedHandler<\n SV,\n Name,\n 'middleware',\n Path,\n P,\n ResBodyMap,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n ResHeaders,\n LocalsObj,\n VersionedApi,\n BaseRequest,\n BaseResponse,\n NextFunction,\n RouterSession,\n Auth\n >\n | ConstrainedForklaunchRouter<SV, RouterHandler>,\n contractDetailsOrMiddlewareOrTypedHandler?:\n | ContractDetailsOrMiddlewareOrTypedHandler<\n SV,\n Name,\n 'middleware',\n Path,\n P,\n ResBodyMap,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n ResHeaders,\n LocalsObj,\n VersionedApi,\n BaseRequest,\n BaseResponse,\n NextFunction,\n RouterSession,\n Auth\n >\n | ConstrainedForklaunchRouter<SV, RouterHandler>,\n ...middlewareOrMiddlewareWithTypedHandler: (\n | MiddlewareOrMiddlewareWithTypedHandler<\n SV,\n Name,\n 'middleware',\n Path,\n P,\n ResBodyMap,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n ResHeaders,\n LocalsObj,\n VersionedApi,\n BaseRequest,\n BaseResponse,\n NextFunction,\n RouterSession,\n Auth\n >\n | ConstrainedForklaunchRouter<SV, RouterHandler>\n )[]\n ): this {\n const middleware: (RouterHandler | Internal)[] = [];\n let path: `/${string}` | undefined;\n\n if (typeof pathOrContractDetailsOrMiddlewareOrTypedHandler === 'string') {\n middleware.push(\n ...this.#extractNestableMiddlewareAsRouterHandlers<\n Name,\n Path,\n P,\n ResBodyMap,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n ResHeaders,\n LocalsObj,\n VersionedApi,\n Auth\n >(\n contractDetailsOrMiddlewareOrTypedHandler,\n middlewareOrMiddlewareWithTypedHandler\n )\n );\n path = pathOrContractDetailsOrMiddlewareOrTypedHandler;\n } else {\n if (\n isConstrainedForklaunchRouter<SV, RouterHandler>(\n pathOrContractDetailsOrMiddlewareOrTypedHandler\n )\n ) {\n const router = pathOrContractDetailsOrMiddlewareOrTypedHandler;\n\n this.addRouterToSdk(router);\n path = router.basePath;\n }\n middleware.push(\n ...this.#extractNestableMiddlewareAsRouterHandlers<\n Name,\n Path,\n P,\n ResBodyMap,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n ResHeaders,\n LocalsObj,\n VersionedApi,\n Auth\n >(\n pathOrContractDetailsOrMiddlewareOrTypedHandler,\n (isExpressLikeSchemaHandler<\n SV,\n 'middleware',\n P,\n ResBodyMap,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n ResHeaders,\n LocalsObj,\n VersionedApi,\n SessionObject<SV> extends SessionSchema\n ? RouterSession\n : SessionSchema,\n BaseRequest,\n BaseResponse,\n NextFunction\n >(contractDetailsOrMiddlewareOrTypedHandler) ||\n isTypedHandler<\n SV,\n Name,\n 'middleware',\n Path,\n P,\n ResBodyMap,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n ResHeaders,\n LocalsObj,\n VersionedApi,\n BaseRequest,\n BaseResponse,\n NextFunction,\n Auth\n >(contractDetailsOrMiddlewareOrTypedHandler) ||\n isConstrainedForklaunchRouter<SV, RouterHandler>(\n contractDetailsOrMiddlewareOrTypedHandler\n )\n ? [contractDetailsOrMiddlewareOrTypedHandler]\n : []\n ).concat(middlewareOrMiddlewareWithTypedHandler)\n )\n );\n }\n\n if (!path) {\n path = middleware.filter((m) =>\n isForklaunchExpressLikeRouter<\n SV,\n Path,\n RouterHandler,\n Internal,\n BaseRequest,\n BaseResponse,\n NextFunction,\n FetchMap,\n Sdk\n >(m)\n )[0]?.basePath;\n }\n\n if (path) {\n registrationMethod.bind(this.internal)(path, ...middleware);\n } else {\n registrationMethod.bind(this.internal)(...middleware);\n }\n return this;\n }\n\n private addRouterOptions(\n router: ConstrainedForklaunchRouter<SV, RouterHandler>\n ) {\n router.routerOptions = {\n ...(this.routerOptions ?? {}),\n ...(router.routerOptions ?? {})\n } as typeof this.routerOptions;\n\n router.routers.forEach((subRouter) => {\n this.addRouterOptions(\n subRouter as ConstrainedForklaunchRouter<SV, RouterHandler>\n );\n });\n }\n\n /**\n * Validates that all protected routes have the required surfacing functions\n * available (from the route, router, or application level).\n * Call this at listen() time when the full option chain is assembled.\n */\n validateSurfacingFunctions(\n router: ForklaunchRouter<SV> = this,\n parentAuth?: Record<string, unknown>\n ) {\n const routerAuth =\n router.routerOptions?.auth &&\n typeof router.routerOptions.auth === 'object'\n ? router.routerOptions.auth\n : undefined;\n const globalAuth =\n routerAuth && parentAuth\n ? { ...parentAuth, ...routerAuth }\n : (routerAuth ?? parentAuth);\n\n for (const route of router.routes) {\n const auth = route.contractDetails.auth;\n const access = route.contractDetails.access;\n if (!auth || access !== 'protected') continue;\n\n const routeAuth = auth as Record<string, unknown>;\n const routeName = route.contractDetails.name;\n\n if (hasPermissionChecks(auth)) {\n if (\n !routeAuth['surfacePermissions'] &&\n !globalAuth?.surfacePermissions\n ) {\n throw new Error(\n `Route '${routeName}': declares allowedPermissions or forbiddenPermissions ` +\n `but no surfacePermissions function was provided on the route, router, or application`\n );\n }\n }\n\n if (hasRoleChecks(auth)) {\n if (!routeAuth['surfaceRoles'] && !globalAuth?.surfaceRoles) {\n throw new Error(\n `Route '${routeName}': declares allowedRoles or forbiddenRoles ` +\n `but no surfaceRoles function was provided on the route, router, or application`\n );\n }\n }\n\n if (hasScopeChecks(auth)) {\n if (!routeAuth['surfaceScopes'] && !globalAuth?.surfaceScopes) {\n throw new Error(\n `Route '${routeName}': declares requiredScope ` +\n `but no surfaceScopes function was provided on the route, router, or application`\n );\n }\n }\n }\n\n for (const subRouter of router.routers) {\n this.validateSurfacingFunctions(subRouter, globalAuth);\n }\n }\n\n use: TypedNestableMiddlewareDefinition<\n this,\n RouterHandler,\n Internal,\n SV,\n RouterSession,\n BaseRequest,\n BaseResponse,\n NextFunction\n > = <\n Name extends string,\n Path extends `/${string}`,\n P extends ParamsObject<SV>,\n ResBodyMap extends ResponsesObject<SV>,\n ReqBody extends Body<SV>,\n ReqQuery extends QueryObject<SV>,\n ReqHeaders extends HeadersObject<SV>,\n ResHeaders extends HeadersObject<SV>,\n LocalsObj extends Record<string, unknown>,\n Router extends ConstrainedForklaunchRouter<SV, RouterHandler>,\n VersionedApi extends VersionSchema<SV, 'middleware'>,\n SessionSchema extends SessionObject<SV>,\n ResolvedSchema extends (SessionObject<SV> extends SessionSchema\n ? RouterSession\n : SessionSchema),\n Auth extends SchemaAuthMethods<\n SV,\n P,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n VersionedApi,\n BaseRequest\n >\n >(\n pathOrContractDetailsOrMiddlewareOrTypedHandler:\n | Path\n | ContractDetailsOrMiddlewareOrTypedHandler<\n SV,\n Name,\n 'middleware',\n Path,\n P,\n ResBodyMap,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n ResHeaders,\n LocalsObj,\n VersionedApi,\n BaseRequest,\n BaseResponse,\n NextFunction,\n RouterSession,\n Auth\n >\n | Router,\n contractDetailsOrMiddlewareOrTypedHandler?:\n | ContractDetailsOrMiddlewareOrTypedHandler<\n SV,\n Name,\n 'middleware',\n Path,\n P,\n ResBodyMap,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n ResHeaders,\n LocalsObj,\n VersionedApi,\n BaseRequest,\n BaseResponse,\n NextFunction,\n RouterSession,\n Auth\n >\n | Router,\n ...middlewareOrMiddlewareWithTypedHandler: (\n | MiddlewareOrMiddlewareWithTypedHandler<\n SV,\n Name,\n 'middleware',\n Path,\n P,\n ResBodyMap,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n ResHeaders,\n LocalsObj,\n VersionedApi,\n BaseRequest,\n BaseResponse,\n NextFunction,\n RouterSession,\n Auth\n >\n | Router\n )[]\n ) => {\n [\n pathOrContractDetailsOrMiddlewareOrTypedHandler,\n contractDetailsOrMiddlewareOrTypedHandler,\n ...middlewareOrMiddlewareWithTypedHandler\n ].forEach((arg) => {\n if (isForklaunchRouter<SV>(arg)) {\n this.routers.push(arg);\n this.addRouterOptions(\n arg as ConstrainedForklaunchRouter<SV, RouterHandler>\n );\n }\n });\n\n return this.registerNestableMiddlewareHandler<\n Name,\n Path,\n P,\n ResBodyMap,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n ResHeaders,\n LocalsObj,\n VersionedApi,\n ResolvedSchema,\n Auth\n >(\n this.internal.use,\n pathOrContractDetailsOrMiddlewareOrTypedHandler,\n contractDetailsOrMiddlewareOrTypedHandler,\n ...middlewareOrMiddlewareWithTypedHandler\n ) as this & {\n _fetchMap: FetchMap & {\n [\n Key in keyof Router['_fetchMap'] as Key extends string\n ? SanitizePathSlashes<`${BasePath}${Key}`>\n : never\n ]: Router['_fetchMap'][Key];\n };\n sdk: Sdk & {\n [\n Key in PrettyCamelCase<\n Router extends { sdkName?: string; basePath: string }\n ? string extends Router['sdkName']\n ? Router['basePath']\n : Router['sdkName']\n : never\n >\n ]: Router['sdk'];\n };\n };\n };\n\n all: TypedMiddlewareDefinition<\n this,\n SV,\n RouterSession,\n BaseRequest,\n BaseResponse,\n NextFunction,\n RouterHandler\n > = <\n Name extends string,\n Path extends `/${string}`,\n P extends ParamsObject<SV>,\n ResBodyMap extends ResponsesObject<SV>,\n ReqBody extends Body<SV>,\n ReqQuery extends QueryObject<SV>,\n ReqHeaders extends HeadersObject<SV>,\n ResHeaders extends HeadersObject<SV>,\n LocalsObj extends Record<string, unknown>,\n VersionedApi extends VersionSchema<SV, 'middleware'>,\n Auth extends SchemaAuthMethods<\n SV,\n P,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n VersionedApi,\n BaseRequest\n >\n >(\n pathOrContractDetailsOrMiddlewareOrTypedHandler:\n | Path\n | ContractDetailsOrMiddlewareOrTypedHandler<\n SV,\n Name,\n 'middleware',\n Path,\n P,\n ResBodyMap,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n ResHeaders,\n LocalsObj,\n VersionedApi,\n BaseRequest,\n BaseResponse,\n NextFunction,\n RouterSession,\n Auth\n >\n | RouterHandler,\n contractDetailsOrMiddlewareOrTypedHandler?:\n | ContractDetailsOrMiddlewareOrTypedHandler<\n SV,\n Name,\n 'middleware',\n Path,\n P,\n ResBodyMap,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n ResHeaders,\n LocalsObj,\n VersionedApi,\n BaseRequest,\n BaseResponse,\n NextFunction,\n RouterSession,\n Auth\n >\n | RouterHandler,\n ...middlewareOrMiddlewareWithTypedHandler: (\n | MiddlewareOrMiddlewareWithTypedHandler<\n SV,\n Name,\n 'middleware',\n Path,\n P,\n ResBodyMap,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n ResHeaders,\n LocalsObj,\n VersionedApi,\n BaseRequest,\n BaseResponse,\n NextFunction,\n RouterSession,\n Auth\n >\n | RouterHandler\n )[]\n ) => {\n return this.registerMiddlewareHandler<\n Name,\n Path,\n P,\n ResBodyMap,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n ResHeaders,\n LocalsObj,\n VersionedApi,\n Auth\n >(\n this.internal.all,\n pathOrContractDetailsOrMiddlewareOrTypedHandler,\n contractDetailsOrMiddlewareOrTypedHandler,\n ...middlewareOrMiddlewareWithTypedHandler\n );\n };\n\n connect: TypedMiddlewareDefinition<\n this,\n SV,\n RouterSession,\n BaseRequest,\n BaseResponse,\n NextFunction,\n RouterHandler\n > = <\n Name extends string,\n Path extends `/${string}`,\n P extends ParamsObject<SV>,\n ResBodyMap extends ResponsesObject<SV>,\n ReqBody extends Body<SV>,\n ReqQuery extends QueryObject<SV>,\n ReqHeaders extends HeadersObject<SV>,\n ResHeaders extends HeadersObject<SV>,\n LocalsObj extends Record<string, unknown>,\n VersionedApi extends VersionSchema<SV, 'middleware'>,\n Auth extends SchemaAuthMethods<\n SV,\n P,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n VersionedApi,\n BaseRequest\n >\n >(\n pathOrContractDetailsOrMiddlewareOrTypedHandler:\n | Path\n | ContractDetailsOrMiddlewareOrTypedHandler<\n SV,\n Name,\n 'middleware',\n Path,\n P,\n ResBodyMap,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n ResHeaders,\n LocalsObj,\n VersionedApi,\n BaseRequest,\n BaseResponse,\n NextFunction,\n RouterSession,\n Auth\n >\n | RouterHandler,\n contractDetailsOrMiddlewareOrTypedHandler?:\n | ContractDetailsOrMiddlewareOrTypedHandler<\n SV,\n Name,\n 'middleware',\n Path,\n P,\n ResBodyMap,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n ResHeaders,\n LocalsObj,\n VersionedApi,\n BaseRequest,\n BaseResponse,\n NextFunction,\n RouterSession,\n Auth\n >\n | RouterHandler,\n ...middlewareOrMiddlewareWithTypedHandler: (\n | MiddlewareOrMiddlewareWithTypedHandler<\n SV,\n Name,\n 'middleware',\n Path,\n P,\n ResBodyMap,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n ResHeaders,\n LocalsObj,\n VersionedApi,\n BaseRequest,\n BaseResponse,\n NextFunction,\n RouterSession,\n Auth\n >\n | RouterHandler\n )[]\n ) => {\n return this.registerMiddlewareHandler<\n Name,\n Path,\n P,\n ResBodyMap,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n ResHeaders,\n LocalsObj,\n VersionedApi,\n Auth\n >(\n this.internal.connect,\n pathOrContractDetailsOrMiddlewareOrTypedHandler,\n contractDetailsOrMiddlewareOrTypedHandler,\n ...middlewareOrMiddlewareWithTypedHandler\n );\n };\n\n /**\n * Registers a GET route with the specified contract details and handler handlers.\n *\n * @template P - The type of request parameters.\n * @template ResBodyMap - The type of response body.\n * @template ReqBody - The type of request body.\n * @template ReqQuery - The type of request query.\n * @template LocalsObj - The type of local variables.\n * @param {string} path - The path for the route.\n * @param {PathParamHttpContractDetails<SV, P, ResBodyMap, ReqQuery>} contractDetails - The contract details.\n * @param {...SchemaHandler<SV, P, ResBodyMap, ReqBody, ReqQuery, LocalsObj>[]} handlers - The handler handlers.\n * @returns {ExpressRouter} - The Express router.\n */\n get: LiveTypeRouteDefinition<\n SV,\n BasePath,\n 'get',\n RouterHandler,\n Internal,\n RouterSession,\n BaseRequest,\n BaseResponse,\n NextFunction,\n this\n > = <\n Name extends string,\n Path extends `/${string}`,\n P extends ParamsObject<SV>,\n ResBodyMap extends ResponsesObject<SV>,\n ReqBody extends Body<SV>,\n ReqQuery extends QueryObject<SV>,\n ReqHeaders extends HeadersObject<SV>,\n ResHeaders extends HeadersObject<SV>,\n LocalsObj extends Record<string, unknown>,\n VersionedApi extends VersionSchema<SV, 'get'>,\n Auth extends SchemaAuthMethods<\n SV,\n P,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n VersionedApi,\n BaseRequest\n >\n >(\n path: Path,\n contractDetailsOrMiddlewareOrTypedHandler: ContractDetailsOrMiddlewareOrTypedHandler<\n SV,\n Name,\n 'get',\n Path,\n P,\n ResBodyMap,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n ResHeaders,\n LocalsObj,\n VersionedApi,\n BaseRequest,\n BaseResponse,\n NextFunction,\n RouterSession,\n Auth\n >,\n ...middlewareOrMiddlewareWithTypedHandler: MiddlewareOrMiddlewareWithTypedHandler<\n SV,\n Name,\n 'get',\n Path,\n P,\n ResBodyMap,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n ResHeaders,\n LocalsObj,\n VersionedApi,\n BaseRequest,\n BaseResponse,\n NextFunction,\n RouterSession,\n Auth\n >[]\n ) => {\n return this.registerRoute<\n Name,\n 'get',\n Path,\n P,\n ResBodyMap,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n ResHeaders,\n LocalsObj,\n VersionedApi,\n Auth\n >(\n 'get',\n path,\n this.internal.get,\n contractDetailsOrMiddlewareOrTypedHandler,\n ...middlewareOrMiddlewareWithTypedHandler\n );\n };\n\n /**\n * Registers a POST route with the specified contract details and handler handlers.\n *\n * @template P - The type of request parameters.\n * @template ResBodyMap - The type of response body.\n * @template ReqBody - The type of request body.\n * @template ReqQuery - The type of request query.\n * @template LocalsObj - The type of local variables.\n * @param {string} path - The path for the route.\n * @param {HttpContractDetails<SV, P, ResBodyMap, ReqBody, ReqQuery>} contractDetails - The contract details.\n * @param {...SchemaHandler<SV, P, ResBodyMap, ReqBody, ReqQuery, LocalsObj>[]} handlers - The handler handlers.\n * @returns {ExpressRouter} - The Expxwress router.\n */\n post: LiveTypeRouteDefinition<\n SV,\n BasePath,\n 'post',\n RouterHandler,\n Internal,\n RouterSession,\n BaseRequest,\n BaseResponse,\n NextFunction,\n this\n > = <\n Name extends string,\n Path extends `/${string}`,\n P extends ParamsObject<SV>,\n ResBodyMap extends ResponsesObject<SV>,\n ReqBody extends Body<SV>,\n ReqQuery extends QueryObject<SV>,\n ReqHeaders extends HeadersObject<SV>,\n ResHeaders extends HeadersObject<SV>,\n LocalsObj extends Record<string, unknown>,\n VersionedApi extends VersionSchema<SV, 'post'>,\n Auth extends SchemaAuthMethods<\n SV,\n P,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n VersionedApi,\n BaseRequest\n >\n >(\n path: Path,\n contractDetailsOrMiddlewareOrTypedHandler: ContractDetailsOrMiddlewareOrTypedHandler<\n SV,\n Name,\n 'post',\n Path,\n P,\n ResBodyMap,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n ResHeaders,\n LocalsObj,\n VersionedApi,\n BaseRequest,\n BaseResponse,\n NextFunction,\n RouterSession,\n Auth\n >,\n ...middlewareOrMiddlewareWithTypedHandler: MiddlewareOrMiddlewareWithTypedHandler<\n SV,\n Name,\n 'post',\n Path,\n P,\n ResBodyMap,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n ResHeaders,\n LocalsObj,\n VersionedApi,\n BaseRequest,\n BaseResponse,\n NextFunction,\n RouterSession,\n Auth\n >[]\n ) => {\n return this.registerRoute<\n Name,\n 'post',\n Path,\n P,\n ResBodyMap,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n ResHeaders,\n LocalsObj,\n VersionedApi,\n Auth\n >(\n 'post',\n path,\n this.internal.post,\n contractDetailsOrMiddlewareOrTypedHandler,\n ...middlewareOrMiddlewareWithTypedHandler\n );\n };\n\n /**\n * Registers a PUT route with the specified contract details and handler handlers.\n *\n * @template P - The type of request parameters.\n * @template ResBodyMap - The type of response body.\n * @template ReqBody - The type of request body.\n * @template ReqQuery - The type of request query.\n * @template LocalsObj - The type of local variables.\n * @param {string} path - The path for the route.\n * @param {HttpContractDetails<SV, P, ResBodyMap, ReqBody, ReqQuery>} contractDetails - The contract details.\n * @param {...SchemaHandler<SV, P, ResBodyMap, ReqBody, ReqQuery, LocalsObj>[]} handlers - The handler handlers.\n * @returns {ExpressRouter} - The Express router.\n */\n put: LiveTypeRouteDefinition<\n SV,\n BasePath,\n 'put',\n RouterHandler,\n Internal,\n RouterSession,\n BaseRequest,\n BaseResponse,\n NextFunction,\n this\n > = <\n Name extends string,\n Path extends `/${string}`,\n P extends ParamsObject<SV>,\n ResBodyMap extends ResponsesObject<SV>,\n ReqBody extends Body<SV>,\n ReqQuery extends QueryObject<SV>,\n ReqHeaders extends HeadersObject<SV>,\n ResHeaders extends HeadersObject<SV>,\n LocalsObj extends Record<string, unknown>,\n VersionedApi extends VersionSchema<SV, 'put'>,\n Auth extends SchemaAuthMethods<\n SV,\n P,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n VersionedApi,\n BaseRequest\n >\n >(\n path: Path,\n contractDetailsOrMiddlewareOrTypedHandler: ContractDetailsOrMiddlewareOrTypedHandler<\n SV,\n Name,\n 'put',\n Path,\n P,\n ResBodyMap,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n ResHeaders,\n LocalsObj,\n VersionedApi,\n BaseRequest,\n BaseResponse,\n NextFunction,\n RouterSession,\n Auth\n >,\n ...middlewareOrMiddlewareWithTypedHandler: MiddlewareOrMiddlewareWithTypedHandler<\n SV,\n Name,\n 'put',\n Path,\n P,\n ResBodyMap,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n ResHeaders,\n LocalsObj,\n VersionedApi,\n BaseRequest,\n BaseResponse,\n NextFunction,\n RouterSession,\n Auth\n >[]\n ) => {\n return this.registerRoute<\n Name,\n 'put',\n Path,\n P,\n ResBodyMap,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n ResHeaders,\n LocalsObj,\n VersionedApi,\n Auth\n >(\n 'put',\n path,\n this.internal.put,\n contractDetailsOrMiddlewareOrTypedHandler,\n ...middlewareOrMiddlewareWithTypedHandler\n );\n };\n\n /**\n * Registers a PATCH route with the specified contract details and handler handlers.\n *\n * @template P - The type of request parameters.\n * @template ResBodyMap - The type of response body.\n * @template ReqBody - The type of request body.\n * @template ReqQuery - The type of request query.\n * @template LocalsObj - The type of local variables.\n * @param {string} path - The path for the route.\n * @param {HttpContractDetails<SV, P, ResBodyMap, ReqBody, ReqQuery>} contractDetails - The contract details.\n * @param {...SchemaHandler<SV, P, ResBodyMap, ReqBody, ReqQuery, LocalsObj>[]} handlers - The handler handlers.\n * @returns {ExpressRouter} - The Express router.\n */\n patch: LiveTypeRouteDefinition<\n SV,\n BasePath,\n 'patch',\n RouterHandler,\n Internal,\n RouterSession,\n BaseRequest,\n BaseResponse,\n NextFunction,\n this\n > = <\n Name extends string,\n Path extends `/${string}`,\n P extends ParamsObject<SV>,\n ResBodyMap extends ResponsesObject<SV>,\n ReqBody extends Body<SV>,\n ReqQuery extends QueryObject<SV>,\n ReqHeaders extends HeadersObject<SV>,\n ResHeaders extends HeadersObject<SV>,\n LocalsObj extends Record<string, unknown>,\n VersionedApi extends VersionSchema<SV, 'patch'>,\n Auth extends SchemaAuthMethods<\n SV,\n P,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n VersionedApi,\n BaseRequest\n >\n >(\n path: Path,\n contractDetailsOrMiddlewareOrTypedHandler: ContractDetailsOrMiddlewareOrTypedHandler<\n SV,\n Name,\n 'patch',\n Path,\n P,\n ResBodyMap,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n ResHeaders,\n LocalsObj,\n VersionedApi,\n BaseRequest,\n BaseResponse,\n NextFunction,\n RouterSession,\n Auth\n >,\n ...middlewareOrMiddlewareWithTypedHandler: MiddlewareOrMiddlewareWithTypedHandler<\n SV,\n Name,\n 'patch',\n Path,\n P,\n ResBodyMap,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n ResHeaders,\n LocalsObj,\n VersionedApi,\n BaseRequest,\n BaseResponse,\n NextFunction,\n RouterSession,\n Auth\n >[]\n ) => {\n return this.registerRoute<\n Name,\n 'patch',\n Path,\n P,\n ResBodyMap,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n ResHeaders,\n LocalsObj,\n VersionedApi,\n Auth\n >(\n 'patch',\n path,\n this.internal.patch,\n contractDetailsOrMiddlewareOrTypedHandler,\n ...middlewareOrMiddlewareWithTypedHandler\n );\n };\n\n /**\n * Registers a DELETE route with the specified contract details and handler handlers.\n *\n * @template P - The type of request parameters.\n * @template ResBodyMap - The type of response body.\n * @template ReqBody - The type of request body.\n * @template ReqQuery - The type of request query.\n * @template LocalsObj - The type of local variables.\n * @param {string} path - The path for the route.\n * @param {PathParamHttpContractDetails<SV, P, ResBodyMap, ReqQuery>} contractDetails - The contract details.\n * @param {...SchemaHandler<SV, P, ResBodyMap, ReqBody, ReqQuery, LocalsObj>[]} handlers - The handler handlers.\n * @returns {ExpressRouter} - The Express router.\n */\n delete: LiveTypeRouteDefinition<\n SV,\n BasePath,\n 'delete',\n RouterHandler,\n Internal,\n RouterSession,\n BaseRequest,\n BaseResponse,\n NextFunction,\n this\n > = <\n Name extends string,\n Path extends `/${string}`,\n P extends ParamsObject<SV>,\n ResBodyMap extends ResponsesObject<SV>,\n ReqBody extends Body<SV>,\n ReqQuery extends QueryObject<SV>,\n ReqHeaders extends HeadersObject<SV>,\n ResHeaders extends HeadersObject<SV>,\n LocalsObj extends Record<string, unknown>,\n VersionedApi extends VersionSchema<SV, 'delete'>,\n Auth extends SchemaAuthMethods<\n SV,\n P,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n VersionedApi,\n BaseRequest\n >\n >(\n path: Path,\n contractDetailsOrMiddlewareOrTypedHandler: ContractDetailsOrMiddlewareOrTypedHandler<\n SV,\n Name,\n 'delete',\n Path,\n P,\n ResBodyMap,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n ResHeaders,\n LocalsObj,\n VersionedApi,\n BaseRequest,\n BaseResponse,\n NextFunction,\n RouterSession,\n Auth\n >,\n ...middlewareOrMiddlewareWithTypedHandler: MiddlewareOrMiddlewareWithTypedHandler<\n SV,\n Name,\n 'delete',\n Path,\n P,\n ResBodyMap,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n ResHeaders,\n LocalsObj,\n VersionedApi,\n BaseRequest,\n BaseResponse,\n NextFunction,\n RouterSession,\n Auth\n >[]\n ) => {\n return this.registerRoute<\n Name,\n 'delete',\n Path,\n P,\n ResBodyMap,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n ResHeaders,\n LocalsObj,\n VersionedApi,\n Auth\n >(\n 'delete',\n path,\n this.internal.delete,\n contractDetailsOrMiddlewareOrTypedHandler,\n ...middlewareOrMiddlewareWithTypedHandler\n );\n };\n\n /**\n * Registers a OPTIONS route with the specified contract details and handler handlers.\n *\n * @template P - The type of request parameters.\n * @template ResBodyMap - The type of response body.\n * @template ReqBody - The type of request body.\n * @template ReqQuery - The type of request query.\n * @template LocalsObj - The type of local variables.\n * @param {string} path - The path for the route.\n * @param {PathParamHttpContractDetails<SV, P, ResBodyMap, ReqQuery>} contractDetails - The contract details.\n * @param {...SchemaHandler<SV, P, ResBodyMap, ReqBody, ReqQuery, LocalsObj>[]} handlers - The handler handlers.\n * @returns {ExpressRouter} - The Express router.\n */\n options: LiveTypeRouteDefinition<\n SV,\n BasePath,\n 'options',\n RouterHandler,\n Internal,\n RouterSession,\n BaseRequest,\n BaseResponse,\n NextFunction,\n this\n > = <\n Name extends string,\n Path extends `/${string}`,\n P extends ParamsObject<SV>,\n ResBodyMap extends ResponsesObject<SV>,\n ReqBody extends Body<SV>,\n ReqQuery extends QueryObject<SV>,\n ReqHeaders extends HeadersObject<SV>,\n ResHeaders extends HeadersObject<SV>,\n LocalsObj extends Record<string, unknown>,\n VersionedApi extends VersionSchema<SV, 'options'>,\n Auth extends SchemaAuthMethods<\n SV,\n P,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n VersionedApi,\n BaseRequest\n >\n >(\n path: Path,\n contractDetailsOrMiddlewareOrTypedHandler: ContractDetailsOrMiddlewareOrTypedHandler<\n SV,\n Name,\n 'options',\n Path,\n P,\n ResBodyMap,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n ResHeaders,\n LocalsObj,\n VersionedApi,\n BaseRequest,\n BaseResponse,\n NextFunction,\n RouterSession,\n Auth\n >,\n ...middlewareOrMiddlewareWithTypedHandler: MiddlewareOrMiddlewareWithTypedHandler<\n SV,\n Name,\n 'options',\n Path,\n P,\n ResBodyMap,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n ResHeaders,\n LocalsObj,\n VersionedApi,\n BaseRequest,\n BaseResponse,\n NextFunction,\n RouterSession,\n Auth\n >[]\n ) => {\n return this.registerRoute<\n Name,\n 'options',\n Path,\n P,\n ResBodyMap,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n ResHeaders,\n LocalsObj,\n VersionedApi,\n Auth\n >(\n 'options',\n path,\n this.internal.options,\n contractDetailsOrMiddlewareOrTypedHandler,\n ...middlewareOrMiddlewareWithTypedHandler\n );\n };\n\n /**\n * Registers a HEAD route with the specified contract details and handler handlers.\n *\n * @template P - The type of request parameters.\n * @template ResBodyMap - The type of response body.\n * @template ReqBody - The type of request body.\n * @template ReqQuery - The type of request query.\n * @template LocalsObj - The type of local variables.\n * @param {string} path - The path for the route.\n * @param {PathParamHttpContractDetails<SV, P, ResBodyMap, ReqQuery>} contractDetails - The contract details.\n * @param {...SchemaHandler<SV, P, ResBodyMap, ReqBody, ReqQuery, LocalsObj>[]} handlers - The handler handlers.\n * @returns {ExpressRouter} - The Express router.\n */\n head: LiveTypeRouteDefinition<\n SV,\n BasePath,\n 'head',\n RouterHandler,\n Internal,\n RouterSession,\n BaseRequest,\n BaseResponse,\n NextFunction,\n this\n > = <\n Name extends string,\n Path extends `/${string}`,\n P extends ParamsObject<SV>,\n ResBodyMap extends ResponsesObject<SV>,\n ReqBody extends Body<SV>,\n ReqQuery extends QueryObject<SV>,\n ReqHeaders extends HeadersObject<SV>,\n ResHeaders extends HeadersObject<SV>,\n LocalsObj extends Record<string, unknown>,\n VersionedApi extends VersionSchema<SV, 'head'>,\n Auth extends SchemaAuthMethods<\n SV,\n P,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n VersionedApi,\n BaseRequest\n >\n >(\n path: Path,\n contractDetailsOrMiddlewareOrTypedHandler: ContractDetailsOrMiddlewareOrTypedHandler<\n SV,\n Name,\n 'head',\n Path,\n P,\n ResBodyMap,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n ResHeaders,\n LocalsObj,\n VersionedApi,\n BaseRequest,\n BaseResponse,\n NextFunction,\n RouterSession,\n Auth\n >,\n ...middlewareOrMiddlewareWithTypedHandler: MiddlewareOrMiddlewareWithTypedHandler<\n SV,\n Name,\n 'head',\n Path,\n P,\n ResBodyMap,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n ResHeaders,\n LocalsObj,\n VersionedApi,\n BaseRequest,\n BaseResponse,\n NextFunction,\n RouterSession,\n Auth\n >[]\n ) => {\n return this.registerRoute<\n Name,\n 'head',\n Path,\n P,\n ResBodyMap,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n ResHeaders,\n LocalsObj,\n VersionedApi,\n Auth\n >(\n 'head',\n path,\n this.internal.head,\n contractDetailsOrMiddlewareOrTypedHandler,\n ...middlewareOrMiddlewareWithTypedHandler\n );\n };\n\n /**\n * Registers a TRACE route with the specified contract details and handler handlers.\n *\n * @template P - The type of request parameters.\n * @template ResBodyMap - The type of response body.\n * @template ReqBody - The type of request body.\n * @template ReqQuery - The type of request query.\n * @template LocalsObj - The type of local variables.\n * @param {string} path - The path for the route.\n * @param {PathParamHttpContractDetails<SV, P, ResBodyMap, ReqQuery>} contractDetails - The contract details.\n * @param {...SchemaHandler<SV, P, ResBodyMap, ReqBody, ReqQuery, LocalsObj>[]} handlers - The handler handlers.\n * @returns {ExpressRouter} - The Express router.\n */\n trace: LiveTypeRouteDefinition<\n SV,\n BasePath,\n 'trace',\n RouterHandler,\n Internal,\n RouterSession,\n BaseRequest,\n BaseResponse,\n NextFunction,\n this\n > = <\n Name extends string,\n Path extends `/${string}`,\n P extends ParamsObject<SV>,\n ResBodyMap extends ResponsesObject<SV>,\n ReqBody extends Body<SV>,\n ReqQuery extends QueryObject<SV>,\n ReqHeaders extends HeadersObject<SV>,\n ResHeaders extends HeadersObject<SV>,\n LocalsObj extends Record<string, unknown>,\n VersionedApi extends VersionSchema<SV, 'trace'>,\n Auth extends SchemaAuthMethods<\n SV,\n P,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n VersionedApi,\n BaseRequest\n >\n >(\n path: Path,\n contractDetailsOrMiddlewareOrTypedHandler: ContractDetailsOrMiddlewareOrTypedHandler<\n SV,\n Name,\n 'trace',\n Path,\n P,\n ResBodyMap,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n ResHeaders,\n LocalsObj,\n VersionedApi,\n BaseRequest,\n BaseResponse,\n NextFunction,\n RouterSession,\n Auth\n >,\n ...middlewareOrMiddlewareWithTypedHandler: MiddlewareOrMiddlewareWithTypedHandler<\n SV,\n Name,\n 'trace',\n Path,\n P,\n ResBodyMap,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n ResHeaders,\n LocalsObj,\n VersionedApi,\n BaseRequest,\n BaseResponse,\n NextFunction,\n RouterSession,\n Auth\n >[]\n ) => {\n return this.registerRoute<\n Name,\n 'trace',\n Path,\n P,\n ResBodyMap,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n ResHeaders,\n LocalsObj,\n VersionedApi,\n Auth\n >(\n 'trace',\n path,\n this.internal.trace,\n contractDetailsOrMiddlewareOrTypedHandler,\n ...middlewareOrMiddlewareWithTypedHandler\n );\n };\n\n insertIntoRouterSdkPaths({\n sdkPath,\n path,\n method,\n name\n }: {\n sdkPath: string;\n name: string;\n path: string;\n method: string;\n }) {\n const routePath = [method, path].join('.');\n for (const route of this.routes) {\n if (\n route.path === path &&\n route.method === method &&\n route.contractDetails.name === name\n ) {\n this.sdkPaths[routePath] = sdkPath;\n }\n }\n\n for (const router of this.routers) {\n router.insertIntoRouterSdkPaths?.({\n sdkPath,\n path,\n method,\n name\n });\n }\n }\n\n private unpackSdks(\n sdks: SdkHandlerObject<SV>,\n path: string[],\n routerUniquenessCache: Set<number>\n ) {\n Object.entries(sdks).forEach(([key, maybeHandler]) => {\n if (isSdkHandler(maybeHandler)) {\n const cacheKey = hashString(safeStringify(maybeHandler));\n if (routerUniquenessCache.has(cacheKey)) {\n throw new Error(`SDK handler ${key} is already registered`);\n }\n routerUniquenessCache.add(cacheKey);\n if (!maybeHandler._method || !maybeHandler._path) {\n throw new Error(`SDK handler ${key} is missing method or path`);\n }\n this.insertIntoRouterSdkPaths({\n sdkPath: [...path, key].join('.'),\n path: maybeHandler._path,\n method: maybeHandler._method,\n name: maybeHandler.contractDetails.name\n });\n routerUniquenessCache.add(cacheKey);\n } else {\n this.unpackSdks(maybeHandler, [...path, key], routerUniquenessCache);\n }\n });\n }\n\n registerSdks(sdks: SdkHandlerObject<SV>) {\n this.unpackSdks(sdks, [], new Set());\n }\n\n protected cloneInternals(clone: this): void {\n clone.routers = [...this.routers];\n clone.routes = [...this.routes];\n clone._fetchMap = { ...this._fetchMap };\n clone.sdk = { ...this.sdk };\n clone.sdkPaths = { ...this.sdkPaths };\n }\n\n clone(): this {\n const clone = new ForklaunchExpressLikeRouter<\n SV,\n BasePath,\n RouterHandler,\n Internal,\n BaseRequest,\n BaseResponse,\n NextFunction,\n RouterSession,\n FetchMap,\n Sdk\n >(\n this.basePath,\n this.schemaValidator,\n this.internal,\n this.postEnrichMiddleware,\n this.openTelemetryCollector,\n this.routerOptions\n ) as this;\n\n this.cloneInternals(clone);\n\n return clone;\n }\n}\n","export function hasPermissionChecks(maybePermissionedAuth: unknown) {\n if (\n typeof maybePermissionedAuth !== 'object' ||\n maybePermissionedAuth === null\n ) {\n return false;\n }\n\n const hasAllowedPermissions =\n 'allowedPermissions' in maybePermissionedAuth &&\n maybePermissionedAuth.allowedPermissions instanceof Set &&\n maybePermissionedAuth.allowedPermissions.size > 0;\n\n const hasForbiddenPermissions =\n 'forbiddenPermissions' in maybePermissionedAuth &&\n maybePermissionedAuth.forbiddenPermissions instanceof Set &&\n maybePermissionedAuth.forbiddenPermissions.size > 0;\n\n return hasAllowedPermissions || hasForbiddenPermissions;\n}\n","export function hasRoleChecks(maybeRoledAuth: unknown): boolean {\n if (typeof maybeRoledAuth !== 'object' || maybeRoledAuth === null) {\n return false;\n }\n\n const hasAllowedRoles =\n 'allowedRoles' in maybeRoledAuth &&\n maybeRoledAuth.allowedRoles instanceof Set &&\n maybeRoledAuth.allowedRoles.size > 0;\n\n const hasForbiddenRoles =\n 'forbiddenRoles' in maybeRoledAuth &&\n maybeRoledAuth.forbiddenRoles instanceof Set &&\n maybeRoledAuth.forbiddenRoles.size > 0;\n\n return hasAllowedRoles || hasForbiddenRoles;\n}\n","export function hasScopeChecks(maybePermissionedAuth: unknown) {\n return (\n typeof maybePermissionedAuth === 'object' &&\n maybePermissionedAuth !== null &&\n 'requiredScope' in maybePermissionedAuth &&\n maybePermissionedAuth.requiredScope != null\n );\n}\n","import { AnySchemaValidator } from '@forklaunch/validator';\nimport { ForklaunchRouter } from '../types/router.types';\n\n/**\n * Type guard that checks if an object is a Forklaunch router.\n * A Forklaunch router is an object that has a base path and an array of routes.\n *\n * @template SV - A type that extends AnySchemaValidator\n * @param {unknown} maybeForklaunchRouter - The object to check\n * @returns {boolean} A type predicate indicating whether the object is a ForklaunchRouter\n *\n * @example\n * ```ts\n * if (isForklaunchRouter(router)) {\n * // router is now typed as ForklaunchRouter\n * router.basePath; // '/api'\n * router.routes; // Route[]\n * }\n * ```\n */\nexport function isForklaunchRouter<SV extends AnySchemaValidator>(\n maybeForklaunchRouter: unknown\n): maybeForklaunchRouter is ForklaunchRouter<SV> {\n return (\n maybeForklaunchRouter != null &&\n typeof maybeForklaunchRouter === 'object' &&\n 'basePath' in maybeForklaunchRouter &&\n 'routes' in maybeForklaunchRouter &&\n Array.isArray(maybeForklaunchRouter.routes)\n );\n}\n","import { AnySchemaValidator } from '@forklaunch/validator';\nimport { ConstrainedForklaunchRouter } from '../types/router.types';\nimport { isForklaunchRouter } from './isForklaunchRouter';\n\n/**\n * Type guard that checks if an object is a constrained Forklaunch router.\n * A constrained router is one that has both the basic router properties and a request handler.\n *\n * @template SV - A type that extends AnySchemaValidator\n * @template RouterHandler - The type of the router handler\n * @param maybeForklaunchExpressLikeRouter - The object to check\n * @returns A type predicate indicating whether the object is a ConstrainedForklaunchRouter\n *\n * @example\n * ```ts\n * if (isConstrainedForklaunchRouter(router)) {\n * // router is now typed as ConstrainedForklaunchRouter\n * router.requestHandler(...);\n * }\n * ```\n */\nexport function isConstrainedForklaunchRouter<\n SV extends AnySchemaValidator,\n RouterHandler\n>(\n maybeForklaunchExpressLikeRouter: unknown\n): maybeForklaunchExpressLikeRouter is ConstrainedForklaunchRouter<\n SV,\n RouterHandler\n> {\n return (\n isForklaunchRouter<SV>(maybeForklaunchExpressLikeRouter) &&\n 'requestHandler' in maybeForklaunchExpressLikeRouter\n );\n}\n","import { extractArgumentNames } from '@forklaunch/common';\nimport { AnySchemaValidator } from '@forklaunch/validator';\nimport { ExpressLikeSchemaHandler } from '../types/apiDefinition.types';\nimport {\n Body,\n HeadersObject,\n Method,\n ParamsObject,\n QueryObject,\n ResponsesObject,\n SessionObject,\n VersionSchema\n} from '../types/contractDetails.types';\n\n/**\n * Type guard that checks if an object is an Express-like schema handler.\n * A schema handler is a function that takes up to 3 arguments (request, response, next)\n * and is used for middleware or route handlers in an Express-like application.\n *\n * @template SV - A type that extends AnySchemaValidator\n * @template P - The type of route parameters\n * @template ResBodyMap - The type of response body mapping\n * @template ReqBody - The type of request body\n * @template ReqQuery - The type of request query parameters\n * @template ReqHeaders - The type of request headers\n * @template ResHeaders - The type of response headers\n * @template LocalsObj - The type of locals object\n * @template BaseRequest - The base request type\n * @template BaseResponse - The base response type\n * @template NextFunction - The type of next function\n * @param {unknown} middleware - The object to check\n * @returns {boolean} A type predicate indicating whether the object is an ExpressLikeSchemaHandler\n *\n * @example\n * ```ts\n * if (isExpressLikeSchemaHandler(middleware)) {\n * // middleware is now typed as ExpressLikeSchemaHandler\n * middleware(req, res, next);\n * }\n * ```\n */\nexport function isExpressLikeSchemaHandler<\n SV extends AnySchemaValidator,\n ContractMethod extends Method,\n P extends ParamsObject<SV>,\n ResBodyMap extends ResponsesObject<SV>,\n ReqBody extends Body<SV>,\n ReqQuery extends QueryObject<SV>,\n ReqHeaders extends HeadersObject<SV>,\n ResHeaders extends HeadersObject<SV>,\n LocalsObj extends Record<string, unknown>,\n VersionedApi extends VersionSchema<SV, ContractMethod>,\n Session extends SessionObject<SV>,\n BaseRequest,\n BaseResponse,\n NextFunction\n>(\n middleware: unknown\n): middleware is ExpressLikeSchemaHandler<\n SV,\n P,\n ResBodyMap,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n ResHeaders,\n LocalsObj,\n VersionedApi,\n Session,\n BaseRequest,\n BaseResponse,\n NextFunction\n> {\n const extractedArgumentNames =\n typeof middleware === 'function' &&\n new Set(\n extractArgumentNames(middleware).map((argumentName) =>\n argumentName.toLowerCase()\n )\n );\n return extractedArgumentNames && extractedArgumentNames.size <= 4;\n}\n","import { AnySchemaValidator } from '@forklaunch/validator';\nimport { ExpressLikeRouter } from '../interfaces/expressLikeRouter.interface';\nimport { ForklaunchExpressLikeRouter } from '../router/expressLikeRouter';\nimport { isConstrainedForklaunchRouter } from './isConstrainedForklaunchRouter';\n\n/**\n * Type guard that checks if an object is a Forklaunch Express-like router.\n * A Forklaunch Express-like router is a constrained router that has both a base path and an internal router.\n *\n * @template SV - A type that extends AnySchemaValidator\n * @template Path - A type that extends `/${string}` representing the base path\n * @template RouterHandler - The type of the router handler\n * @template Internal - The type of the internal router that extends ExpressLikeRouter\n * @template BaseRequest - The base request type\n * @template BaseResponse - The base response type\n * @template NextFunction - The type of next function\n * @param {unknown} maybeForklaunchExpressLikeRouter - The object to check\n * @returns {boolean} A type predicate indicating whether the object is a ForklaunchExpressLikeRouter\n *\n * @example\n * ```ts\n * if (isForklaunchExpressLikeRouter(router)) {\n * // router is now typed as ForklaunchExpressLikeRouter\n * router.basePath; // '/api'\n * router.internal; // ExpressLikeRouter\n * }\n * ```\n */\nexport function isForklaunchExpressLikeRouter<\n SV extends AnySchemaValidator,\n Path extends `/${string}`,\n RouterHandler,\n Internal extends ExpressLikeRouter<RouterHandler, Internal>,\n BaseRequest,\n BaseResponse,\n NextFunction,\n FetchMap extends Record<string, unknown>,\n Sdk extends Record<string, unknown>\n>(\n maybeForklaunchExpressLikeRouter: unknown\n): maybeForklaunchExpressLikeRouter is ForklaunchExpressLikeRouter<\n SV,\n Path,\n RouterHandler,\n Internal,\n BaseRequest,\n BaseResponse,\n NextFunction,\n FetchMap,\n Sdk\n> {\n return (\n isConstrainedForklaunchRouter<SV, RouterHandler>(\n maybeForklaunchExpressLikeRouter\n ) &&\n 'basePath' in maybeForklaunchExpressLikeRouter &&\n 'internal' in maybeForklaunchExpressLikeRouter\n );\n}\n","import { SdkHandler } from '../types/sdk.types';\n\n/**\n * Type guard to determine if a given value is an SdkHandler.\n *\n * @param handler - The value to check.\n * @returns True if the value is an SdkHandler, false otherwise.\n */\nexport function isSdkHandler(handler: unknown): handler is SdkHandler {\n return (\n typeof handler === 'object' &&\n handler !== null &&\n '_path' in handler &&\n '_method' in handler &&\n 'contractDetails' in handler\n );\n}\n","import { AnySchemaValidator } from '@forklaunch/validator';\n\nimport {\n Body,\n HeadersObject,\n Method,\n ParamsObject,\n QueryObject,\n ResponsesObject,\n SchemaAuthMethods,\n VersionSchema\n} from '../types/contractDetails.types';\nimport { TypedHandler } from '../types/typedHandler.types';\n\nexport function isTypedHandler<\n SV extends AnySchemaValidator,\n Name extends string,\n ContractMethod extends Method,\n Path extends `/${string}`,\n P extends ParamsObject<SV>,\n ResBodyMap extends ResponsesObject<SV>,\n ReqBody extends Body<SV>,\n ReqQuery extends QueryObject<SV>,\n ReqHeaders extends HeadersObject<SV>,\n ResHeaders extends HeadersObject<SV>,\n LocalsObj extends Record<string, unknown>,\n VersionedApi extends VersionSchema<SV, ContractMethod>,\n BaseRequest,\n BaseResponse,\n NextFunction,\n const Auth extends SchemaAuthMethods<\n SV,\n P,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n VersionedApi,\n BaseRequest\n >\n>(\n maybeTypedHandler: unknown\n): maybeTypedHandler is TypedHandler<\n SV,\n Name,\n ContractMethod,\n Path,\n P,\n ResBodyMap,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n ResHeaders,\n LocalsObj,\n VersionedApi,\n BaseRequest,\n BaseResponse,\n NextFunction,\n Auth\n> {\n return (\n maybeTypedHandler != null &&\n typeof maybeTypedHandler === 'object' &&\n '_typedHandler' in maybeTypedHandler &&\n maybeTypedHandler._typedHandler === true\n );\n}\n","import { getEnvVar } from '@forklaunch/common';\nimport { AnySchemaValidator } from '@forklaunch/validator';\nimport { context, trace } from '@opentelemetry/api';\nimport { ATTR_SERVICE_NAME as OTEL_ATTR_SERVICE_NAME } from '@opentelemetry/semantic-conventions';\nimport { v4 } from 'uuid';\nimport {\n ATTR_CORRELATION_ID,\n ATTR_SERVICE_NAME\n} from '../../telemetry/constants';\nimport { httpRequestsInFlightCounter } from '../../telemetry/openTelemetryCollector';\nimport {\n ExpressLikeSchemaHandler,\n ForklaunchNextFunction,\n ResolvedForklaunchResponse,\n VersionedResponses\n} from '../../types/apiDefinition.types';\nimport {\n Body,\n HeadersObject,\n ParamsObject,\n QueryObject,\n ResponsesObject,\n SessionObject,\n VersionSchema\n} from '../../types/contractDetails.types';\n\n/**\n * Middleware to create and add a request context.\n *\n * @template SV - A type that extends AnySchemaValidator.\n * @template Request - A type that extends ForklaunchRequest.\n * @template Response - A type that extends ForklaunchResponse.\n * @template NextFunction - A type that extends ForklaunchNextFunction.\n * @param {SV} schemaValidator - The schema validator.\n * @returns {Function} - Middleware function to create request context.\n */\nexport function createContext<\n SV extends AnySchemaValidator,\n P extends ParamsObject<SV>,\n ResBodyMap extends ResponsesObject<SV>,\n ReqBody extends Body<SV>,\n ReqQuery extends QueryObject<SV>,\n ReqHeaders extends HeadersObject<SV>,\n ResHeaders extends HeadersObject<SV>,\n LocalsObj extends Record<string, unknown>,\n VersionedApi extends VersionSchema<SV, 'middleware'>,\n SessionSchema extends SessionObject<SV>\n>(\n schemaValidator: SV\n): ExpressLikeSchemaHandler<\n SV,\n P,\n ResBodyMap,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n ResHeaders,\n LocalsObj,\n VersionedApi,\n SessionSchema,\n unknown,\n unknown,\n ForklaunchNextFunction\n> {\n return function setContext(req, res, next?) {\n req.schemaValidator = schemaValidator;\n\n let correlationId = v4();\n if (req.headers['x-correlation-id']) {\n correlationId = req.headers['x-correlation-id'] as string;\n }\n\n (\n res as ResolvedForklaunchResponse<\n ResHeaders,\n Record<string, string>,\n LocalsObj,\n VersionedResponses,\n unknown\n >\n ).setHeader('x-correlation-id', correlationId);\n\n req.context = {\n correlationId: correlationId,\n requestStartTime: Date.now()\n };\n\n const serviceName = getEnvVar('OTEL_SERVICE_NAME') || 'unknown';\n const inFlightAttrs = {\n [OTEL_ATTR_SERVICE_NAME]: serviceName\n };\n let inFlightActive = true;\n\n const decrementInFlight = () => {\n if (!inFlightActive) {\n return;\n }\n\n httpRequestsInFlightCounter.add(-1, inFlightAttrs);\n inFlightActive = false;\n };\n\n httpRequestsInFlightCounter.add(1, inFlightAttrs);\n res.on('finish', decrementInFlight);\n res.on('close', decrementInFlight);\n res.on('error', decrementInFlight);\n\n const span = trace.getSpan(context.active());\n\n if (span != null) {\n req.context.span = span;\n req.context.span?.setAttribute(ATTR_CORRELATION_ID, correlationId);\n req.context.span?.setAttribute(ATTR_SERVICE_NAME, serviceName);\n }\n\n next?.();\n };\n}\n","import {\n ATTR_HTTP_REQUEST_METHOD,\n ATTR_HTTP_RESPONSE_STATUS_CODE,\n ATTR_HTTP_ROUTE,\n ATTR_SERVICE_NAME\n} from '@opentelemetry/semantic-conventions';\n\nexport const ATTR_API_NAME = 'api.name';\nexport const ATTR_CORRELATION_ID = 'correlation.id';\nexport const ATTR_APPLICATION_ID = 'application_id';\n\nexport {\n ATTR_HTTP_REQUEST_METHOD,\n ATTR_HTTP_RESPONSE_STATUS_CODE,\n ATTR_HTTP_ROUTE,\n ATTR_SERVICE_NAME\n};\n","import { getEnvVar } from '@forklaunch/common';\nimport { HyperExpressInstrumentation } from '@forklaunch/opentelemetry-instrumentation-hyper-express';\nimport {\n Counter,\n Gauge,\n Histogram,\n metrics,\n ObservableCounter,\n ObservableGauge,\n ObservableUpDownCounter,\n UpDownCounter\n} from '@opentelemetry/api';\nimport { OTLPLogExporter } from '@opentelemetry/exporter-logs-otlp-http';\nimport { OTLPMetricExporter } from '@opentelemetry/exporter-metrics-otlp-http';\nimport { OTLPTraceExporter } from '@opentelemetry/exporter-trace-otlp-http';\nimport { ExpressInstrumentation } from '@opentelemetry/instrumentation-express';\nimport { HttpInstrumentation } from '@opentelemetry/instrumentation-http';\nimport { resourceFromAttributes } from '@opentelemetry/resources';\nimport { BatchLogRecordProcessor } from '@opentelemetry/sdk-logs';\nimport { PeriodicExportingMetricReader } from '@opentelemetry/sdk-metrics';\nimport { NodeSDK } from '@opentelemetry/sdk-node';\nimport {\n ATTR_HTTP_REQUEST_METHOD,\n ATTR_HTTP_RESPONSE_STATUS_CODE,\n ATTR_HTTP_ROUTE,\n ATTR_SERVICE_NAME\n} from '@opentelemetry/semantic-conventions';\nimport dotenv from 'dotenv';\nimport { LevelWithSilent, LevelWithSilentOrString } from 'pino';\nimport { isForklaunchRequest } from '../guards/isForklaunchRequest';\nimport {\n LogFn,\n LoggerMeta,\n MetricsDefinition,\n MetricType\n} from '../types/openTelemetryCollector.types';\nimport {\n ATTR_API_NAME,\n ATTR_APPLICATION_ID,\n ATTR_CORRELATION_ID\n} from './constants';\nimport { logger, PinoLogger } from './pinoLogger';\n\nexport class OpenTelemetryCollector<\n AppliedMetricsDefinition extends MetricsDefinition\n> {\n _logger: PinoLogger;\n _serviceName: string;\n _metrics: Record<\n keyof AppliedMetricsDefinition,\n | Counter\n | Gauge\n | Histogram\n | UpDownCounter\n | ObservableCounter\n | ObservableGauge\n | ObservableUpDownCounter\n >;\n\n // scoped creation and create this in middleware when api execute. Also add correlation id\n constructor(\n serviceName: string,\n level?: LevelWithSilentOrString,\n metricDefinitions?: AppliedMetricsDefinition\n ) {\n this._serviceName = serviceName;\n this._logger = logger(level || 'info');\n\n this._metrics = {} as Record<\n keyof AppliedMetricsDefinition,\n MetricType<AppliedMetricsDefinition[keyof AppliedMetricsDefinition]>\n >;\n\n for (const [metricId, metricType] of Object.entries(\n metricDefinitions ?? {}\n )) {\n switch (metricType) {\n case 'counter':\n this._metrics[metricId as keyof AppliedMetricsDefinition] = metrics\n .getMeter(this._serviceName)\n .createCounter(metricId);\n break;\n case 'gauge':\n this._metrics[metricId as keyof AppliedMetricsDefinition] = metrics\n .getMeter(this._serviceName)\n .createGauge(metricId);\n break;\n case 'histogram':\n this._metrics[metricId as keyof AppliedMetricsDefinition] = metrics\n .getMeter(this._serviceName)\n .createHistogram(metricId);\n break;\n case 'upDownCounter':\n this._metrics[metricId as keyof AppliedMetricsDefinition] = metrics\n .getMeter(this._serviceName)\n .createUpDownCounter(metricId);\n break;\n case 'observableCounter':\n this._metrics[metricId as keyof AppliedMetricsDefinition] = metrics\n .getMeter(this._serviceName)\n .createObservableCounter(metricId);\n break;\n case 'observableGauge':\n this._metrics[metricId as keyof AppliedMetricsDefinition] = metrics\n .getMeter(this._serviceName)\n .createObservableGauge(metricId);\n break;\n case 'observableUpDownCounter':\n this._metrics[metricId as keyof AppliedMetricsDefinition] = metrics\n .getMeter(this._serviceName)\n .createObservableUpDownCounter(metricId);\n break;\n }\n }\n\n this.log(\n 'info',\n 'OpenTelemetry Collector (Traces + Logs + Metrics) started'\n );\n }\n\n log(level: LevelWithSilent, ...args: (string | unknown | LoggerMeta)[]) {\n this._logger.log(level, ...args);\n }\n\n info: LogFn = (\n msg: string | unknown | LoggerMeta,\n ...args: (string | unknown | LoggerMeta)[]\n ) => {\n this._logger.log('info', msg, ...args);\n };\n\n error: LogFn = (\n msg: string | unknown | LoggerMeta,\n ...args: (string | unknown | LoggerMeta)[]\n ) => {\n this._logger.log('error', msg, ...args);\n };\n\n warn: LogFn = (\n msg: string | unknown | LoggerMeta,\n ...args: (string | unknown | LoggerMeta)[]\n ) => {\n this._logger.log('warn', msg, ...args);\n };\n\n debug: LogFn = (\n msg: string | unknown | LoggerMeta,\n ...args: (string | unknown | LoggerMeta)[]\n ) => {\n this._logger.log('debug', msg, ...args);\n };\n\n trace: LogFn = (\n msg: string | unknown | LoggerMeta,\n ...args: (string | unknown | LoggerMeta)[]\n ) => {\n this._logger.log('trace', msg, ...args);\n };\n\n getMetric<T extends keyof AppliedMetricsDefinition>(\n metricId: T\n ): MetricType<AppliedMetricsDefinition[T]> {\n return this._metrics[metricId] as MetricType<AppliedMetricsDefinition[T]>;\n }\n}\n\ndotenv.config({ path: getEnvVar('DOTENV_FILE_PATH') });\n\n// Parse OTEL_EXPORTER_OTLP_HEADERS into headers object\n// Format: key1=value1,key2=value2\nfunction parseOtelHeaders(): Record<string, string> | undefined {\n const headersEnv = getEnvVar('OTEL_EXPORTER_OTLP_HEADERS');\n if (!headersEnv) return undefined;\n\n const headers: Record<string, string> = {};\n for (const pair of headersEnv.split(',')) {\n const [key, ...valueParts] = pair.split('=');\n if (key && valueParts.length > 0) {\n headers[key.trim()] = valueParts.join('=').trim();\n }\n }\n return Object.keys(headers).length > 0 ? headers : undefined;\n}\n\nconst otelHeaders = parseOtelHeaders();\n\nnew NodeSDK({\n resource: resourceFromAttributes({\n [ATTR_SERVICE_NAME]: getEnvVar('OTEL_SERVICE_NAME')\n }),\n traceExporter: new OTLPTraceExporter({\n url: `${\n getEnvVar('OTEL_EXPORTER_OTLP_ENDPOINT') ?? 'http://localhost:4318'\n }/v1/traces`,\n headers: otelHeaders\n }),\n metricReader: new PeriodicExportingMetricReader({\n exporter: new OTLPMetricExporter({\n url: `${\n getEnvVar('OTEL_EXPORTER_OTLP_ENDPOINT') ?? 'http://localhost:4318'\n }/v1/metrics`,\n headers: otelHeaders\n }),\n exportIntervalMillis: 5000\n }),\n logRecordProcessors: [\n new BatchLogRecordProcessor({\n exporter: new OTLPLogExporter({\n url: `${\n getEnvVar('OTEL_EXPORTER_OTLP_ENDPOINT') ?? 'http://localhost:4318'\n }/v1/logs`,\n headers: otelHeaders\n })\n })\n ],\n instrumentations: [\n new HttpInstrumentation({\n applyCustomAttributesOnSpan: (span, request) => {\n span.setAttribute(\n ATTR_SERVICE_NAME,\n getEnvVar('OTEL_SERVICE_NAME') ?? 'unknown'\n );\n if (isForklaunchRequest(request)) {\n span.setAttribute(ATTR_API_NAME, request.contractDetails?.name);\n span.setAttribute(ATTR_CORRELATION_ID, request.context.correlationId);\n }\n }\n }),\n new ExpressInstrumentation(),\n new HyperExpressInstrumentation()\n ]\n}).start();\n\n// begin static metrics -- these have to be in here in order to instantiate these after the SDK is instantiated\nexport const httpRequestsTotalCounter = metrics\n .getMeter(getEnvVar('OTEL_SERVICE_NAME') || 'unknown')\n .createCounter<{\n [ATTR_SERVICE_NAME]: string;\n [ATTR_APPLICATION_ID]?: string;\n [ATTR_API_NAME]: string;\n [ATTR_HTTP_REQUEST_METHOD]: string;\n [ATTR_HTTP_ROUTE]: string;\n [ATTR_HTTP_RESPONSE_STATUS_CODE]: number;\n }>('http_requests_total', {\n description: 'Number of HTTP requests'\n });\n\nexport const httpServerDurationHistogram = metrics\n .getMeter(getEnvVar('OTEL_SERVICE_NAME') || 'unknown')\n .createHistogram<{\n [ATTR_SERVICE_NAME]: string;\n [ATTR_APPLICATION_ID]?: string;\n [ATTR_API_NAME]: string;\n [ATTR_HTTP_REQUEST_METHOD]: string;\n [ATTR_HTTP_ROUTE]: string;\n [ATTR_HTTP_RESPONSE_STATUS_CODE]: number;\n }>('http_server_duration', {\n description: 'Duration of HTTP server requests',\n unit: 's'\n });\n\nexport const httpRequestDurationMsHistogram = metrics\n .getMeter(getEnvVar('OTEL_SERVICE_NAME') || 'unknown')\n .createHistogram<{\n [ATTR_SERVICE_NAME]: string;\n [ATTR_APPLICATION_ID]?: string;\n [ATTR_API_NAME]: string;\n [ATTR_HTTP_REQUEST_METHOD]: string;\n [ATTR_HTTP_ROUTE]: string;\n [ATTR_HTTP_RESPONSE_STATUS_CODE]: number;\n }>('http_request_duration_ms', {\n description: 'Duration of HTTP requests in milliseconds'\n });\n\nexport const httpErrorsTotalCounter = metrics\n .getMeter(getEnvVar('OTEL_SERVICE_NAME') || 'unknown')\n .createCounter<{\n [ATTR_SERVICE_NAME]: string;\n [ATTR_APPLICATION_ID]?: string;\n [ATTR_API_NAME]: string;\n [ATTR_HTTP_REQUEST_METHOD]: string;\n [ATTR_HTTP_ROUTE]: string;\n [ATTR_HTTP_RESPONSE_STATUS_CODE]: number;\n }>('http_errors_total', {\n description: 'Total number of HTTP errors (4xx/5xx)'\n });\n\nexport const httpRequestsInFlightCounter = metrics\n .getMeter(getEnvVar('OTEL_SERVICE_NAME') || 'unknown')\n .createUpDownCounter<{\n [ATTR_SERVICE_NAME]: string;\n }>('http_requests_in_flight', {\n description: 'Number of HTTP requests currently in flight'\n });\n","import { AnySchemaValidator } from '@forklaunch/validator';\nimport { ParsedQs } from 'qs';\nimport {\n ForklaunchRequest,\n VersionedRequests\n} from '../types/apiDefinition.types';\nimport { ParamsDictionary } from '../types/contractDetails.types';\n\n/**\n * Type guard that checks if an object is a Forklaunch request.\n * A Forklaunch request is an object that contains contract details and follows the Forklaunch request structure.\n *\n * @template SV - A type that extends AnySchemaValidator\n * @template P - The type of route parameters that extends ParamsDictionary\n * @template ReqBody - The type of request body that extends Record<string, unknown>\n * @template ReqQuery - The type of request query parameters that extends ParsedQs\n * @template ReqHeaders - The type of request headers that extends Record<string, unknown>\n * @param {unknown} request - The object to check\n * @returns {boolean} A type predicate indicating whether the object is a ForklaunchRequest\n *\n * @example\n * ```ts\n * if (isForklaunchRequest(request)) {\n * // request is now typed as ForklaunchRequest\n * const { contractDetails } = request;\n * }\n * ```\n */\nexport function isForklaunchRequest<\n SV extends AnySchemaValidator,\n P extends ParamsDictionary,\n ReqBody extends Record<string, unknown>,\n ReqQuery extends ParsedQs,\n ReqHeaders extends Record<string, string>,\n VersionedReqs extends VersionedRequests,\n SessionSchema extends Record<string, unknown>\n>(\n request: unknown\n): request is ForklaunchRequest<\n SV,\n P,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n Extract<keyof VersionedReqs, string>,\n SessionSchema\n> {\n return (\n request != null &&\n typeof request === 'object' &&\n 'contractDetails' in request\n );\n}\n","import { isNever } from '@forklaunch/common';\nimport { trace } from '@opentelemetry/api';\nimport { AnyValueMap, logs } from '@opentelemetry/api-logs';\nimport pino, { LevelWithSilent, LevelWithSilentOrString, Logger } from 'pino';\nimport { isLoggerMeta } from '../guards/isLoggerMeta';\nimport { LogFn, LoggerMeta } from '../types/openTelemetryCollector.types';\n\nexport type { LevelWithSilent, LevelWithSilentOrString, Logger };\n\nexport function meta(meta: Record<string, unknown>) {\n return meta as LoggerMeta;\n}\n\nfunction mapSeverity(level: LevelWithSilent) {\n switch (level) {\n case 'silent':\n return 0;\n case 'trace':\n return 1;\n case 'debug':\n return 5;\n case 'info':\n return 9;\n case 'warn':\n return 13;\n case 'error':\n return 17;\n case 'fatal':\n return 21;\n default:\n isNever(level);\n return 0;\n }\n}\n\ntype LoggableArg = string | number | boolean | object | null | undefined;\n\n/**\n * Normalize a list of arguments into a single metadata object and message string.\n * @param args - List of log arguments like console.log('msg', { a }, { b }, 123)\n * @returns [metadataObject, messageString]\n */\nfunction normalizeLogArgs(\n args: LoggableArg[]\n): [Record<string, unknown>, string] {\n let message = '';\n const metaObjects: Record<string, unknown>[] = [];\n\n for (const arg of args) {\n if (typeof arg === 'string' && message === '') {\n message = arg;\n } else if (arg instanceof Error) {\n metaObjects.push({\n err: {\n message: arg.message,\n name: arg.name,\n stack: arg.stack,\n ...(Object.keys(arg).length > 0 ? arg : {})\n }\n });\n } else if (arg && typeof arg === 'object' && !Array.isArray(arg)) {\n metaObjects.push(arg as Record<string, unknown>);\n } else {\n message += ` ${String(arg)}`;\n }\n }\n\n const metadata = Object.assign({}, ...metaObjects);\n return [metadata, message.trim()];\n}\n\n/**\n * Safely formats arguments for pretty printing with error handling\n * @param level - Log level\n * @param args - Arguments to format\n * @param timestamp - Optional timestamp\n * @returns Formatted string or fallback message\n */\nfunction safePrettyFormat(\n level: LevelWithSilent,\n args: LoggableArg[],\n timestamp?: string\n): string {\n try {\n const [metadata, message] = normalizeLogArgs(args);\n\n // Return formatted message with level and timestamp\n const formattedTimestamp = timestamp || new Date().toISOString();\n return `[${formattedTimestamp}] ${level.toUpperCase()}: ${message}${\n Object.keys(metadata).length > 0\n ? `\\n${JSON.stringify(metadata, null, 2)}`\n : ''\n }`;\n } catch (error) {\n // Ultimate fallback for any serialization errors\n const fallbackMessage = args\n .map((arg) => {\n try {\n if (typeof arg === 'string') return arg;\n if (arg === null) return 'null';\n if (arg === undefined) return 'undefined';\n return JSON.stringify(arg);\n } catch {\n return '[Circular/Non-serializable Object]';\n }\n })\n .join(' ');\n\n return `[${new Date().toISOString()}] ${level.toUpperCase()}: ${fallbackMessage} [Pretty Print Error: ${error instanceof Error ? error.message : 'Unknown error'}]`;\n }\n}\n\nexport class PinoLogger {\n _pinoLogger: Logger;\n _meta: AnyValueMap;\n\n constructor(level: LevelWithSilentOrString, meta: AnyValueMap = {}) {\n this._pinoLogger = pino({\n level: level || 'info',\n formatters: {\n level(label) {\n return { level: label };\n }\n },\n timestamp: pino.stdTimeFunctions.isoTime,\n transport: {\n target: 'pino-pretty',\n options: {\n colorize: true,\n errorLikeObjectKeys: ['err', 'error'],\n ignore: 'pid,hostname',\n translateTime: 'SYS:standard'\n }\n }\n });\n this._meta = meta;\n }\n\n log(level: LevelWithSilent, ...args: (string | unknown | LoggerMeta)[]) {\n let meta: AnyValueMap = {};\n\n const filteredArgs = args.filter((arg) => {\n if (isLoggerMeta(arg)) {\n Object.assign(meta, arg);\n return false;\n }\n return true;\n }) as LoggableArg[];\n\n const [errorMetadata] = normalizeLogArgs(filteredArgs);\n Object.assign(meta, errorMetadata);\n\n const activeSpan = trace.getActiveSpan();\n if (activeSpan) {\n const activeSpanContext = activeSpan.spanContext();\n meta.trace_id = activeSpanContext.traceId;\n meta.span_id = activeSpanContext.spanId;\n meta.trace_flags = activeSpanContext.traceFlags;\n meta = {\n // @ts-expect-error accessing private property\n ...activeSpan.attributes,\n ...meta\n };\n }\n\n meta = {\n 'api.name': 'none',\n 'correlation.id': 'none',\n ...meta\n };\n\n this._pinoLogger[level](...normalizeLogArgs(filteredArgs));\n\n const formattedBody = safePrettyFormat(level, filteredArgs);\n\n try {\n logs.getLogger(process.env.OTEL_SERVICE_NAME ?? 'unknown').emit({\n severityText: level,\n severityNumber: mapSeverity(level),\n body: formattedBody,\n attributes: { ...this._meta, ...meta }\n });\n } catch (error) {\n console.error('Failed to emit OpenTelemetry log:', error);\n console.log(\n `[${new Date().toISOString()}] ${level.toUpperCase()}:`,\n ...filteredArgs\n );\n }\n }\n\n error: LogFn = (\n msg: string | unknown | LoggerMeta,\n ...args: (string | unknown | LoggerMeta)[]\n ) => this.log('error', msg, ...args);\n\n info: LogFn = (\n msg: string | unknown | LoggerMeta,\n ...args: (string | unknown | LoggerMeta)[]\n ) => this.log('info', msg, ...args);\n\n debug: LogFn = (\n msg: string | unknown | LoggerMeta,\n ...args: (string | unknown | LoggerMeta)[]\n ) => this.log('debug', msg, ...args);\n warn: LogFn = (\n msg: string | unknown | LoggerMeta,\n ...args: (string | unknown | LoggerMeta)[]\n ) => this.log('warn', msg, ...args);\n\n trace: LogFn = (\n msg: string | unknown | LoggerMeta,\n ...args: (string | unknown | LoggerMeta)[]\n ) => this.log('trace', msg, ...args);\n\n child(meta: AnyValueMap = {}) {\n return new PinoLogger(this._pinoLogger.level, { ...this._meta, ...meta });\n }\n\n getBaseLogger() {\n return this._pinoLogger;\n }\n}\n\nexport function logger(level: LevelWithSilentOrString, meta: AnyValueMap = {}) {\n return new PinoLogger(level, meta);\n}\n","import { LoggerMeta } from '../types/openTelemetryCollector.types';\n\nexport function isLoggerMeta(arg: unknown): arg is LoggerMeta {\n return typeof arg === 'object' && arg !== null && '_meta' in arg;\n}\n","import { AnySchemaValidator, SchemaValidator } from '@forklaunch/validator';\nimport {\n Body,\n ResponsesObject,\n TypedBody\n} from '../types/contractDetails.types';\n\n/**\n * Discriminates the body type from the given contract details and returns information\n * necessary for parsing and validation.\n *\n * @template SV - Schema validator type.\n * @template Path - Route path type.\n * @template P - Params schema type.\n * @template ResBodyMap - Response body map type.\n * @template ReqBody - Request body type.\n * @template ReqQuery - Request query object type.\n * @template ReqHeaders - Request headers object type.\n * @template ResHeaders - Response headers object type.\n * @param contractDetails - The HTTP contract details.\n * @returns An object containing the content type, parser type, and schema.\n * @throws If no body-related information is found in the contract details.\n */\nexport function discriminateBody<SV extends AnySchemaValidator>(\n schemaValidator: SV,\n body: Body<SV> | undefined\n):\n | {\n contentType: string;\n parserType: 'json' | 'text' | 'multipart' | 'urlEncoded' | 'file';\n schema: SV['_ValidSchemaObject'];\n }\n | undefined {\n if (body == null) {\n return undefined;\n }\n\n const maybeTypedBody = body as TypedBody<SV>;\n\n if ('text' in maybeTypedBody && maybeTypedBody.text != null) {\n return {\n contentType: maybeTypedBody.contentType ?? 'text/plain',\n parserType: 'text',\n schema: maybeTypedBody.text\n };\n } else if ('json' in maybeTypedBody && maybeTypedBody.json != null) {\n return {\n contentType: maybeTypedBody.contentType ?? 'application/json',\n parserType: 'json',\n schema: maybeTypedBody.json\n };\n } else if ('file' in maybeTypedBody && maybeTypedBody.file != null) {\n return {\n contentType: maybeTypedBody.contentType ?? 'application/octet-stream',\n parserType: 'file',\n schema: maybeTypedBody.file\n };\n } else if (\n 'multipartForm' in maybeTypedBody &&\n maybeTypedBody.multipartForm != null\n ) {\n return {\n contentType: maybeTypedBody.contentType ?? 'multipart/form-data',\n parserType: 'multipart',\n schema: maybeTypedBody.multipartForm\n };\n } else if (\n 'urlEncodedForm' in maybeTypedBody &&\n maybeTypedBody.urlEncodedForm != null\n ) {\n return {\n contentType:\n maybeTypedBody.contentType ?? 'application/x-www-form-urlencoded',\n parserType: 'urlEncoded',\n schema: maybeTypedBody.urlEncodedForm\n };\n } else if ('schema' in maybeTypedBody && maybeTypedBody.schema != null) {\n return {\n contentType: maybeTypedBody.contentType ?? 'application/json',\n parserType: 'text',\n schema: maybeTypedBody.schema\n };\n } else if (\n (schemaValidator as SchemaValidator).isInstanceOf(\n maybeTypedBody,\n schemaValidator.string\n )\n ) {\n return {\n contentType: 'text/plain',\n parserType: 'text',\n schema: maybeTypedBody\n };\n } else if (\n (schemaValidator as SchemaValidator).openapi(maybeTypedBody).format ===\n 'binary'\n ) {\n return {\n contentType: 'application/octet-stream',\n parserType: 'file',\n schema: maybeTypedBody\n };\n } else {\n return {\n contentType: 'application/json',\n parserType: 'json',\n schema: maybeTypedBody\n };\n }\n}\n\n/**\n * Discriminates all response body types from the given contract details and returns\n * information necessary for parsing and validation for each status code.\n *\n * @template SV - Schema validator type.\n * @template Path - Route path type.\n * @template P - Params schema type.\n * @template ResBodyMap - Response body map type.\n * @template ReqQuery - Request query object type.\n * @template ReqHeaders - Request headers object type.\n * @template ResHeaders - Response headers object type.\n * @param contractDetails - The contract details containing response schemas.\n * @returns A record mapping status codes to content type, parser type, and schema info.\n */\nexport function discriminateResponseBodies<SV extends AnySchemaValidator>(\n schemaValidator: SV,\n responses: ResponsesObject<SV>\n) {\n const discriminatedResponses: Record<\n number,\n {\n contentType: string;\n parserType: 'json' | 'text' | 'serverSentEvent' | 'file' | 'multipart';\n schema: SV['_ValidSchemaObject'];\n }\n > = {};\n for (const [statusCode, response] of Object.entries(responses)) {\n if (response != null && typeof response === 'object') {\n if ('json' in response && response.json != null) {\n discriminatedResponses[Number(statusCode)] = {\n contentType:\n ('contentType' in response &&\n typeof response.contentType === 'string'\n ? response.contentType\n : 'application/json') ?? 'application/json',\n parserType: 'json',\n schema: response.json\n };\n } else if ('schema' in response && response.schema != null) {\n discriminatedResponses[Number(statusCode)] = {\n contentType:\n ('contentType' in response &&\n typeof response.contentType === 'string'\n ? response.contentType\n : 'application/json') ?? 'application/json',\n parserType: 'text',\n schema: response.schema\n };\n } else if ('text' in response && response.text != null) {\n discriminatedResponses[Number(statusCode)] = {\n contentType:\n ('contentType' in response &&\n typeof response.contentType === 'string'\n ? response.contentType\n : 'text/plain') ?? 'text/plain',\n parserType: 'text',\n schema: response.text\n };\n } else if ('file' in response && response.file != null) {\n discriminatedResponses[Number(statusCode)] = {\n contentType:\n ('contentType' in response &&\n typeof response.contentType === 'string'\n ? response.contentType\n : 'application/octet-stream') ?? 'application/octet-stream',\n parserType: 'file',\n schema: response.file\n };\n } else if ('event' in response && response.event != null) {\n discriminatedResponses[Number(statusCode)] = {\n contentType:\n ('contentType' in response &&\n typeof response.contentType === 'string'\n ? response.contentType\n : 'text/event-stream') ?? 'text/event-stream',\n parserType: 'serverSentEvent',\n schema: response.event\n };\n } else if (\n (schemaValidator as SchemaValidator).isInstanceOf(\n response,\n schemaValidator.string\n )\n ) {\n discriminatedResponses[Number(statusCode)] = {\n contentType: 'text/plain',\n parserType: 'text',\n schema: response\n };\n } else if (\n (schemaValidator as SchemaValidator).openapi(response).format ===\n 'binary'\n ) {\n discriminatedResponses[Number(statusCode)] = {\n contentType: 'application/octet-stream',\n parserType: 'file',\n schema: response\n };\n } else {\n discriminatedResponses[Number(statusCode)] = {\n contentType: 'application/json',\n parserType: 'json',\n schema: response\n };\n }\n } else {\n discriminatedResponses[Number(statusCode)] = {\n contentType: 'application/json',\n parserType: 'json',\n schema: response\n };\n }\n }\n return discriminatedResponses;\n}\n","import { isRecord } from '@forklaunch/common';\nimport { AnySchemaValidator, SchemaValidator } from '@forklaunch/validator';\nimport { hasPermissionChecks } from '../guards/hasPermissionChecks';\nimport { hasRoleChecks } from '../guards/hasRoleChecks';\nimport { hasScopeChecks } from '../guards/hasScopeChecks';\nimport { hasVersionedSchema } from '../guards/hasVersionedSchema';\nimport { isExpressLikeSchemaHandler } from '../guards/isExpressLikeSchemaHandler';\nimport { isHmacMethod } from '../guards/isHmacMethod';\nimport { isHttpContractDetails } from '../guards/isHttpContractDetails';\nimport { isPathParamHttpContractDetails } from '../guards/isPathParamContractDetails';\nimport { isTypedHandler } from '../guards/isTypedHandler';\nimport { parseRequestAuth } from '../middleware/request/auth.middleware';\nimport { createContext } from '../middleware/request/createContext.middleware';\nimport { enrichDetails } from '../middleware/request/enrichDetails.middleware';\nimport { parse } from '../middleware/request/parse.middleware';\nimport { OpenTelemetryCollector } from '../telemetry/openTelemetryCollector';\nimport { ExpressLikeSchemaHandler } from '../types/apiDefinition.types';\nimport {\n Body,\n ContractDetails,\n HeadersObject,\n HttpMethod,\n Method,\n ParamsDictionary,\n ParamsObject,\n PathParamHttpContractDetails,\n PathParamMethod,\n QueryObject,\n ResponseCompiledSchema,\n ResponsesObject,\n SchemaAuthMethods,\n SessionObject,\n VersionSchema\n} from '../types/contractDetails.types';\nimport { ExpressLikeRouterOptions } from '../types/expressLikeOptions';\nimport {\n ContractDetailsOrMiddlewareOrTypedHandler,\n MiddlewareOrMiddlewareWithTypedHandler\n} from '../types/expressLikeRouter.types';\nimport { MetricsDefinition } from '../types/openTelemetryCollector.types';\nimport {\n discriminateBody,\n discriminateResponseBodies\n} from './discriminateBody';\n\nexport function resolveContractDetailsAndHandlers<\n SV extends AnySchemaValidator,\n Name extends string,\n ContractMethod extends Method,\n Path extends `/${string}`,\n P extends ParamsObject<SV>,\n ResBodyMap extends ResponsesObject<SV>,\n ReqBody extends Body<SV>,\n ReqQuery extends QueryObject<SV>,\n ReqHeaders extends HeadersObject<SV>,\n ResHeaders extends HeadersObject<SV>,\n LocalsObj extends Record<string, unknown>,\n VersionedApi extends VersionSchema<SV, ContractMethod>,\n RouterSession extends SessionObject<SV>,\n BaseRequest,\n BaseResponse,\n NextFunction,\n Auth extends SchemaAuthMethods<\n SV,\n P,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n VersionedApi,\n BaseRequest\n >\n>(\n contractDetailsOrMiddlewareOrTypedHandler: ContractDetailsOrMiddlewareOrTypedHandler<\n SV,\n Name,\n ContractMethod,\n Path,\n P,\n ResBodyMap,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n ResHeaders,\n LocalsObj,\n VersionedApi,\n BaseRequest,\n BaseResponse,\n NextFunction,\n RouterSession,\n Auth\n >,\n middlewareOrMiddlewareAndTypedHandler: MiddlewareOrMiddlewareWithTypedHandler<\n SV,\n Name,\n ContractMethod,\n Path,\n P,\n ResBodyMap,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n ResHeaders,\n LocalsObj,\n VersionedApi,\n BaseRequest,\n BaseResponse,\n NextFunction,\n RouterSession,\n Auth\n >[]\n) {\n let contractDetails: ContractDetails<\n SV,\n Name,\n ContractMethod,\n Path,\n P,\n ResBodyMap,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n ResHeaders,\n VersionedApi,\n BaseRequest,\n Auth\n >;\n // eslint-disable-next-line no-useless-assignment\n let handlers: ExpressLikeSchemaHandler<\n SV,\n P,\n ResBodyMap,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n ResHeaders,\n LocalsObj,\n VersionedApi,\n RouterSession,\n BaseRequest,\n BaseResponse,\n NextFunction\n >[] = [];\n\n if (\n isTypedHandler<\n SV,\n Name,\n ContractMethod,\n Path,\n P,\n ResBodyMap,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n ResHeaders,\n LocalsObj,\n VersionedApi,\n BaseRequest,\n BaseResponse,\n NextFunction,\n Auth\n >(contractDetailsOrMiddlewareOrTypedHandler)\n ) {\n contractDetails = contractDetailsOrMiddlewareOrTypedHandler.contractDetails;\n handlers =\n contractDetailsOrMiddlewareOrTypedHandler.handlers as ExpressLikeSchemaHandler<\n SV,\n P,\n ResBodyMap,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n ResHeaders,\n LocalsObj,\n VersionedApi,\n RouterSession,\n BaseRequest,\n BaseResponse,\n NextFunction\n >[];\n } else {\n const maybeTypedHandler =\n middlewareOrMiddlewareAndTypedHandler[\n middlewareOrMiddlewareAndTypedHandler.length - 1\n ];\n if (\n isTypedHandler<\n SV,\n Name,\n ContractMethod,\n Path,\n P,\n ResBodyMap,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n ResHeaders,\n LocalsObj,\n VersionedApi,\n BaseRequest,\n BaseResponse,\n NextFunction,\n Auth\n >(maybeTypedHandler)\n ) {\n contractDetails = maybeTypedHandler.contractDetails;\n const typedHandlerHandlers = maybeTypedHandler.handlers;\n const finalHandlers: MiddlewareOrMiddlewareWithTypedHandler<\n SV,\n Name,\n ContractMethod,\n Path,\n P,\n ResBodyMap,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n ResHeaders,\n LocalsObj,\n VersionedApi,\n BaseRequest,\n BaseResponse,\n NextFunction,\n RouterSession,\n Auth\n >[] = [];\n\n if (\n isExpressLikeSchemaHandler<\n SV,\n ContractMethod,\n P,\n ResBodyMap,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n ResHeaders,\n LocalsObj,\n VersionedApi,\n RouterSession,\n BaseRequest,\n BaseResponse,\n NextFunction\n >(contractDetailsOrMiddlewareOrTypedHandler)\n ) {\n finalHandlers.push(contractDetailsOrMiddlewareOrTypedHandler);\n }\n finalHandlers.push(...middlewareOrMiddlewareAndTypedHandler.slice(0, -1));\n finalHandlers.push(\n ...(typedHandlerHandlers as ExpressLikeSchemaHandler<\n SV,\n P,\n ResBodyMap,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n ResHeaders,\n LocalsObj,\n VersionedApi,\n RouterSession,\n BaseRequest,\n BaseResponse,\n NextFunction\n >[] as MiddlewareOrMiddlewareWithTypedHandler<\n SV,\n Name,\n ContractMethod,\n Path,\n P,\n ResBodyMap,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n ResHeaders,\n LocalsObj,\n VersionedApi,\n BaseRequest,\n BaseResponse,\n NextFunction,\n RouterSession,\n Auth\n >[])\n );\n\n handlers = (finalHandlers as unknown[]).filter((handler) =>\n isExpressLikeSchemaHandler<\n SV,\n ContractMethod,\n P,\n ResBodyMap,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n ResHeaders,\n LocalsObj,\n VersionedApi,\n RouterSession,\n BaseRequest,\n BaseResponse,\n NextFunction\n >(handler)\n ) as ExpressLikeSchemaHandler<\n SV,\n P,\n ResBodyMap,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n ResHeaders,\n LocalsObj,\n VersionedApi,\n RouterSession,\n BaseRequest,\n BaseResponse,\n NextFunction\n >[];\n } else {\n if (\n isExpressLikeSchemaHandler(contractDetailsOrMiddlewareOrTypedHandler) ||\n isTypedHandler<\n SV,\n Name,\n ContractMethod,\n Path,\n P,\n ResBodyMap,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n ResHeaders,\n LocalsObj,\n VersionedApi,\n BaseRequest,\n BaseResponse,\n NextFunction,\n Auth\n >(contractDetailsOrMiddlewareOrTypedHandler)\n ) {\n throw new Error('Contract details are not defined');\n }\n contractDetails =\n contractDetailsOrMiddlewareOrTypedHandler as ContractDetails<\n SV,\n Name,\n ContractMethod,\n Path,\n P,\n ResBodyMap,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n ResHeaders,\n VersionedApi,\n BaseRequest,\n Auth\n >;\n\n handlers = (middlewareOrMiddlewareAndTypedHandler as unknown[]).filter(\n (handler) =>\n isExpressLikeSchemaHandler<\n SV,\n ContractMethod,\n P,\n ResBodyMap,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n ResHeaders,\n LocalsObj,\n VersionedApi,\n RouterSession,\n BaseRequest,\n BaseResponse,\n NextFunction\n >(handler)\n ) as ExpressLikeSchemaHandler<\n SV,\n P,\n ResBodyMap,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n ResHeaders,\n LocalsObj,\n VersionedApi,\n RouterSession,\n BaseRequest,\n BaseResponse,\n NextFunction\n >[];\n }\n }\n\n return { contractDetails, handlers };\n}\n\nexport function validateContractDetails<\n SV extends AnySchemaValidator,\n Name extends string,\n ContractMethod extends Method,\n Path extends `/${string}`,\n P extends ParamsObject<SV>,\n ResBodyMap extends ResponsesObject<SV>,\n ReqBody extends Body<SV>,\n ReqQuery extends QueryObject<SV>,\n ReqHeaders extends HeadersObject<SV>,\n ResHeaders extends HeadersObject<SV>,\n VersionedApi extends VersionSchema<SV, ContractMethod>,\n BaseRequest,\n Auth extends SchemaAuthMethods<\n SV,\n P,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n VersionedApi,\n BaseRequest\n >\n>(\n contractDetails: ContractDetails<\n SV,\n Name,\n ContractMethod,\n Path,\n P,\n ResBodyMap,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n ResHeaders,\n VersionedApi,\n BaseRequest,\n Auth\n >,\n schemaValidator: SV\n) {\n if (\n !isHttpContractDetails<\n SV,\n Name,\n Path,\n P,\n ResBodyMap,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n ResHeaders,\n VersionedApi extends VersionSchema<SV, HttpMethod> ? VersionedApi : never,\n BaseRequest,\n Auth\n >(contractDetails) &&\n !isPathParamHttpContractDetails<\n SV,\n Name,\n Path,\n P,\n ResBodyMap,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n ResHeaders,\n VersionedApi extends VersionSchema<SV, PathParamMethod>\n ? VersionedApi\n : never,\n BaseRequest,\n Auth\n >(contractDetails)\n ) {\n throw new Error('Contract details are malformed for route definition');\n }\n\n // Validate access field and auth narrowing (runtime safety net for JS users)\n const access = (contractDetails as Record<string, unknown>)['access'] as\n string | undefined;\n const auth = (contractDetails as Record<string, unknown>)['auth'];\n\n if (access != null) {\n const validAccess = ['public', 'authenticated', 'protected', 'internal'];\n if (!validAccess.includes(access)) {\n throw new Error(\n `Route '${contractDetails.name}': invalid access level '${access}'. ` +\n `Must be one of: ${validAccess.join(', ')}`\n );\n }\n\n if (access === 'public' && auth != null) {\n throw new Error(\n `Route '${contractDetails.name}': access 'public' cannot have auth configured`\n );\n }\n\n if (access === 'protected') {\n if (!auth) {\n throw new Error(\n `Route '${contractDetails.name}': access 'protected' requires auth with roles, permissions, or scope`\n );\n }\n if (\n !hasPermissionChecks(auth) &&\n !hasRoleChecks(auth) &&\n !hasScopeChecks(auth)\n ) {\n throw new Error(\n `Route '${contractDetails.name}': access 'protected' requires at least one of ` +\n `allowedRoles, forbiddenRoles, allowedPermissions, forbiddenPermissions, or requiredScope`\n );\n }\n }\n\n if (access === 'internal') {\n if (!auth || !isHmacMethod(auth)) {\n throw new Error(\n `Route '${contractDetails.name}': access 'internal' requires HMAC auth`\n );\n }\n }\n }\n\n if (contractDetails.versions) {\n const parserTypes = Object.values(contractDetails.versions).map(\n (version) => discriminateBody(schemaValidator, version.body)?.parserType\n );\n\n const allParserTypesSame =\n parserTypes.length === 0 ||\n parserTypes.every((pt) => pt === parserTypes[0]);\n\n if (!allParserTypesSame) {\n throw new Error(\n 'All versioned contractDetails must have the same parsing type for body.'\n );\n }\n }\n}\n\nexport function processContractDetailsIO<\n SV extends AnySchemaValidator,\n P extends ParamsObject<SV>\n>(\n schemaValidator: SV & SchemaValidator,\n contractDetailsIO: {\n requestHeaders?: HeadersObject<SV>;\n responseHeaders?: HeadersObject<SV>;\n query?: QueryObject<SV>;\n body?: Body<SV>;\n responses: ResponsesObject<SV>;\n },\n routeParams?: P\n) {\n const responseSchemas = {\n 400: schemaValidator.string,\n 401: schemaValidator.string,\n 403: schemaValidator.string,\n 404: schemaValidator.string,\n 500: schemaValidator.string,\n ...Object.fromEntries(\n Object.entries(\n discriminateResponseBodies(schemaValidator, contractDetailsIO.responses)\n ).map(([key, value]) => [Number(key), value.schema])\n )\n };\n\n return {\n requestSchema: schemaValidator.compile(\n schemaValidator.schemify({\n ...(routeParams != null\n ? { params: routeParams as ParamsDictionary }\n : { params: schemaValidator.unknown as ParamsObject<SV> }),\n ...(contractDetailsIO.requestHeaders != null\n ? { headers: contractDetailsIO.requestHeaders }\n : { headers: schemaValidator.unknown as HeadersObject<SV> }),\n ...(contractDetailsIO.query != null\n ? { query: contractDetailsIO.query }\n : { query: schemaValidator.unknown as QueryObject<SV> }),\n ...(contractDetailsIO.body != null\n ? {\n body: discriminateBody(schemaValidator, contractDetailsIO.body)\n ?.schema\n }\n : { body: schemaValidator.unknown as Body<SV> })\n })\n ),\n responseSchemas: {\n ...(contractDetailsIO.responseHeaders != null\n ? {\n headers: schemaValidator.compile(\n schemaValidator.schemify(contractDetailsIO.responseHeaders)\n )\n }\n : { headers: schemaValidator.unknown as HeadersObject<SV> }),\n responses: Object.fromEntries(\n Object.entries(responseSchemas).map(([key, value]) => [\n key,\n schemaValidator.compile(schemaValidator.schemify(value))\n ])\n )\n }\n };\n}\n\nexport function compileRouteSchemas<\n SV extends AnySchemaValidator,\n Name extends string,\n ContractMethod extends Method,\n Path extends `/${string}`,\n P extends ParamsObject<SV>,\n ResBodyMap extends ResponsesObject<SV>,\n ReqBody extends Body<SV>,\n ReqQuery extends QueryObject<SV>,\n ReqHeaders extends HeadersObject<SV>,\n ResHeaders extends HeadersObject<SV>,\n VersionedApi extends VersionSchema<SV, ContractMethod>,\n BaseRequest,\n Auth extends SchemaAuthMethods<\n SV,\n P,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n VersionedApi,\n BaseRequest\n >\n>(\n contractDetails: ContractDetails<\n SV,\n Name,\n ContractMethod,\n Path,\n P,\n ResBodyMap,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n ResHeaders,\n VersionedApi,\n BaseRequest,\n Auth\n >,\n schemaValidator: SV\n) {\n const validator = schemaValidator as SV & SchemaValidator;\n let requestSchema: unknown | Record<string, unknown>;\n let responseSchemas:\n ResponseCompiledSchema | Record<string, ResponseCompiledSchema>;\n\n if (hasVersionedSchema(contractDetails)) {\n requestSchema = {};\n responseSchemas = {};\n\n Object.entries(contractDetails.versions ?? {}).forEach(\n ([version, versionedContractDetails]) => {\n const {\n requestSchema: versionedRequestSchema,\n responseSchemas: versionedResponseSchemas\n } = processContractDetailsIO(\n validator,\n versionedContractDetails,\n contractDetails.params as P\n );\n\n if (isRecord(requestSchema)) {\n requestSchema = {\n ...requestSchema,\n [version]: versionedRequestSchema\n };\n }\n if (isRecord(responseSchemas)) {\n responseSchemas = {\n ...responseSchemas,\n [version]: versionedResponseSchemas\n };\n }\n }\n );\n } else {\n const {\n requestSchema: unversionedRequestSchema,\n responseSchemas: unversionedResponseSchemas\n } = processContractDetailsIO(\n validator,\n {\n ...('params' in contractDetails && contractDetails.params != null\n ? { params: contractDetails.params }\n : { params: validator.unknown as ParamsObject<SV> }),\n ...('requestHeaders' in contractDetails &&\n contractDetails.requestHeaders != null\n ? { requestHeaders: contractDetails.requestHeaders }\n : {\n requestHeaders: validator.unknown as HeadersObject<SV>\n }),\n ...('responseHeaders' in contractDetails &&\n contractDetails.responseHeaders != null\n ? { responseHeaders: contractDetails.responseHeaders }\n : {\n responseHeaders: validator.unknown as HeadersObject<SV>\n }),\n ...('query' in contractDetails && contractDetails.query != null\n ? { query: contractDetails.query }\n : {\n query: validator.unknown as QueryObject<SV>\n }),\n ...('body' in contractDetails && contractDetails.body != null\n ? { body: contractDetails.body }\n : {\n body: validator.unknown as Body<SV>\n }),\n responses:\n 'responses' in contractDetails && contractDetails.responses != null\n ? contractDetails.responses\n : (validator.unknown as ResponsesObject<SV>)\n },\n contractDetails.params as P\n );\n\n requestSchema = unversionedRequestSchema;\n responseSchemas = unversionedResponseSchemas;\n }\n\n return { requestSchema, responseSchemas };\n}\n\nexport function resolveRouteMiddlewares<\n SV extends AnySchemaValidator,\n Name extends string,\n ContractMethod extends Method,\n Path extends `/${string}`,\n P extends ParamsObject<SV>,\n ResBodyMap extends ResponsesObject<SV>,\n ReqBody extends Body<SV>,\n ReqQuery extends QueryObject<SV>,\n ReqHeaders extends HeadersObject<SV>,\n ResHeaders extends HeadersObject<SV>,\n LocalsObj extends Record<string, unknown>,\n VersionedApi extends VersionSchema<SV, ContractMethod>,\n RouterSession extends SessionObject<SV>,\n BaseRequest,\n BaseResponse,\n NextFunction,\n Auth extends SchemaAuthMethods<\n SV,\n P,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n VersionedApi,\n BaseRequest\n >,\n RouterHandler\n>(params: {\n basePath: string;\n path: Path;\n contractDetails: ContractDetails<\n SV,\n Name,\n ContractMethod,\n Path,\n P,\n ResBodyMap,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n ResHeaders,\n VersionedApi,\n BaseRequest,\n Auth\n >;\n requestSchema: unknown;\n responseSchemas:\n ResponseCompiledSchema | Record<string, ResponseCompiledSchema>;\n openTelemetryCollector?: OpenTelemetryCollector<MetricsDefinition>;\n routerOptions?: ExpressLikeRouterOptions<SV, RouterSession>;\n postEnrichMiddleware?: RouterHandler[];\n includeCreateContext?: boolean;\n handlers: ExpressLikeSchemaHandler<\n SV,\n P,\n ResBodyMap,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n ResHeaders,\n LocalsObj,\n VersionedApi,\n RouterSession,\n BaseRequest,\n BaseResponse,\n NextFunction\n >[];\n router?: { routerOptions?: ExpressLikeRouterOptions<SV, RouterSession> };\n}): {\n middlewares: RouterHandler[];\n controllerHandler: ExpressLikeSchemaHandler<\n SV,\n P,\n ResBodyMap,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n ResHeaders,\n LocalsObj,\n VersionedApi,\n RouterSession,\n BaseRequest,\n BaseResponse,\n NextFunction\n >;\n} {\n const handlersCopy = [...params.handlers];\n const controllerHandler = handlersCopy.pop();\n\n if (typeof controllerHandler !== 'function') {\n throw new Error(\n `Last argument must be a handler, received: ${controllerHandler}`\n );\n }\n\n const middlewares = [\n ...(params.includeCreateContext !== false ? [createContext] : []),\n enrichDetails<\n SV,\n ContractMethod,\n P,\n ResBodyMap,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n ResHeaders,\n LocalsObj,\n VersionedApi,\n RouterSession\n >(\n `${params.basePath}${params.path}`,\n params.contractDetails as PathParamHttpContractDetails<SV>,\n params.requestSchema,\n params.responseSchemas,\n params.openTelemetryCollector,\n // Use dynamic lookup from router instance instead of captured params\n () => (params.router ? params.router.routerOptions : params.routerOptions)\n ),\n ...(params.postEnrichMiddleware as unknown[]),\n parse,\n parseRequestAuth<\n SV,\n ContractMethod,\n P,\n ResBodyMap,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n ResHeaders,\n LocalsObj,\n VersionedApi,\n RouterSession\n >,\n ...handlersCopy\n ] as RouterHandler[];\n\n return {\n middlewares,\n controllerHandler: controllerHandler as ExpressLikeSchemaHandler<\n SV,\n P,\n ResBodyMap,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n ResHeaders,\n LocalsObj,\n VersionedApi,\n RouterSession,\n BaseRequest,\n BaseResponse,\n NextFunction\n >\n };\n}\n","export function hasVersionedSchema(contractDetails: unknown) {\n return (\n typeof contractDetails === 'object' &&\n contractDetails !== null &&\n 'versions' in contractDetails &&\n contractDetails.versions !== null\n );\n}\n","import { HmacMethods } from '../types/contractDetails.types';\n\n/**\n * Type guard to determine if the provided value is an HmacMethods object.\n *\n * @param maybeHmacMethod - The value to check.\n * @returns True if the value is an object with a non-null 'hmac' property, otherwise false.\n */\nexport function isHmacMethod(\n maybeHmacMethod: unknown\n): maybeHmacMethod is HmacMethods {\n return (\n typeof maybeHmacMethod === 'object' &&\n maybeHmacMethod !== null &&\n 'hmac' in maybeHmacMethod &&\n maybeHmacMethod.hmac != null\n );\n}\n","import { AnySchemaValidator } from '@forklaunch/validator';\nimport {\n Body,\n ExtractedParamsObject,\n HeadersObject,\n ParamsObject,\n PathParamHttpContractDetails,\n PathParamMethod,\n QueryObject,\n ResponsesObject,\n SchemaAuthMethods,\n VersionSchema\n} from '../types/contractDetails.types';\n\nexport function isPathParamHttpContractDetails<\n SV extends AnySchemaValidator,\n Name extends string,\n Path extends `/${string}`,\n ParamsSchema extends ExtractedParamsObject<Path> & ParamsObject<SV>,\n ResponseSchemas extends ResponsesObject<SV>,\n BodySchema extends Body<SV>,\n QuerySchema extends QueryObject<SV>,\n ReqHeaders extends HeadersObject<SV>,\n ResHeaders extends HeadersObject<SV>,\n VersionedApi extends VersionSchema<SV, PathParamMethod>,\n BaseRequest,\n const Auth extends SchemaAuthMethods<\n SV,\n ParamsSchema,\n BodySchema,\n QuerySchema,\n ReqHeaders,\n VersionedApi,\n BaseRequest\n >\n>(\n maybePathParamHttpContractDetails: unknown\n): maybePathParamHttpContractDetails is PathParamHttpContractDetails<\n SV,\n Name,\n Path,\n ParamsSchema,\n ResponseSchemas,\n BodySchema,\n QuerySchema,\n ReqHeaders,\n ResHeaders,\n VersionedApi,\n BaseRequest,\n Auth\n> {\n return (\n maybePathParamHttpContractDetails != null &&\n typeof maybePathParamHttpContractDetails === 'object' &&\n 'name' in maybePathParamHttpContractDetails &&\n 'summary' in maybePathParamHttpContractDetails &&\n maybePathParamHttpContractDetails.name != null &&\n maybePathParamHttpContractDetails.summary != null &&\n (('responses' in maybePathParamHttpContractDetails &&\n maybePathParamHttpContractDetails.responses != null) ||\n ('versions' in maybePathParamHttpContractDetails &&\n typeof maybePathParamHttpContractDetails.versions === 'object' &&\n maybePathParamHttpContractDetails.versions != null &&\n Object.values(maybePathParamHttpContractDetails.versions).every(\n (version) => 'responses' in version && version.responses != null\n )))\n );\n}\n","import { AnySchemaValidator } from '@forklaunch/validator';\nimport {\n Body,\n ExtractedParamsObject,\n HeadersObject,\n HttpContractDetails,\n HttpMethod,\n ParamsObject,\n QueryObject,\n ResponsesObject,\n SchemaAuthMethods,\n VersionSchema\n} from '../types/contractDetails.types';\nimport { isPathParamHttpContractDetails } from './isPathParamContractDetails';\n\n/**\n * Type guard that checks if an object is an HTTP contract details object.\n * An HTTP contract details object contains the schema definitions for an HTTP endpoint,\n * including path parameters, response schemas, body schema, query parameters, and headers.\n *\n * @template SV - A type that extends AnySchemaValidator\n * @template Path - A type that extends `/${string}` representing the endpoint path\n * @template ParamsSchema - The type of path parameters schema\n * @template ResponseSchemas - The type of response schemas\n * @template BodySchema - The type of request body schema\n * @template QuerySchema - The type of query parameters schema\n * @template ReqHeaders - The type of request headers schema\n * @template ResHeaders - The type of response headers schema\n * @template BaseRequest - The base request type\n * @param {unknown} maybeContractDetails - The object to check\n * @returns {boolean} A type predicate indicating whether the object is an HttpContractDetails\n *\n * @example\n * ```ts\n * if (isHttpContractDetails(contractDetails)) {\n * // contractDetails is now typed as HttpContractDetails\n * const { body, path, params } = contractDetails;\n * }\n * ```\n */\nexport function isHttpContractDetails<\n SV extends AnySchemaValidator,\n Name extends string,\n Path extends `/${string}`,\n ParamsSchema extends ExtractedParamsObject<Path> & ParamsObject<SV>,\n ResponseSchemas extends ResponsesObject<SV>,\n BodySchema extends Body<SV>,\n QuerySchema extends QueryObject<SV>,\n ReqHeaders extends HeadersObject<SV>,\n ResHeaders extends HeadersObject<SV>,\n VersionedReqs extends VersionSchema<SV, HttpMethod>,\n BaseRequest,\n const Auth extends SchemaAuthMethods<\n SV,\n ParamsSchema,\n BodySchema,\n QuerySchema,\n ReqHeaders,\n VersionedReqs,\n BaseRequest\n >\n>(\n maybeContractDetails: unknown\n): maybeContractDetails is HttpContractDetails<\n SV,\n Name,\n Path,\n ParamsSchema,\n ResponseSchemas,\n BodySchema,\n QuerySchema,\n ReqHeaders,\n ResHeaders,\n VersionedReqs,\n BaseRequest,\n Auth\n> {\n return (\n isPathParamHttpContractDetails(maybeContractDetails) &&\n (('body' in maybeContractDetails && maybeContractDetails.body != null) ||\n ('versions' in maybeContractDetails &&\n typeof maybeContractDetails.versions === 'object' &&\n maybeContractDetails.versions != null &&\n Object.values(maybeContractDetails.versions).every(\n (version) => 'body' in version && version.body != null\n )))\n );\n}\n","import { isNever } from '@forklaunch/common';\nimport {\n AnySchemaValidator,\n prettyPrintParseErrors,\n SchemaValidator\n} from '@forklaunch/validator';\nimport { JWTPayload } from 'jose';\nimport { ParsedQs } from 'qs';\nimport { discriminateAuthMethod } from '../../discriminateAuthMethod';\nimport { hasFeatureChecks } from '../../guards/hasFeatureChecks';\nimport { hasPermissionChecks } from '../../guards/hasPermissionChecks';\nimport { hasRoleChecks } from '../../guards/hasRoleChecks';\nimport { hasScopeChecks } from '../../guards/hasScopeChecks';\nimport { hasSubscriptionChecks } from '../../guards/hasSubscriptionChecks';\nimport { isHmacMethod } from '../../guards/isHmacMethod';\nimport { meta } from '../../telemetry/pinoLogger';\nimport { authLogContext, jwtFailureReason } from './authLogContext';\nimport {\n ForklaunchNextFunction,\n ForklaunchRequest,\n ForklaunchResponse,\n MapParamsSchema,\n MapReqBodySchema,\n MapReqHeadersSchema,\n MapReqQuerySchema,\n MapResBodyMapSchema,\n MapResHeadersSchema,\n MapSessionSchema,\n MapVersionedReqsSchema,\n ResolvedForklaunchRequest,\n VersionedRequests\n} from '../../types/apiDefinition.types';\nimport {\n AuthMethods,\n Body,\n HeadersObject,\n Method,\n ParamsDictionary,\n ParamsObject,\n QueryObject,\n ResponsesObject,\n SessionObject,\n VersionSchema\n} from '../../types/contractDetails.types';\nimport { ExpressLikeGlobalAuthOptions } from '../../types/expressLikeOptions';\n\nconst invalidAuthorizationTokenFormat = [\n 401,\n 'Invalid Authorization token format.'\n] as const;\nconst invalidAuthorizationSignature = [\n 403,\n 'Invalid Authorization signature.'\n] as const;\nconst invalidAuthorizationTokenPermissions = [\n 403,\n 'Invalid Authorization permissions.'\n] as const;\nconst invalidAuthorizationTokenRoles = [\n 403,\n 'Invalid Authorization roles.'\n] as const;\nconst invalidAuthorizationTokenFeatures = [\n 403,\n 'Required features not available.'\n] as const;\nconst invalidAuthorizationSubscription = [\n 403,\n 'Active subscription required.'\n] as const;\nconst invalidAuthorizationToken = [\n 403,\n 'Invalid Authorization token.'\n] as const;\nconst invalidAuthorizationLogin = [\n 403,\n 'Invalid Authorization login.'\n] as const;\nconst invalidScope = [403, 'Invalid scope for operation.'] as const;\nconst invalidAuthorizationMethod = [\n 401,\n 'Invalid Authorization method.'\n] as const;\nconst authorizationTokenRequired = [\n 401,\n 'Authorization token required.'\n] as const;\nconst invalidInstantiation = [\n 500,\n 'Invalid instantiation of authorization method.'\n] as const;\n\n/**\n * Parses a HMAC token part.\n *\n * @param {string} part - The part of the token.\n * @param {string} expectedKey - The expected key.\n * @returns {string | undefined} - The parsed part.\n */\nfunction parseHmacTokenPart(\n part: string,\n expectedKey: string\n): string | undefined {\n if (!part) return undefined;\n const [key, ...rest] = part.split('=');\n if (key !== expectedKey || rest.length === 0) return undefined;\n return rest.join('=');\n}\n\n/**\n * Checks the authorization token for validity.\n *\n * @param {AuthMethod} [authorizationMethod] - The method of authorization.\n * @param {string} [authorizationToken] - The authorization string.\n * @returns {Promise<[401 | 403, string] | string | undefined>} - The result of the authorization check.\n */\nasync function checkAuthorizationToken<\n SV extends AnySchemaValidator,\n P extends ParamsDictionary,\n ReqBody extends Record<string, unknown>,\n ReqQuery extends ParsedQs,\n ReqHeaders extends Record<string, string>,\n VersionedReqs extends VersionedRequests,\n SessionSchema extends SessionObject<SV>,\n BaseRequest\n>(\n req: ForklaunchRequest<\n SV,\n P,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n Extract<keyof VersionedReqs, string>,\n SessionSchema\n >,\n authorizationMethod?: AuthMethods<\n SV,\n P,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n VersionedReqs,\n BaseRequest\n >,\n authorizationToken?: string,\n globalOptions?: ExpressLikeGlobalAuthOptions<SV, SessionSchema>,\n access?: 'public' | 'authenticated' | 'protected' | 'internal'\n): Promise<readonly [400 | 401 | 403 | 500, string] | undefined> {\n if (authorizationMethod == null) {\n return undefined;\n }\n\n const collapsedAuthorizationMethod = {\n ...globalOptions,\n ...authorizationMethod\n } as AuthMethods<\n SV,\n P,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n VersionedReqs,\n BaseRequest\n > &\n Exclude<ExpressLikeGlobalAuthOptions<SV, SessionSchema>, false | undefined>;\n\n if (authorizationToken == null) {\n return authorizationTokenRequired;\n }\n\n const [tokenPrefix, ...tokenParts] = authorizationToken.split(' ');\n\n if (!tokenParts.length || !tokenPrefix) {\n return invalidAuthorizationTokenFormat;\n }\n\n let sessionPayload: (JWTPayload & SessionSchema) | null;\n\n const { type, auth } = await discriminateAuthMethod(\n collapsedAuthorizationMethod as AuthMethods<\n SV,\n P,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n VersionedReqs,\n BaseRequest\n >,\n req.openTelemetryCollector\n );\n\n switch (type) {\n case 'hmac': {\n const [keyId, timestamp, nonce, signature] = tokenParts;\n if (\n keyId == null ||\n timestamp == null ||\n nonce == null ||\n signature == null ||\n tokenPrefix !== (collapsedAuthorizationMethod.tokenPrefix ?? 'HMAC')\n ) {\n return invalidAuthorizationToken;\n }\n\n if (!collapsedAuthorizationMethod.hmac?.secretKeys) {\n return invalidInstantiation;\n }\n\n const parsedKeyId = parseHmacTokenPart(keyId, 'keyId');\n const parsedTimestamp = parseHmacTokenPart(timestamp, 'ts');\n const parsedNonce = parseHmacTokenPart(nonce, 'nonce');\n const parsedSignature = parseHmacTokenPart(signature, 'signature');\n\n if (\n !parsedKeyId ||\n !parsedTimestamp ||\n !parsedNonce ||\n !parsedSignature\n ) {\n return invalidAuthorizationTokenFormat;\n }\n\n const verificationResult = await auth.verificationFunction({\n method: req?.method ?? '',\n path: req?.path ?? '',\n body: req?._rawBody ?? req?.body,\n timestamp: new Date(parsedTimestamp),\n nonce: parsedNonce,\n signature: parsedSignature,\n secretKey: collapsedAuthorizationMethod.hmac.secretKeys[parsedKeyId]\n });\n\n if (!verificationResult) {\n return invalidAuthorizationSignature;\n }\n\n sessionPayload = null;\n break;\n }\n case 'jwt': {\n const [token] = tokenParts;\n if (\n tokenPrefix !== (collapsedAuthorizationMethod.tokenPrefix ?? 'Bearer')\n ) {\n return invalidAuthorizationTokenFormat;\n }\n\n try {\n const decodedJwt =\n 'decodeResource' in auth && auth.decodeResource\n ? await auth.decodeResource(token)\n : 'verificationFunction' in auth && auth.verificationFunction\n ? await auth.verificationFunction(token)\n : undefined;\n\n if (!decodedJwt) {\n return invalidAuthorizationToken;\n }\n\n sessionPayload = decodedJwt as JWTPayload & SessionSchema;\n } catch (error) {\n (\n req as ForklaunchRequest<\n SV,\n P,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n Extract<keyof VersionedReqs, string>,\n SessionSchema\n >\n )?.openTelemetryCollector?.warn(\n 'JWT Verification Failed',\n meta({\n reason: jwtFailureReason(error),\n error: error instanceof Error ? error.message : String(error),\n method: req.method,\n path: req.path,\n ...authLogContext(token)\n })\n );\n return invalidAuthorizationToken;\n }\n\n break;\n }\n case 'basic': {\n const [token] = tokenParts;\n\n if (\n tokenPrefix !== (collapsedAuthorizationMethod.tokenPrefix ?? 'Basic')\n ) {\n return invalidAuthorizationTokenFormat;\n }\n\n if (auth.decodeResource) {\n sessionPayload = (await auth.decodeResource(token)) as JWTPayload &\n SessionSchema;\n } else {\n const [username, password] = Buffer.from(token, 'base64')\n .toString('utf-8')\n .split(':');\n\n if (!username || !password) {\n return invalidAuthorizationTokenFormat;\n }\n\n if (!auth.login(username, password)) {\n return invalidAuthorizationLogin;\n }\n\n sessionPayload = {\n sub: username\n } as JWTPayload & SessionSchema;\n }\n break;\n }\n default:\n isNever(type);\n return [401, 'Invalid Authorization method.'];\n }\n\n if (isHmacMethod(collapsedAuthorizationMethod) && sessionPayload == null) {\n return;\n }\n\n if (sessionPayload == null) {\n return invalidAuthorizationToken;\n }\n\n req.session = sessionPayload;\n if (collapsedAuthorizationMethod.sessionSchema) {\n const parsedSession = (req.schemaValidator as SchemaValidator).parse(\n collapsedAuthorizationMethod.sessionSchema,\n sessionPayload\n );\n if (!parsedSession.ok) {\n return [\n 400,\n `Invalid session: ${prettyPrintParseErrors(parsedSession.errors, 'Session')}`\n ];\n }\n }\n\n if (hasScopeChecks(collapsedAuthorizationMethod)) {\n if (collapsedAuthorizationMethod.surfaceScopes) {\n const resourceScopes = await collapsedAuthorizationMethod.surfaceScopes(\n sessionPayload,\n req as ResolvedForklaunchRequest<\n SV,\n P,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n VersionedReqs,\n SessionSchema,\n BaseRequest\n >\n );\n\n if (collapsedAuthorizationMethod.scopeHeirarchy) {\n if (collapsedAuthorizationMethod.requiredScope) {\n if (\n !resourceScopes.has(collapsedAuthorizationMethod.requiredScope) ||\n !Array.from(resourceScopes).every(\n (scope) =>\n (collapsedAuthorizationMethod.scopeHeirarchy?.indexOf(scope) ??\n -1) > -1\n )\n ) {\n return invalidScope;\n }\n }\n }\n }\n }\n\n // 'authenticated' routes only need a valid token (already verified above).\n // 'internal' routes use HMAC (already verified above, no RBAC).\n // Only 'protected' routes require RBAC checks.\n if (access === 'authenticated' || access === 'internal') {\n // Token/HMAC already validated — skip RBAC, proceed to subscription/feature checks\n } else if (hasPermissionChecks(collapsedAuthorizationMethod)) {\n if (!collapsedAuthorizationMethod.surfacePermissions) {\n return [500, 'No permission surfacing function provided.'];\n }\n\n const resourcePermissions =\n await collapsedAuthorizationMethod.surfacePermissions(\n sessionPayload,\n req as ResolvedForklaunchRequest<\n SV,\n P,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n VersionedReqs,\n SessionSchema,\n BaseRequest\n >\n );\n\n if (\n 'allowedPermissions' in collapsedAuthorizationMethod &&\n collapsedAuthorizationMethod.allowedPermissions\n ) {\n if (\n resourcePermissions.intersection(\n collapsedAuthorizationMethod.allowedPermissions\n ).size === 0\n ) {\n return invalidAuthorizationTokenPermissions;\n }\n }\n\n if (\n 'forbiddenPermissions' in collapsedAuthorizationMethod &&\n collapsedAuthorizationMethod.forbiddenPermissions\n ) {\n if (\n resourcePermissions.intersection(\n collapsedAuthorizationMethod.forbiddenPermissions\n ).size !== 0\n ) {\n return invalidAuthorizationTokenPermissions;\n }\n }\n } else if (hasRoleChecks(collapsedAuthorizationMethod)) {\n if (!collapsedAuthorizationMethod.surfaceRoles) {\n return [500, 'No role surfacing function provided.'];\n }\n\n const resourceRoles = await collapsedAuthorizationMethod.surfaceRoles(\n sessionPayload,\n req as ResolvedForklaunchRequest<\n SV,\n P,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n VersionedReqs,\n SessionSchema,\n BaseRequest\n >\n );\n\n if (\n 'allowedRoles' in collapsedAuthorizationMethod &&\n collapsedAuthorizationMethod.allowedRoles\n ) {\n if (\n resourceRoles.intersection(collapsedAuthorizationMethod.allowedRoles)\n .size === 0\n ) {\n return invalidAuthorizationTokenRoles;\n }\n }\n\n if (\n 'forbiddenRoles' in collapsedAuthorizationMethod &&\n collapsedAuthorizationMethod.forbiddenRoles\n ) {\n if (\n resourceRoles.intersection(collapsedAuthorizationMethod.forbiddenRoles)\n .size !== 0\n ) {\n return invalidAuthorizationTokenRoles;\n }\n }\n } else if (access === 'protected') {\n return invalidAuthorizationMethod;\n }\n\n if (hasSubscriptionChecks(collapsedAuthorizationMethod)) {\n if (!collapsedAuthorizationMethod.surfaceSubscription) {\n return [500, 'No subscription surfacing function provided.'];\n }\n\n const subscription = await collapsedAuthorizationMethod.surfaceSubscription(\n sessionPayload,\n req as ResolvedForklaunchRequest<\n SV,\n P,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n VersionedReqs,\n SessionSchema,\n BaseRequest\n >\n );\n\n if (!subscription) {\n return invalidAuthorizationSubscription;\n }\n }\n\n if (hasFeatureChecks(collapsedAuthorizationMethod)) {\n if (!collapsedAuthorizationMethod.surfaceFeatures) {\n return [500, 'No features surfacing function provided.'];\n }\n\n const availableFeatures =\n await collapsedAuthorizationMethod.surfaceFeatures(\n sessionPayload,\n req as ResolvedForklaunchRequest<\n SV,\n P,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n VersionedReqs,\n SessionSchema,\n BaseRequest\n >\n );\n\n const requiredFeatures =\n collapsedAuthorizationMethod.requiredFeatures ?? [];\n const missingFeatures = requiredFeatures.filter(\n (feature) => !availableFeatures.has(feature)\n );\n\n if (missingFeatures.length > 0) {\n return invalidAuthorizationTokenFeatures;\n }\n }\n}\n\n/**\n * Middleware to parse request authorization.\n *\n * @template SV - A type that extends AnySchemaValidator.\n * @template Request - A type that extends ForklaunchRequest.\n * @template Response - A type that extends ForklaunchResponse.\n * @template NextFunction - A type that extends ForklaunchNextFunction.\n * @param {Request} req - The request object.\n * @param {Response} res - The response object.\n * @param {NextFunction} [next] - The next middleware function.\n */\nexport async function parseRequestAuth<\n SV extends AnySchemaValidator,\n ContractMethod extends Method,\n P extends ParamsObject<SV>,\n ResBodyMap extends ResponsesObject<SV>,\n ReqBody extends Body<SV>,\n ReqQuery extends QueryObject<SV>,\n ReqHeaders extends HeadersObject<SV>,\n ResHeaders extends HeadersObject<SV>,\n LocalsObj extends Record<string, unknown>,\n VersionedApi extends VersionSchema<SV, ContractMethod>,\n SessionSchema extends SessionObject<SV>\n>(\n req: ForklaunchRequest<\n SV,\n MapParamsSchema<SV, P>,\n MapReqBodySchema<SV, ReqBody>,\n MapReqQuerySchema<SV, ReqQuery>,\n MapReqHeadersSchema<SV, ReqHeaders>,\n Extract<keyof MapVersionedReqsSchema<SV, VersionedApi>, string>,\n MapSessionSchema<SV, SessionSchema>\n >,\n res: ForklaunchResponse<\n unknown,\n MapResBodyMapSchema<SV, ResBodyMap>,\n MapResHeadersSchema<SV, ResHeaders>,\n LocalsObj,\n Extract<keyof MapVersionedReqsSchema<SV, VersionedApi>, string>\n >,\n next?: ForklaunchNextFunction\n) {\n const access = req.contractDetails.access as\n 'public' | 'authenticated' | 'protected' | 'internal' | undefined;\n\n // Public routes skip auth entirely\n if (access === 'public') {\n next?.();\n return;\n }\n\n const auth = req.contractDetails.auth as\n | AuthMethods<\n SV,\n MapParamsSchema<SV, P>,\n MapReqBodySchema<SV, ReqBody>,\n MapReqQuerySchema<SV, ReqQuery>,\n MapReqHeadersSchema<SV, ReqHeaders>,\n MapVersionedReqsSchema<SV, VersionedApi>,\n unknown\n >\n | undefined;\n\n const token =\n (req.headers[auth?.headerName ?? 'Authorization'] as string) ||\n (req.headers[auth?.headerName ?? 'authorization'] as string);\n\n const [error, message] =\n (await checkAuthorizationToken<\n SV,\n MapParamsSchema<SV, P>,\n MapReqBodySchema<SV, ReqBody>,\n MapReqQuerySchema<SV, ReqQuery>,\n MapReqHeadersSchema<SV, ReqHeaders>,\n MapVersionedReqsSchema<SV, VersionedApi>,\n MapSessionSchema<SV, SessionSchema>,\n unknown\n >(req, auth, token, req._globalOptions?.()?.auth, access)) ?? [];\n if (error != null) {\n // Warn, not error: an expired or missing token is normal traffic. The\n // credential itself is never logged; see authLogContext.\n req.openTelemetryCollector?.warn(\n message || 'Authorization Failed',\n meta({\n statusCode: error,\n method: req.method,\n path: req.path,\n ...authLogContext(token)\n })\n );\n res.type('text/plain');\n res.status(error).send(message as never);\n return;\n }\n\n next?.();\n}\n","import { safeStringify } from '@forklaunch/common';\nimport { AnySchemaValidator } from '@forklaunch/validator';\nimport { JWK, JWTPayload, jwtVerify } from 'jose';\nimport { ParsedQs } from 'qs';\nimport { createHmacToken } from './createHmacToken';\nimport { isBasicAuthMethod } from './guards/isBasicAuthMethod';\nimport { isHmacMethod } from './guards/isHmacMethod';\nimport { isJwtAuthMethod } from './guards/isJwtAuthMethod';\nimport { OpenTelemetryCollector } from './telemetry/openTelemetryCollector';\nimport { VersionedRequests } from './types/apiDefinition.types';\nimport {\n AuthMethods,\n BasicAuthMethods,\n DecodeResource,\n ParamsDictionary\n} from './types/contractDetails.types';\nimport { MetricsDefinition } from './types/openTelemetryCollector.types';\n\nconst DEFAULT_TTL = process.env.JWKS_TTL\n ? parseInt(process.env.JWKS_TTL)\n : 60 * 1000 * 5;\n\nconst cachedJwks = {\n value: null as JWK[] | null,\n lastUpdated: null as Date | null,\n ttl: DEFAULT_TTL\n};\n\n/**\n * Retrieves and caches the JSON Web Key Set (JWKS) from a given public key URL.\n *\n * This function fetches the JWKS from the specified URL and caches the result in memory\n * to avoid unnecessary network requests. The cache is considered valid for a duration\n * specified by the `cache-control` header in the JWKS HTTP response (in seconds), or\n * falls back to a default TTL if the header is not present. If the cache is still valid,\n * the cached keys are returned immediately.\n *\n * @param {string} jwksPublicKeyUrl - The URL to fetch the JWKS from.\n * @returns {Promise<JWK[]>} A promise that resolves to an array of JWK objects.\n *\n * @example\n * const jwks = await getCachedJwks('https://example.com/.well-known/jwks.json');\n * // Use jwks for JWT verification, etc.\n */\nexport async function getCachedJwks(jwksPublicKeyUrl: string): Promise<JWK[]> {\n if (\n cachedJwks.value &&\n cachedJwks.lastUpdated &&\n Date.now() - cachedJwks.lastUpdated.getTime() < cachedJwks.ttl\n ) {\n return cachedJwks.value;\n } else {\n const jwksResponse = await fetch(jwksPublicKeyUrl);\n const text = await jwksResponse.text();\n if (!text) {\n if (cachedJwks.value) {\n return cachedJwks.value;\n }\n throw new Error(\n `JWKS endpoint returned empty response (status ${jwksResponse.status})`\n );\n }\n const jwks = (JSON.parse(text) as { keys: JWK[] }).keys;\n cachedJwks.value = jwks;\n cachedJwks.lastUpdated = new Date();\n cachedJwks.ttl =\n parseInt(\n jwksResponse.headers.get('cache-control')?.split('=')[1] ??\n `${DEFAULT_TTL / 1000}`\n ) * 1000;\n return jwks;\n }\n}\n\n/**\n * Discriminates between different authentication methods and returns a typed result.\n *\n * This function analyzes the provided authentication configuration and determines\n * whether it uses basic authentication or JWT authentication. It returns a\n * discriminated union type that includes the authentication type and the\n * corresponding authentication configuration.\n *\n * @template SV - A type that extends AnySchemaValidator\n * @template P - A type that extends ParamsDictionary\n * @template ReqBody - A type that extends Record<string, unknown>\n * @template ReqQuery - A type that extends ParsedQs\n * @template ReqHeaders - A type that extends Record<string, unknown>\n * @template BaseRequest - The base request type\n *\n * @param auth - The authentication methods configuration object\n * @returns A discriminated union object with either:\n * - `{ type: 'basic', auth: BasicAuthMethods['basic'] }` for basic authentication\n * - `{ type: 'jwt', auth?: JwtAuthMethods['jwt'] }` for JWT authentication (auth is optional)\n *\n * @example\n * ```typescript\n * const authConfig = {\n * basic: {\n * login: (username: string, password: string) => boolean\n * }\n * };\n * const result = discriminateAuthMethod(authConfig);\n * // result.type === 'basic'\n * // result.auth === authConfig.basic\n * ```\n */\nexport async function discriminateAuthMethod<\n SV extends AnySchemaValidator,\n P extends ParamsDictionary,\n ReqBody extends Record<string, unknown>,\n ReqQuery extends ParsedQs,\n ReqHeaders extends Record<string, string>,\n VersionedReqs extends VersionedRequests,\n BaseRequest\n>(\n auth: AuthMethods<\n SV,\n P,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n VersionedReqs,\n BaseRequest\n >,\n openTelemetryCollector?: OpenTelemetryCollector<MetricsDefinition>\n): Promise<\n | {\n type: 'basic';\n auth: {\n decodeResource?: DecodeResource;\n login: BasicAuthMethods['basic']['login'];\n };\n }\n | {\n type: 'jwt';\n auth:\n | {\n decodeResource?: DecodeResource;\n }\n | {\n verificationFunction: (\n token: string\n ) => Promise<JWTPayload | undefined>;\n };\n }\n | {\n type: 'hmac';\n auth: {\n secretKeys: Record<string, string>;\n verificationFunction: ({\n body,\n path,\n method,\n timestamp,\n nonce,\n signature,\n secretKey\n }: {\n method: string;\n path: string;\n body?: unknown;\n timestamp: Date;\n nonce: string;\n signature: string;\n secretKey: string;\n }) => Promise<boolean | undefined>;\n };\n }\n> {\n let authMethod;\n if (isBasicAuthMethod(auth)) {\n authMethod = {\n type: 'basic' as const,\n auth: {\n decodeResource: auth.decodeResource,\n login: auth.basic.login\n }\n };\n } else if (isJwtAuthMethod(auth)) {\n const jwt = auth.jwt;\n let verificationFunction: (\n token: string\n ) => Promise<JWTPayload | undefined>;\n if ('signatureKey' in jwt) {\n verificationFunction = async (token) => {\n const { payload } = await jwtVerify(\n token,\n new Uint8Array(Buffer.from(jwt.signatureKey))\n );\n return payload;\n };\n } else {\n let jwks: JWK[];\n if ('jwksPublicKeyUrl' in jwt) {\n jwks = await getCachedJwks(jwt.jwksPublicKeyUrl);\n } else if ('jwksPublicKey' in jwt) {\n jwks = [jwt.jwksPublicKey];\n }\n verificationFunction = async (token) => {\n // Keep the last failure so the middleware can log WHY (expired vs\n // bad signature) instead of a bare \"invalid token\". The caller's\n // catch maps any throw to the same 403 as an undefined return.\n let lastError: unknown;\n for (const key of jwks) {\n try {\n const { payload } = await jwtVerify(token, key);\n return payload;\n } catch (error) {\n lastError = error;\n cachedJwks.value = null;\n cachedJwks.lastUpdated = null;\n cachedJwks.ttl = DEFAULT_TTL;\n continue;\n }\n }\n if (lastError !== undefined) throw lastError;\n };\n }\n authMethod = {\n type: 'jwt' as const,\n auth: {\n decodeResource: auth.decodeResource,\n verificationFunction\n }\n };\n } else if (isHmacMethod(auth)) {\n authMethod = {\n type: 'hmac' as const,\n auth: {\n secretKeys: auth.hmac.secretKeys,\n verificationFunction: async ({\n method,\n path,\n body,\n timestamp,\n nonce,\n signature,\n secretKey\n }: {\n method: string;\n path: string;\n body?: unknown;\n timestamp: Date;\n nonce: string;\n signature: string;\n secretKey: string;\n }) => {\n const computedSignature = createHmacToken({\n method,\n path,\n body,\n timestamp,\n nonce,\n secretKey\n });\n\n const isValid = computedSignature === signature;\n\n if (!isValid) {\n const errorInfo = {\n method,\n path,\n timestamp: timestamp.toISOString(),\n nonce,\n receivedSignature: signature,\n computedSignature\n };\n\n openTelemetryCollector?.debug('[HMAC Verification Failed]', {\n ...errorInfo,\n bodyType: body ? typeof body : 'undefined',\n body: body ? safeStringify(body) : 'undefined'\n });\n }\n\n return isValid;\n }\n }\n };\n }\n if (authMethod == null) {\n throw new Error('Invalid auth method');\n }\n\n return authMethod;\n}\n","import { safeStringify } from '@forklaunch/common';\nimport { createHmac } from 'crypto';\n\n/**\n * Creates an HMAC token for a given method, path, body, timestamp, nonce, and secret key.\n * @param method - The HTTP method to use.\n * @param path - The path to use.\n * @param body - The body to use.\n * @param timestamp - The timestamp to use.\n * @param nonce - The nonce to use.\n * @param secretKey - The secret key to use.\n * @returns The HMAC token.\n */\nexport function createHmacToken({\n method,\n path,\n body,\n timestamp,\n nonce,\n secretKey\n}: {\n method: string;\n path: string;\n body?: unknown;\n timestamp: Date;\n nonce: string;\n secretKey: string;\n}) {\n const hmac = createHmac('sha256', secretKey);\n // Buffers and strings are treated as the verbatim request bytes (the\n // content parser captures them on req._rawBody); anything else is signed\n // over its canonical stringification. A client that signs an object and\n // sends its stringification as the wire body therefore verifies cleanly\n // against the server's captured raw bytes.\n const bodyString = body\n ? `${\n Buffer.isBuffer(body)\n ? body.toString('utf8')\n : typeof body === 'string'\n ? body\n : safeStringify(body)\n }\\n`\n : undefined;\n hmac.update(\n `${method}\\n${path}\\n${bodyString}${timestamp.toISOString()}\\n${nonce}`\n );\n return hmac.digest('base64');\n}\n","import { BasicAuthMethods } from '../types/contractDetails.types';\n\nexport function isBasicAuthMethod(\n maybeBasicAuthMethod: unknown\n): maybeBasicAuthMethod is BasicAuthMethods {\n return (\n typeof maybeBasicAuthMethod === 'object' &&\n maybeBasicAuthMethod !== null &&\n 'basic' in maybeBasicAuthMethod &&\n maybeBasicAuthMethod.basic != null\n );\n}\n","import { JwtAuthMethods } from '../types/contractDetails.types';\n\nexport function isJwtAuthMethod(\n maybeJwtAuthMethod: unknown\n): maybeJwtAuthMethod is JwtAuthMethods {\n return (\n typeof maybeJwtAuthMethod === 'object' &&\n maybeJwtAuthMethod !== null &&\n 'jwt' in maybeJwtAuthMethod &&\n maybeJwtAuthMethod.jwt != null\n );\n}\n","export function hasFeatureChecks(maybeFeatureAuth: unknown) {\n return (\n typeof maybeFeatureAuth === 'object' &&\n maybeFeatureAuth !== null &&\n 'requiredFeatures' in maybeFeatureAuth &&\n Array.isArray(maybeFeatureAuth.requiredFeatures) &&\n maybeFeatureAuth.requiredFeatures.length > 0\n );\n}\n","export function hasSubscriptionChecks(maybeSubscriptionAuth: unknown) {\n return (\n typeof maybeSubscriptionAuth === 'object' &&\n maybeSubscriptionAuth !== null &&\n 'requireActiveSubscription' in maybeSubscriptionAuth &&\n maybeSubscriptionAuth.requireActiveSubscription === true\n );\n}\n","import { createHash } from 'crypto';\nimport { decodeJwt, decodeProtectedHeader, errors as joseErrors } from 'jose';\n\n/**\n * What an authorization failure log line may carry about the credential.\n *\n * Never the credential itself. A bearer token is usable until it expires\n * and a Basic header is a password, so neither belongs in a log stream that\n * outlives the request. What support actually needs is why it failed, who\n * it claimed to be, and a way to tell two failures from one caller apart.\n */\nexport type AuthLogContext = {\n /** Whether an Authorization value was present at all. */\n hasToken: boolean;\n /**\n * First 8 hex chars of sha256(header value). Correlates retries of one\n * token and lets a caller match a token they hold against a log line\n * without the log holding the token. Not reversible.\n */\n tokenFingerprint?: string;\n /**\n * Decoded, NOT verified, JWT claims. On a failed verification these are\n * whatever the caller wrote, so they are labelled claimed rather than\n * user and must never be treated as identity. `email` is left out on\n * purpose: `sub` identifies the account without putting PII in logs.\n */\n claimed?: {\n sub?: string;\n organizationId?: string;\n iss?: string;\n exp?: number;\n kid?: string;\n };\n};\n\nconst FINGERPRINT_LENGTH = 8;\nconst MAX_CLAIM_LENGTH = 128;\n\nfunction bounded(value: unknown): string | undefined {\n return typeof value === 'string' && value.length > 0\n ? value.slice(0, MAX_CLAIM_LENGTH)\n : undefined;\n}\n\n/**\n * Builds the loggable context for an Authorization header value. Accepts\n * the full header value (`Bearer eyJ…`, `Basic …`, `HMAC …`) or a bare\n * token; JWT claims are only attempted when the value looks like a JWT.\n */\nexport function authLogContext(headerValue: unknown): AuthLogContext {\n if (typeof headerValue !== 'string' || headerValue.length === 0) {\n return { hasToken: false };\n }\n\n const context: AuthLogContext = {\n hasToken: true,\n tokenFingerprint: createHash('sha256')\n .update(headerValue)\n .digest('hex')\n .slice(0, FINGERPRINT_LENGTH)\n };\n\n const parts = headerValue.trim().split(/\\s+/);\n const candidate = parts[parts.length - 1];\n if (candidate.split('.').length !== 3) {\n return context;\n }\n\n try {\n const payload = decodeJwt(candidate);\n const header = decodeProtectedHeader(candidate);\n context.claimed = {\n sub: bounded(payload.sub),\n organizationId: bounded(payload.organizationId),\n iss: bounded(payload.iss),\n exp: typeof payload.exp === 'number' ? payload.exp : undefined,\n kid: bounded(header.kid)\n };\n } catch {\n // Not a decodable JWT; the fingerprint is all we can offer.\n }\n\n return context;\n}\n\n/**\n * A stable, short reason for a JWT verification failure, derived from the\n * jose error class. This is the field that was missing from the logs: an\n * expired token and a forged one used to produce identical lines.\n */\nexport function jwtFailureReason(error: unknown): string {\n if (error instanceof joseErrors.JWTExpired) return 'jwt_expired';\n if (error instanceof joseErrors.JWTClaimValidationFailed) {\n return `jwt_claim_${error.claim}`;\n }\n if (error instanceof joseErrors.JWSSignatureVerificationFailed) {\n return 'jwt_bad_signature';\n }\n if (error instanceof joseErrors.JWKSNoMatchingKey) return 'jwks_no_key';\n if (error instanceof joseErrors.JWKSTimeout) return 'jwks_unavailable';\n if (\n error instanceof joseErrors.JWTInvalid ||\n error instanceof joseErrors.JWSInvalid\n ) {\n return 'jwt_malformed';\n }\n if (error instanceof joseErrors.JOSEError) return error.code.toLowerCase();\n return 'unknown';\n}\n","import { getEnvVar } from '@forklaunch/common';\nimport { AnySchemaValidator } from '@forklaunch/validator';\nimport {\n ATTR_API_NAME,\n ATTR_APPLICATION_ID,\n ATTR_HTTP_REQUEST_METHOD,\n ATTR_HTTP_RESPONSE_STATUS_CODE,\n ATTR_HTTP_ROUTE,\n ATTR_SERVICE_NAME\n} from '../../telemetry/constants';\nimport {\n httpServerDurationHistogram,\n OpenTelemetryCollector\n} from '../../telemetry/openTelemetryCollector';\nimport {\n ExpressLikeSchemaHandler,\n ForklaunchNextFunction\n} from '../../types/apiDefinition.types';\nimport {\n Body,\n HeadersObject,\n HttpContractDetails,\n Method,\n ParamsObject,\n PathParamHttpContractDetails,\n QueryObject,\n ResponseCompiledSchema,\n ResponsesObject,\n SessionObject,\n VersionSchema\n} from '../../types/contractDetails.types';\nimport { ExpressLikeRouterOptions } from '../../types/expressLikeOptions';\nimport { MetricsDefinition } from '../../types/openTelemetryCollector.types';\n\n/**\n * Middleware to enrich the request details with contract details.\n *\n * @template SV - A type that extends AnySchemaValidator.\n * @template Request - A type that extends ForklaunchRequest.\n * @template Response - A type that extends ForklaunchResponse.\n * @template NextFunction - A type that extends ForklaunchNextFunction.\n * @param {PathParamHttpContractDetails<SV> | HttpContractDetails<SV>} contractDetails - The contract details.\n * @returns {Function} - Middleware function to enrich request details.\n */\nexport function enrichDetails<\n SV extends AnySchemaValidator,\n ContractMethod extends Method,\n P extends ParamsObject<SV>,\n ResBodyMap extends ResponsesObject<SV>,\n ReqBody extends Body<SV>,\n ReqQuery extends QueryObject<SV>,\n ReqHeaders extends HeadersObject<SV>,\n ResHeaders extends HeadersObject<SV>,\n LocalsObj extends Record<string, unknown>,\n VersionedApi extends VersionSchema<SV, ContractMethod>,\n SessionSchema extends SessionObject<SV>\n>(\n path: string,\n contractDetails: HttpContractDetails<SV> | PathParamHttpContractDetails<SV>,\n requestSchema: unknown | Record<string, unknown>,\n responseSchemas:\n ResponseCompiledSchema | Record<string, ResponseCompiledSchema>,\n openTelemetryCollector?: OpenTelemetryCollector<MetricsDefinition>,\n globalOptions?: () => ExpressLikeRouterOptions<SV, SessionSchema> | undefined\n): ExpressLikeSchemaHandler<\n SV,\n P,\n ResBodyMap,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n ResHeaders,\n LocalsObj,\n VersionedApi,\n SessionSchema,\n unknown,\n unknown,\n ForklaunchNextFunction\n> {\n return (req, res, next?) => {\n req.originalPath = path;\n req.contractDetails = contractDetails;\n req.requestSchema = requestSchema;\n res.responseSchemas = responseSchemas;\n req.openTelemetryCollector = openTelemetryCollector;\n req._globalOptions = globalOptions ?? (() => undefined);\n\n req.context?.span?.setAttribute(ATTR_API_NAME, req.contractDetails?.name);\n const startTime = process.hrtime();\n\n res.on('finish', () => {\n const [seconds, nanoseconds] = process.hrtime(startTime);\n const durationMs = seconds + nanoseconds / 1000000000;\n\n httpServerDurationHistogram.record(durationMs, {\n [ATTR_SERVICE_NAME]: getEnvVar('OTEL_SERVICE_NAME') || 'unknown',\n [ATTR_APPLICATION_ID]: getEnvVar('OTEL_APPLICATION_ID'),\n [ATTR_API_NAME]: req.contractDetails?.name || 'unknown',\n [ATTR_HTTP_REQUEST_METHOD]: req.method,\n [ATTR_HTTP_ROUTE]: req.originalPath || 'unknown',\n [ATTR_HTTP_RESPONSE_STATUS_CODE]: Number(res.statusCode)\n });\n });\n\n next?.();\n };\n}\n","import { isRecord } from '@forklaunch/common';\nimport {\n AnySchemaValidator,\n ParseResult,\n prettyPrintParseErrors,\n SchemaValidator\n} from '@forklaunch/validator';\nimport { ParsedQs } from 'qs';\nimport { hasSend } from '../../guards/hasSend';\nimport { isRequestShape } from '../../guards/isRequestShape';\nimport {\n ForklaunchNextFunction,\n ForklaunchRequest,\n ForklaunchResponse,\n VersionedRequests\n} from '../../types/apiDefinition.types';\nimport { ParamsDictionary } from '../../types/contractDetails.types';\n\n/**\n * Pre-handler function to parse and validate input.\n *\n * @template SV - A type that extends AnySchemaValidator.\n * @template Request - A type that extends ForklaunchRequest.\n * @template Response - A type that extends ForklaunchResponse.\n * @template NextFunction - A type that extends ForklaunchNextFunction.\n * @param {Request} req - The request object.\n * @param {Response} res - The response object.\n * @param {NextFunction} [next] - The next middleware function.\n */\nexport function parse<\n SV extends AnySchemaValidator,\n P extends ParamsDictionary,\n ResBodyMap extends Record<number, unknown>,\n ReqBody extends Record<string, unknown>,\n ReqQuery extends ParsedQs,\n ReqHeaders extends Record<string, string>,\n ResHeaders extends Record<string, unknown>,\n LocalsObj extends Record<string, unknown>,\n VersionedReqs extends VersionedRequests,\n SessionSchema extends Record<string, unknown>\n>(\n req: ForklaunchRequest<\n SV,\n P,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n Extract<keyof VersionedReqs, string>,\n SessionSchema\n >,\n res: ForklaunchResponse<\n unknown,\n ResBodyMap,\n ResHeaders,\n LocalsObj,\n Extract<keyof VersionedReqs, string>\n >,\n next?: ForklaunchNextFunction\n) {\n const globalOptions = req._globalOptions?.();\n const collapsedOptions =\n req.contractDetails.options?.requestValidation ??\n (globalOptions?.validation === false\n ? 'none'\n : globalOptions?.validation?.request);\n\n // Preserve the pre-validation body for HMAC verification when the content\n // parser did not already capture the exact request bytes. Never clobber a\n // parser-captured _rawBody: that value is the raw payload as sent by the\n // client, which signature verification (Stripe et al.) must be computed\n // over — req.body may already be a parsed object here.\n req._rawBody ??= req.body;\n\n const request = {\n params: req.params,\n query: req.query,\n headers: req.headers,\n body: req.body\n };\n\n const schemaValidator = req.schemaValidator as SchemaValidator;\n\n let matchedVersions;\n\n let parsedRequest: ParseResult<object> | undefined;\n let collectedParseErrors: string | undefined;\n\n if (req.contractDetails.versions) {\n if (isRecord(req.requestSchema)) {\n let runningParseErrors: string = '';\n matchedVersions = [];\n\n Object.entries(req.requestSchema).forEach(([version, schema]) => {\n const parsingResult = schemaValidator.parse(schema, request);\n\n if (parsingResult.ok) {\n parsedRequest = parsingResult;\n matchedVersions.push(version);\n req.version = version as Extract<keyof VersionedReqs, string>;\n res.version = req.version;\n } else {\n runningParseErrors += prettyPrintParseErrors(\n parsingResult.errors,\n `Version ${version} request`\n );\n }\n });\n\n if (!parsedRequest) {\n parsedRequest = {\n ok: false,\n errors: []\n };\n collectedParseErrors = runningParseErrors;\n }\n } else {\n req.version = Object.keys(req.contractDetails.versions).pop() as Extract<\n keyof VersionedReqs,\n string\n >;\n res.version = req.version;\n\n parsedRequest = {\n ok: true,\n value: request\n };\n\n matchedVersions = Object.keys(req.contractDetails.versions);\n }\n } else {\n const parsingResult = schemaValidator.parse(req.requestSchema, request);\n\n parsedRequest = parsingResult;\n\n matchedVersions = 0;\n }\n\n if (\n parsedRequest.ok &&\n isRequestShape<P, ReqHeaders, ReqQuery, ReqBody>(parsedRequest.value)\n ) {\n req.body = parsedRequest.value.body;\n req.params = parsedRequest.value.params;\n Object.defineProperty(req, 'query', {\n value: parsedRequest.value.query,\n writable: false,\n enumerable: true,\n configurable: false\n });\n const parsedHeaders = parsedRequest.value.headers ?? {};\n req.headers = Object.keys(req.headers).reduce<Record<string, unknown>>(\n (acc, key) => {\n if (parsedHeaders?.[key]) {\n acc[key] = parsedHeaders[key];\n } else {\n acc[key] = req.headers[key];\n }\n return acc;\n },\n {}\n ) as ReqHeaders;\n }\n if (!parsedRequest.ok) {\n switch (collapsedOptions) {\n default:\n case undefined:\n case 'error':\n res.type('application/json');\n res.status(400);\n if (hasSend(res)) {\n res.send(\n `${\n collectedParseErrors ??\n prettyPrintParseErrors(parsedRequest.errors, 'Request')\n }\\n\\nCorrelation id: ${\n req.context.correlationId ?? 'No correlation ID'\n }`\n );\n } else {\n next?.(new Error('Request is not sendable.'));\n }\n return;\n case 'warning':\n req.openTelemetryCollector?.warn(\n collectedParseErrors ??\n prettyPrintParseErrors(parsedRequest.errors, 'Request')\n );\n break;\n case 'none':\n break;\n }\n }\n\n req._parsedVersions = matchedVersions;\n next?.();\n}\n","/**\n * Type guard that checks if an object has a `send` method.\n *\n * @param res - The object to check for the presence of a `send` method\n * @returns A type predicate indicating whether the object has a `send` method\n *\n * @example\n * ```ts\n * if (hasSend(response)) {\n * response.send('Hello World');\n * }\n * ```\n */\nexport function hasSend(\n res: unknown\n): res is { send: (body: unknown) => void } {\n return typeof res === 'object' && res !== null && 'send' in res;\n}\n","import { ResponseShape } from '../types/apiDefinition.types';\n\nexport function isRequestShape<Params, Headers, Query, Body>(\n maybeResponseShape: object | undefined\n): maybeResponseShape is ResponseShape<Params, Headers, Query, Body> {\n return (\n maybeResponseShape != null &&\n ('body' in maybeResponseShape ||\n 'query' in maybeResponseShape ||\n 'params' in maybeResponseShape ||\n 'headers' in maybeResponseShape)\n );\n}\n","import { EmptyObject } from '@forklaunch/common';\nimport { AnySchemaValidator } from '@forklaunch/validator';\nimport { ExpressLikeRouter } from '../interfaces/expressLikeRouter.interface';\nimport { cors } from '../middleware/request/cors.middleware';\nimport { ForklaunchExpressLikeRouter } from '../router/expressLikeRouter';\nimport { OpenTelemetryCollector } from '../telemetry/openTelemetryCollector';\nimport { SessionObject } from '../types/contractDetails.types';\nimport { ExpressLikeApplicationOptions } from '../types/expressLikeOptions';\nimport { MetricsDefinition } from '../types/openTelemetryCollector.types';\n\n/**\n * ForklaunchExpressLikeApplication class that sets up routes and middleware for an Express-like application, for use with controller/routes pattern.\n *\n * @template SV - A type that extends AnySchemaValidator.\n * @template Server - The server type.\n */\nexport abstract class ForklaunchExpressLikeApplication<\n SV extends AnySchemaValidator,\n Server extends ExpressLikeRouter<RouterHandler, Server>,\n RouterHandler,\n BaseRequest,\n BaseResponse,\n NextFunction,\n Session extends SessionObject<SV>,\n FetchMap extends Record<string, unknown> = EmptyObject,\n Sdk extends Record<string, unknown> = EmptyObject\n> extends ForklaunchExpressLikeRouter<\n SV,\n '/',\n RouterHandler,\n Server,\n BaseRequest,\n BaseResponse,\n NextFunction,\n Session,\n FetchMap,\n Sdk\n> {\n /**\n * Creates an instance of the Application class.\n *\n * @param {SV} schemaValidator - The schema validator.\n */\n constructor(\n readonly schemaValidator: SV,\n readonly internal: Server,\n readonly postEnrichMiddleware: RouterHandler[],\n readonly openTelemetryCollector: OpenTelemetryCollector<MetricsDefinition>,\n readonly appOptions?: ExpressLikeApplicationOptions<SV, Session>\n ) {\n super(\n '/',\n schemaValidator,\n internal,\n postEnrichMiddleware,\n openTelemetryCollector,\n {\n ...appOptions,\n openapi: appOptions?.openapi !== false,\n mcp: appOptions?.mcp !== false\n }\n );\n\n this.internal.use(cors(this.appOptions?.cors ?? {}) as RouterHandler);\n }\n\n /**\n * Validates all registered routes across the app and all mounted routers.\n * Call this at the start of listen() to fail fast at startup.\n */\n protected validateAllRoutes() {\n this.validateSurfacingFunctions();\n }\n\n abstract listen(...args: unknown[]): void;\n}\n","import * as net from 'net';\n\nexport function isPortBound(\n port: number,\n host: string = 'localhost'\n): Promise<boolean> {\n return new Promise((resolve) => {\n const socket = new net.Socket();\n\n socket.setTimeout(1000);\n\n socket.on('connect', () => {\n socket.destroy();\n resolve(true);\n });\n\n socket.on('timeout', () => {\n socket.destroy();\n resolve(false);\n });\n\n socket.on('error', () => {\n resolve(false);\n });\n\n socket.connect(port, host);\n });\n}\n","import { randomUUID } from 'crypto';\nimport { createHmacToken } from './createHmacToken';\n\n/**\n * Generate HMAC authorization headers for service-to-service authentication.\n *\n * @param secretKey - The shared HMAC secret key\n * @param method - HTTP method (GET, POST, etc.)\n * @param path - The API path\n * @param body - Optional request body\n * @param keyId - Optional key identifier (defaults to 'default')\n * @returns Authorization header object\n *\n * @example\n * ```typescript\n * const headers = generateHmacAuthHeaders({\n * secretKey: 'my-secret-key',\n * method: 'POST',\n * path: '/api/users',\n * body: { name: 'John' }\n * });\n * // headers.authorization = 'HMAC keyId=default ts=2024-01-16T12:00:00.000Z nonce=... signature=...'\n * ```\n */\nexport function generateHmacAuthHeaders({\n secretKey,\n method,\n path,\n body,\n keyId = 'default'\n}: {\n secretKey: string;\n method: string;\n path: string;\n body?: unknown;\n keyId?: string;\n}): {\n authorization: `HMAC keyId=${string} ts=${string} nonce=${string} signature=${string}`;\n} {\n const timestamp = new Date();\n const nonce = randomUUID();\n\n const signature = createHmacToken({\n secretKey,\n method,\n path,\n timestamp,\n nonce,\n body\n });\n\n return {\n authorization: `HMAC keyId=${keyId} ts=${timestamp.toISOString()} nonce=${nonce} signature=${signature}`\n };\n}\n","import { createHmacToken } from './createHmacToken';\nimport { generateHmacAuthHeaders } from './generateHmacAuthHeaders';\nimport { timingSafeEqual } from 'crypto';\n\n/**\n * The instance gateway: how a managed instance reaches platform-held services\n * (models, payments, email, SMS, WhatsApp, voice) without holding a vendor\n * credential, and how the platform delivers vendor events back to it.\n *\n * Outbound, every request is signed with the instance's own HMAC key\n * (`INSTANCE_HMAC_KEY`, key id `INSTANCE_ID`) over the router-relative path,\n * with a timestamp and a single-use nonce; the platform checks the signature,\n * the product's limits and the instance's own vendor account, then calls the\n * vendor with credentials that never leave it.\n *\n * Inbound, the platform POSTs events (a payment succeeded, an email bounced, a\n * text arrived) to `/platform-events/<feature>` on the service that declared\n * the capability, signed with the same instance key under key id `platform`.\n * `verifyPlatformEvent` checks that signature, the timestamp and the nonce.\n *\n * The platform injects `PLATFORM_GATEWAY_URL`, `INSTANCE_ID` and\n * `INSTANCE_HMAC_KEY` into a hosted instance. Their absence means the service\n * is not running in managed mode, and a client refuses to be created rather\n * than failing on its first call.\n */\n\n/** Where the gateway router is mounted on the platform service. */\nexport const INSTANCE_GATEWAY_MOUNT = '/instance-gateway';\n\n/** The key id the platform signs events with. */\nexport const PLATFORM_EVENT_KEY_ID = 'platform';\n\n/** Where a service receives platform events, per feature. */\nexport const PLATFORM_EVENTS_PATH = '/platform-events';\n\nconst MAX_SKEW_MS = 5 * 60 * 1000;\n\nexport interface InstanceGatewayOptions {\n /** Platform base URL. Default: `PLATFORM_GATEWAY_URL`. */\n gatewayUrl?: string;\n /** This instance's id. Default: `INSTANCE_ID`. */\n instanceId?: string;\n /** This instance's HMAC key. Default: `INSTANCE_HMAC_KEY`. */\n hmacKey?: string;\n fetch?: typeof fetch;\n}\n\n/** A refusal or failure from the gateway, with the status it answered. */\nexport class InstanceGatewayRequestError extends Error {\n override readonly name: string = 'InstanceGatewayRequestError';\n constructor(\n readonly status: number,\n message: string,\n /** Seconds to wait before retrying, on a 429. */\n readonly retryAfterSeconds?: number\n ) {\n super(message);\n }\n}\n\nexport interface InstanceGatewayTransport {\n readonly instanceId: string;\n /** A signed request; throws `InstanceGatewayRequestError` on a non-2xx. */\n request(\n method: 'GET' | 'POST' | 'PUT' | 'DELETE',\n route: string,\n body?: Record<string, unknown>,\n options?: { signal?: AbortSignal; headers?: Record<string, string> }\n ): Promise<Response>;\n /** `request`, then the JSON body. */\n json<T>(\n method: 'GET' | 'POST' | 'PUT' | 'DELETE',\n route: string,\n body?: Record<string, unknown>,\n options?: { signal?: AbortSignal; headers?: Record<string, string> }\n ): Promise<T>;\n}\n\n/** Resolve the managed-mode settings, or explain which are missing. */\nexport function instanceGatewaySettings(\n options: InstanceGatewayOptions = {},\n feature = 'The instance gateway'\n): { gatewayUrl: string; instanceId: string; hmacKey: string } {\n const gatewayUrl = options.gatewayUrl ?? process.env.PLATFORM_GATEWAY_URL;\n const instanceId = options.instanceId ?? process.env.INSTANCE_ID;\n const hmacKey = options.hmacKey ?? process.env.INSTANCE_HMAC_KEY;\n if (!gatewayUrl || !instanceId || !hmacKey) {\n throw new Error(\n `${feature} is only available to instances hosted in managed mode: ` +\n 'PLATFORM_GATEWAY_URL, INSTANCE_ID and INSTANCE_HMAC_KEY must be set'\n );\n }\n return { gatewayUrl, instanceId, hmacKey };\n}\n\n/** Whether this process runs as a managed instance. */\nexport function isManagedInstance(\n env: Record<string, string | undefined> = process.env\n): boolean {\n return Boolean(\n env.PLATFORM_GATEWAY_URL && env.INSTANCE_ID && env.INSTANCE_HMAC_KEY\n );\n}\n\nfunction trimTrailingSlashes(value: string): string {\n // Without a regex: `/\\/+$/` backtracks on long runs.\n let end = value.length;\n while (end > 0 && value[end - 1] === '/') end -= 1;\n return value.slice(0, end);\n}\n\n/** A signed transport to the instance gateway. */\nexport function createInstanceGatewayTransport(\n options: InstanceGatewayOptions = {},\n feature?: string\n): InstanceGatewayTransport {\n const { gatewayUrl, instanceId, hmacKey } = instanceGatewaySettings(\n options,\n feature\n );\n const fetchImpl = options.fetch ?? fetch;\n const base = trimTrailingSlashes(gatewayUrl);\n\n const request: InstanceGatewayTransport['request'] = async (\n method,\n route,\n body,\n requestOptions = {}\n ) => {\n // The gateway verifies the router-relative path, and the body as parsed.\n const { authorization } = generateHmacAuthHeaders({\n secretKey: hmacKey,\n method,\n path: route,\n body,\n keyId: instanceId\n });\n const response = await fetchImpl(`${base}${INSTANCE_GATEWAY_MOUNT}${route}`, {\n method,\n headers: {\n ...requestOptions.headers,\n authorization,\n ...(body ? { 'content-type': 'application/json' } : {})\n },\n body: body ? JSON.stringify(body) : undefined,\n signal: requestOptions.signal\n });\n if (!response.ok) {\n const message = (await response.text().catch(() => '')).trim();\n const retryAfter = Number(response.headers.get('retry-after'));\n throw new InstanceGatewayRequestError(\n response.status,\n message || `Instance gateway answered ${response.status}`,\n Number.isFinite(retryAfter) && retryAfter > 0 ? retryAfter : undefined\n );\n }\n return response;\n };\n\n return {\n instanceId,\n request,\n async json<T>(\n method: 'GET' | 'POST' | 'PUT' | 'DELETE',\n route: string,\n body?: Record<string, unknown>,\n requestOptions?: { signal?: AbortSignal; headers?: Record<string, string> }\n ): Promise<T> {\n return (await (\n await request(method, route, body, requestOptions)\n ).json()) as T;\n }\n };\n}\n\n/** An event the platform delivered to this instance. */\nexport interface PlatformEvent<Data = Record<string, unknown>> {\n /** Unique per event; deliveries can repeat, so handlers dedupe on it. */\n id: string;\n /** The capability it belongs to: payments, email, sms, whatsapp, voice. */\n feature: string;\n /** e.g. `checkout.session.completed`, `email.bounced`, `sms.received`. */\n type: string;\n occurredAt: string;\n data: Data;\n}\n\nexport class PlatformEventVerificationError extends Error {\n override readonly name = 'PlatformEventVerificationError';\n}\n\nconst seenEventNonces = new Map<string, number>();\n\n/**\n * Verify an event the platform delivered and return it.\n *\n * `path` is the path the request arrived on (`/platform-events/payments`);\n * `rawBody` is the exact request body (a string or Buffer) — pass the raw\n * bytes when the framework captured them, else the parsed body. Throws\n * `PlatformEventVerificationError` for a missing, stale, forged or replayed\n * delivery; answer 401 then, and the platform retries.\n */\nexport function verifyPlatformEvent<Data = Record<string, unknown>>(\n request: {\n method: string;\n path: string;\n headers: Record<string, string | string[] | undefined>;\n body: unknown;\n },\n options: { hmacKey?: string; now?: () => number } = {}\n): PlatformEvent<Data> {\n const hmacKey = options.hmacKey ?? process.env.INSTANCE_HMAC_KEY;\n if (!hmacKey) {\n throw new PlatformEventVerificationError(\n 'INSTANCE_HMAC_KEY is not set: this service is not a managed instance'\n );\n }\n const header = request.headers.authorization ?? request.headers.Authorization;\n const value = Array.isArray(header) ? header[0] : header;\n const match =\n /^HMAC keyId=(\\S+) ts=(\\S+) nonce=(\\S+) signature=(\\S+)$/.exec(\n value ?? ''\n );\n if (!match) {\n throw new PlatformEventVerificationError(\n 'Missing or malformed HMAC authorization'\n );\n }\n const [, keyId, ts, nonce, signature] = match;\n if (keyId !== PLATFORM_EVENT_KEY_ID) {\n throw new PlatformEventVerificationError('Not signed by the platform');\n }\n const timestamp = new Date(ts);\n const now = (options.now ?? Date.now)();\n if (\n Number.isNaN(timestamp.getTime()) ||\n Math.abs(now - timestamp.getTime()) > MAX_SKEW_MS\n ) {\n throw new PlatformEventVerificationError('Stale or invalid timestamp');\n }\n const expected = Buffer.from(\n createHmacToken({\n secretKey: hmacKey,\n method: request.method.toUpperCase(),\n path: request.path,\n body: request.body,\n timestamp,\n nonce\n })\n );\n const received = Buffer.from(signature);\n if (\n expected.length !== received.length ||\n !timingSafeEqual(expected, received)\n ) {\n throw new PlatformEventVerificationError('Invalid signature');\n }\n for (const [seen, at] of seenEventNonces) {\n if (now - at > MAX_SKEW_MS) seenEventNonces.delete(seen);\n }\n if (seenEventNonces.has(nonce)) {\n throw new PlatformEventVerificationError('Replayed delivery');\n }\n seenEventNonces.set(nonce, now);\n\n const parsed =\n typeof request.body === 'string' || Buffer.isBuffer(request.body)\n ? JSON.parse(request.body.toString())\n : request.body;\n const event = parsed as Partial<PlatformEvent<Data>>;\n if (\n !event ||\n typeof event.id !== 'string' ||\n typeof event.type !== 'string' ||\n typeof event.feature !== 'string'\n ) {\n throw new PlatformEventVerificationError('Body is not a platform event');\n }\n return event as PlatformEvent<Data>;\n}\n\n/**\n * Sign an event delivery the way the platform does. For tests and the local\n * gateway mock; the platform has its own copy.\n */\nexport function signPlatformEvent(params: {\n hmacKey: string;\n path: string;\n body: string;\n}): { authorization: string } {\n return generateHmacAuthHeaders({\n secretKey: params.hmacKey,\n method: 'POST',\n path: params.path,\n body: params.body,\n keyId: PLATFORM_EVENT_KEY_ID\n });\n}\n","import {\n createInstanceGatewayTransport,\n InstanceGatewayRequestError\n} from './instanceGateway';\n\n/**\n * Client for the ForkLaunch model gateway, used from inside a managed\n * instance.\n *\n * A managed instance calls platform-hosted AI models (Azure AI Foundry)\n * without holding a provider key: each request is signed with the\n * instance's own HMAC key, and the platform enforces the product's model\n * allowlist, monthly token budget and rate limit. For a HIPAA product the\n * platform only offers models covered by its BAA.\n *\n * The platform injects everything this needs into a hosted instance:\n * `PLATFORM_GATEWAY_URL` (the platform's public base), `INSTANCE_ID` and\n * `INSTANCE_HMAC_KEY`. Their absence means the instance is not hosted in\n * managed mode, and the client refuses to be created rather than failing on\n * the first call.\n *\n * @example\n * const models = createModelGatewayClient();\n * const reply = await models.chat.completions.create({\n * model: 'terra',\n * messages: [{ role: 'user', content: 'Summarize this intake form: …' }]\n * });\n * for await (const chunk of models.chat.completions.stream({ model: 'luna', messages })) {\n * process.stdout.write(chunk.choices[0]?.delta?.content ?? '');\n * }\n */\n\nexport interface ModelGatewayClientOptions {\n /** Platform base URL. Default: `PLATFORM_GATEWAY_URL`. */\n gatewayUrl?: string;\n /** This instance's id. Default: `INSTANCE_ID`. */\n instanceId?: string;\n /** This instance's HMAC key. Default: `INSTANCE_HMAC_KEY`. */\n hmacKey?: string;\n fetch?: typeof fetch;\n}\n\n/** An OpenAI-style chat message. */\nexport interface GatewayChatMessage {\n role: 'system' | 'developer' | 'user' | 'assistant' | 'tool';\n content: unknown;\n [key: string]: unknown;\n}\n\n/** An OpenAI-compatible chat completions request; `model` is a catalog alias. */\nexport interface GatewayChatRequest {\n model: string;\n messages: GatewayChatMessage[];\n temperature?: number;\n top_p?: number;\n max_tokens?: number;\n max_completion_tokens?: number;\n response_format?: unknown;\n tools?: unknown[];\n tool_choice?: unknown;\n parallel_tool_calls?: boolean;\n stop?: unknown;\n seed?: number;\n presence_penalty?: number;\n frequency_penalty?: number;\n reasoning_effort?: string;\n}\n\nexport interface GatewayChatCompletion {\n id: string;\n object: string;\n created: number;\n model: string;\n choices: {\n index: number;\n message: { role: string; content: string | null; [key: string]: unknown };\n finish_reason: string | null;\n [key: string]: unknown;\n }[];\n usage?: {\n prompt_tokens: number;\n completion_tokens: number;\n total_tokens: number;\n };\n [key: string]: unknown;\n}\n\nexport interface GatewayChatChunk {\n id: string;\n object: string;\n model: string;\n choices: {\n index: number;\n delta: { role?: string; content?: string | null; [key: string]: unknown };\n finish_reason?: string | null;\n }[];\n usage?: GatewayChatCompletion['usage'];\n [key: string]: unknown;\n}\n\nexport interface GatewayModels {\n models: { id: string; baa: boolean }[];\n monthlyTokenBudget: number;\n tokensUsedThisMonth: number;\n requestsPerMinute: number;\n withheldForHipaa?: string[];\n}\n\n/** A refusal or failure from the gateway, with the status it answered. */\nexport class ModelGatewayRequestError extends InstanceGatewayRequestError {\n override readonly name = 'ModelGatewayRequestError' as const;\n}\n\nexport interface ModelGatewayClient {\n /** The models this instance may call, and where its monthly budget stands. */\n models(): Promise<GatewayModels>;\n chat: {\n completions: {\n create(request: GatewayChatRequest): Promise<GatewayChatCompletion>;\n stream(\n request: GatewayChatRequest,\n options?: { signal?: AbortSignal }\n ): AsyncGenerator<GatewayChatChunk>;\n };\n };\n}\n\nexport function createModelGatewayClient(\n options: ModelGatewayClientOptions = {}\n): ModelGatewayClient {\n const transport = createInstanceGatewayTransport(options, 'The model gateway');\n\n async function send(\n method: 'GET' | 'POST',\n route: string,\n body?: Record<string, unknown>,\n signal?: AbortSignal\n ): Promise<Response> {\n try {\n return await transport.request(method, route, body, { signal });\n } catch (error) {\n if (error instanceof InstanceGatewayRequestError) {\n throw new ModelGatewayRequestError(\n error.status,\n error.message,\n error.retryAfterSeconds\n );\n }\n throw error;\n }\n }\n\n return {\n async models() {\n return (await (await send('GET', '/models')).json()) as GatewayModels;\n },\n chat: {\n completions: {\n async create(request) {\n const response = await send(\n 'POST',\n '/models/chat/completions',\n request as unknown as Record<string, unknown>\n );\n return (await response.json()) as GatewayChatCompletion;\n },\n async *stream(request, streamOptions = {}) {\n const response = await send(\n 'POST',\n '/models/chat/completions/stream',\n request as unknown as Record<string, unknown>,\n streamOptions.signal\n );\n if (!response.body) return;\n for await (const data of sseData(response.body)) {\n if (data === '[DONE]') return;\n try {\n yield JSON.parse(data) as GatewayChatChunk;\n } catch {\n // not a chunk; skip it\n }\n }\n }\n }\n }\n };\n}\n\n/** The `data:` payloads of a server-sent-event stream, in order. */\nasync function* sseData(\n stream: ReadableStream<Uint8Array>\n): AsyncGenerator<string> {\n const decoder = new TextDecoder();\n let buffer = '';\n const reader = stream.getReader();\n try {\n for (;;) {\n const { value, done } = await reader.read();\n if (done) break;\n buffer += decoder.decode(value, { stream: true });\n let boundary: number;\n while ((boundary = buffer.search(/\\r?\\n\\r?\\n/)) !== -1) {\n const event = buffer.slice(0, boundary);\n buffer = buffer.slice(boundary).replace(/^\\r?\\n\\r?\\n/, '');\n const data = event\n .split(/\\r?\\n/)\n .filter((line) => line.startsWith('data:'))\n .map((line) => line.slice(5).trimStart())\n .join('\\n');\n if (data) yield data;\n }\n }\n const tail = buffer.trim();\n if (tail.startsWith('data:')) yield tail.slice(5).trimStart();\n } finally {\n reader.releaseLock();\n }\n}\n","import {\n createInstanceGatewayTransport,\n InstanceGatewayRequestError\n} from './instanceGateway';\nimport {\n ModelGatewayRequestError,\n type GatewayChatCompletion,\n type GatewayChatRequest,\n type ModelGatewayClientOptions\n} from './modelGatewayClient';\n\n/** A local preview's issued ceilings, not a managed product's monthly usage. */\nexport interface GatewayPreviewModels {\n models: { id: string }[];\n preview: {\n /** Capability expiration, in Unix milliseconds. */\n expiresAt: number;\n /** Initial request ceiling; this is not a remaining-request count. */\n maxCalls: number;\n /** Initial conservative allowance units, not billable or monthly tokens. */\n maxUnits: number;\n };\n}\n\n/** Preview relays may omit a provider timestamp; they must not invent one. */\nexport interface GatewayPreviewChatCompletion extends Pick<\n GatewayChatCompletion,\n 'id' | 'object' | 'model' | 'choices' | 'usage'\n> {\n created?: number;\n [key: string]: unknown;\n}\n\nexport interface PreviewModelGatewayClient {\n models(): Promise<GatewayPreviewModels>;\n chat: {\n completions: {\n create(\n request: GatewayChatRequest\n ): Promise<GatewayPreviewChatCompletion>;\n };\n };\n}\n\nfunction record(value: unknown): value is Record<string, unknown> {\n return !!value && typeof value === 'object' && !Array.isArray(value);\n}\nfunction invalidCatalog(): never {\n throw new ModelGatewayRequestError(\n 502,\n 'The local preview model catalog is invalid or expired.'\n );\n}\nfunction previewCatalog(raw: unknown): GatewayPreviewModels {\n if (!record(raw) || !record(raw.preview)) return invalidCatalog();\n const preview = raw.preview;\n if (\n Object.keys(raw).some((key) => !['models', 'preview'].includes(key)) ||\n Object.keys(preview).some(\n (key) => !['expiresAt', 'maxCalls', 'maxUnits'].includes(key)\n ) ||\n !Array.isArray(raw.models) ||\n raw.models.length !== 1 ||\n !record(raw.models[0]) ||\n Object.keys(raw.models[0]).some((key) => key !== 'id') ||\n typeof raw.models[0].id !== 'string' ||\n !/^[\\w.:-]{1,160}$/.test(raw.models[0].id) ||\n typeof preview.expiresAt !== 'number' ||\n !Number.isSafeInteger(preview.expiresAt) ||\n preview.expiresAt <= Date.now() ||\n preview.expiresAt > Date.now() + 15 * 60_000 ||\n typeof preview.maxCalls !== 'number' ||\n !Number.isSafeInteger(preview.maxCalls) ||\n preview.maxCalls < 1 ||\n preview.maxCalls > 20 ||\n typeof preview.maxUnits !== 'number' ||\n !Number.isSafeInteger(preview.maxUnits) ||\n preview.maxUnits < 1 ||\n preview.maxUnits > 100_000\n )\n return invalidCatalog();\n return {\n models: [{ id: raw.models[0].id }],\n preview: {\n expiresAt: preview.expiresAt,\n maxCalls: preview.maxCalls,\n maxUnits: preview.maxUnits\n }\n };\n}\nasync function readPreviewCatalog(\n response: Response\n): Promise<GatewayPreviewModels> {\n if (!response.body) return invalidCatalog();\n const reader = response.body.getReader();\n const decoder = new TextDecoder();\n let text = '',\n bytes = 0;\n try {\n for (;;) {\n const { done, value } = await reader.read();\n if (done) break;\n bytes += value.byteLength;\n if (bytes > 8192) return invalidCatalog();\n text += decoder.decode(value, { stream: true });\n }\n text += decoder.decode();\n return previewCatalog(JSON.parse(text));\n } catch {\n return invalidCatalog();\n } finally {\n await reader.cancel().catch(() => {});\n reader.releaseLock();\n }\n}\n\n/**\n * Use only for the desktop's isolated local preview relay. The desktop supplies\n * PLATFORM_GATEWAY_URL, INSTANCE_ID and a preview-only INSTANCE_HMAC_KEY.\n * This client neither holds the desktop login nor calls a provider directly.\n *\n * Unlike createModelGatewayClient (managed instances), this catalog makes no\n * monthly-token or BAA claims. Streaming is not supported by the preview relay.\n * The gateway still applies its own bounded chat request protocol.\n *\n * @example\n * const client = createPreviewModelGatewayClient();\n * const catalog = await client.models();\n * const reply = await client.chat.completions.create({\n * model: catalog.models[0].id,\n * messages: [{ role: 'user', content: 'Help plan my task.' }]\n * });\n * // catalog.preview.maxUnits is an issued ceiling, not remaining monthly usage.\n */\nexport function createPreviewModelGatewayClient(\n options: ModelGatewayClientOptions = {}\n): PreviewModelGatewayClient {\n const transport = createInstanceGatewayTransport(\n options,\n 'The local preview model gateway'\n );\n async function send(\n method: 'GET' | 'POST',\n route: string,\n body?: Record<string, unknown>\n ): Promise<Response> {\n try {\n return await transport.request(method, route, body);\n } catch (error) {\n if (error instanceof InstanceGatewayRequestError)\n throw new ModelGatewayRequestError(\n error.status,\n 'The local preview model request was refused or is unavailable.',\n error.retryAfterSeconds\n );\n throw error;\n }\n }\n return {\n async models() {\n const response = await send('GET', '/models');\n return readPreviewCatalog(response);\n },\n chat: {\n completions: {\n async create(request) {\n return (await (\n await send(\n 'POST',\n '/models/chat/completions',\n request as unknown as Record<string, unknown>\n )\n ).json()) as GatewayPreviewChatCompletion;\n }\n }\n }\n };\n}\n","import {\n createInstanceGatewayTransport,\n InstanceGatewayRequestError,\n isManagedInstance\n} from './instanceGateway';\n\n/**\n * Client for platform-held email, used from inside a managed instance.\n *\n * The instance never holds a mail credential. It signs each request with its\n * own HMAC key; the platform sends through Amazon SES from the instance's own\n * sending identity (`no-reply@<instance>.<platform sending domain>`, a claimed\n * custom domain later) under a per-instance configuration set, enforces the\n * product's daily quota and rate, and refuses addresses on the instance's\n * suppression list (hard bounces and complaints).\n *\n * Delivery outcomes come back as platform events on\n * `/platform-events/email`: `email.delivered`, `email.bounced` and\n * `email.complained`, each carrying the `messageId` `send` returned. A bounced\n * or complained address is suppressed by the platform; mark it undeliverable\n * in the app too so the person can be asked for a new one.\n *\n * Locally, `forklaunch infra add <service> email` points the service at the\n * gateway mock in docker-compose (PLATFORM_GATEWAY_URL, INSTANCE_ID,\n * INSTANCE_HMAC_KEY), which records messages (GET /__mock/email/messages) and\n * emits the same events. Outside managed mode and without those settings,\n * `createEmailClient` refuses to be created.\n *\n * What to put where: the body may hold what the recipient is entitled to\n * read; the subject shows on lock screens, in notification previews and in\n * mail logs, so never put protected data (a `.deanon` value) in it.\n *\n * @example\n * const email = createEmailClient();\n * const { messageId } = await email.send({\n * to: 'pat@example.com',\n * subject: 'Your appointment is confirmed',\n * text: 'See you on Tuesday at 10:00.'\n * });\n * if (await email.suppressed('pat@example.com')) { … ask for another address }\n */\n\nexport interface EmailClientOptions {\n /** Platform base URL. Default: `PLATFORM_GATEWAY_URL`. */\n gatewayUrl?: string;\n /** This instance's id. Default: `INSTANCE_ID`. */\n instanceId?: string;\n /** This instance's HMAC key. Default: `INSTANCE_HMAC_KEY`. */\n hmacKey?: string;\n fetch?: typeof fetch;\n}\n\nexport interface EmailSendRequest {\n /** One address or up to 50. */\n to: string | string[];\n /** Plain text, one line; shown in previews and logs — no protected data. */\n subject: string;\n /** At least one of `text` and `html`. */\n text?: string;\n html?: string;\n replyTo?: string | string[];\n /**\n * Up to 10 tags, echoed on the delivery events. Names and values:\n * letters, digits, `_` and `-`. Names starting `fl-` or `ses:` are reserved.\n */\n tags?: Record<string, string>;\n}\n\nexport interface EmailSendResult {\n /** The provider's message id; delivery events carry it. */\n messageId: string;\n}\n\n/** Data on `email.delivered`, `email.bounced` and `email.complained` events. */\nexport interface EmailEventData {\n messageId: string;\n recipients: string[];\n tags?: Record<string, string>;\n /** `email.bounced`: `Permanent`, `Transient` or `Undetermined`. */\n bounceType?: string;\n bounceSubType?: string;\n /** `email.bounced`: whether the platform suppressed the addresses. */\n permanent?: boolean;\n /** `email.complained`: the feedback type the mailbox provider reported. */\n feedbackType?: string;\n}\n\n/** A refusal or failure, from the gateway or from validation before sending. */\nexport class EmailRequestError extends InstanceGatewayRequestError {\n override readonly name = 'EmailRequestError' as const;\n}\n\nexport interface EmailClient {\n /** Send one message; throws `EmailRequestError` on a refusal. */\n send(request: EmailSendRequest): Promise<EmailSendResult>;\n /** Whether the platform refuses to send to `address` (bounce/complaint). */\n suppressed(address: string): Promise<boolean>;\n}\n\n/** Limits the platform enforces too; checked here so a bad call fails fast. */\nexport const EMAIL_LIMITS = {\n maxRecipients: 50,\n maxAddressLength: 254,\n maxSubjectLength: 998,\n /** text + html, UTF-8 bytes. */\n maxBodyBytes: 512 * 1024,\n maxTags: 10\n} as const;\n\nconst ADDRESS =\n /^[^\\s@<>()[\\]\\\\,;:\"]+@[A-Za-z0-9](?:[A-Za-z0-9-]*[A-Za-z0-9])?(?:\\.[A-Za-z0-9](?:[A-Za-z0-9-]*[A-Za-z0-9])?)+$/;\nconst TAG_PART = /^[A-Za-z0-9_-]{1,256}$/;\n\n/** Whether `address` is a plain mailbox address (`local@domain.tld`). */\nexport function isEmailAddress(address: unknown): address is string {\n return (\n typeof address === 'string' &&\n address.length <= EMAIL_LIMITS.maxAddressLength &&\n ADDRESS.test(address)\n );\n}\n\nfunction refuse(message: string): never {\n throw new EmailRequestError(400, message);\n}\n\nfunction addresses(value: string | string[] | undefined, field: string) {\n if (value === undefined) return undefined;\n const list = Array.isArray(value) ? value : [value];\n if (list.length === 0) refuse(`${field} must name at least one address`);\n if (list.length > EMAIL_LIMITS.maxRecipients) {\n refuse(\n `${field} has ${list.length} addresses; the limit is ${EMAIL_LIMITS.maxRecipients}`\n );\n }\n for (const address of list) {\n if (!isEmailAddress(address)) {\n refuse(\n `${field}: '${String(address).slice(0, 80)}' is not an email address`\n );\n }\n }\n return list;\n}\n\n/** Validate a send request the way the gateway does; returns the wire body. */\nexport function validateEmailSendRequest(\n request: EmailSendRequest\n): Record<string, unknown> {\n const to = addresses(request.to, 'to') ?? refuse('to is required');\n const replyTo = addresses(request.replyTo, 'replyTo');\n const subject = request.subject;\n if (typeof subject !== 'string' || subject.trim() === '') {\n refuse('subject is required');\n }\n if (/[\\r\\n]/.test(subject)) refuse('subject must be one line');\n if (subject.length > EMAIL_LIMITS.maxSubjectLength) {\n refuse(\n `subject is longer than ${EMAIL_LIMITS.maxSubjectLength} characters`\n );\n }\n if (!request.text && !request.html) refuse('text or html is required');\n const bytes =\n Buffer.byteLength(request.text ?? '', 'utf8') +\n Buffer.byteLength(request.html ?? '', 'utf8');\n if (bytes > EMAIL_LIMITS.maxBodyBytes) {\n refuse(`body is ${bytes} bytes; the limit is ${EMAIL_LIMITS.maxBodyBytes}`);\n }\n const tags = request.tags ?? {};\n const names = Object.keys(tags);\n if (names.length > EMAIL_LIMITS.maxTags) {\n refuse(`${names.length} tags; the limit is ${EMAIL_LIMITS.maxTags}`);\n }\n for (const name of names) {\n if (!TAG_PART.test(name) || !TAG_PART.test(String(tags[name]))) {\n refuse(`tag '${name}': names and values are letters, digits, _ and -`);\n }\n if (name.startsWith('fl-') || name.startsWith('ses:')) {\n refuse(`tag '${name}' is reserved`);\n }\n }\n return {\n to,\n subject,\n ...(request.text !== undefined ? { text: request.text } : {}),\n ...(request.html !== undefined ? { html: request.html } : {}),\n ...(replyTo ? { replyTo } : {}),\n ...(names.length ? { tags } : {})\n };\n}\n\nexport function createEmailClient(\n options: EmailClientOptions = {}\n): EmailClient {\n if (\n !isManagedInstance({\n PLATFORM_GATEWAY_URL:\n options.gatewayUrl ?? process.env.PLATFORM_GATEWAY_URL,\n INSTANCE_ID: options.instanceId ?? process.env.INSTANCE_ID,\n INSTANCE_HMAC_KEY: options.hmacKey ?? process.env.INSTANCE_HMAC_KEY\n })\n ) {\n throw new Error(\n 'Email is sent by the ForkLaunch platform: PLATFORM_GATEWAY_URL, INSTANCE_ID and INSTANCE_HMAC_KEY must be set. ' +\n 'A managed instance and an app deployed with `forklaunch deploy create` get them from the platform at deploy. ' +\n 'Locally, `forklaunch infra add <service> email` sets them to the gateway mock in docker-compose.'\n );\n }\n const transport = createInstanceGatewayTransport(options, 'Email');\n\n async function call<T>(\n method: 'GET' | 'POST',\n route: string,\n body?: Record<string, unknown>\n ): Promise<T> {\n try {\n return await transport.json<T>(method, route, body);\n } catch (error) {\n if (error instanceof InstanceGatewayRequestError) {\n throw new EmailRequestError(\n error.status,\n error.message,\n error.retryAfterSeconds\n );\n }\n throw error;\n }\n }\n\n return {\n async send(request) {\n return call<EmailSendResult>(\n 'POST',\n '/email/send',\n validateEmailSendRequest(request)\n );\n },\n async suppressed(address) {\n if (!isEmailAddress(address)) {\n refuse(`'${String(address).slice(0, 80)}' is not an email address`);\n }\n const answer = await call<{ suppressed: boolean }>(\n 'GET',\n `/email/suppressions/${encodeURIComponent(address.toLowerCase())}`\n );\n return answer.suppressed === true;\n }\n };\n}\n","import {\n createInstanceGatewayTransport,\n InstanceGatewayRequestError,\n isManagedInstance,\n type InstanceGatewayOptions,\n type InstanceGatewayTransport,\n type PlatformEvent\n} from './instanceGateway';\n\n/**\n * Client for platform-held SMS (AWS End User Messaging SMS), used from inside\n * a managed instance.\n *\n * The instance never holds an AWS credential or a phone number. It signs each\n * send with its own HMAC key; the platform checks the instance's monthly\n * segment cap, its rate limit and its opt-out list, then sends from the\n * product's origination pool under a configuration set named for the\n * instance, so delivery receipts come back to this instance and no other.\n *\n * Events arrive at `POST /platform-events/sms` (verify them with\n * `verifyPlatformEvent`): `sms.delivered`, `sms.failed`, `sms.received`\n * (a reply) and `sms.opted_out` (the person texted STOP; further sends to that\n * number are refused with 422).\n *\n * A text message is not a secure channel: carriers, the handset's lock screen\n * and anyone holding the phone can read it. Never put protected data (a\n * `.deanon` value, a diagnosis, a result) in `body`; send a link to sign in\n * instead. `forklaunch score` flags it (`sms-protected-data`).\n *\n * Locally, run the gateway mock (`npx -p @forklaunch/core\n * forklaunch-gateway-mock`, or the `gateway-mock` compose service that\n * `forklaunch infra add <service> sms` wires) and point PLATFORM_GATEWAY_URL,\n * INSTANCE_ID and INSTANCE_HMAC_KEY at it.\n *\n * @example\n * const sms = createSmsClient();\n * const { messageId, segments } = await sms.send({\n * to: '+14155550123',\n * body: 'Your appointment is confirmed. Sign in for details: https://…',\n * purpose: 'transactional'\n * });\n */\n\nexport interface SmsClientOptions extends InstanceGatewayOptions {\n /**\n * Refuse on the first `send` rather than at creation when the service is\n * not a managed instance. For dependency containers that build singletons\n * at boot, so a local run without the gateway still starts.\n */\n deferRefusal?: boolean;\n}\n\nexport type SmsPurpose = 'transactional' | 'promotional';\n\nexport interface SmsSendRequest {\n /** E.164, e.g. `+14155550123`. */\n to: string;\n /** Plain text. At most `SMS_MAX_SEGMENTS` segments. */\n body: string;\n /** Default `transactional`. Promotional texts need prior marketing consent. */\n purpose?: SmsPurpose;\n}\n\nexport interface SmsSendResult {\n /** The vendor's message id; delivery events carry it. */\n messageId: string;\n /** Billed segments (a long or non-GSM message is several). */\n segments: number;\n}\n\nexport interface SmsDeliveredData {\n messageId: string;\n to: string;\n deliveredAt?: string;\n}\nexport interface SmsFailedData {\n messageId: string;\n to: string;\n reason: string;\n}\nexport interface SmsReceivedData {\n from: string;\n body: string;\n receivedAt: string;\n /** The recognized keyword (STOP, HELP, START…), when the text was one. */\n keyword?: string;\n}\nexport interface SmsOptedOutData {\n phone: string;\n optedOutAt: string;\n}\n\n/** The events the platform delivers for SMS. */\nexport type SmsEvent =\n | (PlatformEvent<SmsDeliveredData> & { type: 'sms.delivered' })\n | (PlatformEvent<SmsFailedData> & { type: 'sms.failed' })\n | (PlatformEvent<SmsReceivedData> & { type: 'sms.received' })\n | (PlatformEvent<SmsOptedOutData> & { type: 'sms.opted_out' });\n\n/** A refusal or failure from the SMS gateway, with the status it answered. */\nexport class SmsRequestError extends InstanceGatewayRequestError {\n override readonly name = 'SmsRequestError' as const;\n}\n\n/** An input the client refuses before any network call. */\nexport class SmsValidationError extends Error {\n override readonly name = 'SmsValidationError' as const;\n}\n\nexport const SMS_MAX_SEGMENTS = 10;\n\nconst E164 = /^\\+[1-9]\\d{6,14}$/;\n\nexport function isE164(phone: string): boolean {\n return E164.test(phone);\n}\n\n// GSM 03.38 basic set, and the extension set (each counts as two septets).\nconst GSM_BASIC = new Set(\n '@£$¥èéùìòÇ\\nØø\\rÅåΔ_ΦΓΛΩΠΨΣΘΞÆæßÉ !\"#¤%&\\'()*+,-./0123456789:;<=>?¡ABCDEFGHIJKLMNOPQRSTUVWXYZÄÖÑܧ¿abcdefghijklmnopqrstuvwxyzäöñüà'\n);\nconst GSM_EXTENDED = new Set('^{}\\\\[~]|€\\f');\n\n/**\n * How many segments a body is billed as: GSM-7 is 160 septets in one\n * segment, 153 per segment when split; anything outside GSM-7 is UCS-2, 70\n * characters in one, 67 per segment (UTF-16 code units).\n */\nexport function smsSegments(body: string): {\n encoding: 'GSM-7' | 'UCS-2';\n units: number;\n segments: number;\n} {\n let septets = 0;\n let gsm = true;\n for (const ch of body) {\n if (GSM_BASIC.has(ch)) septets += 1;\n else if (GSM_EXTENDED.has(ch)) septets += 2;\n else {\n gsm = false;\n break;\n }\n }\n if (gsm) {\n return {\n encoding: 'GSM-7',\n units: septets,\n segments: septets <= 160 ? 1 : Math.ceil(septets / 153)\n };\n }\n const units = body.length;\n return {\n encoding: 'UCS-2',\n units,\n segments: units <= 70 ? 1 : Math.ceil(units / 67)\n };\n}\n\n/** Check a send before it leaves the process; throws SmsValidationError. */\nexport function validateSmsSend(request: SmsSendRequest): void {\n if (typeof request.to !== 'string' || !isE164(request.to)) {\n throw new SmsValidationError(\n `'to' must be an E.164 number like +14155550123 (got ${JSON.stringify(request.to)})`\n );\n }\n if (typeof request.body !== 'string' || !request.body.trim()) {\n throw new SmsValidationError(\"'body' must be non-empty text\");\n }\n const { segments, encoding } = smsSegments(request.body);\n if (segments > SMS_MAX_SEGMENTS) {\n throw new SmsValidationError(\n `'body' is ${segments} ${encoding} segments; the limit is ${SMS_MAX_SEGMENTS}. Send a link instead of long text.`\n );\n }\n if (\n request.purpose !== undefined &&\n request.purpose !== 'transactional' &&\n request.purpose !== 'promotional'\n ) {\n throw new SmsValidationError(\n \"'purpose' must be 'transactional' or 'promotional'\"\n );\n }\n}\n\nconst NOT_MANAGED =\n 'SMS is platform-held: this service must run as a managed instance ' +\n '(PLATFORM_GATEWAY_URL, INSTANCE_ID and INSTANCE_HMAC_KEY set). ' +\n 'Locally, run the gateway mock (npx -p @forklaunch/core forklaunch-gateway-mock) ' +\n 'and point those variables at it; do not add a Twilio or AWS SDK.';\n\n/**\n * Sends texts through the platform. A class so a dependency container can\n * register it by type (`type: SmsClient`); build it with `createSmsClient`.\n */\nexport class SmsClient {\n private readonly transport?: InstanceGatewayTransport;\n\n constructor(options: SmsClientOptions = {}) {\n const configured =\n Boolean(\n (options.gatewayUrl ?? process.env.PLATFORM_GATEWAY_URL) &&\n (options.instanceId ?? process.env.INSTANCE_ID) &&\n (options.hmacKey ?? process.env.INSTANCE_HMAC_KEY)\n ) || isManagedInstance();\n if (configured) {\n this.transport = createInstanceGatewayTransport(options, 'SMS');\n } else if (!options.deferRefusal) {\n throw new Error(NOT_MANAGED);\n }\n }\n\n /** Whether sends can reach the gateway (false: every send refuses). */\n get managed(): boolean {\n return this.transport !== undefined;\n }\n\n async send(request: SmsSendRequest): Promise<SmsSendResult> {\n validateSmsSend(request);\n if (!this.transport) throw new Error(NOT_MANAGED);\n try {\n return await this.transport.json<SmsSendResult>('POST', '/sms/send', {\n to: request.to,\n body: request.body,\n purpose: request.purpose ?? 'transactional'\n });\n } catch (error) {\n if (error instanceof InstanceGatewayRequestError) {\n throw new SmsRequestError(\n error.status,\n error.message,\n error.retryAfterSeconds\n );\n }\n throw error;\n }\n }\n}\n\nexport function createSmsClient(options: SmsClientOptions = {}): SmsClient {\n return new SmsClient(options);\n}\n","import {\n createInstanceGatewayTransport,\n type InstanceGatewayOptions,\n InstanceGatewayRequestError\n} from './instanceGateway';\n\n/**\n * Client for WhatsApp through the ForkLaunch instance gateway, used from\n * inside a managed instance.\n *\n * The platform holds the WhatsApp Business Account link (AWS End User\n * Messaging Social) and sends on the instance's behalf from the phone number\n * configured for its product or for this instance. The instance never holds\n * a Meta token: each request is signed with its own HMAC key, and the\n * platform enforces WhatsApp's rules and its own:\n *\n * - Business-initiated messages must use a Meta-approved template\n * (`sendTemplate`).\n * - Free-form text (`sendText`) is allowed only inside the 24-hour\n * customer-service window, opened by the recipient's last inbound\n * message. Outside it the gateway answers 422.\n * - A per-instance rate limit (429 with `retryAfterSeconds`).\n * - HIPAA products cannot send at all (403): WhatsApp is not covered by\n * the AWS BAA and Meta signs none. Never put protected health data in a\n * WhatsApp message.\n * - No phone number configured for the product or instance: 409.\n *\n * Events arrive at `/platform-events/whatsapp` (see `verifyPlatformEvent`):\n * - `whatsapp.received` `{ from, text?, type, receivedAt, messageId }`, an\n * inbound message; it opens the 24-hour window for `from`.\n * - `whatsapp.status` `{ messageId, status, recipient?, timestamp? }`,\n * `status` being Meta's `sent`, `delivered`, `read` or `failed`.\n *\n * Locally, `forklaunch infra add <service> whatsapp` points the service at\n * the gateway mock (`forklaunch-gateway-mock`, routes/whatsapp.mjs), which\n * serves templates, emits these events and applies the same refusals.\n *\n * The shape is channel-neutral on purpose (`ConversationChannelClient`):\n * another conversational channel (for example Apple Messages for Business)\n * would be another channel id behind the same three calls.\n *\n * @example\n * const whatsapp = createWhatsAppClient();\n * await whatsapp.sendTemplate({\n * to: '+14155550123',\n * template: 'appointment_reminder',\n * language: 'en_US',\n * components: [{ type: 'body', parameters: [{ type: 'text', text: 'Tuesday 3pm' }] }]\n * });\n */\n\nexport type WhatsAppClientOptions = InstanceGatewayOptions;\n\n/** A Meta template component (header, body, button), passed through as is. */\nexport interface WhatsAppTemplateComponent {\n type: string;\n parameters?: Record<string, unknown>[];\n [key: string]: unknown;\n}\n\nexport interface SendTemplateRequest {\n /** E.164 recipient, e.g. `+14155550123`. */\n to: string;\n /** The approved template's name. */\n template: string;\n /** The template's language code, e.g. `en_US`. */\n language: string;\n /** Variable values for the template, in Meta's component format. */\n components?: WhatsAppTemplateComponent[];\n}\n\nexport interface SendTextRequest {\n /** E.164 recipient; must have written to this number in the last 24 hours. */\n to: string;\n body: string;\n}\n\nexport interface SentMessage {\n /** Matches `messageId` on later `whatsapp.status` events. */\n messageId: string;\n}\n\nexport interface MessageTemplate {\n name: string;\n language: string;\n /** Meta's review status: `APPROVED`, `PENDING`, `REJECTED`, … */\n status: string;\n category?: string;\n}\n\n/** The data of a `whatsapp.received` event. */\nexport interface WhatsAppReceivedEvent {\n from: string;\n /** Present for `type: 'text'` messages. */\n text?: string;\n type: string;\n receivedAt: string;\n messageId?: string;\n}\n\n/** The data of a `whatsapp.status` event. */\nexport interface WhatsAppStatusEvent {\n messageId: string;\n status: string;\n recipient?: string;\n timestamp?: string;\n}\n\n/** A refusal or failure from the WhatsApp gateway, with its status. */\nexport class WhatsAppRequestError extends InstanceGatewayRequestError {\n override readonly name = 'WhatsAppRequestError' as const;\n}\n\n/**\n * The calls every conversational channel offers. WhatsApp is the only\n * implementation today.\n */\nexport interface ConversationChannelClient {\n /** Business-initiated message from an approved template. */\n sendTemplate(request: SendTemplateRequest): Promise<SentMessage>;\n /** Free-form text, inside the 24-hour customer-service window only. */\n sendText(request: SendTextRequest): Promise<SentMessage>;\n /** The templates the configured account has, with their review status. */\n templates(): Promise<MessageTemplate[]>;\n}\n\nexport type WhatsAppClient = ConversationChannelClient;\n\nconst E164 = /^\\+[1-9]\\d{6,14}$/;\n\nfunction requireRecipient(to: unknown): void {\n if (typeof to !== 'string' || !E164.test(to)) {\n throw new WhatsAppRequestError(\n 400,\n `'to' must be an E.164 phone number such as +14155550123 (got ${JSON.stringify(to)})`\n );\n }\n}\n\nfunction createConversationChannelClient(\n channel: string,\n label: string,\n options: WhatsAppClientOptions\n): ConversationChannelClient {\n const transport = createInstanceGatewayTransport(options, label);\n\n async function call<T>(\n method: 'GET' | 'POST',\n route: string,\n body?: Record<string, unknown>\n ): Promise<T> {\n try {\n return await transport.json<T>(method, `/${channel}${route}`, body);\n } catch (error) {\n if (error instanceof InstanceGatewayRequestError) {\n throw new WhatsAppRequestError(\n error.status,\n error.message,\n error.retryAfterSeconds\n );\n }\n throw error;\n }\n }\n\n return {\n async sendTemplate(request) {\n requireRecipient(request.to);\n if (!request.template || !request.language) {\n throw new WhatsAppRequestError(\n 400,\n 'template and language are required'\n );\n }\n return call<SentMessage>('POST', '/messages', {\n to: request.to,\n type: 'template',\n template: request.template,\n language: request.language,\n ...(request.components ? { components: request.components } : {})\n });\n },\n async sendText(request) {\n requireRecipient(request.to);\n if (typeof request.body !== 'string' || !request.body.trim()) {\n throw new WhatsAppRequestError(400, 'body must be non-empty text');\n }\n return call<SentMessage>('POST', '/messages', {\n to: request.to,\n type: 'text',\n body: request.body\n });\n },\n async templates() {\n const listing = await call<{ templates: MessageTemplate[] }>(\n 'GET',\n '/templates'\n );\n return listing.templates;\n }\n };\n}\n\n/**\n * A WhatsApp client for this managed instance. Throws when the service is\n * not running in managed mode (`PLATFORM_GATEWAY_URL`, `INSTANCE_ID`,\n * `INSTANCE_HMAC_KEY` unset); run the local gateway mock to develop.\n */\nexport function createWhatsAppClient(\n options: WhatsAppClientOptions = {}\n): WhatsAppClient {\n return createConversationChannelClient('whatsapp', 'WhatsApp', options);\n}\n","import {\n createInstanceGatewayTransport,\n type InstanceGatewayOptions,\n InstanceGatewayRequestError,\n type InstanceGatewayTransport\n} from './instanceGateway';\n\n/**\n * Client for platform-held voice calls (Amazon Connect), used from inside a\n * managed instance.\n *\n * The instance never holds an AWS credential, a Connect instance id or a\n * contact-flow ARN. It asks the platform to place a call with a FLOW NAME from\n * the product's flow catalog (`appointment_reminder`, …); the platform maps it\n * to the contact flow, dials from the phone number claimed for this instance,\n * and enforces the instance's concurrent-call and monthly-minute limits.\n *\n * Call progress arrives as platform events on `/platform-events/voice`\n * (`voice.call.started`, `voice.call.ended`, `voice.recording.ready`), signed\n * with the instance key; `forklaunch infra add <service> voice` writes the\n * route and a handler stub.\n *\n * Attributes are passed to the contact flow and are stored in Connect's\n * contact records. Put identifiers in them (an appointment id the flow looks\n * up), never health information: the `voice-protected-data` check flags a\n * `.deanon` value flowing into them.\n *\n * Locally, `infra add` points the service at the gateway mock in\n * docker-compose (flows from `MOCK_VOICE_FLOWS`, events delivered back to the\n * service), so the same code runs with no AWS account.\n *\n * @example\n * const voice = createVoiceClient();\n * const { callId } = await voice.startOutboundCall({\n * to: '+15551230000',\n * flow: 'appointment_reminder',\n * attributes: { appointmentId: appt.id }\n * });\n * const { status } = await voice.call(callId);\n */\n\nexport type VoiceClientOptions = InstanceGatewayOptions;\n\n/** Limits the gateway enforces on attributes; the client checks them first. */\nexport const VOICE_ATTRIBUTE_LIMITS = {\n maxKeys: 20,\n maxKeyLength: 64,\n maxValueLength: 256,\n maxTotalBytes: 4096,\n /** Keys the platform reserves (it prefixes and adds its own under `fl_`). */\n reservedPrefix: 'fl_'\n} as const;\n\nexport interface StartOutboundCallRequest {\n /** The number to call, E.164 (`+15551230000`). */\n to: string;\n /** A flow name from the product's catalog, e.g. `appointment_reminder`. */\n flow: string;\n /** String values the contact flow can read. No health information. */\n attributes?: Record<string, string>;\n}\n\nexport interface StartOutboundCallResult {\n callId: string;\n}\n\nexport type VoiceCallStatus = 'initiated' | 'in_progress' | 'ended';\n\nexport interface VoiceCall {\n status: VoiceCallStatus;\n startedAt: string;\n endedAt?: string;\n durationSeconds?: number;\n /** Why it ended: `customer`, `agent`, `api`, `busy`, `no_answer`, … */\n disconnectReason?: string;\n}\n\n/** Data of `voice.call.started`. */\nexport interface VoiceCallStartedEvent {\n callId: string;\n flow?: string;\n}\n\n/** Data of `voice.call.ended`. */\nexport interface VoiceCallEndedEvent {\n callId: string;\n durationSeconds: number;\n disconnectReason: string;\n}\n\n/** Data of `voice.recording.ready`: the key in the instance's object store. */\nexport interface VoiceRecordingReadyEvent {\n callId: string;\n recordingKey: string;\n}\n\n/** A refusal or failure from the voice gateway, with its status. */\nexport class VoiceRequestError extends InstanceGatewayRequestError {\n override readonly name = 'VoiceRequestError' as const;\n}\n\nconst E164 = /^\\+[1-9]\\d{6,14}$/;\nconst FLOW_NAME = /^[a-z][a-z0-9_-]{0,63}$/;\nconst ATTRIBUTE_KEY = /^[A-Za-z][A-Za-z0-9_]*$/;\n\n/** Why a request would be refused, or undefined. Shared with the gateway. */\nexport function voiceRequestProblem(\n request: StartOutboundCallRequest\n): string | undefined {\n if (typeof request.to !== 'string' || !E164.test(request.to)) {\n return '`to` must be an E.164 number such as +15551230000';\n }\n if (typeof request.flow !== 'string' || request.flow.startsWith('arn:')) {\n return '`flow` is a flow name from the product catalog (e.g. appointment_reminder), not a contact-flow ARN';\n }\n if (!FLOW_NAME.test(request.flow)) {\n return '`flow` must be a catalog flow name: lowercase letters, digits, _ or -';\n }\n const attributes = request.attributes ?? {};\n if (typeof attributes !== 'object' || Array.isArray(attributes)) {\n return '`attributes` must be an object of strings';\n }\n const entries = Object.entries(attributes);\n const limits = VOICE_ATTRIBUTE_LIMITS;\n if (entries.length > limits.maxKeys) {\n return `at most ${limits.maxKeys} attributes`;\n }\n let total = 0;\n for (const [key, value] of entries) {\n if (!ATTRIBUTE_KEY.test(key) || key.length > limits.maxKeyLength) {\n return `attribute key '${key}' must be letters, digits or _ (max ${limits.maxKeyLength})`;\n }\n if (key.toLowerCase().startsWith(limits.reservedPrefix)) {\n return `attribute keys starting with '${limits.reservedPrefix}' are reserved for the platform`;\n }\n if (typeof value !== 'string') {\n return `attribute '${key}' must be a string`;\n }\n if (value.length > limits.maxValueLength) {\n return `attribute '${key}' is longer than ${limits.maxValueLength} characters`;\n }\n total += Buffer.byteLength(key) + Buffer.byteLength(value);\n }\n if (total > limits.maxTotalBytes) {\n return `attributes exceed ${limits.maxTotalBytes} bytes`;\n }\n return undefined;\n}\n\n/**\n * The voice client. A class so a service's registrations.ts can declare it\n * (`type: VoiceClient`); construct it with `createVoiceClient()`.\n */\nexport class VoiceClient {\n private readonly transport: InstanceGatewayTransport;\n\n /** Throws when the process is not a managed instance (see instanceGatewaySettings). */\n constructor(options: VoiceClientOptions = {}) {\n this.transport = createInstanceGatewayTransport(\n options,\n 'Voice calls (createVoiceClient)'\n );\n }\n\n /** Place an outbound call; resolves once the platform accepted it. */\n async startOutboundCall(\n request: StartOutboundCallRequest\n ): Promise<StartOutboundCallResult> {\n const problem = voiceRequestProblem(request);\n if (problem) throw new VoiceRequestError(400, problem);\n return this.send<StartOutboundCallResult>('POST', '/voice/calls', {\n to: request.to,\n flow: request.flow,\n ...(request.attributes ? { attributes: request.attributes } : {})\n });\n }\n\n /** Hang up a call this instance placed. */\n async endCall(callId: string): Promise<void> {\n await this.send<unknown>('DELETE', callPath(callId));\n }\n\n /** Where a call this instance placed stands. */\n async call(callId: string): Promise<VoiceCall> {\n return this.send<VoiceCall>('GET', callPath(callId));\n }\n\n private async send<T>(\n method: 'GET' | 'POST' | 'DELETE',\n route: string,\n body?: Record<string, unknown>\n ): Promise<T> {\n try {\n const response = await this.transport.request(method, route, body);\n const text = await response.text();\n return (text ? JSON.parse(text) : undefined) as T;\n } catch (error) {\n if (error instanceof InstanceGatewayRequestError) {\n throw new VoiceRequestError(\n error.status,\n error.message,\n error.retryAfterSeconds\n );\n }\n throw error;\n }\n }\n}\n\nfunction callPath(callId: string): string {\n if (typeof callId !== 'string' || !/^[A-Za-z0-9_-]{1,128}$/.test(callId)) {\n throw new VoiceRequestError(400, 'callId is not a call id');\n }\n return `/voice/calls/${callId}`;\n}\n\n/** A voice client for this managed instance (settings from the environment). */\nexport function createVoiceClient(\n options: VoiceClientOptions = {}\n): VoiceClient {\n return new VoiceClient(options);\n}\n","import { createRequire } from 'node:module';\nimport type Stripe from 'stripe';\nimport {\n createInstanceGatewayTransport,\n INSTANCE_GATEWAY_MOUNT,\n InstanceGatewayRequestError,\n instanceGatewaySettings,\n isManagedInstance,\n type InstanceGatewayOptions\n} from './instanceGateway';\nimport { generateHmacAuthHeaders } from './generateHmacAuthHeaders';\n\n/**\n * Payments for a managed instance: Stripe Connect through the platform.\n *\n * The product's publisher runs the Stripe Connect platform, linked once to\n * ForkLaunch. Each managed instance (a clinic, a studio) gets its OWN\n * connected account and is the merchant of record: charges are direct\n * charges on that account, and payouts go to the clinic's bank, never through\n * the app. The app never holds a Stripe key:\n *\n * - `createPaymentsClient()` onboards the instance (a Stripe-hosted Account\n * Link) and reports whether it can take payments yet;\n * - `createStripeClient()` is the REAL Stripe SDK, pointed at the instance\n * gateway. Every request is signed with the instance key, and the platform\n * pins `Stripe-Account` to this instance's connected account, forwards\n * only an allowlist of calls (customers, products and prices, checkout and\n * billing-portal sessions, payment links, subscriptions, payment intents,\n * refunds, invoices — never payouts, transfers, external accounts or\n * account changes), adds the product's application fee, and refuses\n * metadata that looks like protected data;\n * - Stripe's events arrive as platform events (`/platform-events/payments`,\n * type = the Stripe event type, id = the Stripe event id, data = the\n * event's object), verified with `verifyPlatformEvent`.\n *\n * Outside managed mode `createStripeClient({ apiKey })` is `new Stripe(apiKey)`,\n * so the same registration runs against a developer's own test account.\n *\n * @example\n * const payments = createPaymentsClient();\n * const { url } = await payments.onboardingLink({\n * returnUrl: 'https://clinic.example.com/settings/payments?done=1',\n * refreshUrl: 'https://clinic.example.com/settings/payments'\n * });\n * const stripe = createStripeClient({ Stripe });\n * const session = await stripe.checkout.sessions.create({ mode: 'payment', … });\n */\n\n/** Where the gateway proxies Stripe's API, router-relative. */\nexport const STRIPE_GATEWAY_ROUTE = '/stripe';\n\nexport interface PaymentsStatus {\n /** The connected account can take card payments. */\n chargesEnabled: boolean;\n /** Stripe can pay out to the clinic's bank account. */\n payoutsEnabled: boolean;\n /** What Stripe still needs (`individual.verification.document`, …). */\n requirementsDue: string[];\n}\n\nexport interface PaymentsClient {\n /**\n * A single-use Stripe-hosted onboarding link for this instance's connected\n * account (created on first use). Send the clinic's owner to `url`; Stripe\n * returns them to `returnUrl`, or to `refreshUrl` when the link expired.\n */\n onboardingLink(params: {\n returnUrl: string;\n refreshUrl: string;\n }): Promise<{ url: string }>;\n /** Whether the instance can take payments yet. */\n status(): Promise<PaymentsStatus>;\n}\n\n/** A refusal or failure from the payments gateway. */\nexport class PaymentsRequestError extends InstanceGatewayRequestError {\n override readonly name = 'PaymentsRequestError' as const;\n}\n\nexport function createPaymentsClient(\n options: InstanceGatewayOptions = {}\n): PaymentsClient {\n const transport = createInstanceGatewayTransport(options, 'Payments');\n async function call<T>(\n method: 'GET' | 'POST',\n route: string,\n body?: Record<string, unknown>\n ): Promise<T> {\n try {\n return await transport.json<T>(method, route, body);\n } catch (error) {\n if (error instanceof InstanceGatewayRequestError) {\n throw new PaymentsRequestError(\n error.status,\n error.message,\n error.retryAfterSeconds\n );\n }\n throw error;\n }\n }\n return {\n onboardingLink({ returnUrl, refreshUrl }) {\n for (const [name, value] of [\n ['returnUrl', returnUrl],\n ['refreshUrl', refreshUrl]\n ] as const) {\n if (!/^https?:\\/\\//.test(value ?? '')) {\n throw new TypeError(`${name} must be an absolute http(s) URL`);\n }\n }\n return call('POST', '/payments/onboarding-link', {\n returnUrl,\n refreshUrl\n });\n },\n status() {\n return call('GET', '/payments/status');\n }\n };\n}\n\ntype StripeConstructor = typeof Stripe;\n\nexport interface StripeClientOptions extends InstanceGatewayOptions {\n /**\n * A Stripe secret key: the service talks to Stripe directly with it (local\n * development against your own test account, a self-hosted or regular\n * deployment). It wins over a managed contract found in the environment;\n * only explicit gateway options (`gatewayUrl`/`instanceId`/`hmacKey`)\n * outrank it. A managed instance passes none and the platform holds the key.\n */\n apiKey?: string;\n /**\n * The `Stripe` class to construct. Pass your own `import Stripe from\n * 'stripe'` when the client is registered with `type: Stripe`: an ESM\n * service and this package could otherwise load different builds of the\n * SDK, and the registration's `instanceof` check would fail. Default: the\n * `stripe` package, loaded on first use (it is an optional peer dependency).\n */\n Stripe?: StripeConstructor;\n /** Extra SDK settings (apiVersion, maxNetworkRetries, timeout, appInfo). */\n config?: Stripe.StripeConfig;\n}\n\nfunction loadStripe(): StripeConstructor {\n // Loaded lazily so `@forklaunch/core/http` never needs `stripe` installed.\n // The CommonJS build has `__filename` (its `import.meta` is empty); the ESM\n // build has `import.meta.url`. (A bare `require` would be rewritten by the\n // bundler into a shim that throws under ESM.)\n const load = createRequire(\n typeof __filename === 'string' ? __filename : import.meta.url\n );\n try {\n const mod = load('stripe') as StripeConstructor & {\n default?: StripeConstructor;\n };\n return mod.default ?? mod;\n } catch {\n throw new Error(\n \"createStripeClient needs the 'stripe' package: add it to this service (pnpm add stripe)\"\n );\n }\n}\n\n/**\n * A fetch that sends Stripe SDK requests to the instance gateway, signed.\n *\n * The SDK builds `https://<host>:<port>/v1/...` from the `host`/`port`/\n * `protocol` settings; this rewrites the path under\n * `/instance-gateway/stripe` and adds the instance's HMAC `authorization`,\n * replacing any bearer key. The signature covers the method, the\n * router-relative path WITH its query string (`/stripe/v1/prices?active=true`,\n * so a list filter cannot be altered in flight) and the body exactly as sent:\n * Stripe's bodies are form-encoded, and the raw form string is signed\n * verbatim (framework `createHmacToken` treats a string body as the wire\n * bytes). An empty body signs as no body.\n */\nexport function stripeGatewayFetch(\n settings: { gatewayUrl: string; instanceId: string; hmacKey: string },\n fetchImpl: typeof fetch = fetch\n): typeof fetch {\n const base = new URL(settings.gatewayUrl);\n const basePath = base.pathname.replace(/\\/+$/, '');\n return async (input, init = {}) => {\n const original = new URL(\n typeof input === 'string' || input instanceof URL ? input : input.url\n );\n const routerPath = `${STRIPE_GATEWAY_ROUTE}${original.pathname}${original.search}`;\n const method = (init.method ?? 'GET').toUpperCase();\n const body = typeof init.body === 'string' ? init.body : undefined;\n const { authorization } = generateHmacAuthHeaders({\n secretKey: settings.hmacKey,\n method,\n path: routerPath,\n body: body || undefined,\n keyId: settings.instanceId\n });\n const headers = new Headers(init.headers);\n headers.set('authorization', authorization);\n const target = `${base.origin}${basePath}${INSTANCE_GATEWAY_MOUNT}${routerPath}`;\n const response = await fetchImpl(target, { ...init, method, headers });\n if (\n response.ok ||\n (response.headers.get('content-type') ?? '').includes('json')\n ) {\n return response;\n }\n // A refusal the gateway answered in plain text (a bad signature, an\n // unknown instance): give the SDK Stripe's error shape, so it raises the\n // usual typed error (401 -> StripeAuthenticationError) with the message.\n const message =\n (await response.text().catch(() => '')).trim() ||\n `Instance gateway answered ${response.status}`;\n return new Response(\n JSON.stringify({\n error: {\n type: 'invalid_request_error',\n code: 'forklaunch_gateway',\n message\n }\n }),\n {\n status: response.status,\n headers: {\n 'content-type': 'application/json',\n 'stripe-should-retry': 'false',\n ...(response.headers.get('retry-after')\n ? { 'retry-after': response.headers.get('retry-after') as string }\n : {})\n }\n }\n );\n };\n}\n\n/**\n * The Stripe SDK for this service.\n *\n * Which Stripe it talks to, in order:\n * 1. explicit gateway options (`gatewayUrl`/`instanceId`/`hmacKey`): the\n * platform's instance gateway;\n * 2. an explicit `apiKey`: `new Stripe(apiKey)`, directly — even when the\n * environment carries the managed contract. Those three variables also\n * reach a regular app's components that use another platform feature\n * (email), and an app that passes its own key means its own key;\n * 3. the managed contract in the environment (`PLATFORM_GATEWAY_URL`,\n * `INSTANCE_ID`, `INSTANCE_HMAC_KEY`): the gateway, signed with the\n * instance key; there is no Stripe key in the app.\n * Otherwise it throws.\n *\n * (Through @forklaunch/core 3.0.1 an explicit `apiKey` lost to the\n * environment in step 3.)\n *\n * Mechanism (stripe-node 22): `host`/`port`/`protocol` point the SDK at the\n * gateway, `httpClient: Stripe.createFetchHttpClient(signedFetch)` rewrites\n * each request under `/instance-gateway/stripe` and signs it (see\n * `stripeGatewayFetch`), and a no-op `authenticator` stands in for the API\n * key so no bearer credential is ever sent. Retries re-enter the fetch, so\n * each attempt carries a fresh nonce.\n */\nexport function createStripeClient(options: StripeClientOptions = {}): Stripe {\n const StripeClass = options.Stripe ?? loadStripe();\n const explicitGateway = Boolean(\n options.gatewayUrl || options.instanceId || options.hmacKey\n );\n // An explicit key wins over a managed contract detected in the\n // environment; only explicit gateway options outrank it.\n if (!explicitGateway && options.apiKey) {\n return new StripeClass(options.apiKey, options.config);\n }\n if (!explicitGateway && !isManagedInstance()) {\n if (!options.apiKey) {\n throw new Error(\n 'createStripeClient: not a managed instance (PLATFORM_GATEWAY_URL, INSTANCE_ID and ' +\n 'INSTANCE_HMAC_KEY are unset) and no apiKey was given — pass { apiKey } for local ' +\n 'development, or run the gateway mock (forklaunch-gateway-mock) with the managed env'\n );\n }\n return new StripeClass(options.apiKey, options.config);\n }\n const settings = instanceGatewaySettings(options, 'Payments');\n const gateway = new URL(settings.gatewayUrl);\n const protocol = gateway.protocol === 'http:' ? 'http' : 'https';\n return new StripeClass(\n // No key: the authenticator below replaces it, and the gateway holds the\n // real one. (stripe-node accepts an authenticator in place of a key.)\n undefined as unknown as string,\n {\n maxNetworkRetries: 2,\n ...options.config,\n host: gateway.hostname,\n port: gateway.port || (protocol === 'http' ? 80 : 443),\n protocol,\n telemetry: false,\n // The signed fetch sets `authorization`; nothing else may.\n authenticator: async () => {},\n httpClient: StripeClass.createFetchHttpClient(\n stripeGatewayFetch(settings, options.fetch)\n )\n }\n );\n}\n","export function isPath<Path extends `/${string}`>(path: string): path is Path {\n return path.startsWith('/');\n}\n","import { AnySchemaValidator } from '@forklaunch/validator';\nimport { isPath } from '../guards/isPath';\nimport { ExpressLikeSchemaHandler } from '../types/apiDefinition.types';\nimport {\n Body,\n ContractDetails,\n HeadersObject,\n Method,\n ParamsObject,\n QueryObject,\n ResolvedSessionObject,\n ResponsesObject,\n SchemaAuthMethods,\n SessionObject,\n VersionSchema\n} from '../types/contractDetails.types';\nimport { ExpressLikeTypedHandler } from '../types/typedHandler.types';\n\n/**\n * Router class that sets up routes and middleware for an Express router, for use with controller/routes pattern.\n *\n * @template SV - A type that extends AnySchemaValidator.\n * @template contractDetails - The contract details.\n * @template handlers - The handler middlware and handler.\n */\nexport function typedHandler<\n SV extends AnySchemaValidator,\n Name extends string,\n ContractMethod extends Method,\n Path extends `/${string}`,\n P extends ParamsObject<SV>,\n ResBodyMap extends ResponsesObject<SV>,\n ReqBody extends Body<SV>,\n ReqQuery extends QueryObject<SV>,\n ReqHeaders extends HeadersObject<SV>,\n ResHeaders extends HeadersObject<SV>,\n LocalsObj extends Record<string, unknown>,\n const VersionedApi extends VersionSchema<SV, ContractMethod>,\n BaseRequest,\n BaseResponse,\n NextFunction,\n const Auth extends SchemaAuthMethods<\n SV,\n P,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n VersionedApi,\n BaseRequest\n >\n>(\n _schemaValidator: SV,\n _path: Path | undefined,\n _contractMethod: ContractMethod,\n contractDetails: ContractDetails<\n SV,\n Name,\n ContractMethod,\n Path,\n P,\n ResBodyMap,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n ResHeaders,\n VersionedApi,\n BaseRequest,\n Auth\n >,\n ...handlers: ExpressLikeSchemaHandler<\n SV,\n P,\n ResBodyMap,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n ResHeaders,\n LocalsObj,\n VersionedApi,\n ResolvedSessionObject<SV, Auth, SessionObject<SV>>,\n BaseRequest,\n BaseResponse,\n NextFunction\n >[]\n): ExpressLikeTypedHandler<\n SV,\n Name,\n ContractMethod,\n Path,\n P,\n ResBodyMap,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n ResHeaders,\n LocalsObj,\n VersionedApi,\n BaseRequest,\n BaseResponse,\n NextFunction,\n Auth\n>;\nexport function typedHandler<\n SV extends AnySchemaValidator,\n Name extends string,\n ContractMethod extends Method,\n Path extends `/${string}`,\n P extends ParamsObject<SV>,\n ResBodyMap extends ResponsesObject<SV>,\n ReqBody extends Body<SV>,\n ReqQuery extends QueryObject<SV>,\n ReqHeaders extends HeadersObject<SV>,\n ResHeaders extends HeadersObject<SV>,\n LocalsObj extends Record<string, unknown>,\n const VersionedApi extends VersionSchema<SV, ContractMethod>,\n BaseRequest,\n BaseResponse,\n NextFunction,\n const Auth extends SchemaAuthMethods<\n SV,\n P,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n VersionedApi,\n BaseRequest\n >\n>(\n _schemaValidator: SV,\n _contractMethod: ContractMethod,\n contractDetails: ContractDetails<\n SV,\n Name,\n ContractMethod,\n Path,\n P,\n ResBodyMap,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n ResHeaders,\n VersionedApi,\n BaseRequest,\n Auth\n >,\n ...handlers: ExpressLikeSchemaHandler<\n SV,\n P,\n ResBodyMap,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n ResHeaders,\n LocalsObj,\n VersionedApi,\n ResolvedSessionObject<SV, Auth, SessionObject<SV>>,\n BaseRequest,\n BaseResponse,\n NextFunction\n >[]\n): ExpressLikeTypedHandler<\n SV,\n Name,\n ContractMethod,\n Path,\n P,\n ResBodyMap,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n ResHeaders,\n LocalsObj,\n VersionedApi,\n BaseRequest,\n BaseResponse,\n NextFunction,\n Auth\n>;\nexport function typedHandler<\n SV extends AnySchemaValidator,\n Name extends string,\n ContractMethod extends Method,\n Path extends `/${string}`,\n P extends ParamsObject<SV>,\n ResBodyMap extends ResponsesObject<SV>,\n ReqBody extends Body<SV>,\n ReqQuery extends QueryObject<SV>,\n ReqHeaders extends HeadersObject<SV>,\n ResHeaders extends HeadersObject<SV>,\n LocalsObj extends Record<string, unknown>,\n const VersionedApi extends VersionSchema<SV, ContractMethod>,\n BaseRequest,\n BaseResponse,\n NextFunction,\n const Auth extends SchemaAuthMethods<\n SV,\n P,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n VersionedApi,\n BaseRequest\n >\n>(\n _schemaValidator: SV,\n pathOrContractMethod: Path | ContractMethod,\n contractMethodOrContractDetails:\n | ContractMethod\n | ContractDetails<\n SV,\n Name,\n ContractMethod,\n Path,\n P,\n ResBodyMap,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n ResHeaders,\n VersionedApi,\n BaseRequest,\n Auth\n >,\n contractDetailsOrHandler:\n | ContractDetails<\n SV,\n Name,\n ContractMethod,\n Path,\n P,\n ResBodyMap,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n ResHeaders,\n VersionedApi,\n BaseRequest,\n Auth\n >\n | ExpressLikeSchemaHandler<\n SV,\n P,\n ResBodyMap,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n ResHeaders,\n LocalsObj,\n VersionedApi,\n ResolvedSessionObject<SV, Auth, SessionObject<SV>>,\n BaseRequest,\n BaseResponse,\n NextFunction\n >,\n ...handlerArray: ExpressLikeSchemaHandler<\n SV,\n P,\n ResBodyMap,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n ResHeaders,\n LocalsObj,\n VersionedApi,\n ResolvedSessionObject<SV, Auth, SessionObject<SV>>,\n BaseRequest,\n BaseResponse,\n NextFunction\n >[]\n): ExpressLikeTypedHandler<\n SV,\n Name,\n ContractMethod,\n Path,\n P,\n ResBodyMap,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n ResHeaders,\n LocalsObj,\n VersionedApi,\n BaseRequest,\n BaseResponse,\n NextFunction,\n Auth\n> {\n // TODO: Clean this up with guards\n\n let contractDetails: ContractDetails<\n SV,\n Name,\n ContractMethod,\n Path,\n P,\n ResBodyMap,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n ResHeaders,\n VersionedApi,\n BaseRequest,\n Auth\n >;\n let handlers: ExpressLikeSchemaHandler<\n SV,\n P,\n ResBodyMap,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n ResHeaders,\n LocalsObj,\n VersionedApi,\n ResolvedSessionObject<SV, Auth, SessionObject<SV>>,\n BaseRequest,\n BaseResponse,\n NextFunction\n >[];\n if (typeof contractMethodOrContractDetails === 'string') {\n if (typeof contractDetailsOrHandler !== 'function') {\n contractDetails = contractDetailsOrHandler;\n } else {\n throw new Error('Invalid definition for contract details');\n }\n handlers = handlerArray;\n } else {\n contractDetails = contractMethodOrContractDetails;\n if (typeof contractDetailsOrHandler === 'function') {\n handlers = [contractDetailsOrHandler, ...handlerArray];\n } else {\n throw new Error('Invalid definition for handler');\n }\n }\n\n if (\n isPath(pathOrContractMethod) &&\n typeof contractMethodOrContractDetails !== 'string'\n ) {\n throw new Error('Contract method not supplied, bailing');\n }\n\n return {\n _typedHandler: true as const,\n _path: isPath(pathOrContractMethod) ? pathOrContractMethod : undefined,\n _method: isPath(pathOrContractMethod)\n ? (contractMethodOrContractDetails as ContractMethod)\n : pathOrContractMethod,\n contractDetails,\n handlers\n };\n}\n","import { AnySchemaValidator } from '@forklaunch/validator';\nimport { ExpressLikeSchemaHandler } from '../types/apiDefinition.types';\nimport {\n Body,\n HeadersObject,\n ParamsObject,\n PathParamHttpContractDetails,\n QueryObject,\n ResolvedSessionObject,\n ResponsesObject,\n SchemaAuthMethods,\n SessionObject,\n VersionSchema\n} from '../types/contractDetails.types';\nimport { typedHandler } from './typedHandler';\n\nexport const delete_ = <\n SV extends AnySchemaValidator,\n Name extends string,\n Path extends `/${string}`,\n P extends ParamsObject<SV>,\n ResBodyMap extends ResponsesObject<SV>,\n ReqBody extends Body<SV>,\n ReqQuery extends QueryObject<SV>,\n ReqHeaders extends HeadersObject<SV>,\n ResHeaders extends HeadersObject<SV>,\n LocalsObj extends Record<string, unknown>,\n VersionedApi extends VersionSchema<SV, 'delete'>,\n BaseRequest,\n BaseResponse,\n NextFunction,\n const Auth extends SchemaAuthMethods<\n SV,\n P,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n VersionedApi,\n BaseRequest\n >\n>(\n _schemaValidator: SV,\n path: Path,\n contractDetails: PathParamHttpContractDetails<\n SV,\n Name,\n Path,\n P,\n ResBodyMap,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n ResHeaders,\n VersionedApi,\n BaseRequest,\n Auth\n >,\n ...handlers: ExpressLikeSchemaHandler<\n SV,\n P,\n ResBodyMap,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n ResHeaders,\n LocalsObj,\n VersionedApi,\n ResolvedSessionObject<SV, Auth, SessionObject<SV>>,\n BaseRequest,\n BaseResponse,\n NextFunction\n >[]\n) => {\n return typedHandler<\n SV,\n Name,\n 'delete',\n Path,\n P,\n ResBodyMap,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n ResHeaders,\n LocalsObj,\n VersionedApi,\n BaseRequest,\n BaseResponse,\n NextFunction,\n Auth\n >(_schemaValidator, path, 'delete', contractDetails, ...handlers);\n};\n","import { AnySchemaValidator } from '@forklaunch/validator';\nimport { ExpressLikeSchemaHandler } from '../types/apiDefinition.types';\nimport {\n Body,\n HeadersObject,\n ParamsObject,\n PathParamHttpContractDetails,\n QueryObject,\n ResolvedSessionObject,\n ResponsesObject,\n SchemaAuthMethods,\n SessionObject,\n VersionSchema\n} from '../types/contractDetails.types';\nimport { typedHandler } from './typedHandler';\n\nexport const get = <\n SV extends AnySchemaValidator,\n Name extends string,\n Path extends `/${string}`,\n P extends ParamsObject<SV>,\n ResBodyMap extends ResponsesObject<SV>,\n ReqBody extends Body<SV>,\n ReqQuery extends QueryObject<SV>,\n ReqHeaders extends HeadersObject<SV>,\n ResHeaders extends HeadersObject<SV>,\n LocalsObj extends Record<string, unknown>,\n VersionedApi extends VersionSchema<SV, 'get'>,\n BaseRequest,\n BaseResponse,\n NextFunction,\n const Auth extends SchemaAuthMethods<\n SV,\n P,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n VersionedApi,\n BaseRequest\n >\n>(\n _schemaValidator: SV,\n path: Path,\n contractDetails: PathParamHttpContractDetails<\n SV,\n Name,\n Path,\n P,\n ResBodyMap,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n ResHeaders,\n VersionedApi,\n BaseRequest,\n Auth\n >,\n ...handlers: ExpressLikeSchemaHandler<\n SV,\n P,\n ResBodyMap,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n ResHeaders,\n LocalsObj,\n VersionedApi,\n ResolvedSessionObject<SV, Auth, SessionObject<SV>>,\n BaseRequest,\n BaseResponse,\n NextFunction\n >[]\n) => {\n return typedHandler<\n SV,\n Name,\n 'get',\n Path,\n P,\n ResBodyMap,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n ResHeaders,\n LocalsObj,\n VersionedApi,\n BaseRequest,\n BaseResponse,\n NextFunction,\n Auth\n >(_schemaValidator, path, 'get', contractDetails, ...handlers);\n};\n","import { AnySchemaValidator } from '@forklaunch/validator';\nimport { ExpressLikeSchemaHandler } from '../types/apiDefinition.types';\nimport {\n Body,\n HeadersObject,\n ParamsObject,\n PathParamHttpContractDetails,\n QueryObject,\n ResolvedSessionObject,\n ResponsesObject,\n SchemaAuthMethods,\n SessionObject,\n VersionSchema\n} from '../types/contractDetails.types';\nimport { typedHandler } from './typedHandler';\n\nexport const head = <\n SV extends AnySchemaValidator,\n Name extends string,\n Path extends `/${string}`,\n P extends ParamsObject<SV>,\n ResBodyMap extends ResponsesObject<SV>,\n ReqBody extends Body<SV>,\n ReqQuery extends QueryObject<SV>,\n ReqHeaders extends HeadersObject<SV>,\n ResHeaders extends HeadersObject<SV>,\n LocalsObj extends Record<string, unknown>,\n VersionedApi extends VersionSchema<SV, 'head'>,\n BaseRequest,\n BaseResponse,\n NextFunction,\n const Auth extends SchemaAuthMethods<\n SV,\n P,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n VersionedApi,\n BaseRequest\n >\n>(\n _schemaValidator: SV,\n path: Path,\n contractDetails: PathParamHttpContractDetails<\n SV,\n Name,\n Path,\n P,\n ResBodyMap,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n ResHeaders,\n VersionedApi,\n BaseRequest,\n Auth\n >,\n ...handlers: ExpressLikeSchemaHandler<\n SV,\n P,\n ResBodyMap,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n ResHeaders,\n LocalsObj,\n VersionedApi,\n ResolvedSessionObject<SV, Auth, SessionObject<SV>>,\n BaseRequest,\n BaseResponse,\n NextFunction\n >[]\n) => {\n return typedHandler<\n SV,\n Name,\n 'head',\n Path,\n P,\n ResBodyMap,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n ResHeaders,\n LocalsObj,\n VersionedApi,\n BaseRequest,\n BaseResponse,\n NextFunction,\n Auth\n >(_schemaValidator, path, 'head', contractDetails, ...handlers);\n};\n","import { AnySchemaValidator } from '@forklaunch/validator';\nimport { ExpressLikeSchemaHandler } from '../types/apiDefinition.types';\nimport {\n Body,\n ContractDetails,\n HeadersObject,\n MiddlewareContractDetails,\n ParamsObject,\n QueryObject,\n ResolvedSessionObject,\n ResponsesObject,\n SchemaAuthMethods,\n SessionObject,\n VersionSchema\n} from '../types/contractDetails.types';\nimport { typedHandler } from './typedHandler';\n\nexport const middleware = <\n SV extends AnySchemaValidator,\n Name extends string,\n Path extends `/${string}`,\n P extends ParamsObject<SV>,\n ResBodyMap extends ResponsesObject<SV>,\n ReqBody extends Body<SV>,\n ReqQuery extends QueryObject<SV>,\n ReqHeaders extends HeadersObject<SV>,\n ResHeaders extends HeadersObject<SV>,\n LocalsObj extends Record<string, unknown>,\n VersionedApi extends VersionSchema<SV, 'middleware'>,\n BaseRequest,\n BaseResponse,\n NextFunction,\n const Auth extends SchemaAuthMethods<\n SV,\n P,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n VersionedApi,\n BaseRequest\n >\n>(\n _schemaValidator: SV,\n path: Path,\n contractDetails: MiddlewareContractDetails<\n SV,\n Name,\n Path,\n P,\n ResBodyMap,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n ResHeaders,\n VersionedApi,\n BaseRequest,\n Auth\n >,\n ...handlers: ExpressLikeSchemaHandler<\n SV,\n P,\n ResBodyMap,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n ResHeaders,\n LocalsObj,\n VersionedApi,\n ResolvedSessionObject<SV, Auth, SessionObject<SV>>,\n BaseRequest,\n BaseResponse,\n NextFunction\n >[]\n) => {\n return typedHandler<\n SV,\n Name,\n 'middleware',\n Path,\n P,\n ResBodyMap,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n ResHeaders,\n LocalsObj,\n VersionedApi,\n BaseRequest,\n BaseResponse,\n NextFunction,\n Auth\n >(_schemaValidator, path, 'middleware', contractDetails, ...handlers) as {\n _typedHandler: true;\n _path: Path;\n contractDetails: ContractDetails<\n SV,\n Name,\n 'middleware',\n Path,\n P,\n ResBodyMap,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n ResHeaders,\n VersionedApi,\n BaseRequest,\n Auth\n >;\n handlers: ExpressLikeSchemaHandler<\n SV,\n P,\n ResBodyMap,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n ResHeaders,\n LocalsObj,\n VersionedApi,\n ResolvedSessionObject<SV, Auth, SessionObject<SV>>,\n BaseRequest,\n BaseResponse,\n NextFunction\n >[];\n };\n};\n","import { AnySchemaValidator } from '@forklaunch/validator';\nimport { ExpressLikeSchemaHandler } from '../types/apiDefinition.types';\nimport {\n Body,\n HeadersObject,\n ParamsObject,\n PathParamHttpContractDetails,\n QueryObject,\n ResolvedSessionObject,\n ResponsesObject,\n SchemaAuthMethods,\n SessionObject,\n VersionSchema\n} from '../types/contractDetails.types';\nimport { typedHandler } from './typedHandler';\n\nexport const options = <\n SV extends AnySchemaValidator,\n Name extends string,\n Path extends `/${string}`,\n P extends ParamsObject<SV>,\n ResBodyMap extends ResponsesObject<SV>,\n ReqBody extends Body<SV>,\n ReqQuery extends QueryObject<SV>,\n ReqHeaders extends HeadersObject<SV>,\n ResHeaders extends HeadersObject<SV>,\n LocalsObj extends Record<string, unknown>,\n VersionedApi extends VersionSchema<SV, 'options'>,\n BaseRequest,\n BaseResponse,\n NextFunction,\n const Auth extends SchemaAuthMethods<\n SV,\n P,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n VersionedApi,\n BaseRequest\n >\n>(\n _schemaValidator: SV,\n path: Path,\n contractDetails: PathParamHttpContractDetails<\n SV,\n Name,\n Path,\n P,\n ResBodyMap,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n ResHeaders,\n VersionedApi,\n BaseRequest,\n Auth\n >,\n ...handlers: ExpressLikeSchemaHandler<\n SV,\n P,\n ResBodyMap,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n ResHeaders,\n LocalsObj,\n VersionedApi,\n ResolvedSessionObject<SV, Auth, SessionObject<SV>>,\n BaseRequest,\n BaseResponse,\n NextFunction\n >[]\n) => {\n return typedHandler<\n SV,\n Name,\n 'options',\n Path,\n P,\n ResBodyMap,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n ResHeaders,\n LocalsObj,\n VersionedApi,\n BaseRequest,\n BaseResponse,\n NextFunction,\n Auth\n >(_schemaValidator, path, 'options', contractDetails, ...handlers);\n};\n","import { AnySchemaValidator } from '@forklaunch/validator';\nimport { ExpressLikeSchemaHandler } from '../types/apiDefinition.types';\nimport {\n Body,\n HeadersObject,\n HttpContractDetails,\n ParamsObject,\n QueryObject,\n ResolvedSessionObject,\n ResponsesObject,\n SchemaAuthMethods,\n SessionObject,\n VersionSchema\n} from '../types/contractDetails.types';\nimport { typedHandler } from './typedHandler';\n\nexport const patch = <\n SV extends AnySchemaValidator,\n Name extends string,\n Path extends `/${string}`,\n P extends ParamsObject<SV>,\n ResBodyMap extends ResponsesObject<SV>,\n ReqBody extends Body<SV>,\n ReqQuery extends QueryObject<SV>,\n ReqHeaders extends HeadersObject<SV>,\n ResHeaders extends HeadersObject<SV>,\n LocalsObj extends Record<string, unknown>,\n VersionedApi extends VersionSchema<SV, 'patch'>,\n BaseRequest,\n BaseResponse,\n NextFunction,\n const Auth extends SchemaAuthMethods<\n SV,\n P,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n VersionedApi,\n BaseRequest\n >\n>(\n _schemaValidator: SV,\n path: Path,\n contractDetails: HttpContractDetails<\n SV,\n Name,\n Path,\n P,\n ResBodyMap,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n ResHeaders,\n VersionedApi,\n BaseRequest,\n Auth\n >,\n ...handlers: ExpressLikeSchemaHandler<\n SV,\n P,\n ResBodyMap,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n ResHeaders,\n LocalsObj,\n VersionedApi,\n ResolvedSessionObject<SV, Auth, SessionObject<SV>>,\n BaseRequest,\n BaseResponse,\n NextFunction\n >[]\n) => {\n return typedHandler<\n SV,\n Name,\n 'patch',\n Path,\n P,\n ResBodyMap,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n ResHeaders,\n LocalsObj,\n VersionedApi,\n BaseRequest,\n BaseResponse,\n NextFunction,\n Auth\n >(_schemaValidator, path, 'patch', contractDetails, ...handlers);\n};\n","import { AnySchemaValidator } from '@forklaunch/validator';\nimport { ExpressLikeSchemaHandler } from '../types/apiDefinition.types';\nimport {\n Body,\n HeadersObject,\n HttpContractDetails,\n ParamsObject,\n QueryObject,\n ResolvedSessionObject,\n ResponsesObject,\n SchemaAuthMethods,\n SessionObject,\n VersionSchema\n} from '../types/contractDetails.types';\nimport { typedHandler } from './typedHandler';\n\nexport const post = <\n SV extends AnySchemaValidator,\n Name extends string,\n Path extends `/${string}`,\n P extends ParamsObject<SV>,\n ResBodyMap extends ResponsesObject<SV>,\n ReqBody extends Body<SV>,\n ReqQuery extends QueryObject<SV>,\n ReqHeaders extends HeadersObject<SV>,\n ResHeaders extends HeadersObject<SV>,\n LocalsObj extends Record<string, unknown>,\n VersionedApi extends VersionSchema<SV, 'post'>,\n BaseRequest,\n BaseResponse,\n NextFunction,\n const Auth extends SchemaAuthMethods<\n SV,\n P,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n VersionedApi,\n BaseRequest\n >\n>(\n _schemaValidator: SV,\n path: Path,\n contractDetails: HttpContractDetails<\n SV,\n Name,\n Path,\n P,\n ResBodyMap,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n ResHeaders,\n VersionedApi,\n BaseRequest,\n Auth\n >,\n ...handlers: ExpressLikeSchemaHandler<\n SV,\n P,\n ResBodyMap,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n ResHeaders,\n LocalsObj,\n VersionedApi,\n ResolvedSessionObject<SV, Auth, SessionObject<SV>>,\n BaseRequest,\n BaseResponse,\n NextFunction\n >[]\n) => {\n return typedHandler<\n SV,\n Name,\n 'post',\n Path,\n P,\n ResBodyMap,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n ResHeaders,\n LocalsObj,\n VersionedApi,\n BaseRequest,\n BaseResponse,\n NextFunction,\n Auth\n >(_schemaValidator, path, 'post', contractDetails, ...handlers);\n};\n","import { AnySchemaValidator } from '@forklaunch/validator';\nimport { ExpressLikeSchemaHandler } from '../types/apiDefinition.types';\nimport {\n Body,\n HeadersObject,\n HttpContractDetails,\n ParamsObject,\n QueryObject,\n ResolvedSessionObject,\n ResponsesObject,\n SchemaAuthMethods,\n SessionObject,\n VersionSchema\n} from '../types/contractDetails.types';\nimport { typedHandler } from './typedHandler';\n\nexport const put = <\n SV extends AnySchemaValidator,\n Name extends string,\n Path extends `/${string}`,\n P extends ParamsObject<SV>,\n ResBodyMap extends ResponsesObject<SV>,\n ReqBody extends Body<SV>,\n ReqQuery extends QueryObject<SV>,\n ReqHeaders extends HeadersObject<SV>,\n ResHeaders extends HeadersObject<SV>,\n LocalsObj extends Record<string, unknown>,\n VersionedApi extends VersionSchema<SV, 'put'>,\n BaseRequest,\n BaseResponse,\n NextFunction,\n const Auth extends SchemaAuthMethods<\n SV,\n P,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n VersionedApi,\n BaseRequest\n >\n>(\n _schemaValidator: SV,\n path: Path,\n contractDetails: HttpContractDetails<\n SV,\n Name,\n Path,\n P,\n ResBodyMap,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n ResHeaders,\n VersionedApi,\n BaseRequest,\n Auth\n >,\n ...handlers: ExpressLikeSchemaHandler<\n SV,\n P,\n ResBodyMap,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n ResHeaders,\n LocalsObj,\n VersionedApi,\n ResolvedSessionObject<SV, Auth, SessionObject<SV>>,\n BaseRequest,\n BaseResponse,\n NextFunction\n >[]\n) => {\n return typedHandler<\n SV,\n Name,\n 'put',\n Path,\n P,\n ResBodyMap,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n ResHeaders,\n LocalsObj,\n VersionedApi,\n BaseRequest,\n BaseResponse,\n NextFunction,\n Auth\n >(_schemaValidator, path, 'put', contractDetails, ...handlers);\n};\n","import { AnySchemaValidator } from '@forklaunch/validator';\nimport { ExpressLikeSchemaHandler } from '../types/apiDefinition.types';\nimport {\n Body,\n HeadersObject,\n ParamsObject,\n PathParamHttpContractDetails,\n QueryObject,\n ResolvedSessionObject,\n ResponsesObject,\n SchemaAuthMethods,\n SessionObject,\n VersionSchema\n} from '../types/contractDetails.types';\nimport { typedHandler } from './typedHandler';\n\nexport const trace = <\n SV extends AnySchemaValidator,\n Name extends string,\n Path extends `/${string}`,\n P extends ParamsObject<SV>,\n ResBodyMap extends ResponsesObject<SV>,\n ReqBody extends Body<SV>,\n ReqQuery extends QueryObject<SV>,\n ReqHeaders extends HeadersObject<SV>,\n ResHeaders extends HeadersObject<SV>,\n LocalsObj extends Record<string, unknown>,\n VersionedApi extends VersionSchema<SV, 'trace'>,\n BaseRequest,\n BaseResponse,\n NextFunction,\n const Auth extends SchemaAuthMethods<\n SV,\n P,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n VersionedApi,\n BaseRequest\n >\n>(\n _schemaValidator: SV,\n path: Path,\n contractDetails: PathParamHttpContractDetails<\n SV,\n Name,\n Path,\n P,\n ResBodyMap,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n ResHeaders,\n VersionedApi,\n BaseRequest,\n Auth\n >,\n ...handlers: ExpressLikeSchemaHandler<\n SV,\n P,\n ResBodyMap,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n ResHeaders,\n LocalsObj,\n VersionedApi,\n ResolvedSessionObject<SV, Auth, SessionObject<SV>>,\n BaseRequest,\n BaseResponse,\n NextFunction\n >[]\n) => {\n return typedHandler<\n SV,\n Name,\n 'trace',\n Path,\n P,\n ResBodyMap,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n ResHeaders,\n LocalsObj,\n VersionedApi,\n BaseRequest,\n BaseResponse,\n NextFunction,\n Auth\n >(_schemaValidator, path, 'trace', contractDetails, ...handlers);\n};\n","import { AnySchemaValidator } from '@forklaunch/validator';\nimport { ExpressLikeSchemaAuthMapper } from '../types/apiDefinition.types';\nimport {\n Body,\n ContractDetails,\n HeadersObject,\n Method,\n ParamsObject,\n QueryObject,\n ResolvedSessionObject,\n ResponsesObject,\n SchemaAuthMethods,\n SessionObject,\n VersionSchema\n} from '../types/contractDetails.types';\n\nexport function typedAuthHandler<\n SV extends AnySchemaValidator,\n Name extends string,\n P extends ParamsObject<SV>,\n ResBodyMap extends ResponsesObject<SV>,\n ReqBody extends Body<SV>,\n ReqQuery extends QueryObject<SV>,\n ReqHeaders extends HeadersObject<SV>,\n ResHeaders extends HeadersObject<SV>,\n VersionedApi extends VersionSchema<SV, Method>,\n Auth extends SchemaAuthMethods<\n SV,\n P,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n VersionedApi,\n BaseRequest\n >,\n BaseRequest\n>(\n _schemaValidator: SV,\n _contractDetails: ContractDetails<\n SV,\n Name,\n Method,\n `/${string}`,\n P,\n ResBodyMap,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n ResHeaders,\n VersionedApi,\n BaseRequest,\n Auth\n >,\n authHandler: ExpressLikeSchemaAuthMapper<\n SV,\n P,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n VersionedApi,\n ResolvedSessionObject<SV, Auth, SessionObject<SV>>,\n BaseRequest\n >\n) {\n return authHandler;\n}\n","/**\n * Object-map of the HTTP Status Codes. Maps from the status code, to the\n * textual name. The key is the HTTP Status Code number, and the resulting\n * value will be the textual name for that Status Code.\n *\n * The comments for each item are taken from httpstatuses.com and the RFC-7231\n * document.\n *\n * @see https://httpstatuses.com\n * @see https://datatracker.ietf.org/doc/html/rfc7231\n */\nexport const HTTPStatuses: Readonly<{ [key: number]: string }> = {\n /**\n * The initial part of a request has been received and has not yet been\n * rejected by the server. The server intends to send a final response after\n * the request has been fully received and acted upon.\n *\n * When the request contains an Expect header field that includes a\n * 100-continue expectation, the 100 response indicates that the server\n * wishes to receive the request payload body. The client ought to continue\n * sending the request and discard the 100 response.\n *\n * If the request did not contain an Expect header field containing the\n * 100-continue expectation, the client can simply discard this interim\n * response.\n */\n 100: 'Continue',\n\n /**\n * The server understands and is willing to comply with the client's request,\n * via the Upgrade header field, for a change in the application protocol\n * being used on this connection.\n *\n * The server MUST generate an Upgrade header field in the response that\n * indicates which protocol(s) will be switched to immediately after the\n * empty line that terminates the 101 response.\n *\n * It is assumed that the server will only agree to switch protocols when it\n * is advantageous to do so. For example, switching to a newer version of\n * HTTP might be advantageous over older versions, and switching to a\n * real-time, synchronous protocol might be advantageous when delivering\n * resources that use such features.\n */\n 101: 'Switching Protocols',\n\n /**\n * An interim response used to inform the client that the server has accepted\n * the complete request, but has not yet completed it.\n *\n * This status code SHOULD only be sent when the server has a reasonable\n * expectation that the request will take significant time to complete. As\n * guidance, if a method is taking longer than 20 seconds (a reasonable, but\n * arbitrary value) to process the server SHOULD return a 102 (Processing)\n * response. The server MUST send a final response after the request has been\n * completed.\n *\n * Methods can potentially take a long period of time to process, especially\n * methods that support the Depth header. In such cases the client may\n * time-out the connection while waiting for a response. To prevent this the\n * server may return a 102 Processing status code to indicate to the client\n * that the server is still processing the method.\n */\n 102: 'Processing',\n\n /**\n * The request has succeeded.\n *\n * Aside from responses to CONNECT, a 200 response always has a payload,\n * though an origin server MAY generate a payload body of zero length. If no\n * payload is desired, an origin server ought to send 204 No Content instead.\n * For CONNECT, no payload is allowed because the successful result is a\n * tunnel, which begins immediately after the 200 response header section.\n *\n * A 200 response is cacheable by default; i.e., unless otherwise indicated\n * by the method definition or explicit cache controls.\n */\n 200: 'OK',\n\n /**\n * The request has been fulfilled and has resulted in one or more new\n * resources being created.\n *\n * The primary resource created by the request is identified by either a\n * Location header field in the response or, if no Location field is\n * received, by the effective request URI.\n *\n * The 201 response payload typically describes and links to the resource(s)\n * created. See Section 7.2 of RFC7231 for a discussion of the meaning and\n * purpose of validator header fields, such as ETag and Last-Modified, in a\n * 201 response.\n */\n 201: 'Created',\n\n /**\n * The request has been accepted for processing, but the processing has not\n * been completed. The request might or might not eventually be acted upon,\n * as it might be disallowed when processing actually takes place.\n *\n * There is no facility in HTTP for re-sending a status code from an\n * asynchronous operation.\n *\n * The 202 response is intentionally noncommittal. Its purpose is to allow a\n * server to accept a request for some other process (perhaps a\n * batch-oriented process that is only run once per day) without requiring\n * that the user agent's connection to the server persist until the process\n * is completed. The representation sent with this response ought to describe\n * the request's current status and point to (or embed) a status monitor that\n * can provide the user with an estimate of when the request will be\n * fulfilled.\n */\n 202: 'Accepted',\n\n /**\n * The request was successful but the enclosed payload has been modified from\n * that of the origin server's 200 OK response by a transforming proxy.\n *\n * This status code allows the proxy to notify recipients when a\n * transformation has been applied, since that knowledge might impact later\n * decisions regarding the content. For example, future cache validation\n * requests for the content might only be applicable along the same request\n * path (through the same proxies).\n *\n * The 203 response is similar to the Warning code of 214 Transformation\n * Applied, which has the advantage of being applicable to responses with any\n * status code.\n *\n * A 203 response is cacheable by default; i.e., unless otherwise indicated\n * by the method definition or explicit cache controls.\n */\n 203: 'Non-authoritative Information',\n\n /**\n * The server has successfully fulfilled the request and that there is no\n * additional content to send in the response payload body.\n *\n * Metadata in the response header fields refer to the target resource and\n * its selected representation after the requested action was applied.\n *\n * A 204 response is terminated by the first empty line after the header\n * fields because it cannot contain a message body.\n *\n * A 204 response is cacheable by default; i.e., unless otherwise indicated\n * by the method definition or explicit cache controls.\n */\n 204: 'No Content',\n\n /**\n * He server has fulfilled the request and desires that the user agent reset\n * the \"document view\", which caused the request to be sent, to its original\n * state as received from the origin server.\n *\n * This response is intended to support a common data entry use case where\n * the user receives content that supports data entry (a form, notepad,\n * canvas, etc.), enters or manipulates data in that space, causes the\n * entered data to be submitted in a request, and then the data entry\n * mechanism is reset for the next entry so that the user can easily\n * initiate another input action.\n *\n * Since the 205 status code implies that no additional content will be\n * provided, a server MUST NOT generate a payload in a 205 response. In\n * other words, a server MUST do one of the following for a 205 response: a)\n * indicate a zero-length body for the response by including a\n * Content-Length header field with a value of 0; b) indicate a zero-length\n * payload for the response by including a Transfer-Encoding header field\n * with a value of chunked and a message body consisting of a single chunk\n * of zero-length; or, c) close the connection immediately after sending the\n * blank line terminating the header section.\n */\n 205: 'Reset Content',\n\n /**\n * The server is successfully fulfilling a range request for the target\n * resource by transferring one or more parts of the selected representation\n * that correspond to the satisfiable ranges found in the request's Range\n * header field.\n *\n * If a single part is being transferred, the server generating the 206\n * response MUST generate a Content-Range header field, describing what range\n * of the selected representation is enclosed, and a payload consisting of\n * the range.\n *\n * If multiple parts are being transferred, the server generating the 206\n * response MUST generate a \"multipart/byteranges\" payload2, and a\n * Content-Type header field containing the multipart/byteranges media type\n * and its required boundary parameter. To avoid confusion with single-part\n * responses, a server MUST NOT generate a Content-Range header field in the\n * HTTP header section of a multiple part response (this field will be sent\n * in each part instead).\n *\n * Within the header area of each body part in the multipart payload, the\n * server MUST generate a Content-Range header field corresponding to the\n * range being enclosed in that body part. If the selected representation\n * would have had a Content-Type header field in a 200 OK response, the\n * server SHOULD generate that same Content-Type field in the header area of\n * each body part.\n *\n * When multiple ranges are requested, a server MAY coalesce any of the\n * ranges that overlap, or that are separated by a gap that is smaller than\n * the overhead of sending multiple parts, regardless of the order in which\n * the corresponding byte-range-spec appeared in the received Range header\n * field. Since the typical overhead between parts of a multipart/byteranges\n * payload is around 80 bytes, depending on the selected representation's\n * media type and the chosen boundary parameter length, it can be less\n * efficient to transfer many small disjoint parts than it is to transfer the\n * entire selected representation.\n *\n * A server MUST NOT generate a multipart response to a request for a single\n * range, since a client that does not request multiple parts might not\n * support multipart responses. However, a server MAY generate a\n * multipart/byteranges payload with only a single body part if multiple\n * ranges were requested and only one range was found to be satisfiable or\n * only one range remained after coalescing. A client that cannot process a\n * multipart/byteranges response MUST NOT generate a request that asks for\n * multiple ranges.\n *\n * When a multipart response payload is generated, the server SHOULD send the\n * parts in the same order that the corresponding byte-range-spec appeared in\n * the received Range header field, excluding those ranges that were deemed\n * unsatisfiable or that were coalesced into other ranges. A client that\n * receives a multipart response MUST inspect the Content-Range header field\n * present in each body part in order to determine which range is contained\n * in that body part; a client cannot rely on receiving the same ranges that\n * it requested, nor the same order that it requested.\n *\n * When a 206 response is generated, the server MUST generate the following\n * header fields, in addition to those required above, if the field would\n * have been sent in a 200 OK response to the same request: Date,\n * Cache-Control, ETag, Expires, Content-Location, and Vary.\n *\n * If a 206 is generated in response to a request with an If-Range header\n * field, the sender SHOULD NOT generate other representation header fields\n * beyond those required above, because the client is understood to already\n * have a prior response containing those header fields. Otherwise, the\n * sender MUST generate all of the representation header fields that would\n * have been sent in a 200 OK response to the same request.\n *\n * A 206 response is cacheable by default; i.e., unless otherwise indicated\n * by explicit cache controls.\n */\n 206: 'Partial Content',\n\n /**\n * A Multi-Status response conveys information about multiple resources in\n * situations where multiple status codes might be appropriate.\n *\n * The default Multi-Status response body is a text/xml or application/xml\n * HTTP entity with a 'multistatus' root element. Further elements contain\n * 200, 300, 400, and 500 series status codes generated during the method\n * invocation. 100 series status codes SHOULD NOT be recorded in a 'response'\n * XML element.\n *\n * Although '207' is used as the overall response status code, the recipient\n * needs to consult the contents of the multistatus response body for further\n * information about the success or failure of the method execution. The\n * response MAY be used in success, partial success and also in failure\n * situations.\n *\n * The 'multistatus' root element holds zero or more 'response' elements in\n * any order, each with information about an individual resource. Each\n * 'response' element MUST have an 'href' element to identify the resource.\n *\n * A Multi-Status response uses one out of two distinct formats for\n * representing the status:\n *\n * 1. A 'status' element as child of the 'response' element indicates the\n * status of the message execution for the identified resource as a whole.\n * Some method definitions provide information about specific status codes\n * clients should be prepared to see in a response. However, clients MUST be\n * able to handle other status codes, using the generic rules defined in\n * RFC2616 Section 10.\n *\n * 2. For PROPFIND and PROPPATCH, the format has been extended using the\n * 'propstat' element instead of 'status', providing information about\n * individual properties of a resource. This format is specific to PROPFIND\n * and PROPPATCH, and is described in detail in RFC4918 Section 9.1 and\n * RFC4918 Section 9.2.\n */\n 207: 'Multi-Status',\n\n /**\n * Used inside a DAV: propstat response element to avoid enumerating the\n * internal members of multiple bindings to the same collection repeatedly.\n *\n * For each binding to a collection inside the request's scope, only one will\n * be reported with a 200 status, while subsequent DAV:response elements for\n * all other bindings will use the 208 status, and no DAV:response elements\n * for their descendants are included.\n *\n * Note that the 208 status will only occur for \"Depth: infinity\" requests,\n * and that it is of particular importance when the multiple collection\n * bindings cause a bind loop.\n *\n * A client can request the DAV:resource-id property in a PROPFIND request to\n * guarantee that they can accurately reconstruct the binding structure of a\n * collection with multiple bindings to a single resource.\n *\n * For backward compatibility with clients not aware of the 208 status code\n * appearing in multistatus response bodies, it SHOULD NOT be used unless the\n * client has signaled support for this specification using the \"DAV\" request\n * header. Instead, a 508 Loop Detected status should be returned when a\n * binding loop is discovered. This allows the server to return the 508 as\n * the top-level return status, if it discovers it before it started the\n * response, or in the middle of a multistatus, if it discovers it in the\n * middle of streaming out a multistatus response.\n */\n 208: 'Already Reported',\n\n /**\n * The server has fulfilled a GET request for the resource, and the response\n * is a representation of the result of one or more instance-manipulations\n * applied to the current instance.\n *\n * The actual current instance might not be available except by combining\n * this response with other previous or future responses, as appropriate for\n * the specific instance-manipulation(s). If so, the headers of the resulting\n * instance are the result of combining the headers from the 226 response and\n * the other instances, following the rules in section 13.5.3 of the HTTP/1.1\n * specification.\n *\n * The request MUST have included an A-IM header field listing at least one\n * instance-manipulation. The response MUST include an Etag header field\n * giving the entity tag of the current instance.\n *\n * A response received with a status code of 226 MAY be stored by a cache and\n * used in reply to a subsequent request, subject to the HTTP expiration\n * mechanism and any Cache-Control headers, and to the requirements in\n * section 10.6.\n *\n * A response received with a status code of 226 MAY be used by a cache, in\n * conjunction with a cache entry for the base instance, to create a cache\n * entry for the current instance.\n */\n 226: 'IM Used',\n\n /**\n * The target resource has more than one representation, each with its own\n * more specific identifier, and information about the alternatives is being\n * provided so that the user (or user agent) can select a preferred\n * representation by redirecting its request to one or more of those\n * identifiers.\n *\n * In other words, the server desires that the user agent engage in reactive\n * negotiation to select the most appropriate representation(s) for its\n * needs.\n *\n * If the server has a preferred choice, the server SHOULD generate a\n * Location header field containing a preferred choice's URI reference. The\n * user agent MAY use the Location field value for automatic redirection.\n *\n * For request methods other than HEAD, the server SHOULD generate a payload\n * in the 300 response containing a list of representation metadata and URI\n * reference(s) from which the user or user agent can choose the one most\n * preferred. The user agent MAY make a selection from that list\n * automatically if it understands the provided media type. A specific format\n * for automatic selection is not defined by this specification because HTTP\n * tries to remain orthogonal to the definition of its payloads. In practice,\n * the representation is provided in some easily parsed format believed to be\n * acceptable to the user agent, as determined by shared design or content\n * negotiation, or in some commonly accepted hypertext format.\n *\n * A 300 response is cacheable by default; i.e., unless otherwise indicated\n * by the method definition or explicit cache controls.\n *\n * Note: The original proposal for the 300 status code defined the URI header\n * field as providing a list of alternative representations, such that it\n * would be usable for 200, 300, and 406 responses and be transferred in\n * responses to the HEAD method. However, lack of deployment and disagreement\n * over syntax led to both URI and Alternates (a subsequent proposal) being\n * dropped from this specification. It is possible to communicate the list\n * using a set of Link header fields3, each with a relationship of\n * \"alternate\", though deployment is a chicken-and-egg problem.\n */\n 300: 'Multiple Choices',\n\n /**\n * The target resource has been assigned a new permanent URI and any future\n * references to this resource ought to use one of the enclosed URIs.\n *\n * Clients with link-editing capabilities ought to automatically re-link\n * references to the effective request URI to one or more of the new\n * references sent by the server, where possible.\n *\n * The server SHOULD generate a Location header field in the response\n * containing a preferred URI reference for the new permanent URI. The user\n * agent MAY use the Location field value for automatic redirection. The\n * server's response payload usually contains a short hypertext note with a\n * hyperlink to the new URI(s).\n *\n * Note: For historical reasons, a user agent MAY change the request method\n * from POST to GET for the subsequent request. If this behavior is\n * undesired, the 307 Temporary Redirect status code can be used instead.\n *\n * A 301 response is cacheable by default; i.e., unless otherwise indicated\n * by the method definition or explicit cache controls.\n */\n 301: 'Moved Permanently',\n\n /**\n * The target resource resides temporarily under a different URI. Since the\n * redirection might be altered on occasion, the client ought to continue to\n * use the effective request URI for future requests.\n *\n * The server SHOULD generate a Location header field in the response\n * containing a URI reference for the different URI. The user agent MAY use\n * the Location field value for automatic redirection. The server's response\n * payload usually contains a short hypertext note with a hyperlink to the\n * different URI(s).\n *\n * Note: For historical reasons, a user agent MAY change the request method\n * from POST to GET for the subsequent request. If this behavior is\n * undesired, the 307 Temporary Redirect status code can be used instead.\n */\n 302: 'Found',\n\n /**\n * The server is redirecting the user agent to a different resource, as\n * indicated by a URI in the Location header field, which is intended to\n * provide an indirect response to the original request.\n *\n * A user agent can perform a retrieval request targeting that URI (a GET or\n * HEAD request if using HTTP), which might also be redirected, and present\n * the eventual result as an answer to the original request. Note that the\n * new URI in the Location header field is not considered equivalent to the\n * effective request URI.\n *\n * This status code is applicable to any HTTP method. It is primarily used\n * to allow the output of a POST action to redirect the user agent to a\n * selected resource, since doing so provides the information corresponding\n * to the POST response in a form that can be separately identified,\n * bookmarked, and cached, independent of the original request.\n *\n * A 303 response to a GET request indicates that the origin server does not\n * have a representation of the target resource that can be transferred by\n * the server over HTTP. However, the Location field value refers to a\n * resource that is descriptive of the target resource, such that making a\n * retrieval request on that other resource might result in a representation\n * that is useful to recipients without implying that it represents the\n * original target resource. Note that answers to the questions of what can\n * be represented, what representations are adequate, and what might be a\n * useful description are outside the scope of HTTP.\n *\n * Except for responses to a HEAD request, the representation of a 303\n * response ought to contain a short hypertext note with a hyperlink to the\n * same URI reference provided in the Location header field.\n */\n 303: 'See Other',\n\n /**\n * A conditional GET or HEAD request has been received and would have\n * resulted in a 200 OK response if it were not for the fact that the\n * condition evaluated to false.\n *\n * In other words, there is no need for the server to transfer a\n * representation of the target resource because the request indicates that\n * the client, which made the request conditional, already has a valid\n * representation; the server is therefore redirecting the client to make\n * use of that stored representation as if it were the payload of a 200 OK\n * response.\n *\n * The server generating a 304 response MUST generate any of the following\n * header fields that would have been sent in a 200 OK response to the same\n * request: Cache-Control, Content-Location, Date, ETag, Expires, and Vary.\n *\n * Since the goal of a 304 response is to minimize information transfer when\n * the recipient already has one or more cached representations, a sender\n * SHOULD NOT generate representation metadata other than the above listed\n * fields unless said metadata exists for the purpose of guiding cache\n * updates (e.g., Last-Modified might be useful if the response does not have\n * an ETag field).\n *\n * Requirements on a cache that receives a 304 response are defined in\n * Section 4.3.4 of RFC7234. If the conditional request originated with an\n * outbound client, such as a user agent with its own cache sending a\n * conditional GET to a shared proxy, then the proxy SHOULD forward the\n * 304 response to that client.\n *\n * A 304 response cannot contain a message-body; it is always terminated by\n * the first empty line after the header fields.\n */\n 304: 'Not Modified',\n\n /**\n * Defined in a previous version of this specification and is now deprecated,\n * due to security concerns regarding in-band configuration of a proxy.\n */\n 305: 'Use Proxy',\n\n /**\n * The target resource resides temporarily under a different URI and the user\n * agent MUST NOT change the request method if it performs an automatic\n * redirection to that URI.\n *\n * Since the redirection can change over time, the client ought to continue\n * using the original effective request URI for future requests.\n *\n * The server SHOULD generate a Location header field in the response\n * containing a URI reference for the different URI. The user agent MAY use\n * the Location field value for automatic redirection. The server's response\n * payload usually contains a short hypertext note with a hyperlink to the\n * different URI(s).\n *\n * Note: This status code is similar to 302 Found, except that it does not\n * allow changing the request method from POST to GET. This specification\n * defines no equivalent counterpart for 301 Moved Permanently (RFC7238,\n * however, proposes defining the status code 308 Permanent Redirect for\n * this purpose).\n */\n 307: 'Temporary Redirect',\n\n /**\n * The target resource has been assigned a new permanent URI and any future\n * references to this resource ought to use one of the enclosed URIs.\n *\n * Clients with link editing capabilities ought to automatically re-link\n * references to the effective request URI to one or more of the new\n * references sent by the server, where possible.\n *\n * The server SHOULD generate a Location header field in the response\n * containing a preferred URI reference for the new permanent URI. The user\n * agent MAY use the Location field value for automatic redirection. The\n * server's response payload usually contains a short hypertext note with a\n * hyperlink to the new URI(s).\n *\n * A 308 response is cacheable by default; i.e., unless otherwise indicated\n * by the method definition or explicit cache controls.\n *\n * Note: This status code is similar to 301 Moved Permanently, except that it\n * does not allow changing the request method from POST to GET.\n */\n 308: 'Permanent Redirect',\n\n /**\n * The 400 (Bad Request) status code indicates that the server cannot or\n * will not process the request due to something that is perceived to be\n * a client error (e.g., malformed request syntax, invalid request\n * message framing, or deceptive request routing).\n */\n 400: 'Bad Request',\n\n /**\n * The request has not been applied because it lacks valid authentication\n * credentials for the target resource.\n *\n * The server generating a 401 response MUST send a WWW-Authenticate header\n * field containing at least one challenge applicable to the target resource.\n *\n * If the request included authentication credentials, then the 401 response\n * indicates that authorization has been refused for those credentials. The\n * user agent MAY repeat the request with a new or replaced Authorization\n * header field. If the 401 response contains the same challenge as the\n * prior response, and the user agent has already attempted authentication at\n * least once, then the user agent SHOULD present the enclosed representation\n * to the user, since it usually contains relevant diagnostic information.\n */\n 401: 'Unauthorized',\n\n /**\n * The 402 (Payment Required) status code is reserved for future use.\n */\n 402: 'Payment Required',\n\n /**\n * The 403 (Forbidden) status code indicates that the server understood\n * the request but refuses to authorize it. A server that wishes to\n * make public why the request has been forbidden can describe that\n * reason in the response payload (if any).\n *\n * If authentication credentials were provided in the request, the\n * server considers them insufficient to grant access. The client\n * SHOULD NOT automatically repeat the request with the same\n * credentials. The client MAY repeat the request with new or different\n * credentials. However, a request might be forbidden for reasons\n * unrelated to the credentials.\n *\n * An origin server that wishes to \"hide\" the current existence of a\n * forbidden target resource MAY instead respond with a status code of\n * 404 (Not Found).\n */\n 403: 'Forbidden',\n\n /**\n * The 404 (Not Found) status code indicates that the origin server did\n * not find a current representation for the target resource or is not\n * willing to disclose that one exists. A 404 status code does not\n * indicate whether this lack of representation is temporary or\n * permanent; the 410 (Gone) status code is preferred over 404 if the\n * origin server knows, presumably through some configurable means, that\n * the condition is likely to be permanent.\n *\n * A 404 response is cacheable by default; i.e., unless otherwise\n * indicated by the method definition or explicit cache controls (see\n * Section 4.2.2 of [RFC7234]).\n */\n 404: 'Not Found',\n\n /**\n * The 405 (Method Not Allowed) status code indicates that the method\n * received in the request-line is known by the origin server but not\n * supported by the target resource. The origin server MUST generate an\n * Allow header field in a 405 response containing a list of the target\n * resource's currently supported methods.\n *\n * A 405 response is cacheable by default; i.e., unless otherwise\n * indicated by the method definition or explicit cache controls (see\n * Section 4.2.2 of [RFC7234]).\n */\n 405: 'Method Not Allowed',\n\n /**\n * The 406 (Not Acceptable) status code indicates that the target\n * resource does not have a current representation that would be\n * acceptable to the user agent, according to the proactive negotiation\n * header fields received in the request (Section 5.3), and the server\n * is unwilling to supply a default representation.\n *\n * The server SHOULD generate a payload containing a list of available\n * representation characteristics and corresponding resource identifiers\n * from which the user or user agent can choose the one most\n * appropriate. A user agent MAY automatically select the most\n * appropriate choice from that list. However, this specification does\n * not define any standard for such automatic selection, as described in\n * Section 6.4.1 of [RFC7231]\n */\n 406: 'Not Acceptable',\n\n /**\n * Similar to 401 Unauthorized, but it indicates that the client needs to\n * authenticate itself in order to use a proxy.\n *\n * The proxy MUST send a Proxy-Authenticate header field containing a\n * challenge applicable to that proxy for the target resource. The client MAY\n * repeat the request with a new or replaced Proxy-Authorization header field.\n */\n 407: 'Proxy Authentication Required',\n\n /**\n * The 408 (Request Timeout) status code indicates that the server did\n * not receive a complete request message within the time that it was\n * prepared to wait. A server SHOULD send the \"close\" connection option\n * (Section 6.1 of [RFC7230]) in the response, since 408 implies that\n * the server has decided to close the connection rather than continue\n * waiting. If the client has an outstanding request in transit, the\n * client MAY repeat that request on a new connection.\n */\n 408: 'Request Timeout',\n\n /**\n * The 409 (Conflict) status code indicates that the request could not\n * be completed due to a conflict with the current state of the target\n * resource. This code is used in situations where the user might be\n * able to resolve the conflict and resubmit the request. The server\n * SHOULD generate a payload that includes enough information for a user\n * to recognize the source of the conflict.\n *\n * Conflicts are most likely to occur in response to a PUT request. For\n * example, if versioning were being used and the representation being\n * PUT included changes to a resource that conflict with those made by\n * an earlier (third-party) request, the origin server might use a 409\n * response to indicate that it can't complete the request. In this\n * case, the response representation would likely contain information\n * useful for merging the differences based on the revision history.\n */\n 409: 'Conflict',\n\n /**\n * The 410 (Gone) status code indicates that access to the target\n * resource is no longer available at the origin server and that this\n * condition is likely to be permanent. If the origin server does not\n * know, or has no facility to determine, whether or not the condition\n * is permanent, the status code 404 (Not Found) ought to be used\n * instead.\n *\n * The 410 response is primarily intended to assist the task of web\n * maintenance by notifying the recipient that the resource is\n * intentionally unavailable and that the server owners desire that\n * remote links to that resource be removed. Such an event is common\n * for limited-time, promotional services and for resources belonging to\n * individuals no longer associated with the origin server's site. It\n * is not necessary to mark all permanently unavailable resources as\n * \"gone\" or to keep the mark for any length of time -- that is left to\n * the discretion of the server owner.\n *\n * A 410 response is cacheable by default; i.e., unless otherwise\n * indicated by the method definition or explicit cache controls (see\n * Section 4.2.2 of [RFC7234]).\n */\n 410: 'Gone',\n\n /**\n * The 411 (Length Required) status code indicates that the server\n * refuses to accept the request without a defined Content-Length\n * (Section 3.3.2 of [RFC7230]). The client MAY repeat the request if\n * it adds a valid Content-Length header field containing the length of\n * the message body in the request message.\n */\n 411: 'Length Required',\n\n /**\n * One or more conditions given in the request header fields evaluated to\n * false when tested on the server.\n *\n * This response code allows the client to place preconditions on the current\n * resource state (its current representations and metadata) and, thus,\n * prevent the request method from being applied if the target resource is in\n * an unexpected state.\n */\n 412: 'Precondition Failed',\n\n /**\n * The 413 (Payload Too Large) status code indicates that the server is\n * refusing to process a request because the request payload is larger\n * than the server is willing or able to process. The server MAY close\n * the connection to prevent the client from continuing the request.\n *\n * If the condition is temporary, the server SHOULD generate a\n * Retry-After header field to indicate that it is temporary and after\n * what time the client MAY try again.\n */\n 413: 'Payload Too Large',\n\n /**\n * The 414 (URI Too Long) status code indicates that the server is\n * refusing to service the request because the request-target (Section\n * 5.3 of [RFC7230]) is longer than the server is willing to interpret.\n * This rare condition is only likely to occur when a client has\n * improperly converted a POST request to a GET request with long query\n * information, when the client has descended into a \"black hole\" of\n * redirection (e.g., a redirected URI prefix that points to a suffix of\n * itself) or when the server is under attack by a client attempting to\n * exploit potential security holes.\n *\n * A 414 response is cacheable by default; i.e., unless otherwise\n * indicated by the method definition or explicit cache controls (see\n * Section 4.2.2 of [RFC7234]).\n */\n 414: 'Request-URI Too Long',\n\n /**\n * The 415 (Unsupported Media Type) status code indicates that the\n * origin server is refusing to service the request because the payload\n * is in a format not supported by this method on the target resource.\n * The format problem might be due to the request's indicated\n * Content-Type or Content-Encoding, or as a result of inspecting the\n * data directly.\n */\n 415: 'Unsupported Media Type',\n\n /**\n * None of the ranges in the request's Range header field overlap the\n * current extent of the selected resource or that the set of ranges\n * requested has been rejected due to invalid ranges or an excessive request\n * of small or overlapping ranges.\n *\n * For byte ranges, failing to overlap the current extent means that the\n * first-byte-pos of all of the byte-range-spec values were greater than the\n * current length of the selected representation. When this status code is\n * generated in response to a byte-range request, the sender SHOULD generate\n * a Content-Range header field specifying the current length of the selected\n * representation\n */\n 416: 'Requested Range Not Satisfiable',\n\n /**\n * The 417 (Expectation Failed) status code indicates that the\n * expectation given in the request's Expect header field\n * (Section 5.1.1 of [RFC7231]) could not be met by at least one of the\n * inbound servers.\n */\n 417: 'Expectation Failed',\n\n /**\n * Any attempt to brew coffee with a teapot should result in the error code\n * \"418 I'm a teapot\". The resulting entity body MAY be short and stout.\n */\n 418: \"I'm a Teapot\",\n\n /**\n * The request was directed at a server that is not able to produce a\n * response. This can be sent by a server that is not configured to produce\n * responses for the combination of scheme and authority that are included\n * in the request URI.\n *\n * Clients receiving a 421 Misdirected Request response from a server MAY\n * retry the request -- whether the request method is idempotent or\n * not -- over a different connection. This is possible if a connection is\n * reused or if an alternative service is selected ALT-SVC.\n *\n * This status code MUST NOT be generated by proxies.\n *\n * A 421 response is cacheable by default, i.e., unless otherwise indicated by\n * the method definition or explicit cache controls\n */\n 421: 'Misdirected Request',\n\n /**\n * The server understands the content type of the request entity (hence a\n * 415 Unsupported Media Type status code is inappropriate), and the syntax\n * of the request entity is correct (thus a 400 Bad Request status code is\n * inappropriate) but was unable to process the contained instructions.\n *\n * For example, this error condition may occur if an XML request body contains\n * well-formed (i.e., syntactically correct), but semantically erroneous, XML\n * instructions.\n */\n 422: 'Unprocessable Entity',\n\n /**\n * The source or destination resource of a method is locked.\n *\n * This response SHOULD contain an appropriate precondition or postcondition\n * code, such as 'lock-token-submitted' or 'no-conflicting-lock'.\n */\n 423: 'Locked',\n\n /**\n * The method could not be performed on the resource because the requested\n * action depended on another action and that action failed.\n *\n * For example, if a command in a PROPPATCH method fails, then, at minimum,\n * the rest of the commands will also fail with 424 Failed Dependency.\n */\n 424: 'Failed Dependency',\n\n /**\n * The 426 (Upgrade Required) status code indicates that the server\n * refuses to perform the request using the current protocol but might\n * be willing to do so after the client upgrades to a different\n * protocol. The server MUST send an Upgrade header field in a 426\n * response to indicate the required protocol(s) (Section 6.7 of\n * [RFC7230]).\n */\n 426: 'Upgrade Required',\n\n /**\n * The origin server requires the request to be conditional.\n *\n * Its typical use is to avoid the \"lost update\" problem, where a client GETs\n * a resource's state, modifies it, and PUTs it back to the server, when\n * meanwhile a third party has modified the state on the server, leading\n * to a conflict. By requiring requests to be conditional, the server can\n * assure that clients are working with the correct copies.\n *\n * Responses using this status code SHOULD explain how to resubmit the request\n * successfully.\n *\n * Responses with the 428 status code MUST NOT be stored by a cache.\n */\n 428: 'Precondition Required',\n\n /**\n * The user has sent too many requests in a given amount of time\n * (\"rate limiting\").\n *\n * The response representations SHOULD include details explaining the\n * condition, and MAY include a Retry-After header indicating how long to\n * wait before making a new request.\n *\n * Responses with the 429 status code MUST NOT be stored by a cache.\n */\n 429: 'Too Many Requests',\n\n /**\n * The server is unwilling to process the request because its header fields\n * are too large. The request MAY be resubmitted after reducing the size of\n * the request header fields.\n *\n * It can be used both when the set of request header fields in total is too\n * large, and when a single header field is at fault. In the latter case, the\n * response representation SHOULD specify which header field was too large.\n */\n 431: 'Request Header Fields Too Large',\n\n /**\n * A non-standard status code used to instruct nginx to close the connection\n * without sending a response to the client, most commonly used to deny\n * malicious or malformed requests.\n *\n * This status code is not seen by the client, it only appears in nginx log\n * files.\n */\n 444: 'Connection Closed Without Response',\n\n /**\n * The server is denying access to the resource as a consequence of a legal\n * demand.\n *\n * The server in question might not be an origin server. This type of legal\n * demand typically most directly affects the operations of ISPs and search\n * engines.\n *\n * Responses using this status code SHOULD include an explanation, in the\n * response body, of the details of the legal demand: the party making it,\n * the applicable legislation or regulation, and what classes of person and\n * resource it applies to.\n *\n * The use of the 451 status code implies neither the existence nor\n * non-existence of the resource named in the request. That is to say, it is\n * possible that if the legal demands were removed, a request for the\n * resource still might not succeed.\n *\n * Note that in many cases clients can still access the denied resource by\n * using technical countermeasures such as a VPN or the Tor network.\n *\n * A 451 response is cacheable by default; i.e., unless otherwise indicated\n * by the method definition or explicit cache controls; see RFC7234.\n */\n 451: 'Unavailable For Legal Reasons',\n\n /**\n * A non-standard status code introduced by nginx for the case when a client\n * closes the connection while nginx is processing the request.\n */\n 499: 'Client Closed Request',\n\n /**\n * The 500 (Internal Server Error) status code indicates that the server\n * encountered an unexpected condition that prevented it from fulfilling\n * the request.\n */\n 500: 'Internal Server Error',\n\n /**\n * The 501 (Not Implemented) status code indicates that the server does\n * not support the functionality required to fulfill the request. This\n * is the appropriate response when the server does not recognize the\n * request method and is not capable of supporting it for any resource.\n *\n * A 501 response is cacheable by default; i.e., unless otherwise\n * indicated by the method definition or explicit cache controls (see\n * Section 4.2.2 of [RFC7234]).\n */\n 501: 'Not Implemented',\n\n /**\n * The 502 (Bad Gateway) status code indicates that the server, while\n * acting as a gateway or proxy, received an invalid response from an\n * inbound server it accessed while attempting to fulfill the request.\n */\n 502: 'Bad Gateway',\n\n /**\n * The 503 (Service Unavailable) status code indicates that the server\n * is currently unable to handle the request due to a temporary overload\n * or scheduled maintenance, which will likely be alleviated after some\n * delay. The server MAY send a Retry-After header field\n * (Section 7.1.3 of [RFC7231]) to suggest an appropriate amount of time for\n * the client to wait before retrying the request.\n */\n 503: 'Service Unavailable',\n\n /**\n * The 504 (Gateway Timeout) status code indicates that the server,\n *while acting as a gateway or proxy, did not receive a timely response\n *from an upstream server it needed to access in order to complete the\n *request.\n */\n 504: 'Gateway Timeout',\n\n /**\n * The 505 (HTTP Version Not Supported) status code indicates that the\n *server does not support, or refuses to support, the major version of\n *HTTP that was used in the request message. The server is indicating\n *that it is unable or unwilling to complete the request using the same\n *major version as the client, as described in Section 2.6 of\n *[RFC7230], other than with this error message. The server SHOULD\n *generate a representation for the 505 response that describes why\n *that version is not supported and what other protocols are supported\n *by that server.\n */\n 505: 'HTTP Version Not Supported',\n\n /**\n * The server has an internal configuration error: the chosen variant\n * resource is configured to engage in transparent content negotiation\n * itself, and is therefore not a proper end point in the negotiation\n * process.\n */\n 506: 'Variant Also Negotiates',\n\n /**\n * The method could not be performed on the resource because the server is\n * unable to store the representation needed to successfully complete the\n * request.\n *\n * This condition is considered to be temporary. If the request that received\n * this status code was the result of a user action, the request MUST NOT be\n * repeated until it is requested by a separate user action.\n */\n 507: 'Insufficient Storage',\n\n /**\n * The server terminated an operation because it encountered an infinite loop\n * while processing a request with \"Depth: infinity\". This status indicates\n * that the entire operation failed.\n */\n 508: 'Loop Detected',\n\n /**\n * The policy for accessing the resource has not been met in the request. The\n * server should send back all the information necessary for the client to\n * issue an extended request.\n *\n * It is outside the scope of this specification to specify how the\n * extensions inform the client.\n *\n * If the 510 response contains information about extensions that were not\n * present in the initial request then the client MAY repeat the request if\n * it has reason to believe it can fulfill the extension policy by modifying\n * the request according to the information provided in the 510 response.\n * Otherwise the client MAY present any entity included in the 510 response\n * to the user, since that entity may include relevant diagnostic information.\n */\n 510: 'Not Extended',\n\n /**\n * The client needs to authenticate to gain network access.\n *\n * The response representation SHOULD contain a link to a resource that\n * allows the user to submit credentials (e.g., with an HTML form).\n *\n * Note that the 511 response SHOULD NOT contain a challenge or the login\n * interface itself, because browsers would show the login interface as being\n * associated with the originally requested URL, which may cause confusion.\n *\n * The 511 status SHOULD NOT be generated by origin servers; it is intended\n * for use by intercepting proxies that are interposed as a means of\n * controlling access to the network.\n *\n * Responses with the 511 status code MUST NOT be stored by a cache.\n */\n 511: 'Network Authentication Required',\n\n /**\n * This status code is not specified in any RFCs, but is used by some HTTP\n * proxies to signal a network connect timeout behind the proxy to a client\n * in front of the proxy.\n */\n 599: 'Network Connect Timeout Error'\n} as const;\n\n/**\n * Numerical HTTP status code.\n */\nexport type StatusCode = keyof typeof HTTPStatuses;\n\n/**\n * Checks if the given numerical status code is in the known HTTP status codes\n * list.\n *\n * @param code HTTP Status code\n * @returns True if the code is a valid HTTP status code\n */\nexport const isValidStatusCode = (code: number): boolean =>\n !!HTTPStatuses[code];\n\n/**\n * Checks if the given status code is in the informational range (1XX).\n *\n * @param code HTTP Status code\n * @returns True if the code is in the \"informational\" range.\n */\nexport const isInformational = (code: StatusCode): boolean =>\n code >= 100 && code < 200;\n\n/**\n * Checks if the given status code is in the successful range (2XX).\n *\n * @param code HTTP Status code\n * @returns True if the code is in the \"success\" range.\n */\nexport const isSuccessful = (code: StatusCode): boolean =>\n code >= 200 && code < 300;\n\n/**\n * Checks if the given status code is in the redirection range (3XX).\n *\n * @param code HTTP Status code\n * @returns True if the code is in the \"redirection\" range.\n */\nexport const isRedirection = (code: StatusCode): boolean =>\n code >= 300 && code < 400;\n\n/**\n * Checks if the given status code is in the client error range (4XX).\n *\n * @param code HTTP Status code\n * @returns True if the code is in the \"client error\" range.\n */\nexport const isClientError = (code: StatusCode): boolean =>\n code >= 400 && code < 500;\n\n/**\n * Checks if the given status code is in the server error range (5XX).\n *\n * @param code HTTP Status code\n * @returns True if the code is in the \"server error\" range.\n */\nexport const isServerError = (code: StatusCode): boolean => code >= 500;\n\n/**\n * Searches the list of HTTP statuses for a matching textual name to the one\n * provided. If a match is found, then the numerical status code is returned,\n * otherwise `null`.\n *\n * Internally, the parameter and the status names are normalized by lower-casing\n * the strings and trimming space.\n *\n * @param status HTTP Status textual name\n * @returns The numerical status code, or null if not found\n */\nexport const getCodeForStatus = (status: string): null | StatusCode => {\n const clnStr = status.toLocaleLowerCase().trim();\n const entry = Object.entries(HTTPStatuses).find(\n (ent) => ent[1].toLowerCase() === clnStr\n );\n if (entry) return parseInt(entry[0]) as StatusCode;\n return null;\n};\n\nexport default HTTPStatuses;\n","import { isNever, isRecord, safeStringify } from '@forklaunch/common';\nimport { string, ZodSchemaValidator, ZodType } from '@forklaunch/validator/zod';\nimport { FastMCP } from 'fastmcp';\nimport http from 'http';\nimport {\n discriminateBody,\n discriminateResponseBodies\n} from '../router/discriminateBody';\nimport { unpackRouters } from '../router/unpackRouters';\nimport {\n Body,\n HeadersObject,\n Method,\n ParamsObject,\n QueryObject,\n SchemaAuthMethods,\n SessionObject,\n VersionSchema\n} from '../types/contractDetails.types';\nimport { ExpressLikeApplicationOptions } from '../types/expressLikeOptions';\nimport { ForklaunchRouter } from '../types/router.types';\n\nfunction generateInputSchema(\n schemaValidator: ZodSchemaValidator,\n body?: Body<ZodSchemaValidator>,\n params?: ParamsObject<ZodSchemaValidator>,\n query?: QueryObject<ZodSchemaValidator>,\n requestHeaders?: HeadersObject<ZodSchemaValidator>,\n auth?: SchemaAuthMethods<\n ZodSchemaValidator,\n ParamsObject<ZodSchemaValidator>,\n Body<ZodSchemaValidator>,\n QueryObject<ZodSchemaValidator>,\n HeadersObject<ZodSchemaValidator>,\n VersionSchema<ZodSchemaValidator, Method>,\n unknown\n >\n) {\n let discriminatedBody:\n ReturnType<typeof discriminateBody<ZodSchemaValidator>> | undefined;\n\n if (body) {\n discriminatedBody = discriminateBody(schemaValidator, body);\n }\n return schemaValidator.schemify({\n ...(discriminatedBody && body\n ? {\n ...('contentType' in body ? { contentType: body.contentType } : {}),\n body: schemaValidator.schemify(discriminatedBody.schema)\n }\n : {}),\n ...(params\n ? {\n params: schemaValidator.schemify(params)\n }\n : {}),\n ...(query\n ? {\n query: schemaValidator.schemify(query)\n }\n : {}),\n ...(requestHeaders\n ? {\n headers: schemaValidator.schemify({\n ...requestHeaders,\n ...(auth\n ? {\n [auth.headerName ?? 'authorization']: string.startsWith(\n auth.tokenPrefix ?? ('basic' in auth ? 'Basic ' : 'Bearer ')\n )\n }\n : {})\n })\n }\n : {})\n });\n}\n/**\n * Generates a ModelContextProtocol server from given routers.\n *\n * @template SV - A type that extends AnySchemaValidator.\n * @param {SV} schemaValidator - The schema validator.\n * @param {string | number} port - The port on which the server is running.\n * @param {ForklaunchRouter<SV>[]} routers - The routers to include in the server.\n * @returns {McpServer} - The generated ModelContextProtocol server.\n */\nexport function generateMcpServer<\n T extends Record<string, unknown> | undefined =\n Record<string, unknown> | undefined\n>(\n schemaValidator: ZodSchemaValidator,\n protocol: 'http' | 'https',\n host: string,\n port: number,\n version: `${number}.${number}.${number}`,\n application: ForklaunchRouter<ZodSchemaValidator>,\n appOptions?: ExpressLikeApplicationOptions<\n ZodSchemaValidator,\n SessionObject<ZodSchemaValidator>\n >['mcp'],\n options?: ConstructorParameters<typeof FastMCP<T>>[0],\n contentTypeMap?: Record<string, string>,\n authenticate?: (\n request: http.IncomingMessage\n ) => Promise<Record<string, unknown> | undefined>\n) {\n if (!(schemaValidator instanceof ZodSchemaValidator)) {\n throw new Error(\n 'Schema validator must be an instance of ZodSchemaValidator'\n );\n }\n\n const mcpServer = new FastMCP({\n ...options,\n name: options?.name ?? 'mcp-server',\n version,\n authenticate\n });\n\n [\n {\n fullPath: application.basePath === '/' ? '' : application.basePath,\n router: application\n },\n ...unpackRouters<ZodSchemaValidator>(application.routers, [\n application.basePath === '/' ? '' : application.basePath\n ])\n ].forEach(({ fullPath, router }) => {\n router.routes.forEach((route) => {\n if (!(\n route.contractDetails.options?.mcp ??\n router.routerOptions?.mcp ??\n appOptions !== false\n )) {\n return;\n }\n\n const inputSchemas: ZodType[] = [];\n\n if (route.contractDetails.versions) {\n Object.values(route.contractDetails.versions).forEach((version) => {\n inputSchemas.push(\n generateInputSchema(\n schemaValidator,\n version.body,\n route.contractDetails.params,\n version.query,\n version.requestHeaders,\n route.contractDetails.auth\n )\n );\n });\n } else {\n inputSchemas.push(\n generateInputSchema(\n schemaValidator,\n route.contractDetails.body,\n route.contractDetails.params,\n route.contractDetails.query,\n route.contractDetails.requestHeaders,\n route.contractDetails.auth\n )\n );\n }\n\n inputSchemas.forEach((inputSchema, index) => {\n mcpServer.addTool({\n name:\n route.contractDetails.name +\n (Object.keys(route.contractDetails.versions ?? {}).length > 1\n ? ` [v${Object.keys(route.contractDetails.versions ?? {})[index]}]`\n : ''),\n description: route.contractDetails.summary,\n parameters: inputSchema,\n execute: async (args) => {\n const { contentType, body, params, query, headers } = args as {\n contentType?: string;\n params?: Record<string, string | number | boolean>;\n body?: Record<string, unknown> | string;\n query?: Record<string, string | number | boolean>;\n headers?: Record<string, unknown>;\n };\n\n let url = `${protocol}://${host}:${port}${fullPath}${route.path}`;\n\n if (params) {\n for (const key in params) {\n url = url.replace(\n `:${key}`,\n encodeURIComponent(params[key] as string)\n );\n }\n }\n\n let bodySchema;\n let responsesSchemas;\n if (route.contractDetails.versions) {\n const version = route.contractDetails.versions[index];\n if (version.body && schemaValidator.parse(inputSchema, args).ok) {\n bodySchema = version.body;\n responsesSchemas = version.responses;\n }\n } else {\n bodySchema = route.contractDetails.body;\n responsesSchemas = route.contractDetails.responses;\n }\n\n const discriminatedBody = bodySchema\n ? discriminateBody(schemaValidator, bodySchema)\n : undefined;\n\n let parsedBody;\n if (discriminatedBody) {\n switch (discriminatedBody.parserType) {\n case 'json': {\n parsedBody = safeStringify(body);\n break;\n }\n case 'text': {\n parsedBody = body;\n break;\n }\n case 'file': {\n parsedBody = Buffer.from(safeStringify(body));\n break;\n }\n case 'multipart': {\n const formData = new FormData();\n if (isRecord(body)) {\n for (const key in body) {\n if (typeof body[key] === 'string') {\n if (\n schemaValidator.isInstanceOf(\n body[key],\n schemaValidator.file\n )\n ) {\n formData.append(\n key,\n new Blob([new Uint8Array(Buffer.from(body[key]))])\n );\n } else {\n formData.append(key, body[key]);\n }\n } else {\n throw new Error('Body is not a valid multipart object');\n }\n }\n } else {\n throw new Error('Body is not a valid multipart object');\n }\n parsedBody = formData;\n break;\n }\n case 'urlEncoded': {\n if (isRecord(body)) {\n parsedBody = new URLSearchParams(\n Object.entries(body).map(([key, value]) => [\n key,\n safeStringify(value)\n ])\n );\n } else {\n throw new Error('Body is not a valid url encoded object');\n }\n break;\n }\n default: {\n isNever(discriminatedBody.parserType);\n parsedBody = safeStringify(body);\n break;\n }\n }\n }\n\n if (query) {\n const queryString = new URLSearchParams(\n Object.entries(query).map(([key, value]) => [\n key,\n safeStringify(value)\n ])\n ).toString();\n url += queryString ? `?${queryString}` : '';\n }\n\n const response = await fetch(encodeURI(url), {\n method: route.method.toUpperCase(),\n headers: {\n ...headers,\n ...(discriminatedBody?.contentType != 'multipart/form-data'\n ? {\n 'Content-Type':\n contentType ?? discriminatedBody?.contentType\n }\n : {})\n },\n body: parsedBody as BodyInit | null | undefined\n });\n\n if (response.status >= 300) {\n throw new Error(\n `Error received while proxying request to ${url}: ${await response.text()}`\n );\n }\n\n if (!responsesSchemas) {\n throw new Error('No responses schemas found');\n }\n\n const contractContentType = discriminateResponseBodies(\n schemaValidator,\n responsesSchemas\n )[response.status].contentType;\n switch (\n contentTypeMap && contentTypeMap[contractContentType]\n ? contentTypeMap[contractContentType]\n : contractContentType\n ) {\n case 'application/json':\n return {\n content: [\n {\n type: 'text' as const,\n text: safeStringify(await response.json())\n }\n ]\n };\n case 'text/plain':\n return {\n content: [\n { type: 'text' as const, text: await response.text() }\n ]\n };\n case 'application/octet-stream':\n return {\n content: [\n {\n type: 'resource' as const,\n resource: {\n uri: response.url,\n blob: Buffer.from(\n await (await response.blob()).arrayBuffer()\n ).toString('base64')\n }\n }\n ]\n };\n case 'text/event-stream':\n return {\n content: [\n { type: 'text' as const, text: await response.text() }\n ]\n };\n default:\n return {\n content: [\n { type: 'text' as const, text: await response.text() }\n ]\n };\n }\n }\n });\n });\n });\n });\n\n return mcpServer;\n}\n","import { AnySchemaValidator } from '@forklaunch/validator';\nimport { ForklaunchRouter } from '../types/router.types';\n\nexport function unpackRouters<SV extends AnySchemaValidator>(\n routers: ForklaunchRouter<SV>[],\n recursiveBasePath: string[] = []\n): {\n fullPath: string;\n router: ForklaunchRouter<SV>;\n}[] {\n return routers.reduce<\n {\n fullPath: string;\n router: ForklaunchRouter<SV>;\n }[]\n >((acc, router) => {\n const fullPath = [...recursiveBasePath, router.basePath].join('');\n acc.push({\n fullPath,\n router\n });\n acc.push(\n ...unpackRouters<SV>(router.routers, [\n ...recursiveBasePath,\n router.basePath\n ])\n );\n return acc;\n }, []);\n}\n","import {\n AnySchemaValidator,\n prettyPrintParseErrors,\n SchemaValidator\n} from '@forklaunch/validator';\nimport { ParsedQs } from 'qs';\nimport { hasSend } from '../../guards/hasSend';\nimport { isResponseCompiledSchema } from '../../guards/isResponseCompiledSchema';\nimport {\n ForklaunchNextFunction,\n ForklaunchRequest,\n ForklaunchResHeaders,\n ForklaunchResponse,\n VersionedRequests\n} from '../../types/apiDefinition.types';\nimport { ParamsDictionary } from '../../types/contractDetails.types';\n\n/**\n * Middleware to parse and validate the response according to the provided schema.\n *\n * This function validates the response against a schema provided by the request's schema validator.\n * If the response does not conform to the schema, the behavior is determined by the `responseValidation`\n * option in `req.contractDetails.options`:\n * - `'error'` (default): Calls `next` with an error.\n * - `'warning'`: Logs a warning to the console.\n * - `'none'`: Silently continues without action.\n *\n * @template SV - The type of the schema validator used in the request.\n * @template P - The type of the parameters dictionary used in the request.\n * @template ResBodyMap - A record type mapping status codes to response body types.\n * @template ReqBody - The type of the request body.\n * @template ReqQuery - The type of the parsed query string.\n * @template ReqHeaders - The type of the request headers.\n * @template ResHeaders - The type of the response headers, extended from `ForklaunchResHeaders`.\n * @template LocalsObj - The type of the locals object in the response.\n *\n * @param {ForklaunchRequest<SV, P, ReqBody, ReqQuery, ReqHeaders>} req - The request object, containing the schema validator and other request data.\n * @param {ForklaunchResponse<ResBodyMap, ForklaunchResHeaders & ResHeaders, LocalsObj>} res - The response object, including headers and body data.\n * @param {ForklaunchNextFunction} [next] - The next middleware function to be called. If not provided, the function will return after processing.\n *\n * @returns {void} This function does not return a value.\n */\nexport function parse<\n SV extends AnySchemaValidator,\n P extends ParamsDictionary,\n ResBodyMap extends Record<number, unknown>,\n ReqBody extends Record<string, unknown>,\n ReqQuery extends ParsedQs,\n ReqHeaders extends Record<string, string>,\n ResHeaders extends Record<string, unknown>,\n LocalsObj extends Record<string, unknown>,\n VersionedReqs extends VersionedRequests,\n SessionSchema extends Record<string, unknown>\n>(\n req: ForklaunchRequest<\n SV,\n P,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n Extract<keyof VersionedReqs, string>,\n SessionSchema\n >,\n res: ForklaunchResponse<\n unknown,\n ResBodyMap,\n ForklaunchResHeaders & ResHeaders,\n LocalsObj,\n Extract<keyof VersionedReqs, string>\n >,\n next?: ForklaunchNextFunction\n) {\n let headers;\n let responses;\n\n const globalOptions = req._globalOptions?.();\n const collapsedOptions =\n req.contractDetails.options?.responseValidation ??\n (globalOptions?.validation === false\n ? 'none'\n : globalOptions?.validation?.response);\n\n if (collapsedOptions === 'none') {\n next?.();\n return;\n }\n\n const responseSchemas = res.responseSchemas;\n const schemaValidator = req.schemaValidator as SchemaValidator;\n\n if (!isResponseCompiledSchema(responseSchemas)) {\n const parsedVersions = req._parsedVersions;\n if (typeof parsedVersions === 'number') {\n throw new Error('Request failed to parse given version map');\n }\n const mappedHeaderSchemas = parsedVersions.map(\n (version) => responseSchemas[version].headers\n );\n const mappedResponseSchemas = parsedVersions.map(\n (version) => responseSchemas[version].responses\n );\n\n const collapsedResponseSchemas = mappedResponseSchemas.reduce<\n Record<number, unknown[]>\n >((acc, responseSchema) => {\n Object.entries(responseSchema).forEach(([status, schema]) => {\n if (!acc[Number(status)]) {\n acc[Number(status)] = [];\n }\n acc[Number(status)].push(schema);\n });\n return acc;\n }, {});\n\n headers = schemaValidator.union(mappedHeaderSchemas);\n responses = Object.fromEntries(\n Object.entries(collapsedResponseSchemas).map(([status, schemas]) => [\n status,\n schemaValidator.union(schemas)\n ])\n );\n } else {\n headers = responseSchemas.headers;\n responses = responseSchemas.responses;\n }\n\n const statusCode = Number(res.statusCode);\n\n const parsedResponse = schemaValidator.parse(\n [400, 401, 404, 403, 500].includes(statusCode)\n ? schemaValidator.union([schemaValidator.string, responses?.[statusCode]])\n : responses?.[statusCode],\n res.bodyData\n );\n\n const parsedHeaders = schemaValidator.parse(\n headers ?? schemaValidator.unknown,\n res.getHeaders()\n );\n const parseErrors: string[] = [];\n if (!parsedHeaders.ok) {\n const headerErrors = prettyPrintParseErrors(parsedHeaders.errors, 'Header');\n if (headerErrors) {\n parseErrors.push(headerErrors);\n }\n }\n\n if (!parsedResponse.ok) {\n const responseErrors = prettyPrintParseErrors(\n parsedResponse.errors,\n 'Response'\n );\n if (responseErrors) {\n parseErrors.push(responseErrors);\n }\n }\n\n if (parseErrors.length > 0) {\n switch (req.contractDetails.options?.responseValidation) {\n default:\n case undefined:\n case 'error':\n res.type('text/plain');\n res.status(500);\n if (hasSend(res)) {\n res.send(\n `Invalid response:\\n${parseErrors.join(\n '\\n\\n'\n )}\\n\\nCorrelation id: ${\n req.context.correlationId ?? 'No correlation ID'\n }`\n );\n } else {\n next?.(new Error('Response is not sendable.'));\n }\n return;\n case 'warning':\n req.openTelemetryCollector?.warn(\n `Invalid response:\\n${parseErrors.join('\\n\\n')}`\n );\n break;\n case 'none':\n break;\n }\n }\n next?.();\n}\n","import { ResponseCompiledSchema } from '../types/contractDetails.types';\n\nexport function isResponseCompiledSchema(\n schema: unknown\n): schema is ResponseCompiledSchema {\n return typeof schema === 'object' && schema !== null && 'responses' in schema;\n}\n","import { AnySchemaValidator } from '@forklaunch/validator';\nimport { ParsedQs } from 'qs';\nimport { parse } from './parse.middleware';\n\nimport {\n isAsyncGenerator,\n isNever,\n isNodeJsWriteableStream,\n isRecord,\n readableStreamToAsyncIterable,\n safeStringify\n} from '@forklaunch/common';\nimport { Readable, Transform } from 'stream';\nimport { discriminateResponseBodies } from '../../router/discriminateBody';\nimport { recordMetric } from '../../telemetry/recordMetric';\nimport {\n ForklaunchRequest,\n ForklaunchResHeaders,\n ForklaunchResponse,\n ForklaunchSendableData,\n ForklaunchStatusResponse,\n VersionedRequests\n} from '../../types/apiDefinition.types';\nimport { ParamsDictionary } from '../../types/contractDetails.types';\n\n/**\n * Enhances the Express-like `send` method with additional logic for response handling and validation.\n *\n * This function intercepts the `send` method to provide custom behavior, including response validation\n * through the `parseResponse` middleware. If the response status is 404, it sends a \"Not Found\" message.\n * If the response validation fails, it sends a parsing error message. Otherwise, it calls the original `send`\n * method with the provided data.\n *\n * @template SV - The type of the schema validator used in the request.\n * @template P - The type of the parameters dictionary used in the request.\n * @template ResBodyMap - A record type mapping status codes to response body types.\n * @template ReqBody - The type of the request body.\n * @template ReqQuery - The type of the parsed query string.\n * @template ReqHeaders - The type of the request headers.\n * @template ResHeaders - The type of the response headers, extended from `ForklaunchResHeaders`.\n * @template LocalsObj - The type of the locals object in the response.\n *\n * @param {unknown} instance - The context (typically `this`) in which the original `send` method is called.\n * @param {ForklaunchRequest<SV, P, ReqBody, ReqQuery, ReqHeaders>} req - The request object, containing the schema validator and other request data.\n * @param {ForklaunchResponse<ResBodyMap, ForklaunchResHeaders & ResHeaders, LocalsObj>} res - The response object, including headers and body data.\n * @param {Function} originalSend - The original `send` method from the response object, to be called after custom logic.\n * @param {string | ArrayBuffer | ArrayBufferView | NodeJS.ReadableStream | null | undefined} data - The data to be sent as the response body.\n * @param {boolean} shouldEnrich - A flag indicating whether the response should be sent immediately.\n *\n * @returns {unknown} The return value of the original `send` method, typically the response itself.\n */\nexport function enrichExpressLikeSend<\n SV extends AnySchemaValidator,\n P extends ParamsDictionary,\n ResBodyMap extends Record<number, unknown>,\n ReqBody extends Record<string, unknown>,\n ReqQuery extends ParsedQs,\n ReqHeaders extends Record<string, string>,\n ResHeaders extends Record<string, unknown>,\n LocalsObj extends Record<string, unknown>,\n VersionedReqs extends VersionedRequests,\n SessionSchema extends Record<string, unknown>\n>(\n instance: unknown,\n req: ForklaunchRequest<\n SV,\n P,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n Extract<keyof VersionedReqs, string>,\n SessionSchema\n >,\n res: ForklaunchResponse<\n unknown,\n ResBodyMap,\n ForklaunchResHeaders & ResHeaders,\n LocalsObj,\n Extract<keyof VersionedReqs, string>\n >,\n originalOperation:\n | ForklaunchStatusResponse<ForklaunchSendableData>['json']\n | ForklaunchStatusResponse<ForklaunchSendableData>['jsonp'],\n originalSend: ForklaunchStatusResponse<ForklaunchSendableData>['send'],\n data:\n | ForklaunchSendableData\n | File\n | Blob\n | AsyncGenerator<Record<string, unknown>>\n | null\n | undefined,\n shouldEnrich: boolean\n) {\n let errorSent = false;\n\n if (data == null) {\n originalSend.call(instance, data);\n return;\n }\n\n let responses;\n if (\n req.contractDetails.responses == null &&\n (req.contractDetails.versions == null ||\n Object.values(req.contractDetails.versions).some(\n (version) => version?.responses == null\n ))\n ) {\n throw new Error('Responses schema definitions are required');\n } else {\n if (req.contractDetails.responses != null) {\n responses = req.contractDetails.responses;\n } else {\n responses = req.contractDetails.versions[req.version].responses;\n }\n }\n\n const responseBodies = discriminateResponseBodies(\n req.schemaValidator,\n responses\n );\n\n if (\n responseBodies != null &&\n responseBodies[Number(res.statusCode)] != null\n ) {\n res.type(responseBodies[Number(res.statusCode)].contentType);\n }\n\n if (data instanceof File || data instanceof Blob) {\n if (data instanceof File) {\n res.setHeader(\n 'Content-Disposition',\n `attachment; filename=\"${data.name}\"` as ResHeaders['Content-Disposition']\n );\n }\n if (isNodeJsWriteableStream(res)) {\n // No cast: isNodeJsWriteableStream is a type predicate\n // (`value is NodeJS.WritableStream`), so `res` is already narrowed here.\n Readable.from(readableStreamToAsyncIterable(data.stream())).pipe(res);\n } else {\n res.type('text/plain');\n res.status(500);\n originalSend.call(instance, 'Not a NodeJS WritableStream');\n errorSent = true;\n }\n } else if (isAsyncGenerator(data)) {\n let firstPass = true;\n const transformer = new Transform({\n objectMode: true,\n transform(\n chunk: Record<string, unknown>,\n _encoding: unknown,\n callback: (error?: Error | null, data?: unknown) => void\n ) {\n if (firstPass) {\n res.bodyData = chunk;\n parse(req, res, (err?: unknown) => {\n if (err) {\n let errorString = (err as Error).message;\n if (res.locals.errorMessage) {\n errorString += `\\n------------------\\n${res.locals.errorMessage}`;\n }\n req.openTelemetryCollector?.error(errorString);\n res.type('text/plain');\n res.status(500);\n originalSend.call(instance, errorString);\n errorSent = true;\n callback(new Error(errorString));\n } else {\n let data = '';\n for (const [key, value] of Object.entries(chunk)) {\n data += `${key}: ${typeof value === 'string' ? value : safeStringify(value)}\\n`;\n }\n data += '\\n';\n callback(null, data);\n }\n });\n firstPass = false;\n } else if (!errorSent) {\n let data = '';\n for (const [key, value] of Object.entries(chunk)) {\n data += `${key}: ${typeof value === 'string' ? value : safeStringify(value)}\\n`;\n }\n data += '\\n';\n callback(null, data);\n }\n }\n });\n if (isNodeJsWriteableStream(res)) {\n Readable.from(data).pipe(transformer).pipe(res);\n } else {\n res.type('text/plain');\n res.status(500);\n originalSend.call(instance, 'Not a NodeJS WritableStream');\n errorSent = true;\n }\n } else {\n const parserType = responseBodies?.[Number(res.statusCode)]?.parserType;\n\n res.bodyData = data;\n if (isRecord(data)) {\n switch (parserType) {\n case 'json':\n res.bodyData = 'json' in data ? data.json : data;\n break;\n case 'text':\n res.bodyData = 'text' in data ? data.text : data;\n break;\n case 'file':\n res.bodyData = 'file' in data ? data.file : data;\n break;\n case 'serverSentEvent':\n res.bodyData = 'event' in data ? data.event : data;\n break;\n case 'multipart':\n res.bodyData = 'multipart' in data ? data.multipart : data;\n break;\n case undefined:\n res.bodyData = data;\n break;\n default:\n isNever(parserType);\n res.bodyData = data;\n break;\n }\n }\n\n parse(req, res, (err?: unknown) => {\n if (err) {\n let errorString = (err as Error).message;\n if (res.locals.errorMessage) {\n errorString += `\\n------------------\\n${res.locals.errorMessage}`;\n }\n req.openTelemetryCollector?.error(errorString);\n res.type('text/plain');\n res.status(500);\n originalSend.call(instance, errorString);\n errorSent = true;\n } else {\n if (typeof data === 'string') {\n res.type('text/plain');\n originalSend.call(instance, data);\n } else if (!(data instanceof File)) {\n res.sent = true;\n originalOperation.call(instance, data);\n }\n }\n });\n }\n\n if (shouldEnrich) {\n recordMetric<\n SV,\n P,\n ReqBody,\n ReqQuery,\n ResBodyMap,\n ReqHeaders,\n ForklaunchResHeaders & ResHeaders,\n LocalsObj,\n VersionedReqs,\n SessionSchema\n >(req, res);\n }\n}\n","import { getEnvVar } from '@forklaunch/common';\nimport { AnySchemaValidator } from '@forklaunch/validator';\nimport {\n ATTR_HTTP_REQUEST_METHOD,\n ATTR_HTTP_RESPONSE_STATUS_CODE,\n ATTR_HTTP_ROUTE,\n ATTR_SERVICE_NAME\n} from '@opentelemetry/semantic-conventions';\nimport { ParsedQs } from 'qs';\nimport {\n ForklaunchRequest,\n ForklaunchResponse,\n ParamsDictionary,\n VersionedRequests\n} from '..';\nimport { ATTR_API_NAME, ATTR_APPLICATION_ID } from './constants';\nimport {\n httpErrorsTotalCounter,\n httpRequestDurationMsHistogram,\n httpRequestsTotalCounter\n} from './openTelemetryCollector';\n\nexport function recordMetric<\n SV extends AnySchemaValidator,\n P extends ParamsDictionary,\n ReqBody extends Record<string, unknown>,\n ReqQuery extends ParsedQs,\n ResBodyMap extends Record<string, unknown>,\n ReqHeaders extends Record<string, string>,\n ResHeaders extends Record<string, unknown>,\n LocalsObj extends Record<string, unknown>,\n VersionedReqs extends VersionedRequests,\n SessionSchema extends Record<string, unknown>\n>(\n req: ForklaunchRequest<\n SV,\n P,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n Extract<keyof VersionedReqs, string>,\n SessionSchema\n >,\n res: ForklaunchResponse<\n unknown,\n ResBodyMap,\n ResHeaders,\n LocalsObj,\n Extract<keyof VersionedReqs, string>\n >\n) {\n if (res.metricRecorded) {\n return;\n }\n\n const serviceName = getEnvVar('OTEL_SERVICE_NAME') || 'unknown';\n const attrs = {\n [ATTR_SERVICE_NAME]: serviceName,\n [ATTR_APPLICATION_ID]: getEnvVar('OTEL_APPLICATION_ID'),\n [ATTR_API_NAME]: req.contractDetails?.name,\n [ATTR_HTTP_REQUEST_METHOD]: req.method,\n [ATTR_HTTP_ROUTE]: req.originalPath,\n [ATTR_HTTP_RESPONSE_STATUS_CODE]: Number(res.statusCode) || 0\n };\n\n httpRequestsTotalCounter.add(1, attrs);\n\n const durationMs =\n req.context?.requestStartTime != null\n ? Date.now() - req.context.requestStartTime\n : 0;\n httpRequestDurationMsHistogram.record(durationMs, attrs);\n\n if (Number(res.statusCode) >= 400) {\n httpErrorsTotalCounter.add(1, attrs);\n }\n\n res.metricRecorded = true;\n}\n","import { openApiCompliantPath } from '@forklaunch/common';\nimport {\n AnySchemaValidator,\n IdiomaticSchema,\n SchemaValidator\n} from '@forklaunch/validator';\nimport {\n ContentObject,\n OpenAPIObject,\n OperationObject,\n PathObject,\n ResponseObject,\n ResponsesObject,\n SecuritySchemeObject,\n TagObject\n} from 'openapi3-ts/oas31';\nimport HTTPStatuses from '../httpStatusCodes';\nimport {\n discriminateBody,\n discriminateResponseBodies\n} from '../router/discriminateBody';\nimport { unpackRouters } from '../router/unpackRouters';\nimport {\n Body,\n HeadersObject,\n Method,\n ParamsObject,\n QueryObject,\n ResponseBody,\n SchemaAuthMethods,\n SessionObject,\n VersionSchema\n} from '../types/contractDetails.types';\nimport { ExpressLikeApplicationOptions } from '../types/expressLikeOptions';\nimport { ForklaunchRouter } from '../types/router.types';\n\nexport const OPENAPI_DEFAULT_VERSION = Symbol('default');\n\n/**\n * Capitalizes the first letter of a string.\n *\n * @param {string} str - The string to transform.\n * @returns {string} - The transformed string with the first letter capitalized.\n */\nfunction toUpperCase(str: string) {\n return str.charAt(0).toUpperCase() + str.slice(1);\n}\n\n/**\n * Transforms a base path by ensuring it starts with a slash and capitalizing the first letter.\n *\n * @param {string} basePath - The base path to transform.\n * @returns {string} - The transformed base path.\n */\nfunction transformBasePath(basePath: string) {\n if (basePath.startsWith('/')) {\n return basePath.slice(1);\n }\n return `/${basePath}`;\n}\n\n/**\n * Creates a Swagger document.\n *\n * @param {string | number} port - The port on which the server is running.\n * @param {TagObject[]} tags - The tags for the Swagger document.\n * @param {PathObject} paths - The paths for the Swagger document.\n * @returns {OpenAPIObject} - The Swagger document.\n */\nfunction generateOpenApiDocument<SV extends AnySchemaValidator>(\n serverUrls: string[],\n serverDescriptions: string[],\n versionedTags: Record<string | symbol, TagObject[]>,\n versionedPaths: Record<string | symbol, PathObject>,\n versionedSecuritySchemes: Record<\n string | symbol,\n Record<string, SecuritySchemeObject>\n >,\n appOptions?: ExpressLikeApplicationOptions<SV, SessionObject<SV>>['openapi']\n): Record<string | symbol, OpenAPIObject> {\n const { title, description, contact } =\n appOptions !== false ? (appOptions ?? {}) : {};\n return {\n [OPENAPI_DEFAULT_VERSION]: {\n openapi: '3.1.0',\n info: {\n title: title || process.env.API_TITLE || 'API Definition',\n version: 'latest',\n description,\n contact\n },\n components: {\n securitySchemes: versionedSecuritySchemes[OPENAPI_DEFAULT_VERSION]\n },\n tags: versionedTags[OPENAPI_DEFAULT_VERSION],\n servers: [\n ...serverUrls.map((url, index) => ({\n url,\n description: serverDescriptions?.[index]\n }))\n ],\n paths: versionedPaths[OPENAPI_DEFAULT_VERSION]\n },\n ...Object.fromEntries(\n Object.entries(versionedPaths).map(([version, paths]) => [\n version,\n {\n openapi: '3.1.0',\n info: {\n title: title || process.env.API_TITLE || 'API Definition',\n version,\n description,\n contact\n },\n components: {\n securitySchemes: versionedSecuritySchemes[version]\n },\n tags: versionedTags[version],\n servers: [\n ...serverUrls.map((url, index) => ({\n url,\n description: serverDescriptions?.[index]\n }))\n ],\n paths\n }\n ])\n )\n };\n}\n\n/**\n * Resolves the content object for a given schema.\n *\n * @template SV - A type that extends AnySchemaValidator.\n * @param {SV} schemaValidator - The schema validator.\n * @param {IdiomaticSchema<SV>} body - The schema body.\n * @returns {ContentObject} - The resolved content object.\n */\nfunction contentResolver<SV extends AnySchemaValidator>(\n schemaValidator: SV,\n body: IdiomaticSchema<SV>,\n contentType?: string\n): ContentObject {\n const bodySpec = (schemaValidator as SchemaValidator).openapi(body);\n return contentType != null\n ? {\n [contentType]: {\n schema: bodySpec\n }\n }\n : body === schemaValidator.string\n ? {\n 'text/plain': {\n schema: bodySpec\n }\n }\n : {\n 'application/json': {\n schema: bodySpec\n }\n };\n}\n\nfunction generateOperationObject<SV extends AnySchemaValidator>(\n schemaValidator: SV,\n path: string,\n method: Method,\n controllerName: string,\n sdkPaths: Record<string, string>,\n securitySchemes: Record<string, SecuritySchemeObject>,\n name: string,\n summary: string,\n responses: Record<number, ResponseBody<SV>>,\n params?: ParamsObject<SV>,\n responseHeaders?: HeadersObject<SV>,\n requestHeaders?: HeadersObject<SV>,\n query?: QueryObject<SV>,\n body?: Body<SV>,\n auth?: SchemaAuthMethods<\n SV,\n ParamsObject<SV>,\n Body<SV>,\n QueryObject<SV>,\n HeadersObject<SV>,\n VersionSchema<SV, Method>,\n unknown\n >\n) {\n const typedSchemaValidator = schemaValidator as SchemaValidator;\n\n const coercedResponses: ResponsesObject = {};\n\n const discriminatedResponseBodiesResult = discriminateResponseBodies(\n schemaValidator,\n responses\n );\n\n for (const key in discriminatedResponseBodiesResult) {\n coercedResponses[key] = {\n description: HTTPStatuses[key],\n content: contentResolver(\n schemaValidator,\n discriminatedResponseBodiesResult[key].schema,\n discriminatedResponseBodiesResult[key].contentType\n ),\n headers: responseHeaders\n ? Object.fromEntries(\n Object.entries(responseHeaders).map(([key, value]) => [\n key,\n {\n schema: typedSchemaValidator.openapi(value)\n }\n ])\n )\n : undefined\n } satisfies ResponseObject;\n }\n\n const commonErrors = [400, 404, 500];\n for (const error of commonErrors) {\n if (!(error in responses)) {\n coercedResponses[error] = {\n description: HTTPStatuses[error],\n content: contentResolver(schemaValidator, schemaValidator.string)\n };\n }\n }\n\n const operationObject: OperationObject = {\n tags: [controllerName],\n summary: `${name}: ${summary}`,\n parameters: [],\n responses: coercedResponses,\n operationId: sdkPaths[[method, path].join('.')]\n };\n\n if (params) {\n for (const key in params) {\n operationObject.parameters?.push({\n name: key,\n in: 'path',\n schema: typedSchemaValidator.openapi(params[key])\n });\n }\n }\n\n const discriminatedBodyResult = body\n ? discriminateBody(schemaValidator, body)\n : null;\n\n if (discriminatedBodyResult) {\n operationObject.requestBody = {\n required: true,\n content: contentResolver(\n schemaValidator,\n discriminatedBodyResult.schema,\n discriminatedBodyResult.contentType\n )\n };\n }\n\n if (requestHeaders) {\n for (const key in requestHeaders) {\n operationObject.parameters?.push({\n name: key,\n in: 'header',\n schema: typedSchemaValidator.openapi(requestHeaders[key])\n });\n }\n }\n\n if (query) {\n for (const key in query) {\n operationObject.parameters?.push({\n name: key,\n in: 'query',\n schema: typedSchemaValidator.openapi(query[key])\n });\n }\n }\n\n if (auth) {\n coercedResponses[401] = {\n description: HTTPStatuses[401],\n content: contentResolver(schemaValidator, schemaValidator.string)\n };\n\n coercedResponses[403] = {\n description: HTTPStatuses[403],\n content: contentResolver(schemaValidator, schemaValidator.string)\n };\n\n if ('basic' in auth) {\n operationObject.security = [\n {\n basic: Array.from(\n 'allowedPermissions' in auth &&\n auth.allowedPermissions instanceof Set\n ? auth.allowedPermissions.values()\n : []\n )\n }\n ];\n\n securitySchemes['basic'] = {\n type: 'http',\n scheme: 'basic'\n };\n } else if (auth) {\n operationObject.security = [\n {\n [auth.headerName !== 'Authorization' ? 'bearer' : 'apiKey']:\n Array.from(\n 'allowedPermissions' in auth &&\n auth.allowedPermissions instanceof Set\n ? auth.allowedPermissions.values()\n : []\n )\n }\n ];\n\n if (auth.headerName && auth.headerName !== 'Authorization') {\n securitySchemes[auth.headerName] = {\n type: 'apiKey',\n in: 'header',\n name: auth.headerName\n };\n } else {\n securitySchemes['Authorization'] = {\n type: 'http',\n scheme: 'bearer',\n bearerFormat: 'JWT'\n };\n }\n }\n }\n\n return operationObject;\n}\n\n/**\n * Generates a Swagger document from given routers.\n *\n * @template SV - A type that extends AnySchemaValidator.\n * @param {SV} schemaValidator - The schema validator.\n * @param {string | number} port - The port on which the server is running.\n * @param {ForklaunchRouter<SV>[]} routers - The routers to include in the Swagger document.\n * @returns {OpenAPIObject} - The generated Swagger document.\n */\nexport function generateOpenApiSpecs<SV extends AnySchemaValidator>(\n schemaValidator: SV,\n serverUrls: string[],\n serverDescriptions: string[],\n application: ForklaunchRouter<SV>,\n appOptions?: ExpressLikeApplicationOptions<SV, SessionObject<SV>>['openapi']\n): Record<string | symbol, OpenAPIObject> {\n const versionedPaths: Record<string | symbol, PathObject> = {\n [OPENAPI_DEFAULT_VERSION]: {}\n };\n const versionedTags: Record<string | symbol, TagObject[]> = {\n [OPENAPI_DEFAULT_VERSION]: []\n };\n const versionedSecuritySchemes: Record<\n string | symbol,\n Record<string, SecuritySchemeObject>\n > = {\n [OPENAPI_DEFAULT_VERSION]: {}\n };\n\n [\n {\n fullPath: application.basePath === '/' ? '' : application.basePath,\n router: application\n },\n ...unpackRouters<SV>(application.routers, [\n application.basePath === '/' ? '' : application.basePath\n ])\n ].forEach(({ fullPath, router }) => {\n const controllerName = transformBasePath(fullPath);\n router.routes.forEach((route) => {\n const openApiPath = openApiCompliantPath(\n `${fullPath}${route.path === '/' ? '' : route.path}`\n );\n\n const { name, summary, params, versions, auth, options } =\n route.contractDetails;\n\n if (!(\n options?.openapi ??\n router.routerOptions?.openapi ??\n appOptions !== false\n )) {\n return;\n }\n\n if (versions) {\n for (const version of Object.keys(versions)) {\n if (!versionedPaths[version]) {\n versionedPaths[version] = {};\n }\n if (!versionedPaths[version][openApiPath]) {\n versionedPaths[version][openApiPath] = {};\n }\n if (!versionedTags[version]) {\n versionedTags[version] = [];\n }\n if (\n !versionedTags[version].find((tag) => tag.name === controllerName)\n ) {\n versionedTags[version].push({\n name: controllerName,\n description: `${toUpperCase(controllerName)} Operations`\n });\n }\n if (!versionedSecuritySchemes[version]) {\n versionedSecuritySchemes[version] = {};\n }\n\n const { query, requestHeaders, body, responses, responseHeaders } =\n versions[version];\n\n const operationObject = generateOperationObject<SV>(\n schemaValidator,\n route.path,\n route.method,\n controllerName,\n router.sdkPaths,\n versionedSecuritySchemes[version],\n name,\n summary,\n responses,\n params,\n responseHeaders,\n requestHeaders,\n query,\n body,\n auth\n );\n\n if (route.method !== 'middleware') {\n versionedPaths[version][openApiPath][route.method] =\n operationObject;\n }\n }\n } else {\n if (!versionedPaths[OPENAPI_DEFAULT_VERSION]) {\n versionedPaths[OPENAPI_DEFAULT_VERSION] = {};\n }\n if (!versionedPaths[OPENAPI_DEFAULT_VERSION][openApiPath]) {\n versionedPaths[OPENAPI_DEFAULT_VERSION][openApiPath] = {};\n }\n if (!versionedTags[OPENAPI_DEFAULT_VERSION]) {\n versionedTags[OPENAPI_DEFAULT_VERSION] = [];\n }\n if (\n !versionedTags[OPENAPI_DEFAULT_VERSION].find(\n (tag) => tag.name === controllerName\n )\n ) {\n versionedTags[OPENAPI_DEFAULT_VERSION].push({\n name: controllerName,\n description: `${toUpperCase(controllerName)} Operations`\n });\n }\n if (!versionedSecuritySchemes[OPENAPI_DEFAULT_VERSION]) {\n versionedSecuritySchemes[OPENAPI_DEFAULT_VERSION] = {};\n }\n\n const { query, requestHeaders, body, responses, responseHeaders } =\n route.contractDetails;\n\n const operationObject = generateOperationObject<SV>(\n schemaValidator,\n route.path,\n route.method,\n controllerName,\n router.sdkPaths,\n versionedSecuritySchemes[OPENAPI_DEFAULT_VERSION],\n name,\n summary,\n responses,\n params,\n responseHeaders,\n requestHeaders,\n query,\n body,\n auth\n );\n\n if (route.method !== 'middleware') {\n versionedPaths[OPENAPI_DEFAULT_VERSION][openApiPath][route.method] =\n operationObject;\n }\n }\n });\n });\n\n return generateOpenApiDocument(\n serverUrls,\n serverDescriptions,\n versionedTags,\n versionedPaths,\n versionedSecuritySchemes,\n appOptions\n );\n}\n","import { createHash } from 'crypto';\nimport { MetricsDefinition } from '../types/openTelemetryCollector.types';\nimport { OpenTelemetryCollector } from './openTelemetryCollector';\n\nexport type AuditEntry = {\n timestamp: string;\n userId: string | null;\n tenantId: string | null;\n route: string;\n method: string;\n bodyHash: string;\n status: number;\n duration: number;\n redactedFields: string[];\n eventType:\n | 'http'\n | 'ws'\n | 'auth_failure'\n | 'rate_limit'\n | 'rbac_deny'\n | 'super_admin_bypass';\n};\n\nexport class AuditLogger {\n _otel: OpenTelemetryCollector<MetricsDefinition>;\n\n constructor(otel: OpenTelemetryCollector<MetricsDefinition>) {\n this._otel = otel;\n }\n\n append(entry: AuditEntry): void {\n try {\n this._otel.info(\n {\n 'log.type': 'audit',\n 'audit.timestamp': entry.timestamp,\n 'audit.userId': entry.userId ?? '',\n 'audit.tenantId': entry.tenantId ?? '',\n 'audit.route': entry.route,\n 'audit.method': entry.method,\n 'audit.bodyHash': entry.bodyHash,\n 'audit.status': entry.status,\n 'audit.duration': entry.duration,\n 'audit.redactedFields': entry.redactedFields.join(','),\n 'audit.eventType': entry.eventType,\n _meta: true\n },\n `audit:${entry.eventType} ${entry.method} ${entry.route} ${entry.status}`\n );\n } catch (error: unknown) {\n console.error('Failed to emit audit log via OTEL:', error);\n }\n }\n\n static hashBody(body: string | Buffer | undefined | null): string {\n if (body === undefined || body === null || body === '') {\n return '';\n }\n return createHash('sha256').update(body).digest('hex');\n }\n}\n","import { LevelWithSilentOrString } from 'pino';\nimport { TelemetryOptions } from '../types/openTelemetryCollector.types';\n\nexport function evaluateTelemetryOptions(telemetryOptions: TelemetryOptions): {\n enabled: {\n metrics?: boolean;\n tracing?: boolean;\n logging?: boolean;\n };\n level: LevelWithSilentOrString;\n} {\n return {\n enabled:\n typeof telemetryOptions.enabled === 'boolean'\n ? {\n metrics: telemetryOptions.enabled,\n tracing: telemetryOptions.enabled,\n logging: telemetryOptions.enabled\n }\n : {\n metrics: telemetryOptions.enabled.metrics,\n tracing: telemetryOptions.enabled.tracing,\n logging: telemetryOptions.enabled.logging\n },\n level: telemetryOptions.level\n };\n}\n","import { MetricsDefinition } from '../types/openTelemetryCollector.types';\n\nexport function metricsDefinitions<T extends MetricsDefinition>(metrics: T) {\n return metrics;\n}\n","import { TtlCache } from '../../cache/interfaces/ttlCache.interface';\n\n/**\n * Configuration for rate limiting with separate read/write limits.\n */\nexport type RateLimitConfig = {\n /** Max requests per window for GET/HEAD/OPTIONS */\n read: number;\n /** Max requests per window for POST/PUT/PATCH/DELETE */\n write: number;\n /** Window duration in milliseconds */\n windowMs: number;\n};\n\n/**\n * Result of a rate limit check.\n */\nexport type RateLimitResult = {\n /** Whether the request is allowed */\n allowed: boolean;\n /** Number of remaining requests in the current window */\n remaining: number;\n /** Unix timestamp (ms) when the current window resets */\n resetAt: number;\n};\n\ntype RateLimitCounter = {\n count: number;\n resetAt: number;\n};\n\nconst READ_METHODS = new Set(['GET', 'HEAD', 'OPTIONS']);\n\n/**\n * Rate limiter backed by a TtlCache.\n *\n * Uses a sliding-window counter pattern: each unique key maps to a\n * {@link RateLimitCounter} stored in the cache with a TTL equal to the\n * configured window duration.\n */\nexport class RateLimiter {\n constructor(private cache: TtlCache) {}\n\n /**\n * Check whether the given key is within its rate limit.\n *\n * The counter is read from the cache, incremented, and written back.\n * If the cache is unreachable the limiter **fails open** (allows the\n * request) so that a cache outage does not take down the service.\n *\n * @param key - The rate limit key (see {@link RateLimiter.buildKey}).\n * @param limit - Maximum number of requests allowed in the window.\n * @param windowMs - Window duration in milliseconds.\n */\n async check(\n key: string,\n limit: number,\n windowMs: number\n ): Promise<RateLimitResult> {\n try {\n const now = Date.now();\n let counter: RateLimitCounter;\n\n try {\n const record = await this.cache.readRecord<RateLimitCounter>(key);\n counter = record.value;\n\n // If the stored window has expired, start a new one\n if (now >= counter.resetAt) {\n counter = { count: 0, resetAt: now + windowMs };\n }\n } catch {\n // Key does not exist yet – start a fresh window\n counter = { count: 0, resetAt: now + windowMs };\n }\n\n counter.count += 1;\n\n const ttl = Math.max(counter.resetAt - now, 1);\n\n await this.cache.putRecord<RateLimitCounter>({\n key,\n value: counter,\n ttlMilliseconds: ttl\n });\n\n const allowed = counter.count <= limit;\n const remaining = Math.max(limit - counter.count, 0);\n\n return { allowed, remaining, resetAt: counter.resetAt };\n } catch {\n // Fail open – cache errors should not block requests\n console.warn(`[RateLimiter] Cache error for key \"${key}\". Failing open.`);\n return { allowed: true, remaining: limit, resetAt: 0 };\n }\n }\n\n /**\n * Build a rate limit key from request context parts.\n *\n * Format: `ratelimit:{tenantId}:{route}:{userId}:{operationType}`\n *\n * When `tenantId` or `userId` is `null`, the placeholder `\"anon\"` is used.\n */\n static buildKey(parts: {\n tenantId: string | null;\n route: string;\n userId: string | null;\n operationType: 'read' | 'write';\n }): string {\n const tenant = parts.tenantId ?? 'anon';\n const user = parts.userId ?? 'anon';\n return `ratelimit:${tenant}:${parts.route}:${user}:${parts.operationType}`;\n }\n\n /**\n * Determine whether an HTTP method is a read or write operation.\n *\n * GET, HEAD, and OPTIONS are reads; everything else is a write.\n */\n static operationType(method: string): 'read' | 'write' {\n return READ_METHODS.has(method.toUpperCase()) ? 'read' : 'write';\n }\n}\n"],"mappings":"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AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAwBL,KAAK;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;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;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAuEL,KAAK;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;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAsCL,KAAK;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,EA4BL,KAAK;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,EA2BL,KAAK;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;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAwCL,KAAK;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA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","names":["trace","corsMiddleware","import_common","middleware","import_common","import_api","import_semantic_conventions","import_common","import_api","import_semantic_conventions","import_common","meta","pino","dotenv","OTEL_ATTR_SERVICE_NAME","import_common","import_common","import_common","import_common","import_crypto","import_jose","context","joseErrors","import_common","import_common","import_validator","middleware","import_crypto","import_crypto","options","options","options","options","options","E164","options","E164","options","options","trace","import_common","options","version","import_validator","parse","import_common","import_common","import_semantic_conventions","parse","data","import_common","key","options","import_crypto","metrics","record"]}
|
|
1
|
+
{"version":3,"sources":["../../src/http/index.ts","../../src/http/middleware/request/cors.middleware.ts","../../src/http/router/expressLikeRouter.ts","../../src/http/guards/hasPermissionChecks.ts","../../src/http/guards/hasRoleChecks.ts","../../src/http/guards/hasScopeChecks.ts","../../src/http/guards/isForklaunchRouter.ts","../../src/http/guards/isConstrainedForklaunchRouter.ts","../../src/http/guards/isExpressLikeSchemaHandler.ts","../../src/http/guards/isForklaunchExpressLikeRouter.ts","../../src/http/guards/isSdkHandler.ts","../../src/http/guards/isTypedHandler.ts","../../src/http/middleware/request/createContext.middleware.ts","../../src/http/telemetry/constants.ts","../../src/http/telemetry/openTelemetryCollector.ts","../../src/http/guards/isForklaunchRequest.ts","../../src/http/telemetry/pinoLogger.ts","../../src/http/guards/isLoggerMeta.ts","../../src/http/router/discriminateBody.ts","../../src/http/router/routerSharedLogic.ts","../../src/http/guards/hasVersionedSchema.ts","../../src/http/guards/isHmacMethod.ts","../../src/http/guards/isPathParamContractDetails.ts","../../src/http/guards/isHttpContractDetails.ts","../../src/http/middleware/request/auth.middleware.ts","../../src/http/discriminateAuthMethod.ts","../../src/http/createHmacToken.ts","../../src/http/guards/isBasicAuthMethod.ts","../../src/http/guards/isJwtAuthMethod.ts","../../src/http/guards/hasFeatureChecks.ts","../../src/http/guards/hasSubscriptionChecks.ts","../../src/http/middleware/request/authLogContext.ts","../../src/http/middleware/request/enrichDetails.middleware.ts","../../src/http/telemetry/requestAudit.ts","../../src/persistence/encryptedType.ts","../../src/persistence/complianceChanges.ts","../../src/persistence/compliantField.ts","../../src/persistence/fieldEncryptor.ts","../../src/http/telemetry/auditLogger.ts","../../src/http/middleware/request/parse.middleware.ts","../../src/http/guards/hasSend.ts","../../src/http/guards/isRequestShape.ts","../../src/http/application/expressLikeApplication.ts","../../src/http/cluster/isPortBound.ts","../../src/http/generateHmacAuthHeaders.ts","../../src/http/instanceGateway.ts","../../src/http/modelGatewayClient.ts","../../src/http/previewModelGatewayClient.ts","../../src/http/emailClient.ts","../../src/http/smsClient.ts","../../src/http/whatsappClient.ts","../../src/http/voiceClient.ts","../../src/http/paymentsClient.ts","../../src/http/guards/isPath.ts","../../src/http/handlers/typedHandler.ts","../../src/http/handlers/delete.ts","../../src/http/handlers/get.ts","../../src/http/handlers/head.ts","../../src/http/handlers/middleware.ts","../../src/http/handlers/options.ts","../../src/http/handlers/patch.ts","../../src/http/handlers/post.ts","../../src/http/handlers/put.ts","../../src/http/handlers/trace.ts","../../src/http/handlers/typedAuthHandler.ts","../../src/http/httpStatusCodes.ts","../../src/http/mcpGenerator/mcpGenerator.ts","../../src/http/router/unpackRouters.ts","../../src/http/middleware/response/parse.middleware.ts","../../src/http/guards/isResponseCompiledSchema.ts","../../src/http/middleware/response/enrichExpressLikeSend.middleware.ts","../../src/http/telemetry/recordMetric.ts","../../src/http/openApiV3Generator/openApiV3Generator.ts","../../src/http/telemetry/evaluateTelemetryOptions.ts","../../src/http/telemetry/metricsDefinition.ts","../../src/http/rateLimit/rateLimiter.ts"],"sourcesContent":["export type { ParsedQs } from 'qs';\nexport * from './application/expressLikeApplication';\nexport * from './cluster/cluster.types';\nexport * from './cluster/isPortBound';\nexport * from './createHmacToken';\nexport * from './generateHmacAuthHeaders';\nexport * from './instanceGateway';\nexport * from './modelGatewayClient';\nexport * from './previewModelGatewayClient';\nexport * from './emailClient';\nexport * from './smsClient';\nexport * from './whatsappClient';\nexport * from './voiceClient';\nexport * from './paymentsClient';\nexport * from './discriminateAuthMethod';\nexport * from './guards/isForklaunchRequest';\nexport * from './guards/isForklaunchRouter';\nexport * from './handlers/delete';\nexport * from './handlers/get';\nexport * from './handlers/head';\nexport * from './handlers/middleware';\nexport * from './handlers/options';\nexport * from './handlers/patch';\nexport * from './handlers/post';\nexport * from './handlers/put';\nexport * from './handlers/trace';\nexport * from './handlers/typedAuthHandler';\nexport * from './handlers/typedHandler';\nexport * from './httpStatusCodes';\nexport * from './interfaces/expressLikeRouter.interface';\nexport * from './mcpGenerator/mcpGenerator';\nexport * from './middleware/request/createContext.middleware';\nexport * from './middleware/response/enrichExpressLikeSend.middleware';\nexport * from './openApiV3Generator/openApiV3Generator';\nexport * from './router/discriminateBody';\nexport * from './router/expressLikeRouter';\nexport * from './telemetry/auditLogger';\nexport * from './telemetry/requestAudit';\nexport * from './telemetry/constants';\nexport * from './telemetry/evaluateTelemetryOptions';\nexport * from './telemetry/metricsDefinition';\nexport * from './telemetry/openTelemetryCollector';\nexport * from './telemetry/pinoLogger';\nexport * from './telemetry/recordMetric';\nexport * from './types/apiDefinition.types';\nexport * from './types/contractDetails.types';\nexport * from './types/docsConfiguration.types';\nexport * from './types/expressLikeOptions';\nexport * from './types/expressLikeRouter.types';\nexport * from './types/openTelemetryCollector.types';\nexport * from './types/router.types';\nexport * from './rateLimit/index';\nexport * from './types/sdk.types';\nexport { MapToSdk } from './types/sdk.types';\nexport * from './types/typedHandler.types';\n","import corsMiddleware, { CorsOptions } from 'cors';\nimport { ParsedQs } from 'qs';\nimport {\n ForklaunchBaseRequest,\n ForklaunchNextFunction,\n ForklaunchResHeaders,\n ForklaunchResponse\n} from '../../types/apiDefinition.types';\nimport { ParamsDictionary } from '../../types/contractDetails.types';\n\n/**\n * Cors middleware handler\n *\n * @param req - Express-like request object\n * @param res - Express-like response object\n * @param next - Express-like next function\n */\nexport function cors<\n P extends ParamsDictionary,\n ResBodyMap extends Record<number, unknown>,\n ReqBody extends Record<string, unknown>,\n ReqQuery extends ParsedQs,\n ReqHeaders extends Record<string, string>,\n ResHeaders extends Record<string, unknown>,\n LocalsObj extends Record<string, unknown>\n>(corsOptions: CorsOptions) {\n return (\n req: ForklaunchBaseRequest<P, ReqBody, ReqQuery, ReqHeaders>,\n res: ForklaunchResponse<\n unknown,\n ResBodyMap,\n ForklaunchResHeaders & ResHeaders,\n LocalsObj,\n never\n >,\n next?: ForklaunchNextFunction\n ) => {\n if (req.method === 'OPTIONS') {\n res.cors = true;\n }\n if (!res.getHeader) {\n res.getHeader = (key: string) => {\n return res.getHeaders()[key] as string | string[] | undefined;\n };\n }\n corsMiddleware(corsOptions)(\n req as typeof req & { headers: Record<string, string> },\n res,\n next ?? (() => {})\n );\n };\n}\n","import { AnySchemaValidator, SchemaValidator } from '@forklaunch/validator';\nimport { ParsedQs } from 'qs';\n\nimport {\n EmptyObject,\n hashString,\n Prettify,\n PrettyCamelCase,\n safeStringify,\n sanitizePathSlashes,\n SanitizePathSlashes,\n toPrettyCamelCase,\n toRecord,\n TypeSafeFunction\n} from '@forklaunch/common';\nimport { hasPermissionChecks } from '../guards/hasPermissionChecks';\nimport { hasRoleChecks } from '../guards/hasRoleChecks';\nimport { hasScopeChecks } from '../guards/hasScopeChecks';\nimport { isConstrainedForklaunchRouter } from '../guards/isConstrainedForklaunchRouter';\nimport { isExpressLikeSchemaHandler } from '../guards/isExpressLikeSchemaHandler';\nimport { isForklaunchExpressLikeRouter } from '../guards/isForklaunchExpressLikeRouter';\nimport { isForklaunchRouter } from '../guards/isForklaunchRouter';\nimport { isSdkHandler } from '../guards/isSdkHandler';\nimport { isTypedHandler } from '../guards/isTypedHandler';\nimport {\n ExpressLikeRouter,\n NestableRouterBasedHandler,\n PathBasedHandler,\n PathOrMiddlewareBasedHandler\n} from '../interfaces/expressLikeRouter.interface';\nimport { createContext } from '../middleware/request/createContext.middleware';\nimport { OpenTelemetryCollector } from '../telemetry/openTelemetryCollector';\nimport {\n ExpressLikeHandler,\n ExpressLikeSchemaHandler,\n LiveSdkFunction,\n LiveTypeFunction,\n VersionedRequests,\n VersionedResponses\n} from '../types/apiDefinition.types';\nimport {\n Body,\n HeadersObject,\n Method,\n ParamsDictionary,\n ParamsObject,\n PathParamHttpContractDetails,\n QueryObject,\n ResponsesObject,\n SchemaAuthMethods,\n SessionObject,\n VersionSchema\n} from '../types/contractDetails.types';\nimport { ExpressLikeRouterOptions } from '../types/expressLikeOptions';\nimport {\n ContractDetailsOrMiddlewareOrTypedHandler,\n LiveTypeRouteDefinition,\n MiddlewareOrMiddlewareWithTypedHandler,\n TypedMiddlewareDefinition,\n TypedNestableMiddlewareDefinition\n} from '../types/expressLikeRouter.types';\nimport { MetricsDefinition } from '../types/openTelemetryCollector.types';\nimport {\n ConstrainedForklaunchRouter,\n ForklaunchRoute,\n ForklaunchRouter\n} from '../types/router.types';\nimport { FetchFunction, SdkHandlerObject } from '../types/sdk.types';\nimport { discriminateBody } from './discriminateBody';\nimport {\n compileRouteSchemas,\n resolveContractDetailsAndHandlers,\n resolveRouteMiddlewares,\n validateContractDetails\n} from './routerSharedLogic';\n\n/**\n * Extracts route middleware and handlers from route registration arguments.\n * This is a port function that converts typed handlers into Express middleware\n * without actually registering them on a router.\n *\n * @template SV - The schema validator type.\n * @template Name - The route name.\n * @template ContractMethod - The HTTP method.\n * @template Path - The route path.\n * @template P - The type of request parameters.\n * @template ResBodyMap - The type of response body map.\n * @template ReqBody - The type of request body.\n * @template ReqQuery - The type of request query.\n * @template ReqHeaders - The type of request headers.\n * @template ResHeaders - The type of response headers.\n * @template LocalsObj - The type of local variables.\n * @template VersionedApi - The versioned API schema.\n * @template RouterSession - The router session type.\n * @template BaseRequest - The base request type.\n * @template BaseResponse - The base response type.\n * @template NextFunction - The next function type.\n * @template Auth - The auth schema.\n * @template RouterHandler - The router handler type.\n * @param {object} params - The parameters for extracting route handlers.\n * @param {ContractMethod} params.method - The HTTP method.\n * @param {Path} params.path - The route path.\n * @param {string} params.basePath - The base path for the router.\n * @param {SV} params.schemaValidator - The schema validator.\n * @param {ContractDetailsOrMiddlewareOrTypedHandler<SV, Name, ContractMethod, Path, P, ResBodyMap, ReqBody, ReqQuery, ReqHeaders, ResHeaders, LocalsObj, VersionedApi, BaseRequest, BaseResponse, NextFunction, RouterSession, Auth>} params.contractDetailsOrMiddlewareOrTypedHandler - The contract details or typed handler.\n * @param {MiddlewareOrMiddlewareWithTypedHandler<SV, Name, ContractMethod, Path, P, ResBodyMap, ReqBody, ReqQuery, ReqHeaders, ResHeaders, LocalsObj, VersionedApi, BaseRequest, BaseResponse, NextFunction, RouterSession, Auth>[]} params.middlewareOrMiddlewareAndTypedHandler - Additional middleware or typed handlers.\n * @param {OpenTelemetryCollector<MetricsDefinition>} params.openTelemetryCollector - The OpenTelemetry collector.\n * @param {RouterHandler[]} params.postEnrichMiddleware - Additional middleware to run after enrichment.\n * @param {ExpressLikeRouterOptions<SV, RouterSession> | undefined} params.routerOptions - Router options.\n * @returns {{ middlewares: RouterHandler[]; controllerHandler: ExpressLikeHandler<SV, P, ResBodyMap, ReqBody, ReqQuery, ReqHeaders, ResHeaders, LocalsObj, VersionedRequests, VersionedResponses, RouterSession, BaseRequest, BaseResponse, NextFunction> }} - The extracted middlewares and controller handler.\n */\nexport function extractRouteHandlers<\n SV extends AnySchemaValidator,\n Name extends string,\n ContractMethod extends Method,\n Path extends `/${string}`,\n P extends ParamsObject<SV>,\n ResBodyMap extends ResponsesObject<SV>,\n ReqBody extends Body<SV>,\n ReqQuery extends QueryObject<SV>,\n ReqHeaders extends HeadersObject<SV>,\n ResHeaders extends HeadersObject<SV>,\n LocalsObj extends Record<string, unknown>,\n VersionedApi extends VersionSchema<SV, ContractMethod>,\n RouterSession extends SessionObject<SV>,\n BaseRequest,\n BaseResponse,\n NextFunction,\n Auth extends SchemaAuthMethods<\n SV,\n P,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n VersionedApi,\n BaseRequest\n >,\n RouterHandler\n>(params: {\n method: ContractMethod;\n path: Path;\n basePath: string;\n schemaValidator: SV;\n contractDetailsOrMiddlewareOrTypedHandler: ContractDetailsOrMiddlewareOrTypedHandler<\n SV,\n Name,\n ContractMethod,\n Path,\n P,\n ResBodyMap,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n ResHeaders,\n LocalsObj,\n VersionedApi,\n BaseRequest,\n BaseResponse,\n NextFunction,\n RouterSession,\n Auth\n >;\n middlewareOrMiddlewareAndTypedHandler: MiddlewareOrMiddlewareWithTypedHandler<\n SV,\n Name,\n ContractMethod,\n Path,\n P,\n ResBodyMap,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n ResHeaders,\n LocalsObj,\n VersionedApi,\n BaseRequest,\n BaseResponse,\n NextFunction,\n RouterSession,\n Auth\n >[];\n openTelemetryCollector?: OpenTelemetryCollector<MetricsDefinition>;\n postEnrichMiddleware?: RouterHandler[];\n routerOptions?: ExpressLikeRouterOptions<SV, RouterSession>;\n}): {\n middlewares: RouterHandler[];\n controllerHandler: ExpressLikeSchemaHandler<\n SV,\n P,\n ResBodyMap,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n ResHeaders,\n LocalsObj,\n VersionedApi,\n RouterSession,\n BaseRequest,\n BaseResponse,\n NextFunction\n >;\n} {\n const schemaValidator = params.schemaValidator as SV & SchemaValidator;\n\n const { contractDetails, handlers } = resolveContractDetailsAndHandlers<\n SV,\n Name,\n ContractMethod,\n Path,\n P,\n ResBodyMap,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n ResHeaders,\n LocalsObj,\n VersionedApi,\n RouterSession,\n BaseRequest,\n BaseResponse,\n NextFunction,\n Auth\n >(\n params.contractDetailsOrMiddlewareOrTypedHandler,\n params.middlewareOrMiddlewareAndTypedHandler\n );\n\n validateContractDetails(contractDetails, schemaValidator);\n\n const { requestSchema, responseSchemas } = compileRouteSchemas(\n contractDetails,\n schemaValidator\n );\n\n const { middlewares, controllerHandler } = resolveRouteMiddlewares<\n SV,\n Name,\n ContractMethod,\n Path,\n P,\n ResBodyMap,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n ResHeaders,\n LocalsObj,\n VersionedApi,\n RouterSession,\n BaseRequest,\n BaseResponse,\n NextFunction,\n Auth,\n RouterHandler\n >({\n basePath: params.basePath,\n path: params.path,\n contractDetails,\n requestSchema,\n responseSchemas,\n openTelemetryCollector: params.openTelemetryCollector,\n routerOptions: params.routerOptions,\n postEnrichMiddleware: params.postEnrichMiddleware ?? [],\n handlers,\n includeCreateContext: false\n });\n\n return {\n middlewares: [\n createContext(schemaValidator) as RouterHandler,\n ...middlewares\n ],\n controllerHandler\n };\n}\n\n/**\n * A class that represents an Express-like router.\n */\n/**\n * Process-level signal handlers belong to the process, not to each router.\n *\n * These used to be registered inside the router constructor, so every router an\n * application created added four more listeners to `process`. A service with\n * eleven routers therefore tripped Node's warning at startup:\n *\n * MaxListenersExceededWarning: Possible EventEmitter memory leak detected.\n * 11 unhandledRejection listeners added to [process].\n *\n * The warning was the visible half. The rest: the listener array grew with\n * router count, and on a single unhandled rejection EVERY registered handler\n * ran — logging the same error once per router and each calling\n * `process.exit(1)`.\n *\n * Installing once keeps the behaviour identical from the outside: the first\n * router to be constructed provides the collector, and there is exactly one\n * handler per signal no matter how many routers follow.\n */\nlet processHandlersInstalled = false;\n\nfunction installProcessHandlers(\n openTelemetryCollector: OpenTelemetryCollector<MetricsDefinition>\n): void {\n if (processHandlersInstalled) {\n return;\n }\n processHandlersInstalled = true;\n\n process.on('uncaughtException', (err) => {\n openTelemetryCollector.error(`Uncaught exception: ${err}`);\n process.exit(1);\n });\n process.on('unhandledRejection', (reason) => {\n openTelemetryCollector.error(`Unhandled rejection: ${reason}`);\n process.exit(1);\n });\n\n process.on('exit', () => {\n openTelemetryCollector.info('Shutting down application');\n });\n process.on('SIGINT', () => {\n openTelemetryCollector.info('Shutting down application');\n process.exit(0);\n });\n}\n\n/**\n * Test-only. Lets a suite assert the handlers install exactly once across many\n * routers without leaking state into the next test.\n */\nexport function resetProcessHandlersForTesting(): void {\n processHandlersInstalled = false;\n}\n\nexport class ForklaunchExpressLikeRouter<\n SV extends AnySchemaValidator,\n BasePath extends `/${string}`,\n RouterHandler,\n Internal extends ExpressLikeRouter<RouterHandler, Internal>,\n BaseRequest,\n BaseResponse,\n NextFunction,\n RouterSession extends SessionObject<SV>,\n FetchMap extends Record<string, unknown> = EmptyObject,\n Sdk extends Record<string, unknown> = EmptyObject\n> implements ConstrainedForklaunchRouter<SV, RouterHandler> {\n requestHandler!: RouterHandler;\n routers: ForklaunchRouter<SV>[] = [];\n routes: ForklaunchRoute<SV>[] = [];\n\n _fetchMap: FetchMap = {} as FetchMap;\n sdk: Sdk = {} as Sdk;\n\n sdkPaths: Record<string, string> = {};\n\n constructor(\n readonly basePath: BasePath,\n readonly schemaValidator: SV,\n readonly internal: Internal,\n readonly postEnrichMiddleware: RouterHandler[],\n readonly openTelemetryCollector: OpenTelemetryCollector<MetricsDefinition>,\n readonly routerOptions?: ExpressLikeRouterOptions<SV, RouterSession>\n ) {\n if (\n process.env.NODE_ENV !== 'test' &&\n !process.env.VITEST &&\n process.env.FORKLAUNCH_MODE !== 'openapi'\n ) {\n installProcessHandlers(this.openTelemetryCollector);\n }\n\n this.internal.use(createContext(this.schemaValidator) as RouterHandler);\n }\n\n /**\n * Resolves middlewares based on the contract details.\n *\n * @param {PathParamHttpContractDetails<SV> | HttpContractDetails<SV>} contractDetails - The contract details.\n * @returns {MiddlewareHandler<SV>[]} - The resolved middlewares.\n */\n\n /**\n * Parses and runs the controller handler with error handling.\n *\n * @template P - The type of request parameters.\n * @template ResBodyMap - The type of response body.\n * @template ReqBody - The type of request body.\n * @template ReqQuery - The type of request query.\n * @template LocalsObj - The type of local variables.\n * @template StatusCode - The type of status code.\n * @param {MiddlewareHandler<SV, P, ResBodyMap | string, ReqBody, ReqQuery, LocalsObj, StatusCode>} requestHandler - The request handler.\n * @returns {ExpressMiddlewareHandler} - The Express request handler.\n */\n #parseAndRunControllerHandler<\n P extends ParamsDictionary,\n ResBodyMap extends Record<number, unknown>,\n ReqBody extends Record<string, unknown>,\n ReqQuery extends ParsedQs,\n ReqHeaders extends Record<string, string>,\n ResHeaders extends Record<string, string>,\n LocalsObj extends Record<string, unknown>,\n VersionedReqs extends VersionedRequests,\n VersionedResps extends VersionedResponses,\n RouterSession extends Record<string, unknown>\n >(\n requestHandler: ExpressLikeHandler<\n SV,\n P,\n ResBodyMap,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n ResHeaders,\n LocalsObj,\n VersionedReqs,\n VersionedResps,\n RouterSession,\n BaseRequest,\n BaseResponse,\n NextFunction\n >\n ): ExpressLikeHandler<\n SV,\n P,\n ResBodyMap,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n ResHeaders,\n LocalsObj,\n VersionedReqs,\n VersionedResps,\n RouterSession,\n BaseRequest,\n BaseResponse,\n NextFunction\n > {\n return async (req, res, next) => {\n if (!requestHandler) {\n throw new Error('Controller handler is not defined');\n }\n\n try {\n await requestHandler(req, res, next);\n } catch (error) {\n if (next && typeof next === 'function') {\n next(error as Error);\n } else {\n throw error;\n }\n }\n };\n }\n\n /**\n * Extracts the controller handler from the provided handlers.\n *\n * @template P - The type of request parameters.\n * @template ResBodyMap - The type of response body.\n * @template ReqBody - The type of request body.\n * @template ReqQuery - The type of request query.\n * @template LocalsObj - The type of local variables.\n * @param {MiddlewareHandler<SV, P, ResBodyMap, ReqBody, ReqQuery, LocalsObj>[]} handlers - The provided handlers.\n * @returns {MiddlewareHandler<SV, P, ResBodyMap, ReqBody, ReqQuery, LocalsObj>} - The extracted controller handler.\n * @throws {Error} - Throws an error if the last argument is not a handler.\n */\n\n /**\n * Fetches a route from the route map and executes it with the given parameters.\n *\n * @template Path - The path type that extends keyof _fetchMap and string.\n * @param {Path} path - The route path\n * @param {Parameters<_fetchMap[Path]>[1]} [requestInit] - Optional request initialization parameters.\n * @returns {Promise<ReturnType<_fetchMap[Path]>>} - The result of executing the route handler.\n */\n fetch: FetchFunction<this['_fetchMap']> = async <\n Path extends keyof this['_fetchMap'],\n Method extends keyof this['_fetchMap'][Path],\n Version extends keyof this['_fetchMap'][Path][Method]\n >(\n path: Path,\n ...reqInit: this['_fetchMap'][Path][Method] extends TypeSafeFunction\n ? 'GET' extends keyof this['_fetchMap'][Path]\n ? this['_fetchMap'][Path]['GET'] extends TypeSafeFunction\n ? Parameters<this['_fetchMap'][Path]['GET']>[1] extends\n | {\n body: unknown;\n }\n | { query: unknown }\n | { params: unknown }\n | { headers: unknown }\n | { version: unknown }\n ? [\n reqInit: Omit<\n Parameters<this['_fetchMap'][Path][Method]>[1],\n 'method'\n > & {\n method: Method;\n }\n ]\n : [\n reqInit?: Omit<\n Parameters<this['_fetchMap'][Path][Method]>[1],\n 'method'\n > & {\n method: Method;\n }\n ]\n : [\n reqInit: Omit<\n Parameters<this['_fetchMap'][Path][Method]>[1],\n 'method'\n > & {\n method: Method;\n }\n ]\n : [\n reqInit: Omit<\n Parameters<this['_fetchMap'][Path][Method]>[1],\n 'method'\n > & {\n method: Method;\n }\n ]\n : this['_fetchMap'][Path][Method] extends Record<string, TypeSafeFunction>\n ? [\n reqInit: Omit<\n Parameters<this['_fetchMap'][Path][Method][Version]>[0],\n 'method' | 'version'\n > & {\n method: Method;\n version: Version;\n }\n ]\n : [{ method: Method }]\n ) => {\n const method = reqInit[0]?.method;\n const version =\n reqInit[0] != null && 'version' in reqInit[0]\n ? reqInit[0].version\n : undefined;\n\n return (\n (version\n ? this._fetchMap[path][method ?? ('GET' as Method)][version]\n : this._fetchMap[path][method ?? ('GET' as Method)]) as (\n route: string,\n request?: unknown\n ) => unknown\n )(\n path as string,\n reqInit[0]\n // reqInit\n ) as this['_fetchMap'][Path][Method] extends TypeSafeFunction\n ? Awaited<ReturnType<this['_fetchMap'][Path][Method]>>\n : this['_fetchMap'][Path][Method] extends Record<string, TypeSafeFunction>\n ? Awaited<ReturnType<this['_fetchMap'][Path][Method][Version]>>\n : never;\n };\n\n /**\n * Executes request locally, applying parameters\n *\n * @param handlers {ExpressLikeHandler<SV>}\n * @param controllerHandler\n * @returns\n */\n #localParamRequest<Middleware, Route extends string>(\n middlewares: Middleware[],\n controllerHandler: Middleware,\n contractDetails: PathParamHttpContractDetails<SV>,\n requestSchema: unknown,\n responseSchemas: unknown,\n version?: string\n ) {\n return async (\n route: SanitizePathSlashes<Route>,\n request?: {\n params?: Record<string, unknown>;\n query?: Record<string, unknown>;\n headers?: Record<string, unknown>;\n body?: Record<string, unknown>;\n executeMiddlewares?: boolean;\n }\n ) => {\n let statusCode: number | undefined;\n let responseMessage: unknown;\n const responseHeaders: Record<string, unknown> = {};\n const resEventHandlers: Record<string, ((...args: unknown[]) => void)[]> =\n {};\n\n const req = {\n params: request?.params ?? {},\n query: request?.query ?? {},\n headers: request?.headers ?? {},\n body:\n discriminateBody(this.schemaValidator, request?.body)?.schema ?? {},\n path: route,\n originalPath: route,\n method: 'GET',\n version,\n schemaValidator: this.schemaValidator,\n contractDetails,\n requestSchema,\n openTelemetryCollector: this.openTelemetryCollector,\n _globalOptions: () => this.routerOptions,\n context: {\n correlationId: 'local-fetch-' + Date.now(),\n span: undefined\n },\n _rawBody: undefined as unknown,\n _parsedVersions: undefined as unknown\n };\n\n const res = {\n statusCode: 200,\n status: (code: number) => {\n statusCode = code;\n res.statusCode = code;\n return res;\n },\n send: (message: string) => {\n responseMessage = message;\n resEventHandlers['finish']?.forEach((handler) => handler());\n },\n json: (body: Record<string, unknown>) => {\n responseMessage = body;\n resEventHandlers['finish']?.forEach((handler) => handler());\n },\n jsonp: (body: Record<string, unknown>) => {\n responseMessage = body;\n resEventHandlers['finish']?.forEach((handler) => handler());\n },\n setHeader: (key: string, value: string) => {\n responseHeaders[key] = value;\n return res;\n },\n getHeader: (key: string) => responseHeaders[key],\n type: (contentType: string) => {\n responseHeaders['content-type'] = contentType;\n return res;\n },\n sseEmitter: (\n generator: () => AsyncGenerator<Record<string, unknown>>\n ) => {\n responseMessage = generator();\n },\n on: (event: string, handler: (...args: unknown[]) => void) => {\n if (!resEventHandlers[event]) {\n resEventHandlers[event] = [];\n }\n resEventHandlers[event].push(handler);\n return res;\n },\n responseSchemas,\n version\n };\n\n const executeMiddlewares = request?.executeMiddlewares ?? false;\n\n if (executeMiddlewares && middlewares.length > 0) {\n const allHandlers = [...middlewares];\n let cursor = allHandlers.shift() as (\n req_: typeof req,\n resp_: typeof res,\n next: (err?: Error) => Promise<void> | void\n ) => Promise<void> | void;\n\n if (cursor) {\n for (const fn of allHandlers) {\n await cursor(req, res, (err?: Error) => {\n if (err) {\n throw err;\n }\n cursor = fn as (\n req_: typeof req,\n resp_: typeof res,\n next: (err?: Error) => Promise<void> | void\n ) => Promise<void> | void;\n });\n }\n await cursor(req, res, async (err?: Error) => {\n if (err) {\n throw err;\n }\n });\n }\n }\n\n const cHandler = controllerHandler as (\n req_: typeof req,\n resp_: typeof res,\n next: (err?: Error) => Promise<void> | void\n ) => void;\n await cHandler(req, res, (err?: Error) => {\n if (err) {\n throw err;\n }\n });\n\n return {\n code: Number(statusCode),\n response: responseMessage,\n headers: responseHeaders\n };\n };\n }\n\n registerRoute<\n Name extends string,\n ContractMethod extends Method,\n Path extends `/${string}`,\n P extends ParamsObject<SV>,\n ResBodyMap extends ResponsesObject<SV>,\n ReqBody extends Body<SV>,\n ReqQuery extends QueryObject<SV>,\n ReqHeaders extends HeadersObject<SV>,\n ResHeaders extends HeadersObject<SV>,\n LocalsObj extends Record<string, unknown>,\n VersionedApi extends VersionSchema<SV, ContractMethod>,\n Auth extends SchemaAuthMethods<\n SV,\n P,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n VersionedApi,\n BaseRequest\n >\n >(\n method: ContractMethod,\n path: Path,\n registrationMethod: PathBasedHandler<RouterHandler>,\n contractDetailsOrMiddlewareOrTypedHandler: ContractDetailsOrMiddlewareOrTypedHandler<\n SV,\n Name,\n ContractMethod,\n Path,\n P,\n ResBodyMap,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n ResHeaders,\n LocalsObj,\n VersionedApi,\n BaseRequest,\n BaseResponse,\n NextFunction,\n RouterSession,\n Auth\n >,\n ...middlewareOrMiddlewareAndTypedHandler: MiddlewareOrMiddlewareWithTypedHandler<\n SV,\n Name,\n ContractMethod,\n Path,\n P,\n ResBodyMap,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n ResHeaders,\n LocalsObj,\n VersionedApi,\n BaseRequest,\n BaseResponse,\n NextFunction,\n RouterSession,\n Auth\n >[]\n ): this & {\n _fetchMap: Prettify<\n FetchMap extends Record<\n SanitizePathSlashes<`${BasePath}${Path}`>,\n unknown\n >\n ? FetchMap &\n Record<\n SanitizePathSlashes<`${BasePath}${Path}`>,\n FetchMap[SanitizePathSlashes<`${BasePath}${Path}`>] &\n Record<\n Uppercase<ContractMethod>,\n LiveTypeFunction<\n SV,\n SanitizePathSlashes<`${BasePath}${Path}`>,\n P,\n ResBodyMap,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n ResHeaders,\n ContractMethod,\n VersionedApi,\n Auth\n >\n >\n >\n : FetchMap &\n Record<\n SanitizePathSlashes<`${BasePath}${Path}`>,\n Record<\n Uppercase<ContractMethod>,\n LiveTypeFunction<\n SV,\n SanitizePathSlashes<`${BasePath}${Path}`>,\n P,\n ResBodyMap,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n ResHeaders,\n ContractMethod,\n VersionedApi,\n Auth\n >\n >\n >\n >;\n sdk: Prettify<\n Sdk &\n Record<\n PrettyCamelCase<\n Name extends string\n ? Name\n : SanitizePathSlashes<`${BasePath}${Path}`>\n >,\n LiveSdkFunction<\n SV,\n P,\n ResBodyMap,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n ResHeaders,\n VersionedApi,\n Auth\n >\n >\n >;\n } {\n // in this case, we know that the first argument is the typedHandler. As a result, we only use defined handlers\n const { contractDetails, handlers } = resolveContractDetailsAndHandlers<\n SV,\n Name,\n ContractMethod,\n Path,\n P,\n ResBodyMap,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n ResHeaders,\n LocalsObj,\n VersionedApi,\n RouterSession,\n BaseRequest,\n BaseResponse,\n NextFunction,\n Auth\n >(\n contractDetailsOrMiddlewareOrTypedHandler,\n middlewareOrMiddlewareAndTypedHandler\n );\n\n validateContractDetails(contractDetails, this.schemaValidator);\n\n this.routes.push({\n basePath: this.basePath,\n path,\n method,\n contractDetails: contractDetails as PathParamHttpContractDetails<SV>\n });\n\n const { requestSchema, responseSchemas } = compileRouteSchemas(\n contractDetails,\n this.schemaValidator\n );\n\n const { middlewares, controllerHandler } = resolveRouteMiddlewares<\n SV,\n Name,\n ContractMethod,\n Path,\n P,\n ResBodyMap,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n ResHeaders,\n LocalsObj,\n VersionedApi,\n RouterSession,\n BaseRequest,\n BaseResponse,\n NextFunction,\n Auth,\n RouterHandler\n >({\n basePath: this.basePath,\n path,\n contractDetails,\n requestSchema,\n responseSchemas,\n openTelemetryCollector: this.openTelemetryCollector,\n routerOptions: this.routerOptions,\n postEnrichMiddleware: this.postEnrichMiddleware,\n includeCreateContext: false,\n handlers,\n router: this\n });\n\n registrationMethod.bind(this.internal)(\n path,\n ...(middlewares as RouterHandler[]),\n this.#parseAndRunControllerHandler(controllerHandler) as RouterHandler\n );\n\n toRecord(this._fetchMap)[sanitizePathSlashes(`${this.basePath}${path}`)] = {\n ...(this._fetchMap[sanitizePathSlashes(`${this.basePath}${path}`)] ?? {}),\n [method.toUpperCase()]: contractDetails.versions\n ? Object.fromEntries(\n Object.keys(contractDetails.versions).map((version) => [\n version,\n this.#localParamRequest(\n middlewares as RouterHandler[],\n controllerHandler as RouterHandler,\n contractDetails as PathParamHttpContractDetails<SV>,\n requestSchema,\n responseSchemas,\n version\n )\n ])\n )\n : this.#localParamRequest(\n middlewares as RouterHandler[],\n controllerHandler as RouterHandler,\n contractDetails as PathParamHttpContractDetails<SV>,\n requestSchema,\n responseSchemas\n )\n };\n\n const contractDetailsName = contractDetails.name;\n if (contractDetailsName) {\n toRecord(this.sdk)[toPrettyCamelCase(contractDetailsName)] =\n contractDetails.versions\n ? Object.fromEntries(\n Object.keys(contractDetails.versions).map((version) => [\n version,\n (req: {\n params?: Record<string, unknown>;\n query?: Record<string, unknown>;\n headers?: Record<string, unknown>;\n body?: Record<string, unknown>;\n }) =>\n this.#localParamRequest(\n middlewares as RouterHandler[],\n controllerHandler as RouterHandler,\n contractDetails as PathParamHttpContractDetails<SV>,\n requestSchema,\n responseSchemas,\n version\n )(`${this.basePath}${path}`, req)\n ])\n )\n : (req: {\n params?: Record<string, unknown>;\n query?: Record<string, unknown>;\n headers?: Record<string, unknown>;\n body?: Record<string, unknown>;\n }) =>\n this.#localParamRequest(\n middlewares as RouterHandler[],\n controllerHandler as RouterHandler,\n contractDetails as PathParamHttpContractDetails<SV>,\n requestSchema,\n responseSchemas\n )(`${this.basePath}${path}`, req);\n }\n return this as this & {\n _fetchMap: FetchMap extends Record<\n SanitizePathSlashes<`${BasePath}${Path}`>,\n unknown\n >\n ? FetchMap &\n Record<\n SanitizePathSlashes<`${BasePath}${Path}`>,\n FetchMap[SanitizePathSlashes<`${BasePath}${Path}`>] &\n Record<\n Uppercase<ContractMethod>,\n LiveTypeFunction<\n SV,\n SanitizePathSlashes<`${BasePath}${Path}`>,\n P,\n ResBodyMap,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n ResHeaders,\n ContractMethod,\n VersionedApi,\n Auth\n >\n >\n >\n : FetchMap &\n Record<\n SanitizePathSlashes<`${BasePath}${Path}`>,\n Record<\n Uppercase<ContractMethod>,\n LiveTypeFunction<\n SV,\n SanitizePathSlashes<`${BasePath}${Path}`>,\n P,\n ResBodyMap,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n ResHeaders,\n ContractMethod,\n VersionedApi,\n Auth\n >\n >\n >;\n sdk: Sdk &\n Record<\n PrettyCamelCase<\n Name extends string\n ? Name\n : SanitizePathSlashes<`${BasePath}${Path}`>\n >,\n LiveSdkFunction<\n SV,\n P,\n ResBodyMap,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n ResHeaders,\n VersionedApi,\n Auth\n >\n >;\n };\n }\n\n #extractHandlers<\n Name extends string,\n Path extends `/${string}`,\n P extends ParamsObject<SV>,\n ResBodyMap extends ResponsesObject<SV>,\n ReqBody extends Body<SV>,\n ReqQuery extends QueryObject<SV>,\n ReqHeaders extends HeadersObject<SV>,\n ResHeaders extends HeadersObject<SV>,\n LocalsObj extends Record<string, unknown>,\n ArrayReturnType,\n VersionedApi extends VersionSchema<SV, 'middleware'>,\n Auth extends SchemaAuthMethods<\n SV,\n P,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n VersionedApi,\n BaseRequest\n >\n >(\n handlers: (\n | MiddlewareOrMiddlewareWithTypedHandler<\n SV,\n Name,\n 'middleware',\n Path,\n P,\n ResBodyMap,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n ResHeaders,\n LocalsObj,\n VersionedApi,\n BaseRequest,\n BaseResponse,\n NextFunction,\n RouterSession,\n Auth\n >\n | ConstrainedForklaunchRouter<SV, RouterHandler>\n | RouterHandler\n )[],\n processMiddleware?: (handler: unknown) => RouterHandler | Internal\n ) {\n const last = handlers.pop();\n let finalHandlers = last ? [last] : [];\n if (\n isTypedHandler<\n SV,\n Name,\n 'middleware',\n Path,\n P,\n ResBodyMap,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n ResHeaders,\n LocalsObj,\n VersionedApi,\n BaseRequest,\n BaseResponse,\n NextFunction,\n Auth\n >(last)\n ) {\n finalHandlers = last.handlers;\n }\n\n handlers.forEach((handler) => {\n if (\n isTypedHandler<\n SV,\n Name,\n 'middleware',\n Path,\n P,\n ResBodyMap,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n ResHeaders,\n LocalsObj,\n VersionedApi,\n BaseRequest,\n BaseResponse,\n NextFunction,\n Auth\n >(handler)\n ) {\n throw new Error(\n 'Only the last argument supplied to this function can be a typed handler. Please use only middleware.'\n );\n }\n });\n\n const middleware = processMiddleware\n ? handlers.map(processMiddleware)\n : (handlers as ArrayReturnType[]);\n\n return [...middleware, ...finalHandlers] as ArrayReturnType[];\n }\n\n #extractMiddlewareFromEnrichedTypedHandlerArray<\n Name extends string,\n Path extends `/${string}`,\n P extends ParamsObject<SV>,\n ResBodyMap extends ResponsesObject<SV>,\n ReqBody extends Body<SV>,\n ReqQuery extends QueryObject<SV>,\n ReqHeaders extends HeadersObject<SV>,\n ResHeaders extends HeadersObject<SV>,\n LocalsObj extends Record<string, unknown>,\n VersionedApi extends VersionSchema<SV, 'middleware'>,\n Auth extends SchemaAuthMethods<\n SV,\n P,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n VersionedApi,\n BaseRequest\n >\n >(\n handlers: (\n | MiddlewareOrMiddlewareWithTypedHandler<\n SV,\n Name,\n 'middleware',\n Path,\n P,\n ResBodyMap,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n ResHeaders,\n LocalsObj,\n VersionedApi,\n BaseRequest,\n BaseResponse,\n NextFunction,\n RouterSession,\n Auth\n >\n | RouterHandler\n )[]\n ) {\n return this.#extractHandlers<\n Name,\n Path,\n P,\n ResBodyMap,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n ResHeaders,\n LocalsObj,\n RouterHandler,\n VersionedApi,\n Auth\n >(handlers);\n }\n\n #extractNestableMiddlewareFromEnrichedTypedHandlerArray<\n Name extends string,\n Path extends `/${string}`,\n P extends ParamsObject<SV>,\n ResBodyMap extends ResponsesObject<SV>,\n ReqBody extends Body<SV>,\n ReqQuery extends QueryObject<SV>,\n ReqHeaders extends HeadersObject<SV>,\n ResHeaders extends HeadersObject<SV>,\n LocalsObj extends Record<string, unknown>,\n VersionedApi extends VersionSchema<SV, 'middleware'>,\n Auth extends SchemaAuthMethods<\n SV,\n P,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n VersionedApi,\n BaseRequest\n >\n >(\n handlers: (\n | MiddlewareOrMiddlewareWithTypedHandler<\n SV,\n Name,\n 'middleware',\n Path,\n P,\n ResBodyMap,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n ResHeaders,\n LocalsObj,\n VersionedApi,\n BaseRequest,\n BaseResponse,\n NextFunction,\n RouterSession,\n Auth\n >\n | ConstrainedForklaunchRouter<SV, RouterHandler>\n )[]\n ) {\n return this.#extractHandlers<\n Name,\n Path,\n P,\n ResBodyMap,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n ResHeaders,\n LocalsObj,\n RouterHandler | Internal,\n VersionedApi,\n Auth\n >(handlers, (handler) => {\n if (\n isForklaunchExpressLikeRouter<\n SV,\n Path,\n RouterHandler,\n Internal,\n BaseRequest,\n BaseResponse,\n NextFunction,\n FetchMap,\n Sdk\n >(handler)\n ) {\n this.addRouterToSdk(handler);\n return handler.internal;\n }\n return handler as RouterHandler;\n });\n }\n\n #processTypedHandlerOrMiddleware<\n Name extends string,\n Path extends `/${string}`,\n P extends ParamsObject<SV>,\n ResBodyMap extends ResponsesObject<SV>,\n ReqBody extends Body<SV>,\n ReqQuery extends QueryObject<SV>,\n ReqHeaders extends HeadersObject<SV>,\n ResHeaders extends HeadersObject<SV>,\n LocalsObj extends Record<string, unknown>,\n VersionedApi extends VersionSchema<SV, 'middleware'>,\n Auth extends SchemaAuthMethods<\n SV,\n P,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n VersionedApi,\n BaseRequest\n >\n >(\n handler:\n | ContractDetailsOrMiddlewareOrTypedHandler<\n SV,\n Name,\n 'middleware',\n Path,\n P,\n ResBodyMap,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n ResHeaders,\n LocalsObj,\n VersionedApi,\n BaseRequest,\n BaseResponse,\n NextFunction,\n RouterSession,\n Auth\n >\n | RouterHandler\n | undefined,\n middleware: RouterHandler[]\n ) {\n if (\n isTypedHandler<\n SV,\n Name,\n 'middleware',\n Path,\n P,\n ResBodyMap,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n ResHeaders,\n LocalsObj,\n VersionedApi,\n BaseRequest,\n BaseResponse,\n NextFunction,\n Auth\n >(handler)\n ) {\n middleware.push(...(handler.handlers as RouterHandler[]));\n } else if (isExpressLikeSchemaHandler(handler)) {\n middleware.push(handler as RouterHandler);\n }\n }\n\n #extractMiddlewareAsRouterHandlers<\n Name extends string,\n Path extends `/${string}`,\n P extends ParamsObject<SV>,\n ResBodyMap extends ResponsesObject<SV>,\n ReqBody extends Body<SV>,\n ReqQuery extends QueryObject<SV>,\n ReqHeaders extends HeadersObject<SV>,\n ResHeaders extends HeadersObject<SV>,\n LocalsObj extends Record<string, unknown>,\n VersionedApi extends VersionSchema<SV, 'middleware'>,\n Auth extends SchemaAuthMethods<\n SV,\n P,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n VersionedApi,\n BaseRequest\n >\n >(\n contractDetailsOrMiddlewareOrTypedHandler:\n | ContractDetailsOrMiddlewareOrTypedHandler<\n SV,\n Name,\n 'middleware',\n Path,\n P,\n ResBodyMap,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n ResHeaders,\n LocalsObj,\n VersionedApi,\n BaseRequest,\n BaseResponse,\n NextFunction,\n RouterSession,\n Auth\n >\n | RouterHandler\n | undefined,\n middlewareOrMiddlewareWithTypedHandler: (\n | MiddlewareOrMiddlewareWithTypedHandler<\n SV,\n Name,\n 'middleware',\n Path,\n P,\n ResBodyMap,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n ResHeaders,\n LocalsObj,\n VersionedApi,\n BaseRequest,\n BaseResponse,\n NextFunction,\n RouterSession,\n Auth\n >\n | RouterHandler\n )[]\n ) {\n const middleware: RouterHandler[] = [];\n\n this.#processTypedHandlerOrMiddleware<\n Name,\n Path,\n P,\n ResBodyMap,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n ResHeaders,\n LocalsObj,\n VersionedApi,\n Auth\n >(contractDetailsOrMiddlewareOrTypedHandler, middleware);\n\n middleware.push(\n ...this.#extractMiddlewareFromEnrichedTypedHandlerArray<\n Name,\n Path,\n P,\n ResBodyMap,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n ResHeaders,\n LocalsObj,\n VersionedApi,\n Auth\n >(middlewareOrMiddlewareWithTypedHandler)\n );\n\n return middleware;\n }\n\n #extractNestableMiddlewareAsRouterHandlers<\n Name extends string,\n Path extends `/${string}`,\n P extends ParamsObject<SV>,\n ResBodyMap extends ResponsesObject<SV>,\n ReqBody extends Body<SV>,\n ReqQuery extends QueryObject<SV>,\n ReqHeaders extends HeadersObject<SV>,\n ResHeaders extends HeadersObject<SV>,\n LocalsObj extends Record<string, unknown>,\n VersionedApi extends VersionSchema<SV, 'middleware'>,\n Auth extends SchemaAuthMethods<\n SV,\n P,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n VersionedApi,\n BaseRequest\n >\n >(\n contractDetailsOrMiddlewareOrTypedHandler:\n | ContractDetailsOrMiddlewareOrTypedHandler<\n SV,\n Name,\n 'middleware',\n Path,\n P,\n ResBodyMap,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n ResHeaders,\n LocalsObj,\n VersionedApi,\n BaseRequest,\n BaseResponse,\n NextFunction,\n RouterSession,\n Auth\n >\n | ConstrainedForklaunchRouter<SV, RouterHandler>\n | undefined,\n middlewareOrMiddlewareWithTypedHandler: (\n | MiddlewareOrMiddlewareWithTypedHandler<\n SV,\n Name,\n 'middleware',\n Path,\n P,\n ResBodyMap,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n ResHeaders,\n LocalsObj,\n VersionedApi,\n BaseRequest,\n BaseResponse,\n NextFunction,\n RouterSession,\n Auth\n >\n | ConstrainedForklaunchRouter<SV, RouterHandler>\n )[]\n ) {\n const middleware: (RouterHandler | Internal)[] = [];\n\n this.#processTypedHandlerOrMiddleware<\n Name,\n Path,\n P,\n ResBodyMap,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n ResHeaders,\n LocalsObj,\n VersionedApi,\n Auth\n >(\n contractDetailsOrMiddlewareOrTypedHandler as ContractDetailsOrMiddlewareOrTypedHandler<\n SV,\n Name,\n 'middleware',\n Path,\n P,\n ResBodyMap,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n ResHeaders,\n LocalsObj,\n VersionedApi,\n BaseRequest,\n BaseResponse,\n NextFunction,\n RouterSession,\n Auth\n >,\n middleware as RouterHandler[]\n );\n\n if (\n isForklaunchExpressLikeRouter<\n SV,\n Path,\n RouterHandler,\n Internal,\n BaseRequest,\n BaseResponse,\n NextFunction,\n FetchMap,\n Sdk\n >(contractDetailsOrMiddlewareOrTypedHandler)\n ) {\n this.addRouterToSdk(contractDetailsOrMiddlewareOrTypedHandler);\n middleware.push(contractDetailsOrMiddlewareOrTypedHandler.internal);\n }\n\n middleware.push(\n ...this.#extractNestableMiddlewareFromEnrichedTypedHandlerArray<\n Name,\n Path,\n P,\n ResBodyMap,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n ResHeaders,\n LocalsObj,\n VersionedApi,\n Auth\n >(middlewareOrMiddlewareWithTypedHandler)\n );\n\n return middleware;\n }\n\n registerMiddlewareHandler<\n Name extends string,\n Path extends `/${string}`,\n P extends ParamsObject<SV>,\n ResBodyMap extends ResponsesObject<SV>,\n ReqBody extends Body<SV>,\n ReqQuery extends QueryObject<SV>,\n ReqHeaders extends HeadersObject<SV>,\n ResHeaders extends HeadersObject<SV>,\n LocalsObj extends Record<string, unknown>,\n VersionedApi extends VersionSchema<SV, 'middleware'>,\n Auth extends SchemaAuthMethods<\n SV,\n P,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n VersionedApi,\n BaseRequest\n >\n >(\n registrationMethod: PathOrMiddlewareBasedHandler<RouterHandler>,\n pathOrContractDetailsOrMiddlewareOrTypedHandler:\n | Path\n | ContractDetailsOrMiddlewareOrTypedHandler<\n SV,\n Name,\n 'middleware',\n Path,\n P,\n ResBodyMap,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n ResHeaders,\n LocalsObj,\n VersionedApi,\n BaseRequest,\n BaseResponse,\n NextFunction,\n RouterSession,\n Auth\n >\n | RouterHandler,\n contractDetailsOrMiddlewareOrTypedHandler?:\n | ContractDetailsOrMiddlewareOrTypedHandler<\n SV,\n Name,\n 'middleware',\n Path,\n P,\n ResBodyMap,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n ResHeaders,\n LocalsObj,\n VersionedApi,\n BaseRequest,\n BaseResponse,\n NextFunction,\n RouterSession,\n Auth\n >\n | RouterHandler,\n ...middlewareOrMiddlewareWithTypedHandler: (\n | MiddlewareOrMiddlewareWithTypedHandler<\n SV,\n Name,\n 'middleware',\n Path,\n P,\n ResBodyMap,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n ResHeaders,\n LocalsObj,\n VersionedApi,\n BaseRequest,\n BaseResponse,\n NextFunction,\n RouterSession,\n Auth\n >\n | RouterHandler\n )[]\n ): this {\n const middleware: RouterHandler[] = [];\n\n if (typeof pathOrContractDetailsOrMiddlewareOrTypedHandler === 'string') {\n middleware.push(\n ...this.#extractMiddlewareAsRouterHandlers<\n Name,\n Path,\n P,\n ResBodyMap,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n ResHeaders,\n LocalsObj,\n VersionedApi,\n Auth\n >(\n contractDetailsOrMiddlewareOrTypedHandler,\n middlewareOrMiddlewareWithTypedHandler\n )\n );\n const path = pathOrContractDetailsOrMiddlewareOrTypedHandler;\n registrationMethod.bind(this.internal)(path, ...middleware);\n } else {\n middleware.push(\n ...this.#extractMiddlewareAsRouterHandlers<\n Name,\n Path,\n P,\n ResBodyMap,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n ResHeaders,\n LocalsObj,\n VersionedApi,\n Auth\n >(\n pathOrContractDetailsOrMiddlewareOrTypedHandler,\n (\n (isExpressLikeSchemaHandler<\n SV,\n 'middleware',\n P,\n ResBodyMap,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n ResHeaders,\n LocalsObj,\n VersionedApi,\n RouterSession,\n BaseRequest,\n BaseResponse,\n NextFunction\n >(contractDetailsOrMiddlewareOrTypedHandler) ||\n isTypedHandler<\n SV,\n Name,\n 'middleware',\n Path,\n P,\n ResBodyMap,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n ResHeaders,\n LocalsObj,\n VersionedApi,\n BaseRequest,\n BaseResponse,\n NextFunction,\n Auth\n >(contractDetailsOrMiddlewareOrTypedHandler)\n ? [contractDetailsOrMiddlewareOrTypedHandler]\n : []) as (\n | MiddlewareOrMiddlewareWithTypedHandler<\n SV,\n Name,\n 'middleware',\n Path,\n P,\n ResBodyMap,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n ResHeaders,\n LocalsObj,\n VersionedApi,\n BaseRequest,\n BaseResponse,\n NextFunction,\n RouterSession,\n Auth\n >\n | RouterHandler\n )[]\n ).concat(middlewareOrMiddlewareWithTypedHandler)\n )\n );\n registrationMethod.bind(this.internal)(...middleware);\n }\n return this;\n }\n\n private addRouterToSdk(\n router: ConstrainedForklaunchRouter<SV, RouterHandler>\n ) {\n Object.entries(router._fetchMap).map(\n ([key, value]) =>\n (toRecord(this._fetchMap)[\n sanitizePathSlashes(`${this.basePath}${key}`)\n ] = value)\n );\n\n const existingSdk =\n this.sdk[router.sdkName ?? toPrettyCamelCase(router.basePath)];\n toRecord(this.sdk)[router.sdkName ?? toPrettyCamelCase(router.basePath)] = {\n ...(typeof existingSdk === 'object' ? existingSdk : {}),\n ...router.sdk\n };\n }\n\n registerNestableMiddlewareHandler<\n Name extends string,\n Path extends `/${string}`,\n P extends ParamsObject<SV>,\n ResBodyMap extends ResponsesObject<SV>,\n ReqBody extends Body<SV>,\n ReqQuery extends QueryObject<SV>,\n ReqHeaders extends HeadersObject<SV>,\n ResHeaders extends HeadersObject<SV>,\n LocalsObj extends Record<string, unknown>,\n VersionedApi extends VersionSchema<SV, 'middleware'>,\n const SessionSchema extends SessionObject<SV>,\n Auth extends SchemaAuthMethods<\n SV,\n P,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n VersionedApi,\n BaseRequest\n >\n >(\n registrationMethod: NestableRouterBasedHandler<RouterHandler, Internal>,\n pathOrContractDetailsOrMiddlewareOrTypedHandler:\n | Path\n | ContractDetailsOrMiddlewareOrTypedHandler<\n SV,\n Name,\n 'middleware',\n Path,\n P,\n ResBodyMap,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n ResHeaders,\n LocalsObj,\n VersionedApi,\n BaseRequest,\n BaseResponse,\n NextFunction,\n RouterSession,\n Auth\n >\n | ConstrainedForklaunchRouter<SV, RouterHandler>,\n contractDetailsOrMiddlewareOrTypedHandler?:\n | ContractDetailsOrMiddlewareOrTypedHandler<\n SV,\n Name,\n 'middleware',\n Path,\n P,\n ResBodyMap,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n ResHeaders,\n LocalsObj,\n VersionedApi,\n BaseRequest,\n BaseResponse,\n NextFunction,\n RouterSession,\n Auth\n >\n | ConstrainedForklaunchRouter<SV, RouterHandler>,\n ...middlewareOrMiddlewareWithTypedHandler: (\n | MiddlewareOrMiddlewareWithTypedHandler<\n SV,\n Name,\n 'middleware',\n Path,\n P,\n ResBodyMap,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n ResHeaders,\n LocalsObj,\n VersionedApi,\n BaseRequest,\n BaseResponse,\n NextFunction,\n RouterSession,\n Auth\n >\n | ConstrainedForklaunchRouter<SV, RouterHandler>\n )[]\n ): this {\n const middleware: (RouterHandler | Internal)[] = [];\n let path: `/${string}` | undefined;\n\n if (typeof pathOrContractDetailsOrMiddlewareOrTypedHandler === 'string') {\n middleware.push(\n ...this.#extractNestableMiddlewareAsRouterHandlers<\n Name,\n Path,\n P,\n ResBodyMap,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n ResHeaders,\n LocalsObj,\n VersionedApi,\n Auth\n >(\n contractDetailsOrMiddlewareOrTypedHandler,\n middlewareOrMiddlewareWithTypedHandler\n )\n );\n path = pathOrContractDetailsOrMiddlewareOrTypedHandler;\n } else {\n if (\n isConstrainedForklaunchRouter<SV, RouterHandler>(\n pathOrContractDetailsOrMiddlewareOrTypedHandler\n )\n ) {\n const router = pathOrContractDetailsOrMiddlewareOrTypedHandler;\n\n this.addRouterToSdk(router);\n path = router.basePath;\n }\n middleware.push(\n ...this.#extractNestableMiddlewareAsRouterHandlers<\n Name,\n Path,\n P,\n ResBodyMap,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n ResHeaders,\n LocalsObj,\n VersionedApi,\n Auth\n >(\n pathOrContractDetailsOrMiddlewareOrTypedHandler,\n (isExpressLikeSchemaHandler<\n SV,\n 'middleware',\n P,\n ResBodyMap,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n ResHeaders,\n LocalsObj,\n VersionedApi,\n SessionObject<SV> extends SessionSchema\n ? RouterSession\n : SessionSchema,\n BaseRequest,\n BaseResponse,\n NextFunction\n >(contractDetailsOrMiddlewareOrTypedHandler) ||\n isTypedHandler<\n SV,\n Name,\n 'middleware',\n Path,\n P,\n ResBodyMap,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n ResHeaders,\n LocalsObj,\n VersionedApi,\n BaseRequest,\n BaseResponse,\n NextFunction,\n Auth\n >(contractDetailsOrMiddlewareOrTypedHandler) ||\n isConstrainedForklaunchRouter<SV, RouterHandler>(\n contractDetailsOrMiddlewareOrTypedHandler\n )\n ? [contractDetailsOrMiddlewareOrTypedHandler]\n : []\n ).concat(middlewareOrMiddlewareWithTypedHandler)\n )\n );\n }\n\n if (!path) {\n path = middleware.filter((m) =>\n isForklaunchExpressLikeRouter<\n SV,\n Path,\n RouterHandler,\n Internal,\n BaseRequest,\n BaseResponse,\n NextFunction,\n FetchMap,\n Sdk\n >(m)\n )[0]?.basePath;\n }\n\n if (path) {\n registrationMethod.bind(this.internal)(path, ...middleware);\n } else {\n registrationMethod.bind(this.internal)(...middleware);\n }\n return this;\n }\n\n private addRouterOptions(\n router: ConstrainedForklaunchRouter<SV, RouterHandler>\n ) {\n router.routerOptions = {\n ...(this.routerOptions ?? {}),\n ...(router.routerOptions ?? {})\n } as typeof this.routerOptions;\n\n router.routers.forEach((subRouter) => {\n this.addRouterOptions(\n subRouter as ConstrainedForklaunchRouter<SV, RouterHandler>\n );\n });\n }\n\n /**\n * Validates that all protected routes have the required surfacing functions\n * available (from the route, router, or application level).\n * Call this at listen() time when the full option chain is assembled.\n */\n validateSurfacingFunctions(\n router: ForklaunchRouter<SV> = this,\n parentAuth?: Record<string, unknown>\n ) {\n const routerAuth =\n router.routerOptions?.auth &&\n typeof router.routerOptions.auth === 'object'\n ? router.routerOptions.auth\n : undefined;\n const globalAuth =\n routerAuth && parentAuth\n ? { ...parentAuth, ...routerAuth }\n : (routerAuth ?? parentAuth);\n\n for (const route of router.routes) {\n const auth = route.contractDetails.auth;\n const access = route.contractDetails.access;\n if (!auth || access !== 'protected') continue;\n\n const routeAuth = auth as Record<string, unknown>;\n const routeName = route.contractDetails.name;\n\n if (hasPermissionChecks(auth)) {\n if (\n !routeAuth['surfacePermissions'] &&\n !globalAuth?.surfacePermissions\n ) {\n throw new Error(\n `Route '${routeName}': declares allowedPermissions or forbiddenPermissions ` +\n `but no surfacePermissions function was provided on the route, router, or application`\n );\n }\n }\n\n if (hasRoleChecks(auth)) {\n if (!routeAuth['surfaceRoles'] && !globalAuth?.surfaceRoles) {\n throw new Error(\n `Route '${routeName}': declares allowedRoles or forbiddenRoles ` +\n `but no surfaceRoles function was provided on the route, router, or application`\n );\n }\n }\n\n if (hasScopeChecks(auth)) {\n if (!routeAuth['surfaceScopes'] && !globalAuth?.surfaceScopes) {\n throw new Error(\n `Route '${routeName}': declares requiredScope ` +\n `but no surfaceScopes function was provided on the route, router, or application`\n );\n }\n }\n }\n\n for (const subRouter of router.routers) {\n this.validateSurfacingFunctions(subRouter, globalAuth);\n }\n }\n\n use: TypedNestableMiddlewareDefinition<\n this,\n RouterHandler,\n Internal,\n SV,\n RouterSession,\n BaseRequest,\n BaseResponse,\n NextFunction\n > = <\n Name extends string,\n Path extends `/${string}`,\n P extends ParamsObject<SV>,\n ResBodyMap extends ResponsesObject<SV>,\n ReqBody extends Body<SV>,\n ReqQuery extends QueryObject<SV>,\n ReqHeaders extends HeadersObject<SV>,\n ResHeaders extends HeadersObject<SV>,\n LocalsObj extends Record<string, unknown>,\n Router extends ConstrainedForklaunchRouter<SV, RouterHandler>,\n VersionedApi extends VersionSchema<SV, 'middleware'>,\n SessionSchema extends SessionObject<SV>,\n ResolvedSchema extends (SessionObject<SV> extends SessionSchema\n ? RouterSession\n : SessionSchema),\n Auth extends SchemaAuthMethods<\n SV,\n P,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n VersionedApi,\n BaseRequest\n >\n >(\n pathOrContractDetailsOrMiddlewareOrTypedHandler:\n | Path\n | ContractDetailsOrMiddlewareOrTypedHandler<\n SV,\n Name,\n 'middleware',\n Path,\n P,\n ResBodyMap,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n ResHeaders,\n LocalsObj,\n VersionedApi,\n BaseRequest,\n BaseResponse,\n NextFunction,\n RouterSession,\n Auth\n >\n | Router,\n contractDetailsOrMiddlewareOrTypedHandler?:\n | ContractDetailsOrMiddlewareOrTypedHandler<\n SV,\n Name,\n 'middleware',\n Path,\n P,\n ResBodyMap,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n ResHeaders,\n LocalsObj,\n VersionedApi,\n BaseRequest,\n BaseResponse,\n NextFunction,\n RouterSession,\n Auth\n >\n | Router,\n ...middlewareOrMiddlewareWithTypedHandler: (\n | MiddlewareOrMiddlewareWithTypedHandler<\n SV,\n Name,\n 'middleware',\n Path,\n P,\n ResBodyMap,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n ResHeaders,\n LocalsObj,\n VersionedApi,\n BaseRequest,\n BaseResponse,\n NextFunction,\n RouterSession,\n Auth\n >\n | Router\n )[]\n ) => {\n [\n pathOrContractDetailsOrMiddlewareOrTypedHandler,\n contractDetailsOrMiddlewareOrTypedHandler,\n ...middlewareOrMiddlewareWithTypedHandler\n ].forEach((arg) => {\n if (isForklaunchRouter<SV>(arg)) {\n this.routers.push(arg);\n this.addRouterOptions(\n arg as ConstrainedForklaunchRouter<SV, RouterHandler>\n );\n }\n });\n\n return this.registerNestableMiddlewareHandler<\n Name,\n Path,\n P,\n ResBodyMap,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n ResHeaders,\n LocalsObj,\n VersionedApi,\n ResolvedSchema,\n Auth\n >(\n this.internal.use,\n pathOrContractDetailsOrMiddlewareOrTypedHandler,\n contractDetailsOrMiddlewareOrTypedHandler,\n ...middlewareOrMiddlewareWithTypedHandler\n ) as this & {\n _fetchMap: FetchMap & {\n [\n Key in keyof Router['_fetchMap'] as Key extends string\n ? SanitizePathSlashes<`${BasePath}${Key}`>\n : never\n ]: Router['_fetchMap'][Key];\n };\n sdk: Sdk & {\n [\n Key in PrettyCamelCase<\n Router extends { sdkName?: string; basePath: string }\n ? string extends Router['sdkName']\n ? Router['basePath']\n : Router['sdkName']\n : never\n >\n ]: Router['sdk'];\n };\n };\n };\n\n all: TypedMiddlewareDefinition<\n this,\n SV,\n RouterSession,\n BaseRequest,\n BaseResponse,\n NextFunction,\n RouterHandler\n > = <\n Name extends string,\n Path extends `/${string}`,\n P extends ParamsObject<SV>,\n ResBodyMap extends ResponsesObject<SV>,\n ReqBody extends Body<SV>,\n ReqQuery extends QueryObject<SV>,\n ReqHeaders extends HeadersObject<SV>,\n ResHeaders extends HeadersObject<SV>,\n LocalsObj extends Record<string, unknown>,\n VersionedApi extends VersionSchema<SV, 'middleware'>,\n Auth extends SchemaAuthMethods<\n SV,\n P,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n VersionedApi,\n BaseRequest\n >\n >(\n pathOrContractDetailsOrMiddlewareOrTypedHandler:\n | Path\n | ContractDetailsOrMiddlewareOrTypedHandler<\n SV,\n Name,\n 'middleware',\n Path,\n P,\n ResBodyMap,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n ResHeaders,\n LocalsObj,\n VersionedApi,\n BaseRequest,\n BaseResponse,\n NextFunction,\n RouterSession,\n Auth\n >\n | RouterHandler,\n contractDetailsOrMiddlewareOrTypedHandler?:\n | ContractDetailsOrMiddlewareOrTypedHandler<\n SV,\n Name,\n 'middleware',\n Path,\n P,\n ResBodyMap,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n ResHeaders,\n LocalsObj,\n VersionedApi,\n BaseRequest,\n BaseResponse,\n NextFunction,\n RouterSession,\n Auth\n >\n | RouterHandler,\n ...middlewareOrMiddlewareWithTypedHandler: (\n | MiddlewareOrMiddlewareWithTypedHandler<\n SV,\n Name,\n 'middleware',\n Path,\n P,\n ResBodyMap,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n ResHeaders,\n LocalsObj,\n VersionedApi,\n BaseRequest,\n BaseResponse,\n NextFunction,\n RouterSession,\n Auth\n >\n | RouterHandler\n )[]\n ) => {\n return this.registerMiddlewareHandler<\n Name,\n Path,\n P,\n ResBodyMap,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n ResHeaders,\n LocalsObj,\n VersionedApi,\n Auth\n >(\n this.internal.all,\n pathOrContractDetailsOrMiddlewareOrTypedHandler,\n contractDetailsOrMiddlewareOrTypedHandler,\n ...middlewareOrMiddlewareWithTypedHandler\n );\n };\n\n connect: TypedMiddlewareDefinition<\n this,\n SV,\n RouterSession,\n BaseRequest,\n BaseResponse,\n NextFunction,\n RouterHandler\n > = <\n Name extends string,\n Path extends `/${string}`,\n P extends ParamsObject<SV>,\n ResBodyMap extends ResponsesObject<SV>,\n ReqBody extends Body<SV>,\n ReqQuery extends QueryObject<SV>,\n ReqHeaders extends HeadersObject<SV>,\n ResHeaders extends HeadersObject<SV>,\n LocalsObj extends Record<string, unknown>,\n VersionedApi extends VersionSchema<SV, 'middleware'>,\n Auth extends SchemaAuthMethods<\n SV,\n P,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n VersionedApi,\n BaseRequest\n >\n >(\n pathOrContractDetailsOrMiddlewareOrTypedHandler:\n | Path\n | ContractDetailsOrMiddlewareOrTypedHandler<\n SV,\n Name,\n 'middleware',\n Path,\n P,\n ResBodyMap,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n ResHeaders,\n LocalsObj,\n VersionedApi,\n BaseRequest,\n BaseResponse,\n NextFunction,\n RouterSession,\n Auth\n >\n | RouterHandler,\n contractDetailsOrMiddlewareOrTypedHandler?:\n | ContractDetailsOrMiddlewareOrTypedHandler<\n SV,\n Name,\n 'middleware',\n Path,\n P,\n ResBodyMap,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n ResHeaders,\n LocalsObj,\n VersionedApi,\n BaseRequest,\n BaseResponse,\n NextFunction,\n RouterSession,\n Auth\n >\n | RouterHandler,\n ...middlewareOrMiddlewareWithTypedHandler: (\n | MiddlewareOrMiddlewareWithTypedHandler<\n SV,\n Name,\n 'middleware',\n Path,\n P,\n ResBodyMap,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n ResHeaders,\n LocalsObj,\n VersionedApi,\n BaseRequest,\n BaseResponse,\n NextFunction,\n RouterSession,\n Auth\n >\n | RouterHandler\n )[]\n ) => {\n return this.registerMiddlewareHandler<\n Name,\n Path,\n P,\n ResBodyMap,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n ResHeaders,\n LocalsObj,\n VersionedApi,\n Auth\n >(\n this.internal.connect,\n pathOrContractDetailsOrMiddlewareOrTypedHandler,\n contractDetailsOrMiddlewareOrTypedHandler,\n ...middlewareOrMiddlewareWithTypedHandler\n );\n };\n\n /**\n * Registers a GET route with the specified contract details and handler handlers.\n *\n * @template P - The type of request parameters.\n * @template ResBodyMap - The type of response body.\n * @template ReqBody - The type of request body.\n * @template ReqQuery - The type of request query.\n * @template LocalsObj - The type of local variables.\n * @param {string} path - The path for the route.\n * @param {PathParamHttpContractDetails<SV, P, ResBodyMap, ReqQuery>} contractDetails - The contract details.\n * @param {...SchemaHandler<SV, P, ResBodyMap, ReqBody, ReqQuery, LocalsObj>[]} handlers - The handler handlers.\n * @returns {ExpressRouter} - The Express router.\n */\n get: LiveTypeRouteDefinition<\n SV,\n BasePath,\n 'get',\n RouterHandler,\n Internal,\n RouterSession,\n BaseRequest,\n BaseResponse,\n NextFunction,\n this\n > = <\n Name extends string,\n Path extends `/${string}`,\n P extends ParamsObject<SV>,\n ResBodyMap extends ResponsesObject<SV>,\n ReqBody extends Body<SV>,\n ReqQuery extends QueryObject<SV>,\n ReqHeaders extends HeadersObject<SV>,\n ResHeaders extends HeadersObject<SV>,\n LocalsObj extends Record<string, unknown>,\n VersionedApi extends VersionSchema<SV, 'get'>,\n Auth extends SchemaAuthMethods<\n SV,\n P,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n VersionedApi,\n BaseRequest\n >\n >(\n path: Path,\n contractDetailsOrMiddlewareOrTypedHandler: ContractDetailsOrMiddlewareOrTypedHandler<\n SV,\n Name,\n 'get',\n Path,\n P,\n ResBodyMap,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n ResHeaders,\n LocalsObj,\n VersionedApi,\n BaseRequest,\n BaseResponse,\n NextFunction,\n RouterSession,\n Auth\n >,\n ...middlewareOrMiddlewareWithTypedHandler: MiddlewareOrMiddlewareWithTypedHandler<\n SV,\n Name,\n 'get',\n Path,\n P,\n ResBodyMap,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n ResHeaders,\n LocalsObj,\n VersionedApi,\n BaseRequest,\n BaseResponse,\n NextFunction,\n RouterSession,\n Auth\n >[]\n ) => {\n return this.registerRoute<\n Name,\n 'get',\n Path,\n P,\n ResBodyMap,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n ResHeaders,\n LocalsObj,\n VersionedApi,\n Auth\n >(\n 'get',\n path,\n this.internal.get,\n contractDetailsOrMiddlewareOrTypedHandler,\n ...middlewareOrMiddlewareWithTypedHandler\n );\n };\n\n /**\n * Registers a POST route with the specified contract details and handler handlers.\n *\n * @template P - The type of request parameters.\n * @template ResBodyMap - The type of response body.\n * @template ReqBody - The type of request body.\n * @template ReqQuery - The type of request query.\n * @template LocalsObj - The type of local variables.\n * @param {string} path - The path for the route.\n * @param {HttpContractDetails<SV, P, ResBodyMap, ReqBody, ReqQuery>} contractDetails - The contract details.\n * @param {...SchemaHandler<SV, P, ResBodyMap, ReqBody, ReqQuery, LocalsObj>[]} handlers - The handler handlers.\n * @returns {ExpressRouter} - The Expxwress router.\n */\n post: LiveTypeRouteDefinition<\n SV,\n BasePath,\n 'post',\n RouterHandler,\n Internal,\n RouterSession,\n BaseRequest,\n BaseResponse,\n NextFunction,\n this\n > = <\n Name extends string,\n Path extends `/${string}`,\n P extends ParamsObject<SV>,\n ResBodyMap extends ResponsesObject<SV>,\n ReqBody extends Body<SV>,\n ReqQuery extends QueryObject<SV>,\n ReqHeaders extends HeadersObject<SV>,\n ResHeaders extends HeadersObject<SV>,\n LocalsObj extends Record<string, unknown>,\n VersionedApi extends VersionSchema<SV, 'post'>,\n Auth extends SchemaAuthMethods<\n SV,\n P,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n VersionedApi,\n BaseRequest\n >\n >(\n path: Path,\n contractDetailsOrMiddlewareOrTypedHandler: ContractDetailsOrMiddlewareOrTypedHandler<\n SV,\n Name,\n 'post',\n Path,\n P,\n ResBodyMap,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n ResHeaders,\n LocalsObj,\n VersionedApi,\n BaseRequest,\n BaseResponse,\n NextFunction,\n RouterSession,\n Auth\n >,\n ...middlewareOrMiddlewareWithTypedHandler: MiddlewareOrMiddlewareWithTypedHandler<\n SV,\n Name,\n 'post',\n Path,\n P,\n ResBodyMap,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n ResHeaders,\n LocalsObj,\n VersionedApi,\n BaseRequest,\n BaseResponse,\n NextFunction,\n RouterSession,\n Auth\n >[]\n ) => {\n return this.registerRoute<\n Name,\n 'post',\n Path,\n P,\n ResBodyMap,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n ResHeaders,\n LocalsObj,\n VersionedApi,\n Auth\n >(\n 'post',\n path,\n this.internal.post,\n contractDetailsOrMiddlewareOrTypedHandler,\n ...middlewareOrMiddlewareWithTypedHandler\n );\n };\n\n /**\n * Registers a PUT route with the specified contract details and handler handlers.\n *\n * @template P - The type of request parameters.\n * @template ResBodyMap - The type of response body.\n * @template ReqBody - The type of request body.\n * @template ReqQuery - The type of request query.\n * @template LocalsObj - The type of local variables.\n * @param {string} path - The path for the route.\n * @param {HttpContractDetails<SV, P, ResBodyMap, ReqBody, ReqQuery>} contractDetails - The contract details.\n * @param {...SchemaHandler<SV, P, ResBodyMap, ReqBody, ReqQuery, LocalsObj>[]} handlers - The handler handlers.\n * @returns {ExpressRouter} - The Express router.\n */\n put: LiveTypeRouteDefinition<\n SV,\n BasePath,\n 'put',\n RouterHandler,\n Internal,\n RouterSession,\n BaseRequest,\n BaseResponse,\n NextFunction,\n this\n > = <\n Name extends string,\n Path extends `/${string}`,\n P extends ParamsObject<SV>,\n ResBodyMap extends ResponsesObject<SV>,\n ReqBody extends Body<SV>,\n ReqQuery extends QueryObject<SV>,\n ReqHeaders extends HeadersObject<SV>,\n ResHeaders extends HeadersObject<SV>,\n LocalsObj extends Record<string, unknown>,\n VersionedApi extends VersionSchema<SV, 'put'>,\n Auth extends SchemaAuthMethods<\n SV,\n P,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n VersionedApi,\n BaseRequest\n >\n >(\n path: Path,\n contractDetailsOrMiddlewareOrTypedHandler: ContractDetailsOrMiddlewareOrTypedHandler<\n SV,\n Name,\n 'put',\n Path,\n P,\n ResBodyMap,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n ResHeaders,\n LocalsObj,\n VersionedApi,\n BaseRequest,\n BaseResponse,\n NextFunction,\n RouterSession,\n Auth\n >,\n ...middlewareOrMiddlewareWithTypedHandler: MiddlewareOrMiddlewareWithTypedHandler<\n SV,\n Name,\n 'put',\n Path,\n P,\n ResBodyMap,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n ResHeaders,\n LocalsObj,\n VersionedApi,\n BaseRequest,\n BaseResponse,\n NextFunction,\n RouterSession,\n Auth\n >[]\n ) => {\n return this.registerRoute<\n Name,\n 'put',\n Path,\n P,\n ResBodyMap,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n ResHeaders,\n LocalsObj,\n VersionedApi,\n Auth\n >(\n 'put',\n path,\n this.internal.put,\n contractDetailsOrMiddlewareOrTypedHandler,\n ...middlewareOrMiddlewareWithTypedHandler\n );\n };\n\n /**\n * Registers a PATCH route with the specified contract details and handler handlers.\n *\n * @template P - The type of request parameters.\n * @template ResBodyMap - The type of response body.\n * @template ReqBody - The type of request body.\n * @template ReqQuery - The type of request query.\n * @template LocalsObj - The type of local variables.\n * @param {string} path - The path for the route.\n * @param {HttpContractDetails<SV, P, ResBodyMap, ReqBody, ReqQuery>} contractDetails - The contract details.\n * @param {...SchemaHandler<SV, P, ResBodyMap, ReqBody, ReqQuery, LocalsObj>[]} handlers - The handler handlers.\n * @returns {ExpressRouter} - The Express router.\n */\n patch: LiveTypeRouteDefinition<\n SV,\n BasePath,\n 'patch',\n RouterHandler,\n Internal,\n RouterSession,\n BaseRequest,\n BaseResponse,\n NextFunction,\n this\n > = <\n Name extends string,\n Path extends `/${string}`,\n P extends ParamsObject<SV>,\n ResBodyMap extends ResponsesObject<SV>,\n ReqBody extends Body<SV>,\n ReqQuery extends QueryObject<SV>,\n ReqHeaders extends HeadersObject<SV>,\n ResHeaders extends HeadersObject<SV>,\n LocalsObj extends Record<string, unknown>,\n VersionedApi extends VersionSchema<SV, 'patch'>,\n Auth extends SchemaAuthMethods<\n SV,\n P,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n VersionedApi,\n BaseRequest\n >\n >(\n path: Path,\n contractDetailsOrMiddlewareOrTypedHandler: ContractDetailsOrMiddlewareOrTypedHandler<\n SV,\n Name,\n 'patch',\n Path,\n P,\n ResBodyMap,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n ResHeaders,\n LocalsObj,\n VersionedApi,\n BaseRequest,\n BaseResponse,\n NextFunction,\n RouterSession,\n Auth\n >,\n ...middlewareOrMiddlewareWithTypedHandler: MiddlewareOrMiddlewareWithTypedHandler<\n SV,\n Name,\n 'patch',\n Path,\n P,\n ResBodyMap,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n ResHeaders,\n LocalsObj,\n VersionedApi,\n BaseRequest,\n BaseResponse,\n NextFunction,\n RouterSession,\n Auth\n >[]\n ) => {\n return this.registerRoute<\n Name,\n 'patch',\n Path,\n P,\n ResBodyMap,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n ResHeaders,\n LocalsObj,\n VersionedApi,\n Auth\n >(\n 'patch',\n path,\n this.internal.patch,\n contractDetailsOrMiddlewareOrTypedHandler,\n ...middlewareOrMiddlewareWithTypedHandler\n );\n };\n\n /**\n * Registers a DELETE route with the specified contract details and handler handlers.\n *\n * @template P - The type of request parameters.\n * @template ResBodyMap - The type of response body.\n * @template ReqBody - The type of request body.\n * @template ReqQuery - The type of request query.\n * @template LocalsObj - The type of local variables.\n * @param {string} path - The path for the route.\n * @param {PathParamHttpContractDetails<SV, P, ResBodyMap, ReqQuery>} contractDetails - The contract details.\n * @param {...SchemaHandler<SV, P, ResBodyMap, ReqBody, ReqQuery, LocalsObj>[]} handlers - The handler handlers.\n * @returns {ExpressRouter} - The Express router.\n */\n delete: LiveTypeRouteDefinition<\n SV,\n BasePath,\n 'delete',\n RouterHandler,\n Internal,\n RouterSession,\n BaseRequest,\n BaseResponse,\n NextFunction,\n this\n > = <\n Name extends string,\n Path extends `/${string}`,\n P extends ParamsObject<SV>,\n ResBodyMap extends ResponsesObject<SV>,\n ReqBody extends Body<SV>,\n ReqQuery extends QueryObject<SV>,\n ReqHeaders extends HeadersObject<SV>,\n ResHeaders extends HeadersObject<SV>,\n LocalsObj extends Record<string, unknown>,\n VersionedApi extends VersionSchema<SV, 'delete'>,\n Auth extends SchemaAuthMethods<\n SV,\n P,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n VersionedApi,\n BaseRequest\n >\n >(\n path: Path,\n contractDetailsOrMiddlewareOrTypedHandler: ContractDetailsOrMiddlewareOrTypedHandler<\n SV,\n Name,\n 'delete',\n Path,\n P,\n ResBodyMap,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n ResHeaders,\n LocalsObj,\n VersionedApi,\n BaseRequest,\n BaseResponse,\n NextFunction,\n RouterSession,\n Auth\n >,\n ...middlewareOrMiddlewareWithTypedHandler: MiddlewareOrMiddlewareWithTypedHandler<\n SV,\n Name,\n 'delete',\n Path,\n P,\n ResBodyMap,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n ResHeaders,\n LocalsObj,\n VersionedApi,\n BaseRequest,\n BaseResponse,\n NextFunction,\n RouterSession,\n Auth\n >[]\n ) => {\n return this.registerRoute<\n Name,\n 'delete',\n Path,\n P,\n ResBodyMap,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n ResHeaders,\n LocalsObj,\n VersionedApi,\n Auth\n >(\n 'delete',\n path,\n this.internal.delete,\n contractDetailsOrMiddlewareOrTypedHandler,\n ...middlewareOrMiddlewareWithTypedHandler\n );\n };\n\n /**\n * Registers a OPTIONS route with the specified contract details and handler handlers.\n *\n * @template P - The type of request parameters.\n * @template ResBodyMap - The type of response body.\n * @template ReqBody - The type of request body.\n * @template ReqQuery - The type of request query.\n * @template LocalsObj - The type of local variables.\n * @param {string} path - The path for the route.\n * @param {PathParamHttpContractDetails<SV, P, ResBodyMap, ReqQuery>} contractDetails - The contract details.\n * @param {...SchemaHandler<SV, P, ResBodyMap, ReqBody, ReqQuery, LocalsObj>[]} handlers - The handler handlers.\n * @returns {ExpressRouter} - The Express router.\n */\n options: LiveTypeRouteDefinition<\n SV,\n BasePath,\n 'options',\n RouterHandler,\n Internal,\n RouterSession,\n BaseRequest,\n BaseResponse,\n NextFunction,\n this\n > = <\n Name extends string,\n Path extends `/${string}`,\n P extends ParamsObject<SV>,\n ResBodyMap extends ResponsesObject<SV>,\n ReqBody extends Body<SV>,\n ReqQuery extends QueryObject<SV>,\n ReqHeaders extends HeadersObject<SV>,\n ResHeaders extends HeadersObject<SV>,\n LocalsObj extends Record<string, unknown>,\n VersionedApi extends VersionSchema<SV, 'options'>,\n Auth extends SchemaAuthMethods<\n SV,\n P,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n VersionedApi,\n BaseRequest\n >\n >(\n path: Path,\n contractDetailsOrMiddlewareOrTypedHandler: ContractDetailsOrMiddlewareOrTypedHandler<\n SV,\n Name,\n 'options',\n Path,\n P,\n ResBodyMap,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n ResHeaders,\n LocalsObj,\n VersionedApi,\n BaseRequest,\n BaseResponse,\n NextFunction,\n RouterSession,\n Auth\n >,\n ...middlewareOrMiddlewareWithTypedHandler: MiddlewareOrMiddlewareWithTypedHandler<\n SV,\n Name,\n 'options',\n Path,\n P,\n ResBodyMap,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n ResHeaders,\n LocalsObj,\n VersionedApi,\n BaseRequest,\n BaseResponse,\n NextFunction,\n RouterSession,\n Auth\n >[]\n ) => {\n return this.registerRoute<\n Name,\n 'options',\n Path,\n P,\n ResBodyMap,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n ResHeaders,\n LocalsObj,\n VersionedApi,\n Auth\n >(\n 'options',\n path,\n this.internal.options,\n contractDetailsOrMiddlewareOrTypedHandler,\n ...middlewareOrMiddlewareWithTypedHandler\n );\n };\n\n /**\n * Registers a HEAD route with the specified contract details and handler handlers.\n *\n * @template P - The type of request parameters.\n * @template ResBodyMap - The type of response body.\n * @template ReqBody - The type of request body.\n * @template ReqQuery - The type of request query.\n * @template LocalsObj - The type of local variables.\n * @param {string} path - The path for the route.\n * @param {PathParamHttpContractDetails<SV, P, ResBodyMap, ReqQuery>} contractDetails - The contract details.\n * @param {...SchemaHandler<SV, P, ResBodyMap, ReqBody, ReqQuery, LocalsObj>[]} handlers - The handler handlers.\n * @returns {ExpressRouter} - The Express router.\n */\n head: LiveTypeRouteDefinition<\n SV,\n BasePath,\n 'head',\n RouterHandler,\n Internal,\n RouterSession,\n BaseRequest,\n BaseResponse,\n NextFunction,\n this\n > = <\n Name extends string,\n Path extends `/${string}`,\n P extends ParamsObject<SV>,\n ResBodyMap extends ResponsesObject<SV>,\n ReqBody extends Body<SV>,\n ReqQuery extends QueryObject<SV>,\n ReqHeaders extends HeadersObject<SV>,\n ResHeaders extends HeadersObject<SV>,\n LocalsObj extends Record<string, unknown>,\n VersionedApi extends VersionSchema<SV, 'head'>,\n Auth extends SchemaAuthMethods<\n SV,\n P,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n VersionedApi,\n BaseRequest\n >\n >(\n path: Path,\n contractDetailsOrMiddlewareOrTypedHandler: ContractDetailsOrMiddlewareOrTypedHandler<\n SV,\n Name,\n 'head',\n Path,\n P,\n ResBodyMap,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n ResHeaders,\n LocalsObj,\n VersionedApi,\n BaseRequest,\n BaseResponse,\n NextFunction,\n RouterSession,\n Auth\n >,\n ...middlewareOrMiddlewareWithTypedHandler: MiddlewareOrMiddlewareWithTypedHandler<\n SV,\n Name,\n 'head',\n Path,\n P,\n ResBodyMap,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n ResHeaders,\n LocalsObj,\n VersionedApi,\n BaseRequest,\n BaseResponse,\n NextFunction,\n RouterSession,\n Auth\n >[]\n ) => {\n return this.registerRoute<\n Name,\n 'head',\n Path,\n P,\n ResBodyMap,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n ResHeaders,\n LocalsObj,\n VersionedApi,\n Auth\n >(\n 'head',\n path,\n this.internal.head,\n contractDetailsOrMiddlewareOrTypedHandler,\n ...middlewareOrMiddlewareWithTypedHandler\n );\n };\n\n /**\n * Registers a TRACE route with the specified contract details and handler handlers.\n *\n * @template P - The type of request parameters.\n * @template ResBodyMap - The type of response body.\n * @template ReqBody - The type of request body.\n * @template ReqQuery - The type of request query.\n * @template LocalsObj - The type of local variables.\n * @param {string} path - The path for the route.\n * @param {PathParamHttpContractDetails<SV, P, ResBodyMap, ReqQuery>} contractDetails - The contract details.\n * @param {...SchemaHandler<SV, P, ResBodyMap, ReqBody, ReqQuery, LocalsObj>[]} handlers - The handler handlers.\n * @returns {ExpressRouter} - The Express router.\n */\n trace: LiveTypeRouteDefinition<\n SV,\n BasePath,\n 'trace',\n RouterHandler,\n Internal,\n RouterSession,\n BaseRequest,\n BaseResponse,\n NextFunction,\n this\n > = <\n Name extends string,\n Path extends `/${string}`,\n P extends ParamsObject<SV>,\n ResBodyMap extends ResponsesObject<SV>,\n ReqBody extends Body<SV>,\n ReqQuery extends QueryObject<SV>,\n ReqHeaders extends HeadersObject<SV>,\n ResHeaders extends HeadersObject<SV>,\n LocalsObj extends Record<string, unknown>,\n VersionedApi extends VersionSchema<SV, 'trace'>,\n Auth extends SchemaAuthMethods<\n SV,\n P,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n VersionedApi,\n BaseRequest\n >\n >(\n path: Path,\n contractDetailsOrMiddlewareOrTypedHandler: ContractDetailsOrMiddlewareOrTypedHandler<\n SV,\n Name,\n 'trace',\n Path,\n P,\n ResBodyMap,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n ResHeaders,\n LocalsObj,\n VersionedApi,\n BaseRequest,\n BaseResponse,\n NextFunction,\n RouterSession,\n Auth\n >,\n ...middlewareOrMiddlewareWithTypedHandler: MiddlewareOrMiddlewareWithTypedHandler<\n SV,\n Name,\n 'trace',\n Path,\n P,\n ResBodyMap,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n ResHeaders,\n LocalsObj,\n VersionedApi,\n BaseRequest,\n BaseResponse,\n NextFunction,\n RouterSession,\n Auth\n >[]\n ) => {\n return this.registerRoute<\n Name,\n 'trace',\n Path,\n P,\n ResBodyMap,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n ResHeaders,\n LocalsObj,\n VersionedApi,\n Auth\n >(\n 'trace',\n path,\n this.internal.trace,\n contractDetailsOrMiddlewareOrTypedHandler,\n ...middlewareOrMiddlewareWithTypedHandler\n );\n };\n\n insertIntoRouterSdkPaths({\n sdkPath,\n path,\n method,\n name\n }: {\n sdkPath: string;\n name: string;\n path: string;\n method: string;\n }) {\n const routePath = [method, path].join('.');\n for (const route of this.routes) {\n if (\n route.path === path &&\n route.method === method &&\n route.contractDetails.name === name\n ) {\n this.sdkPaths[routePath] = sdkPath;\n }\n }\n\n for (const router of this.routers) {\n router.insertIntoRouterSdkPaths?.({\n sdkPath,\n path,\n method,\n name\n });\n }\n }\n\n private unpackSdks(\n sdks: SdkHandlerObject<SV>,\n path: string[],\n routerUniquenessCache: Set<number>\n ) {\n Object.entries(sdks).forEach(([key, maybeHandler]) => {\n if (isSdkHandler(maybeHandler)) {\n const cacheKey = hashString(safeStringify(maybeHandler));\n if (routerUniquenessCache.has(cacheKey)) {\n throw new Error(`SDK handler ${key} is already registered`);\n }\n routerUniquenessCache.add(cacheKey);\n if (!maybeHandler._method || !maybeHandler._path) {\n throw new Error(`SDK handler ${key} is missing method or path`);\n }\n this.insertIntoRouterSdkPaths({\n sdkPath: [...path, key].join('.'),\n path: maybeHandler._path,\n method: maybeHandler._method,\n name: maybeHandler.contractDetails.name\n });\n routerUniquenessCache.add(cacheKey);\n } else {\n this.unpackSdks(maybeHandler, [...path, key], routerUniquenessCache);\n }\n });\n }\n\n registerSdks(sdks: SdkHandlerObject<SV>) {\n this.unpackSdks(sdks, [], new Set());\n }\n\n protected cloneInternals(clone: this): void {\n clone.routers = [...this.routers];\n clone.routes = [...this.routes];\n clone._fetchMap = { ...this._fetchMap };\n clone.sdk = { ...this.sdk };\n clone.sdkPaths = { ...this.sdkPaths };\n }\n\n clone(): this {\n const clone = new ForklaunchExpressLikeRouter<\n SV,\n BasePath,\n RouterHandler,\n Internal,\n BaseRequest,\n BaseResponse,\n NextFunction,\n RouterSession,\n FetchMap,\n Sdk\n >(\n this.basePath,\n this.schemaValidator,\n this.internal,\n this.postEnrichMiddleware,\n this.openTelemetryCollector,\n this.routerOptions\n ) as this;\n\n this.cloneInternals(clone);\n\n return clone;\n }\n}\n","export function hasPermissionChecks(maybePermissionedAuth: unknown) {\n if (\n typeof maybePermissionedAuth !== 'object' ||\n maybePermissionedAuth === null\n ) {\n return false;\n }\n\n const hasAllowedPermissions =\n 'allowedPermissions' in maybePermissionedAuth &&\n maybePermissionedAuth.allowedPermissions instanceof Set &&\n maybePermissionedAuth.allowedPermissions.size > 0;\n\n const hasForbiddenPermissions =\n 'forbiddenPermissions' in maybePermissionedAuth &&\n maybePermissionedAuth.forbiddenPermissions instanceof Set &&\n maybePermissionedAuth.forbiddenPermissions.size > 0;\n\n return hasAllowedPermissions || hasForbiddenPermissions;\n}\n","export function hasRoleChecks(maybeRoledAuth: unknown): boolean {\n if (typeof maybeRoledAuth !== 'object' || maybeRoledAuth === null) {\n return false;\n }\n\n const hasAllowedRoles =\n 'allowedRoles' in maybeRoledAuth &&\n maybeRoledAuth.allowedRoles instanceof Set &&\n maybeRoledAuth.allowedRoles.size > 0;\n\n const hasForbiddenRoles =\n 'forbiddenRoles' in maybeRoledAuth &&\n maybeRoledAuth.forbiddenRoles instanceof Set &&\n maybeRoledAuth.forbiddenRoles.size > 0;\n\n return hasAllowedRoles || hasForbiddenRoles;\n}\n","export function hasScopeChecks(maybePermissionedAuth: unknown) {\n return (\n typeof maybePermissionedAuth === 'object' &&\n maybePermissionedAuth !== null &&\n 'requiredScope' in maybePermissionedAuth &&\n maybePermissionedAuth.requiredScope != null\n );\n}\n","import { AnySchemaValidator } from '@forklaunch/validator';\nimport { ForklaunchRouter } from '../types/router.types';\n\n/**\n * Type guard that checks if an object is a Forklaunch router.\n * A Forklaunch router is an object that has a base path and an array of routes.\n *\n * @template SV - A type that extends AnySchemaValidator\n * @param {unknown} maybeForklaunchRouter - The object to check\n * @returns {boolean} A type predicate indicating whether the object is a ForklaunchRouter\n *\n * @example\n * ```ts\n * if (isForklaunchRouter(router)) {\n * // router is now typed as ForklaunchRouter\n * router.basePath; // '/api'\n * router.routes; // Route[]\n * }\n * ```\n */\nexport function isForklaunchRouter<SV extends AnySchemaValidator>(\n maybeForklaunchRouter: unknown\n): maybeForklaunchRouter is ForklaunchRouter<SV> {\n return (\n maybeForklaunchRouter != null &&\n typeof maybeForklaunchRouter === 'object' &&\n 'basePath' in maybeForklaunchRouter &&\n 'routes' in maybeForklaunchRouter &&\n Array.isArray(maybeForklaunchRouter.routes)\n );\n}\n","import { AnySchemaValidator } from '@forklaunch/validator';\nimport { ConstrainedForklaunchRouter } from '../types/router.types';\nimport { isForklaunchRouter } from './isForklaunchRouter';\n\n/**\n * Type guard that checks if an object is a constrained Forklaunch router.\n * A constrained router is one that has both the basic router properties and a request handler.\n *\n * @template SV - A type that extends AnySchemaValidator\n * @template RouterHandler - The type of the router handler\n * @param maybeForklaunchExpressLikeRouter - The object to check\n * @returns A type predicate indicating whether the object is a ConstrainedForklaunchRouter\n *\n * @example\n * ```ts\n * if (isConstrainedForklaunchRouter(router)) {\n * // router is now typed as ConstrainedForklaunchRouter\n * router.requestHandler(...);\n * }\n * ```\n */\nexport function isConstrainedForklaunchRouter<\n SV extends AnySchemaValidator,\n RouterHandler\n>(\n maybeForklaunchExpressLikeRouter: unknown\n): maybeForklaunchExpressLikeRouter is ConstrainedForklaunchRouter<\n SV,\n RouterHandler\n> {\n return (\n isForklaunchRouter<SV>(maybeForklaunchExpressLikeRouter) &&\n 'requestHandler' in maybeForklaunchExpressLikeRouter\n );\n}\n","import { extractArgumentNames } from '@forklaunch/common';\nimport { AnySchemaValidator } from '@forklaunch/validator';\nimport { ExpressLikeSchemaHandler } from '../types/apiDefinition.types';\nimport {\n Body,\n HeadersObject,\n Method,\n ParamsObject,\n QueryObject,\n ResponsesObject,\n SessionObject,\n VersionSchema\n} from '../types/contractDetails.types';\n\n/**\n * Type guard that checks if an object is an Express-like schema handler.\n * A schema handler is a function that takes up to 3 arguments (request, response, next)\n * and is used for middleware or route handlers in an Express-like application.\n *\n * @template SV - A type that extends AnySchemaValidator\n * @template P - The type of route parameters\n * @template ResBodyMap - The type of response body mapping\n * @template ReqBody - The type of request body\n * @template ReqQuery - The type of request query parameters\n * @template ReqHeaders - The type of request headers\n * @template ResHeaders - The type of response headers\n * @template LocalsObj - The type of locals object\n * @template BaseRequest - The base request type\n * @template BaseResponse - The base response type\n * @template NextFunction - The type of next function\n * @param {unknown} middleware - The object to check\n * @returns {boolean} A type predicate indicating whether the object is an ExpressLikeSchemaHandler\n *\n * @example\n * ```ts\n * if (isExpressLikeSchemaHandler(middleware)) {\n * // middleware is now typed as ExpressLikeSchemaHandler\n * middleware(req, res, next);\n * }\n * ```\n */\nexport function isExpressLikeSchemaHandler<\n SV extends AnySchemaValidator,\n ContractMethod extends Method,\n P extends ParamsObject<SV>,\n ResBodyMap extends ResponsesObject<SV>,\n ReqBody extends Body<SV>,\n ReqQuery extends QueryObject<SV>,\n ReqHeaders extends HeadersObject<SV>,\n ResHeaders extends HeadersObject<SV>,\n LocalsObj extends Record<string, unknown>,\n VersionedApi extends VersionSchema<SV, ContractMethod>,\n Session extends SessionObject<SV>,\n BaseRequest,\n BaseResponse,\n NextFunction\n>(\n middleware: unknown\n): middleware is ExpressLikeSchemaHandler<\n SV,\n P,\n ResBodyMap,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n ResHeaders,\n LocalsObj,\n VersionedApi,\n Session,\n BaseRequest,\n BaseResponse,\n NextFunction\n> {\n const extractedArgumentNames =\n typeof middleware === 'function' &&\n new Set(\n extractArgumentNames(middleware).map((argumentName) =>\n argumentName.toLowerCase()\n )\n );\n return extractedArgumentNames && extractedArgumentNames.size <= 4;\n}\n","import { AnySchemaValidator } from '@forklaunch/validator';\nimport { ExpressLikeRouter } from '../interfaces/expressLikeRouter.interface';\nimport { ForklaunchExpressLikeRouter } from '../router/expressLikeRouter';\nimport { isConstrainedForklaunchRouter } from './isConstrainedForklaunchRouter';\n\n/**\n * Type guard that checks if an object is a Forklaunch Express-like router.\n * A Forklaunch Express-like router is a constrained router that has both a base path and an internal router.\n *\n * @template SV - A type that extends AnySchemaValidator\n * @template Path - A type that extends `/${string}` representing the base path\n * @template RouterHandler - The type of the router handler\n * @template Internal - The type of the internal router that extends ExpressLikeRouter\n * @template BaseRequest - The base request type\n * @template BaseResponse - The base response type\n * @template NextFunction - The type of next function\n * @param {unknown} maybeForklaunchExpressLikeRouter - The object to check\n * @returns {boolean} A type predicate indicating whether the object is a ForklaunchExpressLikeRouter\n *\n * @example\n * ```ts\n * if (isForklaunchExpressLikeRouter(router)) {\n * // router is now typed as ForklaunchExpressLikeRouter\n * router.basePath; // '/api'\n * router.internal; // ExpressLikeRouter\n * }\n * ```\n */\nexport function isForklaunchExpressLikeRouter<\n SV extends AnySchemaValidator,\n Path extends `/${string}`,\n RouterHandler,\n Internal extends ExpressLikeRouter<RouterHandler, Internal>,\n BaseRequest,\n BaseResponse,\n NextFunction,\n FetchMap extends Record<string, unknown>,\n Sdk extends Record<string, unknown>\n>(\n maybeForklaunchExpressLikeRouter: unknown\n): maybeForklaunchExpressLikeRouter is ForklaunchExpressLikeRouter<\n SV,\n Path,\n RouterHandler,\n Internal,\n BaseRequest,\n BaseResponse,\n NextFunction,\n FetchMap,\n Sdk\n> {\n return (\n isConstrainedForklaunchRouter<SV, RouterHandler>(\n maybeForklaunchExpressLikeRouter\n ) &&\n 'basePath' in maybeForklaunchExpressLikeRouter &&\n 'internal' in maybeForklaunchExpressLikeRouter\n );\n}\n","import { SdkHandler } from '../types/sdk.types';\n\n/**\n * Type guard to determine if a given value is an SdkHandler.\n *\n * @param handler - The value to check.\n * @returns True if the value is an SdkHandler, false otherwise.\n */\nexport function isSdkHandler(handler: unknown): handler is SdkHandler {\n return (\n typeof handler === 'object' &&\n handler !== null &&\n '_path' in handler &&\n '_method' in handler &&\n 'contractDetails' in handler\n );\n}\n","import { AnySchemaValidator } from '@forklaunch/validator';\n\nimport {\n Body,\n HeadersObject,\n Method,\n ParamsObject,\n QueryObject,\n ResponsesObject,\n SchemaAuthMethods,\n VersionSchema\n} from '../types/contractDetails.types';\nimport { TypedHandler } from '../types/typedHandler.types';\n\nexport function isTypedHandler<\n SV extends AnySchemaValidator,\n Name extends string,\n ContractMethod extends Method,\n Path extends `/${string}`,\n P extends ParamsObject<SV>,\n ResBodyMap extends ResponsesObject<SV>,\n ReqBody extends Body<SV>,\n ReqQuery extends QueryObject<SV>,\n ReqHeaders extends HeadersObject<SV>,\n ResHeaders extends HeadersObject<SV>,\n LocalsObj extends Record<string, unknown>,\n VersionedApi extends VersionSchema<SV, ContractMethod>,\n BaseRequest,\n BaseResponse,\n NextFunction,\n const Auth extends SchemaAuthMethods<\n SV,\n P,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n VersionedApi,\n BaseRequest\n >\n>(\n maybeTypedHandler: unknown\n): maybeTypedHandler is TypedHandler<\n SV,\n Name,\n ContractMethod,\n Path,\n P,\n ResBodyMap,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n ResHeaders,\n LocalsObj,\n VersionedApi,\n BaseRequest,\n BaseResponse,\n NextFunction,\n Auth\n> {\n return (\n maybeTypedHandler != null &&\n typeof maybeTypedHandler === 'object' &&\n '_typedHandler' in maybeTypedHandler &&\n maybeTypedHandler._typedHandler === true\n );\n}\n","import { getEnvVar } from '@forklaunch/common';\nimport { AnySchemaValidator } from '@forklaunch/validator';\nimport { context, trace } from '@opentelemetry/api';\nimport { ATTR_SERVICE_NAME as OTEL_ATTR_SERVICE_NAME } from '@opentelemetry/semantic-conventions';\nimport { v4 } from 'uuid';\nimport {\n ATTR_CORRELATION_ID,\n ATTR_SERVICE_NAME\n} from '../../telemetry/constants';\nimport { httpRequestsInFlightCounter } from '../../telemetry/openTelemetryCollector';\nimport {\n ExpressLikeSchemaHandler,\n ForklaunchNextFunction,\n ResolvedForklaunchResponse,\n VersionedResponses\n} from '../../types/apiDefinition.types';\nimport {\n Body,\n HeadersObject,\n ParamsObject,\n QueryObject,\n ResponsesObject,\n SessionObject,\n VersionSchema\n} from '../../types/contractDetails.types';\n\n/**\n * Middleware to create and add a request context.\n *\n * @template SV - A type that extends AnySchemaValidator.\n * @template Request - A type that extends ForklaunchRequest.\n * @template Response - A type that extends ForklaunchResponse.\n * @template NextFunction - A type that extends ForklaunchNextFunction.\n * @param {SV} schemaValidator - The schema validator.\n * @returns {Function} - Middleware function to create request context.\n */\nexport function createContext<\n SV extends AnySchemaValidator,\n P extends ParamsObject<SV>,\n ResBodyMap extends ResponsesObject<SV>,\n ReqBody extends Body<SV>,\n ReqQuery extends QueryObject<SV>,\n ReqHeaders extends HeadersObject<SV>,\n ResHeaders extends HeadersObject<SV>,\n LocalsObj extends Record<string, unknown>,\n VersionedApi extends VersionSchema<SV, 'middleware'>,\n SessionSchema extends SessionObject<SV>\n>(\n schemaValidator: SV\n): ExpressLikeSchemaHandler<\n SV,\n P,\n ResBodyMap,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n ResHeaders,\n LocalsObj,\n VersionedApi,\n SessionSchema,\n unknown,\n unknown,\n ForklaunchNextFunction\n> {\n return function setContext(req, res, next?) {\n req.schemaValidator = schemaValidator;\n\n let correlationId = v4();\n if (req.headers['x-correlation-id']) {\n correlationId = req.headers['x-correlation-id'] as string;\n }\n\n (\n res as ResolvedForklaunchResponse<\n ResHeaders,\n Record<string, string>,\n LocalsObj,\n VersionedResponses,\n unknown\n >\n ).setHeader('x-correlation-id', correlationId);\n\n req.context = {\n correlationId: correlationId,\n requestStartTime: Date.now()\n };\n\n const serviceName = getEnvVar('OTEL_SERVICE_NAME') || 'unknown';\n const inFlightAttrs = {\n [OTEL_ATTR_SERVICE_NAME]: serviceName\n };\n let inFlightActive = true;\n\n const decrementInFlight = () => {\n if (!inFlightActive) {\n return;\n }\n\n httpRequestsInFlightCounter.add(-1, inFlightAttrs);\n inFlightActive = false;\n };\n\n httpRequestsInFlightCounter.add(1, inFlightAttrs);\n res.on('finish', decrementInFlight);\n res.on('close', decrementInFlight);\n res.on('error', decrementInFlight);\n\n const span = trace.getSpan(context.active());\n\n if (span != null) {\n req.context.span = span;\n req.context.span?.setAttribute(ATTR_CORRELATION_ID, correlationId);\n req.context.span?.setAttribute(ATTR_SERVICE_NAME, serviceName);\n }\n\n next?.();\n };\n}\n","import {\n ATTR_HTTP_REQUEST_METHOD,\n ATTR_HTTP_RESPONSE_STATUS_CODE,\n ATTR_HTTP_ROUTE,\n ATTR_SERVICE_NAME\n} from '@opentelemetry/semantic-conventions';\n\nexport const ATTR_API_NAME = 'api.name';\nexport const ATTR_CORRELATION_ID = 'correlation.id';\nexport const ATTR_APPLICATION_ID = 'application_id';\n\nexport {\n ATTR_HTTP_REQUEST_METHOD,\n ATTR_HTTP_RESPONSE_STATUS_CODE,\n ATTR_HTTP_ROUTE,\n ATTR_SERVICE_NAME\n};\n","import { getEnvVar } from '@forklaunch/common';\nimport { HyperExpressInstrumentation } from '@forklaunch/opentelemetry-instrumentation-hyper-express';\nimport {\n Counter,\n Gauge,\n Histogram,\n metrics,\n ObservableCounter,\n ObservableGauge,\n ObservableUpDownCounter,\n UpDownCounter\n} from '@opentelemetry/api';\nimport { OTLPLogExporter } from '@opentelemetry/exporter-logs-otlp-http';\nimport { OTLPMetricExporter } from '@opentelemetry/exporter-metrics-otlp-http';\nimport { OTLPTraceExporter } from '@opentelemetry/exporter-trace-otlp-http';\nimport { ExpressInstrumentation } from '@opentelemetry/instrumentation-express';\nimport { HttpInstrumentation } from '@opentelemetry/instrumentation-http';\nimport { resourceFromAttributes } from '@opentelemetry/resources';\nimport { BatchLogRecordProcessor } from '@opentelemetry/sdk-logs';\nimport { PeriodicExportingMetricReader } from '@opentelemetry/sdk-metrics';\nimport { NodeSDK } from '@opentelemetry/sdk-node';\nimport {\n ATTR_HTTP_REQUEST_METHOD,\n ATTR_HTTP_RESPONSE_STATUS_CODE,\n ATTR_HTTP_ROUTE,\n ATTR_SERVICE_NAME\n} from '@opentelemetry/semantic-conventions';\nimport dotenv from 'dotenv';\nimport { LevelWithSilent, LevelWithSilentOrString } from 'pino';\nimport { isForklaunchRequest } from '../guards/isForklaunchRequest';\nimport {\n LogFn,\n LoggerMeta,\n MetricsDefinition,\n MetricType\n} from '../types/openTelemetryCollector.types';\nimport {\n ATTR_API_NAME,\n ATTR_APPLICATION_ID,\n ATTR_CORRELATION_ID\n} from './constants';\nimport { logger, PinoLogger } from './pinoLogger';\n\nexport class OpenTelemetryCollector<\n AppliedMetricsDefinition extends MetricsDefinition\n> {\n _logger: PinoLogger;\n _serviceName: string;\n _metrics: Record<\n keyof AppliedMetricsDefinition,\n | Counter\n | Gauge\n | Histogram\n | UpDownCounter\n | ObservableCounter\n | ObservableGauge\n | ObservableUpDownCounter\n >;\n\n // scoped creation and create this in middleware when api execute. Also add correlation id\n constructor(\n serviceName: string,\n level?: LevelWithSilentOrString,\n metricDefinitions?: AppliedMetricsDefinition\n ) {\n this._serviceName = serviceName;\n this._logger = logger(level || 'info');\n\n this._metrics = {} as Record<\n keyof AppliedMetricsDefinition,\n MetricType<AppliedMetricsDefinition[keyof AppliedMetricsDefinition]>\n >;\n\n for (const [metricId, metricType] of Object.entries(\n metricDefinitions ?? {}\n )) {\n switch (metricType) {\n case 'counter':\n this._metrics[metricId as keyof AppliedMetricsDefinition] = metrics\n .getMeter(this._serviceName)\n .createCounter(metricId);\n break;\n case 'gauge':\n this._metrics[metricId as keyof AppliedMetricsDefinition] = metrics\n .getMeter(this._serviceName)\n .createGauge(metricId);\n break;\n case 'histogram':\n this._metrics[metricId as keyof AppliedMetricsDefinition] = metrics\n .getMeter(this._serviceName)\n .createHistogram(metricId);\n break;\n case 'upDownCounter':\n this._metrics[metricId as keyof AppliedMetricsDefinition] = metrics\n .getMeter(this._serviceName)\n .createUpDownCounter(metricId);\n break;\n case 'observableCounter':\n this._metrics[metricId as keyof AppliedMetricsDefinition] = metrics\n .getMeter(this._serviceName)\n .createObservableCounter(metricId);\n break;\n case 'observableGauge':\n this._metrics[metricId as keyof AppliedMetricsDefinition] = metrics\n .getMeter(this._serviceName)\n .createObservableGauge(metricId);\n break;\n case 'observableUpDownCounter':\n this._metrics[metricId as keyof AppliedMetricsDefinition] = metrics\n .getMeter(this._serviceName)\n .createObservableUpDownCounter(metricId);\n break;\n }\n }\n\n this.log(\n 'info',\n 'OpenTelemetry Collector (Traces + Logs + Metrics) started'\n );\n }\n\n log(level: LevelWithSilent, ...args: (string | unknown | LoggerMeta)[]) {\n this._logger.log(level, ...args);\n }\n\n info: LogFn = (\n msg: string | unknown | LoggerMeta,\n ...args: (string | unknown | LoggerMeta)[]\n ) => {\n this._logger.log('info', msg, ...args);\n };\n\n error: LogFn = (\n msg: string | unknown | LoggerMeta,\n ...args: (string | unknown | LoggerMeta)[]\n ) => {\n this._logger.log('error', msg, ...args);\n };\n\n warn: LogFn = (\n msg: string | unknown | LoggerMeta,\n ...args: (string | unknown | LoggerMeta)[]\n ) => {\n this._logger.log('warn', msg, ...args);\n };\n\n debug: LogFn = (\n msg: string | unknown | LoggerMeta,\n ...args: (string | unknown | LoggerMeta)[]\n ) => {\n this._logger.log('debug', msg, ...args);\n };\n\n trace: LogFn = (\n msg: string | unknown | LoggerMeta,\n ...args: (string | unknown | LoggerMeta)[]\n ) => {\n this._logger.log('trace', msg, ...args);\n };\n\n getMetric<T extends keyof AppliedMetricsDefinition>(\n metricId: T\n ): MetricType<AppliedMetricsDefinition[T]> {\n return this._metrics[metricId] as MetricType<AppliedMetricsDefinition[T]>;\n }\n}\n\ndotenv.config({ path: getEnvVar('DOTENV_FILE_PATH') });\n\n// Parse OTEL_EXPORTER_OTLP_HEADERS into headers object\n// Format: key1=value1,key2=value2\nfunction parseOtelHeaders(): Record<string, string> | undefined {\n const headersEnv = getEnvVar('OTEL_EXPORTER_OTLP_HEADERS');\n if (!headersEnv) return undefined;\n\n const headers: Record<string, string> = {};\n for (const pair of headersEnv.split(',')) {\n const [key, ...valueParts] = pair.split('=');\n if (key && valueParts.length > 0) {\n headers[key.trim()] = valueParts.join('=').trim();\n }\n }\n return Object.keys(headers).length > 0 ? headers : undefined;\n}\n\nconst otelHeaders = parseOtelHeaders();\n\nnew NodeSDK({\n resource: resourceFromAttributes({\n [ATTR_SERVICE_NAME]: getEnvVar('OTEL_SERVICE_NAME')\n }),\n traceExporter: new OTLPTraceExporter({\n url: `${\n getEnvVar('OTEL_EXPORTER_OTLP_ENDPOINT') ?? 'http://localhost:4318'\n }/v1/traces`,\n headers: otelHeaders\n }),\n metricReader: new PeriodicExportingMetricReader({\n exporter: new OTLPMetricExporter({\n url: `${\n getEnvVar('OTEL_EXPORTER_OTLP_ENDPOINT') ?? 'http://localhost:4318'\n }/v1/metrics`,\n headers: otelHeaders\n }),\n exportIntervalMillis: 5000\n }),\n logRecordProcessors: [\n new BatchLogRecordProcessor({\n exporter: new OTLPLogExporter({\n url: `${\n getEnvVar('OTEL_EXPORTER_OTLP_ENDPOINT') ?? 'http://localhost:4318'\n }/v1/logs`,\n headers: otelHeaders\n })\n })\n ],\n instrumentations: [\n new HttpInstrumentation({\n applyCustomAttributesOnSpan: (span, request) => {\n span.setAttribute(\n ATTR_SERVICE_NAME,\n getEnvVar('OTEL_SERVICE_NAME') ?? 'unknown'\n );\n if (isForklaunchRequest(request)) {\n span.setAttribute(ATTR_API_NAME, request.contractDetails?.name);\n span.setAttribute(ATTR_CORRELATION_ID, request.context.correlationId);\n }\n }\n }),\n new ExpressInstrumentation(),\n new HyperExpressInstrumentation()\n ]\n}).start();\n\n// begin static metrics -- these have to be in here in order to instantiate these after the SDK is instantiated\nexport const httpRequestsTotalCounter = metrics\n .getMeter(getEnvVar('OTEL_SERVICE_NAME') || 'unknown')\n .createCounter<{\n [ATTR_SERVICE_NAME]: string;\n [ATTR_APPLICATION_ID]?: string;\n [ATTR_API_NAME]: string;\n [ATTR_HTTP_REQUEST_METHOD]: string;\n [ATTR_HTTP_ROUTE]: string;\n [ATTR_HTTP_RESPONSE_STATUS_CODE]: number;\n }>('http_requests_total', {\n description: 'Number of HTTP requests'\n });\n\nexport const httpServerDurationHistogram = metrics\n .getMeter(getEnvVar('OTEL_SERVICE_NAME') || 'unknown')\n .createHistogram<{\n [ATTR_SERVICE_NAME]: string;\n [ATTR_APPLICATION_ID]?: string;\n [ATTR_API_NAME]: string;\n [ATTR_HTTP_REQUEST_METHOD]: string;\n [ATTR_HTTP_ROUTE]: string;\n [ATTR_HTTP_RESPONSE_STATUS_CODE]: number;\n }>('http_server_duration', {\n description: 'Duration of HTTP server requests',\n unit: 's'\n });\n\nexport const httpRequestDurationMsHistogram = metrics\n .getMeter(getEnvVar('OTEL_SERVICE_NAME') || 'unknown')\n .createHistogram<{\n [ATTR_SERVICE_NAME]: string;\n [ATTR_APPLICATION_ID]?: string;\n [ATTR_API_NAME]: string;\n [ATTR_HTTP_REQUEST_METHOD]: string;\n [ATTR_HTTP_ROUTE]: string;\n [ATTR_HTTP_RESPONSE_STATUS_CODE]: number;\n }>('http_request_duration_ms', {\n description: 'Duration of HTTP requests in milliseconds'\n });\n\nexport const httpErrorsTotalCounter = metrics\n .getMeter(getEnvVar('OTEL_SERVICE_NAME') || 'unknown')\n .createCounter<{\n [ATTR_SERVICE_NAME]: string;\n [ATTR_APPLICATION_ID]?: string;\n [ATTR_API_NAME]: string;\n [ATTR_HTTP_REQUEST_METHOD]: string;\n [ATTR_HTTP_ROUTE]: string;\n [ATTR_HTTP_RESPONSE_STATUS_CODE]: number;\n }>('http_errors_total', {\n description: 'Total number of HTTP errors (4xx/5xx)'\n });\n\nexport const httpRequestsInFlightCounter = metrics\n .getMeter(getEnvVar('OTEL_SERVICE_NAME') || 'unknown')\n .createUpDownCounter<{\n [ATTR_SERVICE_NAME]: string;\n }>('http_requests_in_flight', {\n description: 'Number of HTTP requests currently in flight'\n });\n","import { AnySchemaValidator } from '@forklaunch/validator';\nimport { ParsedQs } from 'qs';\nimport {\n ForklaunchRequest,\n VersionedRequests\n} from '../types/apiDefinition.types';\nimport { ParamsDictionary } from '../types/contractDetails.types';\n\n/**\n * Type guard that checks if an object is a Forklaunch request.\n * A Forklaunch request is an object that contains contract details and follows the Forklaunch request structure.\n *\n * @template SV - A type that extends AnySchemaValidator\n * @template P - The type of route parameters that extends ParamsDictionary\n * @template ReqBody - The type of request body that extends Record<string, unknown>\n * @template ReqQuery - The type of request query parameters that extends ParsedQs\n * @template ReqHeaders - The type of request headers that extends Record<string, unknown>\n * @param {unknown} request - The object to check\n * @returns {boolean} A type predicate indicating whether the object is a ForklaunchRequest\n *\n * @example\n * ```ts\n * if (isForklaunchRequest(request)) {\n * // request is now typed as ForklaunchRequest\n * const { contractDetails } = request;\n * }\n * ```\n */\nexport function isForklaunchRequest<\n SV extends AnySchemaValidator,\n P extends ParamsDictionary,\n ReqBody extends Record<string, unknown>,\n ReqQuery extends ParsedQs,\n ReqHeaders extends Record<string, string>,\n VersionedReqs extends VersionedRequests,\n SessionSchema extends Record<string, unknown>\n>(\n request: unknown\n): request is ForklaunchRequest<\n SV,\n P,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n Extract<keyof VersionedReqs, string>,\n SessionSchema\n> {\n return (\n request != null &&\n typeof request === 'object' &&\n 'contractDetails' in request\n );\n}\n","import { isNever } from '@forklaunch/common';\nimport { trace } from '@opentelemetry/api';\nimport { AnyValueMap, logs } from '@opentelemetry/api-logs';\nimport pino, { LevelWithSilent, LevelWithSilentOrString, Logger } from 'pino';\nimport { isLoggerMeta } from '../guards/isLoggerMeta';\nimport { LogFn, LoggerMeta } from '../types/openTelemetryCollector.types';\n\nexport type { LevelWithSilent, LevelWithSilentOrString, Logger };\n\nexport function meta(meta: Record<string, unknown>) {\n return meta as LoggerMeta;\n}\n\nfunction mapSeverity(level: LevelWithSilent) {\n switch (level) {\n case 'silent':\n return 0;\n case 'trace':\n return 1;\n case 'debug':\n return 5;\n case 'info':\n return 9;\n case 'warn':\n return 13;\n case 'error':\n return 17;\n case 'fatal':\n return 21;\n default:\n isNever(level);\n return 0;\n }\n}\n\ntype LoggableArg = string | number | boolean | object | null | undefined;\n\n/**\n * Normalize a list of arguments into a single metadata object and message string.\n * @param args - List of log arguments like console.log('msg', { a }, { b }, 123)\n * @returns [metadataObject, messageString]\n */\nfunction normalizeLogArgs(\n args: LoggableArg[]\n): [Record<string, unknown>, string] {\n let message = '';\n const metaObjects: Record<string, unknown>[] = [];\n\n for (const arg of args) {\n if (typeof arg === 'string' && message === '') {\n message = arg;\n } else if (arg instanceof Error) {\n metaObjects.push({\n err: {\n message: arg.message,\n name: arg.name,\n stack: arg.stack,\n ...(Object.keys(arg).length > 0 ? arg : {})\n }\n });\n } else if (arg && typeof arg === 'object' && !Array.isArray(arg)) {\n metaObjects.push(arg as Record<string, unknown>);\n } else {\n message += ` ${String(arg)}`;\n }\n }\n\n const metadata = Object.assign({}, ...metaObjects);\n return [metadata, message.trim()];\n}\n\n/**\n * Safely formats arguments for pretty printing with error handling\n * @param level - Log level\n * @param args - Arguments to format\n * @param timestamp - Optional timestamp\n * @returns Formatted string or fallback message\n */\nfunction safePrettyFormat(\n level: LevelWithSilent,\n args: LoggableArg[],\n timestamp?: string\n): string {\n try {\n const [metadata, message] = normalizeLogArgs(args);\n\n // Return formatted message with level and timestamp\n const formattedTimestamp = timestamp || new Date().toISOString();\n return `[${formattedTimestamp}] ${level.toUpperCase()}: ${message}${\n Object.keys(metadata).length > 0\n ? `\\n${JSON.stringify(metadata, null, 2)}`\n : ''\n }`;\n } catch (error) {\n // Ultimate fallback for any serialization errors\n const fallbackMessage = args\n .map((arg) => {\n try {\n if (typeof arg === 'string') return arg;\n if (arg === null) return 'null';\n if (arg === undefined) return 'undefined';\n return JSON.stringify(arg);\n } catch {\n return '[Circular/Non-serializable Object]';\n }\n })\n .join(' ');\n\n return `[${new Date().toISOString()}] ${level.toUpperCase()}: ${fallbackMessage} [Pretty Print Error: ${error instanceof Error ? error.message : 'Unknown error'}]`;\n }\n}\n\nexport class PinoLogger {\n _pinoLogger: Logger;\n _meta: AnyValueMap;\n\n constructor(level: LevelWithSilentOrString, meta: AnyValueMap = {}) {\n this._pinoLogger = pino({\n level: level || 'info',\n formatters: {\n level(label) {\n return { level: label };\n }\n },\n timestamp: pino.stdTimeFunctions.isoTime,\n transport: {\n target: 'pino-pretty',\n options: {\n colorize: true,\n errorLikeObjectKeys: ['err', 'error'],\n ignore: 'pid,hostname',\n translateTime: 'SYS:standard'\n }\n }\n });\n this._meta = meta;\n }\n\n log(level: LevelWithSilent, ...args: (string | unknown | LoggerMeta)[]) {\n let meta: AnyValueMap = {};\n\n const filteredArgs = args.filter((arg) => {\n if (isLoggerMeta(arg)) {\n Object.assign(meta, arg);\n return false;\n }\n return true;\n }) as LoggableArg[];\n\n const [errorMetadata] = normalizeLogArgs(filteredArgs);\n Object.assign(meta, errorMetadata);\n\n const activeSpan = trace.getActiveSpan();\n if (activeSpan) {\n const activeSpanContext = activeSpan.spanContext();\n meta.trace_id = activeSpanContext.traceId;\n meta.span_id = activeSpanContext.spanId;\n meta.trace_flags = activeSpanContext.traceFlags;\n meta = {\n // @ts-expect-error accessing private property\n ...activeSpan.attributes,\n ...meta\n };\n }\n\n meta = {\n 'api.name': 'none',\n 'correlation.id': 'none',\n ...meta\n };\n\n this._pinoLogger[level](...normalizeLogArgs(filteredArgs));\n\n const formattedBody = safePrettyFormat(level, filteredArgs);\n\n try {\n logs.getLogger(process.env.OTEL_SERVICE_NAME ?? 'unknown').emit({\n severityText: level,\n severityNumber: mapSeverity(level),\n body: formattedBody,\n attributes: { ...this._meta, ...meta }\n });\n } catch (error) {\n console.error('Failed to emit OpenTelemetry log:', error);\n console.log(\n `[${new Date().toISOString()}] ${level.toUpperCase()}:`,\n ...filteredArgs\n );\n }\n }\n\n error: LogFn = (\n msg: string | unknown | LoggerMeta,\n ...args: (string | unknown | LoggerMeta)[]\n ) => this.log('error', msg, ...args);\n\n info: LogFn = (\n msg: string | unknown | LoggerMeta,\n ...args: (string | unknown | LoggerMeta)[]\n ) => this.log('info', msg, ...args);\n\n debug: LogFn = (\n msg: string | unknown | LoggerMeta,\n ...args: (string | unknown | LoggerMeta)[]\n ) => this.log('debug', msg, ...args);\n warn: LogFn = (\n msg: string | unknown | LoggerMeta,\n ...args: (string | unknown | LoggerMeta)[]\n ) => this.log('warn', msg, ...args);\n\n trace: LogFn = (\n msg: string | unknown | LoggerMeta,\n ...args: (string | unknown | LoggerMeta)[]\n ) => this.log('trace', msg, ...args);\n\n child(meta: AnyValueMap = {}) {\n return new PinoLogger(this._pinoLogger.level, { ...this._meta, ...meta });\n }\n\n getBaseLogger() {\n return this._pinoLogger;\n }\n}\n\nexport function logger(level: LevelWithSilentOrString, meta: AnyValueMap = {}) {\n return new PinoLogger(level, meta);\n}\n","import { LoggerMeta } from '../types/openTelemetryCollector.types';\n\nexport function isLoggerMeta(arg: unknown): arg is LoggerMeta {\n return typeof arg === 'object' && arg !== null && '_meta' in arg;\n}\n","import { AnySchemaValidator, SchemaValidator } from '@forklaunch/validator';\nimport {\n Body,\n ResponsesObject,\n TypedBody\n} from '../types/contractDetails.types';\n\n/**\n * Discriminates the body type from the given contract details and returns information\n * necessary for parsing and validation.\n *\n * @template SV - Schema validator type.\n * @template Path - Route path type.\n * @template P - Params schema type.\n * @template ResBodyMap - Response body map type.\n * @template ReqBody - Request body type.\n * @template ReqQuery - Request query object type.\n * @template ReqHeaders - Request headers object type.\n * @template ResHeaders - Response headers object type.\n * @param contractDetails - The HTTP contract details.\n * @returns An object containing the content type, parser type, and schema.\n * @throws If no body-related information is found in the contract details.\n */\nexport function discriminateBody<SV extends AnySchemaValidator>(\n schemaValidator: SV,\n body: Body<SV> | undefined\n):\n | {\n contentType: string;\n parserType: 'json' | 'text' | 'multipart' | 'urlEncoded' | 'file';\n schema: SV['_ValidSchemaObject'];\n }\n | undefined {\n if (body == null) {\n return undefined;\n }\n\n const maybeTypedBody = body as TypedBody<SV>;\n\n if ('text' in maybeTypedBody && maybeTypedBody.text != null) {\n return {\n contentType: maybeTypedBody.contentType ?? 'text/plain',\n parserType: 'text',\n schema: maybeTypedBody.text\n };\n } else if ('json' in maybeTypedBody && maybeTypedBody.json != null) {\n return {\n contentType: maybeTypedBody.contentType ?? 'application/json',\n parserType: 'json',\n schema: maybeTypedBody.json\n };\n } else if ('file' in maybeTypedBody && maybeTypedBody.file != null) {\n return {\n contentType: maybeTypedBody.contentType ?? 'application/octet-stream',\n parserType: 'file',\n schema: maybeTypedBody.file\n };\n } else if (\n 'multipartForm' in maybeTypedBody &&\n maybeTypedBody.multipartForm != null\n ) {\n return {\n contentType: maybeTypedBody.contentType ?? 'multipart/form-data',\n parserType: 'multipart',\n schema: maybeTypedBody.multipartForm\n };\n } else if (\n 'urlEncodedForm' in maybeTypedBody &&\n maybeTypedBody.urlEncodedForm != null\n ) {\n return {\n contentType:\n maybeTypedBody.contentType ?? 'application/x-www-form-urlencoded',\n parserType: 'urlEncoded',\n schema: maybeTypedBody.urlEncodedForm\n };\n } else if ('schema' in maybeTypedBody && maybeTypedBody.schema != null) {\n return {\n contentType: maybeTypedBody.contentType ?? 'application/json',\n parserType: 'text',\n schema: maybeTypedBody.schema\n };\n } else if (\n (schemaValidator as SchemaValidator).isInstanceOf(\n maybeTypedBody,\n schemaValidator.string\n )\n ) {\n return {\n contentType: 'text/plain',\n parserType: 'text',\n schema: maybeTypedBody\n };\n } else if (\n (schemaValidator as SchemaValidator).openapi(maybeTypedBody).format ===\n 'binary'\n ) {\n return {\n contentType: 'application/octet-stream',\n parserType: 'file',\n schema: maybeTypedBody\n };\n } else {\n return {\n contentType: 'application/json',\n parserType: 'json',\n schema: maybeTypedBody\n };\n }\n}\n\n/**\n * Discriminates all response body types from the given contract details and returns\n * information necessary for parsing and validation for each status code.\n *\n * @template SV - Schema validator type.\n * @template Path - Route path type.\n * @template P - Params schema type.\n * @template ResBodyMap - Response body map type.\n * @template ReqQuery - Request query object type.\n * @template ReqHeaders - Request headers object type.\n * @template ResHeaders - Response headers object type.\n * @param contractDetails - The contract details containing response schemas.\n * @returns A record mapping status codes to content type, parser type, and schema info.\n */\nexport function discriminateResponseBodies<SV extends AnySchemaValidator>(\n schemaValidator: SV,\n responses: ResponsesObject<SV>\n) {\n const discriminatedResponses: Record<\n number,\n {\n contentType: string;\n parserType: 'json' | 'text' | 'serverSentEvent' | 'file' | 'multipart';\n schema: SV['_ValidSchemaObject'];\n }\n > = {};\n for (const [statusCode, response] of Object.entries(responses)) {\n if (response != null && typeof response === 'object') {\n if ('json' in response && response.json != null) {\n discriminatedResponses[Number(statusCode)] = {\n contentType:\n ('contentType' in response &&\n typeof response.contentType === 'string'\n ? response.contentType\n : 'application/json') ?? 'application/json',\n parserType: 'json',\n schema: response.json\n };\n } else if ('schema' in response && response.schema != null) {\n discriminatedResponses[Number(statusCode)] = {\n contentType:\n ('contentType' in response &&\n typeof response.contentType === 'string'\n ? response.contentType\n : 'application/json') ?? 'application/json',\n parserType: 'text',\n schema: response.schema\n };\n } else if ('text' in response && response.text != null) {\n discriminatedResponses[Number(statusCode)] = {\n contentType:\n ('contentType' in response &&\n typeof response.contentType === 'string'\n ? response.contentType\n : 'text/plain') ?? 'text/plain',\n parserType: 'text',\n schema: response.text\n };\n } else if ('file' in response && response.file != null) {\n discriminatedResponses[Number(statusCode)] = {\n contentType:\n ('contentType' in response &&\n typeof response.contentType === 'string'\n ? response.contentType\n : 'application/octet-stream') ?? 'application/octet-stream',\n parserType: 'file',\n schema: response.file\n };\n } else if ('event' in response && response.event != null) {\n discriminatedResponses[Number(statusCode)] = {\n contentType:\n ('contentType' in response &&\n typeof response.contentType === 'string'\n ? response.contentType\n : 'text/event-stream') ?? 'text/event-stream',\n parserType: 'serverSentEvent',\n schema: response.event\n };\n } else if (\n (schemaValidator as SchemaValidator).isInstanceOf(\n response,\n schemaValidator.string\n )\n ) {\n discriminatedResponses[Number(statusCode)] = {\n contentType: 'text/plain',\n parserType: 'text',\n schema: response\n };\n } else if (\n (schemaValidator as SchemaValidator).openapi(response).format ===\n 'binary'\n ) {\n discriminatedResponses[Number(statusCode)] = {\n contentType: 'application/octet-stream',\n parserType: 'file',\n schema: response\n };\n } else {\n discriminatedResponses[Number(statusCode)] = {\n contentType: 'application/json',\n parserType: 'json',\n schema: response\n };\n }\n } else {\n discriminatedResponses[Number(statusCode)] = {\n contentType: 'application/json',\n parserType: 'json',\n schema: response\n };\n }\n }\n return discriminatedResponses;\n}\n","import { isRecord } from '@forklaunch/common';\nimport { AnySchemaValidator, SchemaValidator } from '@forklaunch/validator';\nimport { hasPermissionChecks } from '../guards/hasPermissionChecks';\nimport { hasRoleChecks } from '../guards/hasRoleChecks';\nimport { hasScopeChecks } from '../guards/hasScopeChecks';\nimport { hasVersionedSchema } from '../guards/hasVersionedSchema';\nimport { isExpressLikeSchemaHandler } from '../guards/isExpressLikeSchemaHandler';\nimport { isHmacMethod } from '../guards/isHmacMethod';\nimport { isHttpContractDetails } from '../guards/isHttpContractDetails';\nimport { isPathParamHttpContractDetails } from '../guards/isPathParamContractDetails';\nimport { isTypedHandler } from '../guards/isTypedHandler';\nimport { parseRequestAuth } from '../middleware/request/auth.middleware';\nimport { createContext } from '../middleware/request/createContext.middleware';\nimport { enrichDetails } from '../middleware/request/enrichDetails.middleware';\nimport { parse } from '../middleware/request/parse.middleware';\nimport { OpenTelemetryCollector } from '../telemetry/openTelemetryCollector';\nimport { ExpressLikeSchemaHandler } from '../types/apiDefinition.types';\nimport {\n Body,\n ContractDetails,\n HeadersObject,\n HttpMethod,\n Method,\n ParamsDictionary,\n ParamsObject,\n PathParamHttpContractDetails,\n PathParamMethod,\n QueryObject,\n ResponseCompiledSchema,\n ResponsesObject,\n SchemaAuthMethods,\n SessionObject,\n VersionSchema\n} from '../types/contractDetails.types';\nimport { ExpressLikeRouterOptions } from '../types/expressLikeOptions';\nimport {\n ContractDetailsOrMiddlewareOrTypedHandler,\n MiddlewareOrMiddlewareWithTypedHandler\n} from '../types/expressLikeRouter.types';\nimport { MetricsDefinition } from '../types/openTelemetryCollector.types';\nimport {\n discriminateBody,\n discriminateResponseBodies\n} from './discriminateBody';\n\nexport function resolveContractDetailsAndHandlers<\n SV extends AnySchemaValidator,\n Name extends string,\n ContractMethod extends Method,\n Path extends `/${string}`,\n P extends ParamsObject<SV>,\n ResBodyMap extends ResponsesObject<SV>,\n ReqBody extends Body<SV>,\n ReqQuery extends QueryObject<SV>,\n ReqHeaders extends HeadersObject<SV>,\n ResHeaders extends HeadersObject<SV>,\n LocalsObj extends Record<string, unknown>,\n VersionedApi extends VersionSchema<SV, ContractMethod>,\n RouterSession extends SessionObject<SV>,\n BaseRequest,\n BaseResponse,\n NextFunction,\n Auth extends SchemaAuthMethods<\n SV,\n P,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n VersionedApi,\n BaseRequest\n >\n>(\n contractDetailsOrMiddlewareOrTypedHandler: ContractDetailsOrMiddlewareOrTypedHandler<\n SV,\n Name,\n ContractMethod,\n Path,\n P,\n ResBodyMap,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n ResHeaders,\n LocalsObj,\n VersionedApi,\n BaseRequest,\n BaseResponse,\n NextFunction,\n RouterSession,\n Auth\n >,\n middlewareOrMiddlewareAndTypedHandler: MiddlewareOrMiddlewareWithTypedHandler<\n SV,\n Name,\n ContractMethod,\n Path,\n P,\n ResBodyMap,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n ResHeaders,\n LocalsObj,\n VersionedApi,\n BaseRequest,\n BaseResponse,\n NextFunction,\n RouterSession,\n Auth\n >[]\n) {\n let contractDetails: ContractDetails<\n SV,\n Name,\n ContractMethod,\n Path,\n P,\n ResBodyMap,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n ResHeaders,\n VersionedApi,\n BaseRequest,\n Auth\n >;\n // eslint-disable-next-line no-useless-assignment\n let handlers: ExpressLikeSchemaHandler<\n SV,\n P,\n ResBodyMap,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n ResHeaders,\n LocalsObj,\n VersionedApi,\n RouterSession,\n BaseRequest,\n BaseResponse,\n NextFunction\n >[] = [];\n\n if (\n isTypedHandler<\n SV,\n Name,\n ContractMethod,\n Path,\n P,\n ResBodyMap,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n ResHeaders,\n LocalsObj,\n VersionedApi,\n BaseRequest,\n BaseResponse,\n NextFunction,\n Auth\n >(contractDetailsOrMiddlewareOrTypedHandler)\n ) {\n contractDetails = contractDetailsOrMiddlewareOrTypedHandler.contractDetails;\n handlers =\n contractDetailsOrMiddlewareOrTypedHandler.handlers as ExpressLikeSchemaHandler<\n SV,\n P,\n ResBodyMap,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n ResHeaders,\n LocalsObj,\n VersionedApi,\n RouterSession,\n BaseRequest,\n BaseResponse,\n NextFunction\n >[];\n } else {\n const maybeTypedHandler =\n middlewareOrMiddlewareAndTypedHandler[\n middlewareOrMiddlewareAndTypedHandler.length - 1\n ];\n if (\n isTypedHandler<\n SV,\n Name,\n ContractMethod,\n Path,\n P,\n ResBodyMap,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n ResHeaders,\n LocalsObj,\n VersionedApi,\n BaseRequest,\n BaseResponse,\n NextFunction,\n Auth\n >(maybeTypedHandler)\n ) {\n contractDetails = maybeTypedHandler.contractDetails;\n const typedHandlerHandlers = maybeTypedHandler.handlers;\n const finalHandlers: MiddlewareOrMiddlewareWithTypedHandler<\n SV,\n Name,\n ContractMethod,\n Path,\n P,\n ResBodyMap,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n ResHeaders,\n LocalsObj,\n VersionedApi,\n BaseRequest,\n BaseResponse,\n NextFunction,\n RouterSession,\n Auth\n >[] = [];\n\n if (\n isExpressLikeSchemaHandler<\n SV,\n ContractMethod,\n P,\n ResBodyMap,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n ResHeaders,\n LocalsObj,\n VersionedApi,\n RouterSession,\n BaseRequest,\n BaseResponse,\n NextFunction\n >(contractDetailsOrMiddlewareOrTypedHandler)\n ) {\n finalHandlers.push(contractDetailsOrMiddlewareOrTypedHandler);\n }\n finalHandlers.push(...middlewareOrMiddlewareAndTypedHandler.slice(0, -1));\n finalHandlers.push(\n ...(typedHandlerHandlers as ExpressLikeSchemaHandler<\n SV,\n P,\n ResBodyMap,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n ResHeaders,\n LocalsObj,\n VersionedApi,\n RouterSession,\n BaseRequest,\n BaseResponse,\n NextFunction\n >[] as MiddlewareOrMiddlewareWithTypedHandler<\n SV,\n Name,\n ContractMethod,\n Path,\n P,\n ResBodyMap,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n ResHeaders,\n LocalsObj,\n VersionedApi,\n BaseRequest,\n BaseResponse,\n NextFunction,\n RouterSession,\n Auth\n >[])\n );\n\n handlers = (finalHandlers as unknown[]).filter((handler) =>\n isExpressLikeSchemaHandler<\n SV,\n ContractMethod,\n P,\n ResBodyMap,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n ResHeaders,\n LocalsObj,\n VersionedApi,\n RouterSession,\n BaseRequest,\n BaseResponse,\n NextFunction\n >(handler)\n ) as ExpressLikeSchemaHandler<\n SV,\n P,\n ResBodyMap,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n ResHeaders,\n LocalsObj,\n VersionedApi,\n RouterSession,\n BaseRequest,\n BaseResponse,\n NextFunction\n >[];\n } else {\n if (\n isExpressLikeSchemaHandler(contractDetailsOrMiddlewareOrTypedHandler) ||\n isTypedHandler<\n SV,\n Name,\n ContractMethod,\n Path,\n P,\n ResBodyMap,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n ResHeaders,\n LocalsObj,\n VersionedApi,\n BaseRequest,\n BaseResponse,\n NextFunction,\n Auth\n >(contractDetailsOrMiddlewareOrTypedHandler)\n ) {\n throw new Error('Contract details are not defined');\n }\n contractDetails =\n contractDetailsOrMiddlewareOrTypedHandler as ContractDetails<\n SV,\n Name,\n ContractMethod,\n Path,\n P,\n ResBodyMap,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n ResHeaders,\n VersionedApi,\n BaseRequest,\n Auth\n >;\n\n handlers = (middlewareOrMiddlewareAndTypedHandler as unknown[]).filter(\n (handler) =>\n isExpressLikeSchemaHandler<\n SV,\n ContractMethod,\n P,\n ResBodyMap,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n ResHeaders,\n LocalsObj,\n VersionedApi,\n RouterSession,\n BaseRequest,\n BaseResponse,\n NextFunction\n >(handler)\n ) as ExpressLikeSchemaHandler<\n SV,\n P,\n ResBodyMap,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n ResHeaders,\n LocalsObj,\n VersionedApi,\n RouterSession,\n BaseRequest,\n BaseResponse,\n NextFunction\n >[];\n }\n }\n\n return { contractDetails, handlers };\n}\n\nexport function validateContractDetails<\n SV extends AnySchemaValidator,\n Name extends string,\n ContractMethod extends Method,\n Path extends `/${string}`,\n P extends ParamsObject<SV>,\n ResBodyMap extends ResponsesObject<SV>,\n ReqBody extends Body<SV>,\n ReqQuery extends QueryObject<SV>,\n ReqHeaders extends HeadersObject<SV>,\n ResHeaders extends HeadersObject<SV>,\n VersionedApi extends VersionSchema<SV, ContractMethod>,\n BaseRequest,\n Auth extends SchemaAuthMethods<\n SV,\n P,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n VersionedApi,\n BaseRequest\n >\n>(\n contractDetails: ContractDetails<\n SV,\n Name,\n ContractMethod,\n Path,\n P,\n ResBodyMap,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n ResHeaders,\n VersionedApi,\n BaseRequest,\n Auth\n >,\n schemaValidator: SV\n) {\n if (\n !isHttpContractDetails<\n SV,\n Name,\n Path,\n P,\n ResBodyMap,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n ResHeaders,\n VersionedApi extends VersionSchema<SV, HttpMethod> ? VersionedApi : never,\n BaseRequest,\n Auth\n >(contractDetails) &&\n !isPathParamHttpContractDetails<\n SV,\n Name,\n Path,\n P,\n ResBodyMap,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n ResHeaders,\n VersionedApi extends VersionSchema<SV, PathParamMethod>\n ? VersionedApi\n : never,\n BaseRequest,\n Auth\n >(contractDetails)\n ) {\n throw new Error('Contract details are malformed for route definition');\n }\n\n // Validate access field and auth narrowing (runtime safety net for JS users)\n const access = (contractDetails as Record<string, unknown>)['access'] as\n string | undefined;\n const auth = (contractDetails as Record<string, unknown>)['auth'];\n\n if (access != null) {\n const validAccess = ['public', 'authenticated', 'protected', 'internal'];\n if (!validAccess.includes(access)) {\n throw new Error(\n `Route '${contractDetails.name}': invalid access level '${access}'. ` +\n `Must be one of: ${validAccess.join(', ')}`\n );\n }\n\n if (access === 'public' && auth != null) {\n throw new Error(\n `Route '${contractDetails.name}': access 'public' cannot have auth configured`\n );\n }\n\n if (access === 'protected') {\n if (!auth) {\n throw new Error(\n `Route '${contractDetails.name}': access 'protected' requires auth with roles, permissions, or scope`\n );\n }\n if (\n !hasPermissionChecks(auth) &&\n !hasRoleChecks(auth) &&\n !hasScopeChecks(auth)\n ) {\n throw new Error(\n `Route '${contractDetails.name}': access 'protected' requires at least one of ` +\n `allowedRoles, forbiddenRoles, allowedPermissions, forbiddenPermissions, or requiredScope`\n );\n }\n }\n\n if (access === 'internal') {\n if (!auth || !isHmacMethod(auth)) {\n throw new Error(\n `Route '${contractDetails.name}': access 'internal' requires HMAC auth`\n );\n }\n }\n }\n\n if (contractDetails.versions) {\n const parserTypes = Object.values(contractDetails.versions).map(\n (version) => discriminateBody(schemaValidator, version.body)?.parserType\n );\n\n const allParserTypesSame =\n parserTypes.length === 0 ||\n parserTypes.every((pt) => pt === parserTypes[0]);\n\n if (!allParserTypesSame) {\n throw new Error(\n 'All versioned contractDetails must have the same parsing type for body.'\n );\n }\n }\n}\n\nexport function processContractDetailsIO<\n SV extends AnySchemaValidator,\n P extends ParamsObject<SV>\n>(\n schemaValidator: SV & SchemaValidator,\n contractDetailsIO: {\n requestHeaders?: HeadersObject<SV>;\n responseHeaders?: HeadersObject<SV>;\n query?: QueryObject<SV>;\n body?: Body<SV>;\n responses: ResponsesObject<SV>;\n },\n routeParams?: P\n) {\n const responseSchemas = {\n 400: schemaValidator.string,\n 401: schemaValidator.string,\n 403: schemaValidator.string,\n 404: schemaValidator.string,\n 500: schemaValidator.string,\n ...Object.fromEntries(\n Object.entries(\n discriminateResponseBodies(schemaValidator, contractDetailsIO.responses)\n ).map(([key, value]) => [Number(key), value.schema])\n )\n };\n\n return {\n requestSchema: schemaValidator.compile(\n schemaValidator.schemify({\n ...(routeParams != null\n ? { params: routeParams as ParamsDictionary }\n : { params: schemaValidator.unknown as ParamsObject<SV> }),\n ...(contractDetailsIO.requestHeaders != null\n ? { headers: contractDetailsIO.requestHeaders }\n : { headers: schemaValidator.unknown as HeadersObject<SV> }),\n ...(contractDetailsIO.query != null\n ? { query: contractDetailsIO.query }\n : { query: schemaValidator.unknown as QueryObject<SV> }),\n ...(contractDetailsIO.body != null\n ? {\n body: discriminateBody(schemaValidator, contractDetailsIO.body)\n ?.schema\n }\n : { body: schemaValidator.unknown as Body<SV> })\n })\n ),\n responseSchemas: {\n ...(contractDetailsIO.responseHeaders != null\n ? {\n headers: schemaValidator.compile(\n schemaValidator.schemify(contractDetailsIO.responseHeaders)\n )\n }\n : { headers: schemaValidator.unknown as HeadersObject<SV> }),\n responses: Object.fromEntries(\n Object.entries(responseSchemas).map(([key, value]) => [\n key,\n schemaValidator.compile(schemaValidator.schemify(value))\n ])\n )\n }\n };\n}\n\nexport function compileRouteSchemas<\n SV extends AnySchemaValidator,\n Name extends string,\n ContractMethod extends Method,\n Path extends `/${string}`,\n P extends ParamsObject<SV>,\n ResBodyMap extends ResponsesObject<SV>,\n ReqBody extends Body<SV>,\n ReqQuery extends QueryObject<SV>,\n ReqHeaders extends HeadersObject<SV>,\n ResHeaders extends HeadersObject<SV>,\n VersionedApi extends VersionSchema<SV, ContractMethod>,\n BaseRequest,\n Auth extends SchemaAuthMethods<\n SV,\n P,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n VersionedApi,\n BaseRequest\n >\n>(\n contractDetails: ContractDetails<\n SV,\n Name,\n ContractMethod,\n Path,\n P,\n ResBodyMap,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n ResHeaders,\n VersionedApi,\n BaseRequest,\n Auth\n >,\n schemaValidator: SV\n) {\n const validator = schemaValidator as SV & SchemaValidator;\n let requestSchema: unknown | Record<string, unknown>;\n let responseSchemas:\n ResponseCompiledSchema | Record<string, ResponseCompiledSchema>;\n\n if (hasVersionedSchema(contractDetails)) {\n requestSchema = {};\n responseSchemas = {};\n\n Object.entries(contractDetails.versions ?? {}).forEach(\n ([version, versionedContractDetails]) => {\n const {\n requestSchema: versionedRequestSchema,\n responseSchemas: versionedResponseSchemas\n } = processContractDetailsIO(\n validator,\n versionedContractDetails,\n contractDetails.params as P\n );\n\n if (isRecord(requestSchema)) {\n requestSchema = {\n ...requestSchema,\n [version]: versionedRequestSchema\n };\n }\n if (isRecord(responseSchemas)) {\n responseSchemas = {\n ...responseSchemas,\n [version]: versionedResponseSchemas\n };\n }\n }\n );\n } else {\n const {\n requestSchema: unversionedRequestSchema,\n responseSchemas: unversionedResponseSchemas\n } = processContractDetailsIO(\n validator,\n {\n ...('params' in contractDetails && contractDetails.params != null\n ? { params: contractDetails.params }\n : { params: validator.unknown as ParamsObject<SV> }),\n ...('requestHeaders' in contractDetails &&\n contractDetails.requestHeaders != null\n ? { requestHeaders: contractDetails.requestHeaders }\n : {\n requestHeaders: validator.unknown as HeadersObject<SV>\n }),\n ...('responseHeaders' in contractDetails &&\n contractDetails.responseHeaders != null\n ? { responseHeaders: contractDetails.responseHeaders }\n : {\n responseHeaders: validator.unknown as HeadersObject<SV>\n }),\n ...('query' in contractDetails && contractDetails.query != null\n ? { query: contractDetails.query }\n : {\n query: validator.unknown as QueryObject<SV>\n }),\n ...('body' in contractDetails && contractDetails.body != null\n ? { body: contractDetails.body }\n : {\n body: validator.unknown as Body<SV>\n }),\n responses:\n 'responses' in contractDetails && contractDetails.responses != null\n ? contractDetails.responses\n : (validator.unknown as ResponsesObject<SV>)\n },\n contractDetails.params as P\n );\n\n requestSchema = unversionedRequestSchema;\n responseSchemas = unversionedResponseSchemas;\n }\n\n return { requestSchema, responseSchemas };\n}\n\nexport function resolveRouteMiddlewares<\n SV extends AnySchemaValidator,\n Name extends string,\n ContractMethod extends Method,\n Path extends `/${string}`,\n P extends ParamsObject<SV>,\n ResBodyMap extends ResponsesObject<SV>,\n ReqBody extends Body<SV>,\n ReqQuery extends QueryObject<SV>,\n ReqHeaders extends HeadersObject<SV>,\n ResHeaders extends HeadersObject<SV>,\n LocalsObj extends Record<string, unknown>,\n VersionedApi extends VersionSchema<SV, ContractMethod>,\n RouterSession extends SessionObject<SV>,\n BaseRequest,\n BaseResponse,\n NextFunction,\n Auth extends SchemaAuthMethods<\n SV,\n P,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n VersionedApi,\n BaseRequest\n >,\n RouterHandler\n>(params: {\n basePath: string;\n path: Path;\n contractDetails: ContractDetails<\n SV,\n Name,\n ContractMethod,\n Path,\n P,\n ResBodyMap,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n ResHeaders,\n VersionedApi,\n BaseRequest,\n Auth\n >;\n requestSchema: unknown;\n responseSchemas:\n ResponseCompiledSchema | Record<string, ResponseCompiledSchema>;\n openTelemetryCollector?: OpenTelemetryCollector<MetricsDefinition>;\n routerOptions?: ExpressLikeRouterOptions<SV, RouterSession>;\n postEnrichMiddleware?: RouterHandler[];\n includeCreateContext?: boolean;\n handlers: ExpressLikeSchemaHandler<\n SV,\n P,\n ResBodyMap,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n ResHeaders,\n LocalsObj,\n VersionedApi,\n RouterSession,\n BaseRequest,\n BaseResponse,\n NextFunction\n >[];\n router?: { routerOptions?: ExpressLikeRouterOptions<SV, RouterSession> };\n}): {\n middlewares: RouterHandler[];\n controllerHandler: ExpressLikeSchemaHandler<\n SV,\n P,\n ResBodyMap,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n ResHeaders,\n LocalsObj,\n VersionedApi,\n RouterSession,\n BaseRequest,\n BaseResponse,\n NextFunction\n >;\n} {\n const handlersCopy = [...params.handlers];\n const controllerHandler = handlersCopy.pop();\n\n if (typeof controllerHandler !== 'function') {\n throw new Error(\n `Last argument must be a handler, received: ${controllerHandler}`\n );\n }\n\n const middlewares = [\n ...(params.includeCreateContext !== false ? [createContext] : []),\n enrichDetails<\n SV,\n ContractMethod,\n P,\n ResBodyMap,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n ResHeaders,\n LocalsObj,\n VersionedApi,\n RouterSession\n >(\n `${params.basePath}${params.path}`,\n params.contractDetails as PathParamHttpContractDetails<SV>,\n params.requestSchema,\n params.responseSchemas,\n params.openTelemetryCollector,\n // Use dynamic lookup from router instance instead of captured params\n () => (params.router ? params.router.routerOptions : params.routerOptions)\n ),\n ...(params.postEnrichMiddleware as unknown[]),\n parse,\n parseRequestAuth<\n SV,\n ContractMethod,\n P,\n ResBodyMap,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n ResHeaders,\n LocalsObj,\n VersionedApi,\n RouterSession\n >,\n ...handlersCopy\n ] as RouterHandler[];\n\n return {\n middlewares,\n controllerHandler: controllerHandler as ExpressLikeSchemaHandler<\n SV,\n P,\n ResBodyMap,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n ResHeaders,\n LocalsObj,\n VersionedApi,\n RouterSession,\n BaseRequest,\n BaseResponse,\n NextFunction\n >\n };\n}\n","export function hasVersionedSchema(contractDetails: unknown) {\n return (\n typeof contractDetails === 'object' &&\n contractDetails !== null &&\n 'versions' in contractDetails &&\n contractDetails.versions !== null\n );\n}\n","import { HmacMethods } from '../types/contractDetails.types';\n\n/**\n * Type guard to determine if the provided value is an HmacMethods object.\n *\n * @param maybeHmacMethod - The value to check.\n * @returns True if the value is an object with a non-null 'hmac' property, otherwise false.\n */\nexport function isHmacMethod(\n maybeHmacMethod: unknown\n): maybeHmacMethod is HmacMethods {\n return (\n typeof maybeHmacMethod === 'object' &&\n maybeHmacMethod !== null &&\n 'hmac' in maybeHmacMethod &&\n maybeHmacMethod.hmac != null\n );\n}\n","import { AnySchemaValidator } from '@forklaunch/validator';\nimport {\n Body,\n ExtractedParamsObject,\n HeadersObject,\n ParamsObject,\n PathParamHttpContractDetails,\n PathParamMethod,\n QueryObject,\n ResponsesObject,\n SchemaAuthMethods,\n VersionSchema\n} from '../types/contractDetails.types';\n\nexport function isPathParamHttpContractDetails<\n SV extends AnySchemaValidator,\n Name extends string,\n Path extends `/${string}`,\n ParamsSchema extends ExtractedParamsObject<Path> & ParamsObject<SV>,\n ResponseSchemas extends ResponsesObject<SV>,\n BodySchema extends Body<SV>,\n QuerySchema extends QueryObject<SV>,\n ReqHeaders extends HeadersObject<SV>,\n ResHeaders extends HeadersObject<SV>,\n VersionedApi extends VersionSchema<SV, PathParamMethod>,\n BaseRequest,\n const Auth extends SchemaAuthMethods<\n SV,\n ParamsSchema,\n BodySchema,\n QuerySchema,\n ReqHeaders,\n VersionedApi,\n BaseRequest\n >\n>(\n maybePathParamHttpContractDetails: unknown\n): maybePathParamHttpContractDetails is PathParamHttpContractDetails<\n SV,\n Name,\n Path,\n ParamsSchema,\n ResponseSchemas,\n BodySchema,\n QuerySchema,\n ReqHeaders,\n ResHeaders,\n VersionedApi,\n BaseRequest,\n Auth\n> {\n return (\n maybePathParamHttpContractDetails != null &&\n typeof maybePathParamHttpContractDetails === 'object' &&\n 'name' in maybePathParamHttpContractDetails &&\n 'summary' in maybePathParamHttpContractDetails &&\n maybePathParamHttpContractDetails.name != null &&\n maybePathParamHttpContractDetails.summary != null &&\n (('responses' in maybePathParamHttpContractDetails &&\n maybePathParamHttpContractDetails.responses != null) ||\n ('versions' in maybePathParamHttpContractDetails &&\n typeof maybePathParamHttpContractDetails.versions === 'object' &&\n maybePathParamHttpContractDetails.versions != null &&\n Object.values(maybePathParamHttpContractDetails.versions).every(\n (version) => 'responses' in version && version.responses != null\n )))\n );\n}\n","import { AnySchemaValidator } from '@forklaunch/validator';\nimport {\n Body,\n ExtractedParamsObject,\n HeadersObject,\n HttpContractDetails,\n HttpMethod,\n ParamsObject,\n QueryObject,\n ResponsesObject,\n SchemaAuthMethods,\n VersionSchema\n} from '../types/contractDetails.types';\nimport { isPathParamHttpContractDetails } from './isPathParamContractDetails';\n\n/**\n * Type guard that checks if an object is an HTTP contract details object.\n * An HTTP contract details object contains the schema definitions for an HTTP endpoint,\n * including path parameters, response schemas, body schema, query parameters, and headers.\n *\n * @template SV - A type that extends AnySchemaValidator\n * @template Path - A type that extends `/${string}` representing the endpoint path\n * @template ParamsSchema - The type of path parameters schema\n * @template ResponseSchemas - The type of response schemas\n * @template BodySchema - The type of request body schema\n * @template QuerySchema - The type of query parameters schema\n * @template ReqHeaders - The type of request headers schema\n * @template ResHeaders - The type of response headers schema\n * @template BaseRequest - The base request type\n * @param {unknown} maybeContractDetails - The object to check\n * @returns {boolean} A type predicate indicating whether the object is an HttpContractDetails\n *\n * @example\n * ```ts\n * if (isHttpContractDetails(contractDetails)) {\n * // contractDetails is now typed as HttpContractDetails\n * const { body, path, params } = contractDetails;\n * }\n * ```\n */\nexport function isHttpContractDetails<\n SV extends AnySchemaValidator,\n Name extends string,\n Path extends `/${string}`,\n ParamsSchema extends ExtractedParamsObject<Path> & ParamsObject<SV>,\n ResponseSchemas extends ResponsesObject<SV>,\n BodySchema extends Body<SV>,\n QuerySchema extends QueryObject<SV>,\n ReqHeaders extends HeadersObject<SV>,\n ResHeaders extends HeadersObject<SV>,\n VersionedReqs extends VersionSchema<SV, HttpMethod>,\n BaseRequest,\n const Auth extends SchemaAuthMethods<\n SV,\n ParamsSchema,\n BodySchema,\n QuerySchema,\n ReqHeaders,\n VersionedReqs,\n BaseRequest\n >\n>(\n maybeContractDetails: unknown\n): maybeContractDetails is HttpContractDetails<\n SV,\n Name,\n Path,\n ParamsSchema,\n ResponseSchemas,\n BodySchema,\n QuerySchema,\n ReqHeaders,\n ResHeaders,\n VersionedReqs,\n BaseRequest,\n Auth\n> {\n return (\n isPathParamHttpContractDetails(maybeContractDetails) &&\n (('body' in maybeContractDetails && maybeContractDetails.body != null) ||\n ('versions' in maybeContractDetails &&\n typeof maybeContractDetails.versions === 'object' &&\n maybeContractDetails.versions != null &&\n Object.values(maybeContractDetails.versions).every(\n (version) => 'body' in version && version.body != null\n )))\n );\n}\n","import { isNever } from '@forklaunch/common';\nimport {\n AnySchemaValidator,\n prettyPrintParseErrors,\n SchemaValidator\n} from '@forklaunch/validator';\nimport { JWTPayload } from 'jose';\nimport { ParsedQs } from 'qs';\nimport { discriminateAuthMethod } from '../../discriminateAuthMethod';\nimport { hasFeatureChecks } from '../../guards/hasFeatureChecks';\nimport { hasPermissionChecks } from '../../guards/hasPermissionChecks';\nimport { hasRoleChecks } from '../../guards/hasRoleChecks';\nimport { hasScopeChecks } from '../../guards/hasScopeChecks';\nimport { hasSubscriptionChecks } from '../../guards/hasSubscriptionChecks';\nimport { isHmacMethod } from '../../guards/isHmacMethod';\nimport { meta } from '../../telemetry/pinoLogger';\nimport { authLogContext, jwtFailureReason } from './authLogContext';\nimport {\n ForklaunchNextFunction,\n ForklaunchRequest,\n ForklaunchResponse,\n MapParamsSchema,\n MapReqBodySchema,\n MapReqHeadersSchema,\n MapReqQuerySchema,\n MapResBodyMapSchema,\n MapResHeadersSchema,\n MapSessionSchema,\n MapVersionedReqsSchema,\n ResolvedForklaunchRequest,\n VersionedRequests\n} from '../../types/apiDefinition.types';\nimport {\n AuthMethods,\n Body,\n HeadersObject,\n Method,\n ParamsDictionary,\n ParamsObject,\n QueryObject,\n ResponsesObject,\n SessionObject,\n VersionSchema\n} from '../../types/contractDetails.types';\nimport { ExpressLikeGlobalAuthOptions } from '../../types/expressLikeOptions';\n\nconst invalidAuthorizationTokenFormat = [\n 401,\n 'Invalid Authorization token format.'\n] as const;\nconst invalidAuthorizationSignature = [\n 403,\n 'Invalid Authorization signature.'\n] as const;\nconst invalidAuthorizationTokenPermissions = [\n 403,\n 'Invalid Authorization permissions.'\n] as const;\nconst invalidAuthorizationTokenRoles = [\n 403,\n 'Invalid Authorization roles.'\n] as const;\nconst invalidAuthorizationTokenFeatures = [\n 403,\n 'Required features not available.'\n] as const;\nconst invalidAuthorizationSubscription = [\n 403,\n 'Active subscription required.'\n] as const;\nconst invalidAuthorizationToken = [\n 403,\n 'Invalid Authorization token.'\n] as const;\nconst invalidAuthorizationLogin = [\n 403,\n 'Invalid Authorization login.'\n] as const;\nconst invalidScope = [403, 'Invalid scope for operation.'] as const;\nconst invalidAuthorizationMethod = [\n 401,\n 'Invalid Authorization method.'\n] as const;\nconst authorizationTokenRequired = [\n 401,\n 'Authorization token required.'\n] as const;\nconst invalidInstantiation = [\n 500,\n 'Invalid instantiation of authorization method.'\n] as const;\n\n/**\n * Parses a HMAC token part.\n *\n * @param {string} part - The part of the token.\n * @param {string} expectedKey - The expected key.\n * @returns {string | undefined} - The parsed part.\n */\nfunction parseHmacTokenPart(\n part: string,\n expectedKey: string\n): string | undefined {\n if (!part) return undefined;\n const [key, ...rest] = part.split('=');\n if (key !== expectedKey || rest.length === 0) return undefined;\n return rest.join('=');\n}\n\n/**\n * Checks the authorization token for validity.\n *\n * @param {AuthMethod} [authorizationMethod] - The method of authorization.\n * @param {string} [authorizationToken] - The authorization string.\n * @returns {Promise<[401 | 403, string] | string | undefined>} - The result of the authorization check.\n */\nasync function checkAuthorizationToken<\n SV extends AnySchemaValidator,\n P extends ParamsDictionary,\n ReqBody extends Record<string, unknown>,\n ReqQuery extends ParsedQs,\n ReqHeaders extends Record<string, string>,\n VersionedReqs extends VersionedRequests,\n SessionSchema extends SessionObject<SV>,\n BaseRequest\n>(\n req: ForklaunchRequest<\n SV,\n P,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n Extract<keyof VersionedReqs, string>,\n SessionSchema\n >,\n authorizationMethod?: AuthMethods<\n SV,\n P,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n VersionedReqs,\n BaseRequest\n >,\n authorizationToken?: string,\n globalOptions?: ExpressLikeGlobalAuthOptions<SV, SessionSchema>,\n access?: 'public' | 'authenticated' | 'protected' | 'internal'\n): Promise<readonly [400 | 401 | 403 | 500, string] | undefined> {\n if (authorizationMethod == null) {\n return undefined;\n }\n\n const collapsedAuthorizationMethod = {\n ...globalOptions,\n ...authorizationMethod\n } as AuthMethods<\n SV,\n P,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n VersionedReqs,\n BaseRequest\n > &\n Exclude<ExpressLikeGlobalAuthOptions<SV, SessionSchema>, false | undefined>;\n\n if (authorizationToken == null) {\n return authorizationTokenRequired;\n }\n\n const [tokenPrefix, ...tokenParts] = authorizationToken.split(' ');\n\n if (!tokenParts.length || !tokenPrefix) {\n return invalidAuthorizationTokenFormat;\n }\n\n let sessionPayload: (JWTPayload & SessionSchema) | null;\n\n const { type, auth } = await discriminateAuthMethod(\n collapsedAuthorizationMethod as AuthMethods<\n SV,\n P,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n VersionedReqs,\n BaseRequest\n >,\n req.openTelemetryCollector\n );\n\n switch (type) {\n case 'hmac': {\n const [keyId, timestamp, nonce, signature] = tokenParts;\n if (\n keyId == null ||\n timestamp == null ||\n nonce == null ||\n signature == null ||\n tokenPrefix !== (collapsedAuthorizationMethod.tokenPrefix ?? 'HMAC')\n ) {\n return invalidAuthorizationToken;\n }\n\n if (!collapsedAuthorizationMethod.hmac?.secretKeys) {\n return invalidInstantiation;\n }\n\n const parsedKeyId = parseHmacTokenPart(keyId, 'keyId');\n const parsedTimestamp = parseHmacTokenPart(timestamp, 'ts');\n const parsedNonce = parseHmacTokenPart(nonce, 'nonce');\n const parsedSignature = parseHmacTokenPart(signature, 'signature');\n\n if (\n !parsedKeyId ||\n !parsedTimestamp ||\n !parsedNonce ||\n !parsedSignature\n ) {\n return invalidAuthorizationTokenFormat;\n }\n\n const verificationResult = await auth.verificationFunction({\n method: req?.method ?? '',\n path: req?.path ?? '',\n body: req?._rawBody ?? req?.body,\n timestamp: new Date(parsedTimestamp),\n nonce: parsedNonce,\n signature: parsedSignature,\n secretKey: collapsedAuthorizationMethod.hmac.secretKeys[parsedKeyId]\n });\n\n if (!verificationResult) {\n return invalidAuthorizationSignature;\n }\n\n sessionPayload = null;\n break;\n }\n case 'jwt': {\n const [token] = tokenParts;\n if (\n tokenPrefix !== (collapsedAuthorizationMethod.tokenPrefix ?? 'Bearer')\n ) {\n return invalidAuthorizationTokenFormat;\n }\n\n try {\n const decodedJwt =\n 'decodeResource' in auth && auth.decodeResource\n ? await auth.decodeResource(token)\n : 'verificationFunction' in auth && auth.verificationFunction\n ? await auth.verificationFunction(token)\n : undefined;\n\n if (!decodedJwt) {\n return invalidAuthorizationToken;\n }\n\n sessionPayload = decodedJwt as JWTPayload & SessionSchema;\n } catch (error) {\n (\n req as ForklaunchRequest<\n SV,\n P,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n Extract<keyof VersionedReqs, string>,\n SessionSchema\n >\n )?.openTelemetryCollector?.warn(\n 'JWT Verification Failed',\n meta({\n reason: jwtFailureReason(error),\n error: error instanceof Error ? error.message : String(error),\n method: req.method,\n path: req.path,\n ...authLogContext(token)\n })\n );\n return invalidAuthorizationToken;\n }\n\n break;\n }\n case 'basic': {\n const [token] = tokenParts;\n\n if (\n tokenPrefix !== (collapsedAuthorizationMethod.tokenPrefix ?? 'Basic')\n ) {\n return invalidAuthorizationTokenFormat;\n }\n\n if (auth.decodeResource) {\n sessionPayload = (await auth.decodeResource(token)) as JWTPayload &\n SessionSchema;\n } else {\n const [username, password] = Buffer.from(token, 'base64')\n .toString('utf-8')\n .split(':');\n\n if (!username || !password) {\n return invalidAuthorizationTokenFormat;\n }\n\n if (!auth.login(username, password)) {\n return invalidAuthorizationLogin;\n }\n\n sessionPayload = {\n sub: username\n } as JWTPayload & SessionSchema;\n }\n break;\n }\n default:\n isNever(type);\n return [401, 'Invalid Authorization method.'];\n }\n\n if (isHmacMethod(collapsedAuthorizationMethod) && sessionPayload == null) {\n return;\n }\n\n if (sessionPayload == null) {\n return invalidAuthorizationToken;\n }\n\n req.session = sessionPayload;\n if (collapsedAuthorizationMethod.sessionSchema) {\n const parsedSession = (req.schemaValidator as SchemaValidator).parse(\n collapsedAuthorizationMethod.sessionSchema,\n sessionPayload\n );\n if (!parsedSession.ok) {\n return [\n 400,\n `Invalid session: ${prettyPrintParseErrors(parsedSession.errors, 'Session')}`\n ];\n }\n }\n\n if (hasScopeChecks(collapsedAuthorizationMethod)) {\n if (collapsedAuthorizationMethod.surfaceScopes) {\n const resourceScopes = await collapsedAuthorizationMethod.surfaceScopes(\n sessionPayload,\n req as ResolvedForklaunchRequest<\n SV,\n P,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n VersionedReqs,\n SessionSchema,\n BaseRequest\n >\n );\n\n if (collapsedAuthorizationMethod.scopeHeirarchy) {\n if (collapsedAuthorizationMethod.requiredScope) {\n if (\n !resourceScopes.has(collapsedAuthorizationMethod.requiredScope) ||\n !Array.from(resourceScopes).every(\n (scope) =>\n (collapsedAuthorizationMethod.scopeHeirarchy?.indexOf(scope) ??\n -1) > -1\n )\n ) {\n return invalidScope;\n }\n }\n }\n }\n }\n\n // 'authenticated' routes only need a valid token (already verified above).\n // 'internal' routes use HMAC (already verified above, no RBAC).\n // Only 'protected' routes require RBAC checks.\n if (access === 'authenticated' || access === 'internal') {\n // Token/HMAC already validated — skip RBAC, proceed to subscription/feature checks\n } else if (hasPermissionChecks(collapsedAuthorizationMethod)) {\n if (!collapsedAuthorizationMethod.surfacePermissions) {\n return [500, 'No permission surfacing function provided.'];\n }\n\n const resourcePermissions =\n await collapsedAuthorizationMethod.surfacePermissions(\n sessionPayload,\n req as ResolvedForklaunchRequest<\n SV,\n P,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n VersionedReqs,\n SessionSchema,\n BaseRequest\n >\n );\n\n if (\n 'allowedPermissions' in collapsedAuthorizationMethod &&\n collapsedAuthorizationMethod.allowedPermissions\n ) {\n if (\n resourcePermissions.intersection(\n collapsedAuthorizationMethod.allowedPermissions\n ).size === 0\n ) {\n return invalidAuthorizationTokenPermissions;\n }\n }\n\n if (\n 'forbiddenPermissions' in collapsedAuthorizationMethod &&\n collapsedAuthorizationMethod.forbiddenPermissions\n ) {\n if (\n resourcePermissions.intersection(\n collapsedAuthorizationMethod.forbiddenPermissions\n ).size !== 0\n ) {\n return invalidAuthorizationTokenPermissions;\n }\n }\n } else if (hasRoleChecks(collapsedAuthorizationMethod)) {\n if (!collapsedAuthorizationMethod.surfaceRoles) {\n return [500, 'No role surfacing function provided.'];\n }\n\n const resourceRoles = await collapsedAuthorizationMethod.surfaceRoles(\n sessionPayload,\n req as ResolvedForklaunchRequest<\n SV,\n P,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n VersionedReqs,\n SessionSchema,\n BaseRequest\n >\n );\n\n if (\n 'allowedRoles' in collapsedAuthorizationMethod &&\n collapsedAuthorizationMethod.allowedRoles\n ) {\n if (\n resourceRoles.intersection(collapsedAuthorizationMethod.allowedRoles)\n .size === 0\n ) {\n return invalidAuthorizationTokenRoles;\n }\n }\n\n if (\n 'forbiddenRoles' in collapsedAuthorizationMethod &&\n collapsedAuthorizationMethod.forbiddenRoles\n ) {\n if (\n resourceRoles.intersection(collapsedAuthorizationMethod.forbiddenRoles)\n .size !== 0\n ) {\n return invalidAuthorizationTokenRoles;\n }\n }\n } else if (access === 'protected') {\n return invalidAuthorizationMethod;\n }\n\n if (hasSubscriptionChecks(collapsedAuthorizationMethod)) {\n if (!collapsedAuthorizationMethod.surfaceSubscription) {\n return [500, 'No subscription surfacing function provided.'];\n }\n\n const subscription = await collapsedAuthorizationMethod.surfaceSubscription(\n sessionPayload,\n req as ResolvedForklaunchRequest<\n SV,\n P,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n VersionedReqs,\n SessionSchema,\n BaseRequest\n >\n );\n\n if (!subscription) {\n return invalidAuthorizationSubscription;\n }\n }\n\n if (hasFeatureChecks(collapsedAuthorizationMethod)) {\n if (!collapsedAuthorizationMethod.surfaceFeatures) {\n return [500, 'No features surfacing function provided.'];\n }\n\n const availableFeatures =\n await collapsedAuthorizationMethod.surfaceFeatures(\n sessionPayload,\n req as ResolvedForklaunchRequest<\n SV,\n P,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n VersionedReqs,\n SessionSchema,\n BaseRequest\n >\n );\n\n const requiredFeatures =\n collapsedAuthorizationMethod.requiredFeatures ?? [];\n const missingFeatures = requiredFeatures.filter(\n (feature) => !availableFeatures.has(feature)\n );\n\n if (missingFeatures.length > 0) {\n return invalidAuthorizationTokenFeatures;\n }\n }\n}\n\n/**\n * Middleware to parse request authorization.\n *\n * @template SV - A type that extends AnySchemaValidator.\n * @template Request - A type that extends ForklaunchRequest.\n * @template Response - A type that extends ForklaunchResponse.\n * @template NextFunction - A type that extends ForklaunchNextFunction.\n * @param {Request} req - The request object.\n * @param {Response} res - The response object.\n * @param {NextFunction} [next] - The next middleware function.\n */\nexport async function parseRequestAuth<\n SV extends AnySchemaValidator,\n ContractMethod extends Method,\n P extends ParamsObject<SV>,\n ResBodyMap extends ResponsesObject<SV>,\n ReqBody extends Body<SV>,\n ReqQuery extends QueryObject<SV>,\n ReqHeaders extends HeadersObject<SV>,\n ResHeaders extends HeadersObject<SV>,\n LocalsObj extends Record<string, unknown>,\n VersionedApi extends VersionSchema<SV, ContractMethod>,\n SessionSchema extends SessionObject<SV>\n>(\n req: ForklaunchRequest<\n SV,\n MapParamsSchema<SV, P>,\n MapReqBodySchema<SV, ReqBody>,\n MapReqQuerySchema<SV, ReqQuery>,\n MapReqHeadersSchema<SV, ReqHeaders>,\n Extract<keyof MapVersionedReqsSchema<SV, VersionedApi>, string>,\n MapSessionSchema<SV, SessionSchema>\n >,\n res: ForklaunchResponse<\n unknown,\n MapResBodyMapSchema<SV, ResBodyMap>,\n MapResHeadersSchema<SV, ResHeaders>,\n LocalsObj,\n Extract<keyof MapVersionedReqsSchema<SV, VersionedApi>, string>\n >,\n next?: ForklaunchNextFunction\n) {\n const access = req.contractDetails.access as\n 'public' | 'authenticated' | 'protected' | 'internal' | undefined;\n\n // Public routes skip auth entirely\n if (access === 'public') {\n next?.();\n return;\n }\n\n const auth = req.contractDetails.auth as\n | AuthMethods<\n SV,\n MapParamsSchema<SV, P>,\n MapReqBodySchema<SV, ReqBody>,\n MapReqQuerySchema<SV, ReqQuery>,\n MapReqHeadersSchema<SV, ReqHeaders>,\n MapVersionedReqsSchema<SV, VersionedApi>,\n unknown\n >\n | undefined;\n\n const token =\n (req.headers[auth?.headerName ?? 'Authorization'] as string) ||\n (req.headers[auth?.headerName ?? 'authorization'] as string);\n\n const [error, message] =\n (await checkAuthorizationToken<\n SV,\n MapParamsSchema<SV, P>,\n MapReqBodySchema<SV, ReqBody>,\n MapReqQuerySchema<SV, ReqQuery>,\n MapReqHeadersSchema<SV, ReqHeaders>,\n MapVersionedReqsSchema<SV, VersionedApi>,\n MapSessionSchema<SV, SessionSchema>,\n unknown\n >(req, auth, token, req._globalOptions?.()?.auth, access)) ?? [];\n if (error != null) {\n // Warn, not error: an expired or missing token is normal traffic. The\n // credential itself is never logged; see authLogContext.\n req.openTelemetryCollector?.warn(\n message || 'Authorization Failed',\n meta({\n statusCode: error,\n method: req.method,\n path: req.path,\n ...authLogContext(token)\n })\n );\n res.type('text/plain');\n res.status(error).send(message as never);\n return;\n }\n\n next?.();\n}\n","import { safeStringify } from '@forklaunch/common';\nimport { AnySchemaValidator } from '@forklaunch/validator';\nimport { JWK, JWTPayload, jwtVerify } from 'jose';\nimport { ParsedQs } from 'qs';\nimport { createHmacToken } from './createHmacToken';\nimport { isBasicAuthMethod } from './guards/isBasicAuthMethod';\nimport { isHmacMethod } from './guards/isHmacMethod';\nimport { isJwtAuthMethod } from './guards/isJwtAuthMethod';\nimport { OpenTelemetryCollector } from './telemetry/openTelemetryCollector';\nimport { VersionedRequests } from './types/apiDefinition.types';\nimport {\n AuthMethods,\n BasicAuthMethods,\n DecodeResource,\n ParamsDictionary\n} from './types/contractDetails.types';\nimport { MetricsDefinition } from './types/openTelemetryCollector.types';\n\nconst DEFAULT_TTL = process.env.JWKS_TTL\n ? parseInt(process.env.JWKS_TTL)\n : 60 * 1000 * 5;\n\nconst cachedJwks = {\n value: null as JWK[] | null,\n lastUpdated: null as Date | null,\n ttl: DEFAULT_TTL\n};\n\n/**\n * Retrieves and caches the JSON Web Key Set (JWKS) from a given public key URL.\n *\n * This function fetches the JWKS from the specified URL and caches the result in memory\n * to avoid unnecessary network requests. The cache is considered valid for a duration\n * specified by the `cache-control` header in the JWKS HTTP response (in seconds), or\n * falls back to a default TTL if the header is not present. If the cache is still valid,\n * the cached keys are returned immediately.\n *\n * @param {string} jwksPublicKeyUrl - The URL to fetch the JWKS from.\n * @returns {Promise<JWK[]>} A promise that resolves to an array of JWK objects.\n *\n * @example\n * const jwks = await getCachedJwks('https://example.com/.well-known/jwks.json');\n * // Use jwks for JWT verification, etc.\n */\nexport async function getCachedJwks(jwksPublicKeyUrl: string): Promise<JWK[]> {\n if (\n cachedJwks.value &&\n cachedJwks.lastUpdated &&\n Date.now() - cachedJwks.lastUpdated.getTime() < cachedJwks.ttl\n ) {\n return cachedJwks.value;\n } else {\n const jwksResponse = await fetch(jwksPublicKeyUrl);\n const text = await jwksResponse.text();\n if (!text) {\n if (cachedJwks.value) {\n return cachedJwks.value;\n }\n throw new Error(\n `JWKS endpoint returned empty response (status ${jwksResponse.status})`\n );\n }\n const jwks = (JSON.parse(text) as { keys: JWK[] }).keys;\n cachedJwks.value = jwks;\n cachedJwks.lastUpdated = new Date();\n cachedJwks.ttl =\n parseInt(\n jwksResponse.headers.get('cache-control')?.split('=')[1] ??\n `${DEFAULT_TTL / 1000}`\n ) * 1000;\n return jwks;\n }\n}\n\n/**\n * Discriminates between different authentication methods and returns a typed result.\n *\n * This function analyzes the provided authentication configuration and determines\n * whether it uses basic authentication or JWT authentication. It returns a\n * discriminated union type that includes the authentication type and the\n * corresponding authentication configuration.\n *\n * @template SV - A type that extends AnySchemaValidator\n * @template P - A type that extends ParamsDictionary\n * @template ReqBody - A type that extends Record<string, unknown>\n * @template ReqQuery - A type that extends ParsedQs\n * @template ReqHeaders - A type that extends Record<string, unknown>\n * @template BaseRequest - The base request type\n *\n * @param auth - The authentication methods configuration object\n * @returns A discriminated union object with either:\n * - `{ type: 'basic', auth: BasicAuthMethods['basic'] }` for basic authentication\n * - `{ type: 'jwt', auth?: JwtAuthMethods['jwt'] }` for JWT authentication (auth is optional)\n *\n * @example\n * ```typescript\n * const authConfig = {\n * basic: {\n * login: (username: string, password: string) => boolean\n * }\n * };\n * const result = discriminateAuthMethod(authConfig);\n * // result.type === 'basic'\n * // result.auth === authConfig.basic\n * ```\n */\nexport async function discriminateAuthMethod<\n SV extends AnySchemaValidator,\n P extends ParamsDictionary,\n ReqBody extends Record<string, unknown>,\n ReqQuery extends ParsedQs,\n ReqHeaders extends Record<string, string>,\n VersionedReqs extends VersionedRequests,\n BaseRequest\n>(\n auth: AuthMethods<\n SV,\n P,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n VersionedReqs,\n BaseRequest\n >,\n openTelemetryCollector?: OpenTelemetryCollector<MetricsDefinition>\n): Promise<\n | {\n type: 'basic';\n auth: {\n decodeResource?: DecodeResource;\n login: BasicAuthMethods['basic']['login'];\n };\n }\n | {\n type: 'jwt';\n auth:\n | {\n decodeResource?: DecodeResource;\n }\n | {\n verificationFunction: (\n token: string\n ) => Promise<JWTPayload | undefined>;\n };\n }\n | {\n type: 'hmac';\n auth: {\n secretKeys: Record<string, string>;\n verificationFunction: ({\n body,\n path,\n method,\n timestamp,\n nonce,\n signature,\n secretKey\n }: {\n method: string;\n path: string;\n body?: unknown;\n timestamp: Date;\n nonce: string;\n signature: string;\n secretKey: string;\n }) => Promise<boolean | undefined>;\n };\n }\n> {\n let authMethod;\n if (isBasicAuthMethod(auth)) {\n authMethod = {\n type: 'basic' as const,\n auth: {\n decodeResource: auth.decodeResource,\n login: auth.basic.login\n }\n };\n } else if (isJwtAuthMethod(auth)) {\n const jwt = auth.jwt;\n let verificationFunction: (\n token: string\n ) => Promise<JWTPayload | undefined>;\n if ('signatureKey' in jwt) {\n verificationFunction = async (token) => {\n const { payload } = await jwtVerify(\n token,\n new Uint8Array(Buffer.from(jwt.signatureKey))\n );\n return payload;\n };\n } else {\n let jwks: JWK[];\n if ('jwksPublicKeyUrl' in jwt) {\n jwks = await getCachedJwks(jwt.jwksPublicKeyUrl);\n } else if ('jwksPublicKey' in jwt) {\n jwks = [jwt.jwksPublicKey];\n }\n verificationFunction = async (token) => {\n // Keep the last failure so the middleware can log WHY (expired vs\n // bad signature) instead of a bare \"invalid token\". The caller's\n // catch maps any throw to the same 403 as an undefined return.\n let lastError: unknown;\n for (const key of jwks) {\n try {\n const { payload } = await jwtVerify(token, key);\n return payload;\n } catch (error) {\n lastError = error;\n cachedJwks.value = null;\n cachedJwks.lastUpdated = null;\n cachedJwks.ttl = DEFAULT_TTL;\n continue;\n }\n }\n if (lastError !== undefined) throw lastError;\n };\n }\n authMethod = {\n type: 'jwt' as const,\n auth: {\n decodeResource: auth.decodeResource,\n verificationFunction\n }\n };\n } else if (isHmacMethod(auth)) {\n authMethod = {\n type: 'hmac' as const,\n auth: {\n secretKeys: auth.hmac.secretKeys,\n verificationFunction: async ({\n method,\n path,\n body,\n timestamp,\n nonce,\n signature,\n secretKey\n }: {\n method: string;\n path: string;\n body?: unknown;\n timestamp: Date;\n nonce: string;\n signature: string;\n secretKey: string;\n }) => {\n const computedSignature = createHmacToken({\n method,\n path,\n body,\n timestamp,\n nonce,\n secretKey\n });\n\n const isValid = computedSignature === signature;\n\n if (!isValid) {\n const errorInfo = {\n method,\n path,\n timestamp: timestamp.toISOString(),\n nonce,\n receivedSignature: signature,\n computedSignature\n };\n\n openTelemetryCollector?.debug('[HMAC Verification Failed]', {\n ...errorInfo,\n bodyType: body ? typeof body : 'undefined',\n body: body ? safeStringify(body) : 'undefined'\n });\n }\n\n return isValid;\n }\n }\n };\n }\n if (authMethod == null) {\n throw new Error('Invalid auth method');\n }\n\n return authMethod;\n}\n","import { safeStringify } from '@forklaunch/common';\nimport { createHmac } from 'crypto';\n\n/**\n * Creates an HMAC token for a given method, path, body, timestamp, nonce, and secret key.\n * @param method - The HTTP method to use.\n * @param path - The path to use.\n * @param body - The body to use.\n * @param timestamp - The timestamp to use.\n * @param nonce - The nonce to use.\n * @param secretKey - The secret key to use.\n * @returns The HMAC token.\n */\nexport function createHmacToken({\n method,\n path,\n body,\n timestamp,\n nonce,\n secretKey\n}: {\n method: string;\n path: string;\n body?: unknown;\n timestamp: Date;\n nonce: string;\n secretKey: string;\n}) {\n const hmac = createHmac('sha256', secretKey);\n // Buffers and strings are treated as the verbatim request bytes (the\n // content parser captures them on req._rawBody); anything else is signed\n // over its canonical stringification. A client that signs an object and\n // sends its stringification as the wire body therefore verifies cleanly\n // against the server's captured raw bytes.\n const bodyString = body\n ? `${\n Buffer.isBuffer(body)\n ? body.toString('utf8')\n : typeof body === 'string'\n ? body\n : safeStringify(body)\n }\\n`\n : undefined;\n hmac.update(\n `${method}\\n${path}\\n${bodyString}${timestamp.toISOString()}\\n${nonce}`\n );\n return hmac.digest('base64');\n}\n","import { BasicAuthMethods } from '../types/contractDetails.types';\n\nexport function isBasicAuthMethod(\n maybeBasicAuthMethod: unknown\n): maybeBasicAuthMethod is BasicAuthMethods {\n return (\n typeof maybeBasicAuthMethod === 'object' &&\n maybeBasicAuthMethod !== null &&\n 'basic' in maybeBasicAuthMethod &&\n maybeBasicAuthMethod.basic != null\n );\n}\n","import { JwtAuthMethods } from '../types/contractDetails.types';\n\nexport function isJwtAuthMethod(\n maybeJwtAuthMethod: unknown\n): maybeJwtAuthMethod is JwtAuthMethods {\n return (\n typeof maybeJwtAuthMethod === 'object' &&\n maybeJwtAuthMethod !== null &&\n 'jwt' in maybeJwtAuthMethod &&\n maybeJwtAuthMethod.jwt != null\n );\n}\n","export function hasFeatureChecks(maybeFeatureAuth: unknown) {\n return (\n typeof maybeFeatureAuth === 'object' &&\n maybeFeatureAuth !== null &&\n 'requiredFeatures' in maybeFeatureAuth &&\n Array.isArray(maybeFeatureAuth.requiredFeatures) &&\n maybeFeatureAuth.requiredFeatures.length > 0\n );\n}\n","export function hasSubscriptionChecks(maybeSubscriptionAuth: unknown) {\n return (\n typeof maybeSubscriptionAuth === 'object' &&\n maybeSubscriptionAuth !== null &&\n 'requireActiveSubscription' in maybeSubscriptionAuth &&\n maybeSubscriptionAuth.requireActiveSubscription === true\n );\n}\n","import { createHash } from 'crypto';\nimport { decodeJwt, decodeProtectedHeader, errors as joseErrors } from 'jose';\n\n/**\n * What an authorization failure log line may carry about the credential.\n *\n * Never the credential itself. A bearer token is usable until it expires\n * and a Basic header is a password, so neither belongs in a log stream that\n * outlives the request. What support actually needs is why it failed, who\n * it claimed to be, and a way to tell two failures from one caller apart.\n */\nexport type AuthLogContext = {\n /** Whether an Authorization value was present at all. */\n hasToken: boolean;\n /**\n * First 8 hex chars of sha256(header value). Correlates retries of one\n * token and lets a caller match a token they hold against a log line\n * without the log holding the token. Not reversible.\n */\n tokenFingerprint?: string;\n /**\n * Decoded, NOT verified, JWT claims. On a failed verification these are\n * whatever the caller wrote, so they are labelled claimed rather than\n * user and must never be treated as identity. `email` is left out on\n * purpose: `sub` identifies the account without putting PII in logs.\n */\n claimed?: {\n sub?: string;\n organizationId?: string;\n iss?: string;\n exp?: number;\n kid?: string;\n };\n};\n\nconst FINGERPRINT_LENGTH = 8;\nconst MAX_CLAIM_LENGTH = 128;\n\nfunction bounded(value: unknown): string | undefined {\n return typeof value === 'string' && value.length > 0\n ? value.slice(0, MAX_CLAIM_LENGTH)\n : undefined;\n}\n\n/**\n * Builds the loggable context for an Authorization header value. Accepts\n * the full header value (`Bearer eyJ…`, `Basic …`, `HMAC …`) or a bare\n * token; JWT claims are only attempted when the value looks like a JWT.\n */\nexport function authLogContext(headerValue: unknown): AuthLogContext {\n if (typeof headerValue !== 'string' || headerValue.length === 0) {\n return { hasToken: false };\n }\n\n const context: AuthLogContext = {\n hasToken: true,\n tokenFingerprint: createHash('sha256')\n .update(headerValue)\n .digest('hex')\n .slice(0, FINGERPRINT_LENGTH)\n };\n\n const parts = headerValue.trim().split(/\\s+/);\n const candidate = parts[parts.length - 1];\n if (candidate.split('.').length !== 3) {\n return context;\n }\n\n try {\n const payload = decodeJwt(candidate);\n const header = decodeProtectedHeader(candidate);\n context.claimed = {\n sub: bounded(payload.sub),\n organizationId: bounded(payload.organizationId),\n iss: bounded(payload.iss),\n exp: typeof payload.exp === 'number' ? payload.exp : undefined,\n kid: bounded(header.kid)\n };\n } catch {\n // Not a decodable JWT; the fingerprint is all we can offer.\n }\n\n return context;\n}\n\n/**\n * A stable, short reason for a JWT verification failure, derived from the\n * jose error class. This is the field that was missing from the logs: an\n * expired token and a forged one used to produce identical lines.\n */\nexport function jwtFailureReason(error: unknown): string {\n if (error instanceof joseErrors.JWTExpired) return 'jwt_expired';\n if (error instanceof joseErrors.JWTClaimValidationFailed) {\n return `jwt_claim_${error.claim}`;\n }\n if (error instanceof joseErrors.JWSSignatureVerificationFailed) {\n return 'jwt_bad_signature';\n }\n if (error instanceof joseErrors.JWKSNoMatchingKey) return 'jwks_no_key';\n if (error instanceof joseErrors.JWKSTimeout) return 'jwks_unavailable';\n if (\n error instanceof joseErrors.JWTInvalid ||\n error instanceof joseErrors.JWSInvalid\n ) {\n return 'jwt_malformed';\n }\n if (error instanceof joseErrors.JOSEError) return error.code.toLowerCase();\n return 'unknown';\n}\n","import { getEnvVar } from '@forklaunch/common';\nimport { AnySchemaValidator } from '@forklaunch/validator';\nimport {\n ATTR_API_NAME,\n ATTR_APPLICATION_ID,\n ATTR_HTTP_REQUEST_METHOD,\n ATTR_HTTP_RESPONSE_STATUS_CODE,\n ATTR_HTTP_ROUTE,\n ATTR_SERVICE_NAME\n} from '../../telemetry/constants';\nimport {\n httpServerDurationHistogram,\n OpenTelemetryCollector\n} from '../../telemetry/openTelemetryCollector';\nimport {\n ExpressLikeSchemaHandler,\n ForklaunchNextFunction\n} from '../../types/apiDefinition.types';\nimport {\n Body,\n HeadersObject,\n HttpContractDetails,\n Method,\n ParamsObject,\n PathParamHttpContractDetails,\n QueryObject,\n ResponseCompiledSchema,\n ResponsesObject,\n SessionObject,\n VersionSchema\n} from '../../types/contractDetails.types';\nimport {\n auditComplianceAccess,\n recordRequestAudit\n} from '../../telemetry/requestAudit';\nimport { ExpressLikeRouterOptions } from '../../types/expressLikeOptions';\nimport { MetricsDefinition } from '../../types/openTelemetryCollector.types';\n\n/**\n * Middleware to enrich the request details with contract details.\n *\n * @template SV - A type that extends AnySchemaValidator.\n * @template Request - A type that extends ForklaunchRequest.\n * @template Response - A type that extends ForklaunchResponse.\n * @template NextFunction - A type that extends ForklaunchNextFunction.\n * @param {PathParamHttpContractDetails<SV> | HttpContractDetails<SV>} contractDetails - The contract details.\n * @returns {Function} - Middleware function to enrich request details.\n */\nexport function enrichDetails<\n SV extends AnySchemaValidator,\n ContractMethod extends Method,\n P extends ParamsObject<SV>,\n ResBodyMap extends ResponsesObject<SV>,\n ReqBody extends Body<SV>,\n ReqQuery extends QueryObject<SV>,\n ReqHeaders extends HeadersObject<SV>,\n ResHeaders extends HeadersObject<SV>,\n LocalsObj extends Record<string, unknown>,\n VersionedApi extends VersionSchema<SV, ContractMethod>,\n SessionSchema extends SessionObject<SV>\n>(\n path: string,\n contractDetails: HttpContractDetails<SV> | PathParamHttpContractDetails<SV>,\n requestSchema: unknown | Record<string, unknown>,\n responseSchemas:\n ResponseCompiledSchema | Record<string, ResponseCompiledSchema>,\n openTelemetryCollector?: OpenTelemetryCollector<MetricsDefinition>,\n globalOptions?: () => ExpressLikeRouterOptions<SV, SessionSchema> | undefined\n): ExpressLikeSchemaHandler<\n SV,\n P,\n ResBodyMap,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n ResHeaders,\n LocalsObj,\n VersionedApi,\n SessionSchema,\n unknown,\n unknown,\n ForklaunchNextFunction\n> {\n return (req, res, next?) => {\n req.originalPath = path;\n req.contractDetails = contractDetails;\n req.requestSchema = requestSchema;\n res.responseSchemas = responseSchemas;\n req.openTelemetryCollector = openTelemetryCollector;\n req._globalOptions = globalOptions ?? (() => undefined);\n\n req.context?.span?.setAttribute(ATTR_API_NAME, req.contractDetails?.name);\n const startTime = process.hrtime();\n if (openTelemetryCollector) auditComplianceAccess(openTelemetryCollector);\n\n res.on('finish', () => {\n // The default audit trail: one record per request, including refused ones.\n const [auditSeconds, auditNanoseconds] = process.hrtime(startTime);\n recordRequestAudit(\n openTelemetryCollector,\n req,\n Number(res.statusCode),\n auditSeconds * 1000 + auditNanoseconds / 1_000_000\n );\n const [seconds, nanoseconds] = process.hrtime(startTime);\n const durationMs = seconds + nanoseconds / 1000000000;\n\n httpServerDurationHistogram.record(durationMs, {\n [ATTR_SERVICE_NAME]: getEnvVar('OTEL_SERVICE_NAME') || 'unknown',\n [ATTR_APPLICATION_ID]: getEnvVar('OTEL_APPLICATION_ID'),\n [ATTR_API_NAME]: req.contractDetails?.name || 'unknown',\n [ATTR_HTTP_REQUEST_METHOD]: req.method,\n [ATTR_HTTP_ROUTE]: req.originalPath || 'unknown',\n [ATTR_HTTP_RESPONSE_STATUS_CODE]: Number(res.statusCode)\n });\n });\n\n next?.();\n };\n}\n","import { getEnvVar } from '@forklaunch/common';\nimport { onComplianceChange } from '../../persistence/complianceChanges';\nimport { onComplianceAccess } from '../../persistence/compliantField';\nimport { MetricsDefinition } from '../types/openTelemetryCollector.types';\nimport { AuditEntry, AuditLogger } from './auditLogger';\nimport { OpenTelemetryCollector } from './openTelemetryCollector';\n\n/**\n * Default audit trail for every app built on ForkLaunch: one audit record per\n * request (who, tenant, method, route, status, duration and a hash of the\n * body, never its content) and one per read of a compliant field's plaintext.\n * Records carry `log.type: audit` so the platform can keep them apart from\n * application logs. On unless FORKLAUNCH_AUDIT=off.\n */\nexport function auditEnabled(): boolean {\n return getEnvVar('FORKLAUNCH_AUDIT') !== 'off';\n}\n\nconst loggers = new WeakMap<object, AuditLogger>();\nfunction loggerFor(otel: OpenTelemetryCollector<MetricsDefinition>) {\n let logger = loggers.get(otel);\n if (!logger) {\n logger = new AuditLogger(otel);\n loggers.set(otel, logger);\n }\n return logger;\n}\n\n/** The audit event a response status stands for. */\nexport function auditEventType(status: number): AuditEntry['eventType'] {\n if (status === 401) return 'auth_failure';\n if (status === 403) return 'rbac_deny';\n if (status === 429) return 'rate_limit';\n return 'http';\n}\n\nconst text = (value: unknown) =>\n typeof value === 'string' && value ? value : null;\n\nfunction bodyText(body: unknown): string | undefined {\n if (body == null || body === '') return undefined;\n if (typeof body === 'string' || Buffer.isBuffer(body)) return String(body);\n try {\n return JSON.stringify(body);\n } catch {\n return undefined;\n }\n}\n\n/** Append the audit record for one finished request. */\nexport function recordRequestAudit(\n otel: OpenTelemetryCollector<MetricsDefinition> | undefined,\n req: {\n method: string;\n originalPath?: string;\n path?: string;\n session?: unknown;\n body?: unknown;\n },\n status: number,\n durationMs: number\n): void {\n if (!otel || !auditEnabled()) return;\n const session =\n req.session && typeof req.session === 'object'\n ? (req.session as Record<string, unknown>)\n : undefined;\n loggerFor(otel).append({\n timestamp: new Date().toISOString(),\n userId: text(session?.sub) ?? text(session?.userId),\n tenantId:\n text(session?.activeOrganizationId) ?? text(session?.organizationId),\n route: req.originalPath ?? req.path ?? 'unknown',\n method: req.method,\n bodyHash: AuditLogger.hashBody(bodyText(req.body)),\n status,\n duration: Math.max(0, Math.round(durationMs)),\n redactedFields: [],\n eventType: auditEventType(status)\n });\n}\n\nlet accessAudit: (() => void) | undefined;\n\n/**\n * Every `.deanon` read of a compliant field becomes an audit record (field,\n * level, tenant), and every create/update/delete of a record holding sensitive\n * fields a `data_change` record (entity#id, action, sensitive field names). It is emitted inside the request's trace, which ties it to\n * the request's own audit record and so to the user. Registered once per\n * process; returns a function that removes it.\n */\nexport function auditComplianceAccess(\n otel: OpenTelemetryCollector<MetricsDefinition>\n): () => void {\n if (!accessAudit && auditEnabled()) {\n const logger = loggerFor(otel);\n const remove = onComplianceAccess((event) =>\n logger.append({\n timestamp: new Date().toISOString(),\n userId: null,\n tenantId: event.tenantId || null,\n route: event.field,\n method: 'READ',\n bodyHash: '',\n status: 0,\n duration: 0,\n redactedFields: [event.field],\n eventType: 'data_access'\n })\n );\n const removeChanges = onComplianceChange((event) =>\n logger.append({\n timestamp: new Date().toISOString(),\n userId: null,\n tenantId: event.tenantId,\n route: `${event.entity}#${event.id}`,\n method: event.action.toUpperCase(),\n bodyHash: '',\n status: 0,\n duration: 0,\n redactedFields: event.sensitiveFields,\n eventType: 'data_change'\n })\n );\n accessAudit = () => {\n remove();\n removeChanges();\n accessAudit = undefined;\n };\n }\n return accessAudit ?? (() => undefined);\n}\n","import { Type, type Platform, type TransformContext } from '@mikro-orm/core';\nimport { AsyncLocalStorage } from 'node:async_hooks';\nimport type { FieldEncryptor } from './fieldEncryptor';\n\nconst ENCRYPTED_PREFIXES = ['v1:', 'v2:', 'v3:'] as const;\n\nfunction isEncrypted(value: string): boolean {\n return ENCRYPTED_PREFIXES.some((p) => value.startsWith(p));\n}\n\n// ---------------------------------------------------------------------------\n// Module-level state\n// ---------------------------------------------------------------------------\n\nlet _encryptor: FieldEncryptor | undefined;\n\n/**\n * AsyncLocalStorage for the current tenant ID. This is set automatically\n * by `withEncryptionContext()` — users don't interact with it directly.\n */\nconst _tenantContext = new AsyncLocalStorage<{ tenantId: string }>();\n\n/**\n * Register the FieldEncryptor instance for use by EncryptedType.\n * Call this once at application bootstrap (e.g., in mikro-orm.config.ts).\n */\nexport function registerEncryptor(encryptor: FieldEncryptor): void {\n _encryptor = encryptor;\n}\n\n/** The encryptor registered with {@link registerEncryptor}, if any. */\nexport function getRegisteredEncryptor(): FieldEncryptor | undefined {\n return _encryptor;\n}\n\n/**\n * The empty string was offered as a tenant id.\n *\n * `''` used to mean \"the global tenant\", which made it impossible to tell a\n * deliberate global row from a tenant that was never resolved — the two are\n * the same key. Rows written by mistake under `''` read back fine from any\n * other unbound path and fail only when a correctly-bound caller finally\n * touches them, arbitrarily far from the code that caused it.\n *\n * Global rows need a tenant id you can name and search for — a constant like\n * `'_internal'` that no organization can collide with. Pick one and pass it.\n */\nexport class EmptyTenantError extends Error {\n constructor(api: string) {\n super(\n `${api}: '' is not a tenant id. It used to mean \"global\", which made a ` +\n `deliberate global row indistinguishable from a tenant nobody resolved. ` +\n `Bind an explicit constant (for example '_internal') for rows that ` +\n `genuinely belong to no organization.`\n );\n this.name = 'EmptyTenantError';\n }\n}\n\n/**\n * An encrypted column was read or written with no tenant bound.\n *\n * This is the failure the empty tenant used to hide. An unbound write\n * encrypted under `''` and looked like it worked; the row then failed to\n * decrypt for the tenant that owned it, and the stack trace pointed at the\n * innocent reader. Failing here names the actual culprit: the write path\n * that never bound a tenant.\n *\n * Bind one with `wrapEmWithTenantContext(em, tenantId)` in the DI\n * `EntityManager` factory, or `withEncryptionContext(tenantId, fn)` around\n * the work. A raw manager — `orm.em.fork()`, or the `__em` off a wrapped\n * entity — escapes the proxy and arrives here unbound.\n */\nexport class UnboundTenantError extends Error {\n constructor(operation: string) {\n super(\n `Cannot ${operation} an encrypted column with no tenant bound. Wrap the ` +\n `work in withEncryptionContext(tenantId, fn), or take the entity ` +\n `manager from a factory that calls wrapEmWithTenantContext. A raw ` +\n `em.fork() (or wrap(entity).__em) escapes the tenant proxy.`\n );\n this.name = 'UnboundTenantError';\n }\n}\n\n/**\n * Reject `''` at every door that binds a tenant.\n *\n * Exported so the binding helpers in this package share one rule, and so an\n * application's own factory can apply the same one at its own boundary.\n */\nexport function assertBindableTenantId(\n tenantId: string,\n api: string\n): asserts tenantId is string {\n if (tenantId === '') {\n throw new EmptyTenantError(api);\n }\n}\n\n/**\n * Set the encryption tenant ID for the current async context.\n *\n * IMPORTANT: this uses `AsyncLocalStorage.enterWith`, which mutates the\n * current async resource's store. It does NOT reliably propagate through\n * `pg` connection pool callback async resources — pooled connections are\n * long-lived async resources created at pool init, and resumption\n * callbacks run in the pool's resource, not the caller's. As a result,\n * MikroORM hydration of encrypted columns can read an empty / wrong\n * tenant id from `getCurrentTenantId()` even when this was called\n * correctly at the start of the request.\n *\n * Prefer `withEncryptionContext(tenantId, fn)` (or the\n * `wrapEmWithTenantContext` helper) for any code path that hits the\n * database. `setEncryptionTenantId` remains useful as a best-effort seed\n * for purely synchronous code paths.\n */\nexport function setEncryptionTenantId(tenantId: string): void {\n assertBindableTenantId(tenantId, 'setEncryptionTenantId');\n _tenantContext.enterWith({ tenantId });\n}\n\n/**\n * Run `fn` inside a fresh AsyncLocalStorage scope bound to `tenantId`.\n *\n * Unlike `setEncryptionTenantId`, this uses `AsyncLocalStorage.run`, which\n * creates a new async resource bound to the store. Node's promise hooks\n * propagate the store forward through pool callback async resources, so\n * MikroORM hydration of encrypted columns inside `fn` (even after multiple\n * awaits and a pg pool roundtrip) sees the correct tenant id.\n *\n * Most application code should not call this directly — use\n * `wrapEmWithTenantContext(em, tenantId)` in your DI EntityManager\n * factory and every method on the returned EM will be wrapped\n * automatically.\n */\nexport function withEncryptionContext<T>(tenantId: string, fn: () => T): T {\n assertBindableTenantId(tenantId, 'withEncryptionContext');\n return _tenantContext.run({ tenantId }, fn);\n}\n\n/**\n * Get the current tenant ID, or the empty string when none is bound.\n *\n * @deprecated The empty string it returns when nothing is bound is the whole\n * problem: \"no tenant\" and \"the global tenant\" became the same value, so an\n * unbound write encrypted under `''` and surfaced as somebody else's decrypt\n * failure. Encryption no longer reads through this — it uses the bound tenant\n * and throws {@link UnboundTenantError} when there is none. Use\n * {@link getBoundTenantId} and handle `undefined` explicitly.\n */\nexport function getCurrentTenantId(): string {\n return _tenantContext.getStore()?.tenantId ?? '';\n}\n\n/**\n * The tenant bound to the current async context, or `undefined` if none is.\n *\n * The distinction {@link getCurrentTenantId} cannot make: `undefined` is\n * \"nobody bound a tenant\", which is a bug on any path that touches an\n * encrypted column, and never a key.\n */\nexport function getBoundTenantId(): string | undefined {\n return _tenantContext.getStore()?.tenantId;\n}\n\n/** The bound tenant, or {@link UnboundTenantError} naming what was attempted. */\nexport function requireBoundTenantId(operation: string): string {\n const tenantId = _tenantContext.getStore()?.tenantId;\n if (tenantId === undefined || tenantId === '') {\n throw new UnboundTenantError(operation);\n }\n return tenantId;\n}\n\n// ---------------------------------------------------------------------------\n// Type resolution helpers\n// ---------------------------------------------------------------------------\n\n/**\n * Resolve a MikroORM type value (string, constructor, or instance) to a\n * Type instance. Returns undefined if unresolvable.\n */\nexport function resolveTypeInstance(\n type: unknown\n): Type<unknown, unknown> | undefined {\n if (type instanceof Type) return type;\n if (typeof type === 'function') {\n try {\n const inst = new (type as new () => unknown)();\n return inst instanceof Type ? inst : undefined;\n } catch {\n return undefined;\n }\n }\n return undefined;\n}\n\n/**\n * Hydrate a raw value (after JSON.parse or string) to the JS type\n * indicated by `runtimeType`. This covers the cases where MikroORM's\n * own convertToJSValue is a NOOP (relies on the DB driver).\n */\nfunction hydrateValue(value: unknown, runtimeType: string): unknown {\n if (value === null || value === undefined) return value;\n switch (runtimeType) {\n case 'string':\n return typeof value === 'string' ? value : String(value);\n case 'number':\n return typeof value === 'number' ? value : Number(value);\n case 'boolean':\n return typeof value === 'boolean'\n ? value\n : typeof value === 'string'\n ? value === 'true'\n : Boolean(value);\n case 'Date':\n return value instanceof Date ? value : new Date(value as string | number);\n case 'bigint':\n return typeof value === 'bigint' ? value : BigInt(value as string);\n case 'Buffer':\n return Buffer.isBuffer(value)\n ? value\n : typeof value === 'string'\n ? Buffer.from(value, 'base64')\n : Buffer.from(value as Uint8Array);\n case 'any': // json — return as-is after JSON.parse\n default:\n return value;\n }\n}\n\n// ---------------------------------------------------------------------------\n// EncryptedType\n// ---------------------------------------------------------------------------\n\n/**\n * MikroORM custom Type that transparently encrypts/decrypts values.\n *\n * Works with any JS type. Non-string values are serialized before\n * encryption and hydrated after decryption using the original Type's\n * runtimeType for correct JS type reconstruction.\n *\n * DB column is always `text` — the encrypted ciphertext is a string\n * regardless of the original JS type.\n *\n * For array container types, the element type is tracked separately\n * so each element is hydrated individually after decryption.\n */\nexport class EncryptedType extends Type<unknown, string | null> {\n // NOTE: Using regular properties instead of #private fields to avoid\n // \"Cannot read private member\" errors when multiple copies of this class\n // are loaded (dual-package hazard with CJS/ESM or duplicate node_modules).\n readonly _elementRuntimeType: string;\n readonly _isArray: boolean;\n readonly _enumValues: unknown[] | undefined;\n\n /**\n * @param elementRuntimeType - The runtimeType of the (element) type,\n * e.g. 'string', 'number', 'Date', 'bigint', 'Buffer', 'any'.\n * @param isArray - Whether this is an array container type.\n * @param enumValues - Optional list of allowed enum values for app-level\n * validation (used when an enum field has encrypted compliance).\n */\n constructor(\n elementRuntimeType: string = 'string',\n isArray: boolean = false,\n enumValues?: unknown[]\n ) {\n super();\n this._elementRuntimeType = elementRuntimeType;\n this._isArray = isArray;\n this._enumValues = enumValues;\n }\n\n override convertToDatabaseValue(\n value: unknown,\n _platform: Platform,\n _context?: TransformContext\n ): string | null {\n if (value === null || value === undefined) return null;\n if (typeof value === 'string' && value.length === 0) return '';\n\n // Validate enum values at app level before encryption replaces them\n // with ciphertext that would never pass a DB check constraint.\n if (this._enumValues) {\n const valuesToCheck =\n this._isArray && Array.isArray(value) ? value : [value];\n for (const v of valuesToCheck) {\n if (!this._enumValues.includes(v)) {\n throw new Error(\n `Invalid enum value: ${String(v)}. Allowed values: ${this._enumValues.join(', ')}`\n );\n }\n }\n }\n\n if (!_encryptor) {\n return this.serialize(value);\n }\n\n if (typeof value === 'string' && isEncrypted(value)) {\n return value;\n }\n\n const serialized = this.serialize(value);\n // Also the WHERE-clause path: a query value is encrypted under the bound\n // tenant before it is compared. Unbound, that used to produce ciphertext\n // under `''` which simply matched nothing — a silent empty result set,\n // not an error.\n return (\n _encryptor.encrypt(serialized, requireBoundTenantId('write')) ??\n serialized\n );\n }\n\n override convertToJSValue(\n value: string | null,\n _platform: Platform\n ): unknown {\n if (value === null || value === undefined) return null;\n if (typeof value !== 'string') return value;\n\n if (!isEncrypted(value)) {\n return this.deserialize(value);\n }\n\n if (!_encryptor) {\n throw new Error(\n 'EncryptedType: no encryptor registered but database contains encrypted value. ' +\n 'Call registerEncryptor() at application bootstrap.'\n );\n }\n\n let decrypted: string | null;\n const tenantId = requireBoundTenantId('read');\n try {\n decrypted = _encryptor.decrypt(value, tenantId);\n } catch (err) {\n throw new Error(\n `Failed to decrypt encrypted column value: ${err instanceof Error ? err.message : String(err)}`,\n { cause: err }\n );\n }\n if (decrypted === null) return null;\n return this.deserialize(decrypted);\n }\n\n override getColumnType(): string {\n return 'text';\n }\n\n override get runtimeType(): string {\n if (this._isArray) return 'object';\n return this._elementRuntimeType;\n }\n\n override ensureComparable(): boolean {\n return false;\n }\n\n // ---------------------------------------------------------------------------\n // Serialization helpers\n // ---------------------------------------------------------------------------\n\n private serialize(value: unknown): string {\n return serializeForEncryption(value);\n }\n\n private deserialize(value: string): unknown {\n return deserializeFromEncryption(\n value,\n this._elementRuntimeType,\n this._isArray\n );\n }\n}\n\n// ---------------------------------------------------------------------------\n// Serialization shared with compliant fields\n// ---------------------------------------------------------------------------\n\n/** Turn any supported JS value into the string that gets encrypted. */\nexport function serializeForEncryption(value: unknown): string {\n if (typeof value === 'string') return value;\n if (value instanceof Date) return value.toISOString();\n if (typeof value === 'bigint') return value.toString();\n if (Buffer.isBuffer(value) || value instanceof Uint8Array)\n return Buffer.from(value as Uint8Array).toString('base64');\n return JSON.stringify(value);\n}\n\nfunction tryJsonParse(value: string): unknown {\n try {\n return JSON.parse(value);\n } catch {\n return value;\n }\n}\n\n/** Inverse of {@link serializeForEncryption}, given the property's runtime type. */\nexport function deserializeFromEncryption(\n value: string,\n elementRuntimeType: string,\n isArray: boolean\n): unknown {\n if (isArray) {\n try {\n const arr = JSON.parse(value);\n if (!Array.isArray(arr)) return arr;\n return arr.map((el: unknown) => hydrateValue(el, elementRuntimeType));\n } catch {\n return value;\n }\n }\n\n switch (elementRuntimeType) {\n case 'string':\n return value;\n case 'any':\n return tryJsonParse(value);\n // Types serialized via toString/toISOString/base64 — hydrate from string directly\n case 'bigint':\n case 'Date':\n case 'Buffer':\n return hydrateValue(value, elementRuntimeType);\n // Types where JSON.parse recovers the native JS value (number, boolean)\n default:\n return hydrateValue(tryJsonParse(value), elementRuntimeType);\n }\n}\n","import type { EntitySchema, EventArgs } from '@mikro-orm/core';\nimport type { ComplianceLevel } from './complianceTypes';\nimport { getBoundTenantId } from './encryptedType';\n\n/**\n * Emitted after a record of an entity holding pii, phi or pci fields is\n * created, updated or deleted. Carries field names, never values.\n */\nexport interface ComplianceChangeEvent {\n entity: string;\n /** Primary key, colon-joined for composite keys. */\n id: string;\n action: 'create' | 'update' | 'delete';\n /** Fields written (create: every field set; update: the changed ones). */\n fields: string[];\n /** The sensitive fields among them. */\n sensitiveFields: string[];\n tenantId: string | null;\n}\n\nexport type ComplianceChangeListener = (event: ComplianceChangeEvent) => void;\n\nconst LISTENERS: Set<ComplianceChangeListener> = ((\n globalThis as Record<symbol, unknown>\n)[Symbol.for('forklaunch.compliance.changeListeners')] ??=\n new Set()) as Set<ComplianceChangeListener>;\n\n/**\n * Register a listener for every change to a sensitive record, for audit\n * trails. Returns a function that removes it.\n */\nexport function onComplianceChange(\n listener: ComplianceChangeListener\n): () => void {\n LISTENERS.add(listener);\n return () => LISTENERS.delete(listener);\n}\n\nfunction emit(event: ComplianceChangeEvent) {\n for (const listener of LISTENERS) {\n try {\n listener(event);\n } catch (error) {\n // An audit sink failing must never fail the write that already happened.\n console.error('Compliance change listener failed:', error);\n }\n }\n}\n\n/**\n * Attach create/update/delete hooks to an entity schema that holds sensitive\n * fields, so every change to one of its records is reported without the app\n * wiring anything.\n */\nexport function installComplianceChangeHooks(\n schema: EntitySchema,\n entityName: string,\n levels: Map<string, ComplianceLevel>\n): void {\n const sensitive = new Set(\n [...levels].filter(([, level]) => level !== 'none').map(([name]) => name)\n );\n if (!sensitive.size) return;\n const report =\n (action: ComplianceChangeEvent['action']) =>\n (args: EventArgs<Record<string, unknown>>) => {\n if (!LISTENERS.size) return;\n const entity = args.entity as Record<string, unknown>;\n const keys = args.meta?.primaryKeys ?? ['id'];\n const fields =\n action === 'update'\n ? Object.keys(args.changeSet?.payload ?? {})\n : action === 'create'\n ? [...levels.keys()].filter((name) => entity[name] !== undefined)\n : [];\n emit({\n entity: entityName,\n id: keys.map((key) => String(entity[key] ?? '')).join(':'),\n action,\n fields,\n sensitiveFields:\n action === 'delete'\n ? [...sensitive]\n : fields.filter((name) => sensitive.has(name)),\n tenantId: getBoundTenantId() ?? null\n });\n };\n schema.addHook('afterCreate', report('create'));\n schema.addHook('afterUpdate', report('update'));\n schema.addHook('afterDelete', report('delete'));\n}\n","import crypto from 'crypto';\nimport {\n Type,\n type Platform,\n type PrimaryKeyProp,\n type TransformContext\n} from '@mikro-orm/core';\nimport type { EncryptedComplianceLevel } from './complianceTypes';\nimport {\n deserializeFromEncryption,\n getBoundTenantId,\n getRegisteredEncryptor,\n requireBoundTenantId,\n serializeForEncryption\n} from './encryptedType';\nimport {\n EncryptionRequiredError,\n isEncryptedCiphertext,\n sealedAnon\n} from './fieldEncryptor';\n\n// ---------------------------------------------------------------------------\n// Options\n// ---------------------------------------------------------------------------\n\n/**\n * How a field's `.anon` value is derived. Shaped after the HIPAA Safe Harbor\n * identifiers: identifiers become random tokens, dates keep the year, ZIP\n * codes keep three digits (or `000` for sparsely populated areas), card\n * numbers keep the last four, everything else is redacted.\n */\nexport type AnonStrategy = 'token' | 'year' | 'zip3' | 'last4' | 'redact';\n\n/** Options accepted by `.compliance(level, options)` for pii, phi and pci. */\nexport interface ComplianceOptions {\n /**\n * How `.anon` is derived. Defaults to `token` for strings, `year` for\n * dates and `redact` for everything else.\n */\n readonly anon?: AnonStrategy;\n /**\n * Allow equality lookups (`where: { field: value }`, `$in`, `$ne`, `$nin`).\n * Adds a `<column>_idx` blind-index column (keyed HMAC) that the query is\n * matched against; the ciphertext stays in the original column.\n */\n readonly queryable?: boolean;\n /**\n * How values are normalized before indexing. `exact` (default) matches\n * byte for byte; `lowercase` trims and lowercases strings first (emails).\n */\n readonly normalize?: 'exact' | 'lowercase';\n}\n\n/** @internal what a compliant column type knows about its property. */\nexport interface CompliantFieldSpec {\n level: EncryptedComplianceLevel;\n anon: AnonStrategy;\n queryable: boolean;\n normalize: 'exact' | 'lowercase';\n elementRuntimeType: string;\n isArray: boolean;\n enumValues?: readonly unknown[];\n /** `Entity.property`, filled in by defineComplianceEntity. */\n path: string;\n}\n\n// ---------------------------------------------------------------------------\n// Access listeners\n// ---------------------------------------------------------------------------\n\n/** Emitted every time a compliant field's plaintext is read via `.deanon`. */\nexport interface ComplianceAccessEvent {\n /** `Entity.property` */\n field: string;\n level: EncryptedComplianceLevel;\n tenantId: string;\n}\n\nexport type ComplianceAccessListener = (event: ComplianceAccessEvent) => void;\n\nconst LISTENERS: Set<ComplianceAccessListener> = ((\n globalThis as Record<symbol, unknown>\n)[Symbol.for('forklaunch.compliance.listeners')] ??=\n new Set()) as Set<ComplianceAccessListener>;\n\n/**\n * Register a listener for every `.deanon` read, for access audit logs.\n * Returns a function that removes it.\n */\nexport function onComplianceAccess(\n listener: ComplianceAccessListener\n): () => void {\n LISTENERS.add(listener);\n return () => LISTENERS.delete(listener);\n}\n\n// ---------------------------------------------------------------------------\n// Errors\n// ---------------------------------------------------------------------------\n\n/**\n * Thrown by `.anon` on a value still stored in a pre-v4 envelope under a\n * `token` strategy: there is no stored token yet, and one must never be\n * derived from the value. Run `reencryptEncryptedColumns` once to upgrade.\n */\nexport class LegacyCiphertextError extends Error {\n readonly name = 'LegacyCiphertextError' as const;\n}\n\n/** Thrown when a query targets a compliant field in a way it cannot answer. */\nexport class CompliantQueryError extends Error {\n readonly name = 'CompliantQueryError' as const;\n}\n\n/**\n * Thrown when a compliant field is read or written while a tenant other than\n * the one that owns it is bound.\n *\n * A field belongs to the tenant it was loaded under (or, for a value assigned\n * in-process, the tenant bound when it was assigned), and `.deanon` decrypts\n * with that tenant's key whatever context is bound at read time. A different\n * bound tenant means the value is about to cross into another tenant's\n * request, so it is refused rather than revealed or re-sealed.\n */\nexport class TenantMismatchError extends Error {\n readonly name = 'TenantMismatchError' as const;\n constructor(\n readonly path: string,\n readonly operation: string,\n readonly ownerTenantId: string,\n readonly boundTenantId: string\n ) {\n super(\n `Cannot ${operation} ${path || 'a compliant field'} under tenant '${boundTenantId}': ` +\n `it belongs to tenant '${ownerTenantId}', the tenant it was loaded or assigned under. ` +\n `Read it outside any encryption context, or inside the owning tenant's.`\n );\n }\n}\n\n// ---------------------------------------------------------------------------\n// Anon\n// ---------------------------------------------------------------------------\n\nconst MINT = Symbol.for('forklaunch.compliance.mint');\nconst ANON_BRAND = Symbol.for('forklaunch.compliance.anon');\n\n/**\n * A de-identified value, produced only by a compliant field's `.anon`.\n * Anything that must never carry protected data (a message to a provider\n * without a BAA, a log line, an analytics event) can require this type and\n * check it at runtime with {@link isAnon}; a plain string cannot pass.\n */\nexport class Anon {\n readonly value!: string;\n\n /** @internal */\n constructor(value: string, key: symbol) {\n if (key !== MINT) {\n throw new Error('Anon values can only be produced by a compliant field');\n }\n Object.defineProperty(this, ANON_BRAND, { value: true });\n Object.defineProperty(this, 'value', { value, enumerable: true });\n Object.freeze(this);\n }\n}\n\n/** True for values produced by `.anon` (works across duplicate package copies). */\nexport function isAnon(value: unknown): value is Anon {\n return (\n value != null &&\n typeof value === 'object' &&\n (value as Record<symbol, unknown>)[ANON_BRAND] === true\n );\n}\n\n// Safe Harbor: three-digit ZIP prefixes covering 20,000 or fewer people must\n// be replaced with 000 (HHS de-identification guidance, 2000 Census list).\nconst RESTRICTED_ZIP3 = new Set([\n '036',\n '059',\n '063',\n '102',\n '203',\n '556',\n '692',\n '790',\n '821',\n '823',\n '830',\n '831',\n '878',\n '879',\n '884',\n '890',\n '893'\n]);\n\nconst REDACTED = '[redacted]';\n\n/** @internal */\nexport function computeAnon(strategy: AnonStrategy, value: unknown): string {\n switch (strategy) {\n case 'token':\n // Random, never derived from the value: Safe Harbor forbids\n // re-identification codes computed from the individual's data.\n return 'tok_' + crypto.randomBytes(9).toString('base64url');\n case 'year': {\n if (value instanceof Date && !isNaN(value.getTime()))\n return String(value.getUTCFullYear());\n const match = /\\d{4}/.exec(String(value));\n return match ? match[0] : REDACTED;\n }\n case 'zip3': {\n const digits = String(value).replace(/\\D/g, '').slice(0, 3);\n if (digits.length < 3 || RESTRICTED_ZIP3.has(digits)) return '000';\n return digits;\n }\n case 'last4': {\n const digits = String(value).replace(/\\D/g, '');\n return digits.length >= 4 ? `•••• ${digits.slice(-4)}` : REDACTED;\n }\n case 'redact':\n return REDACTED;\n }\n}\n\n/** The default strategy for a property's runtime type. */\nexport function defaultAnonStrategy(\n elementRuntimeType: string,\n isArray: boolean,\n hasEnum: boolean\n): AnonStrategy {\n if (isArray || hasEnum) return 'redact';\n if (elementRuntimeType === 'string') return 'token';\n if (elementRuntimeType === 'Date') return 'year';\n return 'redact';\n}\n\n// ---------------------------------------------------------------------------\n// CompliantField\n// ---------------------------------------------------------------------------\n\ninterface FieldState {\n spec: CompliantFieldSpec;\n /** Plaintext is known (created in-process, or decrypted already). */\n hasPlain: boolean;\n plain?: unknown;\n /**\n * The tenant this value belongs to: the tenant bound when it was loaded,\n * or when its plaintext was assigned. `undefined` when none was bound;\n * reads and writes then need one bound at the time.\n */\n tenant?: string;\n /** Stored envelope, as loaded or as last sealed. */\n sealed?: string;\n /** Tenant the cached `sealed` was written under. */\n sealedTenant?: string;\n /** Blind index, as loaded or as computed. */\n index?: string | null;\n anon?: string;\n}\n\nconst STATE: WeakMap<object, FieldState> = ((\n globalThis as Record<symbol, unknown>\n)[Symbol.for('forklaunch.compliance.state')] ??= new WeakMap()) as WeakMap<\n object,\n FieldState\n>;\nconst FIELD_BRAND = Symbol.for('forklaunch.compliance.field');\n\nfunction stateOf(field: object): FieldState {\n const state = STATE.get(field);\n if (!state) throw new Error('Not a compliant field');\n return state;\n}\n\n/**\n * A pii, phi or pci property of an entity. The only ways to its value are\n * `.anon` (de-identified, safe to share) and `.deanon` (plaintext, reported\n * to {@link onComplianceAccess} listeners). There are deliberately no\n * `toString`, `toJSON` or inspect overloads: interpolating it prints\n * `[object Object]` and serializing it prints `{}`, so nothing leaks by\n * accident and every read is explicit.\n *\n * Plaintext is decrypted lazily, on the first `.deanon`, with the key of the\n * tenant the field was loaded (or assigned) under. That tenant is captured\n * when the row is hydrated, so `.deanon` works after the call that loaded it\n * has returned (building a DTO outside the tenant-bound entity manager) and\n * can never decrypt under a different tenant: if another tenant is bound at\n * read time it throws {@link TenantMismatchError}.\n *\n * Assigning a plain value to the property (directly, through `em.create` or\n * through `em.assign`) wraps it; `where: { property: value }` works for\n * fields declared `queryable`.\n */\nexport class CompliantField<\n V = unknown,\n L extends EncryptedComplianceLevel = EncryptedComplianceLevel,\n Q extends boolean = boolean\n> {\n // Type-only members that teach MikroORM's EntityData / FilterQuery types\n // what may be assigned and queried. They do not exist at runtime.\n /** @internal */\n declare readonly __runtime?: CompliantField<V, L, Q> | V;\n /** @internal */\n declare readonly __raw?: string;\n /** @internal */\n declare readonly __serialized?: Record<string, never>;\n /** @internal lets `where` accept a plain value, but only for queryable fields */\n declare readonly [PrimaryKeyProp]?: Q extends true ? V : never;\n /** @internal carries the level into the type */\n declare readonly __level?: L;\n\n private constructor(state: FieldState) {\n Object.defineProperty(this, FIELD_BRAND, { value: true });\n STATE.set(this, state);\n Object.freeze(this);\n }\n\n /**\n * @internal Wrap a plaintext value for `spec`, owned by `tenant` (the one\n * bound where it was assigned, if any). Applications assign plain values to\n * the entity property instead.\n */\n static fromPlain<V>(\n value: V,\n spec: CompliantFieldSpec,\n tenant: string | undefined\n ): CompliantField<V> {\n if (spec.enumValues) {\n const values = spec.isArray && Array.isArray(value) ? value : [value];\n for (const v of values) {\n if (!spec.enumValues.includes(v)) {\n throw new Error(\n `Invalid enum value${spec.path ? ` for ${spec.path}` : ''}: ${String(v)}. Allowed values: ${spec.enumValues.join(', ')}`\n );\n }\n }\n }\n return new CompliantField<V>({\n spec,\n tenant,\n hasPlain: true,\n plain: value,\n anon: computeAnon(spec.anon, value)\n });\n }\n\n /**\n * @internal Wrap a stored value (any envelope, or legacy plaintext) loaded\n * under `tenant`: the tenant bound during hydration, which is the loading\n * entity manager's.\n */\n static fromStored<V>(\n stored: string,\n spec: CompliantFieldSpec,\n index: string | null | undefined,\n tenant: string | undefined\n ): CompliantField<V> {\n if (!isEncryptedCiphertext(stored)) {\n // Written before encryption was switched on: the column holds the\n // serialized plaintext. It is sealed on the next write.\n return new CompliantField<V>({\n spec,\n tenant,\n hasPlain: true,\n plain: deserializeFromEncryption(\n stored,\n spec.elementRuntimeType,\n spec.isArray\n ),\n index\n });\n }\n return new CompliantField<V>({\n spec,\n tenant,\n hasPlain: false,\n sealed: stored,\n anon: sealedAnon(stored) ?? undefined,\n index\n });\n }\n\n /** @internal A queryable field whose ciphertext column was not selected. */\n static fromIndexOnly<V>(\n index: string | null,\n spec: CompliantFieldSpec\n ): CompliantField<V> {\n return new CompliantField<V>({ spec, hasPlain: false, index });\n }\n\n /** The field's classification. */\n get level(): L {\n return stateOf(this).spec.level as L;\n }\n\n /** The de-identified value. Never decrypts for values in a `v4` envelope. */\n get anon(): Anon {\n const state = stateOf(this);\n if (state.anon === undefined) {\n if (state.spec.anon === 'token') {\n throw new LegacyCiphertextError(\n `${state.spec.path} is stored in a pre-v4 envelope and has no token yet; run reencryptEncryptedColumns() once to upgrade it`\n );\n }\n state.anon = computeAnon(state.spec.anon, readPlaintext(this, false));\n }\n return new Anon(state.anon, MINT);\n }\n\n /** The plaintext. Every read is reported to access listeners. */\n get deanon(): V {\n return readPlaintext(this, true) as V;\n }\n}\n\n/**\n * The tenant a field is read or written under: the one it belongs to, and\n * otherwise the one bound now ({@link UnboundTenantError} when none is). A\n * bound tenant that is not the owner is refused.\n */\nfunction tenantOf(state: FieldState, operation: string): string {\n const bound = getBoundTenantId();\n if (state.tenant === undefined) return requireBoundTenantId(operation);\n if (bound !== undefined && bound !== state.tenant) {\n throw new TenantMismatchError(\n state.spec.path,\n operation,\n state.tenant,\n bound\n );\n }\n return state.tenant;\n}\n\nfunction readPlaintext(field: CompliantField, report: boolean): unknown {\n const state = stateOf(field);\n let tenantId = '';\n if (!state.hasPlain) {\n tenantId = tenantOf(state, 'read');\n if (state.sealed === undefined) {\n throw new Error(\n `${state.spec.path} was not loaded: its ciphertext column was left out of the selection`\n );\n }\n const encryptor = getRegisteredEncryptor();\n if (!encryptor) {\n throw new EncryptionRequiredError(\n `Cannot read ${state.spec.path}: no encryptor registered. Call registerEncryptor() at bootstrap.`\n );\n }\n const opened = encryptor.open(state.sealed, tenantId);\n state.plain = deserializeFromEncryption(\n opened.plaintext,\n state.spec.elementRuntimeType,\n state.spec.isArray\n );\n state.hasPlain = true;\n } else if (state.tenant !== undefined) {\n // Plaintext already in memory is held to the same rule: a value that\n // belongs to one tenant is not handed to another tenant's request.\n tenantId = tenantOf(state, 'read');\n }\n if (report) {\n tenantId ||= getBoundTenantId() ?? '';\n for (const listener of LISTENERS) {\n listener({ field: state.spec.path, level: state.spec.level, tenantId });\n }\n }\n return state.plain;\n}\n\n/** True for compliant field instances (works across duplicate package copies). */\nexport function isCompliantField(value: unknown): value is CompliantField {\n return (\n value != null &&\n typeof value === 'object' &&\n (value as Record<symbol, unknown>)[FIELD_BRAND] === true\n );\n}\n\n// ---------------------------------------------------------------------------\n// Sealing and indexing (flush time, inside the caller's encryption context)\n// ---------------------------------------------------------------------------\n\nfunction requireEncryptor(path: string) {\n const encryptor = getRegisteredEncryptor();\n if (!encryptor) {\n throw new EncryptionRequiredError(\n `Cannot write ${path}: no encryptor registered. Call registerEncryptor() at bootstrap; compliant fields are never stored in plaintext.`\n );\n }\n return encryptor;\n}\n\n/** @internal The stored envelope for a field, sealing it on first use. */\nexport function sealedValueOf(field: CompliantField): string | undefined {\n const state = stateOf(field);\n // Loaded values (sealedTenant unset) keep their stored bytes; values sealed\n // in-process are reused while they are sealed under the tenant they belong\n // to. Reusing the bytes is what keeps dirty checking quiet: a fresh random\n // IV would differ on every flush. Neither path seals anything, so neither\n // depends on the tenant bound now.\n if (state.sealed !== undefined && state.sealedTenant === undefined) {\n return state.sealed;\n }\n if (!state.hasPlain) return state.sealed;\n if (state.sealed !== undefined && state.sealedTenant === state.tenant) {\n return state.sealed;\n }\n // Sealed under the tenant the value belongs to. A value assigned with no\n // tenant bound takes the one bound at flush (and still fails unbound), and\n // belongs to that tenant from then on: a later flush under another tenant\n // must not re-seal it under the wrong key.\n const tenantId = tenantOf(state, 'write');\n state.tenant = tenantId;\n if (state.anon === undefined) {\n state.anon = computeAnon(state.spec.anon, state.plain);\n }\n state.sealed = requireEncryptor(state.spec.path).seal(\n serializeForEncryption(state.plain),\n tenantId,\n state.anon\n );\n state.sealedTenant = tenantId;\n return state.sealed;\n}\n\n/** @internal Normalize an already-serialized value for indexing. */\nexport function normalizeSerializedForIndex(\n serialized: string,\n spec: CompliantFieldSpec\n): string {\n return spec.normalize === 'lowercase'\n ? serialized.trim().toLowerCase()\n : serialized;\n}\n\nfunction normalizedForIndex(value: unknown, spec: CompliantFieldSpec): string {\n return normalizeSerializedForIndex(serializeForEncryption(value), spec);\n}\n\n/** @internal Blind index of a raw query value, under the bound tenant. */\nexport function blindIndexOfValue(\n value: unknown,\n spec: CompliantFieldSpec\n): string {\n return blindIndexUnder(value, spec, requireBoundTenantId('query'));\n}\n\nfunction blindIndexUnder(\n value: unknown,\n spec: CompliantFieldSpec,\n tenantId: string\n): string {\n return requireEncryptor(spec.path).blindIndex(\n normalizedForIndex(value, spec),\n tenantId\n );\n}\n\n/** @internal The blind index for a field, computing it when missing. */\nexport function blindIndexOf(field: CompliantField): string | null {\n const state = stateOf(field);\n if (state.index) return state.index;\n if (!state.hasPlain && state.sealed === undefined) return state.index ?? null;\n // Rows written before the field was queryable have no index yet: compute\n // it, so the next flush backfills the column.\n try {\n const plain = state.hasPlain ? state.plain : readPlaintext(field, false);\n state.index = blindIndexUnder(plain, state.spec, tenantOf(state, 'index'));\n } catch {\n return state.index ?? null;\n }\n return state.index;\n}\n\n// ---------------------------------------------------------------------------\n// MikroORM types\n// ---------------------------------------------------------------------------\n\nconst PENDING = Symbol.for('forklaunch.compliance.pending');\n\n/** @internal Placeholder hydrated into a queryable property before its ciphertext is paired with it. */\nexport interface PendingIndex {\n readonly [PENDING]: string | null;\n}\n\nexport function isPendingIndex(value: unknown): value is PendingIndex {\n return value != null && typeof value === 'object' && PENDING in value;\n}\n\nexport function pendingIndexValue(value: PendingIndex): string | null {\n return value[PENDING];\n}\n\n/**\n * @internal The `runtimeType` of a compliant property: what it holds in\n * memory. Deliberately not one of MikroORM's scalar names, which it checks\n * assigned values against.\n */\nexport const COMPLIANT_RUNTIME_TYPE = 'CompliantField';\n\nabstract class CompliantTypeBase extends Type<unknown, string | null> {\n constructor(readonly spec: CompliantFieldSpec) {\n super();\n }\n\n override getColumnType(): string {\n return 'text';\n }\n\n override get runtimeType(): string {\n return COMPLIANT_RUNTIME_TYPE;\n }\n\n override ensureComparable(): boolean {\n return false;\n }\n\n override compareAsType(): string {\n return 'string';\n }\n}\n\n/**\n * Column type of a non-queryable compliant field. The column holds the\n * `v4` envelope; loading yields a {@link CompliantField}.\n */\nexport class CompliantType extends CompliantTypeBase {\n override convertToDatabaseValue(\n value: unknown,\n _platform: Platform,\n context?: TransformContext\n ): string | null {\n // MikroORM sets `fromQuery` both for a `where` value and for the values\n // a bulk update writes (`nativeUpdate`, `qb.update`), and tells them\n // apart by `mode`. A `where` on this column would compare ciphertexts and\n // never match, so it is refused; a value being written is sealed like\n // any other. (Better Auth's adapter changes a password this way.)\n if (context?.fromQuery && context.mode !== 'query-data') {\n throw new CompliantQueryError(\n `${this.spec.path} cannot be queried: declare it with .compliance('${this.spec.level}', { queryable: true }) to allow equality lookups`\n );\n }\n if (value === null || value === undefined) return null;\n if (isCompliantField(value)) return sealedValueOf(value) ?? null;\n if (isEncryptedCiphertext(value)) return value;\n return (\n sealedValueOf(\n CompliantField.fromPlain(value, this.spec, getBoundTenantId())\n ) ?? null\n );\n }\n\n override convertToJSValue(value: string | null): unknown {\n if (value === null || value === undefined) return value;\n if (isCompliantField(value)) return value;\n // Hydration runs inside the loading entity manager's tenant context:\n // the field keeps that tenant, and decrypts under it later.\n return CompliantField.fromStored(\n String(value),\n this.spec,\n undefined,\n getBoundTenantId()\n );\n }\n}\n\nconst EQUALITY_OPERATORS = new Set(['$eq', '$ne', '$in', '$nin']);\n\n/**\n * Column type of a queryable compliant field. The property's own column\n * (`<column>_idx`) holds the blind index, so `where` compiles to an\n * index comparison; the envelope lives in a hidden sibling column.\n */\nexport class CompliantIndexType extends CompliantTypeBase {\n override convertToDatabaseValue(\n value: unknown,\n _platform: Platform,\n context?: TransformContext\n ): string | null {\n if (value === null || value === undefined) return null;\n // A bulk update can write this column (the blind index) but not the\n // hidden one beside it that holds the sealed value, so the two would\n // disagree. Refused, with what to do instead.\n if (context?.mode === 'query-data') {\n throw new CompliantQueryError(\n `${this.spec.path} is queryable, so a bulk update (nativeUpdate, qb.update) cannot set it: its sealed value lives in a second column the update does not write. Load the entity, assign the value and flush.`\n );\n }\n if (context?.fromQuery) {\n const key = context.key;\n if (\n key !== undefined &&\n !EQUALITY_OPERATORS.has(String(key)) &&\n !/^\\d+$/.test(String(key))\n ) {\n throw new CompliantQueryError(\n `${this.spec.path} supports equality lookups only ($eq, $ne, $in, $nin); ${String(key)} would need the plaintext`\n );\n }\n }\n if (isCompliantField(value)) return blindIndexOf(value);\n if (isPendingIndex(value)) return pendingIndexValue(value);\n if (typeof value === 'string' && value.startsWith('bi1:')) return value;\n return blindIndexOfValue(value, this.spec);\n }\n\n override convertToJSValue(value: string | null): unknown {\n if (isCompliantField(value) || isPendingIndex(value)) return value;\n return { [PENDING]: value ?? null } satisfies PendingIndex;\n }\n}\n\n/** True for the column types above. */\nexport function isCompliantType(\n type: unknown\n): type is CompliantType | CompliantIndexType {\n return type instanceof CompliantType || type instanceof CompliantIndexType;\n}\n\n// ---------------------------------------------------------------------------\n// Entity accessors\n// ---------------------------------------------------------------------------\n\n/** @internal One compliant property of an entity class. */\nexport interface CompliantPropertyBinding {\n property: string;\n spec: CompliantFieldSpec;\n /** Hidden property holding the envelope, for queryable fields. */\n sibling?: string;\n}\n\ntype Slots = Record<string, unknown>;\nconst SLOTS: WeakMap<object, Slots> = ((globalThis as Record<symbol, unknown>)[\n Symbol.for('forklaunch.compliance.slots')\n] ??= new WeakMap()) as WeakMap<object, Slots>;\n\n/**\n * The tenant bound when each queryable field's envelope was hydrated, keyed\n * by property. The field itself is built lazily, on first access (it needs\n * both the index and the envelope column), which can be long after the\n * loading entity manager returned; the tenant is recorded at hydration.\n */\nconst LOADED_TENANTS: WeakMap<object, Record<string, string | undefined>> = ((\n globalThis as Record<symbol, unknown>\n)[Symbol.for('forklaunch.compliance.loadedTenants')] ??=\n new WeakMap()) as WeakMap<object, Record<string, string | undefined>>;\n\nfunction loadedTenantOf(\n entity: object,\n binding: CompliantPropertyBinding\n): string | undefined {\n return LOADED_TENANTS.get(entity)?.[binding.property];\n}\n\nfunction recordLoadedTenant(\n entity: object,\n binding: CompliantPropertyBinding\n): void {\n let tenants = LOADED_TENANTS.get(entity);\n if (!tenants) {\n tenants = {};\n LOADED_TENANTS.set(entity, tenants);\n }\n tenants[binding.property] = getBoundTenantId();\n}\n\nfunction slotsOf(entity: object): Slots {\n let slots = SLOTS.get(entity);\n if (!slots) {\n slots = {};\n SLOTS.set(entity, slots);\n }\n return slots;\n}\n\nfunction readProperty(\n entity: object,\n binding: CompliantPropertyBinding\n): CompliantField | null | undefined {\n const slots = slotsOf(entity);\n const value = slots[binding.property];\n if (binding.sibling) {\n const stored = slots[binding.sibling];\n if (isPendingIndex(value)) {\n const index = pendingIndexValue(value);\n const field =\n typeof stored === 'string'\n ? CompliantField.fromStored(\n stored,\n binding.spec,\n index,\n loadedTenantOf(entity, binding)\n )\n : CompliantField.fromIndexOnly(index, binding.spec);\n slots[binding.property] = field;\n return field;\n }\n // A row written before the field was queryable has no index yet (the\n // index column hydrates as null); the envelope alone is enough to load\n // it, and the next flush backfills the index.\n if (value == null && typeof stored === 'string') {\n const field = CompliantField.fromStored(\n stored,\n binding.spec,\n null,\n loadedTenantOf(entity, binding)\n );\n slots[binding.property] = field;\n return field;\n }\n }\n return value as CompliantField | null | undefined;\n}\n\nfunction sameRules(a: CompliantFieldSpec, b: CompliantFieldSpec): boolean {\n return (\n a === b ||\n (a.path === b.path &&\n a.anon === b.anon &&\n a.normalize === b.normalize &&\n a.queryable === b.queryable)\n );\n}\n\nfunction writeProperty(\n entity: object,\n binding: CompliantPropertyBinding,\n value: unknown\n): void {\n const slots = slotsOf(entity);\n if (isPendingIndex(value)) {\n slots[binding.property] = value;\n return;\n }\n if (value === null || value === undefined) {\n slots[binding.property] = value;\n // Clearing the field clears its envelope too. Hydration writes the index\n // column before the envelope column (the sibling is declared right after\n // the property), so a null index hydrated for a legacy row does not wipe\n // the envelope that follows it.\n if (binding.sibling) slots[binding.sibling] = value;\n return;\n }\n if (isCompliantField(value)) {\n // A field copied from another property takes this property's rules\n // (anon strategy, index normalization): re-wrap its plaintext.\n slots[binding.property] = sameRules(stateOf(value).spec, binding.spec)\n ? value\n : CompliantField.fromPlain(\n readPlaintext(value, false),\n binding.spec,\n stateOf(value).tenant ?? getBoundTenantId()\n );\n return;\n }\n slots[binding.property] = CompliantField.fromPlain(\n value,\n binding.spec,\n getBoundTenantId()\n );\n}\n\n/**\n * Install getter/setter pairs for compliant properties on an entity\n * prototype. Assigning a plain value wraps it in a {@link CompliantField};\n * reading returns the field.\n */\nexport function installCompliantAccessors(\n prototype: object,\n bindings: readonly CompliantPropertyBinding[]\n): void {\n installInspect(prototype, bindings);\n for (const binding of bindings) {\n Object.defineProperty(prototype, binding.property, {\n configurable: true,\n enumerable: true,\n get(this: object) {\n return readProperty(this, binding);\n },\n set(this: object, value: unknown) {\n writeProperty(this, binding, value);\n }\n });\n if (binding.sibling) {\n const sibling = binding.sibling;\n Object.defineProperty(prototype, sibling, {\n configurable: true,\n enumerable: false,\n get(this: object) {\n const field = readProperty(this, binding);\n const stored = slotsOf(this)[sibling];\n if (field === null || field === undefined) return stored ?? field;\n return sealedValueOf(field) ?? stored;\n },\n set(this: object, value: unknown) {\n // Only hydration writes the hidden envelope property.\n recordLoadedTenant(this, binding);\n slotsOf(this)[sibling] = value;\n }\n });\n }\n }\n}\n\nconst INSPECT = Symbol.for('nodejs.util.inspect.custom');\n\n/**\n * MikroORM installs a custom inspect on entity prototypes only when none is\n * present (`??=`). Installing ours first keeps the hidden envelope columns\n * of queryable fields out of `console.log(entity)`, and shows compliant\n * properties (which live on the prototype) as `CompliantField {}`.\n */\nfunction installInspect(\n prototype: object,\n bindings: readonly CompliantPropertyBinding[]\n): void {\n const hidden = new Set(\n bindings.map((b) => b.sibling).filter((s): s is string => !!s)\n );\n Object.defineProperty(prototype, INSPECT, {\n configurable: true,\n writable: true,\n value(\n this: Record<string, unknown>,\n depth: number,\n options: Record<string, unknown>,\n inspect: (value: unknown, options: Record<string, unknown>) => string\n ) {\n const shown: Record<string, unknown> = {};\n for (const key of Object.keys(this)) {\n if (!hidden.has(key)) shown[key] = this[key];\n }\n for (const binding of bindings) {\n const value = this[binding.property];\n if (value !== undefined) shown[binding.property] = value;\n }\n const name = (this.constructor as { name?: string })?.name ?? 'Entity';\n return `${name} ${inspect(shown, { ...options, depth })}`;\n }\n });\n}\n\n// ---------------------------------------------------------------------------\n// Whole-entity reveal\n// ---------------------------------------------------------------------------\n\n/** The value type behind a compliant field (null and undefined pass through). */\nexport type Deanon<X> =\n X extends CompliantField<infer V, EncryptedComplianceLevel, boolean> ? V : X;\n\n/** An entity's fields with every compliant field replaced by its value. */\nexport type Deanonymized<T> = { [K in keyof T]: Deanon<T[K]> };\n\n/**\n * A plain copy of an entity with every compliant field replaced by its\n * `.deanon` value: what `{ ...entity }` produced before compliant fields,\n * for first-party responses built by spreading an entity.\n *\n * A spread alone does not work: compliant properties live on the entity's\n * prototype, so `{ ...entity }` would silently leave them out. Every value\n * revealed here is reported to access listeners, like any `.deanon`.\n *\n * @example\n * toDto: async (entity) => ({ ...deanon(entity), customerId: entity.customerId ?? undefined })\n */\nexport function deanon<T extends object>(entity: T): Deanonymized<T> {\n const copy: Record<string, unknown> = {};\n for (const key in entity) {\n const value = (entity as Record<string, unknown>)[key];\n copy[key] = isCompliantField(value) ? value.deanon : value;\n }\n return copy as Deanonymized<T>;\n}\n","import crypto from 'crypto';\n\n// ---------------------------------------------------------------------------\n// Error types\n// ---------------------------------------------------------------------------\n\nexport class MissingEncryptionKeyError extends Error {\n readonly name = 'MissingEncryptionKeyError' as const;\n constructor(message = 'Master encryption key must be provided') {\n super(message);\n }\n}\n\nexport class DecryptionError extends Error {\n readonly name = 'DecryptionError' as const;\n constructor(\n message = 'Decryption failed: ciphertext is corrupted or the wrong key was used'\n ) {\n super(message);\n }\n}\n\nexport class EncryptionRequiredError extends Error {\n readonly name = 'EncryptionRequiredError' as const;\n constructor(\n message = 'Encryption is required before persisting this compliance field'\n ) {\n super(message);\n }\n}\n\n// ---------------------------------------------------------------------------\n// Constants\n// ---------------------------------------------------------------------------\n\nconst ALGORITHM = 'aes-256-gcm' as const;\nconst IV_BYTES = 12;\nconst KEY_BYTES = 32;\nconst HKDF_HASH = 'sha256' as const;\nconst HKDF_SALT = Buffer.alloc(0); // empty salt - key material is already high-entropy\nconst BLIND_INDEX_INFO = 'forklaunch:blind-index\\0';\nconst KEY_ID_HEX_CHARS = 12;\nconst DERIVED_KEY_CACHE_LIMIT = 4096;\n\n/**\n * Ciphertext envelopes the encryptor reads. `v3` and `v4` name their key.\n *\n * v1:{iv}:{tag}:{data} random IV (legacy)\n * v2:{iv}:{tag}:{data} deterministic IV\n * v3:{keyId}:{iv}:{tag}:{data} deterministic IV, stamped with the key fingerprint\n * v4:{keyId}:{anon}:{iv}:{tag}:{data} random IV, stamped, carrying the field's\n * de-identified value (base64url) in clear;\n * written by compliant fields via {@link FieldEncryptor.seal}\n */\nexport const ENCRYPTED_PREFIXES = ['v1:', 'v2:', 'v3:', 'v4:'] as const;\n\n/** Prefix of blind-index values: `bi1:{keyId}:{hmac}`. */\nexport const BLIND_INDEX_PREFIX = 'bi1:';\n\n/**\n * The de-identified value carried by a `v4` envelope, or null for any other\n * envelope. Reading it never decrypts.\n */\nexport function sealedAnon(ciphertext: string): string | null {\n if (!ciphertext.startsWith('v4:')) return null;\n const parts = ciphertext.split(':');\n if (parts.length !== 6) return null;\n return Buffer.from(parts[2], 'base64url').toString('utf8');\n}\n\n/** True when the string carries one of the encryptor's envelopes. */\nexport function isEncryptedCiphertext(value: unknown): value is string {\n return (\n typeof value === 'string' &&\n ENCRYPTED_PREFIXES.some((p) => value.startsWith(p))\n );\n}\n\n/**\n * Which envelope new values are written in.\n *\n * 'v2' unstamped. Default. Byte-compatible with every existing row, so\n * equality lookups keep matching rows written before the ring existed.\n * 'v3' stamped with the writing key's fingerprint. Reads resolve the key\n * directly, a missing key fails by name, and the rows still under a\n * key can be counted with a LIKE. Switch to it only after a rotation\n * sweep has rewritten every row: a v3 write does not byte-match a v2\n * row of the same plaintext, so lookups miss until the sweep is done.\n */\nexport type CiphertextFormat = 'v2' | 'v3';\n\n/** Environment variable holding the key new values are written with. */\nexport const ENCRYPTION_KEY_ENV = 'ENCRYPTION_KEY';\n/** Environment variable holding every previous key, comma separated. */\nexport const LEGACY_ENCRYPTION_KEYS_ENV = 'LEGACY_ENCRYPTION_KEYS';\n/** Older single-key spelling of {@link LEGACY_ENCRYPTION_KEYS_ENV}; still honoured. */\nexport const LEGACY_ENCRYPTION_KEY_ENV = 'LEGACY_ENCRYPTION_KEY';\n/** Environment variable selecting the write format, `v2` (default) or `v3`. */\nexport const ENCRYPTION_FORMAT_ENV = 'ENCRYPTION_FORMAT';\n\n/**\n * Split a key list as it appears in an environment variable: comma,\n * semicolon or whitespace separated, optionally quoted. Blanks and\n * duplicates are dropped, order is kept.\n */\nexport function parseEncryptionKeyList(\n ...sources: (string | undefined | null)[]\n): string[] {\n const keys: string[] = [];\n for (const source of sources) {\n for (const part of (source ?? '').split(/[\\s,;]+/)) {\n const key = part.trim().replace(/^[\"']|[\"']$/g, '');\n if (key && !keys.includes(key)) keys.push(key);\n }\n }\n return keys;\n}\n\n/**\n * A short, non-reversible fingerprint of a master key, for logs, reports\n * and the `v3` envelope. Two deployments with the same key get the same\n * id; the id reveals nothing about the key.\n */\nexport function encryptionKeyId(masterKey: string): string {\n return crypto\n .createHash('sha256')\n .update(masterKey)\n .digest('hex')\n .slice(0, KEY_ID_HEX_CHARS);\n}\n\n/**\n * The key fingerprint a stored value is stamped with, or null for `v1`/`v2`\n * values, which name no key.\n */\nexport function stampedKeyId(ciphertext: string): string | null {\n const parts = ciphertext.split(':');\n if (ciphertext.startsWith('v3:')) return parts.length === 5 ? parts[1] : null;\n if (ciphertext.startsWith('v4:')) return parts.length === 6 ? parts[1] : null;\n if (ciphertext.startsWith(BLIND_INDEX_PREFIX))\n return parts.length === 3 ? parts[1] : null;\n return null;\n}\n\n/** SQL LIKE pattern matching every value stamped with `keyId`. */\nexport function stampedPrefix(keyId: string): string {\n return `v3:${keyId}:`;\n}\n\nexport interface FieldEncryptorOptions {\n /**\n * Keys that data may still be encrypted under, newest first. Values are\n * never written with these; they are only tried when the current key\n * cannot open a ciphertext. Keep a key here until a rotation sweep\n * (`reencryptEncryptedColumns`) reports nothing left under it.\n */\n previousKeys?: readonly string[];\n /** Envelope for new values. See {@link CiphertextFormat}. Default `v2`. */\n format?: CiphertextFormat;\n}\n\n/** What {@link FieldEncryptor.open} learned about a ciphertext. */\nexport interface OpenedCiphertext {\n plaintext: string;\n /** Fingerprint of the key that opened it; see {@link encryptionKeyId}. */\n keyId: string;\n /** True when the current key opened it. */\n current: boolean;\n /** Envelope the value was stored in. */\n version: 'v1' | 'v2' | 'v3' | 'v4';\n /** The de-identified value a `v4` envelope carries; undefined otherwise. */\n anon?: string;\n /**\n * True when a rewrite would change the stored bytes: the value is under\n * a previous key, or it is unstamped while the encryptor writes `v3`.\n */\n stale: boolean;\n}\n\ninterface KeyMaterial {\n readonly id: string;\n readonly masterKey: string;\n}\n\n// ---------------------------------------------------------------------------\n// FieldEncryptor\n// ---------------------------------------------------------------------------\n\n/**\n * AES-256-GCM field encryption with per-tenant keys derived by HKDF from a\n * master key, and a key ring for rotation.\n *\n * The ring has one current key and any number of previous keys. Every\n * write uses the current key. A `v3` value names its key, so a read looks\n * it up directly and a missing key fails by name. A `v1`/`v2` value names\n * nothing, so a read tries the current key and then each previous key in\n * order; AES-GCM's authentication tag makes \"this key opens it\" a real\n * check rather than a guess. Either way the master key can change without\n * a downtime window: add the old key to `previousKeys`, deploy, run the\n * rotation sweep, then drop the old key.\n */\nexport class FieldEncryptor {\n private readonly ring: readonly KeyMaterial[];\n private readonly byId: ReadonlyMap<string, KeyMaterial>;\n private readonly derived = new Map<string, Buffer>();\n readonly format: CiphertextFormat;\n\n constructor(masterKey: string, options: FieldEncryptorOptions = {}) {\n if (!masterKey) {\n throw new MissingEncryptionKeyError();\n }\n const ring: KeyMaterial[] = [{ id: encryptionKeyId(masterKey), masterKey }];\n for (const key of options.previousKeys ?? []) {\n if (!key || ring.some((k) => k.masterKey === key)) continue;\n ring.push({ id: encryptionKeyId(key), masterKey: key });\n }\n this.ring = ring;\n this.byId = new Map(ring.map((k) => [k.id, k]));\n this.format = options.format ?? 'v2';\n }\n\n /**\n * Build the ring from the environment: `ENCRYPTION_KEY` plus\n * `LEGACY_ENCRYPTION_KEYS` (comma separated) and the older\n * `LEGACY_ENCRYPTION_KEY`; `ENCRYPTION_FORMAT` selects the envelope.\n */\n static fromEnv(env: NodeJS.ProcessEnv = process.env): FieldEncryptor {\n const masterKey = env[ENCRYPTION_KEY_ENV];\n if (!masterKey) {\n throw new MissingEncryptionKeyError(`${ENCRYPTION_KEY_ENV} must be set`);\n }\n const format = env[ENCRYPTION_FORMAT_ENV]?.trim().toLowerCase();\n if (format && format !== 'v2' && format !== 'v3') {\n throw new Error(\n `${ENCRYPTION_FORMAT_ENV} must be \"v2\" or \"v3\", got \"${format}\"`\n );\n }\n return new FieldEncryptor(masterKey, {\n previousKeys: parseEncryptionKeyList(\n env[LEGACY_ENCRYPTION_KEYS_ENV],\n env[LEGACY_ENCRYPTION_KEY_ENV]\n ),\n format: (format as CiphertextFormat | undefined) ?? 'v2'\n });\n }\n\n /** Fingerprints of the ring, current first. Safe to log. */\n get keyIds(): { current: string; previous: string[] } {\n return {\n current: this.ring[0].id,\n previous: this.ring.slice(1).map((k) => k.id)\n };\n }\n\n /** A copy of this encryptor with a different set of previous keys. */\n withPreviousKeys(previousKeys: readonly string[]): FieldEncryptor {\n return new FieldEncryptor(this.ring[0].masterKey, {\n previousKeys,\n format: this.format\n });\n }\n\n /** A copy of this encryptor writing a different envelope. */\n withFormat(format: CiphertextFormat): FieldEncryptor {\n return new FieldEncryptor(this.ring[0].masterKey, {\n previousKeys: this.ring.slice(1).map((k) => k.masterKey),\n format\n });\n }\n\n /**\n * Derive a per-tenant 32-byte key using HKDF-SHA256 from the CURRENT\n * master key. The master key is the input key material and the tenantId\n * the info context.\n */\n deriveKey(tenantId: string): Buffer {\n return this.deriveKeyFor(this.ring[0], tenantId);\n }\n\n private deriveKeyFor(key: KeyMaterial, tenantId: string): Buffer {\n const cacheKey = `${key.id} ${tenantId}`;\n const cached = this.derived.get(cacheKey);\n if (cached) return cached;\n const derived = Buffer.from(\n crypto.hkdfSync(HKDF_HASH, key.masterKey, HKDF_SALT, tenantId, KEY_BYTES)\n );\n if (this.derived.size >= DERIVED_KEY_CACHE_LIMIT) this.derived.clear();\n this.derived.set(cacheKey, derived);\n return derived;\n }\n\n /**\n * Derive a deterministic IV from the key and plaintext using HMAC-SHA256,\n * truncated to IV_BYTES. Same plaintext + same key -> same IV -> same\n * ciphertext. This enables WHERE clause matching on encrypted columns\n * while maintaining AES-256-GCM authenticated encryption.\n *\n * Meets SOC 2, HIPAA, PCI DSS, GDPR requirements for encryption at rest.\n */\n private deriveDeterministicIv(key: Buffer, plaintext: string): Buffer {\n return crypto\n .createHmac('sha256', key)\n .update(plaintext)\n .digest()\n .subarray(0, IV_BYTES);\n }\n\n /**\n * Encrypt a plaintext string under the current key.\n *\n * Uses deterministic encryption (HMAC-derived IV) so the same plaintext\n * always produces the same ciphertext. This enables database WHERE clause\n * matching and UNIQUE constraints on encrypted columns.\n *\n * @returns `v2:{iv}:{tag}:{data}`, or `v3:{keyId}:{iv}:{tag}:{data}` when\n * the encryptor's format is `v3`. All parts base64.\n */\n encrypt(plaintext: string | null): string | null;\n encrypt(plaintext: string | null, tenantId: string): string | null;\n encrypt(plaintext: string | null, tenantId?: string): string | null {\n if (plaintext === null || plaintext === undefined) {\n return null;\n }\n\n const key = this.deriveKey(tenantId ?? '');\n const iv = this.deriveDeterministicIv(key, plaintext);\n\n const cipher = crypto.createCipheriv(ALGORITHM, key, iv);\n const encrypted = Buffer.concat([\n cipher.update(plaintext, 'utf8'),\n cipher.final()\n ]);\n const authTag = cipher.getAuthTag();\n\n const body = [\n iv.toString('base64'),\n authTag.toString('base64'),\n encrypted.toString('base64')\n ];\n return this.format === 'v3'\n ? ['v3', this.ring[0].id, ...body].join(':')\n : ['v2', ...body].join(':');\n }\n\n /**\n * Decrypt a ciphertext string produced by {@link encrypt}, in any\n * envelope: `v3` by its stamped key, `v1`/`v2` by trying every key in\n * the ring.\n */\n decrypt(ciphertext: string | null): string | null;\n decrypt(ciphertext: string | null, tenantId: string): string | null;\n decrypt(ciphertext: string | null, tenantId?: string): string | null {\n if (ciphertext === null || ciphertext === undefined) {\n return null;\n }\n return this.open(ciphertext, tenantId ?? '').plaintext;\n }\n\n /**\n * Decrypt and report which key opened the value and whether a rewrite\n * would change it. Throws {@link DecryptionError} when no key in the\n * ring does.\n */\n open(ciphertext: string, tenantId = ''): OpenedCiphertext {\n const parts = ciphertext.split(':');\n const version = parts[0];\n let candidates: readonly KeyMaterial[];\n let body: string[];\n\n let anon: string | undefined;\n if (\n (version === 'v3' && parts.length === 5) ||\n (version === 'v4' && parts.length === 6)\n ) {\n const key = this.byId.get(parts[1]);\n if (!key) {\n throw new DecryptionError(\n `Decryption failed: value is stamped with key ${parts[1]}, which is not in the ring (current ${this.ring[0].id}; previous ${\n this.ring\n .slice(1)\n .map((k) => k.id)\n .join(', ') || 'none'\n }). Add it to ${LEGACY_ENCRYPTION_KEYS_ENV}.`\n );\n }\n candidates = [key];\n if (version === 'v4') {\n anon = Buffer.from(parts[2], 'base64url').toString('utf8');\n body = parts.slice(3);\n } else {\n body = parts.slice(2);\n }\n } else if ((version === 'v1' || version === 'v2') && parts.length === 4) {\n candidates = this.ring;\n body = parts.slice(1);\n } else {\n throw new DecryptionError(\n `Unknown ciphertext version or malformed format`\n );\n }\n\n const [ivB64, authTagB64, encryptedB64] = body;\n const iv = Buffer.from(ivB64, 'base64');\n const authTag = Buffer.from(authTagB64, 'base64');\n const encrypted = Buffer.from(encryptedB64, 'base64');\n\n for (const key of candidates) {\n try {\n const decipher = crypto.createDecipheriv(\n ALGORITHM,\n this.deriveKeyFor(key, tenantId),\n iv\n );\n decipher.setAuthTag(authTag);\n const decrypted = Buffer.concat([\n decipher.update(encrypted),\n decipher.final()\n ]);\n const current = key === this.ring[0];\n return {\n plaintext: decrypted.toString('utf8'),\n keyId: key.id,\n current,\n version: version as 'v1' | 'v2' | 'v3' | 'v4',\n anon,\n stale:\n version === 'v4'\n ? !current\n : !current || (this.format === 'v3' && version !== 'v3')\n };\n } catch {\n // wrong key (or wrong tenant) for this value; try the next candidate\n }\n }\n throw new DecryptionError(\n candidates.length > 1\n ? `Decryption failed: none of the ${candidates.length} keys in the ring opens this value (ciphertext corrupted, wrong tenant, or the key it was written with is not in ${LEGACY_ENCRYPTION_KEYS_ENV})`\n : `Decryption failed: key ${candidates[0].id} does not open this value (ciphertext corrupted or wrong tenant)`\n );\n }\n\n /**\n * True when a rewrite would change the stored bytes: the value is under\n * a previous key, or unstamped while this encryptor writes `v3`. Throws\n * when no key opens it.\n */\n needsRotation(ciphertext: string, tenantId = ''): boolean {\n return this.open(ciphertext, tenantId).stale;\n }\n\n /**\n * Rewrite a value under the current key in the current format. Returns\n * the input unchanged when nothing would change, so callers can compare\n * to detect writes.\n */\n rotate(ciphertext: string | null, tenantId = ''): string | null {\n if (ciphertext === null || ciphertext === undefined) return null;\n const opened = this.open(ciphertext, tenantId);\n if (!opened.stale) return ciphertext;\n if (opened.version === 'v4') {\n return this.seal(opened.plaintext, tenantId, opened.anon ?? '');\n }\n return this.encrypt(opened.plaintext, tenantId);\n }\n\n /**\n * Encrypt for a compliant field: a fresh random IV every time (equal\n * plaintexts produce unrelated ciphertexts), stamped with the current key,\n * and carrying `anon` — the field's de-identified value — in clear so it\n * can be read without decrypting.\n *\n * Equality lookups do not use the ciphertext; they use {@link blindIndex}.\n *\n * @returns `v4:{keyId}:{anon}:{iv}:{tag}:{data}`\n */\n seal(plaintext: string, tenantId: string, anon: string): string {\n const key = this.deriveKey(tenantId);\n const iv = crypto.randomBytes(IV_BYTES);\n const cipher = crypto.createCipheriv(ALGORITHM, key, iv);\n const encrypted = Buffer.concat([\n cipher.update(plaintext, 'utf8'),\n cipher.final()\n ]);\n return [\n 'v4',\n this.ring[0].id,\n Buffer.from(anon, 'utf8').toString('base64url'),\n iv.toString('base64'),\n cipher.getAuthTag().toString('base64'),\n encrypted.toString('base64')\n ].join(':');\n }\n\n /**\n * Keyed HMAC of a plaintext for equality lookups, under a key derived\n * from the current master key and the tenant (separate from the\n * encryption key). Deterministic per tenant and key, one-way, and never\n * decryptable.\n *\n * After a master key rotation, rows still indexed under the previous key\n * do not match until `reencryptEncryptedColumns` re-indexes them; see\n * {@link blindIndexes} for a lookup that spans the ring.\n *\n * @returns `bi1:{keyId}:{hmac base64url}`\n */\n blindIndex(plaintext: string, tenantId: string): string {\n return this.blindIndexFor(this.ring[0], plaintext, tenantId);\n }\n\n /** {@link blindIndex} under every key in the ring, current first. */\n blindIndexes(plaintext: string, tenantId: string): string[] {\n return this.ring.map((k) => this.blindIndexFor(k, plaintext, tenantId));\n }\n\n /** True when a blind index was computed under a previous key. */\n isStaleBlindIndex(index: string): boolean {\n return stampedKeyId(index) !== this.ring[0].id;\n }\n\n private blindIndexFor(\n key: KeyMaterial,\n plaintext: string,\n tenantId: string\n ): string {\n const indexKey = this.deriveKeyFor(key, BLIND_INDEX_INFO + tenantId);\n const mac = crypto\n .createHmac('sha256', indexKey)\n .update(plaintext, 'utf8')\n .digest('base64url');\n return `${BLIND_INDEX_PREFIX}${key.id}:${mac}`;\n }\n}\n","import { createHash } from 'crypto';\nimport { MetricsDefinition } from '../types/openTelemetryCollector.types';\nimport { OpenTelemetryCollector } from './openTelemetryCollector';\n\nexport type AuditEntry = {\n timestamp: string;\n userId: string | null;\n tenantId: string | null;\n route: string;\n method: string;\n bodyHash: string;\n status: number;\n duration: number;\n redactedFields: string[];\n eventType:\n | 'http'\n | 'ws'\n | 'auth_failure'\n | 'rate_limit'\n | 'rbac_deny'\n | 'super_admin_bypass'\n /** A compliant field's plaintext was read (.deanon). */\n | 'data_access'\n /** A record holding sensitive fields was created, updated or deleted. */\n | 'data_change';\n};\n\nexport class AuditLogger {\n _otel: OpenTelemetryCollector<MetricsDefinition>;\n\n constructor(otel: OpenTelemetryCollector<MetricsDefinition>) {\n this._otel = otel;\n }\n\n append(entry: AuditEntry): void {\n try {\n this._otel.info(\n {\n 'log.type': 'audit',\n 'audit.timestamp': entry.timestamp,\n 'audit.userId': entry.userId ?? '',\n 'audit.tenantId': entry.tenantId ?? '',\n 'audit.route': entry.route,\n 'audit.method': entry.method,\n 'audit.bodyHash': entry.bodyHash,\n 'audit.status': entry.status,\n 'audit.duration': entry.duration,\n 'audit.redactedFields': entry.redactedFields.join(','),\n 'audit.eventType': entry.eventType,\n _meta: true\n },\n `audit:${entry.eventType} ${entry.method} ${entry.route} ${entry.status}`\n );\n } catch (error: unknown) {\n console.error('Failed to emit audit log via OTEL:', error);\n }\n }\n\n static hashBody(body: string | Buffer | undefined | null): string {\n if (body === undefined || body === null || body === '') {\n return '';\n }\n return createHash('sha256').update(body).digest('hex');\n }\n}\n","import { isRecord } from '@forklaunch/common';\nimport {\n AnySchemaValidator,\n ParseResult,\n prettyPrintParseErrors,\n SchemaValidator\n} from '@forklaunch/validator';\nimport { ParsedQs } from 'qs';\nimport { hasSend } from '../../guards/hasSend';\nimport { isRequestShape } from '../../guards/isRequestShape';\nimport {\n ForklaunchNextFunction,\n ForklaunchRequest,\n ForklaunchResponse,\n VersionedRequests\n} from '../../types/apiDefinition.types';\nimport { ParamsDictionary } from '../../types/contractDetails.types';\n\n/**\n * Pre-handler function to parse and validate input.\n *\n * @template SV - A type that extends AnySchemaValidator.\n * @template Request - A type that extends ForklaunchRequest.\n * @template Response - A type that extends ForklaunchResponse.\n * @template NextFunction - A type that extends ForklaunchNextFunction.\n * @param {Request} req - The request object.\n * @param {Response} res - The response object.\n * @param {NextFunction} [next] - The next middleware function.\n */\nexport function parse<\n SV extends AnySchemaValidator,\n P extends ParamsDictionary,\n ResBodyMap extends Record<number, unknown>,\n ReqBody extends Record<string, unknown>,\n ReqQuery extends ParsedQs,\n ReqHeaders extends Record<string, string>,\n ResHeaders extends Record<string, unknown>,\n LocalsObj extends Record<string, unknown>,\n VersionedReqs extends VersionedRequests,\n SessionSchema extends Record<string, unknown>\n>(\n req: ForklaunchRequest<\n SV,\n P,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n Extract<keyof VersionedReqs, string>,\n SessionSchema\n >,\n res: ForklaunchResponse<\n unknown,\n ResBodyMap,\n ResHeaders,\n LocalsObj,\n Extract<keyof VersionedReqs, string>\n >,\n next?: ForklaunchNextFunction\n) {\n const globalOptions = req._globalOptions?.();\n const collapsedOptions =\n req.contractDetails.options?.requestValidation ??\n (globalOptions?.validation === false\n ? 'none'\n : globalOptions?.validation?.request);\n\n // Preserve the pre-validation body for HMAC verification when the content\n // parser did not already capture the exact request bytes. Never clobber a\n // parser-captured _rawBody: that value is the raw payload as sent by the\n // client, which signature verification (Stripe et al.) must be computed\n // over — req.body may already be a parsed object here.\n req._rawBody ??= req.body;\n\n const request = {\n params: req.params,\n query: req.query,\n headers: req.headers,\n body: req.body\n };\n\n const schemaValidator = req.schemaValidator as SchemaValidator;\n\n let matchedVersions;\n\n let parsedRequest: ParseResult<object> | undefined;\n let collectedParseErrors: string | undefined;\n\n if (req.contractDetails.versions) {\n if (isRecord(req.requestSchema)) {\n let runningParseErrors: string = '';\n matchedVersions = [];\n\n Object.entries(req.requestSchema).forEach(([version, schema]) => {\n const parsingResult = schemaValidator.parse(schema, request);\n\n if (parsingResult.ok) {\n parsedRequest = parsingResult;\n matchedVersions.push(version);\n req.version = version as Extract<keyof VersionedReqs, string>;\n res.version = req.version;\n } else {\n runningParseErrors += prettyPrintParseErrors(\n parsingResult.errors,\n `Version ${version} request`\n );\n }\n });\n\n if (!parsedRequest) {\n parsedRequest = {\n ok: false,\n errors: []\n };\n collectedParseErrors = runningParseErrors;\n }\n } else {\n req.version = Object.keys(req.contractDetails.versions).pop() as Extract<\n keyof VersionedReqs,\n string\n >;\n res.version = req.version;\n\n parsedRequest = {\n ok: true,\n value: request\n };\n\n matchedVersions = Object.keys(req.contractDetails.versions);\n }\n } else {\n const parsingResult = schemaValidator.parse(req.requestSchema, request);\n\n parsedRequest = parsingResult;\n\n matchedVersions = 0;\n }\n\n if (\n parsedRequest.ok &&\n isRequestShape<P, ReqHeaders, ReqQuery, ReqBody>(parsedRequest.value)\n ) {\n req.body = parsedRequest.value.body;\n req.params = parsedRequest.value.params;\n Object.defineProperty(req, 'query', {\n value: parsedRequest.value.query,\n writable: false,\n enumerable: true,\n configurable: false\n });\n const parsedHeaders = parsedRequest.value.headers ?? {};\n req.headers = Object.keys(req.headers).reduce<Record<string, unknown>>(\n (acc, key) => {\n if (parsedHeaders?.[key]) {\n acc[key] = parsedHeaders[key];\n } else {\n acc[key] = req.headers[key];\n }\n return acc;\n },\n {}\n ) as ReqHeaders;\n }\n if (!parsedRequest.ok) {\n switch (collapsedOptions) {\n default:\n case undefined:\n case 'error':\n res.type('application/json');\n res.status(400);\n if (hasSend(res)) {\n res.send(\n `${\n collectedParseErrors ??\n prettyPrintParseErrors(parsedRequest.errors, 'Request')\n }\\n\\nCorrelation id: ${\n req.context.correlationId ?? 'No correlation ID'\n }`\n );\n } else {\n next?.(new Error('Request is not sendable.'));\n }\n return;\n case 'warning':\n req.openTelemetryCollector?.warn(\n collectedParseErrors ??\n prettyPrintParseErrors(parsedRequest.errors, 'Request')\n );\n break;\n case 'none':\n break;\n }\n }\n\n req._parsedVersions = matchedVersions;\n next?.();\n}\n","/**\n * Type guard that checks if an object has a `send` method.\n *\n * @param res - The object to check for the presence of a `send` method\n * @returns A type predicate indicating whether the object has a `send` method\n *\n * @example\n * ```ts\n * if (hasSend(response)) {\n * response.send('Hello World');\n * }\n * ```\n */\nexport function hasSend(\n res: unknown\n): res is { send: (body: unknown) => void } {\n return typeof res === 'object' && res !== null && 'send' in res;\n}\n","import { ResponseShape } from '../types/apiDefinition.types';\n\nexport function isRequestShape<Params, Headers, Query, Body>(\n maybeResponseShape: object | undefined\n): maybeResponseShape is ResponseShape<Params, Headers, Query, Body> {\n return (\n maybeResponseShape != null &&\n ('body' in maybeResponseShape ||\n 'query' in maybeResponseShape ||\n 'params' in maybeResponseShape ||\n 'headers' in maybeResponseShape)\n );\n}\n","import { EmptyObject } from '@forklaunch/common';\nimport { AnySchemaValidator } from '@forklaunch/validator';\nimport { ExpressLikeRouter } from '../interfaces/expressLikeRouter.interface';\nimport { cors } from '../middleware/request/cors.middleware';\nimport { ForklaunchExpressLikeRouter } from '../router/expressLikeRouter';\nimport { OpenTelemetryCollector } from '../telemetry/openTelemetryCollector';\nimport { SessionObject } from '../types/contractDetails.types';\nimport { ExpressLikeApplicationOptions } from '../types/expressLikeOptions';\nimport { MetricsDefinition } from '../types/openTelemetryCollector.types';\n\n/**\n * ForklaunchExpressLikeApplication class that sets up routes and middleware for an Express-like application, for use with controller/routes pattern.\n *\n * @template SV - A type that extends AnySchemaValidator.\n * @template Server - The server type.\n */\nexport abstract class ForklaunchExpressLikeApplication<\n SV extends AnySchemaValidator,\n Server extends ExpressLikeRouter<RouterHandler, Server>,\n RouterHandler,\n BaseRequest,\n BaseResponse,\n NextFunction,\n Session extends SessionObject<SV>,\n FetchMap extends Record<string, unknown> = EmptyObject,\n Sdk extends Record<string, unknown> = EmptyObject\n> extends ForklaunchExpressLikeRouter<\n SV,\n '/',\n RouterHandler,\n Server,\n BaseRequest,\n BaseResponse,\n NextFunction,\n Session,\n FetchMap,\n Sdk\n> {\n /**\n * Creates an instance of the Application class.\n *\n * @param {SV} schemaValidator - The schema validator.\n */\n constructor(\n readonly schemaValidator: SV,\n readonly internal: Server,\n readonly postEnrichMiddleware: RouterHandler[],\n readonly openTelemetryCollector: OpenTelemetryCollector<MetricsDefinition>,\n readonly appOptions?: ExpressLikeApplicationOptions<SV, Session>\n ) {\n super(\n '/',\n schemaValidator,\n internal,\n postEnrichMiddleware,\n openTelemetryCollector,\n {\n ...appOptions,\n openapi: appOptions?.openapi !== false,\n mcp: appOptions?.mcp !== false\n }\n );\n\n this.internal.use(cors(this.appOptions?.cors ?? {}) as RouterHandler);\n }\n\n /**\n * Validates all registered routes across the app and all mounted routers.\n * Call this at the start of listen() to fail fast at startup.\n */\n protected validateAllRoutes() {\n this.validateSurfacingFunctions();\n }\n\n abstract listen(...args: unknown[]): void;\n}\n","import * as net from 'net';\n\nexport function isPortBound(\n port: number,\n host: string = 'localhost'\n): Promise<boolean> {\n return new Promise((resolve) => {\n const socket = new net.Socket();\n\n socket.setTimeout(1000);\n\n socket.on('connect', () => {\n socket.destroy();\n resolve(true);\n });\n\n socket.on('timeout', () => {\n socket.destroy();\n resolve(false);\n });\n\n socket.on('error', () => {\n resolve(false);\n });\n\n socket.connect(port, host);\n });\n}\n","import { randomUUID } from 'crypto';\nimport { createHmacToken } from './createHmacToken';\n\n/**\n * Generate HMAC authorization headers for service-to-service authentication.\n *\n * @param secretKey - The shared HMAC secret key\n * @param method - HTTP method (GET, POST, etc.)\n * @param path - The API path\n * @param body - Optional request body\n * @param keyId - Optional key identifier (defaults to 'default')\n * @returns Authorization header object\n *\n * @example\n * ```typescript\n * const headers = generateHmacAuthHeaders({\n * secretKey: 'my-secret-key',\n * method: 'POST',\n * path: '/api/users',\n * body: { name: 'John' }\n * });\n * // headers.authorization = 'HMAC keyId=default ts=2024-01-16T12:00:00.000Z nonce=... signature=...'\n * ```\n */\nexport function generateHmacAuthHeaders({\n secretKey,\n method,\n path,\n body,\n keyId = 'default'\n}: {\n secretKey: string;\n method: string;\n path: string;\n body?: unknown;\n keyId?: string;\n}): {\n authorization: `HMAC keyId=${string} ts=${string} nonce=${string} signature=${string}`;\n} {\n const timestamp = new Date();\n const nonce = randomUUID();\n\n const signature = createHmacToken({\n secretKey,\n method,\n path,\n timestamp,\n nonce,\n body\n });\n\n return {\n authorization: `HMAC keyId=${keyId} ts=${timestamp.toISOString()} nonce=${nonce} signature=${signature}`\n };\n}\n","import { createHmacToken } from './createHmacToken';\nimport { generateHmacAuthHeaders } from './generateHmacAuthHeaders';\nimport { timingSafeEqual } from 'crypto';\n\n/**\n * The managed gateway (the instance gateway): how a ForkLaunch app reaches\n * platform-held services (models, payments, email, SMS, WhatsApp, voice)\n * without holding a vendor credential, and how the platform delivers vendor\n * events back to it. A managed instance and an app deployed to its own\n * environment (`forklaunch deploy create`) both use it.\n *\n * Outbound, every request is signed with the instance's own HMAC key\n * (`INSTANCE_HMAC_KEY`, key id `INSTANCE_ID`) over the router-relative path,\n * with a timestamp and a single-use nonce; the platform checks the signature,\n * the product's limits and the instance's own vendor account, then calls the\n * vendor with credentials that never leave it.\n *\n * Inbound, the platform POSTs events (a payment succeeded, an email bounced, a\n * text arrived) to `/platform-events/<feature>` on the service that declared\n * the capability, signed with the same instance key under key id `platform`.\n * `verifyPlatformEvent` checks that signature, the timestamp and the nonce.\n *\n * The platform injects `PLATFORM_GATEWAY_URL`, `INSTANCE_ID` and\n * `INSTANCE_HMAC_KEY` into a managed instance, and into the components of a\n * regular deployment that the release binds a capability to (`forklaunch\n * infra add <service> <capability>`). Their absence means the service has no\n * managed gateway, and a client refuses to be created rather than failing on\n * its first call.\n */\n\n/** Where the gateway router is mounted on the platform service. */\nexport const INSTANCE_GATEWAY_MOUNT = '/instance-gateway';\n\n/** The key id the platform signs events with. */\nexport const PLATFORM_EVENT_KEY_ID = 'platform';\n\n/** Where a service receives platform events, per feature. */\nexport const PLATFORM_EVENTS_PATH = '/platform-events';\n\nconst MAX_SKEW_MS = 5 * 60 * 1000;\n\nexport interface InstanceGatewayOptions {\n /** Platform base URL. Default: `PLATFORM_GATEWAY_URL`. */\n gatewayUrl?: string;\n /** This instance's id. Default: `INSTANCE_ID`. */\n instanceId?: string;\n /** This instance's HMAC key. Default: `INSTANCE_HMAC_KEY`. */\n hmacKey?: string;\n fetch?: typeof fetch;\n}\n\n/** A refusal or failure from the gateway, with the status it answered. */\nexport class InstanceGatewayRequestError extends Error {\n override readonly name: string = 'InstanceGatewayRequestError';\n constructor(\n readonly status: number,\n message: string,\n /** Seconds to wait before retrying, on a 429. */\n readonly retryAfterSeconds?: number\n ) {\n super(message);\n }\n}\n\nexport interface InstanceGatewayTransport {\n readonly instanceId: string;\n /** A signed request; throws `InstanceGatewayRequestError` on a non-2xx. */\n request(\n method: 'GET' | 'POST' | 'PUT' | 'DELETE',\n route: string,\n body?: Record<string, unknown>,\n options?: { signal?: AbortSignal; headers?: Record<string, string> }\n ): Promise<Response>;\n /** `request`, then the JSON body. */\n json<T>(\n method: 'GET' | 'POST' | 'PUT' | 'DELETE',\n route: string,\n body?: Record<string, unknown>,\n options?: { signal?: AbortSignal; headers?: Record<string, string> }\n ): Promise<T>;\n}\n\n/** Resolve the managed-mode settings, or explain which are missing. */\nexport function instanceGatewaySettings(\n options: InstanceGatewayOptions = {},\n feature = 'The instance gateway'\n): { gatewayUrl: string; instanceId: string; hmacKey: string } {\n const gatewayUrl = options.gatewayUrl ?? process.env.PLATFORM_GATEWAY_URL;\n const instanceId = options.instanceId ?? process.env.INSTANCE_ID;\n const hmacKey = options.hmacKey ?? process.env.INSTANCE_HMAC_KEY;\n if (!gatewayUrl || !instanceId || !hmacKey) {\n throw new Error(\n `${feature} goes through the ForkLaunch managed gateway: ` +\n 'PLATFORM_GATEWAY_URL, INSTANCE_ID and INSTANCE_HMAC_KEY must be set. ' +\n 'The platform sets them for a managed instance, and at deploy for a component ' +\n 'that declares the capability (`forklaunch infra add <service> <capability>`), ' +\n 'which also points them at the local gateway mock'\n );\n }\n return { gatewayUrl, instanceId, hmacKey };\n}\n\n/** Whether this process runs as a managed instance. */\nexport function isManagedInstance(\n env: Record<string, string | undefined> = process.env\n): boolean {\n return Boolean(\n env.PLATFORM_GATEWAY_URL && env.INSTANCE_ID && env.INSTANCE_HMAC_KEY\n );\n}\n\nfunction trimTrailingSlashes(value: string): string {\n // Without a regex: `/\\/+$/` backtracks on long runs.\n let end = value.length;\n while (end > 0 && value[end - 1] === '/') end -= 1;\n return value.slice(0, end);\n}\n\n/** A signed transport to the instance gateway. */\nexport function createInstanceGatewayTransport(\n options: InstanceGatewayOptions = {},\n feature?: string\n): InstanceGatewayTransport {\n const { gatewayUrl, instanceId, hmacKey } = instanceGatewaySettings(\n options,\n feature\n );\n const fetchImpl = options.fetch ?? fetch;\n const base = trimTrailingSlashes(gatewayUrl);\n\n const request: InstanceGatewayTransport['request'] = async (\n method,\n route,\n body,\n requestOptions = {}\n ) => {\n // The gateway verifies the router-relative path, and the body as parsed.\n const { authorization } = generateHmacAuthHeaders({\n secretKey: hmacKey,\n method,\n path: route,\n body,\n keyId: instanceId\n });\n const response = await fetchImpl(`${base}${INSTANCE_GATEWAY_MOUNT}${route}`, {\n method,\n headers: {\n ...requestOptions.headers,\n authorization,\n ...(body ? { 'content-type': 'application/json' } : {})\n },\n body: body ? JSON.stringify(body) : undefined,\n signal: requestOptions.signal\n });\n if (!response.ok) {\n const message = (await response.text().catch(() => '')).trim();\n const retryAfter = Number(response.headers.get('retry-after'));\n throw new InstanceGatewayRequestError(\n response.status,\n message || `Instance gateway answered ${response.status}`,\n Number.isFinite(retryAfter) && retryAfter > 0 ? retryAfter : undefined\n );\n }\n return response;\n };\n\n return {\n instanceId,\n request,\n async json<T>(\n method: 'GET' | 'POST' | 'PUT' | 'DELETE',\n route: string,\n body?: Record<string, unknown>,\n requestOptions?: { signal?: AbortSignal; headers?: Record<string, string> }\n ): Promise<T> {\n return (await (\n await request(method, route, body, requestOptions)\n ).json()) as T;\n }\n };\n}\n\n/** An event the platform delivered to this instance. */\nexport interface PlatformEvent<Data = Record<string, unknown>> {\n /** Unique per event; deliveries can repeat, so handlers dedupe on it. */\n id: string;\n /** The capability it belongs to: payments, email, sms, whatsapp, voice. */\n feature: string;\n /** e.g. `checkout.session.completed`, `email.bounced`, `sms.received`. */\n type: string;\n occurredAt: string;\n data: Data;\n}\n\nexport class PlatformEventVerificationError extends Error {\n override readonly name = 'PlatformEventVerificationError';\n}\n\nconst seenEventNonces = new Map<string, number>();\n\n/**\n * Verify an event the platform delivered and return it.\n *\n * `path` is the path the request arrived on (`/platform-events/payments`);\n * `rawBody` is the exact request body (a string or Buffer) — pass the raw\n * bytes when the framework captured them, else the parsed body. Throws\n * `PlatformEventVerificationError` for a missing, stale, forged or replayed\n * delivery; answer 401 then, and the platform retries.\n */\nexport function verifyPlatformEvent<Data = Record<string, unknown>>(\n request: {\n method: string;\n path: string;\n headers: Record<string, string | string[] | undefined>;\n body: unknown;\n },\n options: { hmacKey?: string; now?: () => number } = {}\n): PlatformEvent<Data> {\n const hmacKey = options.hmacKey ?? process.env.INSTANCE_HMAC_KEY;\n if (!hmacKey) {\n throw new PlatformEventVerificationError(\n 'INSTANCE_HMAC_KEY is not set: this service is not a managed instance'\n );\n }\n const header = request.headers.authorization ?? request.headers.Authorization;\n const value = Array.isArray(header) ? header[0] : header;\n const match =\n /^HMAC keyId=(\\S+) ts=(\\S+) nonce=(\\S+) signature=(\\S+)$/.exec(\n value ?? ''\n );\n if (!match) {\n throw new PlatformEventVerificationError(\n 'Missing or malformed HMAC authorization'\n );\n }\n const [, keyId, ts, nonce, signature] = match;\n if (keyId !== PLATFORM_EVENT_KEY_ID) {\n throw new PlatformEventVerificationError('Not signed by the platform');\n }\n const timestamp = new Date(ts);\n const now = (options.now ?? Date.now)();\n if (\n Number.isNaN(timestamp.getTime()) ||\n Math.abs(now - timestamp.getTime()) > MAX_SKEW_MS\n ) {\n throw new PlatformEventVerificationError('Stale or invalid timestamp');\n }\n const expected = Buffer.from(\n createHmacToken({\n secretKey: hmacKey,\n method: request.method.toUpperCase(),\n path: request.path,\n body: request.body,\n timestamp,\n nonce\n })\n );\n const received = Buffer.from(signature);\n if (\n expected.length !== received.length ||\n !timingSafeEqual(expected, received)\n ) {\n throw new PlatformEventVerificationError('Invalid signature');\n }\n for (const [seen, at] of seenEventNonces) {\n if (now - at > MAX_SKEW_MS) seenEventNonces.delete(seen);\n }\n if (seenEventNonces.has(nonce)) {\n throw new PlatformEventVerificationError('Replayed delivery');\n }\n seenEventNonces.set(nonce, now);\n\n const parsed =\n typeof request.body === 'string' || Buffer.isBuffer(request.body)\n ? JSON.parse(request.body.toString())\n : request.body;\n const event = parsed as Partial<PlatformEvent<Data>>;\n if (\n !event ||\n typeof event.id !== 'string' ||\n typeof event.type !== 'string' ||\n typeof event.feature !== 'string'\n ) {\n throw new PlatformEventVerificationError('Body is not a platform event');\n }\n return event as PlatformEvent<Data>;\n}\n\n/**\n * Sign an event delivery the way the platform does. For tests and the local\n * gateway mock; the platform has its own copy.\n */\nexport function signPlatformEvent(params: {\n hmacKey: string;\n path: string;\n body: string;\n}): { authorization: string } {\n return generateHmacAuthHeaders({\n secretKey: params.hmacKey,\n method: 'POST',\n path: params.path,\n body: params.body,\n keyId: PLATFORM_EVENT_KEY_ID\n });\n}\n","import {\n createInstanceGatewayTransport,\n InstanceGatewayRequestError\n} from './instanceGateway';\n\n/**\n * Client for the ForkLaunch model gateway (part of the managed gateway), for\n * a managed instance or any app deployed on ForkLaunch.\n *\n * The service calls platform-hosted AI models (Azure AI Foundry) without\n * holding a provider key: each request is signed with its own HMAC key, and\n * the platform enforces the model allowlist, monthly token budget and rate\n * limit. For a HIPAA product the platform only offers models covered by its\n * BAA.\n *\n * The platform injects everything this needs: `PLATFORM_GATEWAY_URL` (the\n * platform's public base), `INSTANCE_ID` and `INSTANCE_HMAC_KEY`, into a\n * managed instance and, at deploy, into a component that declares models\n * (`forklaunch infra add <service> models`, which also points them at the\n * local gateway mock). Without them the client refuses to be created rather\n * than failing on the first call.\n *\n * @example\n * const models = createModelGatewayClient();\n * const reply = await models.chat.completions.create({\n * model: 'terra',\n * messages: [{ role: 'user', content: 'Summarize this intake form: …' }]\n * });\n * for await (const chunk of models.chat.completions.stream({ model: 'luna', messages })) {\n * process.stdout.write(chunk.choices[0]?.delta?.content ?? '');\n * }\n */\n\nexport interface ModelGatewayClientOptions {\n /** Platform base URL. Default: `PLATFORM_GATEWAY_URL`. */\n gatewayUrl?: string;\n /** This instance's id. Default: `INSTANCE_ID`. */\n instanceId?: string;\n /** This instance's HMAC key. Default: `INSTANCE_HMAC_KEY`. */\n hmacKey?: string;\n fetch?: typeof fetch;\n}\n\n/** An OpenAI-style chat message. */\nexport interface GatewayChatMessage {\n role: 'system' | 'developer' | 'user' | 'assistant' | 'tool';\n content: unknown;\n [key: string]: unknown;\n}\n\n/** An OpenAI-compatible chat completions request; `model` is a catalog alias. */\nexport interface GatewayChatRequest {\n model: string;\n messages: GatewayChatMessage[];\n temperature?: number;\n top_p?: number;\n max_tokens?: number;\n max_completion_tokens?: number;\n response_format?: unknown;\n tools?: unknown[];\n tool_choice?: unknown;\n parallel_tool_calls?: boolean;\n stop?: unknown;\n seed?: number;\n presence_penalty?: number;\n frequency_penalty?: number;\n reasoning_effort?: string;\n}\n\nexport interface GatewayChatCompletion {\n id: string;\n object: string;\n created: number;\n model: string;\n choices: {\n index: number;\n message: { role: string; content: string | null; [key: string]: unknown };\n finish_reason: string | null;\n [key: string]: unknown;\n }[];\n usage?: {\n prompt_tokens: number;\n completion_tokens: number;\n total_tokens: number;\n };\n [key: string]: unknown;\n}\n\nexport interface GatewayChatChunk {\n id: string;\n object: string;\n model: string;\n choices: {\n index: number;\n delta: { role?: string; content?: string | null; [key: string]: unknown };\n finish_reason?: string | null;\n }[];\n usage?: GatewayChatCompletion['usage'];\n [key: string]: unknown;\n}\n\nexport interface GatewayModels {\n models: { id: string; baa: boolean }[];\n monthlyTokenBudget: number;\n tokensUsedThisMonth: number;\n requestsPerMinute: number;\n withheldForHipaa?: string[];\n}\n\n/** A refusal or failure from the gateway, with the status it answered. */\nexport class ModelGatewayRequestError extends InstanceGatewayRequestError {\n override readonly name = 'ModelGatewayRequestError' as const;\n}\n\nexport interface ModelGatewayClient {\n /** The models this instance may call, and where its monthly budget stands. */\n models(): Promise<GatewayModels>;\n chat: {\n completions: {\n create(request: GatewayChatRequest): Promise<GatewayChatCompletion>;\n stream(\n request: GatewayChatRequest,\n options?: { signal?: AbortSignal }\n ): AsyncGenerator<GatewayChatChunk>;\n };\n };\n}\n\nexport function createModelGatewayClient(\n options: ModelGatewayClientOptions = {}\n): ModelGatewayClient {\n const transport = createInstanceGatewayTransport(options, 'The model gateway');\n\n async function send(\n method: 'GET' | 'POST',\n route: string,\n body?: Record<string, unknown>,\n signal?: AbortSignal\n ): Promise<Response> {\n try {\n return await transport.request(method, route, body, { signal });\n } catch (error) {\n if (error instanceof InstanceGatewayRequestError) {\n throw new ModelGatewayRequestError(\n error.status,\n error.message,\n error.retryAfterSeconds\n );\n }\n throw error;\n }\n }\n\n return {\n async models() {\n return (await (await send('GET', '/models')).json()) as GatewayModels;\n },\n chat: {\n completions: {\n async create(request) {\n const response = await send(\n 'POST',\n '/models/chat/completions',\n request as unknown as Record<string, unknown>\n );\n return (await response.json()) as GatewayChatCompletion;\n },\n async *stream(request, streamOptions = {}) {\n const response = await send(\n 'POST',\n '/models/chat/completions/stream',\n request as unknown as Record<string, unknown>,\n streamOptions.signal\n );\n if (!response.body) return;\n for await (const data of sseData(response.body)) {\n if (data === '[DONE]') return;\n try {\n yield JSON.parse(data) as GatewayChatChunk;\n } catch {\n // not a chunk; skip it\n }\n }\n }\n }\n }\n };\n}\n\n/** The `data:` payloads of a server-sent-event stream, in order. */\nasync function* sseData(\n stream: ReadableStream<Uint8Array>\n): AsyncGenerator<string> {\n const decoder = new TextDecoder();\n let buffer = '';\n const reader = stream.getReader();\n try {\n for (;;) {\n const { value, done } = await reader.read();\n if (done) break;\n buffer += decoder.decode(value, { stream: true });\n let boundary: number;\n while ((boundary = buffer.search(/\\r?\\n\\r?\\n/)) !== -1) {\n const event = buffer.slice(0, boundary);\n buffer = buffer.slice(boundary).replace(/^\\r?\\n\\r?\\n/, '');\n const data = event\n .split(/\\r?\\n/)\n .filter((line) => line.startsWith('data:'))\n .map((line) => line.slice(5).trimStart())\n .join('\\n');\n if (data) yield data;\n }\n }\n const tail = buffer.trim();\n if (tail.startsWith('data:')) yield tail.slice(5).trimStart();\n } finally {\n reader.releaseLock();\n }\n}\n","import {\n createInstanceGatewayTransport,\n InstanceGatewayRequestError\n} from './instanceGateway';\nimport {\n ModelGatewayRequestError,\n type GatewayChatCompletion,\n type GatewayChatRequest,\n type ModelGatewayClientOptions\n} from './modelGatewayClient';\n\n/** A local preview's issued ceilings, not a managed product's monthly usage. */\nexport interface GatewayPreviewModels {\n models: { id: string }[];\n preview: {\n /** Capability expiration, in Unix milliseconds. */\n expiresAt: number;\n /** Initial request ceiling; this is not a remaining-request count. */\n maxCalls: number;\n /** Initial conservative allowance units, not billable or monthly tokens. */\n maxUnits: number;\n };\n}\n\n/** Preview relays may omit a provider timestamp; they must not invent one. */\nexport interface GatewayPreviewChatCompletion extends Pick<\n GatewayChatCompletion,\n 'id' | 'object' | 'model' | 'choices' | 'usage'\n> {\n created?: number;\n [key: string]: unknown;\n}\n\nexport interface PreviewModelGatewayClient {\n models(): Promise<GatewayPreviewModels>;\n chat: {\n completions: {\n create(\n request: GatewayChatRequest\n ): Promise<GatewayPreviewChatCompletion>;\n };\n };\n}\n\nfunction record(value: unknown): value is Record<string, unknown> {\n return !!value && typeof value === 'object' && !Array.isArray(value);\n}\nfunction invalidCatalog(): never {\n throw new ModelGatewayRequestError(\n 502,\n 'The local preview model catalog is invalid or expired.'\n );\n}\nfunction previewCatalog(raw: unknown): GatewayPreviewModels {\n if (!record(raw) || !record(raw.preview)) return invalidCatalog();\n const preview = raw.preview;\n if (\n Object.keys(raw).some((key) => !['models', 'preview'].includes(key)) ||\n Object.keys(preview).some(\n (key) => !['expiresAt', 'maxCalls', 'maxUnits'].includes(key)\n ) ||\n !Array.isArray(raw.models) ||\n raw.models.length !== 1 ||\n !record(raw.models[0]) ||\n Object.keys(raw.models[0]).some((key) => key !== 'id') ||\n typeof raw.models[0].id !== 'string' ||\n !/^[\\w.:-]{1,160}$/.test(raw.models[0].id) ||\n typeof preview.expiresAt !== 'number' ||\n !Number.isSafeInteger(preview.expiresAt) ||\n preview.expiresAt <= Date.now() ||\n preview.expiresAt > Date.now() + 15 * 60_000 ||\n typeof preview.maxCalls !== 'number' ||\n !Number.isSafeInteger(preview.maxCalls) ||\n preview.maxCalls < 1 ||\n preview.maxCalls > 20 ||\n typeof preview.maxUnits !== 'number' ||\n !Number.isSafeInteger(preview.maxUnits) ||\n preview.maxUnits < 1 ||\n preview.maxUnits > 100_000\n )\n return invalidCatalog();\n return {\n models: [{ id: raw.models[0].id }],\n preview: {\n expiresAt: preview.expiresAt,\n maxCalls: preview.maxCalls,\n maxUnits: preview.maxUnits\n }\n };\n}\nasync function readPreviewCatalog(\n response: Response\n): Promise<GatewayPreviewModels> {\n if (!response.body) return invalidCatalog();\n const reader = response.body.getReader();\n const decoder = new TextDecoder();\n let text = '',\n bytes = 0;\n try {\n for (;;) {\n const { done, value } = await reader.read();\n if (done) break;\n bytes += value.byteLength;\n if (bytes > 8192) return invalidCatalog();\n text += decoder.decode(value, { stream: true });\n }\n text += decoder.decode();\n return previewCatalog(JSON.parse(text));\n } catch {\n return invalidCatalog();\n } finally {\n await reader.cancel().catch(() => {});\n reader.releaseLock();\n }\n}\n\n/**\n * Use only for the desktop's isolated local preview relay. The desktop supplies\n * PLATFORM_GATEWAY_URL, INSTANCE_ID and a preview-only INSTANCE_HMAC_KEY.\n * This client neither holds the desktop login nor calls a provider directly.\n *\n * Unlike createModelGatewayClient (managed instances), this catalog makes no\n * monthly-token or BAA claims. Streaming is not supported by the preview relay.\n * The gateway still applies its own bounded chat request protocol.\n *\n * @example\n * const client = createPreviewModelGatewayClient();\n * const catalog = await client.models();\n * const reply = await client.chat.completions.create({\n * model: catalog.models[0].id,\n * messages: [{ role: 'user', content: 'Help plan my task.' }]\n * });\n * // catalog.preview.maxUnits is an issued ceiling, not remaining monthly usage.\n */\nexport function createPreviewModelGatewayClient(\n options: ModelGatewayClientOptions = {}\n): PreviewModelGatewayClient {\n const transport = createInstanceGatewayTransport(\n options,\n 'The local preview model gateway'\n );\n async function send(\n method: 'GET' | 'POST',\n route: string,\n body?: Record<string, unknown>\n ): Promise<Response> {\n try {\n return await transport.request(method, route, body);\n } catch (error) {\n if (error instanceof InstanceGatewayRequestError)\n throw new ModelGatewayRequestError(\n error.status,\n 'The local preview model request was refused or is unavailable.',\n error.retryAfterSeconds\n );\n throw error;\n }\n }\n return {\n async models() {\n const response = await send('GET', '/models');\n return readPreviewCatalog(response);\n },\n chat: {\n completions: {\n async create(request) {\n return (await (\n await send(\n 'POST',\n '/models/chat/completions',\n request as unknown as Record<string, unknown>\n )\n ).json()) as GatewayPreviewChatCompletion;\n }\n }\n }\n };\n}\n","import {\n createInstanceGatewayTransport,\n InstanceGatewayRequestError,\n isManagedInstance\n} from './instanceGateway';\n\n/**\n * Client for platform-held email through the managed gateway, from a managed\n * instance or any app deployed on ForkLaunch.\n *\n * The instance never holds a mail credential. It signs each request with its\n * own HMAC key; the platform sends through Amazon SES from the instance's own\n * sending identity (`no-reply@<instance>.<platform sending domain>`, a claimed\n * custom domain later) under a per-instance configuration set, enforces the\n * product's daily quota and rate, and refuses addresses on the instance's\n * suppression list (hard bounces and complaints).\n *\n * Delivery outcomes come back as platform events on\n * `/platform-events/email`: `email.delivered`, `email.bounced` and\n * `email.complained`, each carrying the `messageId` `send` returned. A bounced\n * or complained address is suppressed by the platform; mark it undeliverable\n * in the app too so the person can be asked for a new one.\n *\n * Locally, `forklaunch infra add <service> email` points the service at the\n * gateway mock in docker-compose (PLATFORM_GATEWAY_URL, INSTANCE_ID,\n * INSTANCE_HMAC_KEY), which records messages (GET /__mock/email/messages) and\n * emits the same events. Outside managed mode and without those settings,\n * `createEmailClient` refuses to be created.\n *\n * What to put where: the body may hold what the recipient is entitled to\n * read; the subject shows on lock screens, in notification previews and in\n * mail logs, so never put protected data (a `.deanon` value) in it.\n *\n * @example\n * const email = createEmailClient();\n * const { messageId } = await email.send({\n * to: 'pat@example.com',\n * subject: 'Your appointment is confirmed',\n * text: 'See you on Tuesday at 10:00.'\n * });\n * if (await email.suppressed('pat@example.com')) { … ask for another address }\n *\n * @example One-click unsubscribe (RFC 8058), which Gmail and Yahoo require of\n * bulk senders: the platform adds `List-Unsubscribe` and\n * `List-Unsubscribe-Post: List-Unsubscribe=One-Click`.\n * await email.send({\n * to: member.email,\n * subject: 'Your weekly recap',\n * html,\n * listUnsubscribe: {\n * url: `https://app.example.com/unsubscribe?token=${token}`, // accepts POST\n * oneClick: true\n * }\n * });\n */\n\nexport interface EmailClientOptions {\n /** Platform base URL. Default: `PLATFORM_GATEWAY_URL`. */\n gatewayUrl?: string;\n /** This instance's id. Default: `INSTANCE_ID`. */\n instanceId?: string;\n /** This instance's HMAC key. Default: `INSTANCE_HMAC_KEY`. */\n hmacKey?: string;\n fetch?: typeof fetch;\n}\n\nexport interface EmailSendRequest {\n /** One address or up to 50. */\n to: string | string[];\n /** Plain text, one line; shown in previews and logs — no protected data. */\n subject: string;\n /** At least one of `text` and `html`. */\n text?: string;\n html?: string;\n replyTo?: string | string[];\n /**\n * Up to 10 tags, echoed on the delivery events. Names and values:\n * letters, digits, `_` and `-`. Names starting `fl-` or `ses:` are reserved.\n */\n tags?: Record<string, string>;\n /** `List-Unsubscribe` targets; see {@link EmailListUnsubscribe}. */\n listUnsubscribe?: EmailListUnsubscribe;\n}\n\n/**\n * Where a recipient unsubscribes: the `List-Unsubscribe` header (RFC 2369),\n * plus `List-Unsubscribe-Post: List-Unsubscribe=One-Click` (RFC 8058) with\n * `oneClick`. The platform writes the headers; these are targets, not header\n * text.\n *\n * - `url`: https only, printable ASCII up to 512 characters, no `< > , \" \\`\n * (percent-encode them). With `oneClick`, mailbox providers POST\n * `List-Unsubscribe=One-Click` to it (form-encoded, no cookies): it must\n * unsubscribe from that alone, without a confirmation page.\n * - `mailto`: a plain mailbox (letters, digits, `. _ + -` before the `@`).\n *\n * The headers go to every address in `to`; for a per-recipient link, send\n * one message per recipient.\n */\nexport type EmailListUnsubscribe =\n | { url: string; mailto?: string; oneClick?: boolean }\n | { url?: undefined; mailto: string; oneClick?: false };\n\nexport interface EmailSendResult {\n /** The provider's message id; delivery events carry it. */\n messageId: string;\n}\n\n/** Data on `email.delivered`, `email.bounced` and `email.complained` events. */\nexport interface EmailEventData {\n messageId: string;\n recipients: string[];\n tags?: Record<string, string>;\n /** `email.bounced`: `Permanent`, `Transient` or `Undetermined`. */\n bounceType?: string;\n bounceSubType?: string;\n /** `email.bounced`: whether the platform suppressed the addresses. */\n permanent?: boolean;\n /** `email.complained`: the feedback type the mailbox provider reported. */\n feedbackType?: string;\n}\n\n/** A refusal or failure, from the gateway or from validation before sending. */\nexport class EmailRequestError extends InstanceGatewayRequestError {\n override readonly name = 'EmailRequestError' as const;\n}\n\nexport interface EmailClient {\n /** Send one message; throws `EmailRequestError` on a refusal. */\n send(request: EmailSendRequest): Promise<EmailSendResult>;\n /** Whether the platform refuses to send to `address` (bounce/complaint). */\n suppressed(address: string): Promise<boolean>;\n}\n\n/** Limits the platform enforces too; checked here so a bad call fails fast. */\nexport const EMAIL_LIMITS = {\n maxRecipients: 50,\n maxAddressLength: 254,\n maxSubjectLength: 998,\n /** text + html, UTF-8 bytes. */\n maxBodyBytes: 512 * 1024,\n maxTags: 10,\n /** `listUnsubscribe.url`; keeps the header within SES's limit. */\n maxUnsubscribeUrlLength: 512\n} as const;\n\nconst ADDRESS =\n /^[^\\s@<>()[\\]\\\\,;:\"]+@[A-Za-z0-9](?:[A-Za-z0-9-]*[A-Za-z0-9])?(?:\\.[A-Za-z0-9](?:[A-Za-z0-9-]*[A-Za-z0-9])?)+$/;\nconst TAG_PART = /^[A-Za-z0-9_-]{1,256}$/;\n/** Printable ASCII, no space: nothing that can end or fold a header line. */\nconst HEADER_SAFE = /^[\\x21-\\x7e]+$/;\n/** Delimiters of the header's `<…>, <…>` list; percent-encode them instead. */\nconst URL_DELIMITERS = /[<>,\"\\\\]/;\nconst MAILBOX =\n /^[A-Za-z0-9._+-]+@[A-Za-z0-9](?:[A-Za-z0-9-]*[A-Za-z0-9])?(?:\\.[A-Za-z0-9](?:[A-Za-z0-9-]*[A-Za-z0-9])?)+$/;\nconst UNSUBSCRIBE_FIELDS = new Set(['url', 'mailto', 'oneClick']);\n\n/** Whether `address` is a plain mailbox address (`local@domain.tld`). */\nexport function isEmailAddress(address: unknown): address is string {\n return (\n typeof address === 'string' &&\n address.length <= EMAIL_LIMITS.maxAddressLength &&\n ADDRESS.test(address)\n );\n}\n\nfunction refuse(message: string): never {\n throw new EmailRequestError(400, message);\n}\n\nfunction addresses(value: string | string[] | undefined, field: string) {\n if (value === undefined) return undefined;\n const list = Array.isArray(value) ? value : [value];\n if (list.length === 0) refuse(`${field} must name at least one address`);\n if (list.length > EMAIL_LIMITS.maxRecipients) {\n refuse(\n `${field} has ${list.length} addresses; the limit is ${EMAIL_LIMITS.maxRecipients}`\n );\n }\n for (const address of list) {\n if (!isEmailAddress(address)) {\n refuse(\n `${field}: '${String(address).slice(0, 80)}' is not an email address`\n );\n }\n }\n return list;\n}\n\nfunction fail(problem: string): never {\n refuse(`listUnsubscribe: ${problem}`);\n}\n\nfunction unsubscribeUrlProblem(url: unknown): string | null {\n if (typeof url !== 'string' || url === '') return 'url must be a string';\n if (url.length > EMAIL_LIMITS.maxUnsubscribeUrlLength) {\n return `url is longer than ${EMAIL_LIMITS.maxUnsubscribeUrlLength} characters`;\n }\n if (!HEADER_SAFE.test(url)) {\n return 'url must be printable ASCII with no spaces or line breaks; percent-encode anything else';\n }\n if (URL_DELIMITERS.test(url)) {\n return 'url must not contain < > , \" or \\\\; percent-encode them';\n }\n let parsed: URL;\n try {\n parsed = new URL(url);\n } catch {\n return 'url is not a URL';\n }\n if (parsed.protocol !== 'https:') return 'url must be https';\n if (parsed.username || parsed.password) {\n return 'url must not carry a user name or password';\n }\n return null;\n}\n\n/**\n * Check `listUnsubscribe` the way the gateway does; returns its wire form.\n * At least one of `url` and `mailto`; `oneClick` only with `url`.\n */\nexport function validateListUnsubscribe(\n value: unknown\n): EmailListUnsubscribe | undefined {\n if (value === undefined || value === null) return undefined;\n if (typeof value !== 'object' || Array.isArray(value)) {\n fail('must be an object');\n }\n const unknownFields = Object.keys(value).filter(\n (key) => !UNSUBSCRIBE_FIELDS.has(key)\n );\n if (unknownFields.length) {\n fail(`unknown field ${unknownFields.map((k) => `'${k}'`).join(', ')}`);\n }\n const url = 'url' in value ? value.url : undefined;\n const mailto = 'mailto' in value ? value.mailto : undefined;\n const oneClick = 'oneClick' in value ? value.oneClick : undefined;\n if (url === undefined && mailto === undefined) {\n fail('needs a url or a mailto');\n }\n if (url !== undefined) {\n const problem = unsubscribeUrlProblem(url);\n if (problem) fail(problem);\n }\n if (\n mailto !== undefined &&\n (typeof mailto !== 'string' ||\n mailto.length > EMAIL_LIMITS.maxAddressLength ||\n !MAILBOX.test(mailto))\n ) {\n fail(\n `mailto: '${String(mailto).slice(0, 80)}' is not a plain mailbox (letters, digits, . _ + - before the @)`\n );\n }\n if (oneClick !== undefined && typeof oneClick !== 'boolean') {\n fail('oneClick must be true or false');\n }\n if (typeof url === 'string') {\n return {\n url,\n ...(typeof mailto === 'string' ? { mailto } : {}),\n ...(oneClick === true ? { oneClick: true } : {})\n };\n }\n if (oneClick === true) fail('oneClick needs a url (RFC 8058 posts to it)');\n if (typeof mailto === 'string') return { mailto };\n return fail('needs a url or a mailto');\n}\n\n/** Validate a send request the way the gateway does; returns the wire body. */\nexport function validateEmailSendRequest(\n request: EmailSendRequest\n): Record<string, unknown> {\n const to = addresses(request.to, 'to') ?? refuse('to is required');\n const replyTo = addresses(request.replyTo, 'replyTo');\n const subject = request.subject;\n if (typeof subject !== 'string' || subject.trim() === '') {\n refuse('subject is required');\n }\n if (/[\\r\\n]/.test(subject)) refuse('subject must be one line');\n if (subject.length > EMAIL_LIMITS.maxSubjectLength) {\n refuse(\n `subject is longer than ${EMAIL_LIMITS.maxSubjectLength} characters`\n );\n }\n if (!request.text && !request.html) refuse('text or html is required');\n const bytes =\n Buffer.byteLength(request.text ?? '', 'utf8') +\n Buffer.byteLength(request.html ?? '', 'utf8');\n if (bytes > EMAIL_LIMITS.maxBodyBytes) {\n refuse(`body is ${bytes} bytes; the limit is ${EMAIL_LIMITS.maxBodyBytes}`);\n }\n const tags = request.tags ?? {};\n const names = Object.keys(tags);\n if (names.length > EMAIL_LIMITS.maxTags) {\n refuse(`${names.length} tags; the limit is ${EMAIL_LIMITS.maxTags}`);\n }\n for (const name of names) {\n if (!TAG_PART.test(name) || !TAG_PART.test(String(tags[name]))) {\n refuse(`tag '${name}': names and values are letters, digits, _ and -`);\n }\n if (name.startsWith('fl-') || name.startsWith('ses:')) {\n refuse(`tag '${name}' is reserved`);\n }\n }\n const listUnsubscribe = validateListUnsubscribe(request.listUnsubscribe);\n return {\n to,\n subject,\n ...(request.text !== undefined ? { text: request.text } : {}),\n ...(request.html !== undefined ? { html: request.html } : {}),\n ...(replyTo ? { replyTo } : {}),\n ...(names.length ? { tags } : {}),\n ...(listUnsubscribe ? { listUnsubscribe } : {})\n };\n}\n\nexport function createEmailClient(\n options: EmailClientOptions = {}\n): EmailClient {\n if (\n !isManagedInstance({\n PLATFORM_GATEWAY_URL:\n options.gatewayUrl ?? process.env.PLATFORM_GATEWAY_URL,\n INSTANCE_ID: options.instanceId ?? process.env.INSTANCE_ID,\n INSTANCE_HMAC_KEY: options.hmacKey ?? process.env.INSTANCE_HMAC_KEY\n })\n ) {\n throw new Error(\n 'Email is sent by the ForkLaunch platform: PLATFORM_GATEWAY_URL, INSTANCE_ID and INSTANCE_HMAC_KEY must be set. ' +\n 'A managed instance and an app deployed with `forklaunch deploy create` get them from the platform at deploy. ' +\n 'Locally, `forklaunch infra add <service> email` sets them to the gateway mock in docker-compose.'\n );\n }\n const transport = createInstanceGatewayTransport(options, 'Email');\n\n async function call<T>(\n method: 'GET' | 'POST',\n route: string,\n body?: Record<string, unknown>\n ): Promise<T> {\n try {\n return await transport.json<T>(method, route, body);\n } catch (error) {\n if (error instanceof InstanceGatewayRequestError) {\n throw new EmailRequestError(\n error.status,\n error.message,\n error.retryAfterSeconds\n );\n }\n throw error;\n }\n }\n\n return {\n async send(request) {\n return call<EmailSendResult>(\n 'POST',\n '/email/send',\n validateEmailSendRequest(request)\n );\n },\n async suppressed(address) {\n if (!isEmailAddress(address)) {\n refuse(`'${String(address).slice(0, 80)}' is not an email address`);\n }\n const answer = await call<{ suppressed: boolean }>(\n 'GET',\n `/email/suppressions/${encodeURIComponent(address.toLowerCase())}`\n );\n return answer.suppressed === true;\n }\n };\n}\n","import {\n createInstanceGatewayTransport,\n InstanceGatewayRequestError,\n isManagedInstance,\n type InstanceGatewayOptions,\n type InstanceGatewayTransport,\n type PlatformEvent\n} from './instanceGateway';\n\n/**\n * Client for platform-held SMS (AWS End User Messaging SMS) through the\n * managed gateway, from a managed instance or any app deployed on ForkLaunch.\n *\n * The instance never holds an AWS credential or a phone number. It signs each\n * send with its own HMAC key; the platform checks the instance's monthly\n * segment cap, its rate limit and its opt-out list, then sends from the\n * product's origination pool under a configuration set named for the\n * instance, so delivery receipts come back to this instance and no other.\n *\n * Events arrive at `POST /platform-events/sms` (verify them with\n * `verifyPlatformEvent`): `sms.delivered`, `sms.failed`, `sms.received`\n * (a reply) and `sms.opted_out` (the person texted STOP; further sends to that\n * number are refused with 422).\n *\n * A text message is not a secure channel: carriers, the handset's lock screen\n * and anyone holding the phone can read it. Never put protected data (a\n * `.deanon` value, a diagnosis, a result) in `body`; send a link to sign in\n * instead. `forklaunch score` flags it (`sms-protected-data`).\n *\n * Locally, run the gateway mock (`npx -p @forklaunch/core\n * forklaunch-gateway-mock`, or the `gateway-mock` compose service that\n * `forklaunch infra add <service> sms` wires) and point PLATFORM_GATEWAY_URL,\n * INSTANCE_ID and INSTANCE_HMAC_KEY at it.\n *\n * @example\n * const sms = createSmsClient();\n * const { messageId, segments } = await sms.send({\n * to: '+14155550123',\n * body: 'Your appointment is confirmed. Sign in for details: https://…',\n * purpose: 'transactional'\n * });\n */\n\nexport interface SmsClientOptions extends InstanceGatewayOptions {\n /**\n * Refuse on the first `send` rather than at creation when the service is\n * not a managed instance. For dependency containers that build singletons\n * at boot, so a local run without the gateway still starts.\n */\n deferRefusal?: boolean;\n}\n\nexport type SmsPurpose = 'transactional' | 'promotional';\n\nexport interface SmsSendRequest {\n /** E.164, e.g. `+14155550123`. */\n to: string;\n /** Plain text. At most `SMS_MAX_SEGMENTS` segments. */\n body: string;\n /** Default `transactional`. Promotional texts need prior marketing consent. */\n purpose?: SmsPurpose;\n}\n\nexport interface SmsSendResult {\n /** The vendor's message id; delivery events carry it. */\n messageId: string;\n /** Billed segments (a long or non-GSM message is several). */\n segments: number;\n}\n\nexport interface SmsDeliveredData {\n messageId: string;\n to: string;\n deliveredAt?: string;\n}\nexport interface SmsFailedData {\n messageId: string;\n to: string;\n reason: string;\n}\nexport interface SmsReceivedData {\n from: string;\n body: string;\n receivedAt: string;\n /** The recognized keyword (STOP, HELP, START…), when the text was one. */\n keyword?: string;\n}\nexport interface SmsOptedOutData {\n phone: string;\n optedOutAt: string;\n}\n\n/** The events the platform delivers for SMS. */\nexport type SmsEvent =\n | (PlatformEvent<SmsDeliveredData> & { type: 'sms.delivered' })\n | (PlatformEvent<SmsFailedData> & { type: 'sms.failed' })\n | (PlatformEvent<SmsReceivedData> & { type: 'sms.received' })\n | (PlatformEvent<SmsOptedOutData> & { type: 'sms.opted_out' });\n\n/** A refusal or failure from the SMS gateway, with the status it answered. */\nexport class SmsRequestError extends InstanceGatewayRequestError {\n override readonly name = 'SmsRequestError' as const;\n}\n\n/** An input the client refuses before any network call. */\nexport class SmsValidationError extends Error {\n override readonly name = 'SmsValidationError' as const;\n}\n\nexport const SMS_MAX_SEGMENTS = 10;\n\nconst E164 = /^\\+[1-9]\\d{6,14}$/;\n\nexport function isE164(phone: string): boolean {\n return E164.test(phone);\n}\n\n// GSM 03.38 basic set, and the extension set (each counts as two septets).\nconst GSM_BASIC = new Set(\n '@£$¥èéùìòÇ\\nØø\\rÅåΔ_ΦΓΛΩΠΨΣΘΞÆæßÉ !\"#¤%&\\'()*+,-./0123456789:;<=>?¡ABCDEFGHIJKLMNOPQRSTUVWXYZÄÖÑܧ¿abcdefghijklmnopqrstuvwxyzäöñüà'\n);\nconst GSM_EXTENDED = new Set('^{}\\\\[~]|€\\f');\n\n/**\n * How many segments a body is billed as: GSM-7 is 160 septets in one\n * segment, 153 per segment when split; anything outside GSM-7 is UCS-2, 70\n * characters in one, 67 per segment (UTF-16 code units).\n */\nexport function smsSegments(body: string): {\n encoding: 'GSM-7' | 'UCS-2';\n units: number;\n segments: number;\n} {\n let septets = 0;\n let gsm = true;\n for (const ch of body) {\n if (GSM_BASIC.has(ch)) septets += 1;\n else if (GSM_EXTENDED.has(ch)) septets += 2;\n else {\n gsm = false;\n break;\n }\n }\n if (gsm) {\n return {\n encoding: 'GSM-7',\n units: septets,\n segments: septets <= 160 ? 1 : Math.ceil(septets / 153)\n };\n }\n const units = body.length;\n return {\n encoding: 'UCS-2',\n units,\n segments: units <= 70 ? 1 : Math.ceil(units / 67)\n };\n}\n\n/** Check a send before it leaves the process; throws SmsValidationError. */\nexport function validateSmsSend(request: SmsSendRequest): void {\n if (typeof request.to !== 'string' || !isE164(request.to)) {\n throw new SmsValidationError(\n `'to' must be an E.164 number like +14155550123 (got ${JSON.stringify(request.to)})`\n );\n }\n if (typeof request.body !== 'string' || !request.body.trim()) {\n throw new SmsValidationError(\"'body' must be non-empty text\");\n }\n const { segments, encoding } = smsSegments(request.body);\n if (segments > SMS_MAX_SEGMENTS) {\n throw new SmsValidationError(\n `'body' is ${segments} ${encoding} segments; the limit is ${SMS_MAX_SEGMENTS}. Send a link instead of long text.`\n );\n }\n if (\n request.purpose !== undefined &&\n request.purpose !== 'transactional' &&\n request.purpose !== 'promotional'\n ) {\n throw new SmsValidationError(\n \"'purpose' must be 'transactional' or 'promotional'\"\n );\n }\n}\n\nconst NOT_MANAGED =\n 'SMS goes through the ForkLaunch managed gateway: PLATFORM_GATEWAY_URL, ' +\n 'INSTANCE_ID and INSTANCE_HMAC_KEY must be set (the platform sets them for a ' +\n 'managed instance, and at deploy for a component that declares sms). ' +\n 'Locally, run the gateway mock (npx -p @forklaunch/core forklaunch-gateway-mock) ' +\n 'and point those variables at it; do not add a Twilio or AWS SDK.';\n\n/**\n * Sends texts through the platform. A class so a dependency container can\n * register it by type (`type: SmsClient`); build it with `createSmsClient`.\n */\nexport class SmsClient {\n private readonly transport?: InstanceGatewayTransport;\n\n constructor(options: SmsClientOptions = {}) {\n const configured =\n Boolean(\n (options.gatewayUrl ?? process.env.PLATFORM_GATEWAY_URL) &&\n (options.instanceId ?? process.env.INSTANCE_ID) &&\n (options.hmacKey ?? process.env.INSTANCE_HMAC_KEY)\n ) || isManagedInstance();\n if (configured) {\n this.transport = createInstanceGatewayTransport(options, 'SMS');\n } else if (!options.deferRefusal) {\n throw new Error(NOT_MANAGED);\n }\n }\n\n /** Whether sends can reach the gateway (false: every send refuses). */\n get managed(): boolean {\n return this.transport !== undefined;\n }\n\n async send(request: SmsSendRequest): Promise<SmsSendResult> {\n validateSmsSend(request);\n if (!this.transport) throw new Error(NOT_MANAGED);\n try {\n return await this.transport.json<SmsSendResult>('POST', '/sms/send', {\n to: request.to,\n body: request.body,\n purpose: request.purpose ?? 'transactional'\n });\n } catch (error) {\n if (error instanceof InstanceGatewayRequestError) {\n throw new SmsRequestError(\n error.status,\n error.message,\n error.retryAfterSeconds\n );\n }\n throw error;\n }\n }\n}\n\nexport function createSmsClient(options: SmsClientOptions = {}): SmsClient {\n return new SmsClient(options);\n}\n","import {\n createInstanceGatewayTransport,\n type InstanceGatewayOptions,\n InstanceGatewayRequestError\n} from './instanceGateway';\n\n/**\n * Client for WhatsApp through the ForkLaunch managed gateway, from a managed\n * instance or any app deployed on ForkLaunch.\n *\n * The platform holds the WhatsApp Business Account link (AWS End User\n * Messaging Social) and sends on the instance's behalf from the phone number\n * configured for its product or for this instance. The instance never holds\n * a Meta token: each request is signed with its own HMAC key, and the\n * platform enforces WhatsApp's rules and its own:\n *\n * - Business-initiated messages must use a Meta-approved template\n * (`sendTemplate`).\n * - Free-form text (`sendText`) is allowed only inside the 24-hour\n * customer-service window, opened by the recipient's last inbound\n * message. Outside it the gateway answers 422.\n * - A per-instance rate limit (429 with `retryAfterSeconds`).\n * - HIPAA products cannot send at all (403): WhatsApp is not covered by\n * the AWS BAA and Meta signs none. Never put protected health data in a\n * WhatsApp message.\n * - No phone number configured for the product or instance: 409.\n *\n * Events arrive at `/platform-events/whatsapp` (see `verifyPlatformEvent`):\n * - `whatsapp.received` `{ from, text?, type, receivedAt, messageId }`, an\n * inbound message; it opens the 24-hour window for `from`.\n * - `whatsapp.status` `{ messageId, status, recipient?, timestamp? }`,\n * `status` being Meta's `sent`, `delivered`, `read` or `failed`.\n *\n * Locally, `forklaunch infra add <service> whatsapp` points the service at\n * the gateway mock (`forklaunch-gateway-mock`, routes/whatsapp.mjs), which\n * serves templates, emits these events and applies the same refusals.\n *\n * The shape is channel-neutral on purpose (`ConversationChannelClient`):\n * another conversational channel (for example Apple Messages for Business)\n * would be another channel id behind the same three calls.\n *\n * @example\n * const whatsapp = createWhatsAppClient();\n * await whatsapp.sendTemplate({\n * to: '+14155550123',\n * template: 'appointment_reminder',\n * language: 'en_US',\n * components: [{ type: 'body', parameters: [{ type: 'text', text: 'Tuesday 3pm' }] }]\n * });\n */\n\nexport type WhatsAppClientOptions = InstanceGatewayOptions;\n\n/** A Meta template component (header, body, button), passed through as is. */\nexport interface WhatsAppTemplateComponent {\n type: string;\n parameters?: Record<string, unknown>[];\n [key: string]: unknown;\n}\n\nexport interface SendTemplateRequest {\n /** E.164 recipient, e.g. `+14155550123`. */\n to: string;\n /** The approved template's name. */\n template: string;\n /** The template's language code, e.g. `en_US`. */\n language: string;\n /** Variable values for the template, in Meta's component format. */\n components?: WhatsAppTemplateComponent[];\n}\n\nexport interface SendTextRequest {\n /** E.164 recipient; must have written to this number in the last 24 hours. */\n to: string;\n body: string;\n}\n\nexport interface SentMessage {\n /** Matches `messageId` on later `whatsapp.status` events. */\n messageId: string;\n}\n\nexport interface MessageTemplate {\n name: string;\n language: string;\n /** Meta's review status: `APPROVED`, `PENDING`, `REJECTED`, … */\n status: string;\n category?: string;\n}\n\n/** The data of a `whatsapp.received` event. */\nexport interface WhatsAppReceivedEvent {\n from: string;\n /** Present for `type: 'text'` messages. */\n text?: string;\n type: string;\n receivedAt: string;\n messageId?: string;\n}\n\n/** The data of a `whatsapp.status` event. */\nexport interface WhatsAppStatusEvent {\n messageId: string;\n status: string;\n recipient?: string;\n timestamp?: string;\n}\n\n/** A refusal or failure from the WhatsApp gateway, with its status. */\nexport class WhatsAppRequestError extends InstanceGatewayRequestError {\n override readonly name = 'WhatsAppRequestError' as const;\n}\n\n/**\n * The calls every conversational channel offers. WhatsApp is the only\n * implementation today.\n */\nexport interface ConversationChannelClient {\n /** Business-initiated message from an approved template. */\n sendTemplate(request: SendTemplateRequest): Promise<SentMessage>;\n /** Free-form text, inside the 24-hour customer-service window only. */\n sendText(request: SendTextRequest): Promise<SentMessage>;\n /** The templates the configured account has, with their review status. */\n templates(): Promise<MessageTemplate[]>;\n}\n\nexport type WhatsAppClient = ConversationChannelClient;\n\nconst E164 = /^\\+[1-9]\\d{6,14}$/;\n\nfunction requireRecipient(to: unknown): void {\n if (typeof to !== 'string' || !E164.test(to)) {\n throw new WhatsAppRequestError(\n 400,\n `'to' must be an E.164 phone number such as +14155550123 (got ${JSON.stringify(to)})`\n );\n }\n}\n\nfunction createConversationChannelClient(\n channel: string,\n label: string,\n options: WhatsAppClientOptions\n): ConversationChannelClient {\n const transport = createInstanceGatewayTransport(options, label);\n\n async function call<T>(\n method: 'GET' | 'POST',\n route: string,\n body?: Record<string, unknown>\n ): Promise<T> {\n try {\n return await transport.json<T>(method, `/${channel}${route}`, body);\n } catch (error) {\n if (error instanceof InstanceGatewayRequestError) {\n throw new WhatsAppRequestError(\n error.status,\n error.message,\n error.retryAfterSeconds\n );\n }\n throw error;\n }\n }\n\n return {\n async sendTemplate(request) {\n requireRecipient(request.to);\n if (!request.template || !request.language) {\n throw new WhatsAppRequestError(\n 400,\n 'template and language are required'\n );\n }\n return call<SentMessage>('POST', '/messages', {\n to: request.to,\n type: 'template',\n template: request.template,\n language: request.language,\n ...(request.components ? { components: request.components } : {})\n });\n },\n async sendText(request) {\n requireRecipient(request.to);\n if (typeof request.body !== 'string' || !request.body.trim()) {\n throw new WhatsAppRequestError(400, 'body must be non-empty text');\n }\n return call<SentMessage>('POST', '/messages', {\n to: request.to,\n type: 'text',\n body: request.body\n });\n },\n async templates() {\n const listing = await call<{ templates: MessageTemplate[] }>(\n 'GET',\n '/templates'\n );\n return listing.templates;\n }\n };\n}\n\n/**\n * A WhatsApp client through the managed gateway. Throws without its settings\n * (`PLATFORM_GATEWAY_URL`, `INSTANCE_ID`, `INSTANCE_HMAC_KEY` unset); run the\n * local gateway mock to develop.\n */\nexport function createWhatsAppClient(\n options: WhatsAppClientOptions = {}\n): WhatsAppClient {\n return createConversationChannelClient('whatsapp', 'WhatsApp', options);\n}\n","import {\n createInstanceGatewayTransport,\n type InstanceGatewayOptions,\n InstanceGatewayRequestError,\n type InstanceGatewayTransport\n} from './instanceGateway';\n\n/**\n * Client for platform-held voice calls (Amazon Connect) through the managed\n * gateway, from a managed instance or any app deployed on ForkLaunch.\n *\n * The instance never holds an AWS credential, a Connect instance id or a\n * contact-flow ARN. It asks the platform to place a call with a FLOW NAME from\n * the product's flow catalog (`appointment_reminder`, …); the platform maps it\n * to the contact flow, dials from the phone number claimed for this instance,\n * and enforces the instance's concurrent-call and monthly-minute limits.\n *\n * Call progress arrives as platform events on `/platform-events/voice`\n * (`voice.call.started`, `voice.call.ended`, `voice.recording.ready`), signed\n * with the instance key; `forklaunch infra add <service> voice` writes the\n * route and a handler stub.\n *\n * Attributes are passed to the contact flow and are stored in Connect's\n * contact records. Put identifiers in them (an appointment id the flow looks\n * up), never health information: the `voice-protected-data` check flags a\n * `.deanon` value flowing into them.\n *\n * Locally, `infra add` points the service at the gateway mock in\n * docker-compose (flows from `MOCK_VOICE_FLOWS`, events delivered back to the\n * service), so the same code runs with no AWS account.\n *\n * @example\n * const voice = createVoiceClient();\n * const { callId } = await voice.startOutboundCall({\n * to: '+15551230000',\n * flow: 'appointment_reminder',\n * attributes: { appointmentId: appt.id }\n * });\n * const { status } = await voice.call(callId);\n */\n\nexport type VoiceClientOptions = InstanceGatewayOptions;\n\n/** Limits the gateway enforces on attributes; the client checks them first. */\nexport const VOICE_ATTRIBUTE_LIMITS = {\n maxKeys: 20,\n maxKeyLength: 64,\n maxValueLength: 256,\n maxTotalBytes: 4096,\n /** Keys the platform reserves (it prefixes and adds its own under `fl_`). */\n reservedPrefix: 'fl_'\n} as const;\n\nexport interface StartOutboundCallRequest {\n /** The number to call, E.164 (`+15551230000`). */\n to: string;\n /** A flow name from the product's catalog, e.g. `appointment_reminder`. */\n flow: string;\n /** String values the contact flow can read. No health information. */\n attributes?: Record<string, string>;\n}\n\nexport interface StartOutboundCallResult {\n callId: string;\n}\n\nexport type VoiceCallStatus = 'initiated' | 'in_progress' | 'ended';\n\nexport interface VoiceCall {\n status: VoiceCallStatus;\n startedAt: string;\n endedAt?: string;\n durationSeconds?: number;\n /** Why it ended: `customer`, `agent`, `api`, `busy`, `no_answer`, … */\n disconnectReason?: string;\n}\n\n/** Data of `voice.call.started`. */\nexport interface VoiceCallStartedEvent {\n callId: string;\n flow?: string;\n}\n\n/** Data of `voice.call.ended`. */\nexport interface VoiceCallEndedEvent {\n callId: string;\n durationSeconds: number;\n disconnectReason: string;\n}\n\n/** Data of `voice.recording.ready`: the key in the instance's object store. */\nexport interface VoiceRecordingReadyEvent {\n callId: string;\n recordingKey: string;\n}\n\n/** A refusal or failure from the voice gateway, with its status. */\nexport class VoiceRequestError extends InstanceGatewayRequestError {\n override readonly name = 'VoiceRequestError' as const;\n}\n\nconst E164 = /^\\+[1-9]\\d{6,14}$/;\nconst FLOW_NAME = /^[a-z][a-z0-9_-]{0,63}$/;\nconst ATTRIBUTE_KEY = /^[A-Za-z][A-Za-z0-9_]*$/;\n\n/** Why a request would be refused, or undefined. Shared with the gateway. */\nexport function voiceRequestProblem(\n request: StartOutboundCallRequest\n): string | undefined {\n if (typeof request.to !== 'string' || !E164.test(request.to)) {\n return '`to` must be an E.164 number such as +15551230000';\n }\n if (typeof request.flow !== 'string' || request.flow.startsWith('arn:')) {\n return '`flow` is a flow name from the product catalog (e.g. appointment_reminder), not a contact-flow ARN';\n }\n if (!FLOW_NAME.test(request.flow)) {\n return '`flow` must be a catalog flow name: lowercase letters, digits, _ or -';\n }\n const attributes = request.attributes ?? {};\n if (typeof attributes !== 'object' || Array.isArray(attributes)) {\n return '`attributes` must be an object of strings';\n }\n const entries = Object.entries(attributes);\n const limits = VOICE_ATTRIBUTE_LIMITS;\n if (entries.length > limits.maxKeys) {\n return `at most ${limits.maxKeys} attributes`;\n }\n let total = 0;\n for (const [key, value] of entries) {\n if (!ATTRIBUTE_KEY.test(key) || key.length > limits.maxKeyLength) {\n return `attribute key '${key}' must be letters, digits or _ (max ${limits.maxKeyLength})`;\n }\n if (key.toLowerCase().startsWith(limits.reservedPrefix)) {\n return `attribute keys starting with '${limits.reservedPrefix}' are reserved for the platform`;\n }\n if (typeof value !== 'string') {\n return `attribute '${key}' must be a string`;\n }\n if (value.length > limits.maxValueLength) {\n return `attribute '${key}' is longer than ${limits.maxValueLength} characters`;\n }\n total += Buffer.byteLength(key) + Buffer.byteLength(value);\n }\n if (total > limits.maxTotalBytes) {\n return `attributes exceed ${limits.maxTotalBytes} bytes`;\n }\n return undefined;\n}\n\n/**\n * The voice client. A class so a service's registrations.ts can declare it\n * (`type: VoiceClient`); construct it with `createVoiceClient()`.\n */\nexport class VoiceClient {\n private readonly transport: InstanceGatewayTransport;\n\n /** Throws without the managed gateway settings (see instanceGatewaySettings). */\n constructor(options: VoiceClientOptions = {}) {\n this.transport = createInstanceGatewayTransport(\n options,\n 'Voice calls (createVoiceClient)'\n );\n }\n\n /** Place an outbound call; resolves once the platform accepted it. */\n async startOutboundCall(\n request: StartOutboundCallRequest\n ): Promise<StartOutboundCallResult> {\n const problem = voiceRequestProblem(request);\n if (problem) throw new VoiceRequestError(400, problem);\n return this.send<StartOutboundCallResult>('POST', '/voice/calls', {\n to: request.to,\n flow: request.flow,\n ...(request.attributes ? { attributes: request.attributes } : {})\n });\n }\n\n /** Hang up a call this instance placed. */\n async endCall(callId: string): Promise<void> {\n await this.send<unknown>('DELETE', callPath(callId));\n }\n\n /** Where a call this instance placed stands. */\n async call(callId: string): Promise<VoiceCall> {\n return this.send<VoiceCall>('GET', callPath(callId));\n }\n\n private async send<T>(\n method: 'GET' | 'POST' | 'DELETE',\n route: string,\n body?: Record<string, unknown>\n ): Promise<T> {\n try {\n const response = await this.transport.request(method, route, body);\n const text = await response.text();\n return (text ? JSON.parse(text) : undefined) as T;\n } catch (error) {\n if (error instanceof InstanceGatewayRequestError) {\n throw new VoiceRequestError(\n error.status,\n error.message,\n error.retryAfterSeconds\n );\n }\n throw error;\n }\n }\n}\n\nfunction callPath(callId: string): string {\n if (typeof callId !== 'string' || !/^[A-Za-z0-9_-]{1,128}$/.test(callId)) {\n throw new VoiceRequestError(400, 'callId is not a call id');\n }\n return `/voice/calls/${callId}`;\n}\n\n/** A voice client through the managed gateway (settings from the environment). */\nexport function createVoiceClient(\n options: VoiceClientOptions = {}\n): VoiceClient {\n return new VoiceClient(options);\n}\n","import { createRequire } from 'node:module';\nimport type Stripe from 'stripe';\nimport {\n createInstanceGatewayTransport,\n INSTANCE_GATEWAY_MOUNT,\n InstanceGatewayRequestError,\n instanceGatewaySettings,\n isManagedInstance,\n type InstanceGatewayOptions\n} from './instanceGateway';\nimport { generateHmacAuthHeaders } from './generateHmacAuthHeaders';\n\n/**\n * Payments for a managed instance: Stripe Connect through the platform.\n *\n * The product's publisher runs the Stripe Connect platform, linked once to\n * ForkLaunch. Each managed instance (a clinic, a studio) gets its OWN\n * connected account and is the merchant of record: charges are direct\n * charges on that account, and payouts go to the clinic's bank, never through\n * the app. The app never holds a Stripe key:\n *\n * - `createPaymentsClient()` onboards the instance (a Stripe-hosted Account\n * Link) and reports whether it can take payments yet;\n * - `createStripeClient()` is the REAL Stripe SDK, pointed at the instance\n * gateway. Every request is signed with the instance key, and the platform\n * pins `Stripe-Account` to this instance's connected account, forwards\n * only an allowlist of calls (customers, products and prices, checkout and\n * billing-portal sessions, payment links, subscriptions, payment intents,\n * refunds, invoices — never payouts, transfers, external accounts or\n * account changes), adds the product's application fee, and refuses\n * metadata that looks like protected data;\n * - Stripe's events arrive as platform events (`/platform-events/payments`,\n * type = the Stripe event type, id = the Stripe event id, data = the\n * event's object), verified with `verifyPlatformEvent`.\n *\n * Outside managed mode `createStripeClient({ apiKey })` is `new Stripe(apiKey)`,\n * so the same registration runs against a developer's own test account.\n *\n * @example\n * const payments = createPaymentsClient();\n * const { url } = await payments.onboardingLink({\n * returnUrl: 'https://clinic.example.com/settings/payments?done=1',\n * refreshUrl: 'https://clinic.example.com/settings/payments'\n * });\n * const stripe = createStripeClient({ Stripe });\n * const session = await stripe.checkout.sessions.create({ mode: 'payment', … });\n */\n\n/** Where the gateway proxies Stripe's API, router-relative. */\nexport const STRIPE_GATEWAY_ROUTE = '/stripe';\n\nexport interface PaymentsStatus {\n /** The connected account can take card payments. */\n chargesEnabled: boolean;\n /** Stripe can pay out to the clinic's bank account. */\n payoutsEnabled: boolean;\n /** What Stripe still needs (`individual.verification.document`, …). */\n requirementsDue: string[];\n}\n\nexport interface PaymentsClient {\n /**\n * A single-use Stripe-hosted onboarding link for this instance's connected\n * account (created on first use). Send the clinic's owner to `url`; Stripe\n * returns them to `returnUrl`, or to `refreshUrl` when the link expired.\n */\n onboardingLink(params: {\n returnUrl: string;\n refreshUrl: string;\n }): Promise<{ url: string }>;\n /** Whether the instance can take payments yet. */\n status(): Promise<PaymentsStatus>;\n}\n\n/** A refusal or failure from the payments gateway. */\nexport class PaymentsRequestError extends InstanceGatewayRequestError {\n override readonly name = 'PaymentsRequestError' as const;\n}\n\nexport function createPaymentsClient(\n options: InstanceGatewayOptions = {}\n): PaymentsClient {\n const transport = createInstanceGatewayTransport(options, 'Payments');\n async function call<T>(\n method: 'GET' | 'POST',\n route: string,\n body?: Record<string, unknown>\n ): Promise<T> {\n try {\n return await transport.json<T>(method, route, body);\n } catch (error) {\n if (error instanceof InstanceGatewayRequestError) {\n throw new PaymentsRequestError(\n error.status,\n error.message,\n error.retryAfterSeconds\n );\n }\n throw error;\n }\n }\n return {\n onboardingLink({ returnUrl, refreshUrl }) {\n for (const [name, value] of [\n ['returnUrl', returnUrl],\n ['refreshUrl', refreshUrl]\n ] as const) {\n if (!/^https?:\\/\\//.test(value ?? '')) {\n throw new TypeError(`${name} must be an absolute http(s) URL`);\n }\n }\n return call('POST', '/payments/onboarding-link', {\n returnUrl,\n refreshUrl\n });\n },\n status() {\n return call('GET', '/payments/status');\n }\n };\n}\n\ntype StripeConstructor = typeof Stripe;\n\nexport interface StripeClientOptions extends InstanceGatewayOptions {\n /**\n * A Stripe secret key: the service talks to Stripe directly with it (local\n * development against your own test account, a self-hosted or regular\n * deployment). It wins over a managed contract found in the environment;\n * only explicit gateway options (`gatewayUrl`/`instanceId`/`hmacKey`)\n * outrank it. A managed instance passes none and the platform holds the key.\n */\n apiKey?: string;\n /**\n * The `Stripe` class to construct. Pass your own `import Stripe from\n * 'stripe'` when the client is registered with `type: Stripe`: an ESM\n * service and this package could otherwise load different builds of the\n * SDK, and the registration's `instanceof` check would fail. Default: the\n * `stripe` package, loaded on first use (it is an optional peer dependency).\n */\n Stripe?: StripeConstructor;\n /** Extra SDK settings (apiVersion, maxNetworkRetries, timeout, appInfo). */\n config?: Stripe.StripeConfig;\n}\n\nfunction loadStripe(): StripeConstructor {\n // Loaded lazily so `@forklaunch/core/http` never needs `stripe` installed.\n // The CommonJS build has `__filename` (its `import.meta` is empty); the ESM\n // build has `import.meta.url`. (A bare `require` would be rewritten by the\n // bundler into a shim that throws under ESM.)\n const load = createRequire(\n typeof __filename === 'string' ? __filename : import.meta.url\n );\n try {\n const mod = load('stripe') as StripeConstructor & {\n default?: StripeConstructor;\n };\n return mod.default ?? mod;\n } catch {\n throw new Error(\n \"createStripeClient needs the 'stripe' package: add it to this service (pnpm add stripe)\"\n );\n }\n}\n\n/**\n * A fetch that sends Stripe SDK requests to the instance gateway, signed.\n *\n * The SDK builds `https://<host>:<port>/v1/...` from the `host`/`port`/\n * `protocol` settings; this rewrites the path under\n * `/instance-gateway/stripe` and adds the instance's HMAC `authorization`,\n * replacing any bearer key. The signature covers the method, the\n * router-relative path WITH its query string (`/stripe/v1/prices?active=true`,\n * so a list filter cannot be altered in flight) and the body exactly as sent:\n * Stripe's bodies are form-encoded, and the raw form string is signed\n * verbatim (framework `createHmacToken` treats a string body as the wire\n * bytes). An empty body signs as no body.\n */\nexport function stripeGatewayFetch(\n settings: { gatewayUrl: string; instanceId: string; hmacKey: string },\n fetchImpl: typeof fetch = fetch\n): typeof fetch {\n const base = new URL(settings.gatewayUrl);\n const basePath = base.pathname.replace(/\\/+$/, '');\n return async (input, init = {}) => {\n const original = new URL(\n typeof input === 'string' || input instanceof URL ? input : input.url\n );\n const routerPath = `${STRIPE_GATEWAY_ROUTE}${original.pathname}${original.search}`;\n const method = (init.method ?? 'GET').toUpperCase();\n const body = typeof init.body === 'string' ? init.body : undefined;\n const { authorization } = generateHmacAuthHeaders({\n secretKey: settings.hmacKey,\n method,\n path: routerPath,\n body: body || undefined,\n keyId: settings.instanceId\n });\n const headers = new Headers(init.headers);\n headers.set('authorization', authorization);\n const target = `${base.origin}${basePath}${INSTANCE_GATEWAY_MOUNT}${routerPath}`;\n const response = await fetchImpl(target, { ...init, method, headers });\n if (\n response.ok ||\n (response.headers.get('content-type') ?? '').includes('json')\n ) {\n return response;\n }\n // A refusal the gateway answered in plain text (a bad signature, an\n // unknown instance): give the SDK Stripe's error shape, so it raises the\n // usual typed error (401 -> StripeAuthenticationError) with the message.\n const message =\n (await response.text().catch(() => '')).trim() ||\n `Instance gateway answered ${response.status}`;\n return new Response(\n JSON.stringify({\n error: {\n type: 'invalid_request_error',\n code: 'forklaunch_gateway',\n message\n }\n }),\n {\n status: response.status,\n headers: {\n 'content-type': 'application/json',\n 'stripe-should-retry': 'false',\n ...(response.headers.get('retry-after')\n ? { 'retry-after': response.headers.get('retry-after') as string }\n : {})\n }\n }\n );\n };\n}\n\n/**\n * The Stripe SDK for this service.\n *\n * Which Stripe it talks to, in order:\n * 1. explicit gateway options (`gatewayUrl`/`instanceId`/`hmacKey`): the\n * platform's instance gateway;\n * 2. an explicit `apiKey`: `new Stripe(apiKey)`, directly — even when the\n * environment carries the managed contract. Those three variables also\n * reach a regular app's components that use another platform feature\n * (email), and an app that passes its own key means its own key;\n * 3. the managed contract in the environment (`PLATFORM_GATEWAY_URL`,\n * `INSTANCE_ID`, `INSTANCE_HMAC_KEY`): the gateway, signed with the\n * instance key; there is no Stripe key in the app.\n * Otherwise it throws.\n *\n * (Through @forklaunch/core 3.0.1 an explicit `apiKey` lost to the\n * environment in step 3.)\n *\n * Mechanism (stripe-node 22): `host`/`port`/`protocol` point the SDK at the\n * gateway, `httpClient: Stripe.createFetchHttpClient(signedFetch)` rewrites\n * each request under `/instance-gateway/stripe` and signs it (see\n * `stripeGatewayFetch`), and a no-op `authenticator` stands in for the API\n * key so no bearer credential is ever sent. Retries re-enter the fetch, so\n * each attempt carries a fresh nonce.\n */\nexport function createStripeClient(options: StripeClientOptions = {}): Stripe {\n const StripeClass = options.Stripe ?? loadStripe();\n const explicitGateway = Boolean(\n options.gatewayUrl || options.instanceId || options.hmacKey\n );\n // An explicit key wins over a managed contract detected in the\n // environment; only explicit gateway options outrank it.\n if (!explicitGateway && options.apiKey) {\n return new StripeClass(options.apiKey, options.config);\n }\n if (!explicitGateway && !isManagedInstance()) {\n if (!options.apiKey) {\n throw new Error(\n 'createStripeClient: no managed gateway (PLATFORM_GATEWAY_URL, INSTANCE_ID and ' +\n 'INSTANCE_HMAC_KEY are unset) and no apiKey was given — pass { apiKey } for local ' +\n 'development, or run the gateway mock (forklaunch-gateway-mock) with the managed env'\n );\n }\n return new StripeClass(options.apiKey, options.config);\n }\n const settings = instanceGatewaySettings(options, 'Payments');\n const gateway = new URL(settings.gatewayUrl);\n const protocol = gateway.protocol === 'http:' ? 'http' : 'https';\n return new StripeClass(\n // No key: the authenticator below replaces it, and the gateway holds the\n // real one. (stripe-node accepts an authenticator in place of a key.)\n undefined as unknown as string,\n {\n maxNetworkRetries: 2,\n ...options.config,\n host: gateway.hostname,\n port: gateway.port || (protocol === 'http' ? 80 : 443),\n protocol,\n telemetry: false,\n // The signed fetch sets `authorization`; nothing else may.\n authenticator: async () => {},\n httpClient: StripeClass.createFetchHttpClient(\n stripeGatewayFetch(settings, options.fetch)\n )\n }\n );\n}\n","export function isPath<Path extends `/${string}`>(path: string): path is Path {\n return path.startsWith('/');\n}\n","import { AnySchemaValidator } from '@forklaunch/validator';\nimport { isPath } from '../guards/isPath';\nimport { ExpressLikeSchemaHandler } from '../types/apiDefinition.types';\nimport {\n Body,\n ContractDetails,\n HeadersObject,\n Method,\n ParamsObject,\n QueryObject,\n ResolvedSessionObject,\n ResponsesObject,\n SchemaAuthMethods,\n SessionObject,\n VersionSchema\n} from '../types/contractDetails.types';\nimport { ExpressLikeTypedHandler } from '../types/typedHandler.types';\n\n/**\n * Router class that sets up routes and middleware for an Express router, for use with controller/routes pattern.\n *\n * @template SV - A type that extends AnySchemaValidator.\n * @template contractDetails - The contract details.\n * @template handlers - The handler middlware and handler.\n */\nexport function typedHandler<\n SV extends AnySchemaValidator,\n Name extends string,\n ContractMethod extends Method,\n Path extends `/${string}`,\n P extends ParamsObject<SV>,\n ResBodyMap extends ResponsesObject<SV>,\n ReqBody extends Body<SV>,\n ReqQuery extends QueryObject<SV>,\n ReqHeaders extends HeadersObject<SV>,\n ResHeaders extends HeadersObject<SV>,\n LocalsObj extends Record<string, unknown>,\n const VersionedApi extends VersionSchema<SV, ContractMethod>,\n BaseRequest,\n BaseResponse,\n NextFunction,\n const Auth extends SchemaAuthMethods<\n SV,\n P,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n VersionedApi,\n BaseRequest\n >\n>(\n _schemaValidator: SV,\n _path: Path | undefined,\n _contractMethod: ContractMethod,\n contractDetails: ContractDetails<\n SV,\n Name,\n ContractMethod,\n Path,\n P,\n ResBodyMap,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n ResHeaders,\n VersionedApi,\n BaseRequest,\n Auth\n >,\n ...handlers: ExpressLikeSchemaHandler<\n SV,\n P,\n ResBodyMap,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n ResHeaders,\n LocalsObj,\n VersionedApi,\n ResolvedSessionObject<SV, Auth, SessionObject<SV>>,\n BaseRequest,\n BaseResponse,\n NextFunction\n >[]\n): ExpressLikeTypedHandler<\n SV,\n Name,\n ContractMethod,\n Path,\n P,\n ResBodyMap,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n ResHeaders,\n LocalsObj,\n VersionedApi,\n BaseRequest,\n BaseResponse,\n NextFunction,\n Auth\n>;\nexport function typedHandler<\n SV extends AnySchemaValidator,\n Name extends string,\n ContractMethod extends Method,\n Path extends `/${string}`,\n P extends ParamsObject<SV>,\n ResBodyMap extends ResponsesObject<SV>,\n ReqBody extends Body<SV>,\n ReqQuery extends QueryObject<SV>,\n ReqHeaders extends HeadersObject<SV>,\n ResHeaders extends HeadersObject<SV>,\n LocalsObj extends Record<string, unknown>,\n const VersionedApi extends VersionSchema<SV, ContractMethod>,\n BaseRequest,\n BaseResponse,\n NextFunction,\n const Auth extends SchemaAuthMethods<\n SV,\n P,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n VersionedApi,\n BaseRequest\n >\n>(\n _schemaValidator: SV,\n _contractMethod: ContractMethod,\n contractDetails: ContractDetails<\n SV,\n Name,\n ContractMethod,\n Path,\n P,\n ResBodyMap,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n ResHeaders,\n VersionedApi,\n BaseRequest,\n Auth\n >,\n ...handlers: ExpressLikeSchemaHandler<\n SV,\n P,\n ResBodyMap,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n ResHeaders,\n LocalsObj,\n VersionedApi,\n ResolvedSessionObject<SV, Auth, SessionObject<SV>>,\n BaseRequest,\n BaseResponse,\n NextFunction\n >[]\n): ExpressLikeTypedHandler<\n SV,\n Name,\n ContractMethod,\n Path,\n P,\n ResBodyMap,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n ResHeaders,\n LocalsObj,\n VersionedApi,\n BaseRequest,\n BaseResponse,\n NextFunction,\n Auth\n>;\nexport function typedHandler<\n SV extends AnySchemaValidator,\n Name extends string,\n ContractMethod extends Method,\n Path extends `/${string}`,\n P extends ParamsObject<SV>,\n ResBodyMap extends ResponsesObject<SV>,\n ReqBody extends Body<SV>,\n ReqQuery extends QueryObject<SV>,\n ReqHeaders extends HeadersObject<SV>,\n ResHeaders extends HeadersObject<SV>,\n LocalsObj extends Record<string, unknown>,\n const VersionedApi extends VersionSchema<SV, ContractMethod>,\n BaseRequest,\n BaseResponse,\n NextFunction,\n const Auth extends SchemaAuthMethods<\n SV,\n P,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n VersionedApi,\n BaseRequest\n >\n>(\n _schemaValidator: SV,\n pathOrContractMethod: Path | ContractMethod,\n contractMethodOrContractDetails:\n | ContractMethod\n | ContractDetails<\n SV,\n Name,\n ContractMethod,\n Path,\n P,\n ResBodyMap,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n ResHeaders,\n VersionedApi,\n BaseRequest,\n Auth\n >,\n contractDetailsOrHandler:\n | ContractDetails<\n SV,\n Name,\n ContractMethod,\n Path,\n P,\n ResBodyMap,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n ResHeaders,\n VersionedApi,\n BaseRequest,\n Auth\n >\n | ExpressLikeSchemaHandler<\n SV,\n P,\n ResBodyMap,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n ResHeaders,\n LocalsObj,\n VersionedApi,\n ResolvedSessionObject<SV, Auth, SessionObject<SV>>,\n BaseRequest,\n BaseResponse,\n NextFunction\n >,\n ...handlerArray: ExpressLikeSchemaHandler<\n SV,\n P,\n ResBodyMap,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n ResHeaders,\n LocalsObj,\n VersionedApi,\n ResolvedSessionObject<SV, Auth, SessionObject<SV>>,\n BaseRequest,\n BaseResponse,\n NextFunction\n >[]\n): ExpressLikeTypedHandler<\n SV,\n Name,\n ContractMethod,\n Path,\n P,\n ResBodyMap,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n ResHeaders,\n LocalsObj,\n VersionedApi,\n BaseRequest,\n BaseResponse,\n NextFunction,\n Auth\n> {\n // TODO: Clean this up with guards\n\n let contractDetails: ContractDetails<\n SV,\n Name,\n ContractMethod,\n Path,\n P,\n ResBodyMap,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n ResHeaders,\n VersionedApi,\n BaseRequest,\n Auth\n >;\n let handlers: ExpressLikeSchemaHandler<\n SV,\n P,\n ResBodyMap,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n ResHeaders,\n LocalsObj,\n VersionedApi,\n ResolvedSessionObject<SV, Auth, SessionObject<SV>>,\n BaseRequest,\n BaseResponse,\n NextFunction\n >[];\n if (typeof contractMethodOrContractDetails === 'string') {\n if (typeof contractDetailsOrHandler !== 'function') {\n contractDetails = contractDetailsOrHandler;\n } else {\n throw new Error('Invalid definition for contract details');\n }\n handlers = handlerArray;\n } else {\n contractDetails = contractMethodOrContractDetails;\n if (typeof contractDetailsOrHandler === 'function') {\n handlers = [contractDetailsOrHandler, ...handlerArray];\n } else {\n throw new Error('Invalid definition for handler');\n }\n }\n\n if (\n isPath(pathOrContractMethod) &&\n typeof contractMethodOrContractDetails !== 'string'\n ) {\n throw new Error('Contract method not supplied, bailing');\n }\n\n return {\n _typedHandler: true as const,\n _path: isPath(pathOrContractMethod) ? pathOrContractMethod : undefined,\n _method: isPath(pathOrContractMethod)\n ? (contractMethodOrContractDetails as ContractMethod)\n : pathOrContractMethod,\n contractDetails,\n handlers\n };\n}\n","import { AnySchemaValidator } from '@forklaunch/validator';\nimport { ExpressLikeSchemaHandler } from '../types/apiDefinition.types';\nimport {\n Body,\n HeadersObject,\n ParamsObject,\n PathParamHttpContractDetails,\n QueryObject,\n ResolvedSessionObject,\n ResponsesObject,\n SchemaAuthMethods,\n SessionObject,\n VersionSchema\n} from '../types/contractDetails.types';\nimport { typedHandler } from './typedHandler';\n\nexport const delete_ = <\n SV extends AnySchemaValidator,\n Name extends string,\n Path extends `/${string}`,\n P extends ParamsObject<SV>,\n ResBodyMap extends ResponsesObject<SV>,\n ReqBody extends Body<SV>,\n ReqQuery extends QueryObject<SV>,\n ReqHeaders extends HeadersObject<SV>,\n ResHeaders extends HeadersObject<SV>,\n LocalsObj extends Record<string, unknown>,\n VersionedApi extends VersionSchema<SV, 'delete'>,\n BaseRequest,\n BaseResponse,\n NextFunction,\n const Auth extends SchemaAuthMethods<\n SV,\n P,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n VersionedApi,\n BaseRequest\n >\n>(\n _schemaValidator: SV,\n path: Path,\n contractDetails: PathParamHttpContractDetails<\n SV,\n Name,\n Path,\n P,\n ResBodyMap,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n ResHeaders,\n VersionedApi,\n BaseRequest,\n Auth\n >,\n ...handlers: ExpressLikeSchemaHandler<\n SV,\n P,\n ResBodyMap,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n ResHeaders,\n LocalsObj,\n VersionedApi,\n ResolvedSessionObject<SV, Auth, SessionObject<SV>>,\n BaseRequest,\n BaseResponse,\n NextFunction\n >[]\n) => {\n return typedHandler<\n SV,\n Name,\n 'delete',\n Path,\n P,\n ResBodyMap,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n ResHeaders,\n LocalsObj,\n VersionedApi,\n BaseRequest,\n BaseResponse,\n NextFunction,\n Auth\n >(_schemaValidator, path, 'delete', contractDetails, ...handlers);\n};\n","import { AnySchemaValidator } from '@forklaunch/validator';\nimport { ExpressLikeSchemaHandler } from '../types/apiDefinition.types';\nimport {\n Body,\n HeadersObject,\n ParamsObject,\n PathParamHttpContractDetails,\n QueryObject,\n ResolvedSessionObject,\n ResponsesObject,\n SchemaAuthMethods,\n SessionObject,\n VersionSchema\n} from '../types/contractDetails.types';\nimport { typedHandler } from './typedHandler';\n\nexport const get = <\n SV extends AnySchemaValidator,\n Name extends string,\n Path extends `/${string}`,\n P extends ParamsObject<SV>,\n ResBodyMap extends ResponsesObject<SV>,\n ReqBody extends Body<SV>,\n ReqQuery extends QueryObject<SV>,\n ReqHeaders extends HeadersObject<SV>,\n ResHeaders extends HeadersObject<SV>,\n LocalsObj extends Record<string, unknown>,\n VersionedApi extends VersionSchema<SV, 'get'>,\n BaseRequest,\n BaseResponse,\n NextFunction,\n const Auth extends SchemaAuthMethods<\n SV,\n P,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n VersionedApi,\n BaseRequest\n >\n>(\n _schemaValidator: SV,\n path: Path,\n contractDetails: PathParamHttpContractDetails<\n SV,\n Name,\n Path,\n P,\n ResBodyMap,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n ResHeaders,\n VersionedApi,\n BaseRequest,\n Auth\n >,\n ...handlers: ExpressLikeSchemaHandler<\n SV,\n P,\n ResBodyMap,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n ResHeaders,\n LocalsObj,\n VersionedApi,\n ResolvedSessionObject<SV, Auth, SessionObject<SV>>,\n BaseRequest,\n BaseResponse,\n NextFunction\n >[]\n) => {\n return typedHandler<\n SV,\n Name,\n 'get',\n Path,\n P,\n ResBodyMap,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n ResHeaders,\n LocalsObj,\n VersionedApi,\n BaseRequest,\n BaseResponse,\n NextFunction,\n Auth\n >(_schemaValidator, path, 'get', contractDetails, ...handlers);\n};\n","import { AnySchemaValidator } from '@forklaunch/validator';\nimport { ExpressLikeSchemaHandler } from '../types/apiDefinition.types';\nimport {\n Body,\n HeadersObject,\n ParamsObject,\n PathParamHttpContractDetails,\n QueryObject,\n ResolvedSessionObject,\n ResponsesObject,\n SchemaAuthMethods,\n SessionObject,\n VersionSchema\n} from '../types/contractDetails.types';\nimport { typedHandler } from './typedHandler';\n\nexport const head = <\n SV extends AnySchemaValidator,\n Name extends string,\n Path extends `/${string}`,\n P extends ParamsObject<SV>,\n ResBodyMap extends ResponsesObject<SV>,\n ReqBody extends Body<SV>,\n ReqQuery extends QueryObject<SV>,\n ReqHeaders extends HeadersObject<SV>,\n ResHeaders extends HeadersObject<SV>,\n LocalsObj extends Record<string, unknown>,\n VersionedApi extends VersionSchema<SV, 'head'>,\n BaseRequest,\n BaseResponse,\n NextFunction,\n const Auth extends SchemaAuthMethods<\n SV,\n P,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n VersionedApi,\n BaseRequest\n >\n>(\n _schemaValidator: SV,\n path: Path,\n contractDetails: PathParamHttpContractDetails<\n SV,\n Name,\n Path,\n P,\n ResBodyMap,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n ResHeaders,\n VersionedApi,\n BaseRequest,\n Auth\n >,\n ...handlers: ExpressLikeSchemaHandler<\n SV,\n P,\n ResBodyMap,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n ResHeaders,\n LocalsObj,\n VersionedApi,\n ResolvedSessionObject<SV, Auth, SessionObject<SV>>,\n BaseRequest,\n BaseResponse,\n NextFunction\n >[]\n) => {\n return typedHandler<\n SV,\n Name,\n 'head',\n Path,\n P,\n ResBodyMap,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n ResHeaders,\n LocalsObj,\n VersionedApi,\n BaseRequest,\n BaseResponse,\n NextFunction,\n Auth\n >(_schemaValidator, path, 'head', contractDetails, ...handlers);\n};\n","import { AnySchemaValidator } from '@forklaunch/validator';\nimport { ExpressLikeSchemaHandler } from '../types/apiDefinition.types';\nimport {\n Body,\n ContractDetails,\n HeadersObject,\n MiddlewareContractDetails,\n ParamsObject,\n QueryObject,\n ResolvedSessionObject,\n ResponsesObject,\n SchemaAuthMethods,\n SessionObject,\n VersionSchema\n} from '../types/contractDetails.types';\nimport { typedHandler } from './typedHandler';\n\nexport const middleware = <\n SV extends AnySchemaValidator,\n Name extends string,\n Path extends `/${string}`,\n P extends ParamsObject<SV>,\n ResBodyMap extends ResponsesObject<SV>,\n ReqBody extends Body<SV>,\n ReqQuery extends QueryObject<SV>,\n ReqHeaders extends HeadersObject<SV>,\n ResHeaders extends HeadersObject<SV>,\n LocalsObj extends Record<string, unknown>,\n VersionedApi extends VersionSchema<SV, 'middleware'>,\n BaseRequest,\n BaseResponse,\n NextFunction,\n const Auth extends SchemaAuthMethods<\n SV,\n P,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n VersionedApi,\n BaseRequest\n >\n>(\n _schemaValidator: SV,\n path: Path,\n contractDetails: MiddlewareContractDetails<\n SV,\n Name,\n Path,\n P,\n ResBodyMap,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n ResHeaders,\n VersionedApi,\n BaseRequest,\n Auth\n >,\n ...handlers: ExpressLikeSchemaHandler<\n SV,\n P,\n ResBodyMap,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n ResHeaders,\n LocalsObj,\n VersionedApi,\n ResolvedSessionObject<SV, Auth, SessionObject<SV>>,\n BaseRequest,\n BaseResponse,\n NextFunction\n >[]\n) => {\n return typedHandler<\n SV,\n Name,\n 'middleware',\n Path,\n P,\n ResBodyMap,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n ResHeaders,\n LocalsObj,\n VersionedApi,\n BaseRequest,\n BaseResponse,\n NextFunction,\n Auth\n >(_schemaValidator, path, 'middleware', contractDetails, ...handlers) as {\n _typedHandler: true;\n _path: Path;\n contractDetails: ContractDetails<\n SV,\n Name,\n 'middleware',\n Path,\n P,\n ResBodyMap,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n ResHeaders,\n VersionedApi,\n BaseRequest,\n Auth\n >;\n handlers: ExpressLikeSchemaHandler<\n SV,\n P,\n ResBodyMap,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n ResHeaders,\n LocalsObj,\n VersionedApi,\n ResolvedSessionObject<SV, Auth, SessionObject<SV>>,\n BaseRequest,\n BaseResponse,\n NextFunction\n >[];\n };\n};\n","import { AnySchemaValidator } from '@forklaunch/validator';\nimport { ExpressLikeSchemaHandler } from '../types/apiDefinition.types';\nimport {\n Body,\n HeadersObject,\n ParamsObject,\n PathParamHttpContractDetails,\n QueryObject,\n ResolvedSessionObject,\n ResponsesObject,\n SchemaAuthMethods,\n SessionObject,\n VersionSchema\n} from '../types/contractDetails.types';\nimport { typedHandler } from './typedHandler';\n\nexport const options = <\n SV extends AnySchemaValidator,\n Name extends string,\n Path extends `/${string}`,\n P extends ParamsObject<SV>,\n ResBodyMap extends ResponsesObject<SV>,\n ReqBody extends Body<SV>,\n ReqQuery extends QueryObject<SV>,\n ReqHeaders extends HeadersObject<SV>,\n ResHeaders extends HeadersObject<SV>,\n LocalsObj extends Record<string, unknown>,\n VersionedApi extends VersionSchema<SV, 'options'>,\n BaseRequest,\n BaseResponse,\n NextFunction,\n const Auth extends SchemaAuthMethods<\n SV,\n P,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n VersionedApi,\n BaseRequest\n >\n>(\n _schemaValidator: SV,\n path: Path,\n contractDetails: PathParamHttpContractDetails<\n SV,\n Name,\n Path,\n P,\n ResBodyMap,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n ResHeaders,\n VersionedApi,\n BaseRequest,\n Auth\n >,\n ...handlers: ExpressLikeSchemaHandler<\n SV,\n P,\n ResBodyMap,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n ResHeaders,\n LocalsObj,\n VersionedApi,\n ResolvedSessionObject<SV, Auth, SessionObject<SV>>,\n BaseRequest,\n BaseResponse,\n NextFunction\n >[]\n) => {\n return typedHandler<\n SV,\n Name,\n 'options',\n Path,\n P,\n ResBodyMap,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n ResHeaders,\n LocalsObj,\n VersionedApi,\n BaseRequest,\n BaseResponse,\n NextFunction,\n Auth\n >(_schemaValidator, path, 'options', contractDetails, ...handlers);\n};\n","import { AnySchemaValidator } from '@forklaunch/validator';\nimport { ExpressLikeSchemaHandler } from '../types/apiDefinition.types';\nimport {\n Body,\n HeadersObject,\n HttpContractDetails,\n ParamsObject,\n QueryObject,\n ResolvedSessionObject,\n ResponsesObject,\n SchemaAuthMethods,\n SessionObject,\n VersionSchema\n} from '../types/contractDetails.types';\nimport { typedHandler } from './typedHandler';\n\nexport const patch = <\n SV extends AnySchemaValidator,\n Name extends string,\n Path extends `/${string}`,\n P extends ParamsObject<SV>,\n ResBodyMap extends ResponsesObject<SV>,\n ReqBody extends Body<SV>,\n ReqQuery extends QueryObject<SV>,\n ReqHeaders extends HeadersObject<SV>,\n ResHeaders extends HeadersObject<SV>,\n LocalsObj extends Record<string, unknown>,\n VersionedApi extends VersionSchema<SV, 'patch'>,\n BaseRequest,\n BaseResponse,\n NextFunction,\n const Auth extends SchemaAuthMethods<\n SV,\n P,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n VersionedApi,\n BaseRequest\n >\n>(\n _schemaValidator: SV,\n path: Path,\n contractDetails: HttpContractDetails<\n SV,\n Name,\n Path,\n P,\n ResBodyMap,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n ResHeaders,\n VersionedApi,\n BaseRequest,\n Auth\n >,\n ...handlers: ExpressLikeSchemaHandler<\n SV,\n P,\n ResBodyMap,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n ResHeaders,\n LocalsObj,\n VersionedApi,\n ResolvedSessionObject<SV, Auth, SessionObject<SV>>,\n BaseRequest,\n BaseResponse,\n NextFunction\n >[]\n) => {\n return typedHandler<\n SV,\n Name,\n 'patch',\n Path,\n P,\n ResBodyMap,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n ResHeaders,\n LocalsObj,\n VersionedApi,\n BaseRequest,\n BaseResponse,\n NextFunction,\n Auth\n >(_schemaValidator, path, 'patch', contractDetails, ...handlers);\n};\n","import { AnySchemaValidator } from '@forklaunch/validator';\nimport { ExpressLikeSchemaHandler } from '../types/apiDefinition.types';\nimport {\n Body,\n HeadersObject,\n HttpContractDetails,\n ParamsObject,\n QueryObject,\n ResolvedSessionObject,\n ResponsesObject,\n SchemaAuthMethods,\n SessionObject,\n VersionSchema\n} from '../types/contractDetails.types';\nimport { typedHandler } from './typedHandler';\n\nexport const post = <\n SV extends AnySchemaValidator,\n Name extends string,\n Path extends `/${string}`,\n P extends ParamsObject<SV>,\n ResBodyMap extends ResponsesObject<SV>,\n ReqBody extends Body<SV>,\n ReqQuery extends QueryObject<SV>,\n ReqHeaders extends HeadersObject<SV>,\n ResHeaders extends HeadersObject<SV>,\n LocalsObj extends Record<string, unknown>,\n VersionedApi extends VersionSchema<SV, 'post'>,\n BaseRequest,\n BaseResponse,\n NextFunction,\n const Auth extends SchemaAuthMethods<\n SV,\n P,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n VersionedApi,\n BaseRequest\n >\n>(\n _schemaValidator: SV,\n path: Path,\n contractDetails: HttpContractDetails<\n SV,\n Name,\n Path,\n P,\n ResBodyMap,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n ResHeaders,\n VersionedApi,\n BaseRequest,\n Auth\n >,\n ...handlers: ExpressLikeSchemaHandler<\n SV,\n P,\n ResBodyMap,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n ResHeaders,\n LocalsObj,\n VersionedApi,\n ResolvedSessionObject<SV, Auth, SessionObject<SV>>,\n BaseRequest,\n BaseResponse,\n NextFunction\n >[]\n) => {\n return typedHandler<\n SV,\n Name,\n 'post',\n Path,\n P,\n ResBodyMap,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n ResHeaders,\n LocalsObj,\n VersionedApi,\n BaseRequest,\n BaseResponse,\n NextFunction,\n Auth\n >(_schemaValidator, path, 'post', contractDetails, ...handlers);\n};\n","import { AnySchemaValidator } from '@forklaunch/validator';\nimport { ExpressLikeSchemaHandler } from '../types/apiDefinition.types';\nimport {\n Body,\n HeadersObject,\n HttpContractDetails,\n ParamsObject,\n QueryObject,\n ResolvedSessionObject,\n ResponsesObject,\n SchemaAuthMethods,\n SessionObject,\n VersionSchema\n} from '../types/contractDetails.types';\nimport { typedHandler } from './typedHandler';\n\nexport const put = <\n SV extends AnySchemaValidator,\n Name extends string,\n Path extends `/${string}`,\n P extends ParamsObject<SV>,\n ResBodyMap extends ResponsesObject<SV>,\n ReqBody extends Body<SV>,\n ReqQuery extends QueryObject<SV>,\n ReqHeaders extends HeadersObject<SV>,\n ResHeaders extends HeadersObject<SV>,\n LocalsObj extends Record<string, unknown>,\n VersionedApi extends VersionSchema<SV, 'put'>,\n BaseRequest,\n BaseResponse,\n NextFunction,\n const Auth extends SchemaAuthMethods<\n SV,\n P,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n VersionedApi,\n BaseRequest\n >\n>(\n _schemaValidator: SV,\n path: Path,\n contractDetails: HttpContractDetails<\n SV,\n Name,\n Path,\n P,\n ResBodyMap,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n ResHeaders,\n VersionedApi,\n BaseRequest,\n Auth\n >,\n ...handlers: ExpressLikeSchemaHandler<\n SV,\n P,\n ResBodyMap,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n ResHeaders,\n LocalsObj,\n VersionedApi,\n ResolvedSessionObject<SV, Auth, SessionObject<SV>>,\n BaseRequest,\n BaseResponse,\n NextFunction\n >[]\n) => {\n return typedHandler<\n SV,\n Name,\n 'put',\n Path,\n P,\n ResBodyMap,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n ResHeaders,\n LocalsObj,\n VersionedApi,\n BaseRequest,\n BaseResponse,\n NextFunction,\n Auth\n >(_schemaValidator, path, 'put', contractDetails, ...handlers);\n};\n","import { AnySchemaValidator } from '@forklaunch/validator';\nimport { ExpressLikeSchemaHandler } from '../types/apiDefinition.types';\nimport {\n Body,\n HeadersObject,\n ParamsObject,\n PathParamHttpContractDetails,\n QueryObject,\n ResolvedSessionObject,\n ResponsesObject,\n SchemaAuthMethods,\n SessionObject,\n VersionSchema\n} from '../types/contractDetails.types';\nimport { typedHandler } from './typedHandler';\n\nexport const trace = <\n SV extends AnySchemaValidator,\n Name extends string,\n Path extends `/${string}`,\n P extends ParamsObject<SV>,\n ResBodyMap extends ResponsesObject<SV>,\n ReqBody extends Body<SV>,\n ReqQuery extends QueryObject<SV>,\n ReqHeaders extends HeadersObject<SV>,\n ResHeaders extends HeadersObject<SV>,\n LocalsObj extends Record<string, unknown>,\n VersionedApi extends VersionSchema<SV, 'trace'>,\n BaseRequest,\n BaseResponse,\n NextFunction,\n const Auth extends SchemaAuthMethods<\n SV,\n P,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n VersionedApi,\n BaseRequest\n >\n>(\n _schemaValidator: SV,\n path: Path,\n contractDetails: PathParamHttpContractDetails<\n SV,\n Name,\n Path,\n P,\n ResBodyMap,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n ResHeaders,\n VersionedApi,\n BaseRequest,\n Auth\n >,\n ...handlers: ExpressLikeSchemaHandler<\n SV,\n P,\n ResBodyMap,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n ResHeaders,\n LocalsObj,\n VersionedApi,\n ResolvedSessionObject<SV, Auth, SessionObject<SV>>,\n BaseRequest,\n BaseResponse,\n NextFunction\n >[]\n) => {\n return typedHandler<\n SV,\n Name,\n 'trace',\n Path,\n P,\n ResBodyMap,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n ResHeaders,\n LocalsObj,\n VersionedApi,\n BaseRequest,\n BaseResponse,\n NextFunction,\n Auth\n >(_schemaValidator, path, 'trace', contractDetails, ...handlers);\n};\n","import { AnySchemaValidator } from '@forklaunch/validator';\nimport { ExpressLikeSchemaAuthMapper } from '../types/apiDefinition.types';\nimport {\n Body,\n ContractDetails,\n HeadersObject,\n Method,\n ParamsObject,\n QueryObject,\n ResolvedSessionObject,\n ResponsesObject,\n SchemaAuthMethods,\n SessionObject,\n VersionSchema\n} from '../types/contractDetails.types';\n\nexport function typedAuthHandler<\n SV extends AnySchemaValidator,\n Name extends string,\n P extends ParamsObject<SV>,\n ResBodyMap extends ResponsesObject<SV>,\n ReqBody extends Body<SV>,\n ReqQuery extends QueryObject<SV>,\n ReqHeaders extends HeadersObject<SV>,\n ResHeaders extends HeadersObject<SV>,\n VersionedApi extends VersionSchema<SV, Method>,\n Auth extends SchemaAuthMethods<\n SV,\n P,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n VersionedApi,\n BaseRequest\n >,\n BaseRequest\n>(\n _schemaValidator: SV,\n _contractDetails: ContractDetails<\n SV,\n Name,\n Method,\n `/${string}`,\n P,\n ResBodyMap,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n ResHeaders,\n VersionedApi,\n BaseRequest,\n Auth\n >,\n authHandler: ExpressLikeSchemaAuthMapper<\n SV,\n P,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n VersionedApi,\n ResolvedSessionObject<SV, Auth, SessionObject<SV>>,\n BaseRequest\n >\n) {\n return authHandler;\n}\n","/**\n * Object-map of the HTTP Status Codes. Maps from the status code, to the\n * textual name. The key is the HTTP Status Code number, and the resulting\n * value will be the textual name for that Status Code.\n *\n * The comments for each item are taken from httpstatuses.com and the RFC-7231\n * document.\n *\n * @see https://httpstatuses.com\n * @see https://datatracker.ietf.org/doc/html/rfc7231\n */\nexport const HTTPStatuses: Readonly<{ [key: number]: string }> = {\n /**\n * The initial part of a request has been received and has not yet been\n * rejected by the server. The server intends to send a final response after\n * the request has been fully received and acted upon.\n *\n * When the request contains an Expect header field that includes a\n * 100-continue expectation, the 100 response indicates that the server\n * wishes to receive the request payload body. The client ought to continue\n * sending the request and discard the 100 response.\n *\n * If the request did not contain an Expect header field containing the\n * 100-continue expectation, the client can simply discard this interim\n * response.\n */\n 100: 'Continue',\n\n /**\n * The server understands and is willing to comply with the client's request,\n * via the Upgrade header field, for a change in the application protocol\n * being used on this connection.\n *\n * The server MUST generate an Upgrade header field in the response that\n * indicates which protocol(s) will be switched to immediately after the\n * empty line that terminates the 101 response.\n *\n * It is assumed that the server will only agree to switch protocols when it\n * is advantageous to do so. For example, switching to a newer version of\n * HTTP might be advantageous over older versions, and switching to a\n * real-time, synchronous protocol might be advantageous when delivering\n * resources that use such features.\n */\n 101: 'Switching Protocols',\n\n /**\n * An interim response used to inform the client that the server has accepted\n * the complete request, but has not yet completed it.\n *\n * This status code SHOULD only be sent when the server has a reasonable\n * expectation that the request will take significant time to complete. As\n * guidance, if a method is taking longer than 20 seconds (a reasonable, but\n * arbitrary value) to process the server SHOULD return a 102 (Processing)\n * response. The server MUST send a final response after the request has been\n * completed.\n *\n * Methods can potentially take a long period of time to process, especially\n * methods that support the Depth header. In such cases the client may\n * time-out the connection while waiting for a response. To prevent this the\n * server may return a 102 Processing status code to indicate to the client\n * that the server is still processing the method.\n */\n 102: 'Processing',\n\n /**\n * The request has succeeded.\n *\n * Aside from responses to CONNECT, a 200 response always has a payload,\n * though an origin server MAY generate a payload body of zero length. If no\n * payload is desired, an origin server ought to send 204 No Content instead.\n * For CONNECT, no payload is allowed because the successful result is a\n * tunnel, which begins immediately after the 200 response header section.\n *\n * A 200 response is cacheable by default; i.e., unless otherwise indicated\n * by the method definition or explicit cache controls.\n */\n 200: 'OK',\n\n /**\n * The request has been fulfilled and has resulted in one or more new\n * resources being created.\n *\n * The primary resource created by the request is identified by either a\n * Location header field in the response or, if no Location field is\n * received, by the effective request URI.\n *\n * The 201 response payload typically describes and links to the resource(s)\n * created. See Section 7.2 of RFC7231 for a discussion of the meaning and\n * purpose of validator header fields, such as ETag and Last-Modified, in a\n * 201 response.\n */\n 201: 'Created',\n\n /**\n * The request has been accepted for processing, but the processing has not\n * been completed. The request might or might not eventually be acted upon,\n * as it might be disallowed when processing actually takes place.\n *\n * There is no facility in HTTP for re-sending a status code from an\n * asynchronous operation.\n *\n * The 202 response is intentionally noncommittal. Its purpose is to allow a\n * server to accept a request for some other process (perhaps a\n * batch-oriented process that is only run once per day) without requiring\n * that the user agent's connection to the server persist until the process\n * is completed. The representation sent with this response ought to describe\n * the request's current status and point to (or embed) a status monitor that\n * can provide the user with an estimate of when the request will be\n * fulfilled.\n */\n 202: 'Accepted',\n\n /**\n * The request was successful but the enclosed payload has been modified from\n * that of the origin server's 200 OK response by a transforming proxy.\n *\n * This status code allows the proxy to notify recipients when a\n * transformation has been applied, since that knowledge might impact later\n * decisions regarding the content. For example, future cache validation\n * requests for the content might only be applicable along the same request\n * path (through the same proxies).\n *\n * The 203 response is similar to the Warning code of 214 Transformation\n * Applied, which has the advantage of being applicable to responses with any\n * status code.\n *\n * A 203 response is cacheable by default; i.e., unless otherwise indicated\n * by the method definition or explicit cache controls.\n */\n 203: 'Non-authoritative Information',\n\n /**\n * The server has successfully fulfilled the request and that there is no\n * additional content to send in the response payload body.\n *\n * Metadata in the response header fields refer to the target resource and\n * its selected representation after the requested action was applied.\n *\n * A 204 response is terminated by the first empty line after the header\n * fields because it cannot contain a message body.\n *\n * A 204 response is cacheable by default; i.e., unless otherwise indicated\n * by the method definition or explicit cache controls.\n */\n 204: 'No Content',\n\n /**\n * He server has fulfilled the request and desires that the user agent reset\n * the \"document view\", which caused the request to be sent, to its original\n * state as received from the origin server.\n *\n * This response is intended to support a common data entry use case where\n * the user receives content that supports data entry (a form, notepad,\n * canvas, etc.), enters or manipulates data in that space, causes the\n * entered data to be submitted in a request, and then the data entry\n * mechanism is reset for the next entry so that the user can easily\n * initiate another input action.\n *\n * Since the 205 status code implies that no additional content will be\n * provided, a server MUST NOT generate a payload in a 205 response. In\n * other words, a server MUST do one of the following for a 205 response: a)\n * indicate a zero-length body for the response by including a\n * Content-Length header field with a value of 0; b) indicate a zero-length\n * payload for the response by including a Transfer-Encoding header field\n * with a value of chunked and a message body consisting of a single chunk\n * of zero-length; or, c) close the connection immediately after sending the\n * blank line terminating the header section.\n */\n 205: 'Reset Content',\n\n /**\n * The server is successfully fulfilling a range request for the target\n * resource by transferring one or more parts of the selected representation\n * that correspond to the satisfiable ranges found in the request's Range\n * header field.\n *\n * If a single part is being transferred, the server generating the 206\n * response MUST generate a Content-Range header field, describing what range\n * of the selected representation is enclosed, and a payload consisting of\n * the range.\n *\n * If multiple parts are being transferred, the server generating the 206\n * response MUST generate a \"multipart/byteranges\" payload2, and a\n * Content-Type header field containing the multipart/byteranges media type\n * and its required boundary parameter. To avoid confusion with single-part\n * responses, a server MUST NOT generate a Content-Range header field in the\n * HTTP header section of a multiple part response (this field will be sent\n * in each part instead).\n *\n * Within the header area of each body part in the multipart payload, the\n * server MUST generate a Content-Range header field corresponding to the\n * range being enclosed in that body part. If the selected representation\n * would have had a Content-Type header field in a 200 OK response, the\n * server SHOULD generate that same Content-Type field in the header area of\n * each body part.\n *\n * When multiple ranges are requested, a server MAY coalesce any of the\n * ranges that overlap, or that are separated by a gap that is smaller than\n * the overhead of sending multiple parts, regardless of the order in which\n * the corresponding byte-range-spec appeared in the received Range header\n * field. Since the typical overhead between parts of a multipart/byteranges\n * payload is around 80 bytes, depending on the selected representation's\n * media type and the chosen boundary parameter length, it can be less\n * efficient to transfer many small disjoint parts than it is to transfer the\n * entire selected representation.\n *\n * A server MUST NOT generate a multipart response to a request for a single\n * range, since a client that does not request multiple parts might not\n * support multipart responses. However, a server MAY generate a\n * multipart/byteranges payload with only a single body part if multiple\n * ranges were requested and only one range was found to be satisfiable or\n * only one range remained after coalescing. A client that cannot process a\n * multipart/byteranges response MUST NOT generate a request that asks for\n * multiple ranges.\n *\n * When a multipart response payload is generated, the server SHOULD send the\n * parts in the same order that the corresponding byte-range-spec appeared in\n * the received Range header field, excluding those ranges that were deemed\n * unsatisfiable or that were coalesced into other ranges. A client that\n * receives a multipart response MUST inspect the Content-Range header field\n * present in each body part in order to determine which range is contained\n * in that body part; a client cannot rely on receiving the same ranges that\n * it requested, nor the same order that it requested.\n *\n * When a 206 response is generated, the server MUST generate the following\n * header fields, in addition to those required above, if the field would\n * have been sent in a 200 OK response to the same request: Date,\n * Cache-Control, ETag, Expires, Content-Location, and Vary.\n *\n * If a 206 is generated in response to a request with an If-Range header\n * field, the sender SHOULD NOT generate other representation header fields\n * beyond those required above, because the client is understood to already\n * have a prior response containing those header fields. Otherwise, the\n * sender MUST generate all of the representation header fields that would\n * have been sent in a 200 OK response to the same request.\n *\n * A 206 response is cacheable by default; i.e., unless otherwise indicated\n * by explicit cache controls.\n */\n 206: 'Partial Content',\n\n /**\n * A Multi-Status response conveys information about multiple resources in\n * situations where multiple status codes might be appropriate.\n *\n * The default Multi-Status response body is a text/xml or application/xml\n * HTTP entity with a 'multistatus' root element. Further elements contain\n * 200, 300, 400, and 500 series status codes generated during the method\n * invocation. 100 series status codes SHOULD NOT be recorded in a 'response'\n * XML element.\n *\n * Although '207' is used as the overall response status code, the recipient\n * needs to consult the contents of the multistatus response body for further\n * information about the success or failure of the method execution. The\n * response MAY be used in success, partial success and also in failure\n * situations.\n *\n * The 'multistatus' root element holds zero or more 'response' elements in\n * any order, each with information about an individual resource. Each\n * 'response' element MUST have an 'href' element to identify the resource.\n *\n * A Multi-Status response uses one out of two distinct formats for\n * representing the status:\n *\n * 1. A 'status' element as child of the 'response' element indicates the\n * status of the message execution for the identified resource as a whole.\n * Some method definitions provide information about specific status codes\n * clients should be prepared to see in a response. However, clients MUST be\n * able to handle other status codes, using the generic rules defined in\n * RFC2616 Section 10.\n *\n * 2. For PROPFIND and PROPPATCH, the format has been extended using the\n * 'propstat' element instead of 'status', providing information about\n * individual properties of a resource. This format is specific to PROPFIND\n * and PROPPATCH, and is described in detail in RFC4918 Section 9.1 and\n * RFC4918 Section 9.2.\n */\n 207: 'Multi-Status',\n\n /**\n * Used inside a DAV: propstat response element to avoid enumerating the\n * internal members of multiple bindings to the same collection repeatedly.\n *\n * For each binding to a collection inside the request's scope, only one will\n * be reported with a 200 status, while subsequent DAV:response elements for\n * all other bindings will use the 208 status, and no DAV:response elements\n * for their descendants are included.\n *\n * Note that the 208 status will only occur for \"Depth: infinity\" requests,\n * and that it is of particular importance when the multiple collection\n * bindings cause a bind loop.\n *\n * A client can request the DAV:resource-id property in a PROPFIND request to\n * guarantee that they can accurately reconstruct the binding structure of a\n * collection with multiple bindings to a single resource.\n *\n * For backward compatibility with clients not aware of the 208 status code\n * appearing in multistatus response bodies, it SHOULD NOT be used unless the\n * client has signaled support for this specification using the \"DAV\" request\n * header. Instead, a 508 Loop Detected status should be returned when a\n * binding loop is discovered. This allows the server to return the 508 as\n * the top-level return status, if it discovers it before it started the\n * response, or in the middle of a multistatus, if it discovers it in the\n * middle of streaming out a multistatus response.\n */\n 208: 'Already Reported',\n\n /**\n * The server has fulfilled a GET request for the resource, and the response\n * is a representation of the result of one or more instance-manipulations\n * applied to the current instance.\n *\n * The actual current instance might not be available except by combining\n * this response with other previous or future responses, as appropriate for\n * the specific instance-manipulation(s). If so, the headers of the resulting\n * instance are the result of combining the headers from the 226 response and\n * the other instances, following the rules in section 13.5.3 of the HTTP/1.1\n * specification.\n *\n * The request MUST have included an A-IM header field listing at least one\n * instance-manipulation. The response MUST include an Etag header field\n * giving the entity tag of the current instance.\n *\n * A response received with a status code of 226 MAY be stored by a cache and\n * used in reply to a subsequent request, subject to the HTTP expiration\n * mechanism and any Cache-Control headers, and to the requirements in\n * section 10.6.\n *\n * A response received with a status code of 226 MAY be used by a cache, in\n * conjunction with a cache entry for the base instance, to create a cache\n * entry for the current instance.\n */\n 226: 'IM Used',\n\n /**\n * The target resource has more than one representation, each with its own\n * more specific identifier, and information about the alternatives is being\n * provided so that the user (or user agent) can select a preferred\n * representation by redirecting its request to one or more of those\n * identifiers.\n *\n * In other words, the server desires that the user agent engage in reactive\n * negotiation to select the most appropriate representation(s) for its\n * needs.\n *\n * If the server has a preferred choice, the server SHOULD generate a\n * Location header field containing a preferred choice's URI reference. The\n * user agent MAY use the Location field value for automatic redirection.\n *\n * For request methods other than HEAD, the server SHOULD generate a payload\n * in the 300 response containing a list of representation metadata and URI\n * reference(s) from which the user or user agent can choose the one most\n * preferred. The user agent MAY make a selection from that list\n * automatically if it understands the provided media type. A specific format\n * for automatic selection is not defined by this specification because HTTP\n * tries to remain orthogonal to the definition of its payloads. In practice,\n * the representation is provided in some easily parsed format believed to be\n * acceptable to the user agent, as determined by shared design or content\n * negotiation, or in some commonly accepted hypertext format.\n *\n * A 300 response is cacheable by default; i.e., unless otherwise indicated\n * by the method definition or explicit cache controls.\n *\n * Note: The original proposal for the 300 status code defined the URI header\n * field as providing a list of alternative representations, such that it\n * would be usable for 200, 300, and 406 responses and be transferred in\n * responses to the HEAD method. However, lack of deployment and disagreement\n * over syntax led to both URI and Alternates (a subsequent proposal) being\n * dropped from this specification. It is possible to communicate the list\n * using a set of Link header fields3, each with a relationship of\n * \"alternate\", though deployment is a chicken-and-egg problem.\n */\n 300: 'Multiple Choices',\n\n /**\n * The target resource has been assigned a new permanent URI and any future\n * references to this resource ought to use one of the enclosed URIs.\n *\n * Clients with link-editing capabilities ought to automatically re-link\n * references to the effective request URI to one or more of the new\n * references sent by the server, where possible.\n *\n * The server SHOULD generate a Location header field in the response\n * containing a preferred URI reference for the new permanent URI. The user\n * agent MAY use the Location field value for automatic redirection. The\n * server's response payload usually contains a short hypertext note with a\n * hyperlink to the new URI(s).\n *\n * Note: For historical reasons, a user agent MAY change the request method\n * from POST to GET for the subsequent request. If this behavior is\n * undesired, the 307 Temporary Redirect status code can be used instead.\n *\n * A 301 response is cacheable by default; i.e., unless otherwise indicated\n * by the method definition or explicit cache controls.\n */\n 301: 'Moved Permanently',\n\n /**\n * The target resource resides temporarily under a different URI. Since the\n * redirection might be altered on occasion, the client ought to continue to\n * use the effective request URI for future requests.\n *\n * The server SHOULD generate a Location header field in the response\n * containing a URI reference for the different URI. The user agent MAY use\n * the Location field value for automatic redirection. The server's response\n * payload usually contains a short hypertext note with a hyperlink to the\n * different URI(s).\n *\n * Note: For historical reasons, a user agent MAY change the request method\n * from POST to GET for the subsequent request. If this behavior is\n * undesired, the 307 Temporary Redirect status code can be used instead.\n */\n 302: 'Found',\n\n /**\n * The server is redirecting the user agent to a different resource, as\n * indicated by a URI in the Location header field, which is intended to\n * provide an indirect response to the original request.\n *\n * A user agent can perform a retrieval request targeting that URI (a GET or\n * HEAD request if using HTTP), which might also be redirected, and present\n * the eventual result as an answer to the original request. Note that the\n * new URI in the Location header field is not considered equivalent to the\n * effective request URI.\n *\n * This status code is applicable to any HTTP method. It is primarily used\n * to allow the output of a POST action to redirect the user agent to a\n * selected resource, since doing so provides the information corresponding\n * to the POST response in a form that can be separately identified,\n * bookmarked, and cached, independent of the original request.\n *\n * A 303 response to a GET request indicates that the origin server does not\n * have a representation of the target resource that can be transferred by\n * the server over HTTP. However, the Location field value refers to a\n * resource that is descriptive of the target resource, such that making a\n * retrieval request on that other resource might result in a representation\n * that is useful to recipients without implying that it represents the\n * original target resource. Note that answers to the questions of what can\n * be represented, what representations are adequate, and what might be a\n * useful description are outside the scope of HTTP.\n *\n * Except for responses to a HEAD request, the representation of a 303\n * response ought to contain a short hypertext note with a hyperlink to the\n * same URI reference provided in the Location header field.\n */\n 303: 'See Other',\n\n /**\n * A conditional GET or HEAD request has been received and would have\n * resulted in a 200 OK response if it were not for the fact that the\n * condition evaluated to false.\n *\n * In other words, there is no need for the server to transfer a\n * representation of the target resource because the request indicates that\n * the client, which made the request conditional, already has a valid\n * representation; the server is therefore redirecting the client to make\n * use of that stored representation as if it were the payload of a 200 OK\n * response.\n *\n * The server generating a 304 response MUST generate any of the following\n * header fields that would have been sent in a 200 OK response to the same\n * request: Cache-Control, Content-Location, Date, ETag, Expires, and Vary.\n *\n * Since the goal of a 304 response is to minimize information transfer when\n * the recipient already has one or more cached representations, a sender\n * SHOULD NOT generate representation metadata other than the above listed\n * fields unless said metadata exists for the purpose of guiding cache\n * updates (e.g., Last-Modified might be useful if the response does not have\n * an ETag field).\n *\n * Requirements on a cache that receives a 304 response are defined in\n * Section 4.3.4 of RFC7234. If the conditional request originated with an\n * outbound client, such as a user agent with its own cache sending a\n * conditional GET to a shared proxy, then the proxy SHOULD forward the\n * 304 response to that client.\n *\n * A 304 response cannot contain a message-body; it is always terminated by\n * the first empty line after the header fields.\n */\n 304: 'Not Modified',\n\n /**\n * Defined in a previous version of this specification and is now deprecated,\n * due to security concerns regarding in-band configuration of a proxy.\n */\n 305: 'Use Proxy',\n\n /**\n * The target resource resides temporarily under a different URI and the user\n * agent MUST NOT change the request method if it performs an automatic\n * redirection to that URI.\n *\n * Since the redirection can change over time, the client ought to continue\n * using the original effective request URI for future requests.\n *\n * The server SHOULD generate a Location header field in the response\n * containing a URI reference for the different URI. The user agent MAY use\n * the Location field value for automatic redirection. The server's response\n * payload usually contains a short hypertext note with a hyperlink to the\n * different URI(s).\n *\n * Note: This status code is similar to 302 Found, except that it does not\n * allow changing the request method from POST to GET. This specification\n * defines no equivalent counterpart for 301 Moved Permanently (RFC7238,\n * however, proposes defining the status code 308 Permanent Redirect for\n * this purpose).\n */\n 307: 'Temporary Redirect',\n\n /**\n * The target resource has been assigned a new permanent URI and any future\n * references to this resource ought to use one of the enclosed URIs.\n *\n * Clients with link editing capabilities ought to automatically re-link\n * references to the effective request URI to one or more of the new\n * references sent by the server, where possible.\n *\n * The server SHOULD generate a Location header field in the response\n * containing a preferred URI reference for the new permanent URI. The user\n * agent MAY use the Location field value for automatic redirection. The\n * server's response payload usually contains a short hypertext note with a\n * hyperlink to the new URI(s).\n *\n * A 308 response is cacheable by default; i.e., unless otherwise indicated\n * by the method definition or explicit cache controls.\n *\n * Note: This status code is similar to 301 Moved Permanently, except that it\n * does not allow changing the request method from POST to GET.\n */\n 308: 'Permanent Redirect',\n\n /**\n * The 400 (Bad Request) status code indicates that the server cannot or\n * will not process the request due to something that is perceived to be\n * a client error (e.g., malformed request syntax, invalid request\n * message framing, or deceptive request routing).\n */\n 400: 'Bad Request',\n\n /**\n * The request has not been applied because it lacks valid authentication\n * credentials for the target resource.\n *\n * The server generating a 401 response MUST send a WWW-Authenticate header\n * field containing at least one challenge applicable to the target resource.\n *\n * If the request included authentication credentials, then the 401 response\n * indicates that authorization has been refused for those credentials. The\n * user agent MAY repeat the request with a new or replaced Authorization\n * header field. If the 401 response contains the same challenge as the\n * prior response, and the user agent has already attempted authentication at\n * least once, then the user agent SHOULD present the enclosed representation\n * to the user, since it usually contains relevant diagnostic information.\n */\n 401: 'Unauthorized',\n\n /**\n * The 402 (Payment Required) status code is reserved for future use.\n */\n 402: 'Payment Required',\n\n /**\n * The 403 (Forbidden) status code indicates that the server understood\n * the request but refuses to authorize it. A server that wishes to\n * make public why the request has been forbidden can describe that\n * reason in the response payload (if any).\n *\n * If authentication credentials were provided in the request, the\n * server considers them insufficient to grant access. The client\n * SHOULD NOT automatically repeat the request with the same\n * credentials. The client MAY repeat the request with new or different\n * credentials. However, a request might be forbidden for reasons\n * unrelated to the credentials.\n *\n * An origin server that wishes to \"hide\" the current existence of a\n * forbidden target resource MAY instead respond with a status code of\n * 404 (Not Found).\n */\n 403: 'Forbidden',\n\n /**\n * The 404 (Not Found) status code indicates that the origin server did\n * not find a current representation for the target resource or is not\n * willing to disclose that one exists. A 404 status code does not\n * indicate whether this lack of representation is temporary or\n * permanent; the 410 (Gone) status code is preferred over 404 if the\n * origin server knows, presumably through some configurable means, that\n * the condition is likely to be permanent.\n *\n * A 404 response is cacheable by default; i.e., unless otherwise\n * indicated by the method definition or explicit cache controls (see\n * Section 4.2.2 of [RFC7234]).\n */\n 404: 'Not Found',\n\n /**\n * The 405 (Method Not Allowed) status code indicates that the method\n * received in the request-line is known by the origin server but not\n * supported by the target resource. The origin server MUST generate an\n * Allow header field in a 405 response containing a list of the target\n * resource's currently supported methods.\n *\n * A 405 response is cacheable by default; i.e., unless otherwise\n * indicated by the method definition or explicit cache controls (see\n * Section 4.2.2 of [RFC7234]).\n */\n 405: 'Method Not Allowed',\n\n /**\n * The 406 (Not Acceptable) status code indicates that the target\n * resource does not have a current representation that would be\n * acceptable to the user agent, according to the proactive negotiation\n * header fields received in the request (Section 5.3), and the server\n * is unwilling to supply a default representation.\n *\n * The server SHOULD generate a payload containing a list of available\n * representation characteristics and corresponding resource identifiers\n * from which the user or user agent can choose the one most\n * appropriate. A user agent MAY automatically select the most\n * appropriate choice from that list. However, this specification does\n * not define any standard for such automatic selection, as described in\n * Section 6.4.1 of [RFC7231]\n */\n 406: 'Not Acceptable',\n\n /**\n * Similar to 401 Unauthorized, but it indicates that the client needs to\n * authenticate itself in order to use a proxy.\n *\n * The proxy MUST send a Proxy-Authenticate header field containing a\n * challenge applicable to that proxy for the target resource. The client MAY\n * repeat the request with a new or replaced Proxy-Authorization header field.\n */\n 407: 'Proxy Authentication Required',\n\n /**\n * The 408 (Request Timeout) status code indicates that the server did\n * not receive a complete request message within the time that it was\n * prepared to wait. A server SHOULD send the \"close\" connection option\n * (Section 6.1 of [RFC7230]) in the response, since 408 implies that\n * the server has decided to close the connection rather than continue\n * waiting. If the client has an outstanding request in transit, the\n * client MAY repeat that request on a new connection.\n */\n 408: 'Request Timeout',\n\n /**\n * The 409 (Conflict) status code indicates that the request could not\n * be completed due to a conflict with the current state of the target\n * resource. This code is used in situations where the user might be\n * able to resolve the conflict and resubmit the request. The server\n * SHOULD generate a payload that includes enough information for a user\n * to recognize the source of the conflict.\n *\n * Conflicts are most likely to occur in response to a PUT request. For\n * example, if versioning were being used and the representation being\n * PUT included changes to a resource that conflict with those made by\n * an earlier (third-party) request, the origin server might use a 409\n * response to indicate that it can't complete the request. In this\n * case, the response representation would likely contain information\n * useful for merging the differences based on the revision history.\n */\n 409: 'Conflict',\n\n /**\n * The 410 (Gone) status code indicates that access to the target\n * resource is no longer available at the origin server and that this\n * condition is likely to be permanent. If the origin server does not\n * know, or has no facility to determine, whether or not the condition\n * is permanent, the status code 404 (Not Found) ought to be used\n * instead.\n *\n * The 410 response is primarily intended to assist the task of web\n * maintenance by notifying the recipient that the resource is\n * intentionally unavailable and that the server owners desire that\n * remote links to that resource be removed. Such an event is common\n * for limited-time, promotional services and for resources belonging to\n * individuals no longer associated with the origin server's site. It\n * is not necessary to mark all permanently unavailable resources as\n * \"gone\" or to keep the mark for any length of time -- that is left to\n * the discretion of the server owner.\n *\n * A 410 response is cacheable by default; i.e., unless otherwise\n * indicated by the method definition or explicit cache controls (see\n * Section 4.2.2 of [RFC7234]).\n */\n 410: 'Gone',\n\n /**\n * The 411 (Length Required) status code indicates that the server\n * refuses to accept the request without a defined Content-Length\n * (Section 3.3.2 of [RFC7230]). The client MAY repeat the request if\n * it adds a valid Content-Length header field containing the length of\n * the message body in the request message.\n */\n 411: 'Length Required',\n\n /**\n * One or more conditions given in the request header fields evaluated to\n * false when tested on the server.\n *\n * This response code allows the client to place preconditions on the current\n * resource state (its current representations and metadata) and, thus,\n * prevent the request method from being applied if the target resource is in\n * an unexpected state.\n */\n 412: 'Precondition Failed',\n\n /**\n * The 413 (Payload Too Large) status code indicates that the server is\n * refusing to process a request because the request payload is larger\n * than the server is willing or able to process. The server MAY close\n * the connection to prevent the client from continuing the request.\n *\n * If the condition is temporary, the server SHOULD generate a\n * Retry-After header field to indicate that it is temporary and after\n * what time the client MAY try again.\n */\n 413: 'Payload Too Large',\n\n /**\n * The 414 (URI Too Long) status code indicates that the server is\n * refusing to service the request because the request-target (Section\n * 5.3 of [RFC7230]) is longer than the server is willing to interpret.\n * This rare condition is only likely to occur when a client has\n * improperly converted a POST request to a GET request with long query\n * information, when the client has descended into a \"black hole\" of\n * redirection (e.g., a redirected URI prefix that points to a suffix of\n * itself) or when the server is under attack by a client attempting to\n * exploit potential security holes.\n *\n * A 414 response is cacheable by default; i.e., unless otherwise\n * indicated by the method definition or explicit cache controls (see\n * Section 4.2.2 of [RFC7234]).\n */\n 414: 'Request-URI Too Long',\n\n /**\n * The 415 (Unsupported Media Type) status code indicates that the\n * origin server is refusing to service the request because the payload\n * is in a format not supported by this method on the target resource.\n * The format problem might be due to the request's indicated\n * Content-Type or Content-Encoding, or as a result of inspecting the\n * data directly.\n */\n 415: 'Unsupported Media Type',\n\n /**\n * None of the ranges in the request's Range header field overlap the\n * current extent of the selected resource or that the set of ranges\n * requested has been rejected due to invalid ranges or an excessive request\n * of small or overlapping ranges.\n *\n * For byte ranges, failing to overlap the current extent means that the\n * first-byte-pos of all of the byte-range-spec values were greater than the\n * current length of the selected representation. When this status code is\n * generated in response to a byte-range request, the sender SHOULD generate\n * a Content-Range header field specifying the current length of the selected\n * representation\n */\n 416: 'Requested Range Not Satisfiable',\n\n /**\n * The 417 (Expectation Failed) status code indicates that the\n * expectation given in the request's Expect header field\n * (Section 5.1.1 of [RFC7231]) could not be met by at least one of the\n * inbound servers.\n */\n 417: 'Expectation Failed',\n\n /**\n * Any attempt to brew coffee with a teapot should result in the error code\n * \"418 I'm a teapot\". The resulting entity body MAY be short and stout.\n */\n 418: \"I'm a Teapot\",\n\n /**\n * The request was directed at a server that is not able to produce a\n * response. This can be sent by a server that is not configured to produce\n * responses for the combination of scheme and authority that are included\n * in the request URI.\n *\n * Clients receiving a 421 Misdirected Request response from a server MAY\n * retry the request -- whether the request method is idempotent or\n * not -- over a different connection. This is possible if a connection is\n * reused or if an alternative service is selected ALT-SVC.\n *\n * This status code MUST NOT be generated by proxies.\n *\n * A 421 response is cacheable by default, i.e., unless otherwise indicated by\n * the method definition or explicit cache controls\n */\n 421: 'Misdirected Request',\n\n /**\n * The server understands the content type of the request entity (hence a\n * 415 Unsupported Media Type status code is inappropriate), and the syntax\n * of the request entity is correct (thus a 400 Bad Request status code is\n * inappropriate) but was unable to process the contained instructions.\n *\n * For example, this error condition may occur if an XML request body contains\n * well-formed (i.e., syntactically correct), but semantically erroneous, XML\n * instructions.\n */\n 422: 'Unprocessable Entity',\n\n /**\n * The source or destination resource of a method is locked.\n *\n * This response SHOULD contain an appropriate precondition or postcondition\n * code, such as 'lock-token-submitted' or 'no-conflicting-lock'.\n */\n 423: 'Locked',\n\n /**\n * The method could not be performed on the resource because the requested\n * action depended on another action and that action failed.\n *\n * For example, if a command in a PROPPATCH method fails, then, at minimum,\n * the rest of the commands will also fail with 424 Failed Dependency.\n */\n 424: 'Failed Dependency',\n\n /**\n * The 426 (Upgrade Required) status code indicates that the server\n * refuses to perform the request using the current protocol but might\n * be willing to do so after the client upgrades to a different\n * protocol. The server MUST send an Upgrade header field in a 426\n * response to indicate the required protocol(s) (Section 6.7 of\n * [RFC7230]).\n */\n 426: 'Upgrade Required',\n\n /**\n * The origin server requires the request to be conditional.\n *\n * Its typical use is to avoid the \"lost update\" problem, where a client GETs\n * a resource's state, modifies it, and PUTs it back to the server, when\n * meanwhile a third party has modified the state on the server, leading\n * to a conflict. By requiring requests to be conditional, the server can\n * assure that clients are working with the correct copies.\n *\n * Responses using this status code SHOULD explain how to resubmit the request\n * successfully.\n *\n * Responses with the 428 status code MUST NOT be stored by a cache.\n */\n 428: 'Precondition Required',\n\n /**\n * The user has sent too many requests in a given amount of time\n * (\"rate limiting\").\n *\n * The response representations SHOULD include details explaining the\n * condition, and MAY include a Retry-After header indicating how long to\n * wait before making a new request.\n *\n * Responses with the 429 status code MUST NOT be stored by a cache.\n */\n 429: 'Too Many Requests',\n\n /**\n * The server is unwilling to process the request because its header fields\n * are too large. The request MAY be resubmitted after reducing the size of\n * the request header fields.\n *\n * It can be used both when the set of request header fields in total is too\n * large, and when a single header field is at fault. In the latter case, the\n * response representation SHOULD specify which header field was too large.\n */\n 431: 'Request Header Fields Too Large',\n\n /**\n * A non-standard status code used to instruct nginx to close the connection\n * without sending a response to the client, most commonly used to deny\n * malicious or malformed requests.\n *\n * This status code is not seen by the client, it only appears in nginx log\n * files.\n */\n 444: 'Connection Closed Without Response',\n\n /**\n * The server is denying access to the resource as a consequence of a legal\n * demand.\n *\n * The server in question might not be an origin server. This type of legal\n * demand typically most directly affects the operations of ISPs and search\n * engines.\n *\n * Responses using this status code SHOULD include an explanation, in the\n * response body, of the details of the legal demand: the party making it,\n * the applicable legislation or regulation, and what classes of person and\n * resource it applies to.\n *\n * The use of the 451 status code implies neither the existence nor\n * non-existence of the resource named in the request. That is to say, it is\n * possible that if the legal demands were removed, a request for the\n * resource still might not succeed.\n *\n * Note that in many cases clients can still access the denied resource by\n * using technical countermeasures such as a VPN or the Tor network.\n *\n * A 451 response is cacheable by default; i.e., unless otherwise indicated\n * by the method definition or explicit cache controls; see RFC7234.\n */\n 451: 'Unavailable For Legal Reasons',\n\n /**\n * A non-standard status code introduced by nginx for the case when a client\n * closes the connection while nginx is processing the request.\n */\n 499: 'Client Closed Request',\n\n /**\n * The 500 (Internal Server Error) status code indicates that the server\n * encountered an unexpected condition that prevented it from fulfilling\n * the request.\n */\n 500: 'Internal Server Error',\n\n /**\n * The 501 (Not Implemented) status code indicates that the server does\n * not support the functionality required to fulfill the request. This\n * is the appropriate response when the server does not recognize the\n * request method and is not capable of supporting it for any resource.\n *\n * A 501 response is cacheable by default; i.e., unless otherwise\n * indicated by the method definition or explicit cache controls (see\n * Section 4.2.2 of [RFC7234]).\n */\n 501: 'Not Implemented',\n\n /**\n * The 502 (Bad Gateway) status code indicates that the server, while\n * acting as a gateway or proxy, received an invalid response from an\n * inbound server it accessed while attempting to fulfill the request.\n */\n 502: 'Bad Gateway',\n\n /**\n * The 503 (Service Unavailable) status code indicates that the server\n * is currently unable to handle the request due to a temporary overload\n * or scheduled maintenance, which will likely be alleviated after some\n * delay. The server MAY send a Retry-After header field\n * (Section 7.1.3 of [RFC7231]) to suggest an appropriate amount of time for\n * the client to wait before retrying the request.\n */\n 503: 'Service Unavailable',\n\n /**\n * The 504 (Gateway Timeout) status code indicates that the server,\n *while acting as a gateway or proxy, did not receive a timely response\n *from an upstream server it needed to access in order to complete the\n *request.\n */\n 504: 'Gateway Timeout',\n\n /**\n * The 505 (HTTP Version Not Supported) status code indicates that the\n *server does not support, or refuses to support, the major version of\n *HTTP that was used in the request message. The server is indicating\n *that it is unable or unwilling to complete the request using the same\n *major version as the client, as described in Section 2.6 of\n *[RFC7230], other than with this error message. The server SHOULD\n *generate a representation for the 505 response that describes why\n *that version is not supported and what other protocols are supported\n *by that server.\n */\n 505: 'HTTP Version Not Supported',\n\n /**\n * The server has an internal configuration error: the chosen variant\n * resource is configured to engage in transparent content negotiation\n * itself, and is therefore not a proper end point in the negotiation\n * process.\n */\n 506: 'Variant Also Negotiates',\n\n /**\n * The method could not be performed on the resource because the server is\n * unable to store the representation needed to successfully complete the\n * request.\n *\n * This condition is considered to be temporary. If the request that received\n * this status code was the result of a user action, the request MUST NOT be\n * repeated until it is requested by a separate user action.\n */\n 507: 'Insufficient Storage',\n\n /**\n * The server terminated an operation because it encountered an infinite loop\n * while processing a request with \"Depth: infinity\". This status indicates\n * that the entire operation failed.\n */\n 508: 'Loop Detected',\n\n /**\n * The policy for accessing the resource has not been met in the request. The\n * server should send back all the information necessary for the client to\n * issue an extended request.\n *\n * It is outside the scope of this specification to specify how the\n * extensions inform the client.\n *\n * If the 510 response contains information about extensions that were not\n * present in the initial request then the client MAY repeat the request if\n * it has reason to believe it can fulfill the extension policy by modifying\n * the request according to the information provided in the 510 response.\n * Otherwise the client MAY present any entity included in the 510 response\n * to the user, since that entity may include relevant diagnostic information.\n */\n 510: 'Not Extended',\n\n /**\n * The client needs to authenticate to gain network access.\n *\n * The response representation SHOULD contain a link to a resource that\n * allows the user to submit credentials (e.g., with an HTML form).\n *\n * Note that the 511 response SHOULD NOT contain a challenge or the login\n * interface itself, because browsers would show the login interface as being\n * associated with the originally requested URL, which may cause confusion.\n *\n * The 511 status SHOULD NOT be generated by origin servers; it is intended\n * for use by intercepting proxies that are interposed as a means of\n * controlling access to the network.\n *\n * Responses with the 511 status code MUST NOT be stored by a cache.\n */\n 511: 'Network Authentication Required',\n\n /**\n * This status code is not specified in any RFCs, but is used by some HTTP\n * proxies to signal a network connect timeout behind the proxy to a client\n * in front of the proxy.\n */\n 599: 'Network Connect Timeout Error'\n} as const;\n\n/**\n * Numerical HTTP status code.\n */\nexport type StatusCode = keyof typeof HTTPStatuses;\n\n/**\n * Checks if the given numerical status code is in the known HTTP status codes\n * list.\n *\n * @param code HTTP Status code\n * @returns True if the code is a valid HTTP status code\n */\nexport const isValidStatusCode = (code: number): boolean =>\n !!HTTPStatuses[code];\n\n/**\n * Checks if the given status code is in the informational range (1XX).\n *\n * @param code HTTP Status code\n * @returns True if the code is in the \"informational\" range.\n */\nexport const isInformational = (code: StatusCode): boolean =>\n code >= 100 && code < 200;\n\n/**\n * Checks if the given status code is in the successful range (2XX).\n *\n * @param code HTTP Status code\n * @returns True if the code is in the \"success\" range.\n */\nexport const isSuccessful = (code: StatusCode): boolean =>\n code >= 200 && code < 300;\n\n/**\n * Checks if the given status code is in the redirection range (3XX).\n *\n * @param code HTTP Status code\n * @returns True if the code is in the \"redirection\" range.\n */\nexport const isRedirection = (code: StatusCode): boolean =>\n code >= 300 && code < 400;\n\n/**\n * Checks if the given status code is in the client error range (4XX).\n *\n * @param code HTTP Status code\n * @returns True if the code is in the \"client error\" range.\n */\nexport const isClientError = (code: StatusCode): boolean =>\n code >= 400 && code < 500;\n\n/**\n * Checks if the given status code is in the server error range (5XX).\n *\n * @param code HTTP Status code\n * @returns True if the code is in the \"server error\" range.\n */\nexport const isServerError = (code: StatusCode): boolean => code >= 500;\n\n/**\n * Searches the list of HTTP statuses for a matching textual name to the one\n * provided. If a match is found, then the numerical status code is returned,\n * otherwise `null`.\n *\n * Internally, the parameter and the status names are normalized by lower-casing\n * the strings and trimming space.\n *\n * @param status HTTP Status textual name\n * @returns The numerical status code, or null if not found\n */\nexport const getCodeForStatus = (status: string): null | StatusCode => {\n const clnStr = status.toLocaleLowerCase().trim();\n const entry = Object.entries(HTTPStatuses).find(\n (ent) => ent[1].toLowerCase() === clnStr\n );\n if (entry) return parseInt(entry[0]) as StatusCode;\n return null;\n};\n\nexport default HTTPStatuses;\n","import { isNever, isRecord, safeStringify } from '@forklaunch/common';\nimport { string, ZodSchemaValidator, ZodType } from '@forklaunch/validator/zod';\nimport { FastMCP } from 'fastmcp';\nimport http from 'http';\nimport {\n discriminateBody,\n discriminateResponseBodies\n} from '../router/discriminateBody';\nimport { unpackRouters } from '../router/unpackRouters';\nimport {\n Body,\n HeadersObject,\n Method,\n ParamsObject,\n QueryObject,\n SchemaAuthMethods,\n SessionObject,\n VersionSchema\n} from '../types/contractDetails.types';\nimport { ExpressLikeApplicationOptions } from '../types/expressLikeOptions';\nimport { ForklaunchRouter } from '../types/router.types';\n\nfunction generateInputSchema(\n schemaValidator: ZodSchemaValidator,\n body?: Body<ZodSchemaValidator>,\n params?: ParamsObject<ZodSchemaValidator>,\n query?: QueryObject<ZodSchemaValidator>,\n requestHeaders?: HeadersObject<ZodSchemaValidator>,\n auth?: SchemaAuthMethods<\n ZodSchemaValidator,\n ParamsObject<ZodSchemaValidator>,\n Body<ZodSchemaValidator>,\n QueryObject<ZodSchemaValidator>,\n HeadersObject<ZodSchemaValidator>,\n VersionSchema<ZodSchemaValidator, Method>,\n unknown\n >\n) {\n let discriminatedBody:\n ReturnType<typeof discriminateBody<ZodSchemaValidator>> | undefined;\n\n if (body) {\n discriminatedBody = discriminateBody(schemaValidator, body);\n }\n return schemaValidator.schemify({\n ...(discriminatedBody && body\n ? {\n ...('contentType' in body ? { contentType: body.contentType } : {}),\n body: schemaValidator.schemify(discriminatedBody.schema)\n }\n : {}),\n ...(params\n ? {\n params: schemaValidator.schemify(params)\n }\n : {}),\n ...(query\n ? {\n query: schemaValidator.schemify(query)\n }\n : {}),\n ...(requestHeaders\n ? {\n headers: schemaValidator.schemify({\n ...requestHeaders,\n ...(auth\n ? {\n [auth.headerName ?? 'authorization']: string.startsWith(\n auth.tokenPrefix ?? ('basic' in auth ? 'Basic ' : 'Bearer ')\n )\n }\n : {})\n })\n }\n : {})\n });\n}\n/**\n * Generates a ModelContextProtocol server from given routers.\n *\n * @template SV - A type that extends AnySchemaValidator.\n * @param {SV} schemaValidator - The schema validator.\n * @param {string | number} port - The port on which the server is running.\n * @param {ForklaunchRouter<SV>[]} routers - The routers to include in the server.\n * @returns {McpServer} - The generated ModelContextProtocol server.\n */\nexport function generateMcpServer<\n T extends Record<string, unknown> | undefined =\n Record<string, unknown> | undefined\n>(\n schemaValidator: ZodSchemaValidator,\n protocol: 'http' | 'https',\n host: string,\n port: number,\n version: `${number}.${number}.${number}`,\n application: ForklaunchRouter<ZodSchemaValidator>,\n appOptions?: ExpressLikeApplicationOptions<\n ZodSchemaValidator,\n SessionObject<ZodSchemaValidator>\n >['mcp'],\n options?: ConstructorParameters<typeof FastMCP<T>>[0],\n contentTypeMap?: Record<string, string>,\n authenticate?: (\n request: http.IncomingMessage\n ) => Promise<Record<string, unknown> | undefined>\n) {\n if (!(schemaValidator instanceof ZodSchemaValidator)) {\n throw new Error(\n 'Schema validator must be an instance of ZodSchemaValidator'\n );\n }\n\n const mcpServer = new FastMCP({\n ...options,\n name: options?.name ?? 'mcp-server',\n version,\n authenticate\n });\n\n [\n {\n fullPath: application.basePath === '/' ? '' : application.basePath,\n router: application\n },\n ...unpackRouters<ZodSchemaValidator>(application.routers, [\n application.basePath === '/' ? '' : application.basePath\n ])\n ].forEach(({ fullPath, router }) => {\n router.routes.forEach((route) => {\n if (!(\n route.contractDetails.options?.mcp ??\n router.routerOptions?.mcp ??\n appOptions !== false\n )) {\n return;\n }\n\n const inputSchemas: ZodType[] = [];\n\n if (route.contractDetails.versions) {\n Object.values(route.contractDetails.versions).forEach((version) => {\n inputSchemas.push(\n generateInputSchema(\n schemaValidator,\n version.body,\n route.contractDetails.params,\n version.query,\n version.requestHeaders,\n route.contractDetails.auth\n )\n );\n });\n } else {\n inputSchemas.push(\n generateInputSchema(\n schemaValidator,\n route.contractDetails.body,\n route.contractDetails.params,\n route.contractDetails.query,\n route.contractDetails.requestHeaders,\n route.contractDetails.auth\n )\n );\n }\n\n inputSchemas.forEach((inputSchema, index) => {\n mcpServer.addTool({\n name:\n route.contractDetails.name +\n (Object.keys(route.contractDetails.versions ?? {}).length > 1\n ? ` [v${Object.keys(route.contractDetails.versions ?? {})[index]}]`\n : ''),\n description: route.contractDetails.summary,\n parameters: inputSchema,\n execute: async (args) => {\n const { contentType, body, params, query, headers } = args as {\n contentType?: string;\n params?: Record<string, string | number | boolean>;\n body?: Record<string, unknown> | string;\n query?: Record<string, string | number | boolean>;\n headers?: Record<string, unknown>;\n };\n\n let url = `${protocol}://${host}:${port}${fullPath}${route.path}`;\n\n if (params) {\n for (const key in params) {\n url = url.replace(\n `:${key}`,\n encodeURIComponent(params[key] as string)\n );\n }\n }\n\n let bodySchema;\n let responsesSchemas;\n if (route.contractDetails.versions) {\n const version = route.contractDetails.versions[index];\n if (version.body && schemaValidator.parse(inputSchema, args).ok) {\n bodySchema = version.body;\n responsesSchemas = version.responses;\n }\n } else {\n bodySchema = route.contractDetails.body;\n responsesSchemas = route.contractDetails.responses;\n }\n\n const discriminatedBody = bodySchema\n ? discriminateBody(schemaValidator, bodySchema)\n : undefined;\n\n let parsedBody;\n if (discriminatedBody) {\n switch (discriminatedBody.parserType) {\n case 'json': {\n parsedBody = safeStringify(body);\n break;\n }\n case 'text': {\n parsedBody = body;\n break;\n }\n case 'file': {\n parsedBody = Buffer.from(safeStringify(body));\n break;\n }\n case 'multipart': {\n const formData = new FormData();\n if (isRecord(body)) {\n for (const key in body) {\n if (typeof body[key] === 'string') {\n if (\n schemaValidator.isInstanceOf(\n body[key],\n schemaValidator.file\n )\n ) {\n formData.append(\n key,\n new Blob([new Uint8Array(Buffer.from(body[key]))])\n );\n } else {\n formData.append(key, body[key]);\n }\n } else {\n throw new Error('Body is not a valid multipart object');\n }\n }\n } else {\n throw new Error('Body is not a valid multipart object');\n }\n parsedBody = formData;\n break;\n }\n case 'urlEncoded': {\n if (isRecord(body)) {\n parsedBody = new URLSearchParams(\n Object.entries(body).map(([key, value]) => [\n key,\n safeStringify(value)\n ])\n );\n } else {\n throw new Error('Body is not a valid url encoded object');\n }\n break;\n }\n default: {\n isNever(discriminatedBody.parserType);\n parsedBody = safeStringify(body);\n break;\n }\n }\n }\n\n if (query) {\n const queryString = new URLSearchParams(\n Object.entries(query).map(([key, value]) => [\n key,\n safeStringify(value)\n ])\n ).toString();\n url += queryString ? `?${queryString}` : '';\n }\n\n const response = await fetch(encodeURI(url), {\n method: route.method.toUpperCase(),\n headers: {\n ...headers,\n ...(discriminatedBody?.contentType != 'multipart/form-data'\n ? {\n 'Content-Type':\n contentType ?? discriminatedBody?.contentType\n }\n : {})\n },\n body: parsedBody as BodyInit | null | undefined\n });\n\n if (response.status >= 300) {\n throw new Error(\n `Error received while proxying request to ${url}: ${await response.text()}`\n );\n }\n\n if (!responsesSchemas) {\n throw new Error('No responses schemas found');\n }\n\n const contractContentType = discriminateResponseBodies(\n schemaValidator,\n responsesSchemas\n )[response.status].contentType;\n switch (\n contentTypeMap && contentTypeMap[contractContentType]\n ? contentTypeMap[contractContentType]\n : contractContentType\n ) {\n case 'application/json':\n return {\n content: [\n {\n type: 'text' as const,\n text: safeStringify(await response.json())\n }\n ]\n };\n case 'text/plain':\n return {\n content: [\n { type: 'text' as const, text: await response.text() }\n ]\n };\n case 'application/octet-stream':\n return {\n content: [\n {\n type: 'resource' as const,\n resource: {\n uri: response.url,\n blob: Buffer.from(\n await (await response.blob()).arrayBuffer()\n ).toString('base64')\n }\n }\n ]\n };\n case 'text/event-stream':\n return {\n content: [\n { type: 'text' as const, text: await response.text() }\n ]\n };\n default:\n return {\n content: [\n { type: 'text' as const, text: await response.text() }\n ]\n };\n }\n }\n });\n });\n });\n });\n\n return mcpServer;\n}\n","import { AnySchemaValidator } from '@forklaunch/validator';\nimport { ForklaunchRouter } from '../types/router.types';\n\nexport function unpackRouters<SV extends AnySchemaValidator>(\n routers: ForklaunchRouter<SV>[],\n recursiveBasePath: string[] = []\n): {\n fullPath: string;\n router: ForklaunchRouter<SV>;\n}[] {\n return routers.reduce<\n {\n fullPath: string;\n router: ForklaunchRouter<SV>;\n }[]\n >((acc, router) => {\n const fullPath = [...recursiveBasePath, router.basePath].join('');\n acc.push({\n fullPath,\n router\n });\n acc.push(\n ...unpackRouters<SV>(router.routers, [\n ...recursiveBasePath,\n router.basePath\n ])\n );\n return acc;\n }, []);\n}\n","import {\n AnySchemaValidator,\n prettyPrintParseErrors,\n SchemaValidator\n} from '@forklaunch/validator';\nimport { ParsedQs } from 'qs';\nimport { hasSend } from '../../guards/hasSend';\nimport { isResponseCompiledSchema } from '../../guards/isResponseCompiledSchema';\nimport {\n ForklaunchNextFunction,\n ForklaunchRequest,\n ForklaunchResHeaders,\n ForklaunchResponse,\n VersionedRequests\n} from '../../types/apiDefinition.types';\nimport { ParamsDictionary } from '../../types/contractDetails.types';\n\n/**\n * Middleware to parse and validate the response according to the provided schema.\n *\n * This function validates the response against a schema provided by the request's schema validator.\n * If the response does not conform to the schema, the behavior is determined by the `responseValidation`\n * option in `req.contractDetails.options`:\n * - `'error'` (default): Calls `next` with an error.\n * - `'warning'`: Logs a warning to the console.\n * - `'none'`: Silently continues without action.\n *\n * @template SV - The type of the schema validator used in the request.\n * @template P - The type of the parameters dictionary used in the request.\n * @template ResBodyMap - A record type mapping status codes to response body types.\n * @template ReqBody - The type of the request body.\n * @template ReqQuery - The type of the parsed query string.\n * @template ReqHeaders - The type of the request headers.\n * @template ResHeaders - The type of the response headers, extended from `ForklaunchResHeaders`.\n * @template LocalsObj - The type of the locals object in the response.\n *\n * @param {ForklaunchRequest<SV, P, ReqBody, ReqQuery, ReqHeaders>} req - The request object, containing the schema validator and other request data.\n * @param {ForklaunchResponse<ResBodyMap, ForklaunchResHeaders & ResHeaders, LocalsObj>} res - The response object, including headers and body data.\n * @param {ForklaunchNextFunction} [next] - The next middleware function to be called. If not provided, the function will return after processing.\n *\n * @returns {void} This function does not return a value.\n */\nexport function parse<\n SV extends AnySchemaValidator,\n P extends ParamsDictionary,\n ResBodyMap extends Record<number, unknown>,\n ReqBody extends Record<string, unknown>,\n ReqQuery extends ParsedQs,\n ReqHeaders extends Record<string, string>,\n ResHeaders extends Record<string, unknown>,\n LocalsObj extends Record<string, unknown>,\n VersionedReqs extends VersionedRequests,\n SessionSchema extends Record<string, unknown>\n>(\n req: ForklaunchRequest<\n SV,\n P,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n Extract<keyof VersionedReqs, string>,\n SessionSchema\n >,\n res: ForklaunchResponse<\n unknown,\n ResBodyMap,\n ForklaunchResHeaders & ResHeaders,\n LocalsObj,\n Extract<keyof VersionedReqs, string>\n >,\n next?: ForklaunchNextFunction\n) {\n let headers;\n let responses;\n\n const globalOptions = req._globalOptions?.();\n const collapsedOptions =\n req.contractDetails.options?.responseValidation ??\n (globalOptions?.validation === false\n ? 'none'\n : globalOptions?.validation?.response);\n\n if (collapsedOptions === 'none') {\n next?.();\n return;\n }\n\n const responseSchemas = res.responseSchemas;\n const schemaValidator = req.schemaValidator as SchemaValidator;\n\n if (!isResponseCompiledSchema(responseSchemas)) {\n const parsedVersions = req._parsedVersions;\n if (typeof parsedVersions === 'number') {\n throw new Error('Request failed to parse given version map');\n }\n const mappedHeaderSchemas = parsedVersions.map(\n (version) => responseSchemas[version].headers\n );\n const mappedResponseSchemas = parsedVersions.map(\n (version) => responseSchemas[version].responses\n );\n\n const collapsedResponseSchemas = mappedResponseSchemas.reduce<\n Record<number, unknown[]>\n >((acc, responseSchema) => {\n Object.entries(responseSchema).forEach(([status, schema]) => {\n if (!acc[Number(status)]) {\n acc[Number(status)] = [];\n }\n acc[Number(status)].push(schema);\n });\n return acc;\n }, {});\n\n headers = schemaValidator.union(mappedHeaderSchemas);\n responses = Object.fromEntries(\n Object.entries(collapsedResponseSchemas).map(([status, schemas]) => [\n status,\n schemaValidator.union(schemas)\n ])\n );\n } else {\n headers = responseSchemas.headers;\n responses = responseSchemas.responses;\n }\n\n const statusCode = Number(res.statusCode);\n\n const parsedResponse = schemaValidator.parse(\n [400, 401, 404, 403, 500].includes(statusCode)\n ? schemaValidator.union([schemaValidator.string, responses?.[statusCode]])\n : responses?.[statusCode],\n res.bodyData\n );\n\n const parsedHeaders = schemaValidator.parse(\n headers ?? schemaValidator.unknown,\n res.getHeaders()\n );\n const parseErrors: string[] = [];\n if (!parsedHeaders.ok) {\n const headerErrors = prettyPrintParseErrors(parsedHeaders.errors, 'Header');\n if (headerErrors) {\n parseErrors.push(headerErrors);\n }\n }\n\n if (!parsedResponse.ok) {\n const responseErrors = prettyPrintParseErrors(\n parsedResponse.errors,\n 'Response'\n );\n if (responseErrors) {\n parseErrors.push(responseErrors);\n }\n }\n\n if (parseErrors.length > 0) {\n switch (req.contractDetails.options?.responseValidation) {\n default:\n case undefined:\n case 'error':\n res.type('text/plain');\n res.status(500);\n if (hasSend(res)) {\n res.send(\n `Invalid response:\\n${parseErrors.join(\n '\\n\\n'\n )}\\n\\nCorrelation id: ${\n req.context.correlationId ?? 'No correlation ID'\n }`\n );\n } else {\n next?.(new Error('Response is not sendable.'));\n }\n return;\n case 'warning':\n req.openTelemetryCollector?.warn(\n `Invalid response:\\n${parseErrors.join('\\n\\n')}`\n );\n break;\n case 'none':\n break;\n }\n }\n next?.();\n}\n","import { ResponseCompiledSchema } from '../types/contractDetails.types';\n\nexport function isResponseCompiledSchema(\n schema: unknown\n): schema is ResponseCompiledSchema {\n return typeof schema === 'object' && schema !== null && 'responses' in schema;\n}\n","import { AnySchemaValidator } from '@forklaunch/validator';\nimport { ParsedQs } from 'qs';\nimport { parse } from './parse.middleware';\n\nimport {\n isAsyncGenerator,\n isNever,\n isNodeJsWriteableStream,\n isRecord,\n readableStreamToAsyncIterable,\n safeStringify\n} from '@forklaunch/common';\nimport { Readable, Transform } from 'stream';\nimport { discriminateResponseBodies } from '../../router/discriminateBody';\nimport { recordMetric } from '../../telemetry/recordMetric';\nimport {\n ForklaunchRequest,\n ForklaunchResHeaders,\n ForklaunchResponse,\n ForklaunchSendableData,\n ForklaunchStatusResponse,\n VersionedRequests\n} from '../../types/apiDefinition.types';\nimport { ParamsDictionary } from '../../types/contractDetails.types';\n\n/**\n * Enhances the Express-like `send` method with additional logic for response handling and validation.\n *\n * This function intercepts the `send` method to provide custom behavior, including response validation\n * through the `parseResponse` middleware. If the response status is 404, it sends a \"Not Found\" message.\n * If the response validation fails, it sends a parsing error message. Otherwise, it calls the original `send`\n * method with the provided data.\n *\n * @template SV - The type of the schema validator used in the request.\n * @template P - The type of the parameters dictionary used in the request.\n * @template ResBodyMap - A record type mapping status codes to response body types.\n * @template ReqBody - The type of the request body.\n * @template ReqQuery - The type of the parsed query string.\n * @template ReqHeaders - The type of the request headers.\n * @template ResHeaders - The type of the response headers, extended from `ForklaunchResHeaders`.\n * @template LocalsObj - The type of the locals object in the response.\n *\n * @param {unknown} instance - The context (typically `this`) in which the original `send` method is called.\n * @param {ForklaunchRequest<SV, P, ReqBody, ReqQuery, ReqHeaders>} req - The request object, containing the schema validator and other request data.\n * @param {ForklaunchResponse<ResBodyMap, ForklaunchResHeaders & ResHeaders, LocalsObj>} res - The response object, including headers and body data.\n * @param {Function} originalSend - The original `send` method from the response object, to be called after custom logic.\n * @param {string | ArrayBuffer | ArrayBufferView | NodeJS.ReadableStream | null | undefined} data - The data to be sent as the response body.\n * @param {boolean} shouldEnrich - A flag indicating whether the response should be sent immediately.\n *\n * @returns {unknown} The return value of the original `send` method, typically the response itself.\n */\nexport function enrichExpressLikeSend<\n SV extends AnySchemaValidator,\n P extends ParamsDictionary,\n ResBodyMap extends Record<number, unknown>,\n ReqBody extends Record<string, unknown>,\n ReqQuery extends ParsedQs,\n ReqHeaders extends Record<string, string>,\n ResHeaders extends Record<string, unknown>,\n LocalsObj extends Record<string, unknown>,\n VersionedReqs extends VersionedRequests,\n SessionSchema extends Record<string, unknown>\n>(\n instance: unknown,\n req: ForklaunchRequest<\n SV,\n P,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n Extract<keyof VersionedReqs, string>,\n SessionSchema\n >,\n res: ForklaunchResponse<\n unknown,\n ResBodyMap,\n ForklaunchResHeaders & ResHeaders,\n LocalsObj,\n Extract<keyof VersionedReqs, string>\n >,\n originalOperation:\n | ForklaunchStatusResponse<ForklaunchSendableData>['json']\n | ForklaunchStatusResponse<ForklaunchSendableData>['jsonp'],\n originalSend: ForklaunchStatusResponse<ForklaunchSendableData>['send'],\n data:\n | ForklaunchSendableData\n | File\n | Blob\n | AsyncGenerator<Record<string, unknown>>\n | null\n | undefined,\n shouldEnrich: boolean\n) {\n let errorSent = false;\n\n if (data == null) {\n originalSend.call(instance, data);\n return;\n }\n\n let responses;\n if (\n req.contractDetails.responses == null &&\n (req.contractDetails.versions == null ||\n Object.values(req.contractDetails.versions).some(\n (version) => version?.responses == null\n ))\n ) {\n throw new Error('Responses schema definitions are required');\n } else {\n if (req.contractDetails.responses != null) {\n responses = req.contractDetails.responses;\n } else {\n responses = req.contractDetails.versions[req.version].responses;\n }\n }\n\n const responseBodies = discriminateResponseBodies(\n req.schemaValidator,\n responses\n );\n\n if (\n responseBodies != null &&\n responseBodies[Number(res.statusCode)] != null\n ) {\n res.type(responseBodies[Number(res.statusCode)].contentType);\n }\n\n if (data instanceof File || data instanceof Blob) {\n if (data instanceof File) {\n res.setHeader(\n 'Content-Disposition',\n `attachment; filename=\"${data.name}\"` as ResHeaders['Content-Disposition']\n );\n }\n if (isNodeJsWriteableStream(res)) {\n // No cast: isNodeJsWriteableStream is a type predicate\n // (`value is NodeJS.WritableStream`), so `res` is already narrowed here.\n Readable.from(readableStreamToAsyncIterable(data.stream())).pipe(res);\n } else {\n res.type('text/plain');\n res.status(500);\n originalSend.call(instance, 'Not a NodeJS WritableStream');\n errorSent = true;\n }\n } else if (isAsyncGenerator(data)) {\n let firstPass = true;\n const transformer = new Transform({\n objectMode: true,\n transform(\n chunk: Record<string, unknown>,\n _encoding: unknown,\n callback: (error?: Error | null, data?: unknown) => void\n ) {\n if (firstPass) {\n res.bodyData = chunk;\n parse(req, res, (err?: unknown) => {\n if (err) {\n let errorString = (err as Error).message;\n if (res.locals.errorMessage) {\n errorString += `\\n------------------\\n${res.locals.errorMessage}`;\n }\n req.openTelemetryCollector?.error(errorString);\n res.type('text/plain');\n res.status(500);\n originalSend.call(instance, errorString);\n errorSent = true;\n callback(new Error(errorString));\n } else {\n let data = '';\n for (const [key, value] of Object.entries(chunk)) {\n data += `${key}: ${typeof value === 'string' ? value : safeStringify(value)}\\n`;\n }\n data += '\\n';\n callback(null, data);\n }\n });\n firstPass = false;\n } else if (!errorSent) {\n let data = '';\n for (const [key, value] of Object.entries(chunk)) {\n data += `${key}: ${typeof value === 'string' ? value : safeStringify(value)}\\n`;\n }\n data += '\\n';\n callback(null, data);\n }\n }\n });\n if (isNodeJsWriteableStream(res)) {\n Readable.from(data).pipe(transformer).pipe(res);\n } else {\n res.type('text/plain');\n res.status(500);\n originalSend.call(instance, 'Not a NodeJS WritableStream');\n errorSent = true;\n }\n } else {\n const parserType = responseBodies?.[Number(res.statusCode)]?.parserType;\n\n res.bodyData = data;\n if (isRecord(data)) {\n switch (parserType) {\n case 'json':\n res.bodyData = 'json' in data ? data.json : data;\n break;\n case 'text':\n res.bodyData = 'text' in data ? data.text : data;\n break;\n case 'file':\n res.bodyData = 'file' in data ? data.file : data;\n break;\n case 'serverSentEvent':\n res.bodyData = 'event' in data ? data.event : data;\n break;\n case 'multipart':\n res.bodyData = 'multipart' in data ? data.multipart : data;\n break;\n case undefined:\n res.bodyData = data;\n break;\n default:\n isNever(parserType);\n res.bodyData = data;\n break;\n }\n }\n\n parse(req, res, (err?: unknown) => {\n if (err) {\n let errorString = (err as Error).message;\n if (res.locals.errorMessage) {\n errorString += `\\n------------------\\n${res.locals.errorMessage}`;\n }\n req.openTelemetryCollector?.error(errorString);\n res.type('text/plain');\n res.status(500);\n originalSend.call(instance, errorString);\n errorSent = true;\n } else {\n if (typeof data === 'string') {\n res.type('text/plain');\n originalSend.call(instance, data);\n } else if (!(data instanceof File)) {\n res.sent = true;\n originalOperation.call(instance, data);\n }\n }\n });\n }\n\n if (shouldEnrich) {\n recordMetric<\n SV,\n P,\n ReqBody,\n ReqQuery,\n ResBodyMap,\n ReqHeaders,\n ForklaunchResHeaders & ResHeaders,\n LocalsObj,\n VersionedReqs,\n SessionSchema\n >(req, res);\n }\n}\n","import { getEnvVar } from '@forklaunch/common';\nimport { AnySchemaValidator } from '@forklaunch/validator';\nimport {\n ATTR_HTTP_REQUEST_METHOD,\n ATTR_HTTP_RESPONSE_STATUS_CODE,\n ATTR_HTTP_ROUTE,\n ATTR_SERVICE_NAME\n} from '@opentelemetry/semantic-conventions';\nimport { ParsedQs } from 'qs';\nimport {\n ForklaunchRequest,\n ForklaunchResponse,\n ParamsDictionary,\n VersionedRequests\n} from '..';\nimport { ATTR_API_NAME, ATTR_APPLICATION_ID } from './constants';\nimport {\n httpErrorsTotalCounter,\n httpRequestDurationMsHistogram,\n httpRequestsTotalCounter\n} from './openTelemetryCollector';\n\nexport function recordMetric<\n SV extends AnySchemaValidator,\n P extends ParamsDictionary,\n ReqBody extends Record<string, unknown>,\n ReqQuery extends ParsedQs,\n ResBodyMap extends Record<string, unknown>,\n ReqHeaders extends Record<string, string>,\n ResHeaders extends Record<string, unknown>,\n LocalsObj extends Record<string, unknown>,\n VersionedReqs extends VersionedRequests,\n SessionSchema extends Record<string, unknown>\n>(\n req: ForklaunchRequest<\n SV,\n P,\n ReqBody,\n ReqQuery,\n ReqHeaders,\n Extract<keyof VersionedReqs, string>,\n SessionSchema\n >,\n res: ForklaunchResponse<\n unknown,\n ResBodyMap,\n ResHeaders,\n LocalsObj,\n Extract<keyof VersionedReqs, string>\n >\n) {\n if (res.metricRecorded) {\n return;\n }\n\n const serviceName = getEnvVar('OTEL_SERVICE_NAME') || 'unknown';\n const attrs = {\n [ATTR_SERVICE_NAME]: serviceName,\n [ATTR_APPLICATION_ID]: getEnvVar('OTEL_APPLICATION_ID'),\n [ATTR_API_NAME]: req.contractDetails?.name,\n [ATTR_HTTP_REQUEST_METHOD]: req.method,\n [ATTR_HTTP_ROUTE]: req.originalPath,\n [ATTR_HTTP_RESPONSE_STATUS_CODE]: Number(res.statusCode) || 0\n };\n\n httpRequestsTotalCounter.add(1, attrs);\n\n const durationMs =\n req.context?.requestStartTime != null\n ? Date.now() - req.context.requestStartTime\n : 0;\n httpRequestDurationMsHistogram.record(durationMs, attrs);\n\n if (Number(res.statusCode) >= 400) {\n httpErrorsTotalCounter.add(1, attrs);\n }\n\n res.metricRecorded = true;\n}\n","import { openApiCompliantPath } from '@forklaunch/common';\nimport {\n AnySchemaValidator,\n IdiomaticSchema,\n SchemaValidator\n} from '@forklaunch/validator';\nimport {\n ContentObject,\n OpenAPIObject,\n OperationObject,\n PathObject,\n ResponseObject,\n ResponsesObject,\n SecuritySchemeObject,\n TagObject\n} from 'openapi3-ts/oas31';\nimport HTTPStatuses from '../httpStatusCodes';\nimport {\n discriminateBody,\n discriminateResponseBodies\n} from '../router/discriminateBody';\nimport { unpackRouters } from '../router/unpackRouters';\nimport {\n Body,\n HeadersObject,\n Method,\n ParamsObject,\n QueryObject,\n ResponseBody,\n SchemaAuthMethods,\n SessionObject,\n VersionSchema\n} from '../types/contractDetails.types';\nimport { ExpressLikeApplicationOptions } from '../types/expressLikeOptions';\nimport { ForklaunchRouter } from '../types/router.types';\n\nexport const OPENAPI_DEFAULT_VERSION = Symbol('default');\n\n/**\n * Capitalizes the first letter of a string.\n *\n * @param {string} str - The string to transform.\n * @returns {string} - The transformed string with the first letter capitalized.\n */\nfunction toUpperCase(str: string) {\n return str.charAt(0).toUpperCase() + str.slice(1);\n}\n\n/**\n * Transforms a base path by ensuring it starts with a slash and capitalizing the first letter.\n *\n * @param {string} basePath - The base path to transform.\n * @returns {string} - The transformed base path.\n */\nfunction transformBasePath(basePath: string) {\n if (basePath.startsWith('/')) {\n return basePath.slice(1);\n }\n return `/${basePath}`;\n}\n\n/**\n * Creates a Swagger document.\n *\n * @param {string | number} port - The port on which the server is running.\n * @param {TagObject[]} tags - The tags for the Swagger document.\n * @param {PathObject} paths - The paths for the Swagger document.\n * @returns {OpenAPIObject} - The Swagger document.\n */\nfunction generateOpenApiDocument<SV extends AnySchemaValidator>(\n serverUrls: string[],\n serverDescriptions: string[],\n versionedTags: Record<string | symbol, TagObject[]>,\n versionedPaths: Record<string | symbol, PathObject>,\n versionedSecuritySchemes: Record<\n string | symbol,\n Record<string, SecuritySchemeObject>\n >,\n appOptions?: ExpressLikeApplicationOptions<SV, SessionObject<SV>>['openapi']\n): Record<string | symbol, OpenAPIObject> {\n const { title, description, contact } =\n appOptions !== false ? (appOptions ?? {}) : {};\n return {\n [OPENAPI_DEFAULT_VERSION]: {\n openapi: '3.1.0',\n info: {\n title: title || process.env.API_TITLE || 'API Definition',\n version: 'latest',\n description,\n contact\n },\n components: {\n securitySchemes: versionedSecuritySchemes[OPENAPI_DEFAULT_VERSION]\n },\n tags: versionedTags[OPENAPI_DEFAULT_VERSION],\n servers: [\n ...serverUrls.map((url, index) => ({\n url,\n description: serverDescriptions?.[index]\n }))\n ],\n paths: versionedPaths[OPENAPI_DEFAULT_VERSION]\n },\n ...Object.fromEntries(\n Object.entries(versionedPaths).map(([version, paths]) => [\n version,\n {\n openapi: '3.1.0',\n info: {\n title: title || process.env.API_TITLE || 'API Definition',\n version,\n description,\n contact\n },\n components: {\n securitySchemes: versionedSecuritySchemes[version]\n },\n tags: versionedTags[version],\n servers: [\n ...serverUrls.map((url, index) => ({\n url,\n description: serverDescriptions?.[index]\n }))\n ],\n paths\n }\n ])\n )\n };\n}\n\n/**\n * Resolves the content object for a given schema.\n *\n * @template SV - A type that extends AnySchemaValidator.\n * @param {SV} schemaValidator - The schema validator.\n * @param {IdiomaticSchema<SV>} body - The schema body.\n * @returns {ContentObject} - The resolved content object.\n */\nfunction contentResolver<SV extends AnySchemaValidator>(\n schemaValidator: SV,\n body: IdiomaticSchema<SV>,\n contentType?: string\n): ContentObject {\n const bodySpec = (schemaValidator as SchemaValidator).openapi(body);\n return contentType != null\n ? {\n [contentType]: {\n schema: bodySpec\n }\n }\n : body === schemaValidator.string\n ? {\n 'text/plain': {\n schema: bodySpec\n }\n }\n : {\n 'application/json': {\n schema: bodySpec\n }\n };\n}\n\nfunction generateOperationObject<SV extends AnySchemaValidator>(\n schemaValidator: SV,\n path: string,\n method: Method,\n controllerName: string,\n sdkPaths: Record<string, string>,\n securitySchemes: Record<string, SecuritySchemeObject>,\n name: string,\n summary: string,\n responses: Record<number, ResponseBody<SV>>,\n params?: ParamsObject<SV>,\n responseHeaders?: HeadersObject<SV>,\n requestHeaders?: HeadersObject<SV>,\n query?: QueryObject<SV>,\n body?: Body<SV>,\n auth?: SchemaAuthMethods<\n SV,\n ParamsObject<SV>,\n Body<SV>,\n QueryObject<SV>,\n HeadersObject<SV>,\n VersionSchema<SV, Method>,\n unknown\n >\n) {\n const typedSchemaValidator = schemaValidator as SchemaValidator;\n\n const coercedResponses: ResponsesObject = {};\n\n const discriminatedResponseBodiesResult = discriminateResponseBodies(\n schemaValidator,\n responses\n );\n\n for (const key in discriminatedResponseBodiesResult) {\n coercedResponses[key] = {\n description: HTTPStatuses[key],\n content: contentResolver(\n schemaValidator,\n discriminatedResponseBodiesResult[key].schema,\n discriminatedResponseBodiesResult[key].contentType\n ),\n headers: responseHeaders\n ? Object.fromEntries(\n Object.entries(responseHeaders).map(([key, value]) => [\n key,\n {\n schema: typedSchemaValidator.openapi(value)\n }\n ])\n )\n : undefined\n } satisfies ResponseObject;\n }\n\n const commonErrors = [400, 404, 500];\n for (const error of commonErrors) {\n if (!(error in responses)) {\n coercedResponses[error] = {\n description: HTTPStatuses[error],\n content: contentResolver(schemaValidator, schemaValidator.string)\n };\n }\n }\n\n const operationObject: OperationObject = {\n tags: [controllerName],\n summary: `${name}: ${summary}`,\n parameters: [],\n responses: coercedResponses,\n operationId: sdkPaths[[method, path].join('.')]\n };\n\n if (params) {\n for (const key in params) {\n operationObject.parameters?.push({\n name: key,\n in: 'path',\n schema: typedSchemaValidator.openapi(params[key])\n });\n }\n }\n\n const discriminatedBodyResult = body\n ? discriminateBody(schemaValidator, body)\n : null;\n\n if (discriminatedBodyResult) {\n operationObject.requestBody = {\n required: true,\n content: contentResolver(\n schemaValidator,\n discriminatedBodyResult.schema,\n discriminatedBodyResult.contentType\n )\n };\n }\n\n if (requestHeaders) {\n for (const key in requestHeaders) {\n operationObject.parameters?.push({\n name: key,\n in: 'header',\n schema: typedSchemaValidator.openapi(requestHeaders[key])\n });\n }\n }\n\n if (query) {\n for (const key in query) {\n operationObject.parameters?.push({\n name: key,\n in: 'query',\n schema: typedSchemaValidator.openapi(query[key])\n });\n }\n }\n\n if (auth) {\n coercedResponses[401] = {\n description: HTTPStatuses[401],\n content: contentResolver(schemaValidator, schemaValidator.string)\n };\n\n coercedResponses[403] = {\n description: HTTPStatuses[403],\n content: contentResolver(schemaValidator, schemaValidator.string)\n };\n\n if ('basic' in auth) {\n operationObject.security = [\n {\n basic: Array.from(\n 'allowedPermissions' in auth &&\n auth.allowedPermissions instanceof Set\n ? auth.allowedPermissions.values()\n : []\n )\n }\n ];\n\n securitySchemes['basic'] = {\n type: 'http',\n scheme: 'basic'\n };\n } else if (auth) {\n operationObject.security = [\n {\n [auth.headerName !== 'Authorization' ? 'bearer' : 'apiKey']:\n Array.from(\n 'allowedPermissions' in auth &&\n auth.allowedPermissions instanceof Set\n ? auth.allowedPermissions.values()\n : []\n )\n }\n ];\n\n if (auth.headerName && auth.headerName !== 'Authorization') {\n securitySchemes[auth.headerName] = {\n type: 'apiKey',\n in: 'header',\n name: auth.headerName\n };\n } else {\n securitySchemes['Authorization'] = {\n type: 'http',\n scheme: 'bearer',\n bearerFormat: 'JWT'\n };\n }\n }\n }\n\n return operationObject;\n}\n\n/**\n * Generates a Swagger document from given routers.\n *\n * @template SV - A type that extends AnySchemaValidator.\n * @param {SV} schemaValidator - The schema validator.\n * @param {string | number} port - The port on which the server is running.\n * @param {ForklaunchRouter<SV>[]} routers - The routers to include in the Swagger document.\n * @returns {OpenAPIObject} - The generated Swagger document.\n */\nexport function generateOpenApiSpecs<SV extends AnySchemaValidator>(\n schemaValidator: SV,\n serverUrls: string[],\n serverDescriptions: string[],\n application: ForklaunchRouter<SV>,\n appOptions?: ExpressLikeApplicationOptions<SV, SessionObject<SV>>['openapi']\n): Record<string | symbol, OpenAPIObject> {\n const versionedPaths: Record<string | symbol, PathObject> = {\n [OPENAPI_DEFAULT_VERSION]: {}\n };\n const versionedTags: Record<string | symbol, TagObject[]> = {\n [OPENAPI_DEFAULT_VERSION]: []\n };\n const versionedSecuritySchemes: Record<\n string | symbol,\n Record<string, SecuritySchemeObject>\n > = {\n [OPENAPI_DEFAULT_VERSION]: {}\n };\n\n [\n {\n fullPath: application.basePath === '/' ? '' : application.basePath,\n router: application\n },\n ...unpackRouters<SV>(application.routers, [\n application.basePath === '/' ? '' : application.basePath\n ])\n ].forEach(({ fullPath, router }) => {\n const controllerName = transformBasePath(fullPath);\n router.routes.forEach((route) => {\n const openApiPath = openApiCompliantPath(\n `${fullPath}${route.path === '/' ? '' : route.path}`\n );\n\n const { name, summary, params, versions, auth, options } =\n route.contractDetails;\n\n if (!(\n options?.openapi ??\n router.routerOptions?.openapi ??\n appOptions !== false\n )) {\n return;\n }\n\n if (versions) {\n for (const version of Object.keys(versions)) {\n if (!versionedPaths[version]) {\n versionedPaths[version] = {};\n }\n if (!versionedPaths[version][openApiPath]) {\n versionedPaths[version][openApiPath] = {};\n }\n if (!versionedTags[version]) {\n versionedTags[version] = [];\n }\n if (\n !versionedTags[version].find((tag) => tag.name === controllerName)\n ) {\n versionedTags[version].push({\n name: controllerName,\n description: `${toUpperCase(controllerName)} Operations`\n });\n }\n if (!versionedSecuritySchemes[version]) {\n versionedSecuritySchemes[version] = {};\n }\n\n const { query, requestHeaders, body, responses, responseHeaders } =\n versions[version];\n\n const operationObject = generateOperationObject<SV>(\n schemaValidator,\n route.path,\n route.method,\n controllerName,\n router.sdkPaths,\n versionedSecuritySchemes[version],\n name,\n summary,\n responses,\n params,\n responseHeaders,\n requestHeaders,\n query,\n body,\n auth\n );\n\n if (route.method !== 'middleware') {\n versionedPaths[version][openApiPath][route.method] =\n operationObject;\n }\n }\n } else {\n if (!versionedPaths[OPENAPI_DEFAULT_VERSION]) {\n versionedPaths[OPENAPI_DEFAULT_VERSION] = {};\n }\n if (!versionedPaths[OPENAPI_DEFAULT_VERSION][openApiPath]) {\n versionedPaths[OPENAPI_DEFAULT_VERSION][openApiPath] = {};\n }\n if (!versionedTags[OPENAPI_DEFAULT_VERSION]) {\n versionedTags[OPENAPI_DEFAULT_VERSION] = [];\n }\n if (\n !versionedTags[OPENAPI_DEFAULT_VERSION].find(\n (tag) => tag.name === controllerName\n )\n ) {\n versionedTags[OPENAPI_DEFAULT_VERSION].push({\n name: controllerName,\n description: `${toUpperCase(controllerName)} Operations`\n });\n }\n if (!versionedSecuritySchemes[OPENAPI_DEFAULT_VERSION]) {\n versionedSecuritySchemes[OPENAPI_DEFAULT_VERSION] = {};\n }\n\n const { query, requestHeaders, body, responses, responseHeaders } =\n route.contractDetails;\n\n const operationObject = generateOperationObject<SV>(\n schemaValidator,\n route.path,\n route.method,\n controllerName,\n router.sdkPaths,\n versionedSecuritySchemes[OPENAPI_DEFAULT_VERSION],\n name,\n summary,\n responses,\n params,\n responseHeaders,\n requestHeaders,\n query,\n body,\n auth\n );\n\n if (route.method !== 'middleware') {\n versionedPaths[OPENAPI_DEFAULT_VERSION][openApiPath][route.method] =\n operationObject;\n }\n }\n });\n });\n\n return generateOpenApiDocument(\n serverUrls,\n serverDescriptions,\n versionedTags,\n versionedPaths,\n versionedSecuritySchemes,\n appOptions\n );\n}\n","import { LevelWithSilentOrString } from 'pino';\nimport { TelemetryOptions } from '../types/openTelemetryCollector.types';\n\nexport function evaluateTelemetryOptions(telemetryOptions: TelemetryOptions): {\n enabled: {\n metrics?: boolean;\n tracing?: boolean;\n logging?: boolean;\n };\n level: LevelWithSilentOrString;\n} {\n return {\n enabled:\n typeof telemetryOptions.enabled === 'boolean'\n ? {\n metrics: telemetryOptions.enabled,\n tracing: telemetryOptions.enabled,\n logging: telemetryOptions.enabled\n }\n : {\n metrics: telemetryOptions.enabled.metrics,\n tracing: telemetryOptions.enabled.tracing,\n logging: telemetryOptions.enabled.logging\n },\n level: telemetryOptions.level\n };\n}\n","import { MetricsDefinition } from '../types/openTelemetryCollector.types';\n\nexport function metricsDefinitions<T extends MetricsDefinition>(metrics: T) {\n return metrics;\n}\n","import { TtlCache } from '../../cache/interfaces/ttlCache.interface';\n\n/**\n * Configuration for rate limiting with separate read/write limits.\n */\nexport type RateLimitConfig = {\n /** Max requests per window for GET/HEAD/OPTIONS */\n read: number;\n /** Max requests per window for POST/PUT/PATCH/DELETE */\n write: number;\n /** Window duration in milliseconds */\n windowMs: number;\n};\n\n/**\n * Result of a rate limit check.\n */\nexport type RateLimitResult = {\n /** Whether the request is allowed */\n allowed: boolean;\n /** Number of remaining requests in the current window */\n remaining: number;\n /** Unix timestamp (ms) when the current window resets */\n resetAt: number;\n};\n\ntype RateLimitCounter = {\n count: number;\n resetAt: number;\n};\n\nconst READ_METHODS = new Set(['GET', 'HEAD', 'OPTIONS']);\n\n/**\n * Rate limiter backed by a TtlCache.\n *\n * Uses a sliding-window counter pattern: each unique key maps to a\n * {@link RateLimitCounter} stored in the cache with a TTL equal to the\n * configured window duration.\n */\nexport class RateLimiter {\n constructor(private cache: TtlCache) {}\n\n /**\n * Check whether the given key is within its rate limit.\n *\n * The counter is read from the cache, incremented, and written back.\n * If the cache is unreachable the limiter **fails open** (allows the\n * request) so that a cache outage does not take down the service.\n *\n * @param key - The rate limit key (see {@link RateLimiter.buildKey}).\n * @param limit - Maximum number of requests allowed in the window.\n * @param windowMs - Window duration in milliseconds.\n */\n async check(\n key: string,\n limit: number,\n windowMs: number\n ): Promise<RateLimitResult> {\n try {\n const now = Date.now();\n let counter: RateLimitCounter;\n\n try {\n const record = await this.cache.readRecord<RateLimitCounter>(key);\n counter = record.value;\n\n // If the stored window has expired, start a new one\n if (now >= counter.resetAt) {\n counter = { count: 0, resetAt: now + windowMs };\n }\n } catch {\n // Key does not exist yet – start a fresh window\n counter = { count: 0, resetAt: now + windowMs };\n }\n\n counter.count += 1;\n\n const ttl = Math.max(counter.resetAt - now, 1);\n\n await this.cache.putRecord<RateLimitCounter>({\n key,\n value: counter,\n ttlMilliseconds: ttl\n });\n\n const allowed = counter.count <= limit;\n const remaining = Math.max(limit - counter.count, 0);\n\n return { allowed, remaining, resetAt: counter.resetAt };\n } catch {\n // Fail open – cache errors should not block requests\n console.warn(`[RateLimiter] Cache error for key \"${key}\". Failing open.`);\n return { allowed: true, remaining: limit, resetAt: 0 };\n }\n }\n\n /**\n * Build a rate limit key from request context parts.\n *\n * Format: `ratelimit:{tenantId}:{route}:{userId}:{operationType}`\n *\n * When `tenantId` or `userId` is `null`, the placeholder `\"anon\"` is used.\n */\n static buildKey(parts: {\n tenantId: string | null;\n route: string;\n userId: string | null;\n operationType: 'read' | 'write';\n }): string {\n const tenant = parts.tenantId ?? 'anon';\n const user = parts.userId ?? 'anon';\n return `ratelimit:${tenant}:${parts.route}:${user}:${parts.operationType}`;\n }\n\n /**\n * Determine whether an HTTP method is a read or write operation.\n *\n * GET, HEAD, and OPTIONS are reads; everything else is a write.\n */\n static operationType(method: string): 'read' | 'write' {\n return READ_METHODS.has(method.toUpperCase()) ? 'read' : 'write';\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;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;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;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,eAAAA;AAAA,EAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACAA,kBAA4C;AAiBrC,SAAS,KAQd,aAA0B;AAC1B,SAAO,CACL,KACA,KAOA,SACG;AACH,QAAI,IAAI,WAAW,WAAW;AAC5B,UAAI,OAAO;AAAA,IACb;AACA,QAAI,CAAC,IAAI,WAAW;AAClB,UAAI,YAAY,CAAC,QAAgB;AAC/B,eAAO,IAAI,WAAW,EAAE,GAAG;AAAA,MAC7B;AAAA,IACF;AACA,oBAAAC,SAAe,WAAW;AAAA,MACxB;AAAA,MACA;AAAA,MACA,SAAS,MAAM;AAAA,MAAC;AAAA,IAClB;AAAA,EACF;AACF;;;AChDA,IAAAC,kBAWO;;;ACdA,SAAS,oBAAoB,uBAAgC;AAClE,MACE,OAAO,0BAA0B,YACjC,0BAA0B,MAC1B;AACA,WAAO;AAAA,EACT;AAEA,QAAM,wBACJ,wBAAwB,yBACxB,sBAAsB,8BAA8B,OACpD,sBAAsB,mBAAmB,OAAO;AAElD,QAAM,0BACJ,0BAA0B,yBAC1B,sBAAsB,gCAAgC,OACtD,sBAAsB,qBAAqB,OAAO;AAEpD,SAAO,yBAAyB;AAClC;;;ACnBO,SAAS,cAAc,gBAAkC;AAC9D,MAAI,OAAO,mBAAmB,YAAY,mBAAmB,MAAM;AACjE,WAAO;AAAA,EACT;AAEA,QAAM,kBACJ,kBAAkB,kBAClB,eAAe,wBAAwB,OACvC,eAAe,aAAa,OAAO;AAErC,QAAM,oBACJ,oBAAoB,kBACpB,eAAe,0BAA0B,OACzC,eAAe,eAAe,OAAO;AAEvC,SAAO,mBAAmB;AAC5B;;;AChBO,SAAS,eAAe,uBAAgC;AAC7D,SACE,OAAO,0BAA0B,YACjC,0BAA0B,QAC1B,mBAAmB,yBACnB,sBAAsB,iBAAiB;AAE3C;;;ACaO,SAAS,mBACd,uBAC+C;AAC/C,SACE,yBAAyB,QACzB,OAAO,0BAA0B,YACjC,cAAc,yBACd,YAAY,yBACZ,MAAM,QAAQ,sBAAsB,MAAM;AAE9C;;;ACTO,SAAS,8BAId,kCAIA;AACA,SACE,mBAAuB,gCAAgC,KACvD,oBAAoB;AAExB;;;AClCA,oBAAqC;AAyC9B,SAAS,2BAgBdC,aAeA;AACA,QAAM,yBACJ,OAAOA,gBAAe,cACtB,IAAI;AAAA,QACF,oCAAqBA,WAAU,EAAE;AAAA,MAAI,CAAC,iBACpC,aAAa,YAAY;AAAA,IAC3B;AAAA,EACF;AACF,SAAO,0BAA0B,uBAAuB,QAAQ;AAClE;;;ACrDO,SAAS,8BAWd,kCAWA;AACA,SACE;AAAA,IACE;AAAA,EACF,KACA,cAAc,oCACd,cAAc;AAElB;;;AClDO,SAAS,aAAa,SAAyC;AACpE,SACE,OAAO,YAAY,YACnB,YAAY,QACZ,WAAW,WACX,aAAa,WACb,qBAAqB;AAEzB;;;ACFO,SAAS,eA0Bd,mBAkBA;AACA,SACE,qBAAqB,QACrB,OAAO,sBAAsB,YAC7B,mBAAmB,qBACnB,kBAAkB,kBAAkB;AAExC;;;ACjEA,IAAAC,iBAA0B;AAE1B,IAAAC,cAA+B;AAC/B,IAAAC,+BAA4D;AAC5D,kBAAmB;;;ACJnB,kCAKO;AAEA,IAAM,gBAAgB;AACtB,IAAM,sBAAsB;AAC5B,IAAM,sBAAsB;;;ACTnC,IAAAC,iBAA0B;AAC1B,yDAA4C;AAC5C,IAAAC,cASO;AACP,qCAAgC;AAChC,wCAAmC;AACnC,sCAAkC;AAClC,qCAAuC;AACvC,kCAAoC;AACpC,uBAAuC;AACvC,sBAAwC;AACxC,yBAA8C;AAC9C,sBAAwB;AACxB,IAAAC,+BAKO;AACP,oBAAmB;;;ACCZ,SAAS,oBASd,SASA;AACA,SACE,WAAW,QACX,OAAO,YAAY,YACnB,qBAAqB;AAEzB;;;ACpDA,IAAAC,iBAAwB;AACxB,iBAAsB;AACtB,sBAAkC;AAClC,kBAAuE;;;ACDhE,SAAS,aAAa,KAAiC;AAC5D,SAAO,OAAO,QAAQ,YAAY,QAAQ,QAAQ,WAAW;AAC/D;;;ADKO,SAAS,KAAKC,OAA+B;AAClD,SAAOA;AACT;AAEA,SAAS,YAAY,OAAwB;AAC3C,UAAQ,OAAO;AAAA,IACb,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO;AAAA,IACT;AACE,kCAAQ,KAAK;AACb,aAAO;AAAA,EACX;AACF;AASA,SAAS,iBACP,MACmC;AACnC,MAAI,UAAU;AACd,QAAM,cAAyC,CAAC;AAEhD,aAAW,OAAO,MAAM;AACtB,QAAI,OAAO,QAAQ,YAAY,YAAY,IAAI;AAC7C,gBAAU;AAAA,IACZ,WAAW,eAAe,OAAO;AAC/B,kBAAY,KAAK;AAAA,QACf,KAAK;AAAA,UACH,SAAS,IAAI;AAAA,UACb,MAAM,IAAI;AAAA,UACV,OAAO,IAAI;AAAA,UACX,GAAI,OAAO,KAAK,GAAG,EAAE,SAAS,IAAI,MAAM,CAAC;AAAA,QAC3C;AAAA,MACF,CAAC;AAAA,IACH,WAAW,OAAO,OAAO,QAAQ,YAAY,CAAC,MAAM,QAAQ,GAAG,GAAG;AAChE,kBAAY,KAAK,GAA8B;AAAA,IACjD,OAAO;AACL,iBAAW,IAAI,OAAO,GAAG,CAAC;AAAA,IAC5B;AAAA,EACF;AAEA,QAAM,WAAW,OAAO,OAAO,CAAC,GAAG,GAAG,WAAW;AACjD,SAAO,CAAC,UAAU,QAAQ,KAAK,CAAC;AAClC;AASA,SAAS,iBACP,OACA,MACA,WACQ;AACR,MAAI;AACF,UAAM,CAAC,UAAU,OAAO,IAAI,iBAAiB,IAAI;AAGjD,UAAM,qBAAqB,cAAa,oBAAI,KAAK,GAAE,YAAY;AAC/D,WAAO,IAAI,kBAAkB,KAAK,MAAM,YAAY,CAAC,KAAK,OAAO,GAC/D,OAAO,KAAK,QAAQ,EAAE,SAAS,IAC3B;AAAA,EAAK,KAAK,UAAU,UAAU,MAAM,CAAC,CAAC,KACtC,EACN;AAAA,EACF,SAAS,OAAO;AAEd,UAAM,kBAAkB,KACrB,IAAI,CAAC,QAAQ;AACZ,UAAI;AACF,YAAI,OAAO,QAAQ,SAAU,QAAO;AACpC,YAAI,QAAQ,KAAM,QAAO;AACzB,YAAI,QAAQ,OAAW,QAAO;AAC9B,eAAO,KAAK,UAAU,GAAG;AAAA,MAC3B,QAAQ;AACN,eAAO;AAAA,MACT;AAAA,IACF,CAAC,EACA,KAAK,GAAG;AAEX,WAAO,KAAI,oBAAI,KAAK,GAAE,YAAY,CAAC,KAAK,MAAM,YAAY,CAAC,KAAK,eAAe,yBAAyB,iBAAiB,QAAQ,MAAM,UAAU,eAAe;AAAA,EAClK;AACF;AAEO,IAAM,aAAN,MAAM,YAAW;AAAA,EACtB;AAAA,EACA;AAAA,EAEA,YAAY,OAAgCA,QAAoB,CAAC,GAAG;AAClE,SAAK,kBAAc,YAAAC,SAAK;AAAA,MACtB,OAAO,SAAS;AAAA,MAChB,YAAY;AAAA,QACV,MAAM,OAAO;AACX,iBAAO,EAAE,OAAO,MAAM;AAAA,QACxB;AAAA,MACF;AAAA,MACA,WAAW,YAAAA,QAAK,iBAAiB;AAAA,MACjC,WAAW;AAAA,QACT,QAAQ;AAAA,QACR,SAAS;AAAA,UACP,UAAU;AAAA,UACV,qBAAqB,CAAC,OAAO,OAAO;AAAA,UACpC,QAAQ;AAAA,UACR,eAAe;AAAA,QACjB;AAAA,MACF;AAAA,IACF,CAAC;AACD,SAAK,QAAQD;AAAA,EACf;AAAA,EAEA,IAAI,UAA2B,MAAyC;AACtE,QAAIA,QAAoB,CAAC;AAEzB,UAAM,eAAe,KAAK,OAAO,CAAC,QAAQ;AACxC,UAAI,aAAa,GAAG,GAAG;AACrB,eAAO,OAAOA,OAAM,GAAG;AACvB,eAAO;AAAA,MACT;AACA,aAAO;AAAA,IACT,CAAC;AAED,UAAM,CAAC,aAAa,IAAI,iBAAiB,YAAY;AACrD,WAAO,OAAOA,OAAM,aAAa;AAEjC,UAAM,aAAa,iBAAM,cAAc;AACvC,QAAI,YAAY;AACd,YAAM,oBAAoB,WAAW,YAAY;AACjD,MAAAA,MAAK,WAAW,kBAAkB;AAClC,MAAAA,MAAK,UAAU,kBAAkB;AACjC,MAAAA,MAAK,cAAc,kBAAkB;AACrC,MAAAA,QAAO;AAAA;AAAA,QAEL,GAAG,WAAW;AAAA,QACd,GAAGA;AAAA,MACL;AAAA,IACF;AAEA,IAAAA,QAAO;AAAA,MACL,YAAY;AAAA,MACZ,kBAAkB;AAAA,MAClB,GAAGA;AAAA,IACL;AAEA,SAAK,YAAY,KAAK,EAAE,GAAG,iBAAiB,YAAY,CAAC;AAEzD,UAAM,gBAAgB,iBAAiB,OAAO,YAAY;AAE1D,QAAI;AACF,2BAAK,UAAU,QAAQ,IAAI,qBAAqB,SAAS,EAAE,KAAK;AAAA,QAC9D,cAAc;AAAA,QACd,gBAAgB,YAAY,KAAK;AAAA,QACjC,MAAM;AAAA,QACN,YAAY,EAAE,GAAG,KAAK,OAAO,GAAGA,MAAK;AAAA,MACvC,CAAC;AAAA,IACH,SAAS,OAAO;AACd,cAAQ,MAAM,qCAAqC,KAAK;AACxD,cAAQ;AAAA,QACN,KAAI,oBAAI,KAAK,GAAE,YAAY,CAAC,KAAK,MAAM,YAAY,CAAC;AAAA,QACpD,GAAG;AAAA,MACL;AAAA,IACF;AAAA,EACF;AAAA,EAEA,QAAe,CACb,QACG,SACA,KAAK,IAAI,SAAS,KAAK,GAAG,IAAI;AAAA,EAEnC,OAAc,CACZ,QACG,SACA,KAAK,IAAI,QAAQ,KAAK,GAAG,IAAI;AAAA,EAElC,QAAe,CACb,QACG,SACA,KAAK,IAAI,SAAS,KAAK,GAAG,IAAI;AAAA,EACnC,OAAc,CACZ,QACG,SACA,KAAK,IAAI,QAAQ,KAAK,GAAG,IAAI;AAAA,EAElC,QAAe,CACb,QACG,SACA,KAAK,IAAI,SAAS,KAAK,GAAG,IAAI;AAAA,EAEnC,MAAMA,QAAoB,CAAC,GAAG;AAC5B,WAAO,IAAI,YAAW,KAAK,YAAY,OAAO,EAAE,GAAG,KAAK,OAAO,GAAGA,MAAK,CAAC;AAAA,EAC1E;AAAA,EAEA,gBAAgB;AACd,WAAO,KAAK;AAAA,EACd;AACF;AAEO,SAAS,OAAO,OAAgCA,QAAoB,CAAC,GAAG;AAC7E,SAAO,IAAI,WAAW,OAAOA,KAAI;AACnC;;;AFvLO,IAAM,yBAAN,MAEL;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA;AAAA,EAYA,YACE,aACA,OACA,mBACA;AACA,SAAK,eAAe;AACpB,SAAK,UAAU,OAAO,SAAS,MAAM;AAErC,SAAK,WAAW,CAAC;AAKjB,eAAW,CAAC,UAAU,UAAU,KAAK,OAAO;AAAA,MAC1C,qBAAqB,CAAC;AAAA,IACxB,GAAG;AACD,cAAQ,YAAY;AAAA,QAClB,KAAK;AACH,eAAK,SAAS,QAA0C,IAAI,oBACzD,SAAS,KAAK,YAAY,EAC1B,cAAc,QAAQ;AACzB;AAAA,QACF,KAAK;AACH,eAAK,SAAS,QAA0C,IAAI,oBACzD,SAAS,KAAK,YAAY,EAC1B,YAAY,QAAQ;AACvB;AAAA,QACF,KAAK;AACH,eAAK,SAAS,QAA0C,IAAI,oBACzD,SAAS,KAAK,YAAY,EAC1B,gBAAgB,QAAQ;AAC3B;AAAA,QACF,KAAK;AACH,eAAK,SAAS,QAA0C,IAAI,oBACzD,SAAS,KAAK,YAAY,EAC1B,oBAAoB,QAAQ;AAC/B;AAAA,QACF,KAAK;AACH,eAAK,SAAS,QAA0C,IAAI,oBACzD,SAAS,KAAK,YAAY,EAC1B,wBAAwB,QAAQ;AACnC;AAAA,QACF,KAAK;AACH,eAAK,SAAS,QAA0C,IAAI,oBACzD,SAAS,KAAK,YAAY,EAC1B,sBAAsB,QAAQ;AACjC;AAAA,QACF,KAAK;AACH,eAAK,SAAS,QAA0C,IAAI,oBACzD,SAAS,KAAK,YAAY,EAC1B,8BAA8B,QAAQ;AACzC;AAAA,MACJ;AAAA,IACF;AAEA,SAAK;AAAA,MACH;AAAA,MACA;AAAA,IACF;AAAA,EACF;AAAA,EAEA,IAAI,UAA2B,MAAyC;AACtE,SAAK,QAAQ,IAAI,OAAO,GAAG,IAAI;AAAA,EACjC;AAAA,EAEA,OAAc,CACZ,QACG,SACA;AACH,SAAK,QAAQ,IAAI,QAAQ,KAAK,GAAG,IAAI;AAAA,EACvC;AAAA,EAEA,QAAe,CACb,QACG,SACA;AACH,SAAK,QAAQ,IAAI,SAAS,KAAK,GAAG,IAAI;AAAA,EACxC;AAAA,EAEA,OAAc,CACZ,QACG,SACA;AACH,SAAK,QAAQ,IAAI,QAAQ,KAAK,GAAG,IAAI;AAAA,EACvC;AAAA,EAEA,QAAe,CACb,QACG,SACA;AACH,SAAK,QAAQ,IAAI,SAAS,KAAK,GAAG,IAAI;AAAA,EACxC;AAAA,EAEA,QAAe,CACb,QACG,SACA;AACH,SAAK,QAAQ,IAAI,SAAS,KAAK,GAAG,IAAI;AAAA,EACxC;AAAA,EAEA,UACE,UACyC;AACzC,WAAO,KAAK,SAAS,QAAQ;AAAA,EAC/B;AACF;AAEA,cAAAE,QAAO,OAAO,EAAE,UAAM,0BAAU,kBAAkB,EAAE,CAAC;AAIrD,SAAS,mBAAuD;AAC9D,QAAM,iBAAa,0BAAU,4BAA4B;AACzD,MAAI,CAAC,WAAY,QAAO;AAExB,QAAM,UAAkC,CAAC;AACzC,aAAW,QAAQ,WAAW,MAAM,GAAG,GAAG;AACxC,UAAM,CAAC,KAAK,GAAG,UAAU,IAAI,KAAK,MAAM,GAAG;AAC3C,QAAI,OAAO,WAAW,SAAS,GAAG;AAChC,cAAQ,IAAI,KAAK,CAAC,IAAI,WAAW,KAAK,GAAG,EAAE,KAAK;AAAA,IAClD;AAAA,EACF;AACA,SAAO,OAAO,KAAK,OAAO,EAAE,SAAS,IAAI,UAAU;AACrD;AAEA,IAAM,cAAc,iBAAiB;AAErC,IAAI,wBAAQ;AAAA,EACV,cAAU,yCAAuB;AAAA,IAC/B,CAAC,8CAAiB,OAAG,0BAAU,mBAAmB;AAAA,EACpD,CAAC;AAAA,EACD,eAAe,IAAI,kDAAkB;AAAA,IACnC,KAAK,OACH,0BAAU,6BAA6B,KAAK,uBAC9C;AAAA,IACA,SAAS;AAAA,EACX,CAAC;AAAA,EACD,cAAc,IAAI,iDAA8B;AAAA,IAC9C,UAAU,IAAI,qDAAmB;AAAA,MAC/B,KAAK,OACH,0BAAU,6BAA6B,KAAK,uBAC9C;AAAA,MACA,SAAS;AAAA,IACX,CAAC;AAAA,IACD,sBAAsB;AAAA,EACxB,CAAC;AAAA,EACD,qBAAqB;AAAA,IACnB,IAAI,wCAAwB;AAAA,MAC1B,UAAU,IAAI,+CAAgB;AAAA,QAC5B,KAAK,OACH,0BAAU,6BAA6B,KAAK,uBAC9C;AAAA,QACA,SAAS;AAAA,MACX,CAAC;AAAA,IACH,CAAC;AAAA,EACH;AAAA,EACA,kBAAkB;AAAA,IAChB,IAAI,gDAAoB;AAAA,MACtB,6BAA6B,CAAC,MAAM,YAAY;AAC9C,aAAK;AAAA,UACH;AAAA,cACA,0BAAU,mBAAmB,KAAK;AAAA,QACpC;AACA,YAAI,oBAAoB,OAAO,GAAG;AAChC,eAAK,aAAa,eAAe,QAAQ,iBAAiB,IAAI;AAC9D,eAAK,aAAa,qBAAqB,QAAQ,QAAQ,aAAa;AAAA,QACtE;AAAA,MACF;AAAA,IACF,CAAC;AAAA,IACD,IAAI,sDAAuB;AAAA,IAC3B,IAAI,+EAA4B;AAAA,EAClC;AACF,CAAC,EAAE,MAAM;AAGF,IAAM,2BAA2B,oBACrC,aAAS,0BAAU,mBAAmB,KAAK,SAAS,EACpD,cAOE,uBAAuB;AAAA,EACxB,aAAa;AACf,CAAC;AAEI,IAAM,8BAA8B,oBACxC,aAAS,0BAAU,mBAAmB,KAAK,SAAS,EACpD,gBAOE,wBAAwB;AAAA,EACzB,aAAa;AAAA,EACb,MAAM;AACR,CAAC;AAEI,IAAM,iCAAiC,oBAC3C,aAAS,0BAAU,mBAAmB,KAAK,SAAS,EACpD,gBAOE,4BAA4B;AAAA,EAC7B,aAAa;AACf,CAAC;AAEI,IAAM,yBAAyB,oBACnC,aAAS,0BAAU,mBAAmB,KAAK,SAAS,EACpD,cAOE,qBAAqB;AAAA,EACtB,aAAa;AACf,CAAC;AAEI,IAAM,8BAA8B,oBACxC,aAAS,0BAAU,mBAAmB,KAAK,SAAS,EACpD,oBAEE,2BAA2B;AAAA,EAC5B,aAAa;AACf,CAAC;;;AFlQI,SAAS,cAYd,iBAeA;AACA,SAAO,SAAS,WAAW,KAAK,KAAK,MAAO;AAC1C,QAAI,kBAAkB;AAEtB,QAAI,oBAAgB,gBAAG;AACvB,QAAI,IAAI,QAAQ,kBAAkB,GAAG;AACnC,sBAAgB,IAAI,QAAQ,kBAAkB;AAAA,IAChD;AAEA,IACE,IAOA,UAAU,oBAAoB,aAAa;AAE7C,QAAI,UAAU;AAAA,MACZ;AAAA,MACA,kBAAkB,KAAK,IAAI;AAAA,IAC7B;AAEA,UAAM,kBAAc,0BAAU,mBAAmB,KAAK;AACtD,UAAM,gBAAgB;AAAA,MACpB,CAAC,6BAAAC,iBAAsB,GAAG;AAAA,IAC5B;AACA,QAAI,iBAAiB;AAErB,UAAM,oBAAoB,MAAM;AAC9B,UAAI,CAAC,gBAAgB;AACnB;AAAA,MACF;AAEA,kCAA4B,IAAI,IAAI,aAAa;AACjD,uBAAiB;AAAA,IACnB;AAEA,gCAA4B,IAAI,GAAG,aAAa;AAChD,QAAI,GAAG,UAAU,iBAAiB;AAClC,QAAI,GAAG,SAAS,iBAAiB;AACjC,QAAI,GAAG,SAAS,iBAAiB;AAEjC,UAAM,OAAO,kBAAM,QAAQ,oBAAQ,OAAO,CAAC;AAE3C,QAAI,QAAQ,MAAM;AAChB,UAAI,QAAQ,OAAO;AACnB,UAAI,QAAQ,MAAM,aAAa,qBAAqB,aAAa;AACjE,UAAI,QAAQ,MAAM,aAAa,+CAAmB,WAAW;AAAA,IAC/D;AAEA,WAAO;AAAA,EACT;AACF;;;AM9FO,SAAS,iBACd,iBACA,MAOY;AACZ,MAAI,QAAQ,MAAM;AAChB,WAAO;AAAA,EACT;AAEA,QAAM,iBAAiB;AAEvB,MAAI,UAAU,kBAAkB,eAAe,QAAQ,MAAM;AAC3D,WAAO;AAAA,MACL,aAAa,eAAe,eAAe;AAAA,MAC3C,YAAY;AAAA,MACZ,QAAQ,eAAe;AAAA,IACzB;AAAA,EACF,WAAW,UAAU,kBAAkB,eAAe,QAAQ,MAAM;AAClE,WAAO;AAAA,MACL,aAAa,eAAe,eAAe;AAAA,MAC3C,YAAY;AAAA,MACZ,QAAQ,eAAe;AAAA,IACzB;AAAA,EACF,WAAW,UAAU,kBAAkB,eAAe,QAAQ,MAAM;AAClE,WAAO;AAAA,MACL,aAAa,eAAe,eAAe;AAAA,MAC3C,YAAY;AAAA,MACZ,QAAQ,eAAe;AAAA,IACzB;AAAA,EACF,WACE,mBAAmB,kBACnB,eAAe,iBAAiB,MAChC;AACA,WAAO;AAAA,MACL,aAAa,eAAe,eAAe;AAAA,MAC3C,YAAY;AAAA,MACZ,QAAQ,eAAe;AAAA,IACzB;AAAA,EACF,WACE,oBAAoB,kBACpB,eAAe,kBAAkB,MACjC;AACA,WAAO;AAAA,MACL,aACE,eAAe,eAAe;AAAA,MAChC,YAAY;AAAA,MACZ,QAAQ,eAAe;AAAA,IACzB;AAAA,EACF,WAAW,YAAY,kBAAkB,eAAe,UAAU,MAAM;AACtE,WAAO;AAAA,MACL,aAAa,eAAe,eAAe;AAAA,MAC3C,YAAY;AAAA,MACZ,QAAQ,eAAe;AAAA,IACzB;AAAA,EACF,WACG,gBAAoC;AAAA,IACnC;AAAA,IACA,gBAAgB;AAAA,EAClB,GACA;AACA,WAAO;AAAA,MACL,aAAa;AAAA,MACb,YAAY;AAAA,MACZ,QAAQ;AAAA,IACV;AAAA,EACF,WACG,gBAAoC,QAAQ,cAAc,EAAE,WAC7D,UACA;AACA,WAAO;AAAA,MACL,aAAa;AAAA,MACb,YAAY;AAAA,MACZ,QAAQ;AAAA,IACV;AAAA,EACF,OAAO;AACL,WAAO;AAAA,MACL,aAAa;AAAA,MACb,YAAY;AAAA,MACZ,QAAQ;AAAA,IACV;AAAA,EACF;AACF;AAgBO,SAAS,2BACd,iBACA,WACA;AACA,QAAM,yBAOF,CAAC;AACL,aAAW,CAAC,YAAY,QAAQ,KAAK,OAAO,QAAQ,SAAS,GAAG;AAC9D,QAAI,YAAY,QAAQ,OAAO,aAAa,UAAU;AACpD,UAAI,UAAU,YAAY,SAAS,QAAQ,MAAM;AAC/C,+BAAuB,OAAO,UAAU,CAAC,IAAI;AAAA,UAC3C,cACG,iBAAiB,YAClB,OAAO,SAAS,gBAAgB,WAC5B,SAAS,cACT,uBAAuB;AAAA,UAC7B,YAAY;AAAA,UACZ,QAAQ,SAAS;AAAA,QACnB;AAAA,MACF,WAAW,YAAY,YAAY,SAAS,UAAU,MAAM;AAC1D,+BAAuB,OAAO,UAAU,CAAC,IAAI;AAAA,UAC3C,cACG,iBAAiB,YAClB,OAAO,SAAS,gBAAgB,WAC5B,SAAS,cACT,uBAAuB;AAAA,UAC7B,YAAY;AAAA,UACZ,QAAQ,SAAS;AAAA,QACnB;AAAA,MACF,WAAW,UAAU,YAAY,SAAS,QAAQ,MAAM;AACtD,+BAAuB,OAAO,UAAU,CAAC,IAAI;AAAA,UAC3C,cACG,iBAAiB,YAClB,OAAO,SAAS,gBAAgB,WAC5B,SAAS,cACT,iBAAiB;AAAA,UACvB,YAAY;AAAA,UACZ,QAAQ,SAAS;AAAA,QACnB;AAAA,MACF,WAAW,UAAU,YAAY,SAAS,QAAQ,MAAM;AACtD,+BAAuB,OAAO,UAAU,CAAC,IAAI;AAAA,UAC3C,cACG,iBAAiB,YAClB,OAAO,SAAS,gBAAgB,WAC5B,SAAS,cACT,+BAA+B;AAAA,UACrC,YAAY;AAAA,UACZ,QAAQ,SAAS;AAAA,QACnB;AAAA,MACF,WAAW,WAAW,YAAY,SAAS,SAAS,MAAM;AACxD,+BAAuB,OAAO,UAAU,CAAC,IAAI;AAAA,UAC3C,cACG,iBAAiB,YAClB,OAAO,SAAS,gBAAgB,WAC5B,SAAS,cACT,wBAAwB;AAAA,UAC9B,YAAY;AAAA,UACZ,QAAQ,SAAS;AAAA,QACnB;AAAA,MACF,WACG,gBAAoC;AAAA,QACnC;AAAA,QACA,gBAAgB;AAAA,MAClB,GACA;AACA,+BAAuB,OAAO,UAAU,CAAC,IAAI;AAAA,UAC3C,aAAa;AAAA,UACb,YAAY;AAAA,UACZ,QAAQ;AAAA,QACV;AAAA,MACF,WACG,gBAAoC,QAAQ,QAAQ,EAAE,WACvD,UACA;AACA,+BAAuB,OAAO,UAAU,CAAC,IAAI;AAAA,UAC3C,aAAa;AAAA,UACb,YAAY;AAAA,UACZ,QAAQ;AAAA,QACV;AAAA,MACF,OAAO;AACL,+BAAuB,OAAO,UAAU,CAAC,IAAI;AAAA,UAC3C,aAAa;AAAA,UACb,YAAY;AAAA,UACZ,QAAQ;AAAA,QACV;AAAA,MACF;AAAA,IACF,OAAO;AACL,6BAAuB,OAAO,UAAU,CAAC,IAAI;AAAA,QAC3C,aAAa;AAAA,QACb,YAAY;AAAA,QACZ,QAAQ;AAAA,MACV;AAAA,IACF;AAAA,EACF;AACA,SAAO;AACT;;;ACjOA,IAAAC,kBAAyB;;;ACAlB,SAAS,mBAAmB,iBAA0B;AAC3D,SACE,OAAO,oBAAoB,YAC3B,oBAAoB,QACpB,cAAc,mBACd,gBAAgB,aAAa;AAEjC;;;ACCO,SAAS,aACd,iBACgC;AAChC,SACE,OAAO,oBAAoB,YAC3B,oBAAoB,QACpB,UAAU,mBACV,gBAAgB,QAAQ;AAE5B;;;ACHO,SAAS,+BAsBd,mCAcA;AACA,SACE,qCAAqC,QACrC,OAAO,sCAAsC,YAC7C,UAAU,qCACV,aAAa,qCACb,kCAAkC,QAAQ,QAC1C,kCAAkC,WAAW,SAC3C,eAAe,qCACf,kCAAkC,aAAa,QAC9C,cAAc,qCACb,OAAO,kCAAkC,aAAa,YACtD,kCAAkC,YAAY,QAC9C,OAAO,OAAO,kCAAkC,QAAQ,EAAE;AAAA,IACxD,CAAC,YAAY,eAAe,WAAW,QAAQ,aAAa;AAAA,EAC9D;AAER;;;AC3BO,SAAS,sBAsBd,sBAcA;AACA,SACE,+BAA+B,oBAAoB,MACjD,UAAU,wBAAwB,qBAAqB,QAAQ,QAC9D,cAAc,wBACb,OAAO,qBAAqB,aAAa,YACzC,qBAAqB,YAAY,QACjC,OAAO,OAAO,qBAAqB,QAAQ,EAAE;AAAA,IAC3C,CAAC,YAAY,UAAU,WAAW,QAAQ,QAAQ;AAAA,EACpD;AAER;;;ACvFA,IAAAC,iBAAwB;AACxB,uBAIO;;;ACLP,IAAAC,iBAA8B;AAE9B,kBAA2C;;;ACF3C,IAAAC,iBAA8B;AAC9B,oBAA2B;AAYpB,SAAS,gBAAgB;AAAA,EAC9B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAOG;AACD,QAAM,WAAO,0BAAW,UAAU,SAAS;AAM3C,QAAM,aAAa,OACf,GACE,OAAO,SAAS,IAAI,IAChB,KAAK,SAAS,MAAM,IACpB,OAAO,SAAS,WACd,WACA,8BAAc,IAAI,CAC1B;AAAA,IACA;AACJ,OAAK;AAAA,IACH,GAAG,MAAM;AAAA,EAAK,IAAI;AAAA,EAAK,UAAU,GAAG,UAAU,YAAY,CAAC;AAAA,EAAK,KAAK;AAAA,EACvE;AACA,SAAO,KAAK,OAAO,QAAQ;AAC7B;;;AC7CO,SAAS,kBACd,sBAC0C;AAC1C,SACE,OAAO,yBAAyB,YAChC,yBAAyB,QACzB,WAAW,wBACX,qBAAqB,SAAS;AAElC;;;ACTO,SAAS,gBACd,oBACsC;AACtC,SACE,OAAO,uBAAuB,YAC9B,uBAAuB,QACvB,SAAS,sBACT,mBAAmB,OAAO;AAE9B;;;AHOA,IAAM,cAAc,QAAQ,IAAI,WAC5B,SAAS,QAAQ,IAAI,QAAQ,IAC7B,KAAK,MAAO;AAEhB,IAAM,aAAa;AAAA,EACjB,OAAO;AAAA,EACP,aAAa;AAAA,EACb,KAAK;AACP;AAkBA,eAAsB,cAAc,kBAA0C;AAC5E,MACE,WAAW,SACX,WAAW,eACX,KAAK,IAAI,IAAI,WAAW,YAAY,QAAQ,IAAI,WAAW,KAC3D;AACA,WAAO,WAAW;AAAA,EACpB,OAAO;AACL,UAAM,eAAe,MAAM,MAAM,gBAAgB;AACjD,UAAMC,QAAO,MAAM,aAAa,KAAK;AACrC,QAAI,CAACA,OAAM;AACT,UAAI,WAAW,OAAO;AACpB,eAAO,WAAW;AAAA,MACpB;AACA,YAAM,IAAI;AAAA,QACR,iDAAiD,aAAa,MAAM;AAAA,MACtE;AAAA,IACF;AACA,UAAM,OAAQ,KAAK,MAAMA,KAAI,EAAsB;AACnD,eAAW,QAAQ;AACnB,eAAW,cAAc,oBAAI,KAAK;AAClC,eAAW,MACT;AAAA,MACE,aAAa,QAAQ,IAAI,eAAe,GAAG,MAAM,GAAG,EAAE,CAAC,KACrD,GAAG,cAAc,GAAI;AAAA,IACzB,IAAI;AACN,WAAO;AAAA,EACT;AACF;AAkCA,eAAsB,uBASpB,MASA,wBA4CA;AACA,MAAI;AACJ,MAAI,kBAAkB,IAAI,GAAG;AAC3B,iBAAa;AAAA,MACX,MAAM;AAAA,MACN,MAAM;AAAA,QACJ,gBAAgB,KAAK;AAAA,QACrB,OAAO,KAAK,MAAM;AAAA,MACpB;AAAA,IACF;AAAA,EACF,WAAW,gBAAgB,IAAI,GAAG;AAChC,UAAM,MAAM,KAAK;AACjB,QAAI;AAGJ,QAAI,kBAAkB,KAAK;AACzB,6BAAuB,OAAO,UAAU;AACtC,cAAM,EAAE,QAAQ,IAAI,UAAM;AAAA,UACxB;AAAA,UACA,IAAI,WAAW,OAAO,KAAK,IAAI,YAAY,CAAC;AAAA,QAC9C;AACA,eAAO;AAAA,MACT;AAAA,IACF,OAAO;AACL,UAAI;AACJ,UAAI,sBAAsB,KAAK;AAC7B,eAAO,MAAM,cAAc,IAAI,gBAAgB;AAAA,MACjD,WAAW,mBAAmB,KAAK;AACjC,eAAO,CAAC,IAAI,aAAa;AAAA,MAC3B;AACA,6BAAuB,OAAO,UAAU;AAItC,YAAI;AACJ,mBAAW,OAAO,MAAM;AACtB,cAAI;AACF,kBAAM,EAAE,QAAQ,IAAI,UAAM,uBAAU,OAAO,GAAG;AAC9C,mBAAO;AAAA,UACT,SAAS,OAAO;AACd,wBAAY;AACZ,uBAAW,QAAQ;AACnB,uBAAW,cAAc;AACzB,uBAAW,MAAM;AACjB;AAAA,UACF;AAAA,QACF;AACA,YAAI,cAAc,OAAW,OAAM;AAAA,MACrC;AAAA,IACF;AACA,iBAAa;AAAA,MACX,MAAM;AAAA,MACN,MAAM;AAAA,QACJ,gBAAgB,KAAK;AAAA,QACrB;AAAA,MACF;AAAA,IACF;AAAA,EACF,WAAW,aAAa,IAAI,GAAG;AAC7B,iBAAa;AAAA,MACX,MAAM;AAAA,MACN,MAAM;AAAA,QACJ,YAAY,KAAK,KAAK;AAAA,QACtB,sBAAsB,OAAO;AAAA,UAC3B;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,QACF,MAQM;AACJ,gBAAM,oBAAoB,gBAAgB;AAAA,YACxC;AAAA,YACA;AAAA,YACA;AAAA,YACA;AAAA,YACA;AAAA,YACA;AAAA,UACF,CAAC;AAED,gBAAM,UAAU,sBAAsB;AAEtC,cAAI,CAAC,SAAS;AACZ,kBAAM,YAAY;AAAA,cAChB;AAAA,cACA;AAAA,cACA,WAAW,UAAU,YAAY;AAAA,cACjC;AAAA,cACA,mBAAmB;AAAA,cACnB;AAAA,YACF;AAEA,oCAAwB,MAAM,8BAA8B;AAAA,cAC1D,GAAG;AAAA,cACH,UAAU,OAAO,OAAO,OAAO;AAAA,cAC/B,MAAM,WAAO,8BAAc,IAAI,IAAI;AAAA,YACrC,CAAC;AAAA,UACH;AAEA,iBAAO;AAAA,QACT;AAAA,MACF;AAAA,IACF;AAAA,EACF;AACA,MAAI,cAAc,MAAM;AACtB,UAAM,IAAI,MAAM,qBAAqB;AAAA,EACvC;AAEA,SAAO;AACT;;;AI7RO,SAAS,iBAAiB,kBAA2B;AAC1D,SACE,OAAO,qBAAqB,YAC5B,qBAAqB,QACrB,sBAAsB,oBACtB,MAAM,QAAQ,iBAAiB,gBAAgB,KAC/C,iBAAiB,iBAAiB,SAAS;AAE/C;;;ACRO,SAAS,sBAAsB,uBAAgC;AACpE,SACE,OAAO,0BAA0B,YACjC,0BAA0B,QAC1B,+BAA+B,yBAC/B,sBAAsB,8BAA8B;AAExD;;;ACPA,IAAAC,iBAA2B;AAC3B,IAAAC,eAAuE;AAkCvE,IAAM,qBAAqB;AAC3B,IAAM,mBAAmB;AAEzB,SAAS,QAAQ,OAAoC;AACnD,SAAO,OAAO,UAAU,YAAY,MAAM,SAAS,IAC/C,MAAM,MAAM,GAAG,gBAAgB,IAC/B;AACN;AAOO,SAAS,eAAe,aAAsC;AACnE,MAAI,OAAO,gBAAgB,YAAY,YAAY,WAAW,GAAG;AAC/D,WAAO,EAAE,UAAU,MAAM;AAAA,EAC3B;AAEA,QAAMC,WAA0B;AAAA,IAC9B,UAAU;AAAA,IACV,sBAAkB,2BAAW,QAAQ,EAClC,OAAO,WAAW,EAClB,OAAO,KAAK,EACZ,MAAM,GAAG,kBAAkB;AAAA,EAChC;AAEA,QAAM,QAAQ,YAAY,KAAK,EAAE,MAAM,KAAK;AAC5C,QAAM,YAAY,MAAM,MAAM,SAAS,CAAC;AACxC,MAAI,UAAU,MAAM,GAAG,EAAE,WAAW,GAAG;AACrC,WAAOA;AAAA,EACT;AAEA,MAAI;AACF,UAAM,cAAU,wBAAU,SAAS;AACnC,UAAM,aAAS,oCAAsB,SAAS;AAC9C,IAAAA,SAAQ,UAAU;AAAA,MAChB,KAAK,QAAQ,QAAQ,GAAG;AAAA,MACxB,gBAAgB,QAAQ,QAAQ,cAAc;AAAA,MAC9C,KAAK,QAAQ,QAAQ,GAAG;AAAA,MACxB,KAAK,OAAO,QAAQ,QAAQ,WAAW,QAAQ,MAAM;AAAA,MACrD,KAAK,QAAQ,OAAO,GAAG;AAAA,IACzB;AAAA,EACF,QAAQ;AAAA,EAER;AAEA,SAAOA;AACT;AAOO,SAAS,iBAAiB,OAAwB;AACvD,MAAI,iBAAiB,aAAAC,OAAW,WAAY,QAAO;AACnD,MAAI,iBAAiB,aAAAA,OAAW,0BAA0B;AACxD,WAAO,aAAa,MAAM,KAAK;AAAA,EACjC;AACA,MAAI,iBAAiB,aAAAA,OAAW,gCAAgC;AAC9D,WAAO;AAAA,EACT;AACA,MAAI,iBAAiB,aAAAA,OAAW,kBAAmB,QAAO;AAC1D,MAAI,iBAAiB,aAAAA,OAAW,YAAa,QAAO;AACpD,MACE,iBAAiB,aAAAA,OAAW,cAC5B,iBAAiB,aAAAA,OAAW,YAC5B;AACA,WAAO;AAAA,EACT;AACA,MAAI,iBAAiB,aAAAA,OAAW,UAAW,QAAO,MAAM,KAAK,YAAY;AACzE,SAAO;AACT;;;AP9DA,IAAM,kCAAkC;AAAA,EACtC;AAAA,EACA;AACF;AACA,IAAM,gCAAgC;AAAA,EACpC;AAAA,EACA;AACF;AACA,IAAM,uCAAuC;AAAA,EAC3C;AAAA,EACA;AACF;AACA,IAAM,iCAAiC;AAAA,EACrC;AAAA,EACA;AACF;AACA,IAAM,oCAAoC;AAAA,EACxC;AAAA,EACA;AACF;AACA,IAAM,mCAAmC;AAAA,EACvC;AAAA,EACA;AACF;AACA,IAAM,4BAA4B;AAAA,EAChC;AAAA,EACA;AACF;AACA,IAAM,4BAA4B;AAAA,EAChC;AAAA,EACA;AACF;AACA,IAAM,eAAe,CAAC,KAAK,8BAA8B;AACzD,IAAM,6BAA6B;AAAA,EACjC;AAAA,EACA;AACF;AACA,IAAM,6BAA6B;AAAA,EACjC;AAAA,EACA;AACF;AACA,IAAM,uBAAuB;AAAA,EAC3B;AAAA,EACA;AACF;AASA,SAAS,mBACP,MACA,aACoB;AACpB,MAAI,CAAC,KAAM,QAAO;AAClB,QAAM,CAAC,KAAK,GAAG,IAAI,IAAI,KAAK,MAAM,GAAG;AACrC,MAAI,QAAQ,eAAe,KAAK,WAAW,EAAG,QAAO;AACrD,SAAO,KAAK,KAAK,GAAG;AACtB;AASA,eAAe,wBAUb,KASA,qBASA,oBACA,eACA,QAC+D;AAC/D,MAAI,uBAAuB,MAAM;AAC/B,WAAO;AAAA,EACT;AAEA,QAAM,+BAA+B;AAAA,IACnC,GAAG;AAAA,IACH,GAAG;AAAA,EACL;AAWA,MAAI,sBAAsB,MAAM;AAC9B,WAAO;AAAA,EACT;AAEA,QAAM,CAAC,aAAa,GAAG,UAAU,IAAI,mBAAmB,MAAM,GAAG;AAEjE,MAAI,CAAC,WAAW,UAAU,CAAC,aAAa;AACtC,WAAO;AAAA,EACT;AAEA,MAAI;AAEJ,QAAM,EAAE,MAAM,KAAK,IAAI,MAAM;AAAA,IAC3B;AAAA,IASA,IAAI;AAAA,EACN;AAEA,UAAQ,MAAM;AAAA,IACZ,KAAK,QAAQ;AACX,YAAM,CAAC,OAAO,WAAW,OAAO,SAAS,IAAI;AAC7C,UACE,SAAS,QACT,aAAa,QACb,SAAS,QACT,aAAa,QACb,iBAAiB,6BAA6B,eAAe,SAC7D;AACA,eAAO;AAAA,MACT;AAEA,UAAI,CAAC,6BAA6B,MAAM,YAAY;AAClD,eAAO;AAAA,MACT;AAEA,YAAM,cAAc,mBAAmB,OAAO,OAAO;AACrD,YAAM,kBAAkB,mBAAmB,WAAW,IAAI;AAC1D,YAAM,cAAc,mBAAmB,OAAO,OAAO;AACrD,YAAM,kBAAkB,mBAAmB,WAAW,WAAW;AAEjE,UACE,CAAC,eACD,CAAC,mBACD,CAAC,eACD,CAAC,iBACD;AACA,eAAO;AAAA,MACT;AAEA,YAAM,qBAAqB,MAAM,KAAK,qBAAqB;AAAA,QACzD,QAAQ,KAAK,UAAU;AAAA,QACvB,MAAM,KAAK,QAAQ;AAAA,QACnB,MAAM,KAAK,YAAY,KAAK;AAAA,QAC5B,WAAW,IAAI,KAAK,eAAe;AAAA,QACnC,OAAO;AAAA,QACP,WAAW;AAAA,QACX,WAAW,6BAA6B,KAAK,WAAW,WAAW;AAAA,MACrE,CAAC;AAED,UAAI,CAAC,oBAAoB;AACvB,eAAO;AAAA,MACT;AAEA,uBAAiB;AACjB;AAAA,IACF;AAAA,IACA,KAAK,OAAO;AACV,YAAM,CAAC,KAAK,IAAI;AAChB,UACE,iBAAiB,6BAA6B,eAAe,WAC7D;AACA,eAAO;AAAA,MACT;AAEA,UAAI;AACF,cAAM,aACJ,oBAAoB,QAAQ,KAAK,iBAC7B,MAAM,KAAK,eAAe,KAAK,IAC/B,0BAA0B,QAAQ,KAAK,uBACrC,MAAM,KAAK,qBAAqB,KAAK,IACrC;AAER,YAAI,CAAC,YAAY;AACf,iBAAO;AAAA,QACT;AAEA,yBAAiB;AAAA,MACnB,SAAS,OAAO;AACd,QACE,KASC,wBAAwB;AAAA,UACzB;AAAA,UACA,KAAK;AAAA,YACH,QAAQ,iBAAiB,KAAK;AAAA,YAC9B,OAAO,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;AAAA,YAC5D,QAAQ,IAAI;AAAA,YACZ,MAAM,IAAI;AAAA,YACV,GAAG,eAAe,KAAK;AAAA,UACzB,CAAC;AAAA,QACH;AACA,eAAO;AAAA,MACT;AAEA;AAAA,IACF;AAAA,IACA,KAAK,SAAS;AACZ,YAAM,CAAC,KAAK,IAAI;AAEhB,UACE,iBAAiB,6BAA6B,eAAe,UAC7D;AACA,eAAO;AAAA,MACT;AAEA,UAAI,KAAK,gBAAgB;AACvB,yBAAkB,MAAM,KAAK,eAAe,KAAK;AAAA,MAEnD,OAAO;AACL,cAAM,CAAC,UAAU,QAAQ,IAAI,OAAO,KAAK,OAAO,QAAQ,EACrD,SAAS,OAAO,EAChB,MAAM,GAAG;AAEZ,YAAI,CAAC,YAAY,CAAC,UAAU;AAC1B,iBAAO;AAAA,QACT;AAEA,YAAI,CAAC,KAAK,MAAM,UAAU,QAAQ,GAAG;AACnC,iBAAO;AAAA,QACT;AAEA,yBAAiB;AAAA,UACf,KAAK;AAAA,QACP;AAAA,MACF;AACA;AAAA,IACF;AAAA,IACA;AACE,kCAAQ,IAAI;AACZ,aAAO,CAAC,KAAK,+BAA+B;AAAA,EAChD;AAEA,MAAI,aAAa,4BAA4B,KAAK,kBAAkB,MAAM;AACxE;AAAA,EACF;AAEA,MAAI,kBAAkB,MAAM;AAC1B,WAAO;AAAA,EACT;AAEA,MAAI,UAAU;AACd,MAAI,6BAA6B,eAAe;AAC9C,UAAM,gBAAiB,IAAI,gBAAoC;AAAA,MAC7D,6BAA6B;AAAA,MAC7B;AAAA,IACF;AACA,QAAI,CAAC,cAAc,IAAI;AACrB,aAAO;AAAA,QACL;AAAA,QACA,wBAAoB,yCAAuB,cAAc,QAAQ,SAAS,CAAC;AAAA,MAC7E;AAAA,IACF;AAAA,EACF;AAEA,MAAI,eAAe,4BAA4B,GAAG;AAChD,QAAI,6BAA6B,eAAe;AAC9C,YAAM,iBAAiB,MAAM,6BAA6B;AAAA,QACxD;AAAA,QACA;AAAA,MAUF;AAEA,UAAI,6BAA6B,gBAAgB;AAC/C,YAAI,6BAA6B,eAAe;AAC9C,cACE,CAAC,eAAe,IAAI,6BAA6B,aAAa,KAC9D,CAAC,MAAM,KAAK,cAAc,EAAE;AAAA,YAC1B,CAAC,WACE,6BAA6B,gBAAgB,QAAQ,KAAK,KACzD,MAAM;AAAA,UACZ,GACA;AACA,mBAAO;AAAA,UACT;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAKA,MAAI,WAAW,mBAAmB,WAAW,YAAY;AAAA,EAEzD,WAAW,oBAAoB,4BAA4B,GAAG;AAC5D,QAAI,CAAC,6BAA6B,oBAAoB;AACpD,aAAO,CAAC,KAAK,4CAA4C;AAAA,IAC3D;AAEA,UAAM,sBACJ,MAAM,6BAA6B;AAAA,MACjC;AAAA,MACA;AAAA,IAUF;AAEF,QACE,wBAAwB,gCACxB,6BAA6B,oBAC7B;AACA,UACE,oBAAoB;AAAA,QAClB,6BAA6B;AAAA,MAC/B,EAAE,SAAS,GACX;AACA,eAAO;AAAA,MACT;AAAA,IACF;AAEA,QACE,0BAA0B,gCAC1B,6BAA6B,sBAC7B;AACA,UACE,oBAAoB;AAAA,QAClB,6BAA6B;AAAA,MAC/B,EAAE,SAAS,GACX;AACA,eAAO;AAAA,MACT;AAAA,IACF;AAAA,EACF,WAAW,cAAc,4BAA4B,GAAG;AACtD,QAAI,CAAC,6BAA6B,cAAc;AAC9C,aAAO,CAAC,KAAK,sCAAsC;AAAA,IACrD;AAEA,UAAM,gBAAgB,MAAM,6BAA6B;AAAA,MACvD;AAAA,MACA;AAAA,IAUF;AAEA,QACE,kBAAkB,gCAClB,6BAA6B,cAC7B;AACA,UACE,cAAc,aAAa,6BAA6B,YAAY,EACjE,SAAS,GACZ;AACA,eAAO;AAAA,MACT;AAAA,IACF;AAEA,QACE,oBAAoB,gCACpB,6BAA6B,gBAC7B;AACA,UACE,cAAc,aAAa,6BAA6B,cAAc,EACnE,SAAS,GACZ;AACA,eAAO;AAAA,MACT;AAAA,IACF;AAAA,EACF,WAAW,WAAW,aAAa;AACjC,WAAO;AAAA,EACT;AAEA,MAAI,sBAAsB,4BAA4B,GAAG;AACvD,QAAI,CAAC,6BAA6B,qBAAqB;AACrD,aAAO,CAAC,KAAK,8CAA8C;AAAA,IAC7D;AAEA,UAAM,eAAe,MAAM,6BAA6B;AAAA,MACtD;AAAA,MACA;AAAA,IAUF;AAEA,QAAI,CAAC,cAAc;AACjB,aAAO;AAAA,IACT;AAAA,EACF;AAEA,MAAI,iBAAiB,4BAA4B,GAAG;AAClD,QAAI,CAAC,6BAA6B,iBAAiB;AACjD,aAAO,CAAC,KAAK,0CAA0C;AAAA,IACzD;AAEA,UAAM,oBACJ,MAAM,6BAA6B;AAAA,MACjC;AAAA,MACA;AAAA,IAUF;AAEF,UAAM,mBACJ,6BAA6B,oBAAoB,CAAC;AACpD,UAAM,kBAAkB,iBAAiB;AAAA,MACvC,CAAC,YAAY,CAAC,kBAAkB,IAAI,OAAO;AAAA,IAC7C;AAEA,QAAI,gBAAgB,SAAS,GAAG;AAC9B,aAAO;AAAA,IACT;AAAA,EACF;AACF;AAaA,eAAsB,iBAapB,KASA,KAOA,MACA;AACA,QAAM,SAAS,IAAI,gBAAgB;AAInC,MAAI,WAAW,UAAU;AACvB,WAAO;AACP;AAAA,EACF;AAEA,QAAM,OAAO,IAAI,gBAAgB;AAYjC,QAAM,QACH,IAAI,QAAQ,MAAM,cAAc,eAAe,KAC/C,IAAI,QAAQ,MAAM,cAAc,eAAe;AAElD,QAAM,CAAC,OAAO,OAAO,IAClB,MAAM,wBASL,KAAK,MAAM,OAAO,IAAI,iBAAiB,GAAG,MAAM,MAAM,KAAM,CAAC;AACjE,MAAI,SAAS,MAAM;AAGjB,QAAI,wBAAwB;AAAA,MAC1B,WAAW;AAAA,MACX,KAAK;AAAA,QACH,YAAY;AAAA,QACZ,QAAQ,IAAI;AAAA,QACZ,MAAM,IAAI;AAAA,QACV,GAAG,eAAe,KAAK;AAAA,MACzB,CAAC;AAAA,IACH;AACA,QAAI,KAAK,YAAY;AACrB,QAAI,OAAO,KAAK,EAAE,KAAK,OAAgB;AACvC;AAAA,EACF;AAEA,SAAO;AACT;;;AQjnBA,IAAAC,iBAA0B;;;ACA1B,IAAAC,iBAA0B;;;ACA1B,kBAA2D;AAC3D,8BAAkC;AAmBlC,IAAM,iBAAiB,IAAI,0CAAwC;;;ACEnE,IAAM,YACJ,WACA,uBAAO,IAAI,uCAAuC,CAAC,MACnD,oBAAI,IAAI;AAMH,SAAS,mBACd,UACY;AACZ,YAAU,IAAI,QAAQ;AACtB,SAAO,MAAM,UAAU,OAAO,QAAQ;AACxC;;;ACnCA,IAAAC,eAKO;;;ACiCP,IAAM,YAAY,OAAO,MAAM,CAAC;;;ADyChC,IAAMC,aACJ,WACA,uBAAO,IAAI,iCAAiC,CAAC,MAC7C,oBAAI,IAAI;AAMH,SAAS,mBACd,UACY;AACZ,EAAAA,WAAU,IAAI,QAAQ;AACtB,SAAO,MAAMA,WAAU,OAAO,QAAQ;AACxC;AAyKA,IAAM,QACJ,WACA,uBAAO,IAAI,6BAA6B,CAAC,MAAM,oBAAI,QAAQ;AAwd7D,IAAM,QAAkC,WACtC,uBAAO,IAAI,6BAA6B,CAC1C,MAAM,oBAAI,QAAQ;AAQlB,IAAM,iBACJ,WACA,uBAAO,IAAI,qCAAqC,CAAC,MACjD,oBAAI,QAAQ;;;AE9uBd,IAAAC,iBAA2B;AA2BpB,IAAM,cAAN,MAAkB;AAAA,EACvB;AAAA,EAEA,YAAY,MAAiD;AAC3D,SAAK,QAAQ;AAAA,EACf;AAAA,EAEA,OAAO,OAAyB;AAC9B,QAAI;AACF,WAAK,MAAM;AAAA,QACT;AAAA,UACE,YAAY;AAAA,UACZ,mBAAmB,MAAM;AAAA,UACzB,gBAAgB,MAAM,UAAU;AAAA,UAChC,kBAAkB,MAAM,YAAY;AAAA,UACpC,eAAe,MAAM;AAAA,UACrB,gBAAgB,MAAM;AAAA,UACtB,kBAAkB,MAAM;AAAA,UACxB,gBAAgB,MAAM;AAAA,UACtB,kBAAkB,MAAM;AAAA,UACxB,wBAAwB,MAAM,eAAe,KAAK,GAAG;AAAA,UACrD,mBAAmB,MAAM;AAAA,UACzB,OAAO;AAAA,QACT;AAAA,QACA,SAAS,MAAM,SAAS,IAAI,MAAM,MAAM,IAAI,MAAM,KAAK,IAAI,MAAM,MAAM;AAAA,MACzE;AAAA,IACF,SAAS,OAAgB;AACvB,cAAQ,MAAM,sCAAsC,KAAK;AAAA,IAC3D;AAAA,EACF;AAAA,EAEA,OAAO,SAAS,MAAkD;AAChE,QAAI,SAAS,UAAa,SAAS,QAAQ,SAAS,IAAI;AACtD,aAAO;AAAA,IACT;AACA,eAAO,2BAAW,QAAQ,EAAE,OAAO,IAAI,EAAE,OAAO,KAAK;AAAA,EACvD;AACF;;;ALlDO,SAAS,eAAwB;AACtC,aAAO,0BAAU,kBAAkB,MAAM;AAC3C;AAEA,IAAM,UAAU,oBAAI,QAA6B;AACjD,SAAS,UAAU,MAAiD;AAClE,MAAIC,UAAS,QAAQ,IAAI,IAAI;AAC7B,MAAI,CAACA,SAAQ;AACX,IAAAA,UAAS,IAAI,YAAY,IAAI;AAC7B,YAAQ,IAAI,MAAMA,OAAM;AAAA,EAC1B;AACA,SAAOA;AACT;AAGO,SAAS,eAAe,QAAyC;AACtE,MAAI,WAAW,IAAK,QAAO;AAC3B,MAAI,WAAW,IAAK,QAAO;AAC3B,MAAI,WAAW,IAAK,QAAO;AAC3B,SAAO;AACT;AAEA,IAAM,OAAO,CAAC,UACZ,OAAO,UAAU,YAAY,QAAQ,QAAQ;AAE/C,SAAS,SAAS,MAAmC;AACnD,MAAI,QAAQ,QAAQ,SAAS,GAAI,QAAO;AACxC,MAAI,OAAO,SAAS,YAAY,OAAO,SAAS,IAAI,EAAG,QAAO,OAAO,IAAI;AACzE,MAAI;AACF,WAAO,KAAK,UAAU,IAAI;AAAA,EAC5B,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAGO,SAAS,mBACd,MACA,KAOA,QACA,YACM;AACN,MAAI,CAAC,QAAQ,CAAC,aAAa,EAAG;AAC9B,QAAM,UACJ,IAAI,WAAW,OAAO,IAAI,YAAY,WACjC,IAAI,UACL;AACN,YAAU,IAAI,EAAE,OAAO;AAAA,IACrB,YAAW,oBAAI,KAAK,GAAE,YAAY;AAAA,IAClC,QAAQ,KAAK,SAAS,GAAG,KAAK,KAAK,SAAS,MAAM;AAAA,IAClD,UACE,KAAK,SAAS,oBAAoB,KAAK,KAAK,SAAS,cAAc;AAAA,IACrE,OAAO,IAAI,gBAAgB,IAAI,QAAQ;AAAA,IACvC,QAAQ,IAAI;AAAA,IACZ,UAAU,YAAY,SAAS,SAAS,IAAI,IAAI,CAAC;AAAA,IACjD;AAAA,IACA,UAAU,KAAK,IAAI,GAAG,KAAK,MAAM,UAAU,CAAC;AAAA,IAC5C,gBAAgB,CAAC;AAAA,IACjB,WAAW,eAAe,MAAM;AAAA,EAClC,CAAC;AACH;AAEA,IAAI;AASG,SAAS,sBACd,MACY;AACZ,MAAI,CAAC,eAAe,aAAa,GAAG;AAClC,UAAMA,UAAS,UAAU,IAAI;AAC7B,UAAM,SAAS;AAAA,MAAmB,CAAC,UACjCA,QAAO,OAAO;AAAA,QACZ,YAAW,oBAAI,KAAK,GAAE,YAAY;AAAA,QAClC,QAAQ;AAAA,QACR,UAAU,MAAM,YAAY;AAAA,QAC5B,OAAO,MAAM;AAAA,QACb,QAAQ;AAAA,QACR,UAAU;AAAA,QACV,QAAQ;AAAA,QACR,UAAU;AAAA,QACV,gBAAgB,CAAC,MAAM,KAAK;AAAA,QAC5B,WAAW;AAAA,MACb,CAAC;AAAA,IACH;AACA,UAAM,gBAAgB;AAAA,MAAmB,CAAC,UACxCA,QAAO,OAAO;AAAA,QACZ,YAAW,oBAAI,KAAK,GAAE,YAAY;AAAA,QAClC,QAAQ;AAAA,QACR,UAAU,MAAM;AAAA,QAChB,OAAO,GAAG,MAAM,MAAM,IAAI,MAAM,EAAE;AAAA,QAClC,QAAQ,MAAM,OAAO,YAAY;AAAA,QACjC,UAAU;AAAA,QACV,QAAQ;AAAA,QACR,UAAU;AAAA,QACV,gBAAgB,MAAM;AAAA,QACtB,WAAW;AAAA,MACb,CAAC;AAAA,IACH;AACA,kBAAc,MAAM;AAClB,aAAO;AACP,oBAAc;AACd,oBAAc;AAAA,IAChB;AAAA,EACF;AACA,SAAO,gBAAgB,MAAM;AAC/B;;;ADnFO,SAAS,cAad,MACA,iBACA,eACA,iBAEA,wBACA,eAeA;AACA,SAAO,CAAC,KAAK,KAAK,SAAU;AAC1B,QAAI,eAAe;AACnB,QAAI,kBAAkB;AACtB,QAAI,gBAAgB;AACpB,QAAI,kBAAkB;AACtB,QAAI,yBAAyB;AAC7B,QAAI,iBAAiB,kBAAkB,MAAM;AAE7C,QAAI,SAAS,MAAM,aAAa,eAAe,IAAI,iBAAiB,IAAI;AACxE,UAAM,YAAY,QAAQ,OAAO;AACjC,QAAI,uBAAwB,uBAAsB,sBAAsB;AAExE,QAAI,GAAG,UAAU,MAAM;AAErB,YAAM,CAAC,cAAc,gBAAgB,IAAI,QAAQ,OAAO,SAAS;AACjE;AAAA,QACE;AAAA,QACA;AAAA,QACA,OAAO,IAAI,UAAU;AAAA,QACrB,eAAe,MAAO,mBAAmB;AAAA,MAC3C;AACA,YAAM,CAAC,SAAS,WAAW,IAAI,QAAQ,OAAO,SAAS;AACvD,YAAM,aAAa,UAAU,cAAc;AAE3C,kCAA4B,OAAO,YAAY;AAAA,QAC7C,CAAC,6CAAiB,OAAG,0BAAU,mBAAmB,KAAK;AAAA,QACvD,CAAC,mBAAmB,OAAG,0BAAU,qBAAqB;AAAA,QACtD,CAAC,aAAa,GAAG,IAAI,iBAAiB,QAAQ;AAAA,QAC9C,CAAC,oDAAwB,GAAG,IAAI;AAAA,QAChC,CAAC,2CAAe,GAAG,IAAI,gBAAgB;AAAA,QACvC,CAAC,0DAA8B,GAAG,OAAO,IAAI,UAAU;AAAA,MACzD,CAAC;AAAA,IACH,CAAC;AAED,WAAO;AAAA,EACT;AACF;;;AOvHA,IAAAC,kBAAyB;AACzB,IAAAC,oBAKO;;;ACOA,SAAS,QACd,KAC0C;AAC1C,SAAO,OAAO,QAAQ,YAAY,QAAQ,QAAQ,UAAU;AAC9D;;;ACfO,SAAS,eACd,oBACmE;AACnE,SACE,sBAAsB,SACrB,UAAU,sBACT,WAAW,sBACX,YAAY,sBACZ,aAAa;AAEnB;;;AFiBO,SAAS,MAYd,KASA,KAOA,MACA;AACA,QAAM,gBAAgB,IAAI,iBAAiB;AAC3C,QAAM,mBACJ,IAAI,gBAAgB,SAAS,sBAC5B,eAAe,eAAe,QAC3B,SACA,eAAe,YAAY;AAOjC,MAAI,aAAa,IAAI;AAErB,QAAM,UAAU;AAAA,IACd,QAAQ,IAAI;AAAA,IACZ,OAAO,IAAI;AAAA,IACX,SAAS,IAAI;AAAA,IACb,MAAM,IAAI;AAAA,EACZ;AAEA,QAAM,kBAAkB,IAAI;AAE5B,MAAI;AAEJ,MAAI;AACJ,MAAI;AAEJ,MAAI,IAAI,gBAAgB,UAAU;AAChC,YAAI,0BAAS,IAAI,aAAa,GAAG;AAC/B,UAAI,qBAA6B;AACjC,wBAAkB,CAAC;AAEnB,aAAO,QAAQ,IAAI,aAAa,EAAE,QAAQ,CAAC,CAAC,SAAS,MAAM,MAAM;AAC/D,cAAM,gBAAgB,gBAAgB,MAAM,QAAQ,OAAO;AAE3D,YAAI,cAAc,IAAI;AACpB,0BAAgB;AAChB,0BAAgB,KAAK,OAAO;AAC5B,cAAI,UAAU;AACd,cAAI,UAAU,IAAI;AAAA,QACpB,OAAO;AACL,oCAAsB;AAAA,YACpB,cAAc;AAAA,YACd,WAAW,OAAO;AAAA,UACpB;AAAA,QACF;AAAA,MACF,CAAC;AAED,UAAI,CAAC,eAAe;AAClB,wBAAgB;AAAA,UACd,IAAI;AAAA,UACJ,QAAQ,CAAC;AAAA,QACX;AACA,+BAAuB;AAAA,MACzB;AAAA,IACF,OAAO;AACL,UAAI,UAAU,OAAO,KAAK,IAAI,gBAAgB,QAAQ,EAAE,IAAI;AAI5D,UAAI,UAAU,IAAI;AAElB,sBAAgB;AAAA,QACd,IAAI;AAAA,QACJ,OAAO;AAAA,MACT;AAEA,wBAAkB,OAAO,KAAK,IAAI,gBAAgB,QAAQ;AAAA,IAC5D;AAAA,EACF,OAAO;AACL,UAAM,gBAAgB,gBAAgB,MAAM,IAAI,eAAe,OAAO;AAEtE,oBAAgB;AAEhB,sBAAkB;AAAA,EACpB;AAEA,MACE,cAAc,MACd,eAAiD,cAAc,KAAK,GACpE;AACA,QAAI,OAAO,cAAc,MAAM;AAC/B,QAAI,SAAS,cAAc,MAAM;AACjC,WAAO,eAAe,KAAK,SAAS;AAAA,MAClC,OAAO,cAAc,MAAM;AAAA,MAC3B,UAAU;AAAA,MACV,YAAY;AAAA,MACZ,cAAc;AAAA,IAChB,CAAC;AACD,UAAM,gBAAgB,cAAc,MAAM,WAAW,CAAC;AACtD,QAAI,UAAU,OAAO,KAAK,IAAI,OAAO,EAAE;AAAA,MACrC,CAAC,KAAK,QAAQ;AACZ,YAAI,gBAAgB,GAAG,GAAG;AACxB,cAAI,GAAG,IAAI,cAAc,GAAG;AAAA,QAC9B,OAAO;AACL,cAAI,GAAG,IAAI,IAAI,QAAQ,GAAG;AAAA,QAC5B;AACA,eAAO;AAAA,MACT;AAAA,MACA,CAAC;AAAA,IACH;AAAA,EACF;AACA,MAAI,CAAC,cAAc,IAAI;AACrB,YAAQ,kBAAkB;AAAA,MACxB;AAAA,MACA,KAAK;AAAA,MACL,KAAK;AACH,YAAI,KAAK,kBAAkB;AAC3B,YAAI,OAAO,GAAG;AACd,YAAI,QAAQ,GAAG,GAAG;AAChB,cAAI;AAAA,YACF,GACE,4BACA,0CAAuB,cAAc,QAAQ,SAAS,CACxD;AAAA;AAAA,kBACE,IAAI,QAAQ,iBAAiB,mBAC/B;AAAA,UACF;AAAA,QACF,OAAO;AACL,iBAAO,IAAI,MAAM,0BAA0B,CAAC;AAAA,QAC9C;AACA;AAAA,MACF,KAAK;AACH,YAAI,wBAAwB;AAAA,UAC1B,4BACE,0CAAuB,cAAc,QAAQ,SAAS;AAAA,QAC1D;AACA;AAAA,MACF,KAAK;AACH;AAAA,IACJ;AAAA,EACF;AAEA,MAAI,kBAAkB;AACtB,SAAO;AACT;;;ApBtJO,SAAS,kCA2Bd,2CAmBA,uCAmBA;AACA,MAAI;AAgBJ,MAAI,WAcE,CAAC;AAEP,MACE,eAiBE,yCAAyC,GAC3C;AACA,sBAAkB,0CAA0C;AAC5D,eACE,0CAA0C;AAAA,EAe9C,OAAO;AACL,UAAM,oBACJ,sCACE,sCAAsC,SAAS,CACjD;AACF,QACE,eAiBE,iBAAiB,GACnB;AACA,wBAAkB,kBAAkB;AACpC,YAAM,uBAAuB,kBAAkB;AAC/C,YAAM,gBAkBA,CAAC;AAEP,UACE,2BAeE,yCAAyC,GAC3C;AACA,sBAAc,KAAK,yCAAyC;AAAA,MAC9D;AACA,oBAAc,KAAK,GAAG,sCAAsC,MAAM,GAAG,EAAE,CAAC;AACxE,oBAAc;AAAA,QACZ,GAAI;AAAA,MAiCN;AAEA,iBAAY,cAA4B;AAAA,QAAO,CAAC,YAC9C,2BAeE,OAAO;AAAA,MACX;AAAA,IAeF,OAAO;AACL,UACE,2BAA2B,yCAAyC,KACpE,eAiBE,yCAAyC,GAC3C;AACA,cAAM,IAAI,MAAM,kCAAkC;AAAA,MACpD;AACA,wBACE;AAgBF,iBAAY,sCAAoD;AAAA,QAC9D,CAAC,YACC,2BAeE,OAAO;AAAA,MACb;AAAA,IAeF;AAAA,EACF;AAEA,SAAO,EAAE,iBAAiB,SAAS;AACrC;AAEO,SAAS,wBAuBd,iBAeA,iBACA;AACA,MACE,CAAC,sBAaC,eAAe,KACjB,CAAC,+BAeC,eAAe,GACjB;AACA,UAAM,IAAI,MAAM,qDAAqD;AAAA,EACvE;AAGA,QAAM,SAAU,gBAA4C,QAAQ;AAEpE,QAAM,OAAQ,gBAA4C,MAAM;AAEhE,MAAI,UAAU,MAAM;AAClB,UAAM,cAAc,CAAC,UAAU,iBAAiB,aAAa,UAAU;AACvE,QAAI,CAAC,YAAY,SAAS,MAAM,GAAG;AACjC,YAAM,IAAI;AAAA,QACR,UAAU,gBAAgB,IAAI,4BAA4B,MAAM,sBAC3C,YAAY,KAAK,IAAI,CAAC;AAAA,MAC7C;AAAA,IACF;AAEA,QAAI,WAAW,YAAY,QAAQ,MAAM;AACvC,YAAM,IAAI;AAAA,QACR,UAAU,gBAAgB,IAAI;AAAA,MAChC;AAAA,IACF;AAEA,QAAI,WAAW,aAAa;AAC1B,UAAI,CAAC,MAAM;AACT,cAAM,IAAI;AAAA,UACR,UAAU,gBAAgB,IAAI;AAAA,QAChC;AAAA,MACF;AACA,UACE,CAAC,oBAAoB,IAAI,KACzB,CAAC,cAAc,IAAI,KACnB,CAAC,eAAe,IAAI,GACpB;AACA,cAAM,IAAI;AAAA,UACR,UAAU,gBAAgB,IAAI;AAAA,QAEhC;AAAA,MACF;AAAA,IACF;AAEA,QAAI,WAAW,YAAY;AACzB,UAAI,CAAC,QAAQ,CAAC,aAAa,IAAI,GAAG;AAChC,cAAM,IAAI;AAAA,UACR,UAAU,gBAAgB,IAAI;AAAA,QAChC;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAEA,MAAI,gBAAgB,UAAU;AAC5B,UAAM,cAAc,OAAO,OAAO,gBAAgB,QAAQ,EAAE;AAAA,MAC1D,CAAC,YAAY,iBAAiB,iBAAiB,QAAQ,IAAI,GAAG;AAAA,IAChE;AAEA,UAAM,qBACJ,YAAY,WAAW,KACvB,YAAY,MAAM,CAAC,OAAO,OAAO,YAAY,CAAC,CAAC;AAEjD,QAAI,CAAC,oBAAoB;AACvB,YAAM,IAAI;AAAA,QACR;AAAA,MACF;AAAA,IACF;AAAA,EACF;AACF;AAEO,SAAS,yBAId,iBACA,mBAOA,aACA;AACA,QAAM,kBAAkB;AAAA,IACtB,KAAK,gBAAgB;AAAA,IACrB,KAAK,gBAAgB;AAAA,IACrB,KAAK,gBAAgB;AAAA,IACrB,KAAK,gBAAgB;AAAA,IACrB,KAAK,gBAAgB;AAAA,IACrB,GAAG,OAAO;AAAA,MACR,OAAO;AAAA,QACL,2BAA2B,iBAAiB,kBAAkB,SAAS;AAAA,MACzE,EAAE,IAAI,CAAC,CAAC,KAAK,KAAK,MAAM,CAAC,OAAO,GAAG,GAAG,MAAM,MAAM,CAAC;AAAA,IACrD;AAAA,EACF;AAEA,SAAO;AAAA,IACL,eAAe,gBAAgB;AAAA,MAC7B,gBAAgB,SAAS;AAAA,QACvB,GAAI,eAAe,OACf,EAAE,QAAQ,YAAgC,IAC1C,EAAE,QAAQ,gBAAgB,QAA4B;AAAA,QAC1D,GAAI,kBAAkB,kBAAkB,OACpC,EAAE,SAAS,kBAAkB,eAAe,IAC5C,EAAE,SAAS,gBAAgB,QAA6B;AAAA,QAC5D,GAAI,kBAAkB,SAAS,OAC3B,EAAE,OAAO,kBAAkB,MAAM,IACjC,EAAE,OAAO,gBAAgB,QAA2B;AAAA,QACxD,GAAI,kBAAkB,QAAQ,OAC1B;AAAA,UACE,MAAM,iBAAiB,iBAAiB,kBAAkB,IAAI,GAC1D;AAAA,QACN,IACA,EAAE,MAAM,gBAAgB,QAAoB;AAAA,MAClD,CAAC;AAAA,IACH;AAAA,IACA,iBAAiB;AAAA,MACf,GAAI,kBAAkB,mBAAmB,OACrC;AAAA,QACE,SAAS,gBAAgB;AAAA,UACvB,gBAAgB,SAAS,kBAAkB,eAAe;AAAA,QAC5D;AAAA,MACF,IACA,EAAE,SAAS,gBAAgB,QAA6B;AAAA,MAC5D,WAAW,OAAO;AAAA,QAChB,OAAO,QAAQ,eAAe,EAAE,IAAI,CAAC,CAAC,KAAK,KAAK,MAAM;AAAA,UACpD;AAAA,UACA,gBAAgB,QAAQ,gBAAgB,SAAS,KAAK,CAAC;AAAA,QACzD,CAAC;AAAA,MACH;AAAA,IACF;AAAA,EACF;AACF;AAEO,SAAS,oBAuBd,iBAeA,iBACA;AACA,QAAM,YAAY;AAClB,MAAI;AACJ,MAAI;AAGJ,MAAI,mBAAmB,eAAe,GAAG;AACvC,oBAAgB,CAAC;AACjB,sBAAkB,CAAC;AAEnB,WAAO,QAAQ,gBAAgB,YAAY,CAAC,CAAC,EAAE;AAAA,MAC7C,CAAC,CAAC,SAAS,wBAAwB,MAAM;AACvC,cAAM;AAAA,UACJ,eAAe;AAAA,UACf,iBAAiB;AAAA,QACnB,IAAI;AAAA,UACF;AAAA,UACA;AAAA,UACA,gBAAgB;AAAA,QAClB;AAEA,gBAAI,0BAAS,aAAa,GAAG;AAC3B,0BAAgB;AAAA,YACd,GAAG;AAAA,YACH,CAAC,OAAO,GAAG;AAAA,UACb;AAAA,QACF;AACA,gBAAI,0BAAS,eAAe,GAAG;AAC7B,4BAAkB;AAAA,YAChB,GAAG;AAAA,YACH,CAAC,OAAO,GAAG;AAAA,UACb;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAAA,EACF,OAAO;AACL,UAAM;AAAA,MACJ,eAAe;AAAA,MACf,iBAAiB;AAAA,IACnB,IAAI;AAAA,MACF;AAAA,MACA;AAAA,QACE,GAAI,YAAY,mBAAmB,gBAAgB,UAAU,OACzD,EAAE,QAAQ,gBAAgB,OAAO,IACjC,EAAE,QAAQ,UAAU,QAA4B;AAAA,QACpD,GAAI,oBAAoB,mBACxB,gBAAgB,kBAAkB,OAC9B,EAAE,gBAAgB,gBAAgB,eAAe,IACjD;AAAA,UACE,gBAAgB,UAAU;AAAA,QAC5B;AAAA,QACJ,GAAI,qBAAqB,mBACzB,gBAAgB,mBAAmB,OAC/B,EAAE,iBAAiB,gBAAgB,gBAAgB,IACnD;AAAA,UACE,iBAAiB,UAAU;AAAA,QAC7B;AAAA,QACJ,GAAI,WAAW,mBAAmB,gBAAgB,SAAS,OACvD,EAAE,OAAO,gBAAgB,MAAM,IAC/B;AAAA,UACE,OAAO,UAAU;AAAA,QACnB;AAAA,QACJ,GAAI,UAAU,mBAAmB,gBAAgB,QAAQ,OACrD,EAAE,MAAM,gBAAgB,KAAK,IAC7B;AAAA,UACE,MAAM,UAAU;AAAA,QAClB;AAAA,QACJ,WACE,eAAe,mBAAmB,gBAAgB,aAAa,OAC3D,gBAAgB,YACf,UAAU;AAAA,MACnB;AAAA,MACA,gBAAgB;AAAA,IAClB;AAEA,oBAAgB;AAChB,sBAAkB;AAAA,EACpB;AAEA,SAAO,EAAE,eAAe,gBAAgB;AAC1C;AAEO,SAAS,wBA2Bd,QA0DA;AACA,QAAM,eAAe,CAAC,GAAG,OAAO,QAAQ;AACxC,QAAM,oBAAoB,aAAa,IAAI;AAE3C,MAAI,OAAO,sBAAsB,YAAY;AAC3C,UAAM,IAAI;AAAA,MACR,8CAA8C,iBAAiB;AAAA,IACjE;AAAA,EACF;AAEA,QAAM,cAAc;AAAA,IAClB,GAAI,OAAO,yBAAyB,QAAQ,CAAC,aAAa,IAAI,CAAC;AAAA,IAC/D;AAAA,MAaE,GAAG,OAAO,QAAQ,GAAG,OAAO,IAAI;AAAA,MAChC,OAAO;AAAA,MACP,OAAO;AAAA,MACP,OAAO;AAAA,MACP,OAAO;AAAA;AAAA,MAEP,MAAO,OAAO,SAAS,OAAO,OAAO,gBAAgB,OAAO;AAAA,IAC9D;AAAA,IACA,GAAI,OAAO;AAAA,IACX;AAAA,IACA;AAAA,IAaA,GAAG;AAAA,EACL;AAEA,SAAO;AAAA,IACL;AAAA,IACA;AAAA,EAeF;AACF;;;AjB5vBO,SAAS,qBA2Bd,QA+DA;AACA,QAAM,kBAAkB,OAAO;AAE/B,QAAM,EAAE,iBAAiB,SAAS,IAAI;AAAA,IAmBpC,OAAO;AAAA,IACP,OAAO;AAAA,EACT;AAEA,0BAAwB,iBAAiB,eAAe;AAExD,QAAM,EAAE,eAAe,gBAAgB,IAAI;AAAA,IACzC;AAAA,IACA;AAAA,EACF;AAEA,QAAM,EAAE,aAAa,kBAAkB,IAAI,wBAmBzC;AAAA,IACA,UAAU,OAAO;AAAA,IACjB,MAAM,OAAO;AAAA,IACb;AAAA,IACA;AAAA,IACA;AAAA,IACA,wBAAwB,OAAO;AAAA,IAC/B,eAAe,OAAO;AAAA,IACtB,sBAAsB,OAAO,wBAAwB,CAAC;AAAA,IACtD;AAAA,IACA,sBAAsB;AAAA,EACxB,CAAC;AAED,SAAO;AAAA,IACL,aAAa;AAAA,MACX,cAAc,eAAe;AAAA,MAC7B,GAAG;AAAA,IACL;AAAA,IACA;AAAA,EACF;AACF;AAwBA,IAAI,2BAA2B;AAE/B,SAAS,uBACP,wBACM;AACN,MAAI,0BAA0B;AAC5B;AAAA,EACF;AACA,6BAA2B;AAE3B,UAAQ,GAAG,qBAAqB,CAAC,QAAQ;AACvC,2BAAuB,MAAM,uBAAuB,GAAG,EAAE;AACzD,YAAQ,KAAK,CAAC;AAAA,EAChB,CAAC;AACD,UAAQ,GAAG,sBAAsB,CAAC,WAAW;AAC3C,2BAAuB,MAAM,wBAAwB,MAAM,EAAE;AAC7D,YAAQ,KAAK,CAAC;AAAA,EAChB,CAAC;AAED,UAAQ,GAAG,QAAQ,MAAM;AACvB,2BAAuB,KAAK,2BAA2B;AAAA,EACzD,CAAC;AACD,UAAQ,GAAG,UAAU,MAAM;AACzB,2BAAuB,KAAK,2BAA2B;AACvD,YAAQ,KAAK,CAAC;AAAA,EAChB,CAAC;AACH;AAMO,SAAS,iCAAuC;AACrD,6BAA2B;AAC7B;AAEO,IAAM,8BAAN,MAAM,6BAW+C;AAAA,EAU1D,YACW,UACA,iBACA,UACA,sBACA,wBACA,eACT;AANS;AACA;AACA;AACA;AACA;AACA;AAET,QACE,QAAQ,IAAI,aAAa,UACzB,CAAC,QAAQ,IAAI,UACb,QAAQ,IAAI,oBAAoB,WAChC;AACA,6BAAuB,KAAK,sBAAsB;AAAA,IACpD;AAEA,SAAK,SAAS,IAAI,cAAc,KAAK,eAAe,CAAkB;AAAA,EACxE;AAAA,EAhBW;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EAfX;AAAA,EACA,UAAkC,CAAC;AAAA,EACnC,SAAgC,CAAC;AAAA,EAEjC,YAAsB,CAAC;AAAA,EACvB,MAAW,CAAC;AAAA,EAEZ,WAAmC,CAAC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAwCpC,8BAYE,gBA+BA;AACA,WAAO,OAAO,KAAK,KAAK,SAAS;AAC/B,UAAI,CAAC,gBAAgB;AACnB,cAAM,IAAI,MAAM,mCAAmC;AAAA,MACrD;AAEA,UAAI;AACF,cAAM,eAAe,KAAK,KAAK,IAAI;AAAA,MACrC,SAAS,OAAO;AACd,YAAI,QAAQ,OAAO,SAAS,YAAY;AACtC,eAAK,KAAc;AAAA,QACrB,OAAO;AACL,gBAAM;AAAA,QACR;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAuBA,QAA0C,OAKxC,SACG,YAsDA;AACH,UAAM,SAAS,QAAQ,CAAC,GAAG;AAC3B,UAAM,UACJ,QAAQ,CAAC,KAAK,QAAQ,aAAa,QAAQ,CAAC,IACxC,QAAQ,CAAC,EAAE,UACX;AAEN,YACG,UACG,KAAK,UAAU,IAAI,EAAE,UAAW,KAAgB,EAAE,OAAO,IACzD,KAAK,UAAU,IAAI,EAAE,UAAW,KAAgB;AAAA,MAKpD;AAAA,MACA,QAAQ,CAAC;AAAA;AAAA,IAEX;AAAA,EAKF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,mBACE,aACA,mBACA,iBACA,eACA,iBACA,SACA;AACA,WAAO,OACL,OACA,YAOG;AACH,UAAI;AACJ,UAAI;AACJ,YAAM,kBAA2C,CAAC;AAClD,YAAM,mBACJ,CAAC;AAEH,YAAM,MAAM;AAAA,QACV,QAAQ,SAAS,UAAU,CAAC;AAAA,QAC5B,OAAO,SAAS,SAAS,CAAC;AAAA,QAC1B,SAAS,SAAS,WAAW,CAAC;AAAA,QAC9B,MACE,iBAAiB,KAAK,iBAAiB,SAAS,IAAI,GAAG,UAAU,CAAC;AAAA,QACpE,MAAM;AAAA,QACN,cAAc;AAAA,QACd,QAAQ;AAAA,QACR;AAAA,QACA,iBAAiB,KAAK;AAAA,QACtB;AAAA,QACA;AAAA,QACA,wBAAwB,KAAK;AAAA,QAC7B,gBAAgB,MAAM,KAAK;AAAA,QAC3B,SAAS;AAAA,UACP,eAAe,iBAAiB,KAAK,IAAI;AAAA,UACzC,MAAM;AAAA,QACR;AAAA,QACA,UAAU;AAAA,QACV,iBAAiB;AAAA,MACnB;AAEA,YAAM,MAAM;AAAA,QACV,YAAY;AAAA,QACZ,QAAQ,CAAC,SAAiB;AACxB,uBAAa;AACb,cAAI,aAAa;AACjB,iBAAO;AAAA,QACT;AAAA,QACA,MAAM,CAAC,YAAoB;AACzB,4BAAkB;AAClB,2BAAiB,QAAQ,GAAG,QAAQ,CAAC,YAAY,QAAQ,CAAC;AAAA,QAC5D;AAAA,QACA,MAAM,CAAC,SAAkC;AACvC,4BAAkB;AAClB,2BAAiB,QAAQ,GAAG,QAAQ,CAAC,YAAY,QAAQ,CAAC;AAAA,QAC5D;AAAA,QACA,OAAO,CAAC,SAAkC;AACxC,4BAAkB;AAClB,2BAAiB,QAAQ,GAAG,QAAQ,CAAC,YAAY,QAAQ,CAAC;AAAA,QAC5D;AAAA,QACA,WAAW,CAAC,KAAa,UAAkB;AACzC,0BAAgB,GAAG,IAAI;AACvB,iBAAO;AAAA,QACT;AAAA,QACA,WAAW,CAAC,QAAgB,gBAAgB,GAAG;AAAA,QAC/C,MAAM,CAAC,gBAAwB;AAC7B,0BAAgB,cAAc,IAAI;AAClC,iBAAO;AAAA,QACT;AAAA,QACA,YAAY,CACV,cACG;AACH,4BAAkB,UAAU;AAAA,QAC9B;AAAA,QACA,IAAI,CAAC,OAAe,YAA0C;AAC5D,cAAI,CAAC,iBAAiB,KAAK,GAAG;AAC5B,6BAAiB,KAAK,IAAI,CAAC;AAAA,UAC7B;AACA,2BAAiB,KAAK,EAAE,KAAK,OAAO;AACpC,iBAAO;AAAA,QACT;AAAA,QACA;AAAA,QACA;AAAA,MACF;AAEA,YAAM,qBAAqB,SAAS,sBAAsB;AAE1D,UAAI,sBAAsB,YAAY,SAAS,GAAG;AAChD,cAAM,cAAc,CAAC,GAAG,WAAW;AACnC,YAAI,SAAS,YAAY,MAAM;AAM/B,YAAI,QAAQ;AACV,qBAAW,MAAM,aAAa;AAC5B,kBAAM,OAAO,KAAK,KAAK,CAAC,QAAgB;AACtC,kBAAI,KAAK;AACP,sBAAM;AAAA,cACR;AACA,uBAAS;AAAA,YAKX,CAAC;AAAA,UACH;AACA,gBAAM,OAAO,KAAK,KAAK,OAAO,QAAgB;AAC5C,gBAAI,KAAK;AACP,oBAAM;AAAA,YACR;AAAA,UACF,CAAC;AAAA,QACH;AAAA,MACF;AAEA,YAAM,WAAW;AAKjB,YAAM,SAAS,KAAK,KAAK,CAAC,QAAgB;AACxC,YAAI,KAAK;AACP,gBAAM;AAAA,QACR;AAAA,MACF,CAAC;AAED,aAAO;AAAA,QACL,MAAM,OAAO,UAAU;AAAA,QACvB,UAAU;AAAA,QACV,SAAS;AAAA,MACX;AAAA,IACF;AAAA,EACF;AAAA,EAEA,cAsBE,QACA,MACA,oBACA,8CAmBG,uCAwFH;AAEA,UAAM,EAAE,iBAAiB,SAAS,IAAI;AAAA,MAmBpC;AAAA,MACA;AAAA,IACF;AAEA,4BAAwB,iBAAiB,KAAK,eAAe;AAE7D,SAAK,OAAO,KAAK;AAAA,MACf,UAAU,KAAK;AAAA,MACf;AAAA,MACA;AAAA,MACA;AAAA,IACF,CAAC;AAED,UAAM,EAAE,eAAe,gBAAgB,IAAI;AAAA,MACzC;AAAA,MACA,KAAK;AAAA,IACP;AAEA,UAAM,EAAE,aAAa,kBAAkB,IAAI,wBAmBzC;AAAA,MACA,UAAU,KAAK;AAAA,MACf;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA,wBAAwB,KAAK;AAAA,MAC7B,eAAe,KAAK;AAAA,MACpB,sBAAsB,KAAK;AAAA,MAC3B,sBAAsB;AAAA,MACtB;AAAA,MACA,QAAQ;AAAA,IACV,CAAC;AAED,uBAAmB,KAAK,KAAK,QAAQ;AAAA,MACnC;AAAA,MACA,GAAI;AAAA,MACJ,KAAK,8BAA8B,iBAAiB;AAAA,IACtD;AAEA,kCAAS,KAAK,SAAS,MAAE,qCAAoB,GAAG,KAAK,QAAQ,GAAG,IAAI,EAAE,CAAC,IAAI;AAAA,MACzE,GAAI,KAAK,cAAU,qCAAoB,GAAG,KAAK,QAAQ,GAAG,IAAI,EAAE,CAAC,KAAK,CAAC;AAAA,MACvE,CAAC,OAAO,YAAY,CAAC,GAAG,gBAAgB,WACpC,OAAO;AAAA,QACL,OAAO,KAAK,gBAAgB,QAAQ,EAAE,IAAI,CAAC,YAAY;AAAA,UACrD;AAAA,UACA,KAAK;AAAA,YACH;AAAA,YACA;AAAA,YACA;AAAA,YACA;AAAA,YACA;AAAA,YACA;AAAA,UACF;AAAA,QACF,CAAC;AAAA,MACH,IACA,KAAK;AAAA,QACH;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,MACF;AAAA,IACN;AAEA,UAAM,sBAAsB,gBAAgB;AAC5C,QAAI,qBAAqB;AACvB,oCAAS,KAAK,GAAG,MAAE,mCAAkB,mBAAmB,CAAC,IACvD,gBAAgB,WACZ,OAAO;AAAA,QACL,OAAO,KAAK,gBAAgB,QAAQ,EAAE,IAAI,CAAC,YAAY;AAAA,UACrD;AAAA,UACA,CAAC,QAMC,KAAK;AAAA,YACH;AAAA,YACA;AAAA,YACA;AAAA,YACA;AAAA,YACA;AAAA,YACA;AAAA,UACF,EAAE,GAAG,KAAK,QAAQ,GAAG,IAAI,IAAI,GAAG;AAAA,QACpC,CAAC;AAAA,MACH,IACA,CAAC,QAMC,KAAK;AAAA,QACH;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,MACF,EAAE,GAAG,KAAK,QAAQ,GAAG,IAAI,IAAI,GAAG;AAAA,IAC1C;AACA,WAAO;AAAA,EAkET;AAAA,EAEA,iBAsBE,UAuBA,mBACA;AACA,UAAM,OAAO,SAAS,IAAI;AAC1B,QAAI,gBAAgB,OAAO,CAAC,IAAI,IAAI,CAAC;AACrC,QACE,eAiBE,IAAI,GACN;AACA,sBAAgB,KAAK;AAAA,IACvB;AAEA,aAAS,QAAQ,CAAC,YAAY;AAC5B,UACE,eAiBE,OAAO,GACT;AACA,cAAM,IAAI;AAAA,UACR;AAAA,QACF;AAAA,MACF;AAAA,IACF,CAAC;AAED,UAAMC,cAAa,oBACf,SAAS,IAAI,iBAAiB,IAC7B;AAEL,WAAO,CAAC,GAAGA,aAAY,GAAG,aAAa;AAAA,EACzC;AAAA,EAEA,gDAqBE,UAsBA;AACA,WAAO,KAAK,iBAaV,QAAQ;AAAA,EACZ;AAAA,EAEA,wDAqBE,UAsBA;AACA,WAAO,KAAK,iBAaV,UAAU,CAAC,YAAY;AACvB,UACE,8BAUE,OAAO,GACT;AACA,aAAK,eAAe,OAAO;AAC3B,eAAO,QAAQ;AAAA,MACjB;AACA,aAAO;AAAA,IACT,CAAC;AAAA,EACH;AAAA,EAEA,iCAqBE,SAsBAA,aACA;AACA,QACE,eAiBE,OAAO,GACT;AACA,MAAAA,YAAW,KAAK,GAAI,QAAQ,QAA4B;AAAA,IAC1D,WAAW,2BAA2B,OAAO,GAAG;AAC9C,MAAAA,YAAW,KAAK,OAAwB;AAAA,IAC1C;AAAA,EACF;AAAA,EAEA,mCAqBE,2CAsBA,wCAsBA;AACA,UAAMA,cAA8B,CAAC;AAErC,SAAK,iCAYH,2CAA2CA,WAAU;AAEvD,IAAAA,YAAW;AAAA,MACT,GAAG,KAAK,gDAYN,sCAAsC;AAAA,IAC1C;AAEA,WAAOA;AAAA,EACT;AAAA,EAEA,2CAqBE,2CAsBA,wCAsBA;AACA,UAAMA,cAA2C,CAAC;AAElD,SAAK;AAAA,MAaH;AAAA,MAmBAA;AAAA,IACF;AAEA,QACE,8BAUE,yCAAyC,GAC3C;AACA,WAAK,eAAe,yCAAyC;AAC7D,MAAAA,YAAW,KAAK,0CAA0C,QAAQ;AAAA,IACpE;AAEA,IAAAA,YAAW;AAAA,MACT,GAAG,KAAK,wDAYN,sCAAsC;AAAA,IAC1C;AAEA,WAAOA;AAAA,EACT;AAAA,EAEA,0BAqBE,oBACA,iDAsBA,8CAqBG,wCAsBG;AACN,UAAMA,cAA8B,CAAC;AAErC,QAAI,OAAO,oDAAoD,UAAU;AACvE,MAAAA,YAAW;AAAA,QACT,GAAG,KAAK;AAAA,UAaN;AAAA,UACA;AAAA,QACF;AAAA,MACF;AACA,YAAM,OAAO;AACb,yBAAmB,KAAK,KAAK,QAAQ,EAAE,MAAM,GAAGA,WAAU;AAAA,IAC5D,OAAO;AACL,MAAAA,YAAW;AAAA,QACT,GAAG,KAAK;AAAA,UAaN;AAAA,WAEG,2BAeC,yCAAyC,KAC3C,eAiBE,yCAAyC,IACvC,CAAC,yCAAyC,IAC1C,CAAC,GAsBL,OAAO,sCAAsC;AAAA,QACjD;AAAA,MACF;AACA,yBAAmB,KAAK,KAAK,QAAQ,EAAE,GAAGA,WAAU;AAAA,IACtD;AACA,WAAO;AAAA,EACT;AAAA,EAEQ,eACN,QACA;AACA,WAAO,QAAQ,OAAO,SAAS,EAAE;AAAA,MAC/B,CAAC,CAAC,KAAK,KAAK,UACT,0BAAS,KAAK,SAAS,MACtB,qCAAoB,GAAG,KAAK,QAAQ,GAAG,GAAG,EAAE,CAC9C,IAAI;AAAA,IACR;AAEA,UAAM,cACJ,KAAK,IAAI,OAAO,eAAW,mCAAkB,OAAO,QAAQ,CAAC;AAC/D,kCAAS,KAAK,GAAG,EAAE,OAAO,eAAW,mCAAkB,OAAO,QAAQ,CAAC,IAAI;AAAA,MACzE,GAAI,OAAO,gBAAgB,WAAW,cAAc,CAAC;AAAA,MACrD,GAAG,OAAO;AAAA,IACZ;AAAA,EACF;AAAA,EAEA,kCAsBE,oBACA,iDAsBA,8CAqBG,wCAsBG;AACN,UAAMA,cAA2C,CAAC;AAClD,QAAI;AAEJ,QAAI,OAAO,oDAAoD,UAAU;AACvE,MAAAA,YAAW;AAAA,QACT,GAAG,KAAK;AAAA,UAaN;AAAA,UACA;AAAA,QACF;AAAA,MACF;AACA,aAAO;AAAA,IACT,OAAO;AACL,UACE;AAAA,QACE;AAAA,MACF,GACA;AACA,cAAM,SAAS;AAEf,aAAK,eAAe,MAAM;AAC1B,eAAO,OAAO;AAAA,MAChB;AACA,MAAAA,YAAW;AAAA,QACT,GAAG,KAAK;AAAA,UAaN;AAAA,WACC,2BAiBC,yCAAyC,KAC3C,eAiBE,yCAAyC,KAC3C;AAAA,YACE;AAAA,UACF,IACI,CAAC,yCAAyC,IAC1C,CAAC,GACH,OAAO,sCAAsC;AAAA,QACjD;AAAA,MACF;AAAA,IACF;AAEA,QAAI,CAAC,MAAM;AACT,aAAOA,YAAW;AAAA,QAAO,CAAC,MACxB,8BAUE,CAAC;AAAA,MACL,EAAE,CAAC,GAAG;AAAA,IACR;AAEA,QAAI,MAAM;AACR,yBAAmB,KAAK,KAAK,QAAQ,EAAE,MAAM,GAAGA,WAAU;AAAA,IAC5D,OAAO;AACL,yBAAmB,KAAK,KAAK,QAAQ,EAAE,GAAGA,WAAU;AAAA,IACtD;AACA,WAAO;AAAA,EACT;AAAA,EAEQ,iBACN,QACA;AACA,WAAO,gBAAgB;AAAA,MACrB,GAAI,KAAK,iBAAiB,CAAC;AAAA,MAC3B,GAAI,OAAO,iBAAiB,CAAC;AAAA,IAC/B;AAEA,WAAO,QAAQ,QAAQ,CAAC,cAAc;AACpC,WAAK;AAAA,QACH;AAAA,MACF;AAAA,IACF,CAAC;AAAA,EACH;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,2BACE,SAA+B,MAC/B,YACA;AACA,UAAM,aACJ,OAAO,eAAe,QACtB,OAAO,OAAO,cAAc,SAAS,WACjC,OAAO,cAAc,OACrB;AACN,UAAM,aACJ,cAAc,aACV,EAAE,GAAG,YAAY,GAAG,WAAW,IAC9B,cAAc;AAErB,eAAW,SAAS,OAAO,QAAQ;AACjC,YAAM,OAAO,MAAM,gBAAgB;AACnC,YAAM,SAAS,MAAM,gBAAgB;AACrC,UAAI,CAAC,QAAQ,WAAW,YAAa;AAErC,YAAM,YAAY;AAClB,YAAM,YAAY,MAAM,gBAAgB;AAExC,UAAI,oBAAoB,IAAI,GAAG;AAC7B,YACE,CAAC,UAAU,oBAAoB,KAC/B,CAAC,YAAY,oBACb;AACA,gBAAM,IAAI;AAAA,YACR,UAAU,SAAS;AAAA,UAErB;AAAA,QACF;AAAA,MACF;AAEA,UAAI,cAAc,IAAI,GAAG;AACvB,YAAI,CAAC,UAAU,cAAc,KAAK,CAAC,YAAY,cAAc;AAC3D,gBAAM,IAAI;AAAA,YACR,UAAU,SAAS;AAAA,UAErB;AAAA,QACF;AAAA,MACF;AAEA,UAAI,eAAe,IAAI,GAAG;AACxB,YAAI,CAAC,UAAU,eAAe,KAAK,CAAC,YAAY,eAAe;AAC7D,gBAAM,IAAI;AAAA,YACR,UAAU,SAAS;AAAA,UAErB;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAEA,eAAW,aAAa,OAAO,SAAS;AACtC,WAAK,2BAA2B,WAAW,UAAU;AAAA,IACvD;AAAA,EACF;AAAA,EAEA,MASI,CA0BF,iDAsBA,8CAqBG,2CAsBA;AACH;AAAA,MACE;AAAA,MACA;AAAA,MACA,GAAG;AAAA,IACL,EAAE,QAAQ,CAAC,QAAQ;AACjB,UAAI,mBAAuB,GAAG,GAAG;AAC/B,aAAK,QAAQ,KAAK,GAAG;AACrB,aAAK;AAAA,UACH;AAAA,QACF;AAAA,MACF;AAAA,IACF,CAAC;AAED,WAAO,KAAK;AAAA,MAcV,KAAK,SAAS;AAAA,MACd;AAAA,MACA;AAAA,MACA,GAAG;AAAA,IACL;AAAA,EAoBF;AAAA,EAEA,MAQI,CAqBF,iDAsBA,8CAqBG,2CAsBA;AACH,WAAO,KAAK;AAAA,MAaV,KAAK,SAAS;AAAA,MACd;AAAA,MACA;AAAA,MACA,GAAG;AAAA,IACL;AAAA,EACF;AAAA,EAEA,UAQI,CAqBF,iDAsBA,8CAqBG,2CAsBA;AACH,WAAO,KAAK;AAAA,MAaV,KAAK,SAAS;AAAA,MACd;AAAA,MACA;AAAA,MACA,GAAG;AAAA,IACL;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAeA,MAWI,CAqBF,MACA,8CAmBG,2CAmBA;AACH,WAAO,KAAK;AAAA,MAcV;AAAA,MACA;AAAA,MACA,KAAK,SAAS;AAAA,MACd;AAAA,MACA,GAAG;AAAA,IACL;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAeA,OAWI,CAqBF,MACA,8CAmBG,2CAmBA;AACH,WAAO,KAAK;AAAA,MAcV;AAAA,MACA;AAAA,MACA,KAAK,SAAS;AAAA,MACd;AAAA,MACA,GAAG;AAAA,IACL;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAeA,MAWI,CAqBF,MACA,8CAmBG,2CAmBA;AACH,WAAO,KAAK;AAAA,MAcV;AAAA,MACA;AAAA,MACA,KAAK,SAAS;AAAA,MACd;AAAA,MACA,GAAG;AAAA,IACL;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAeA,QAWI,CAqBF,MACA,8CAmBG,2CAmBA;AACH,WAAO,KAAK;AAAA,MAcV;AAAA,MACA;AAAA,MACA,KAAK,SAAS;AAAA,MACd;AAAA,MACA,GAAG;AAAA,IACL;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAeA,SAWI,CAqBF,MACA,8CAmBG,2CAmBA;AACH,WAAO,KAAK;AAAA,MAcV;AAAA,MACA;AAAA,MACA,KAAK,SAAS;AAAA,MACd;AAAA,MACA,GAAG;AAAA,IACL;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAeA,UAWI,CAqBF,MACA,8CAmBG,2CAmBA;AACH,WAAO,KAAK;AAAA,MAcV;AAAA,MACA;AAAA,MACA,KAAK,SAAS;AAAA,MACd;AAAA,MACA,GAAG;AAAA,IACL;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAeA,OAWI,CAqBF,MACA,8CAmBG,2CAmBA;AACH,WAAO,KAAK;AAAA,MAcV;AAAA,MACA;AAAA,MACA,KAAK,SAAS;AAAA,MACd;AAAA,MACA,GAAG;AAAA,IACL;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAeA,QAWI,CAqBF,MACA,8CAmBG,2CAmBA;AACH,WAAO,KAAK;AAAA,MAcV;AAAA,MACA;AAAA,MACA,KAAK,SAAS;AAAA,MACd;AAAA,MACA,GAAG;AAAA,IACL;AAAA,EACF;AAAA,EAEA,yBAAyB;AAAA,IACvB;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,GAKG;AACD,UAAM,YAAY,CAAC,QAAQ,IAAI,EAAE,KAAK,GAAG;AACzC,eAAW,SAAS,KAAK,QAAQ;AAC/B,UACE,MAAM,SAAS,QACf,MAAM,WAAW,UACjB,MAAM,gBAAgB,SAAS,MAC/B;AACA,aAAK,SAAS,SAAS,IAAI;AAAA,MAC7B;AAAA,IACF;AAEA,eAAW,UAAU,KAAK,SAAS;AACjC,aAAO,2BAA2B;AAAA,QAChC;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,MACF,CAAC;AAAA,IACH;AAAA,EACF;AAAA,EAEQ,WACN,MACA,MACA,uBACA;AACA,WAAO,QAAQ,IAAI,EAAE,QAAQ,CAAC,CAAC,KAAK,YAAY,MAAM;AACpD,UAAI,aAAa,YAAY,GAAG;AAC9B,cAAM,eAAW,gCAAW,+BAAc,YAAY,CAAC;AACvD,YAAI,sBAAsB,IAAI,QAAQ,GAAG;AACvC,gBAAM,IAAI,MAAM,eAAe,GAAG,wBAAwB;AAAA,QAC5D;AACA,8BAAsB,IAAI,QAAQ;AAClC,YAAI,CAAC,aAAa,WAAW,CAAC,aAAa,OAAO;AAChD,gBAAM,IAAI,MAAM,eAAe,GAAG,4BAA4B;AAAA,QAChE;AACA,aAAK,yBAAyB;AAAA,UAC5B,SAAS,CAAC,GAAG,MAAM,GAAG,EAAE,KAAK,GAAG;AAAA,UAChC,MAAM,aAAa;AAAA,UACnB,QAAQ,aAAa;AAAA,UACrB,MAAM,aAAa,gBAAgB;AAAA,QACrC,CAAC;AACD,8BAAsB,IAAI,QAAQ;AAAA,MACpC,OAAO;AACL,aAAK,WAAW,cAAc,CAAC,GAAG,MAAM,GAAG,GAAG,qBAAqB;AAAA,MACrE;AAAA,IACF,CAAC;AAAA,EACH;AAAA,EAEA,aAAa,MAA4B;AACvC,SAAK,WAAW,MAAM,CAAC,GAAG,oBAAI,IAAI,CAAC;AAAA,EACrC;AAAA,EAEU,eAAe,OAAmB;AAC1C,UAAM,UAAU,CAAC,GAAG,KAAK,OAAO;AAChC,UAAM,SAAS,CAAC,GAAG,KAAK,MAAM;AAC9B,UAAM,YAAY,EAAE,GAAG,KAAK,UAAU;AACtC,UAAM,MAAM,EAAE,GAAG,KAAK,IAAI;AAC1B,UAAM,WAAW,EAAE,GAAG,KAAK,SAAS;AAAA,EACtC;AAAA,EAEA,QAAc;AACZ,UAAM,QAAQ,IAAI;AAAA,MAYhB,KAAK;AAAA,MACL,KAAK;AAAA,MACL,KAAK;AAAA,MACL,KAAK;AAAA,MACL,KAAK;AAAA,MACL,KAAK;AAAA,IACP;AAEA,SAAK,eAAe,KAAK;AAEzB,WAAO;AAAA,EACT;AACF;;;AwC51GO,IAAe,mCAAf,cAUG,4BAWR;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,YACW,iBACA,UACA,sBACA,wBACA,YACT;AACA;AAAA,MACE;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,QACE,GAAG;AAAA,QACH,SAAS,YAAY,YAAY;AAAA,QACjC,KAAK,YAAY,QAAQ;AAAA,MAC3B;AAAA,IACF;AAjBS;AACA;AACA;AACA;AACA;AAeT,SAAK,SAAS,IAAI,KAAK,KAAK,YAAY,QAAQ,CAAC,CAAC,CAAkB;AAAA,EACtE;AAAA,EApBW;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA;AAAA;AAAA;AAAA;AAAA,EAsBD,oBAAoB;AAC5B,SAAK,2BAA2B;AAAA,EAClC;AAGF;;;AC3EA,UAAqB;AAEd,SAAS,YACd,MACA,OAAe,aACG;AAClB,SAAO,IAAI,QAAQ,CAAC,YAAY;AAC9B,UAAM,SAAS,IAAQ,WAAO;AAE9B,WAAO,WAAW,GAAI;AAEtB,WAAO,GAAG,WAAW,MAAM;AACzB,aAAO,QAAQ;AACf,cAAQ,IAAI;AAAA,IACd,CAAC;AAED,WAAO,GAAG,WAAW,MAAM;AACzB,aAAO,QAAQ;AACf,cAAQ,KAAK;AAAA,IACf,CAAC;AAED,WAAO,GAAG,SAAS,MAAM;AACvB,cAAQ,KAAK;AAAA,IACf,CAAC;AAED,WAAO,QAAQ,MAAM,IAAI;AAAA,EAC3B,CAAC;AACH;;;AC3BA,IAAAC,iBAA2B;AAwBpB,SAAS,wBAAwB;AAAA,EACtC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,QAAQ;AACV,GAQE;AACA,QAAM,YAAY,oBAAI,KAAK;AAC3B,QAAM,YAAQ,2BAAW;AAEzB,QAAM,YAAY,gBAAgB;AAAA,IAChC;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,CAAC;AAED,SAAO;AAAA,IACL,eAAe,cAAc,KAAK,OAAO,UAAU,YAAY,CAAC,UAAU,KAAK,cAAc,SAAS;AAAA,EACxG;AACF;;;ACpDA,IAAAC,iBAAgC;AA6BzB,IAAM,yBAAyB;AAG/B,IAAM,wBAAwB;AAG9B,IAAM,uBAAuB;AAEpC,IAAM,cAAc,IAAI,KAAK;AAatB,IAAM,8BAAN,cAA0C,MAAM;AAAA,EAErD,YACW,QACT,SAES,mBACT;AACA,UAAM,OAAO;AALJ;AAGA;AAAA,EAGX;AAAA,EANW;AAAA,EAGA;AAAA,EALO,OAAe;AASnC;AAqBO,SAAS,wBACdC,WAAkC,CAAC,GACnC,UAAU,wBACmD;AAC7D,QAAM,aAAaA,SAAQ,cAAc,QAAQ,IAAI;AACrD,QAAM,aAAaA,SAAQ,cAAc,QAAQ,IAAI;AACrD,QAAM,UAAUA,SAAQ,WAAW,QAAQ,IAAI;AAC/C,MAAI,CAAC,cAAc,CAAC,cAAc,CAAC,SAAS;AAC1C,UAAM,IAAI;AAAA,MACR,GAAG,OAAO;AAAA,IAKZ;AAAA,EACF;AACA,SAAO,EAAE,YAAY,YAAY,QAAQ;AAC3C;AAGO,SAAS,kBACd,MAA0C,QAAQ,KACzC;AACT,SAAO;AAAA,IACL,IAAI,wBAAwB,IAAI,eAAe,IAAI;AAAA,EACrD;AACF;AAEA,SAAS,oBAAoB,OAAuB;AAElD,MAAI,MAAM,MAAM;AAChB,SAAO,MAAM,KAAK,MAAM,MAAM,CAAC,MAAM,IAAK,QAAO;AACjD,SAAO,MAAM,MAAM,GAAG,GAAG;AAC3B;AAGO,SAAS,+BACdA,WAAkC,CAAC,GACnC,SAC0B;AAC1B,QAAM,EAAE,YAAY,YAAY,QAAQ,IAAI;AAAA,IAC1CA;AAAA,IACA;AAAA,EACF;AACA,QAAM,YAAYA,SAAQ,SAAS;AACnC,QAAM,OAAO,oBAAoB,UAAU;AAE3C,QAAM,UAA+C,OACnD,QACA,OACA,MACA,iBAAiB,CAAC,MACf;AAEH,UAAM,EAAE,cAAc,IAAI,wBAAwB;AAAA,MAChD,WAAW;AAAA,MACX;AAAA,MACA,MAAM;AAAA,MACN;AAAA,MACA,OAAO;AAAA,IACT,CAAC;AACD,UAAM,WAAW,MAAM,UAAU,GAAG,IAAI,GAAG,sBAAsB,GAAG,KAAK,IAAI;AAAA,MAC3E;AAAA,MACA,SAAS;AAAA,QACP,GAAG,eAAe;AAAA,QAClB;AAAA,QACA,GAAI,OAAO,EAAE,gBAAgB,mBAAmB,IAAI,CAAC;AAAA,MACvD;AAAA,MACA,MAAM,OAAO,KAAK,UAAU,IAAI,IAAI;AAAA,MACpC,QAAQ,eAAe;AAAA,IACzB,CAAC;AACD,QAAI,CAAC,SAAS,IAAI;AAChB,YAAM,WAAW,MAAM,SAAS,KAAK,EAAE,MAAM,MAAM,EAAE,GAAG,KAAK;AAC7D,YAAM,aAAa,OAAO,SAAS,QAAQ,IAAI,aAAa,CAAC;AAC7D,YAAM,IAAI;AAAA,QACR,SAAS;AAAA,QACT,WAAW,6BAA6B,SAAS,MAAM;AAAA,QACvD,OAAO,SAAS,UAAU,KAAK,aAAa,IAAI,aAAa;AAAA,MAC/D;AAAA,IACF;AACA,WAAO;AAAA,EACT;AAEA,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA,MAAM,KACJ,QACA,OACA,MACA,gBACY;AACZ,aAAQ,OACN,MAAM,QAAQ,QAAQ,OAAO,MAAM,cAAc,GACjD,KAAK;AAAA,IACT;AAAA,EACF;AACF;AAcO,IAAM,iCAAN,cAA6C,MAAM;AAAA,EACtC,OAAO;AAC3B;AAEA,IAAM,kBAAkB,oBAAI,IAAoB;AAWzC,SAAS,oBACd,SAMAA,WAAoD,CAAC,GAChC;AACrB,QAAM,UAAUA,SAAQ,WAAW,QAAQ,IAAI;AAC/C,MAAI,CAAC,SAAS;AACZ,UAAM,IAAI;AAAA,MACR;AAAA,IACF;AAAA,EACF;AACA,QAAM,SAAS,QAAQ,QAAQ,iBAAiB,QAAQ,QAAQ;AAChE,QAAM,QAAQ,MAAM,QAAQ,MAAM,IAAI,OAAO,CAAC,IAAI;AAClD,QAAM,QACJ,0DAA0D;AAAA,IACxD,SAAS;AAAA,EACX;AACF,MAAI,CAAC,OAAO;AACV,UAAM,IAAI;AAAA,MACR;AAAA,IACF;AAAA,EACF;AACA,QAAM,CAAC,EAAE,OAAO,IAAI,OAAO,SAAS,IAAI;AACxC,MAAI,UAAU,uBAAuB;AACnC,UAAM,IAAI,+BAA+B,4BAA4B;AAAA,EACvE;AACA,QAAM,YAAY,IAAI,KAAK,EAAE;AAC7B,QAAM,OAAOA,SAAQ,OAAO,KAAK,KAAK;AACtC,MACE,OAAO,MAAM,UAAU,QAAQ,CAAC,KAChC,KAAK,IAAI,MAAM,UAAU,QAAQ,CAAC,IAAI,aACtC;AACA,UAAM,IAAI,+BAA+B,4BAA4B;AAAA,EACvE;AACA,QAAM,WAAW,OAAO;AAAA,IACtB,gBAAgB;AAAA,MACd,WAAW;AAAA,MACX,QAAQ,QAAQ,OAAO,YAAY;AAAA,MACnC,MAAM,QAAQ;AAAA,MACd,MAAM,QAAQ;AAAA,MACd;AAAA,MACA;AAAA,IACF,CAAC;AAAA,EACH;AACA,QAAM,WAAW,OAAO,KAAK,SAAS;AACtC,MACE,SAAS,WAAW,SAAS,UAC7B,KAAC,gCAAgB,UAAU,QAAQ,GACnC;AACA,UAAM,IAAI,+BAA+B,mBAAmB;AAAA,EAC9D;AACA,aAAW,CAAC,MAAM,EAAE,KAAK,iBAAiB;AACxC,QAAI,MAAM,KAAK,YAAa,iBAAgB,OAAO,IAAI;AAAA,EACzD;AACA,MAAI,gBAAgB,IAAI,KAAK,GAAG;AAC9B,UAAM,IAAI,+BAA+B,mBAAmB;AAAA,EAC9D;AACA,kBAAgB,IAAI,OAAO,GAAG;AAE9B,QAAM,SACJ,OAAO,QAAQ,SAAS,YAAY,OAAO,SAAS,QAAQ,IAAI,IAC5D,KAAK,MAAM,QAAQ,KAAK,SAAS,CAAC,IAClC,QAAQ;AACd,QAAM,QAAQ;AACd,MACE,CAAC,SACD,OAAO,MAAM,OAAO,YACpB,OAAO,MAAM,SAAS,YACtB,OAAO,MAAM,YAAY,UACzB;AACA,UAAM,IAAI,+BAA+B,8BAA8B;AAAA,EACzE;AACA,SAAO;AACT;AAMO,SAAS,kBAAkB,QAIJ;AAC5B,SAAO,wBAAwB;AAAA,IAC7B,WAAW,OAAO;AAAA,IAClB,QAAQ;AAAA,IACR,MAAM,OAAO;AAAA,IACb,MAAM,OAAO;AAAA,IACb,OAAO;AAAA,EACT,CAAC;AACH;;;AClMO,IAAM,2BAAN,cAAuC,4BAA4B;AAAA,EACtD,OAAO;AAC3B;AAgBO,SAAS,yBACdC,WAAqC,CAAC,GAClB;AACpB,QAAM,YAAY,+BAA+BA,UAAS,mBAAmB;AAE7E,iBAAe,KACb,QACA,OACA,MACA,QACmB;AACnB,QAAI;AACF,aAAO,MAAM,UAAU,QAAQ,QAAQ,OAAO,MAAM,EAAE,OAAO,CAAC;AAAA,IAChE,SAAS,OAAO;AACd,UAAI,iBAAiB,6BAA6B;AAChD,cAAM,IAAI;AAAA,UACR,MAAM;AAAA,UACN,MAAM;AAAA,UACN,MAAM;AAAA,QACR;AAAA,MACF;AACA,YAAM;AAAA,IACR;AAAA,EACF;AAEA,SAAO;AAAA,IACL,MAAM,SAAS;AACb,aAAQ,OAAO,MAAM,KAAK,OAAO,SAAS,GAAG,KAAK;AAAA,IACpD;AAAA,IACA,MAAM;AAAA,MACJ,aAAa;AAAA,QACX,MAAM,OAAO,SAAS;AACpB,gBAAM,WAAW,MAAM;AAAA,YACrB;AAAA,YACA;AAAA,YACA;AAAA,UACF;AACA,iBAAQ,MAAM,SAAS,KAAK;AAAA,QAC9B;AAAA,QACA,OAAO,OAAO,SAAS,gBAAgB,CAAC,GAAG;AACzC,gBAAM,WAAW,MAAM;AAAA,YACrB;AAAA,YACA;AAAA,YACA;AAAA,YACA,cAAc;AAAA,UAChB;AACA,cAAI,CAAC,SAAS,KAAM;AACpB,2BAAiB,QAAQ,QAAQ,SAAS,IAAI,GAAG;AAC/C,gBAAI,SAAS,SAAU;AACvB,gBAAI;AACF,oBAAM,KAAK,MAAM,IAAI;AAAA,YACvB,QAAQ;AAAA,YAER;AAAA,UACF;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAAA,EACF;AACF;AAGA,gBAAgB,QACd,QACwB;AACxB,QAAM,UAAU,IAAI,YAAY;AAChC,MAAI,SAAS;AACb,QAAM,SAAS,OAAO,UAAU;AAChC,MAAI;AACF,eAAS;AACP,YAAM,EAAE,OAAO,KAAK,IAAI,MAAM,OAAO,KAAK;AAC1C,UAAI,KAAM;AACV,gBAAU,QAAQ,OAAO,OAAO,EAAE,QAAQ,KAAK,CAAC;AAChD,UAAI;AACJ,cAAQ,WAAW,OAAO,OAAO,YAAY,OAAO,IAAI;AACtD,cAAM,QAAQ,OAAO,MAAM,GAAG,QAAQ;AACtC,iBAAS,OAAO,MAAM,QAAQ,EAAE,QAAQ,eAAe,EAAE;AACzD,cAAM,OAAO,MACV,MAAM,OAAO,EACb,OAAO,CAAC,SAAS,KAAK,WAAW,OAAO,CAAC,EACzC,IAAI,CAAC,SAAS,KAAK,MAAM,CAAC,EAAE,UAAU,CAAC,EACvC,KAAK,IAAI;AACZ,YAAI,KAAM,OAAM;AAAA,MAClB;AAAA,IACF;AACA,UAAM,OAAO,OAAO,KAAK;AACzB,QAAI,KAAK,WAAW,OAAO,EAAG,OAAM,KAAK,MAAM,CAAC,EAAE,UAAU;AAAA,EAC9D,UAAE;AACA,WAAO,YAAY;AAAA,EACrB;AACF;;;AC9KA,SAAS,OAAO,OAAkD;AAChE,SAAO,CAAC,CAAC,SAAS,OAAO,UAAU,YAAY,CAAC,MAAM,QAAQ,KAAK;AACrE;AACA,SAAS,iBAAwB;AAC/B,QAAM,IAAI;AAAA,IACR;AAAA,IACA;AAAA,EACF;AACF;AACA,SAAS,eAAe,KAAoC;AAC1D,MAAI,CAAC,OAAO,GAAG,KAAK,CAAC,OAAO,IAAI,OAAO,EAAG,QAAO,eAAe;AAChE,QAAM,UAAU,IAAI;AACpB,MACE,OAAO,KAAK,GAAG,EAAE,KAAK,CAAC,QAAQ,CAAC,CAAC,UAAU,SAAS,EAAE,SAAS,GAAG,CAAC,KACnE,OAAO,KAAK,OAAO,EAAE;AAAA,IACnB,CAAC,QAAQ,CAAC,CAAC,aAAa,YAAY,UAAU,EAAE,SAAS,GAAG;AAAA,EAC9D,KACA,CAAC,MAAM,QAAQ,IAAI,MAAM,KACzB,IAAI,OAAO,WAAW,KACtB,CAAC,OAAO,IAAI,OAAO,CAAC,CAAC,KACrB,OAAO,KAAK,IAAI,OAAO,CAAC,CAAC,EAAE,KAAK,CAAC,QAAQ,QAAQ,IAAI,KACrD,OAAO,IAAI,OAAO,CAAC,EAAE,OAAO,YAC5B,CAAC,mBAAmB,KAAK,IAAI,OAAO,CAAC,EAAE,EAAE,KACzC,OAAO,QAAQ,cAAc,YAC7B,CAAC,OAAO,cAAc,QAAQ,SAAS,KACvC,QAAQ,aAAa,KAAK,IAAI,KAC9B,QAAQ,YAAY,KAAK,IAAI,IAAI,KAAK,OACtC,OAAO,QAAQ,aAAa,YAC5B,CAAC,OAAO,cAAc,QAAQ,QAAQ,KACtC,QAAQ,WAAW,KACnB,QAAQ,WAAW,MACnB,OAAO,QAAQ,aAAa,YAC5B,CAAC,OAAO,cAAc,QAAQ,QAAQ,KACtC,QAAQ,WAAW,KACnB,QAAQ,WAAW;AAEnB,WAAO,eAAe;AACxB,SAAO;AAAA,IACL,QAAQ,CAAC,EAAE,IAAI,IAAI,OAAO,CAAC,EAAE,GAAG,CAAC;AAAA,IACjC,SAAS;AAAA,MACP,WAAW,QAAQ;AAAA,MACnB,UAAU,QAAQ;AAAA,MAClB,UAAU,QAAQ;AAAA,IACpB;AAAA,EACF;AACF;AACA,eAAe,mBACb,UAC+B;AAC/B,MAAI,CAAC,SAAS,KAAM,QAAO,eAAe;AAC1C,QAAM,SAAS,SAAS,KAAK,UAAU;AACvC,QAAM,UAAU,IAAI,YAAY;AAChC,MAAIC,QAAO,IACT,QAAQ;AACV,MAAI;AACF,eAAS;AACP,YAAM,EAAE,MAAM,MAAM,IAAI,MAAM,OAAO,KAAK;AAC1C,UAAI,KAAM;AACV,eAAS,MAAM;AACf,UAAI,QAAQ,KAAM,QAAO,eAAe;AACxC,MAAAA,SAAQ,QAAQ,OAAO,OAAO,EAAE,QAAQ,KAAK,CAAC;AAAA,IAChD;AACA,IAAAA,SAAQ,QAAQ,OAAO;AACvB,WAAO,eAAe,KAAK,MAAMA,KAAI,CAAC;AAAA,EACxC,QAAQ;AACN,WAAO,eAAe;AAAA,EACxB,UAAE;AACA,UAAM,OAAO,OAAO,EAAE,MAAM,MAAM;AAAA,IAAC,CAAC;AACpC,WAAO,YAAY;AAAA,EACrB;AACF;AAoBO,SAAS,gCACdC,WAAqC,CAAC,GACX;AAC3B,QAAM,YAAY;AAAA,IAChBA;AAAA,IACA;AAAA,EACF;AACA,iBAAe,KACb,QACA,OACA,MACmB;AACnB,QAAI;AACF,aAAO,MAAM,UAAU,QAAQ,QAAQ,OAAO,IAAI;AAAA,IACpD,SAAS,OAAO;AACd,UAAI,iBAAiB;AACnB,cAAM,IAAI;AAAA,UACR,MAAM;AAAA,UACN;AAAA,UACA,MAAM;AAAA,QACR;AACF,YAAM;AAAA,IACR;AAAA,EACF;AACA,SAAO;AAAA,IACL,MAAM,SAAS;AACb,YAAM,WAAW,MAAM,KAAK,OAAO,SAAS;AAC5C,aAAO,mBAAmB,QAAQ;AAAA,IACpC;AAAA,IACA,MAAM;AAAA,MACJ,aAAa;AAAA,QACX,MAAM,OAAO,SAAS;AACpB,iBAAQ,OACN,MAAM;AAAA,YACJ;AAAA,YACA;AAAA,YACA;AAAA,UACF,GACA,KAAK;AAAA,QACT;AAAA,MACF;AAAA,IACF;AAAA,EACF;AACF;;;ACtDO,IAAM,oBAAN,cAAgC,4BAA4B;AAAA,EAC/C,OAAO;AAC3B;AAUO,IAAM,eAAe;AAAA,EAC1B,eAAe;AAAA,EACf,kBAAkB;AAAA,EAClB,kBAAkB;AAAA;AAAA,EAElB,cAAc,MAAM;AAAA,EACpB,SAAS;AAAA;AAAA,EAET,yBAAyB;AAC3B;AAEA,IAAM,UACJ;AACF,IAAM,WAAW;AAEjB,IAAM,cAAc;AAEpB,IAAM,iBAAiB;AACvB,IAAM,UACJ;AACF,IAAM,qBAAqB,oBAAI,IAAI,CAAC,OAAO,UAAU,UAAU,CAAC;AAGzD,SAAS,eAAe,SAAqC;AAClE,SACE,OAAO,YAAY,YACnB,QAAQ,UAAU,aAAa,oBAC/B,QAAQ,KAAK,OAAO;AAExB;AAEA,SAAS,OAAO,SAAwB;AACtC,QAAM,IAAI,kBAAkB,KAAK,OAAO;AAC1C;AAEA,SAAS,UAAU,OAAsC,OAAe;AACtE,MAAI,UAAU,OAAW,QAAO;AAChC,QAAM,OAAO,MAAM,QAAQ,KAAK,IAAI,QAAQ,CAAC,KAAK;AAClD,MAAI,KAAK,WAAW,EAAG,QAAO,GAAG,KAAK,iCAAiC;AACvE,MAAI,KAAK,SAAS,aAAa,eAAe;AAC5C;AAAA,MACE,GAAG,KAAK,QAAQ,KAAK,MAAM,4BAA4B,aAAa,aAAa;AAAA,IACnF;AAAA,EACF;AACA,aAAW,WAAW,MAAM;AAC1B,QAAI,CAAC,eAAe,OAAO,GAAG;AAC5B;AAAA,QACE,GAAG,KAAK,MAAM,OAAO,OAAO,EAAE,MAAM,GAAG,EAAE,CAAC;AAAA,MAC5C;AAAA,IACF;AAAA,EACF;AACA,SAAO;AACT;AAEA,SAAS,KAAK,SAAwB;AACpC,SAAO,oBAAoB,OAAO,EAAE;AACtC;AAEA,SAAS,sBAAsB,KAA6B;AAC1D,MAAI,OAAO,QAAQ,YAAY,QAAQ,GAAI,QAAO;AAClD,MAAI,IAAI,SAAS,aAAa,yBAAyB;AACrD,WAAO,sBAAsB,aAAa,uBAAuB;AAAA,EACnE;AACA,MAAI,CAAC,YAAY,KAAK,GAAG,GAAG;AAC1B,WAAO;AAAA,EACT;AACA,MAAI,eAAe,KAAK,GAAG,GAAG;AAC5B,WAAO;AAAA,EACT;AACA,MAAI;AACJ,MAAI;AACF,aAAS,IAAI,IAAI,GAAG;AAAA,EACtB,QAAQ;AACN,WAAO;AAAA,EACT;AACA,MAAI,OAAO,aAAa,SAAU,QAAO;AACzC,MAAI,OAAO,YAAY,OAAO,UAAU;AACtC,WAAO;AAAA,EACT;AACA,SAAO;AACT;AAMO,SAAS,wBACd,OACkC;AAClC,MAAI,UAAU,UAAa,UAAU,KAAM,QAAO;AAClD,MAAI,OAAO,UAAU,YAAY,MAAM,QAAQ,KAAK,GAAG;AACrD,SAAK,mBAAmB;AAAA,EAC1B;AACA,QAAM,gBAAgB,OAAO,KAAK,KAAK,EAAE;AAAA,IACvC,CAAC,QAAQ,CAAC,mBAAmB,IAAI,GAAG;AAAA,EACtC;AACA,MAAI,cAAc,QAAQ;AACxB,SAAK,iBAAiB,cAAc,IAAI,CAAC,MAAM,IAAI,CAAC,GAAG,EAAE,KAAK,IAAI,CAAC,EAAE;AAAA,EACvE;AACA,QAAM,MAAM,SAAS,QAAQ,MAAM,MAAM;AACzC,QAAM,SAAS,YAAY,QAAQ,MAAM,SAAS;AAClD,QAAM,WAAW,cAAc,QAAQ,MAAM,WAAW;AACxD,MAAI,QAAQ,UAAa,WAAW,QAAW;AAC7C,SAAK,yBAAyB;AAAA,EAChC;AACA,MAAI,QAAQ,QAAW;AACrB,UAAM,UAAU,sBAAsB,GAAG;AACzC,QAAI,QAAS,MAAK,OAAO;AAAA,EAC3B;AACA,MACE,WAAW,WACV,OAAO,WAAW,YACjB,OAAO,SAAS,aAAa,oBAC7B,CAAC,QAAQ,KAAK,MAAM,IACtB;AACA;AAAA,MACE,YAAY,OAAO,MAAM,EAAE,MAAM,GAAG,EAAE,CAAC;AAAA,IACzC;AAAA,EACF;AACA,MAAI,aAAa,UAAa,OAAO,aAAa,WAAW;AAC3D,SAAK,gCAAgC;AAAA,EACvC;AACA,MAAI,OAAO,QAAQ,UAAU;AAC3B,WAAO;AAAA,MACL;AAAA,MACA,GAAI,OAAO,WAAW,WAAW,EAAE,OAAO,IAAI,CAAC;AAAA,MAC/C,GAAI,aAAa,OAAO,EAAE,UAAU,KAAK,IAAI,CAAC;AAAA,IAChD;AAAA,EACF;AACA,MAAI,aAAa,KAAM,MAAK,6CAA6C;AACzE,MAAI,OAAO,WAAW,SAAU,QAAO,EAAE,OAAO;AAChD,SAAO,KAAK,yBAAyB;AACvC;AAGO,SAAS,yBACd,SACyB;AACzB,QAAM,KAAK,UAAU,QAAQ,IAAI,IAAI,KAAK,OAAO,gBAAgB;AACjE,QAAM,UAAU,UAAU,QAAQ,SAAS,SAAS;AACpD,QAAM,UAAU,QAAQ;AACxB,MAAI,OAAO,YAAY,YAAY,QAAQ,KAAK,MAAM,IAAI;AACxD,WAAO,qBAAqB;AAAA,EAC9B;AACA,MAAI,SAAS,KAAK,OAAO,EAAG,QAAO,0BAA0B;AAC7D,MAAI,QAAQ,SAAS,aAAa,kBAAkB;AAClD;AAAA,MACE,0BAA0B,aAAa,gBAAgB;AAAA,IACzD;AAAA,EACF;AACA,MAAI,CAAC,QAAQ,QAAQ,CAAC,QAAQ,KAAM,QAAO,0BAA0B;AACrE,QAAM,QACJ,OAAO,WAAW,QAAQ,QAAQ,IAAI,MAAM,IAC5C,OAAO,WAAW,QAAQ,QAAQ,IAAI,MAAM;AAC9C,MAAI,QAAQ,aAAa,cAAc;AACrC,WAAO,WAAW,KAAK,wBAAwB,aAAa,YAAY,EAAE;AAAA,EAC5E;AACA,QAAM,OAAO,QAAQ,QAAQ,CAAC;AAC9B,QAAM,QAAQ,OAAO,KAAK,IAAI;AAC9B,MAAI,MAAM,SAAS,aAAa,SAAS;AACvC,WAAO,GAAG,MAAM,MAAM,uBAAuB,aAAa,OAAO,EAAE;AAAA,EACrE;AACA,aAAW,QAAQ,OAAO;AACxB,QAAI,CAAC,SAAS,KAAK,IAAI,KAAK,CAAC,SAAS,KAAK,OAAO,KAAK,IAAI,CAAC,CAAC,GAAG;AAC9D,aAAO,QAAQ,IAAI,kDAAkD;AAAA,IACvE;AACA,QAAI,KAAK,WAAW,KAAK,KAAK,KAAK,WAAW,MAAM,GAAG;AACrD,aAAO,QAAQ,IAAI,eAAe;AAAA,IACpC;AAAA,EACF;AACA,QAAM,kBAAkB,wBAAwB,QAAQ,eAAe;AACvE,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA,GAAI,QAAQ,SAAS,SAAY,EAAE,MAAM,QAAQ,KAAK,IAAI,CAAC;AAAA,IAC3D,GAAI,QAAQ,SAAS,SAAY,EAAE,MAAM,QAAQ,KAAK,IAAI,CAAC;AAAA,IAC3D,GAAI,UAAU,EAAE,QAAQ,IAAI,CAAC;AAAA,IAC7B,GAAI,MAAM,SAAS,EAAE,KAAK,IAAI,CAAC;AAAA,IAC/B,GAAI,kBAAkB,EAAE,gBAAgB,IAAI,CAAC;AAAA,EAC/C;AACF;AAEO,SAAS,kBACdC,WAA8B,CAAC,GAClB;AACb,MACE,CAAC,kBAAkB;AAAA,IACjB,sBACEA,SAAQ,cAAc,QAAQ,IAAI;AAAA,IACpC,aAAaA,SAAQ,cAAc,QAAQ,IAAI;AAAA,IAC/C,mBAAmBA,SAAQ,WAAW,QAAQ,IAAI;AAAA,EACpD,CAAC,GACD;AACA,UAAM,IAAI;AAAA,MACR;AAAA,IAGF;AAAA,EACF;AACA,QAAM,YAAY,+BAA+BA,UAAS,OAAO;AAEjE,iBAAe,KACb,QACA,OACA,MACY;AACZ,QAAI;AACF,aAAO,MAAM,UAAU,KAAQ,QAAQ,OAAO,IAAI;AAAA,IACpD,SAAS,OAAO;AACd,UAAI,iBAAiB,6BAA6B;AAChD,cAAM,IAAI;AAAA,UACR,MAAM;AAAA,UACN,MAAM;AAAA,UACN,MAAM;AAAA,QACR;AAAA,MACF;AACA,YAAM;AAAA,IACR;AAAA,EACF;AAEA,SAAO;AAAA,IACL,MAAM,KAAK,SAAS;AAClB,aAAO;AAAA,QACL;AAAA,QACA;AAAA,QACA,yBAAyB,OAAO;AAAA,MAClC;AAAA,IACF;AAAA,IACA,MAAM,WAAW,SAAS;AACxB,UAAI,CAAC,eAAe,OAAO,GAAG;AAC5B,eAAO,IAAI,OAAO,OAAO,EAAE,MAAM,GAAG,EAAE,CAAC,2BAA2B;AAAA,MACpE;AACA,YAAM,SAAS,MAAM;AAAA,QACnB;AAAA,QACA,uBAAuB,mBAAmB,QAAQ,YAAY,CAAC,CAAC;AAAA,MAClE;AACA,aAAO,OAAO,eAAe;AAAA,IAC/B;AAAA,EACF;AACF;;;AClRO,IAAM,kBAAN,cAA8B,4BAA4B;AAAA,EAC7C,OAAO;AAC3B;AAGO,IAAM,qBAAN,cAAiC,MAAM;AAAA,EAC1B,OAAO;AAC3B;AAEO,IAAM,mBAAmB;AAEhC,IAAM,OAAO;AAEN,SAAS,OAAO,OAAwB;AAC7C,SAAO,KAAK,KAAK,KAAK;AACxB;AAGA,IAAM,YAAY,IAAI;AAAA,EACpB;AAAA;AACF;AACA,IAAM,eAAe,IAAI,IAAI,mBAAc;AAOpC,SAAS,YAAY,MAI1B;AACA,MAAI,UAAU;AACd,MAAI,MAAM;AACV,aAAW,MAAM,MAAM;AACrB,QAAI,UAAU,IAAI,EAAE,EAAG,YAAW;AAAA,aACzB,aAAa,IAAI,EAAE,EAAG,YAAW;AAAA,SACrC;AACH,YAAM;AACN;AAAA,IACF;AAAA,EACF;AACA,MAAI,KAAK;AACP,WAAO;AAAA,MACL,UAAU;AAAA,MACV,OAAO;AAAA,MACP,UAAU,WAAW,MAAM,IAAI,KAAK,KAAK,UAAU,GAAG;AAAA,IACxD;AAAA,EACF;AACA,QAAM,QAAQ,KAAK;AACnB,SAAO;AAAA,IACL,UAAU;AAAA,IACV;AAAA,IACA,UAAU,SAAS,KAAK,IAAI,KAAK,KAAK,QAAQ,EAAE;AAAA,EAClD;AACF;AAGO,SAAS,gBAAgB,SAA+B;AAC7D,MAAI,OAAO,QAAQ,OAAO,YAAY,CAAC,OAAO,QAAQ,EAAE,GAAG;AACzD,UAAM,IAAI;AAAA,MACR,uDAAuD,KAAK,UAAU,QAAQ,EAAE,CAAC;AAAA,IACnF;AAAA,EACF;AACA,MAAI,OAAO,QAAQ,SAAS,YAAY,CAAC,QAAQ,KAAK,KAAK,GAAG;AAC5D,UAAM,IAAI,mBAAmB,+BAA+B;AAAA,EAC9D;AACA,QAAM,EAAE,UAAU,SAAS,IAAI,YAAY,QAAQ,IAAI;AACvD,MAAI,WAAW,kBAAkB;AAC/B,UAAM,IAAI;AAAA,MACR,aAAa,QAAQ,IAAI,QAAQ,2BAA2B,gBAAgB;AAAA,IAC9E;AAAA,EACF;AACA,MACE,QAAQ,YAAY,UACpB,QAAQ,YAAY,mBACpB,QAAQ,YAAY,eACpB;AACA,UAAM,IAAI;AAAA,MACR;AAAA,IACF;AAAA,EACF;AACF;AAEA,IAAM,cACJ;AAUK,IAAM,YAAN,MAAgB;AAAA,EACJ;AAAA,EAEjB,YAAYC,WAA4B,CAAC,GAAG;AAC1C,UAAM,aACJ;AAAA,OACGA,SAAQ,cAAc,QAAQ,IAAI,0BAClCA,SAAQ,cAAc,QAAQ,IAAI,iBAClCA,SAAQ,WAAW,QAAQ,IAAI;AAAA,IAClC,KAAK,kBAAkB;AACzB,QAAI,YAAY;AACd,WAAK,YAAY,+BAA+BA,UAAS,KAAK;AAAA,IAChE,WAAW,CAACA,SAAQ,cAAc;AAChC,YAAM,IAAI,MAAM,WAAW;AAAA,IAC7B;AAAA,EACF;AAAA;AAAA,EAGA,IAAI,UAAmB;AACrB,WAAO,KAAK,cAAc;AAAA,EAC5B;AAAA,EAEA,MAAM,KAAK,SAAiD;AAC1D,oBAAgB,OAAO;AACvB,QAAI,CAAC,KAAK,UAAW,OAAM,IAAI,MAAM,WAAW;AAChD,QAAI;AACF,aAAO,MAAM,KAAK,UAAU,KAAoB,QAAQ,aAAa;AAAA,QACnE,IAAI,QAAQ;AAAA,QACZ,MAAM,QAAQ;AAAA,QACd,SAAS,QAAQ,WAAW;AAAA,MAC9B,CAAC;AAAA,IACH,SAAS,OAAO;AACd,UAAI,iBAAiB,6BAA6B;AAChD,cAAM,IAAI;AAAA,UACR,MAAM;AAAA,UACN,MAAM;AAAA,UACN,MAAM;AAAA,QACR;AAAA,MACF;AACA,YAAM;AAAA,IACR;AAAA,EACF;AACF;AAEO,SAAS,gBAAgBA,WAA4B,CAAC,GAAc;AACzE,SAAO,IAAI,UAAUA,QAAO;AAC9B;;;ACrIO,IAAM,uBAAN,cAAmC,4BAA4B;AAAA,EAClD,OAAO;AAC3B;AAiBA,IAAMC,QAAO;AAEb,SAAS,iBAAiB,IAAmB;AAC3C,MAAI,OAAO,OAAO,YAAY,CAACA,MAAK,KAAK,EAAE,GAAG;AAC5C,UAAM,IAAI;AAAA,MACR;AAAA,MACA,gEAAgE,KAAK,UAAU,EAAE,CAAC;AAAA,IACpF;AAAA,EACF;AACF;AAEA,SAAS,gCACP,SACA,OACAC,UAC2B;AAC3B,QAAM,YAAY,+BAA+BA,UAAS,KAAK;AAE/D,iBAAe,KACb,QACA,OACA,MACY;AACZ,QAAI;AACF,aAAO,MAAM,UAAU,KAAQ,QAAQ,IAAI,OAAO,GAAG,KAAK,IAAI,IAAI;AAAA,IACpE,SAAS,OAAO;AACd,UAAI,iBAAiB,6BAA6B;AAChD,cAAM,IAAI;AAAA,UACR,MAAM;AAAA,UACN,MAAM;AAAA,UACN,MAAM;AAAA,QACR;AAAA,MACF;AACA,YAAM;AAAA,IACR;AAAA,EACF;AAEA,SAAO;AAAA,IACL,MAAM,aAAa,SAAS;AAC1B,uBAAiB,QAAQ,EAAE;AAC3B,UAAI,CAAC,QAAQ,YAAY,CAAC,QAAQ,UAAU;AAC1C,cAAM,IAAI;AAAA,UACR;AAAA,UACA;AAAA,QACF;AAAA,MACF;AACA,aAAO,KAAkB,QAAQ,aAAa;AAAA,QAC5C,IAAI,QAAQ;AAAA,QACZ,MAAM;AAAA,QACN,UAAU,QAAQ;AAAA,QAClB,UAAU,QAAQ;AAAA,QAClB,GAAI,QAAQ,aAAa,EAAE,YAAY,QAAQ,WAAW,IAAI,CAAC;AAAA,MACjE,CAAC;AAAA,IACH;AAAA,IACA,MAAM,SAAS,SAAS;AACtB,uBAAiB,QAAQ,EAAE;AAC3B,UAAI,OAAO,QAAQ,SAAS,YAAY,CAAC,QAAQ,KAAK,KAAK,GAAG;AAC5D,cAAM,IAAI,qBAAqB,KAAK,6BAA6B;AAAA,MACnE;AACA,aAAO,KAAkB,QAAQ,aAAa;AAAA,QAC5C,IAAI,QAAQ;AAAA,QACZ,MAAM;AAAA,QACN,MAAM,QAAQ;AAAA,MAChB,CAAC;AAAA,IACH;AAAA,IACA,MAAM,YAAY;AAChB,YAAM,UAAU,MAAM;AAAA,QACpB;AAAA,QACA;AAAA,MACF;AACA,aAAO,QAAQ;AAAA,IACjB;AAAA,EACF;AACF;AAOO,SAAS,qBACdA,WAAiC,CAAC,GAClB;AAChB,SAAO,gCAAgC,YAAY,YAAYA,QAAO;AACxE;;;ACxKO,IAAM,yBAAyB;AAAA,EACpC,SAAS;AAAA,EACT,cAAc;AAAA,EACd,gBAAgB;AAAA,EAChB,eAAe;AAAA;AAAA,EAEf,gBAAgB;AAClB;AA8CO,IAAM,oBAAN,cAAgC,4BAA4B;AAAA,EAC/C,OAAO;AAC3B;AAEA,IAAMC,QAAO;AACb,IAAM,YAAY;AAClB,IAAM,gBAAgB;AAGf,SAAS,oBACd,SACoB;AACpB,MAAI,OAAO,QAAQ,OAAO,YAAY,CAACA,MAAK,KAAK,QAAQ,EAAE,GAAG;AAC5D,WAAO;AAAA,EACT;AACA,MAAI,OAAO,QAAQ,SAAS,YAAY,QAAQ,KAAK,WAAW,MAAM,GAAG;AACvE,WAAO;AAAA,EACT;AACA,MAAI,CAAC,UAAU,KAAK,QAAQ,IAAI,GAAG;AACjC,WAAO;AAAA,EACT;AACA,QAAM,aAAa,QAAQ,cAAc,CAAC;AAC1C,MAAI,OAAO,eAAe,YAAY,MAAM,QAAQ,UAAU,GAAG;AAC/D,WAAO;AAAA,EACT;AACA,QAAM,UAAU,OAAO,QAAQ,UAAU;AACzC,QAAM,SAAS;AACf,MAAI,QAAQ,SAAS,OAAO,SAAS;AACnC,WAAO,WAAW,OAAO,OAAO;AAAA,EAClC;AACA,MAAI,QAAQ;AACZ,aAAW,CAAC,KAAK,KAAK,KAAK,SAAS;AAClC,QAAI,CAAC,cAAc,KAAK,GAAG,KAAK,IAAI,SAAS,OAAO,cAAc;AAChE,aAAO,kBAAkB,GAAG,uCAAuC,OAAO,YAAY;AAAA,IACxF;AACA,QAAI,IAAI,YAAY,EAAE,WAAW,OAAO,cAAc,GAAG;AACvD,aAAO,iCAAiC,OAAO,cAAc;AAAA,IAC/D;AACA,QAAI,OAAO,UAAU,UAAU;AAC7B,aAAO,cAAc,GAAG;AAAA,IAC1B;AACA,QAAI,MAAM,SAAS,OAAO,gBAAgB;AACxC,aAAO,cAAc,GAAG,oBAAoB,OAAO,cAAc;AAAA,IACnE;AACA,aAAS,OAAO,WAAW,GAAG,IAAI,OAAO,WAAW,KAAK;AAAA,EAC3D;AACA,MAAI,QAAQ,OAAO,eAAe;AAChC,WAAO,qBAAqB,OAAO,aAAa;AAAA,EAClD;AACA,SAAO;AACT;AAMO,IAAM,cAAN,MAAkB;AAAA,EACN;AAAA;AAAA,EAGjB,YAAYC,WAA8B,CAAC,GAAG;AAC5C,SAAK,YAAY;AAAA,MACfA;AAAA,MACA;AAAA,IACF;AAAA,EACF;AAAA;AAAA,EAGA,MAAM,kBACJ,SACkC;AAClC,UAAM,UAAU,oBAAoB,OAAO;AAC3C,QAAI,QAAS,OAAM,IAAI,kBAAkB,KAAK,OAAO;AACrD,WAAO,KAAK,KAA8B,QAAQ,gBAAgB;AAAA,MAChE,IAAI,QAAQ;AAAA,MACZ,MAAM,QAAQ;AAAA,MACd,GAAI,QAAQ,aAAa,EAAE,YAAY,QAAQ,WAAW,IAAI,CAAC;AAAA,IACjE,CAAC;AAAA,EACH;AAAA;AAAA,EAGA,MAAM,QAAQ,QAA+B;AAC3C,UAAM,KAAK,KAAc,UAAU,SAAS,MAAM,CAAC;AAAA,EACrD;AAAA;AAAA,EAGA,MAAM,KAAK,QAAoC;AAC7C,WAAO,KAAK,KAAgB,OAAO,SAAS,MAAM,CAAC;AAAA,EACrD;AAAA,EAEA,MAAc,KACZ,QACA,OACA,MACY;AACZ,QAAI;AACF,YAAM,WAAW,MAAM,KAAK,UAAU,QAAQ,QAAQ,OAAO,IAAI;AACjE,YAAMC,QAAO,MAAM,SAAS,KAAK;AACjC,aAAQA,QAAO,KAAK,MAAMA,KAAI,IAAI;AAAA,IACpC,SAAS,OAAO;AACd,UAAI,iBAAiB,6BAA6B;AAChD,cAAM,IAAI;AAAA,UACR,MAAM;AAAA,UACN,MAAM;AAAA,UACN,MAAM;AAAA,QACR;AAAA,MACF;AACA,YAAM;AAAA,IACR;AAAA,EACF;AACF;AAEA,SAAS,SAAS,QAAwB;AACxC,MAAI,OAAO,WAAW,YAAY,CAAC,yBAAyB,KAAK,MAAM,GAAG;AACxE,UAAM,IAAI,kBAAkB,KAAK,yBAAyB;AAAA,EAC5D;AACA,SAAO,gBAAgB,MAAM;AAC/B;AAGO,SAAS,kBACdD,WAA8B,CAAC,GAClB;AACb,SAAO,IAAI,YAAYA,QAAO;AAChC;;;AC7NA,yBAA8B;AAA9B;AAiDO,IAAM,uBAAuB;AA0B7B,IAAM,uBAAN,cAAmC,4BAA4B;AAAA,EAClD,OAAO;AAC3B;AAEO,SAAS,qBACdE,WAAkC,CAAC,GACnB;AAChB,QAAM,YAAY,+BAA+BA,UAAS,UAAU;AACpE,iBAAe,KACb,QACA,OACA,MACY;AACZ,QAAI;AACF,aAAO,MAAM,UAAU,KAAQ,QAAQ,OAAO,IAAI;AAAA,IACpD,SAAS,OAAO;AACd,UAAI,iBAAiB,6BAA6B;AAChD,cAAM,IAAI;AAAA,UACR,MAAM;AAAA,UACN,MAAM;AAAA,UACN,MAAM;AAAA,QACR;AAAA,MACF;AACA,YAAM;AAAA,IACR;AAAA,EACF;AACA,SAAO;AAAA,IACL,eAAe,EAAE,WAAW,WAAW,GAAG;AACxC,iBAAW,CAAC,MAAM,KAAK,KAAK;AAAA,QAC1B,CAAC,aAAa,SAAS;AAAA,QACvB,CAAC,cAAc,UAAU;AAAA,MAC3B,GAAY;AACV,YAAI,CAAC,eAAe,KAAK,SAAS,EAAE,GAAG;AACrC,gBAAM,IAAI,UAAU,GAAG,IAAI,kCAAkC;AAAA,QAC/D;AAAA,MACF;AACA,aAAO,KAAK,QAAQ,6BAA6B;AAAA,QAC/C;AAAA,QACA;AAAA,MACF,CAAC;AAAA,IACH;AAAA,IACA,SAAS;AACP,aAAO,KAAK,OAAO,kBAAkB;AAAA,IACvC;AAAA,EACF;AACF;AAyBA,SAAS,aAAgC;AAKvC,QAAM,WAAO;AAAA,IACX,OAAO,eAAe,WAAW,aAAa,YAAY;AAAA,EAC5D;AACA,MAAI;AACF,UAAM,MAAM,KAAK,QAAQ;AAGzB,WAAO,IAAI,WAAW;AAAA,EACxB,QAAQ;AACN,UAAM,IAAI;AAAA,MACR;AAAA,IACF;AAAA,EACF;AACF;AAeO,SAAS,mBACd,UACA,YAA0B,OACZ;AACd,QAAM,OAAO,IAAI,IAAI,SAAS,UAAU;AACxC,QAAM,WAAW,KAAK,SAAS,QAAQ,QAAQ,EAAE;AACjD,SAAO,OAAO,OAAO,OAAO,CAAC,MAAM;AACjC,UAAM,WAAW,IAAI;AAAA,MACnB,OAAO,UAAU,YAAY,iBAAiB,MAAM,QAAQ,MAAM;AAAA,IACpE;AACA,UAAM,aAAa,GAAG,oBAAoB,GAAG,SAAS,QAAQ,GAAG,SAAS,MAAM;AAChF,UAAM,UAAU,KAAK,UAAU,OAAO,YAAY;AAClD,UAAM,OAAO,OAAO,KAAK,SAAS,WAAW,KAAK,OAAO;AACzD,UAAM,EAAE,cAAc,IAAI,wBAAwB;AAAA,MAChD,WAAW,SAAS;AAAA,MACpB;AAAA,MACA,MAAM;AAAA,MACN,MAAM,QAAQ;AAAA,MACd,OAAO,SAAS;AAAA,IAClB,CAAC;AACD,UAAM,UAAU,IAAI,QAAQ,KAAK,OAAO;AACxC,YAAQ,IAAI,iBAAiB,aAAa;AAC1C,UAAM,SAAS,GAAG,KAAK,MAAM,GAAG,QAAQ,GAAG,sBAAsB,GAAG,UAAU;AAC9E,UAAM,WAAW,MAAM,UAAU,QAAQ,EAAE,GAAG,MAAM,QAAQ,QAAQ,CAAC;AACrE,QACE,SAAS,OACR,SAAS,QAAQ,IAAI,cAAc,KAAK,IAAI,SAAS,MAAM,GAC5D;AACA,aAAO;AAAA,IACT;AAIA,UAAM,WACH,MAAM,SAAS,KAAK,EAAE,MAAM,MAAM,EAAE,GAAG,KAAK,KAC7C,6BAA6B,SAAS,MAAM;AAC9C,WAAO,IAAI;AAAA,MACT,KAAK,UAAU;AAAA,QACb,OAAO;AAAA,UACL,MAAM;AAAA,UACN,MAAM;AAAA,UACN;AAAA,QACF;AAAA,MACF,CAAC;AAAA,MACD;AAAA,QACE,QAAQ,SAAS;AAAA,QACjB,SAAS;AAAA,UACP,gBAAgB;AAAA,UAChB,uBAAuB;AAAA,UACvB,GAAI,SAAS,QAAQ,IAAI,aAAa,IAClC,EAAE,eAAe,SAAS,QAAQ,IAAI,aAAa,EAAY,IAC/D,CAAC;AAAA,QACP;AAAA,MACF;AAAA,IACF;AAAA,EACF;AACF;AA2BO,SAAS,mBAAmBA,WAA+B,CAAC,GAAW;AAC5E,QAAM,cAAcA,SAAQ,UAAU,WAAW;AACjD,QAAM,kBAAkB;AAAA,IACtBA,SAAQ,cAAcA,SAAQ,cAAcA,SAAQ;AAAA,EACtD;AAGA,MAAI,CAAC,mBAAmBA,SAAQ,QAAQ;AACtC,WAAO,IAAI,YAAYA,SAAQ,QAAQA,SAAQ,MAAM;AAAA,EACvD;AACA,MAAI,CAAC,mBAAmB,CAAC,kBAAkB,GAAG;AAC5C,QAAI,CAACA,SAAQ,QAAQ;AACnB,YAAM,IAAI;AAAA,QACR;AAAA,MAGF;AAAA,IACF;AACA,WAAO,IAAI,YAAYA,SAAQ,QAAQA,SAAQ,MAAM;AAAA,EACvD;AACA,QAAM,WAAW,wBAAwBA,UAAS,UAAU;AAC5D,QAAM,UAAU,IAAI,IAAI,SAAS,UAAU;AAC3C,QAAM,WAAW,QAAQ,aAAa,UAAU,SAAS;AACzD,SAAO,IAAI;AAAA;AAAA;AAAA,IAGT;AAAA,IACA;AAAA,MACE,mBAAmB;AAAA,MACnB,GAAGA,SAAQ;AAAA,MACX,MAAM,QAAQ;AAAA,MACd,MAAM,QAAQ,SAAS,aAAa,SAAS,KAAK;AAAA,MAClD;AAAA,MACA,WAAW;AAAA;AAAA,MAEX,eAAe,YAAY;AAAA,MAAC;AAAA,MAC5B,YAAY,YAAY;AAAA,QACtB,mBAAmB,UAAUA,SAAQ,KAAK;AAAA,MAC5C;AAAA,IACF;AAAA,EACF;AACF;;;AC9SO,SAAS,OAAkC,MAA4B;AAC5E,SAAO,KAAK,WAAW,GAAG;AAC5B;;;ACgLO,SAAS,aA0Bd,kBACA,sBACA,iCAiBA,6BA+BG,cAgCH;AAGA,MAAI;AAeJ,MAAI;AAeJ,MAAI,OAAO,oCAAoC,UAAU;AACvD,QAAI,OAAO,6BAA6B,YAAY;AAClD,wBAAkB;AAAA,IACpB,OAAO;AACL,YAAM,IAAI,MAAM,yCAAyC;AAAA,IAC3D;AACA,eAAW;AAAA,EACb,OAAO;AACL,sBAAkB;AAClB,QAAI,OAAO,6BAA6B,YAAY;AAClD,iBAAW,CAAC,0BAA0B,GAAG,YAAY;AAAA,IACvD,OAAO;AACL,YAAM,IAAI,MAAM,gCAAgC;AAAA,IAClD;AAAA,EACF;AAEA,MACE,OAAO,oBAAoB,KAC3B,OAAO,oCAAoC,UAC3C;AACA,UAAM,IAAI,MAAM,uCAAuC;AAAA,EACzD;AAEA,SAAO;AAAA,IACL,eAAe;AAAA,IACf,OAAO,OAAO,oBAAoB,IAAI,uBAAuB;AAAA,IAC7D,SAAS,OAAO,oBAAoB,IAC/B,kCACD;AAAA,IACJ;AAAA,IACA;AAAA,EACF;AACF;;;AC/UO,IAAM,UAAU,CAyBrB,kBACA,MACA,oBAcG,aAeA;AACH,SAAO,aAiBL,kBAAkB,MAAM,UAAU,iBAAiB,GAAG,QAAQ;AAClE;;;AC3EO,IAAM,MAAM,CAyBjB,kBACA,MACA,oBAcG,aAeA;AACH,SAAO,aAiBL,kBAAkB,MAAM,OAAO,iBAAiB,GAAG,QAAQ;AAC/D;;;AC3EO,IAAM,OAAO,CAyBlB,kBACA,MACA,oBAcG,aAeA;AACH,SAAO,aAiBL,kBAAkB,MAAM,QAAQ,iBAAiB,GAAG,QAAQ;AAChE;;;AC1EO,IAAM,aAAa,CAyBxB,kBACA,MACA,oBAcG,aAeA;AACH,SAAO,aAiBL,kBAAkB,MAAM,cAAc,iBAAiB,GAAG,QAAQ;AAkCtE;;;AC7GO,IAAM,UAAU,CAyBrB,kBACA,MACA,oBAcG,aAeA;AACH,SAAO,aAiBL,kBAAkB,MAAM,WAAW,iBAAiB,GAAG,QAAQ;AACnE;;;AC3EO,IAAM,QAAQ,CAyBnB,kBACA,MACA,oBAcG,aAeA;AACH,SAAO,aAiBL,kBAAkB,MAAM,SAAS,iBAAiB,GAAG,QAAQ;AACjE;;;AC3EO,IAAM,OAAO,CAyBlB,kBACA,MACA,oBAcG,aAeA;AACH,SAAO,aAiBL,kBAAkB,MAAM,QAAQ,iBAAiB,GAAG,QAAQ;AAChE;;;AC3EO,IAAM,MAAM,CAyBjB,kBACA,MACA,oBAcG,aAeA;AACH,SAAO,aAiBL,kBAAkB,MAAM,OAAO,iBAAiB,GAAG,QAAQ;AAC/D;;;AC3EO,IAAMC,SAAQ,CAyBnB,kBACA,MACA,oBAcG,aAeA;AACH,SAAO,aAiBL,kBAAkB,MAAM,SAAS,iBAAiB,GAAG,QAAQ;AACjE;;;AC3EO,SAAS,iBAqBd,kBACA,kBAeA,aAUA;AACA,SAAO;AACT;;;ACtDO,IAAM,eAAoD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAe/D,KAAK;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAiBL,KAAK;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAmBL,KAAK;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAcL,KAAK;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAeL,KAAK;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAmBL,KAAK;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAmBL,KAAK;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAeL,KAAK;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAwBL,KAAK;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;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;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAuEL,KAAK;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;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAsCL,KAAK;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAA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","names":["trace","corsMiddleware","import_common","middleware","import_common","import_api","import_semantic_conventions","import_common","import_api","import_semantic_conventions","import_common","meta","pino","dotenv","OTEL_ATTR_SERVICE_NAME","import_common","import_common","import_common","import_common","text","import_crypto","import_jose","context","joseErrors","import_common","import_common","import_core","LISTENERS","import_crypto","logger","import_common","import_validator","middleware","import_crypto","import_crypto","options","options","text","options","options","options","E164","options","E164","options","text","options","trace","import_common","options","version","import_validator","parse","import_common","import_common","import_semantic_conventions","parse","data","import_common","key","options","metrics","record"]}
|