shokupan 0.0.1 → 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +1 @@
1
- {"version":3,"file":"index.cjs","sources":["../src/response.ts","../src/context.ts","../src/symbol.ts","../src/types.ts","../src/decorators.ts","../src/di.ts","../src/util/instrumentation.ts","../src/middleware.ts","../src/request.ts","../src/util/async-hooks.ts","../src/util/deep-merge.ts","../src/router.ts","../src/shokupan.ts","../src/plugins/auth.ts","../src/plugins/compression.ts","../src/plugins/cors.ts","../src/plugins/rate-limit.ts","../src/plugins/scalar.ts","../src/plugins/security-headers.ts","../src/plugins/session.ts","../src/plugins/validation.ts"],"sourcesContent":["\n/**\n * Custom response class to handle response state (headers, status) \n * before the actual Response object is created.\n */\nexport class ShokupanResponse {\n private _headers = new Headers();\n private _status = 200;\n\n /**\n * Get the current headers\n */\n get headers() {\n return this._headers;\n }\n\n /**\n * Get the current status code\n */\n get status() {\n return this._status;\n }\n\n /**\n * Set the status code\n */\n set status(code: number) {\n this._status = code;\n }\n\n /**\n * Set a response header\n * @param key Header name\n * @param value Header value\n */\n public set(key: string, value: string) {\n this._headers.set(key, value);\n return this;\n }\n\n /**\n * Append to a response header\n * @param key Header name\n * @param value Header value\n */\n public append(key: string, value: string) {\n this._headers.append(key, value);\n return this;\n }\n\n /**\n * Get a response header value\n * @param key Header name\n */\n public get(key: string) {\n return this._headers.get(key);\n }\n\n /**\n * Check if a header exists\n * @param key Header name\n */\n public has(key: string) {\n return this._headers.has(key);\n }\n}\n","\nimport type { BodyInit } from 'bun';\nimport type { ShokupanRequest } from './request';\nimport { ShokupanResponse } from './response';\nimport type { CookieOptions } from './types';\n\n// Shim for HeadersInit if not available globally in some envs\ntype HeadersInit = Headers | Record<string, string> | [string, string][];\n\nexport class ShokupanContext<State extends Record<string, any> = Record<string, any>> {\n public readonly url: URL;\n public params: Record<string, string> = {};\n public state: State;\n\n public readonly response: ShokupanResponse;\n\n constructor(\n public readonly request: ShokupanRequest<any>,\n state?: State\n ) {\n this.url = new URL(request.url);\n this.state = state || {} as State;\n this.response = new ShokupanResponse();\n }\n\n /**\n * Base request\n */\n get req() { return this.request; }\n /**\n * HTTP method\n */\n get method() { return this.request.method; }\n /**\n * Request path\n */\n get path() { return this.url.pathname; }\n /**\n * Request query params\n */\n get query() { return Object.fromEntries(this.url.searchParams); }\n /**\n * Request headers\n */\n get headers() { return this.request.headers; }\n\n /**\n * Base response object\n */\n get res() { return this.response; }\n\n /**\n * Helper to set a header on the response\n */\n public set(key: string, value: string) {\n this.response.set(key, value);\n return this;\n }\n\n /**\n * Set a cookie\n * @param name Cookie name\n * @param value Cookie value\n * @param options Cookie options\n */\n public setCookie(name: string, value: string, options: CookieOptions = {}) {\n let cookie = `${encodeURIComponent(name)}=${encodeURIComponent(value)}`;\n\n if (options.maxAge) cookie += `; Max-Age=${Math.floor(options.maxAge)}`;\n if (options.expires) cookie += `; Expires=${options.expires.toUTCString()}`;\n if (options.httpOnly) cookie += `; HttpOnly`;\n if (options.secure) cookie += `; Secure`;\n if (options.domain) cookie += `; Domain=${options.domain}`;\n if (options.path) cookie += `; Path=${options.path || '/'}`;\n if (options.sameSite) {\n const sameSite = typeof options.sameSite === 'string'\n ? options.sameSite.toLowerCase()\n : options.sameSite\n ? 'strict'\n : 'lax'; // Default logic if boolean true, though usually explicit string is better\n // Ideally follow specific behavior: express-session/cookies uses boolean to mean strict/lax sometimes?\n // Let's stick to standard strings mostly, but maybe map boolean to Strict/Lax?\n // Standard: SameSite=Lax (default if missing but we are setting it only if present)\n // If strictly boolean true -> Strict, false -> (don't set? or None? usually don't set)\n cookie += `; SameSite=${typeof options.sameSite === 'boolean' ? 'Strict' : (options.sameSite.charAt(0).toUpperCase() + options.sameSite.slice(1))}`;\n }\n if (options.priority) {\n cookie += `; Priority=${options.priority.charAt(0).toUpperCase() + options.priority.slice(1)}`;\n }\n\n this.response.append('Set-Cookie', cookie);\n return this;\n }\n\n private mergeHeaders(headers?: HeadersInit): Headers {\n const h = new Headers(this.response.headers);\n if (headers) {\n new Headers(headers).forEach((v, k) => h.set(k, v));\n }\n return h;\n }\n\n /**\n * Send a response\n * @param body Response body\n * @param options Response options\n * @returns Response\n */\n public send(body?: BodyInit, options?: ResponseInit) {\n const headers = this.mergeHeaders(options?.headers as any);\n const status = options?.status ?? this.response.status;\n return new Response(body, { status, headers });\n }\n\n /**\n * Read request body\n */\n async body<T = any>(): Promise<T> {\n const contentType = this.request.headers.get(\"content-type\");\n if (contentType?.includes(\"application/json\")) {\n return this.request.json() as any;\n }\n if (contentType?.includes(\"multipart/form-data\") || contentType?.includes(\"application/x-www-form-urlencoded\")) {\n return this.request.formData() as any;\n }\n return this.request.text() as any;\n }\n\n /**\n * Respond with a JSON object\n */\n json(data: any, status?: number, headers?: HeadersInit) {\n const finalHeaders = this.mergeHeaders(headers);\n finalHeaders.set(\"content-type\", \"application/json\");\n const finalStatus = status ?? this.response.status;\n return new Response(JSON.stringify(data), { status: finalStatus, headers: finalHeaders });\n }\n\n /**\n * Respond with a text string\n */\n text(data: string, status?: number, headers?: HeadersInit) {\n const finalHeaders = this.mergeHeaders(headers);\n finalHeaders.set(\"content-type\", \"text/plain\");\n const finalStatus = status ?? this.response.status;\n return new Response(data, { status: finalStatus, headers: finalHeaders });\n }\n\n /**\n * Respond with HTML content\n */\n html(html: string, status?: number, headers?: HeadersInit) {\n const finalHeaders = this.mergeHeaders(headers);\n finalHeaders.set(\"content-type\", \"text/html\");\n const finalStatus = status ?? this.response.status;\n return new Response(html, { status: finalStatus, headers: finalHeaders });\n }\n\n /**\n * Respond with a redirect\n */\n redirect(url: string, status = 302) {\n const headers = this.mergeHeaders();\n headers.set('Location', url);\n return new Response(null, { status, headers });\n }\n\n /**\n * Respond with a status code\n * DOES NOT CHAIN!\n */\n status(status: number) {\n const headers = this.mergeHeaders();\n return new Response(null, { status, headers });\n }\n\n /**\n * Respond with a file\n */\n file(path: string, fileOptions?: BlobPropertyBag, responseOptions?: ResponseInit) {\n const headers = this.mergeHeaders(responseOptions?.headers as any);\n const status = responseOptions?.status ?? this.response.status;\n return new Response(Bun.file(path, fileOptions), { status, headers });\n }\n}\n","export const $isApplication = Symbol.for(\"Shokupan.app\");\nexport const $appRoot = Symbol.for(\"Shokupan.app-root\");\nexport const $isMounted = Symbol(\"Shokupan.isMounted\");\nexport const $routeMethods = Symbol(\"Shokupan.routeMethods\");\nexport const $routeArgs = Symbol(\"Shokupan.routeArgs\");\nexport const $controllerPath = Symbol(\"Shokupan.controllerPath\");\nexport const $middleware = Symbol(\"Shokupan.middleware\");\nexport const $isRouter = Symbol.for(\"Shokupan.router\");\nexport const $parent = Symbol.for(\"Shokupan.parent\");\nexport const $childRouters = Symbol.for(\"Shokupan.child-routers\");\nexport const $childControllers = Symbol.for(\"Shokupan.child-controllers\");\nexport const $mountPath = Symbol.for(\"Shokupan.mount-path\");\nexport const $dispatch = Symbol.for(\"Shokupan.dispatch\");","import type { OpenAPI } from '@scalar/openapi-types';\nimport type { ShokupanContext } from './context';\nimport { $isRouter } from \"./symbol\";\n\nexport type DeepPartial<T> = T extends object ? {\n [P in keyof T]?: DeepPartial<T[P]>;\n} : T;\n\nexport type MethodAPISpec = OpenAPI.Operation;\nexport type GuardAPISpec = DeepPartial<OpenAPI.Operation>;\nexport type RouterAPISpec = OpenAPI.Operation & Pick<Required<OpenAPI.Operation>, 'tags'> & { group: string; };\n\nexport interface OpenAPIOptions {\n info?: OpenAPI.Document['info'];\n servers?: OpenAPI.Document['servers'];\n components?: OpenAPI.Document['components'];\n tags?: OpenAPI.Document['tags'];\n externalDocs?: OpenAPI.Document['externalDocs'];\n defaultTagGroup?: string;\n defaultTag?: string;\n}\n\nexport interface CookieOptions {\n maxAge?: number;\n expires?: Date;\n httpOnly?: boolean;\n secure?: boolean;\n domain?: string;\n path?: string;\n sameSite?: boolean | 'lax' | 'strict' | 'none' | 'Lax' | 'Strict' | 'None';\n priority?: 'low' | 'medium' | 'high' | 'Low' | 'Medium' | 'High';\n}\n\n\nexport type ShokupanHandler<T extends Record<string, any> = Record<string, any>> = (ctx: ShokupanContext<T>, next?: NextFn) => Promise<any> | any;\nexport const HTTPMethods = [\"GET\", \"POST\", \"PUT\", \"DELETE\", \"PATCH\", \"HEAD\", \"OPTIONS\", \"ALL\"];\nexport type Method = \"GET\" | \"POST\" | \"PUT\" | \"DELETE\" | \"PATCH\" | \"OPTIONS\" | \"HEAD\" | \"ALL\";\n\nexport enum RouteParamType {\n BODY = \"BODY\",\n PARAM = \"PARAM\",\n QUERY = \"QUERY\",\n HEADER = \"HEADER\",\n REQUEST = \"REQUEST\",\n CONTEXT = \"CONTEXT\"\n}\n\nexport type NextFn = () => Promise<any>;\nexport type Middleware = (ctx: ShokupanContext<unknown>, next: NextFn) => Promise<any> | any;\n\nexport type ShokupanRouteConfig = DeepPartial<{\n name: string;\n group: string;\n openapi: DeepPartial<OpenAPI.Operation>;\n}>;\n\nexport type ShokupanRoute = {\n method: Method;\n path: string;\n regex: RegExp;\n keys: string[];\n handler: ShokupanHandler;\n handlerSpec?: MethodAPISpec;\n group?: string;\n guards?: {\n handler: ShokupanHandler;\n spec?: GuardAPISpec;\n }[];\n};\n\nexport type ShokupanConfig<T extends Record<string, any> = Record<string, any>> = DeepPartial<{\n port: number;\n hostname: string;\n development: boolean;\n enableAsyncLocalStorage: boolean;\n httpLogger: (ctx: ShokupanContext<T>) => void;\n logger: {\n verbose: boolean;\n info: (msg: string, props: Record<string, any>) => void;\n debug: (msg: string, props: Record<string, any>) => void;\n warning: (msg: string, props: Record<string, any>) => void;\n error: (msg: string, props: Record<string, any>) => void;\n /**\n * Something fatally went wrong and the application cannot continue.\n */\n fatal: (msg: string, props: Record<string, any>) => void;\n };\n // Open for extension\n [key: string]: any;\n}>;\n\n\nexport interface RequestOptions {\n path?: string;\n url?: string;\n method?: Method;\n headers?: Record<string, string>;\n body?: any;\n query?: Record<string, string>;\n}\n\nexport interface ProcessResult {\n status: number;\n headers: Record<string, string>;\n data: any;\n}\n\nexport type ShokupanController<T = any> = (new (...args: any[]) => T) & {\n [$isRouter]?: undefined;\n};\n\nexport interface StaticServeHooks<T extends Record<string, any>> {\n onRequest?: (ctx: ShokupanContext<T>) => Promise<Response | void> | Response | void;\n onResponse?: (ctx: ShokupanContext<T>, response: Response) => Promise<Response> | Response;\n}\n\nexport interface StaticServeOptions<T extends Record<string, any>> {\n /**\n * Root directory to serve files from.\n * Can be an absolute path or relative to the CWD.\n */\n root?: string;\n /**\n * Whether to list directory contents if no index file is found.\n * @default false\n */\n listDirectory?: boolean;\n /**\n * Index file(s) to look for when a directory is requested.\n * @default ['index.html', 'index.htm']\n */\n index?: string | string[];\n /**\n * Hooks to intercept requests/responses.\n */\n hooks?: StaticServeHooks<T>;\n /**\n * How to treat dotfiles (files starting with .)\n * 'allow': Serve them\n * 'deny': Return 403\n * 'ignore': Return 404\n * @default 'ignore'\n */\n dotfiles?: 'allow' | 'deny' | 'ignore';\n /**\n * Regex or glob patterns to exclude\n */\n exclude?: (string | RegExp)[];\n /**\n * Try to append these extensions to the path if the file is not found.\n * e.g. ['html', 'htm']\n */\n extensions?: string[];\n /**\n * OpenAPI specification for the static route.\n */\n openapi?: MethodAPISpec;\n}\n","import { $controllerPath, $middleware, $routeArgs, $routeMethods } from \"./symbol\";\nimport { type Method, type Middleware, RouteParamType } from \"./types\";\n\n/**\n * Class Decorator: Defines the base path for a controller.\n */\nexport function Controller(path: string = \"/\") {\n return (target: any) => {\n target[$controllerPath] = path;\n };\n}\n\n/**\n * Decorator: Applies middleware to a class or method.\n */\nexport function Use(...middleware: Middleware[]) {\n return (target: any, propertyKey?: string, descriptor?: PropertyDescriptor) => {\n // If propertyKey is undefined, it's a class decorator\n if (!propertyKey) {\n const existing = target[$middleware] || [];\n target[$middleware] = [...existing, ...middleware];\n }\n // Method decorator\n else {\n if (!target[$middleware]) {\n target[$middleware] = new Map();\n }\n const existing = target[$middleware].get(propertyKey) || [];\n target[$middleware].set(propertyKey, [...existing, ...middleware]);\n }\n };\n}\n\n// --- Parameter Decorators ---\n\nfunction createParamDecorator(type: RouteParamType) {\n return (name?: string) => {\n return (target: any, propertyKey: string, parameterIndex: number) => {\n if (!target[$routeArgs]) {\n target[$routeArgs] = new Map();\n }\n if (!target[$routeArgs].has(propertyKey)) {\n target[$routeArgs].set(propertyKey, []);\n }\n target[$routeArgs].get(propertyKey).push({\n index: parameterIndex,\n type,\n name\n });\n };\n };\n}\n\nexport const Body = createParamDecorator(RouteParamType.BODY);\nexport const Param = createParamDecorator(RouteParamType.PARAM);\nexport const Query = createParamDecorator(RouteParamType.QUERY);\nexport const Headers = createParamDecorator(RouteParamType.HEADER);\nexport const Req = createParamDecorator(RouteParamType.REQUEST);\nexport const Ctx = createParamDecorator(RouteParamType.CONTEXT);\n\n/**\n * Creates a method decorator for a specific HTTP verb.\n * @param method HTTP Method\n */\nfunction createMethodDecorator(method: Method) {\n return (path: string = \"/\") => {\n return (target: any, propertyKey: string, descriptor: PropertyDescriptor) => {\n if (!target[$routeMethods]) {\n target[$routeMethods] = new Map();\n }\n\n target[$routeMethods].set(propertyKey, {\n method,\n path\n });\n };\n };\n}\n\nexport const Get = createMethodDecorator(\"GET\");\nexport const Post = createMethodDecorator(\"POST\");\nexport const Put = createMethodDecorator(\"PUT\");\nexport const Delete = createMethodDecorator(\"DELETE\");\nexport const Patch = createMethodDecorator(\"PATCH\");\nexport const Options = createMethodDecorator(\"OPTIONS\");\nexport const Head = createMethodDecorator(\"HEAD\");\nexport const All = createMethodDecorator(\"ALL\");\n","\n/**\n * Simple Dependency Injection Container\n */\nexport class Container {\n private static services = new Map<any, any>();\n\n public static register<T>(target: new (...args: any[]) => T, instance: T) {\n this.services.set(target, instance);\n }\n\n public static get<T>(target: new (...args: any[]) => T): T | undefined {\n return this.services.get(target);\n }\n\n public static has(target: any): boolean {\n return this.services.has(target);\n }\n\n public static resolve<T>(target: new (...args: any[]) => T): T {\n if (this.services.has(target)) {\n return this.services.get(target);\n }\n\n // Auto-instantiate if possible (transient)\n // Note: For full DI we would read constructor params here using 'design:paramtypes'\n // But Bun/Esbuild need distinct config for that.\n // For now, we assume simple instantiation or manual registration.\n const instance = new target();\n this.services.set(target, instance);\n return instance;\n }\n}\n\n/**\n * Decorator to mark a class as injectable (Service).\n */\nexport function Injectable() {\n return (target: any) => {\n // Just a marker for now, or could auto-register\n };\n}\n\n/**\n * Property Decorator: Injects a service.\n */\nexport function Inject(token: any) {\n return (target: any, key: string) => {\n Object.defineProperty(target, key, {\n get: () => Container.resolve(token),\n enumerable: true,\n configurable: true\n });\n };\n}\n","import { SpanKind, SpanStatusCode, trace } from \"@opentelemetry/api\";\nimport type { Middleware, ShokupanHandler } from \"../types\";\n\nimport { OTLPTraceExporter } from '@opentelemetry/exporter-trace-otlp-proto';\nimport { resourceFromAttributes } from '@opentelemetry/resources';\nimport { SimpleSpanProcessor } from '@opentelemetry/sdk-trace-base';\nimport { NodeTracerProvider } from '@opentelemetry/sdk-trace-node';\nimport { ATTR_SERVICE_NAME } from '@opentelemetry/semantic-conventions';\n\nconst provider = new NodeTracerProvider({\n resource: resourceFromAttributes({\n [ATTR_SERVICE_NAME]: 'basic-service',\n }),\n spanProcessors: [\n new SimpleSpanProcessor(\n new OTLPTraceExporter({\n url: 'http://localhost:4318/v1/traces', // Default OTLP port\n })\n )\n ],\n});\nprovider.register();\n\nconst tracer = trace.getTracer(\"shokupan.middleware\");\n\n/**\n * Wraps a middleware function with an OpenTelemetry span.\n */\nexport function traceMiddleware(fn: Middleware, name?: string): Middleware {\n const middlewareName = name || fn.name || \"anonymous middleware\";\n\n return async (ctx, next) => {\n return tracer.startActiveSpan(`middleware - ${middlewareName}`, {\n kind: SpanKind.INTERNAL,\n attributes: {\n \"code.function\": middlewareName,\n \"component\": \"shokupan.middleware\"\n }\n }, async (span) => {\n try {\n const result = await fn(ctx, next);\n return result;\n }\n catch (err: any) {\n span.recordException(err);\n span.setStatus({ code: SpanStatusCode.ERROR, message: err.message });\n throw err;\n }\n finally {\n span.end();\n }\n });\n };\n}\n\n/**\n * Wraps a route handler with an OpenTelemetry span.\n */\nexport function traceHandler(fn: ShokupanHandler | ((...args: any[]) => any), name: string): ShokupanHandler {\n return async function (this: any, ...args: any[]) {\n return tracer.startActiveSpan(`route handler - ${name}`, {\n kind: SpanKind.INTERNAL,\n attributes: {\n \"http.route\": name,\n \"component\": \"shokupan.route\"\n }\n }, async (span) => {\n try {\n const result = await (fn as Function).apply(this, args);\n return result;\n }\n catch (err: any) {\n span.recordException(err);\n span.setStatus({ code: SpanStatusCode.ERROR, message: err.message });\n throw err;\n }\n finally {\n span.end();\n }\n });\n };\n}\n","import type { ShokupanContext } from \"./context\";\nimport type { Middleware, NextFn } from './types';\nimport { traceMiddleware } from \"./util/instrumentation\";\n\n/**\n * Composes a list of middleware into a single function.\n * This is the onion model (Koa-style).\n */\nexport const compose = (middleware: Middleware[]) => {\n function fn(context: ShokupanContext<unknown>, next?: NextFn) {\n let runner: NextFn = next || (async () => { });\n\n for (let i = middleware.length - 1; i >= 0; i--) {\n const fn = traceMiddleware(middleware[i]);\n const nextStep = runner;\n let called = false;\n\n runner = async () => {\n if (called) throw new Error('next() called multiple times');\n called = true;\n return fn(context, nextStep);\n };\n }\n\n return runner();\n };\n\n return fn;\n};\n\n\n","import type { Method } from './types';\n\nexport type ShokupanRequestProps = {\n method: Method;\n url: string;\n headers: Headers;\n body: any;\n};\n\n/**\n * This class is used to create a request object.\n * It is used to make requests to the router.\n */\nclass ShokupanRequestBase {\n method: Method;\n url: string;\n headers: Headers;\n body: any;\n\n async json(): Promise<any> { return JSON.parse(this.body); }\n async text(): Promise<string> { return this.body; }\n async formData(): Promise<FormData> {\n if (this.body instanceof FormData) {\n return this.body;\n }\n return new Response(this.body, { headers: this.headers }).formData() as any;\n }\n\n constructor(props: ShokupanRequestProps) {\n Object.assign(this, props);\n if (!(this.headers instanceof Headers)) {\n this.headers = new Headers(this.headers);\n }\n }\n}\n\n/**\n * This type is used to add properties to the request object.\n */\nexport type ShokupanRequest<T> = ShokupanRequestBase & T;\n\ninterface ShokupanConstructor {\n new <T extends Record<string, any>>(props: ShokupanRequestProps): ShokupanRequest<T>;\n}\n\n/**\n * This class is used to create a request object.\n * It is used to make requests to the router.\n */\nexport const ShokupanRequest = ShokupanRequestBase as ShokupanConstructor;\n","\nimport { AsyncLocalStorage } from \"node:async_hooks\";\n\nexport const asyncContext = new AsyncLocalStorage<Map<string, any>>();\n\nexport function runInContext<T>(callback: () => T, initialStore = new Map<string, any>()): T {\n return asyncContext.run(initialStore, callback);\n}\n","/**\n * Simple object check.\n */\nexport function isObject(item: any): item is Record<string, any> {\n return (item && typeof item === 'object' && !Array.isArray(item));\n}\n\n/**\n * Deep merge two objects.\n * \n * - Arrays are concatenated.\n * - Objects are merged recursively.\n * - Primitives are overwritten.\n */\nexport function deepMerge<T extends Record<string, any>>(target: T, ...sources: Partial<T>[]): T {\n if (!sources.length) return target;\n const source = sources.shift();\n\n if (isObject(target) && isObject(source)) {\n for (const key in source) {\n if (isObject(source[key])) {\n if (!target[key]) Object.assign(target, { [key]: {} });\n deepMerge(target[key], source[key]);\n } else if (Array.isArray(source[key])) {\n if (!target[key]) Object.assign(target, { [key]: [] });\n // Concatenate arrays? Or overwrite? \n // For OpenAPI, often appending is good (e.g. tags, security). \n // But for things like 'servers', maybe we want overwrite or union?\n // Let's go with concatenation for now as a safe default for lists like parameters.\n (target as any)[key] = (target as any)[key].concat(source[key]);\n } else {\n Object.assign(target, { [key]: source[key] });\n }\n }\n }\n\n return deepMerge(target, ...sources);\n}\n","import type { OpenAPI } from '@scalar/openapi-types';\nimport { Eta } from 'eta';\nimport { readdir, stat } from 'fs/promises';\nimport { basename, join, resolve } from 'path';\nimport { ShokupanContext } from './context';\nimport { Container } from './di';\nimport { compose } from './middleware';\nimport { ShokupanRequest } from './request';\nimport type { Shokupan } from './shokupan';\nimport { $appRoot, $childControllers, $childRouters, $controllerPath, $dispatch, $isApplication, $isMounted, $isRouter, $middleware, $mountPath, $parent, $routeArgs, $routeMethods } from './symbol';\nimport type { GuardAPISpec, MethodAPISpec, OpenAPIOptions, ProcessResult, RequestOptions, ShokupanRouteConfig, StaticServeOptions } from './types';\nimport { HTTPMethods, RouteParamType, type Method, type ShokupanController, type ShokupanHandler, type ShokupanRoute } from './types';\nimport { asyncContext } from './util/async-hooks';\nimport { deepMerge } from './util/deep-merge';\nimport { traceHandler } from './util/instrumentation';\n\nconst eta = new Eta();\n\n\n// Shim for HeadersInit if not available globally\ntype HeadersInit = Headers | Record<string, string> | [string, string][];\n\n\nexport const RouterRegistry = new Map<string, ShokupanRouter<any>>();\n\nexport const ShokupanApplicationTree = {};\n\nexport class ShokupanRouter<T extends Record<string, any> = Record<string, any>> {\n // Internal marker to identify Router vs. Application\n private [$isApplication]: boolean = false;\n private [$isMounted]: boolean = false;\n private [$isRouter]: true = true;\n private [$appRoot]: Shokupan;\n private [$mountPath]: string = \"/\";\n\n private [$parent]: ShokupanRouter<T> | null = null;\n public [$childRouters]: ShokupanRouter<T>[] = [];\n public [$childControllers]: ShokupanController[] = [];\n\n get rootConfig() {\n return this[$appRoot]?.applicationConfig;\n }\n get root() {\n return this[$appRoot];\n }\n\n private routes: ShokupanRoute[] = [];\n private currentGuards: { handler: ShokupanHandler<T>; spec?: GuardAPISpec; }[] = [];\n\n constructor(\n private readonly config?: ShokupanRouteConfig\n ) {\n }\n\n private isRouterInstance(target: ShokupanController | ShokupanController<T> | ShokupanRouter | ShokupanRouter<T>): target is ShokupanRouter<T> {\n // Check if it's an object and has your specific symbol\n return typeof target === 'object' && target !== null && $isRouter in target;\n }\n\n /**\n * Mounts a controller instance to a path prefix.\n * \n * Controller can be a convection router or an arbitrary class.\n * \n * Routes are derived from method names:\n * - get(ctx) -> GET /prefix/\n * - getUsers(ctx) -> GET /prefix/users\n * - postCreate(ctx) -> POST /prefix/create\n */\n public mount(prefix: string, controller: ShokupanController | ShokupanController<T> | ShokupanRouter | ShokupanRouter<T>) {\n\n if (this.isRouterInstance(controller)) {\n if (controller[$isMounted]) {\n throw new Error(\"Router is already mounted\");\n }\n\n controller[$mountPath] = prefix;\n this[$childRouters].push(controller);\n\n /**\n * Descendants are defined first, then mounted backwards up to the application root.\n * Thus, we have to recurse through the children and assign the root reference.\n */\n controller[$parent] = this;\n\n const setRouterContext = (router: ShokupanRouter<T>) => {\n router[$appRoot] = this.root;\n router[$childRouters].forEach((child) => setRouterContext(child));\n };\n setRouterContext(controller);\n\n\n // If the controller is the root router\n if (this[$appRoot]) {\n // TODO:\n }\n controller[$appRoot] = this.root;\n controller[$isMounted] = true;\n }\n // Controller is an arbitrary class\n else {\n let instance = controller;\n if (typeof controller === 'function') {\n // DI Resolution\n instance = Container.resolve(controller);\n\n // Controller Parameter Decorator (@Controller('prefix'))\n const controllerPath = (controller as any)[$controllerPath];\n if (controllerPath) {\n // Combine mount prefix + controller path\n // mount('/api', Ctrl) + @Controller('/users') -> /api/users\n const p1 = prefix.endsWith(\"/\") ? prefix.slice(0, -1) : prefix;\n const p2 = controllerPath.startsWith(\"/\") ? controllerPath : \"/\" + controllerPath;\n prefix = (p1 + p2);\n // Normalize\n if (!prefix) prefix = \"/\";\n }\n }\n\n instance[$mountPath] = prefix;\n this[$childControllers].push(instance as any);\n\n // Get Middleware for Controller\n // It could be on the Constructor (if passed as class) or Instance (if passed as object and manually set?)\n // Usually decorators set it on Constructor.\n const controllerMiddleware = (typeof controller === 'function' ? (controller as any)[$middleware] : (instance as any)[$middleware]) || [];\n\n // Get all method names from the prototype (for classes)\n const proto = Object.getPrototypeOf(instance);\n const methods = new Set<string>();\n\n // Scan prototype chain\n let current = proto;\n while (current && current !== Object.prototype) {\n Object.getOwnPropertyNames(current).forEach(name => methods.add(name));\n current = Object.getPrototypeOf(current);\n }\n // Also scan own properties (for objects or bound methods)\n Object.getOwnPropertyNames(instance).forEach(name => methods.add(name));\n\n const decoratedRoutes = (instance as any)[$routeMethods] || (proto && (proto as any)[$routeMethods]);\n const decoratedArgs = (instance as any)[$routeArgs] || (proto && (proto as any)[$routeArgs]);\n const methodMiddlewareMap = (instance as any)[$middleware] || (proto && (proto as any)[$middleware]);\n\n let routesAttached = 0;\n for (const name of methods) {\n if (name === \"constructor\") continue;\n if ([\"arguments\", \"caller\", \"callee\"].includes(name)) continue;\n\n const originalHandler = (instance as any)[name];\n if (typeof originalHandler !== \"function\") continue;\n\n let method: Method | undefined;\n let subPath = \"\";\n\n // 1. Check for Decorator Metadata\n if (decoratedRoutes && decoratedRoutes.has(name)) {\n const config = decoratedRoutes.get(name);\n method = config.method;\n subPath = config.path;\n }\n // 2. Fallback to Convention\n else {\n // Simple convention matching\n // Check if name starts with HTTP verb\n for (const m of HTTPMethods) {\n if (name.toUpperCase().startsWith(m)) {\n method = m as Method;\n const rest = name.slice(m.length);\n if (rest.length === 0) {\n subPath = \"/\";\n }\n else {\n // Existing parsing logic...\n subPath = \"\";\n let buffer = \"\";\n const flush = () => {\n if (buffer.length > 0) {\n subPath += \"/\" + buffer.toLowerCase();\n buffer = \"\";\n }\n };\n for (let i = 0; i < rest.length; i++) {\n const char = rest[i];\n if (char === \"$\") {\n flush();\n subPath += \"/:\";\n continue;\n }\n // Revised simple loop\n }\n subPath = rest\n .replace(/\\$/g, \"/:\") // $id -> /:id\n .replace(/([a-z0-9])([A-Z])/g, \"$1/$2\") // camelCase -> camel/Case\n .toLowerCase();\n\n if (!subPath.startsWith(\"/\")) {\n subPath = \"/\" + subPath;\n }\n }\n break;\n }\n }\n }\n\n if (method) {\n routesAttached++;\n // Remove trailing slash from prefix if needed, combine with subPath\n const cleanPrefix = prefix.endsWith(\"/\") ? prefix.slice(0, -1) : prefix;\n const cleanSubPath = subPath === \"/\" ? \"\" : subPath;\n\n let joined: string;\n if (cleanSubPath.length === 0) {\n joined = cleanPrefix;\n }\n else if (cleanSubPath.startsWith(\"/\")) {\n joined = cleanPrefix + cleanSubPath;\n }\n else {\n joined = cleanPrefix + \"/\" + cleanSubPath;\n }\n\n const fullPath = joined || \"/\";\n const normalizedPath = fullPath.replace(/\\/+/g, \"/\");\n\n // -- Compose Handler with Middleware and Param Resolution --\n\n const methodMw = (methodMiddlewareMap instanceof Map) ? (methodMiddlewareMap.get(name) || []) : [];\n const allMiddleware = [...controllerMiddleware, ...methodMw];\n\n // Check for Args\n const routeArgs = decoratedArgs && decoratedArgs.get(name);\n\n // Create Wrapper\n const wrappedHandler = async (ctx: ShokupanContext<T>) => {\n // Resolve Arguments\n let args: any[] = [ctx]; // Default to just context if no decorators\n\n if (routeArgs?.length > 0) {\n args = [];\n // Sort by index\n const sortedArgs = [...routeArgs].sort((a, b) => a.index - b.index);\n\n // Fill args array\n for (const arg of sortedArgs) {\n switch (arg.type) {\n case RouteParamType.BODY:\n args[arg.index] = await ctx.req.json().catch(() => ({}));\n break;\n case RouteParamType.PARAM:\n args[arg.index] = arg.name ? ctx.params[arg.name] : ctx.params;\n break;\n case RouteParamType.QUERY: {\n const url = new URL(ctx.req.url);\n args[arg.index] = arg.name ? url.searchParams.get(arg.name) : Object.fromEntries(url.searchParams);\n break;\n }\n case RouteParamType.HEADER:\n args[arg.index] = arg.name ? ctx.req.headers.get(arg.name) : ctx.req.headers;\n break;\n case RouteParamType.REQUEST:\n args[arg.index] = ctx.req;\n break;\n case RouteParamType.CONTEXT:\n args[arg.index] = ctx;\n break;\n }\n }\n }\n\n const tracedOriginalHandler = traceHandler(originalHandler, normalizedPath);\n return tracedOriginalHandler.apply(instance, args);\n };\n\n // Apply Middleware wrapping\n let finalHandler = wrappedHandler;\n if (allMiddleware.length > 0) {\n const composed = compose(allMiddleware);\n finalHandler = async (ctx) => {\n return composed(ctx, () => wrappedHandler(ctx));\n };\n }\n\n // Inject Controller Name as Tag\n const tagName = instance.constructor.name;\n // TODO: Merge with existing spec from decorator if available\n const spec = { tags: [tagName] };\n\n this.add({ method, path: normalizedPath, handler: finalHandler, spec });\n }\n }\n if (routesAttached === 0) {\n console.warn(`No routes attached to controller ${instance.constructor.name}`);\n }\n instance[$isMounted] = true;\n }\n\n return this;\n }\n\n /**\n * Returns all routes attached to this router and its descendants.\n */\n public getRoutes(): { method: Method, path: string, handler: ShokupanHandler<T>; }[] {\n const routes = this.routes.map(r => ({\n method: r.method,\n path: r.path,\n handler: r.handler\n }));\n\n for (const child of this[$childRouters]) {\n const childRoutes = child.getRoutes();\n for (const route of childRoutes) {\n const cleanPrefix = child[$mountPath].endsWith(\"/\") ? child[$mountPath].slice(0, -1) : child[$mountPath];\n const cleanPath = route.path.startsWith(\"/\") ? route.path : \"/\" + route.path;\n const fullPath = (cleanPrefix + cleanPath) || \"/\";\n\n routes.push({\n method: route.method as Method,\n path: fullPath,\n handler: route.handler\n });\n }\n }\n return routes;\n }\n\n /**\n * Makes a sub request to this router.\n * This is useful for triggering other methods or route handlers. \n * @param options The request options.\n * @returns The response.\n */\n public async subRequest(arg: {\n path: string;\n method?: Method;\n headers?: HeadersInit;\n body?: any;\n } | string): Promise<Response> {\n const options = typeof arg === \"string\" ? { path: arg } : arg;\n\n const store = asyncContext.getStore();\n const originalReq = store?.get(\"req\") as ShokupanRequest<T>;\n\n let url = options.path;\n // If path is relative, make it absolute (required by Request constructor)\n if (!url.startsWith(\"http\")) {\n const base = `http://${this.rootConfig?.hostname || \"localhost\"}:${this.rootConfig.port || 3000}`;\n\n // Ensure path starts with /\n const path = url.startsWith(\"/\") ? url : \"/\" + url;\n url = base + path;\n }\n\n const req = new ShokupanRequest({\n method: options.method || \"GET\",\n url,\n headers: options.headers as any,\n body: options.body ? JSON.stringify(options.body) : undefined\n });\n\n return this.root[$dispatch](req);\n }\n\n /**\n * Processes a request directly.\n */\n public async processRequest(options: RequestOptions): Promise<ProcessResult> {\n let url = options.url || options.path || \"/\";\n if (!url.startsWith(\"http\")) {\n const base = `http://${this.rootConfig?.hostname || \"localhost\"}:${this.rootConfig?.port || 3000}`;\n const path = url.startsWith(\"/\") ? url : \"/\" + url;\n url = base + path;\n }\n\n // Handle query params in options\n if (options.query) {\n const u = new URL(url);\n for (const [k, v] of Object.entries(options.query)) {\n u.searchParams.set(k, v);\n }\n url = u.toString();\n }\n\n const req = new ShokupanRequest({\n method: (options.method || \"GET\") as Method,\n url,\n headers: options.headers as any,\n body: options.body && typeof options.body === \"object\" ? JSON.stringify(options.body) : options.body\n });\n\n // Basic Dispatch Logic (moved/duplicated from Shokupan.handleRequest but simpler for pure Router)\n // Note: Pure Routers don't have global middleware usually, but if we call processRequest on them, \n // we just run their routing logic.\n // HOWEVER, Shokupan.override will invoke middleware.\n\n const ctx = new ShokupanContext<T>(req);\n\n let result: any = null;\n let status = 200;\n const headers: Record<string, string> = {};\n\n const match = this.find(req.method, ctx.path);\n if (match) {\n ctx.params = match.params;\n try {\n result = await match.handler(ctx);\n } catch (err: any) {\n console.error(err);\n status = err.status || err.statusCode || 500;\n result = { error: err.message || \"Internal Server Error\" };\n if (err.errors) result.errors = err.errors;\n }\n }\n else {\n status = 404;\n result = \"Not Found\";\n }\n\n // Normalize Result\n // If result is Response object, we need to read it back to ProcessResult?\n // The user wants { status, headers, data }.\n // If handler returns Response, we extract data.\n\n if (result instanceof Response) {\n status = result.status;\n result.headers.forEach((v, k) => headers[k] = v);\n\n if (headers['content-type']?.includes('application/json')) {\n result = await result.json();\n }\n else {\n result = await result.text();\n }\n }\n\n return {\n status,\n headers,\n data: result\n };\n }\n\n /**\n * Find a route matching the given method and path.\n * @param method HTTP method\n * @param path Request path\n * @returns Route handler and parameters if found, otherwise null\n */\n public find(method: string, path: string): { handler: ShokupanHandler<T>; params: Record<string, string>; } | null {\n // console.log(`[Router] find ${method} ${path} (routes: ${this.routes.length}, children: ${this[$childRouters].length})`);\n\n // 1. Check local routes\n for (const route of this.routes) {\n if (route.method !== \"ALL\" && route.method !== method) continue;\n\n const match = route.regex.exec(path);\n if (match) {\n // console.log(` -> Matched route ${route.path}`);\n const params: Record<string, string> = {};\n route.keys.forEach((key, index) => {\n params[key] = match[index + 1];\n });\n return { handler: route.handler, params };\n }\n }\n\n // 2. Check child routers\n for (const child of this[$childRouters]) {\n const prefix = child[$mountPath];\n // console.log(` -> Checking child prefix ${prefix}`);\n\n if (path === prefix || path.startsWith(prefix + \"/\")) {\n const subPath = path.slice(prefix.length) || \"/\";\n const match = child.find(method, subPath);\n if (match) return match;\n }\n // Handle case where prefix ends with /\n if (prefix.endsWith(\"/\")) {\n if (path.startsWith(prefix)) {\n const subPath = path.slice(prefix.length) || \"/\";\n const match = child.find(method, subPath);\n if (match) return match;\n }\n }\n }\n\n return null; // Not found\n }\n\n private parsePath(path: string): { regex: RegExp; keys: string[]; } {\n const keys: string[] = [];\n const pattern = path\n .replace(/:([a-zA-Z0-9_]+)/g, (_, key) => {\n keys.push(key);\n return \"([^/]+)\";\n })\n .replace(/\\*/g, \".*\"); // Wildcard support\n\n return {\n regex: new RegExp(`^${pattern}$`),\n keys\n };\n }\n\n // --- Functional Routing ---\n\n /**\n * Adds a route to the router.\n * \n * @param method - HTTP method\n * @param path - URL path\n * @param spec - OpenAPI specification for the route\n * @param handler - Route handler function\n */\n public add({ method, path, spec, handler, regex: customRegex, group }: {\n method: Method,\n path: string,\n spec?: MethodAPISpec,\n handler: ShokupanHandler<T>;\n regex?: RegExp;\n group?: string;\n }) {\n const { regex, keys } = customRegex\n ? { regex: customRegex, keys: [] }\n : this.parsePath(path);\n\n // Wrap handler with current guards if any exist\n let wrappedHandler = handler;\n const routeGuards = [...this.currentGuards];\n\n if (routeGuards.length > 0) {\n wrappedHandler = async (ctx: ShokupanContext<T>) => {\n // Execute guards in order\n for (const guard of routeGuards) {\n let guardPassed = false;\n let nextCalled = false;\n\n // Create next function for middleware-style guards\n const next = () => {\n nextCalled = true;\n return Promise.resolve();\n };\n\n try {\n const result = await guard.handler(ctx, next);\n\n // Check if guard explicitly returned true or called next()\n if (result === true || nextCalled) {\n guardPassed = true;\n }\n // If guard returned a response, return it (short-circuit)\n else if (result !== undefined && result !== null && result !== false) {\n return result;\n }\n // If guard returned false or nothing, block the request\n else {\n return ctx.json({ error: 'Forbidden' }, 403);\n }\n }\n catch (error) {\n // If guard throws, propagate the error to error handling\n throw error;\n }\n\n if (!guardPassed) {\n return ctx.json({ error: 'Forbidden' }, 403);\n }\n }\n\n // All guards passed, execute the actual handler\n return handler(ctx);\n };\n }\n\n this.routes.push({\n method,\n path,\n regex,\n keys,\n handler: wrappedHandler,\n handlerSpec: spec,\n group,\n guards: routeGuards.length > 0 ? routeGuards : undefined\n });\n\n return this;\n }\n\n /**\n * Adds a GET route to the router.\n * \n * @param path - URL path \n * @param handler - Route handler function \n */\n public get(path: string, ...handlers: ShokupanHandler<T>[]);\n /**\n * Adds a GET route to the router.\n * \n * @param path - URL path \n * @param spec - OpenAPI specification for the route\n * @param handlers - Route handler functions \n */\n public get(path: string, spec: MethodAPISpec, ...handlers: ShokupanHandler<T>[]);\n public get(path: string, ...args: (MethodAPISpec | ShokupanHandler<T>)[]) {\n this.attachVerb(\"GET\", path, ...args);\n return this;\n }\n\n /**\n * Adds a POST route to the router.\n * \n * @param path - URL path \n * @param handler - Route handler function \n */\n public post(path: string, ...handlers: ShokupanHandler<T>[]);\n /**\n * Adds a POST route to the router.\n * \n * @param path - URL path \n * @param spec - OpenAPI specification for the route\n * @param handlers - Route handler functions \n */\n public post(path: string, spec: MethodAPISpec, ...handlers: ShokupanHandler<T>[]);\n public post(path: string, ...args: (MethodAPISpec | ShokupanHandler<T>)[]) {\n this.attachVerb(\"POST\", path, ...args);\n return this;\n }\n\n /**\n * Adds a PUT route to the router.\n * \n * @param path - URL path \n * @param handler - Route handler function \n */\n public put(path: string, ...handlers: ShokupanHandler<T>[]);\n /**\n * Adds a PUT route to the router.\n * \n * @param path - URL path \n * @param spec - OpenAPI specification for the route\n * @param handlers - Route handler functions \n */\n public put(path: string, spec: MethodAPISpec, ...handlers: ShokupanHandler<T>[]);\n public put(path: string, ...args: (MethodAPISpec | ShokupanHandler<T>)[]) {\n this.attachVerb(\"PUT\", path, ...args);\n return this;\n }\n\n /**\n * Adds a DELETE route to the router.\n * \n * @param path - URL path \n * @param handler - Route handler function \n */\n public delete(path: string, ...handlers: ShokupanHandler<T>[]);\n /**\n * Adds a DELETE route to the router.\n * \n * @param path - URL path \n * @param spec - OpenAPI specification for the route\n * @param handlers - Route handler functions \n */\n public delete(path: string, spec: MethodAPISpec, ...handlers: ShokupanHandler<T>[]);\n public delete(path: string, ...args: (MethodAPISpec | ShokupanHandler<T>)[]) {\n this.attachVerb(\"DELETE\", path, ...args);\n return this;\n }\n\n /**\n * Adds a PATCH route to the router.\n * \n * @param path - URL path \n * @param handler - Route handler function \n */\n public patch(path: string, ...handlers: ShokupanHandler<T>[]);\n /**\n * Adds a PATCH route to the router.\n * \n * @param path - URL path \n * @param spec - OpenAPI specification for the route\n * @param handlers - Route handler functions \n */\n public patch(path: string, spec: MethodAPISpec, ...handlers: ShokupanHandler<T>[]);\n public patch(path: string, ...args: (MethodAPISpec | ShokupanHandler<T>)[]) {\n this.attachVerb(\"PATCH\", path, ...args);\n return this;\n }\n\n /**\n * Adds a OPTIONS route to the router.\n * \n * @param path - URL path \n * @param handler - Route handler function \n */\n public options(path: string, ...handlers: ShokupanHandler<T>[]);\n /**\n * Adds a OPTIONS route to the router.\n * \n * @param path - URL path \n * @param spec - OpenAPI specification for the route\n * @param handlers - Route handler functions \n */\n public options(path: string, spec: MethodAPISpec, ...handlers: ShokupanHandler<T>[]);\n public options(path: string, ...args: (MethodAPISpec | ShokupanHandler<T>)[]) {\n this.attachVerb(\"OPTIONS\", path, ...args);\n return this;\n }\n\n /**\n * Adds a HEAD route to the router.\n * \n * @param path - URL path \n * @param handler - Route handler function \n */\n public head(path: string, ...handlers: ShokupanHandler<T>[]);\n /**\n * Adds a HEAD route to the router.\n * \n * @param path - URL path \n * @param spec - OpenAPI specification for the route\n * @param handlers - Route handler functions \n */\n public head(path: string, spec: MethodAPISpec, ...handlers: ShokupanHandler<T>[]);\n public head(path: string, ...args: (MethodAPISpec | ShokupanHandler<T>)[]) {\n this.attachVerb(\"HEAD\", path, ...args);\n return this;\n }\n\n /**\n * Adds a guard to the router that applies to all routes added **after** this point.\n * Guards must return true or call `ctx.next()` to allow the request to continue.\n * \n * @param handler - Guard handler function \n */\n public guard(handler: ShokupanHandler<T>): void;\n /**\n * Adds a guard to the router that applies to all routes added **after** this point.\n * Guards must return true or call `ctx.next()` to allow the request to continue.\n \n * @param spec - OpenAPI specification for the guard\n * @param handler - Guard handler function \n */\n public guard(spec: GuardAPISpec, handler: ShokupanHandler<T>);\n public guard(specOrHandler: GuardAPISpec | ShokupanHandler<T>, handler?: ShokupanHandler<T>) {\n const spec = typeof specOrHandler === \"function\" ? undefined : specOrHandler as GuardAPISpec;\n const guardHandler = typeof specOrHandler === \"function\" ? specOrHandler as ShokupanHandler<T> : handler as ShokupanHandler<T>;\n\n this.currentGuards.push({ handler: guardHandler, spec });\n\n return this;\n }\n\n /**\n * Statically serves a directory with standard options.\n * @param uriPath URL path prefix\n * @param options Configuration options or root directory string\n */\n public static(uriPath: string, options: string | StaticServeOptions<T>) {\n const config: StaticServeOptions<T> = typeof options === 'string' ? { root: options } : options;\n const rootPath = resolve(config.root || \".\");\n // Normalize path prefix to ensure it has leading slash and no trailing slash for consistent matching\n const prefix = uriPath.startsWith('/') ? uriPath : '/' + uriPath;\n const normalizedPrefix = prefix.endsWith('/') && prefix !== '/' ? prefix.slice(0, -1) : prefix;\n\n const handler = async (ctx: ShokupanContext<T>) => {\n // 1. Calculate relative path\n // ctx.path is full path.\n // If prefix is /static, and path is /static/foo.css, relative is /foo.css\n let relative = ctx.path.slice(normalizedPrefix.length);\n if (!relative.startsWith('/') && relative.length > 0) relative = '/' + relative;\n if (relative.length === 0) relative = '/';\n\n // Decode URI components\n relative = decodeURIComponent(relative);\n\n // Security: Prevent directory traversal\n const requestPath = join(rootPath, relative);\n if (!requestPath.startsWith(rootPath)) {\n return ctx.json({ error: 'Forbidden' }, 403);\n }\n\n // check if path includes null byte\n if (requestPath.includes('\\0')) {\n return ctx.json({ error: 'Forbidden' }, 403);\n }\n\n // Hooks: onRequest\n if (config.hooks?.onRequest) {\n const res = await config.hooks.onRequest(ctx);\n if (res) return res;\n }\n\n // Check Excludes\n if (config.exclude) {\n for (const pattern of config.exclude) {\n if (pattern instanceof RegExp) {\n if (pattern.test(relative)) return ctx.json({ error: 'Forbidden' }, 403);\n } else if (typeof pattern === 'string') {\n if (relative.includes(pattern)) return ctx.json({ error: 'Forbidden' }, 403);\n }\n }\n }\n\n // Dotfiles\n if (basename(requestPath).startsWith('.')) {\n const behavior = config.dotfiles || 'ignore';\n if (behavior === 'deny') return ctx.json({ error: 'Forbidden' }, 403);\n if (behavior === 'ignore') return ctx.json({ error: 'Not Found' }, 404);\n }\n\n let finalPath = requestPath;\n let stats;\n\n try {\n stats = await stat(requestPath);\n } catch (e) {\n // Path not found. Try extensions.\n if (config.extensions) {\n for (const ext of config.extensions) {\n const p = requestPath + (ext.startsWith('.') ? ext : '.' + ext);\n try {\n const s = await stat(p);\n if (s.isFile()) {\n finalPath = p;\n stats = s;\n break;\n }\n } catch { }\n }\n }\n if (!stats) return ctx.json({ error: 'Not Found' }, 404);\n }\n\n // Directory handling\n if (stats.isDirectory()) {\n // Return 302 Redirect to add trailing slash if missing and not root\n // This ensures relative paths in served files work correctly.\n if (!ctx.path.endsWith('/')) {\n const query = ctx.url.search;\n return ctx.redirect(ctx.path + '/' + query, 302);\n }\n\n // Try indexes\n let indexes: string[] = [];\n if (config.index === undefined) {\n indexes = ['index.html', 'index.htm'];\n }\n else if (Array.isArray(config.index)) {\n indexes = config.index;\n }\n else if (config.index) {\n indexes = [config.index];\n }\n\n let foundIndex = false;\n for (const idx of indexes) {\n const idxPath = join(finalPath, idx);\n try {\n const idxStats = await stat(idxPath);\n if (idxStats.isFile()) {\n finalPath = idxPath;\n foundIndex = true;\n break;\n }\n } catch { }\n }\n\n if (!foundIndex) {\n if (config.listDirectory) {\n // List directory\n try {\n const files = await readdir(requestPath);\n // Simple HTML listing\n const listing = eta.renderString(`\n <!DOCTYPE html>\n <html>\n <head>\n <title>Index of <%= it.relative %></title>\n <style>\n body { font-family: system-ui, -apple-system, sans-serif; padding: 2rem; max-width: 800px; margin: 0 auto; }\n ul { list-style: none; padding: 0; }\n li { padding: 0.5rem 0; border-bottom: 1px solid #eee; }\n a { text-decoration: none; color: #0066cc; }\n a:hover { text-decoration: underline; }\n h1 { font-size: 1.5rem; margin-bottom: 1rem; }\n </style>\n </head>\n <body>\n <h1>Index of <%= it.relative %></h1>\n <ul>\n <% if (it.relative !== '/') { %>\n <li><a href=\"../\">../</a></li>\n <% } %>\n <% it.files.forEach(function(f) { %>\n <li><a href=\"<%= f %>\"><%= f %></a></li>\n <% }) %>\n </ul>\n </body>\n </html>\n `, { relative, files, join });\n return new Response(listing, { headers: { 'Content-Type': 'text/html' } });\n } catch (e) {\n return ctx.json({ error: 'Internal Server Error' }, 500);\n }\n } else {\n // If no index and no listing, it's 404 or 403. typically 404/403.\n // Nginx returns 403 Forbidden.\n return ctx.json({ error: 'Forbidden' }, 403);\n }\n }\n }\n\n // Serving File\n // @ts-ignore\n const file = Bun.file(finalPath);\n let response = new Response(file);\n\n if (config.hooks?.onResponse) {\n const hooked = await config.hooks.onResponse(ctx, response);\n if (hooked) response = hooked;\n }\n return response;\n };\n\n // Derive Group/Tag name from the path's last segment\n // e.g. /assets -> Assets\n // /static/images -> Images\n let groupName = \"Static\";\n const segments = normalizedPrefix.split('/').filter(Boolean);\n if (segments.length > 0) {\n const last = segments[segments.length - 1];\n groupName = last.charAt(0).toUpperCase() + last.slice(1);\n }\n\n const defaultSpec = {\n summary: \"Static Content\",\n description: \"Serves static files from \" + normalizedPrefix,\n tags: [groupName]\n };\n const spec = config.openapi ? config.openapi : defaultSpec;\n if (!spec.tags) spec.tags = [groupName];\n else if (!spec.tags.includes(groupName)) spec.tags.push(groupName);\n\n const pattern = `^${normalizedPrefix}(/.*)?$`;\n const regex = new RegExp(pattern);\n\n // Display path in OpenAPI as /prefix/*\n const displayPath = normalizedPrefix === '/' ? '/*' : normalizedPrefix + '/*';\n\n this.add({ method: 'GET', path: displayPath, handler, spec, regex });\n this.add({ method: 'HEAD', path: displayPath, handler, spec, regex });\n\n return this;\n }\n\n\n /**\n * Attach the verb routes with their overload signatures.\n * Use compose to handle multiple handlers (middleware).\n */\n private attachVerb(method: Method, path: string, ...args: (MethodAPISpec | ShokupanHandler<T>)[]) {\n let spec: MethodAPISpec | undefined;\n let handlers: ShokupanHandler<T>[] = [];\n\n if (args.length > 0) {\n // Check if first arg is an object (Spec) and NOT a ShokupanHandler (function)\n if (typeof args[0] === 'object' && args[0] !== null) {\n spec = args[0] as MethodAPISpec;\n handlers = args.slice(1) as ShokupanHandler<T>[];\n } else {\n handlers = args as ShokupanHandler<T>[];\n }\n }\n\n if (handlers.length === 0) {\n // Should potentially throw or warn?\n return;\n }\n\n let finalHandler = handlers[handlers.length - 1]; // Last handler is the main handler?\n // Wait, compose logic: \n // If we have [m1, m2, h], we want m1 -> m2 -> h.\n // compose([m1, m2, h]) does exactly that.\n // However, middleware returns `Promise<any>`.\n // If `handlers.length > 1`, we wrap them.\n\n if (handlers.length > 1) {\n // Since handlers are [ctx, next?], they fit Strict Middleware signature.\n // compose takes Middleware[].\n // We assume ALL provided handlers are valid middleware/handlers.\n const fn = compose(handlers as any);\n finalHandler = (ctx) => fn(ctx);\n }\n\n this.add({\n method,\n path,\n spec,\n handler: finalHandler\n });\n }\n\n /**\n * Generates an OpenAPI 3.1 Document by recursing through the router and its descendants.\n */\n public generateApiSpec(options: OpenAPIOptions = {}): OpenAPI.Document {\n const paths: OpenAPI.Document['paths'] = {};\n const tagGroups = new Map<string, Set<string>>();\n\n const defaultTagGroup = options.defaultTagGroup || \"General\";\n const defaultTagName = options.defaultTag || \"Application\";\n\n // Helper to collect routes\n const collect = (router: ShokupanRouter<T>, prefix = \"\", currentGroup = defaultTagGroup, defaultTag = defaultTagName) => {\n // Determine effective group and tag for this router\n let group = currentGroup;\n let tag = defaultTag;\n\n // If explicit group name is provided, switch to that group\n if (router.config?.group) {\n group = router.config.group;\n }\n\n // If explicit name is provided, switch to that tag\n // But if ONLY name is provided (no group), we interpret it as a Tag in the current Group (if we are nested)\n // or should we interpret it as a Group if it's top level?\n // The explicit `group` property solves ambiguity.\n // If `name` is present, it updates the Tag.\n // If explicit name is provided, switch to that tag\n if (router.config?.name) {\n tag = router.config.name;\n } else {\n // Infer from mountPath if name is missing\n const mountPath = router[$mountPath];\n if (mountPath && mountPath !== \"/\") {\n // Convert /path/to/something -> Something? Or PathToSomething?\n // Strategy: Take the last segment\n const segments = mountPath.split(\"/\").filter(Boolean);\n if (segments.length > 0) {\n const lastSegment = segments[segments.length - 1];\n // Capitalize logic\n const humanized = lastSegment\n .replace(/[-_]/g, ' ')\n .replace(/\\b\\w/g, c => c.toUpperCase());\n\n tag = humanized;\n }\n }\n }\n\n // Ensure group exists\n if (!tagGroups.has(group)) {\n tagGroups.set(group, new Set());\n }\n\n // 1. Local Routes\n for (const route of router.routes) {\n // Determine effective group for this route\n const routeGroup = route.group || group;\n\n // Determine full path\n const cleanPrefix = prefix.endsWith(\"/\") ? prefix.slice(0, -1) : prefix;\n const cleanSubPath = route.path.startsWith(\"/\") ? route.path : \"/\" + route.path;\n let fullPath = (cleanPrefix + cleanSubPath) || \"/\";\n\n // Convert path parameters from :param to {param} for OpenAPI\n fullPath = fullPath.replace(/:([a-zA-Z0-9_]+)/g, \"{$1}\");\n\n // Initialize path item if missing\n if (!paths[fullPath]) {\n paths[fullPath] = {};\n }\n\n // Generate Operation Spec\n const operation: OpenAPI.Operation = {\n responses: {\n 200: { description: \"OK\" }\n }\n };\n\n // Add Path Parameters from route keys\n if (route.keys.length > 0) {\n operation.parameters = route.keys.map(key => ({\n name: key,\n in: \"path\",\n required: true,\n schema: { type: \"string\" }\n }));\n }\n\n // Merge Guard Specs\n if (route.guards) {\n for (const guard of route.guards) {\n if (guard.spec) {\n deepMerge(operation, guard.spec);\n }\n }\n }\n\n // Merge Handler Spec\n if (route.handlerSpec) {\n deepMerge(operation, route.handlerSpec);\n }\n\n // Apply Default Tag if none exist\n if (!operation.tags || operation.tags.length === 0) {\n operation.tags = [tag];\n }\n\n // Deduplicate Tags\n if (operation.tags) {\n operation.tags = Array.from(new Set(operation.tags));\n // Register tags to group\n for (const t of operation.tags) {\n // Ensure group exists if it was switched\n if (!tagGroups.has(routeGroup)) {\n tagGroups.set(routeGroup, new Set());\n }\n tagGroups.get(routeGroup)?.add(t);\n }\n }\n\n // Assign to path item\n const methodLower = route.method.toLowerCase();\n if (methodLower === \"all\") {\n [\"get\", \"post\", \"put\", \"delete\", \"patch\"].forEach(m => {\n if (!(paths as any)[fullPath][m]) {\n (paths as any)[fullPath][m] = { ...operation };\n }\n });\n } else {\n (paths as any)[fullPath][methodLower] = operation;\n }\n }\n\n // 2. Child Controllers\n for (const controller of router[$childControllers]) {\n const mountPath = (controller as any)[$mountPath] || \"\"; // Should differ based on controller logic\n // Re-calculate prefix for controller\n const cleanPrefix = prefix.endsWith(\"/\") ? prefix.slice(0, -1) : prefix;\n const cleanMount = mountPath.startsWith(\"/\") ? mountPath : \"/\" + mountPath;\n const nextPrefix = (cleanPrefix + cleanMount) || \"/\";\n\n // Controller Name as Tag\n const controllerName = controller.constructor.name || \"UnknownController\";\n tagGroups.get(group)?.add(controllerName);\n\n // We need to extract routes from controller similar to how we did in mount()\n // But wait, the routes are not in `router.routes`? \n // Ah, looking at `mount()`, it calls `this.add()` which pushes to `this.routes`.\n // SO `this.routes` ALREADY contains the controller routes!\n\n // Wait, if `mount` adds routes to `this.routes`, then loop #1 (Local Routes) covers them.\n // BUT, they are mixed in. We need to identify WHICH routes belong to WHICH controller to assign the correct tag.\n // The current `ShokupanRoute` structure does not store \"source controller\".\n\n // CRITICAL MISSING PIECE: We cannot distinguish controller routes from raw routes in `this.routes` \n // unless we store metadata on the route.\n\n // However, `mount` logic:\n // It calls `this.add({ ... })`.\n\n // I should assume for now that if I can't distinguish, I might have to change `mount` to store metadata,\n // OR `mount` logic for Controllers was:\n // \"this[$childControllers].push(instance)\" AND \"this.add(...)\".\n\n // Only `mount` adds to `childControllers`.\n // So checking `childControllers` here is redundant if I iterate `routes`.\n // BUT I need to know the tag.\n\n // Strategy: Update `mount` to attach `tags` to the `spec` when adding the route.\n // This seems cleaner than trying to reconstruct it here.\n }\n\n // 3. Child Routers\n for (const child of router[$childRouters]) {\n const mountPath = child[$mountPath];\n const cleanPrefix = prefix.endsWith(\"/\") ? prefix.slice(0, -1) : prefix;\n const cleanMount = mountPath.startsWith(\"/\") ? mountPath : \"/\" + mountPath;\n const nextPrefix = (cleanPrefix + cleanMount) || \"/\";\n\n collect(child, nextPrefix, group, tag);\n }\n };\n\n // If I update mount, I don't need to change `collect` significantly regarding controllers,\n // because the routes will already have the tags in `handlerSpec`.\n // BUT `collect` overrides/defaults tags.\n\n collect(this);\n\n // Build x-tagGroups\n const xTagGroups: { name: string; tags: string[]; }[] = [];\n for (const [name, tags] of tagGroups) {\n xTagGroups.push({\n name,\n tags: Array.from(tags).sort()\n });\n }\n\n return {\n openapi: \"3.1.0\",\n info: {\n title: \"Shokupan API\",\n version: \"1.0.0\",\n ...options.info\n },\n paths,\n components: options.components,\n servers: options.servers,\n tags: options.tags,\n externalDocs: options.externalDocs,\n \"x-tagGroups\": xTagGroups\n } as OpenAPI.Document;\n }\n}\n","import \"./util/instrumentation\";\n\nimport { context, trace } from '@opentelemetry/api';\nimport { ShokupanContext } from \"./context\";\nimport { compose } from \"./middleware\";\nimport { ShokupanRequest } from './request';\nimport { ShokupanRouter } from \"./router\";\nimport { $appRoot, $dispatch, $isApplication } from './symbol';\nimport type { Method, Middleware, ProcessResult, RequestOptions, ShokupanConfig } from './types';\nimport { asyncContext } from \"./util/async-hooks\";\n\nconst defaults: ShokupanConfig = {\n port: 3000,\n hostname: \"localhost\",\n development: process.env.NODE_ENV !== \"production\",\n enableAsyncLocalStorage: false,\n};\nconst tracer = trace.getTracer(\"shokupan.application\");\n\n\nexport class Shokupan<T = any> extends ShokupanRouter<T> {\n readonly applicationConfig: ShokupanConfig = {};\n private middleware: Middleware[] = [];\n\n get logger() {\n return this.applicationConfig.logger;\n }\n\n constructor(\n applicationConfig: ShokupanConfig = {}\n ) {\n super();\n this[$isApplication] = true;\n this[$appRoot] = this;\n Object.assign(this.applicationConfig, defaults, applicationConfig);\n }\n\n /**\n * Adds middleware to the application.\n */\n public use(middleware: Middleware) {\n this.middleware.push(middleware);\n return this;\n }\n\n /**\n * Starts the application server.\n * \n * @param port - The port to listen on. If not specified, the port from the configuration is used. If that is not specified, port 3000 is used.\n * @returns The server instance.\n */\n public listen(port?: number) {\n const finalPort = port ?? this.applicationConfig.port ?? 3000;\n\n if (finalPort < 0 || finalPort > 65535) {\n throw new Error(\"Invalid port number\");\n }\n\n if (port === 0 && process.platform === \"linux\") {\n\n }\n\n const server = Bun.serve({\n port: finalPort,\n hostname: this.applicationConfig.hostname,\n development: this.applicationConfig.development,\n fetch: this.fetch.bind(this)\n });\n\n console.log(`Shokupan server listening on http://${server.hostname}:${server.port}`);\n return server;\n }\n\n public [$dispatch](req: ShokupanRequest<T>) {\n return this.fetch(req as unknown as Request);\n }\n\n /**\n * Processes a request by wrapping the standard fetch method.\n */\n public override async processRequest(options: RequestOptions): Promise<ProcessResult> {\n let url = options.url || options.path || \"/\";\n if (!url.startsWith(\"http\")) {\n const base = `http://${this.applicationConfig.hostname || \"localhost\"}:${this.applicationConfig.port || 3000}`;\n const path = url.startsWith(\"/\") ? url : \"/\" + url;\n url = base + path;\n }\n\n if (options.query) {\n const u = new URL(url);\n for (const [k, v] of Object.entries(options.query)) {\n u.searchParams.set(k, v);\n }\n url = u.toString();\n }\n\n // Create Request to pass to fetch\n const req = new ShokupanRequest({\n method: (options.method || \"GET\") as Method,\n url,\n headers: options.headers as any,\n body: options.body && typeof options.body === \"object\" ? JSON.stringify(options.body) : options.body\n }) as unknown as ShokupanRequest<T>;\n\n const res = await this.fetch(req as unknown as Request);\n\n // Convert Response to ProcessResult\n const status = res.status;\n const headers: Record<string, string> = {};\n res.headers.forEach((v, k) => headers[k] = v);\n\n let data: any;\n if (headers['content-type']?.includes('application/json')) {\n data = await res.json();\n }\n else {\n data = await res.text();\n }\n\n return {\n status,\n headers,\n data\n };\n }\n\n /**\n * Handles an incoming request (Bun.serve interface).\n * This logic contains the middleware chain and router dispatch.\n * \n * @param req - The request to handle.\n * @returns The response to send.\n */\n public async fetch(req: Request): Promise<Response> {\n const tracer = trace.getTracer(\"shokupan.application\");\n const store = asyncContext.getStore();\n\n const attrs = {\n attributes: {\n \"http.url\": req.url,\n \"http.method\": req.method\n }\n };\n\n const parent = store?.get(\"span\");\n const ctx = parent ? trace.setSpan(context.active(), parent) : undefined;\n return tracer.startActiveSpan(`${req.method} ${new URL(req.url).pathname}`, attrs, ctx, span => {\n const ctxMap = new Map();\n ctxMap.set(\"span\", span);\n ctxMap.set(\"request\", req);\n\n const runCallback = () => {\n // Cast to ShokupanRequest if needed, though at runtime it's just a Request\n // But ShokupanContext expects ShokupanRequest.\n const request = req as unknown as ShokupanRequest<T>;\n\n const handle = async () => {\n const ctx = new ShokupanContext<T>(request);\n\n // Compose middleware + router dispatch\n const fn = compose(this.middleware);\n // Object.defineProperty(fn, 'name', { value: \"middleware chain\", configurable: false });\n\n try {\n // The \"next\" at the end of the middleware chain is the router dispatch\n const result = await fn(ctx, async () => {\n const match = this.find(req.method, ctx.path);\n if (match) {\n ctx.params = match.params;\n return match.handler(ctx);\n }\n return null;\n });\n\n if (result instanceof Response) {\n return result;\n }\n if (result === null || result === undefined) {\n span.setAttribute(\"http.status_code\", 404);\n return ctx.text(\"Not Found\", 404);\n }\n if (typeof result === \"object\") {\n return ctx.json(result);\n }\n\n return ctx.text(String(result));\n\n }\n catch (err: any) {\n console.error(err);\n span.recordException(err);\n span.setStatus({ code: 2 }); // Error\n const status = err.status || err.statusCode || 500;\n const body: any = { error: err.message || \"Internal Server Error\" };\n if (err.errors) body.errors = err.errors;\n return ctx.json(body, status);\n }\n };\n\n return handle()\n .finally(() => span.end());\n };\n\n if (this.applicationConfig.enableAsyncLocalStorage) {\n return asyncContext.run(ctxMap, runCallback);\n }\n else {\n return runCallback();\n }\n });\n }\n}\n","\nimport {\n Apple, Auth0,\n GitHub, Google, MicrosoftEntraId,\n OAuth2Client,\n Okta,\n generateCodeVerifier,\n generateState\n} from \"arctic\";\nimport * as jose from \"jose\";\nimport { ShokupanContext } from \"../context\";\nimport { ShokupanRouter } from \"../router\";\n\nexport interface AuthUser {\n id: string;\n email?: string;\n name?: string;\n picture?: string;\n provider: string;\n raw?: any;\n}\n\nexport interface ProviderConfig {\n clientId: string;\n clientSecret: string;\n redirectUri: string; // Must be absolute\n scopes?: string[];\n tenantId?: string; // For MS\n domain?: string; // For Auth0, Okta\n teamId?: string; // For Apple\n keyId?: string; // For Apple\n authUrl?: string; // For generic OAuth2\n tokenUrl?: string; // For generic OAuth2\n userInfoUrl?: string; // For generic OAuth2\n}\n\nexport interface AuthConfig {\n jwtSecret: string | Uint8Array;\n jwtExpiration?: string; // e.g. \"2h\"\n cookieOptions?: {\n httpOnly?: boolean;\n secure?: boolean;\n sameSite?: \"Strict\" | \"Lax\" | \"None\";\n path?: string;\n maxAge?: number;\n };\n onSuccess?: (user: AuthUser, ctx: ShokupanContext) => Promise<any> | any;\n providers: {\n github?: ProviderConfig;\n google?: ProviderConfig;\n microsoft?: ProviderConfig;\n apple?: ProviderConfig;\n auth0?: ProviderConfig;\n okta?: ProviderConfig;\n oauth2?: ProviderConfig;\n [key: string]: ProviderConfig | undefined;\n };\n}\n\nexport class AuthPlugin extends ShokupanRouter<any> {\n private secret: Uint8Array;\n\n constructor(private authConfig: AuthConfig) {\n super();\n this.secret = typeof authConfig.jwtSecret === 'string'\n ? new TextEncoder().encode(authConfig.jwtSecret)\n : authConfig.jwtSecret;\n\n this.init();\n }\n\n private getProviderInstance(name: string, p: ProviderConfig) {\n switch (name) {\n case 'github':\n return new GitHub(p.clientId, p.clientSecret, p.redirectUri);\n case 'google':\n return new Google(p.clientId, p.clientSecret, p.redirectUri);\n case 'microsoft':\n return new MicrosoftEntraId(p.tenantId!, p.clientId, p.clientSecret, p.redirectUri);\n case 'apple':\n // TODO: There is a type issue, requires testing.\n return new Apple(\n p.clientId,\n p.teamId!,\n p.keyId!,\n p.clientSecret as any,\n p.redirectUri\n );\n case 'auth0':\n return new Auth0(p.domain!, p.clientId, p.clientSecret, p.redirectUri);\n case 'okta':\n return new Okta(p.domain!, p.authUrl, p.clientId, p.clientSecret, p.redirectUri);\n case 'oauth2':\n return new OAuth2Client(p.clientId, p.clientSecret, p.redirectUri);\n default:\n return null;\n }\n }\n\n private async createSession(user: AuthUser, ctx: ShokupanContext) {\n const alg = 'HS256';\n const jwt = await new jose.SignJWT({ ...user })\n .setProtectedHeader({ alg })\n .setIssuedAt()\n .setExpirationTime(this.authConfig.jwtExpiration || '24h')\n .sign(this.secret);\n\n // Set cookie\n const opts = this.authConfig.cookieOptions || {};\n let cookie = `auth_token=${jwt}; Path=${opts.path || '/'}; HttpOnly`;\n if (opts.secure) cookie += '; Secure';\n if (opts.sameSite) cookie += `; SameSite=${opts.sameSite}`;\n if (opts.maxAge) cookie += `; Max-Age=${opts.maxAge}`;\n\n ctx.set('Set-Cookie', cookie);\n\n return jwt;\n }\n\n private init() {\n for (const [providerName, providerConfig] of Object.entries(this.authConfig.providers)) {\n if (!providerConfig) continue;\n\n const provider = this.getProviderInstance(providerName, providerConfig);\n if (!provider) {\n // Try treating as generic oauth2 if it has configured urls? \n // But for now strict mapping based on key unless we add logic.\n // We'll skip if unknown.\n continue;\n }\n\n // Login Route\n this.get(`/auth/${providerName}/login`, async (ctx) => {\n const state = generateState();\n const codeVerifier = (providerName === 'google' || providerName === 'microsoft' || providerName === 'auth0' || providerName === 'okta')\n ? generateCodeVerifier() : undefined; // PKCE for some\n\n // Store state/verifier in cookie for verification\n const scopes = providerConfig.scopes || [];\n let url: URL;\n\n if (provider instanceof GitHub) {\n url = await provider.createAuthorizationURL(state, scopes);\n } else if (provider instanceof Google || provider instanceof MicrosoftEntraId || provider instanceof Auth0 || provider instanceof Okta) {\n // These all support PKCE in recent versions\n // Types might vary slightly but usually createAuthorizationURL(state, codeVerifier, scopes)\n url = await (provider as any).createAuthorizationURL(state, codeVerifier!, scopes);\n } else if (provider instanceof Apple) {\n url = await provider.createAuthorizationURL(state, scopes);\n } else if (provider instanceof OAuth2Client) {\n if (!providerConfig.authUrl) return ctx.text(\"Config error: authUrl required for oauth2\", 500);\n url = await provider.createAuthorizationURL(providerConfig.authUrl, state, scopes);\n } else {\n return ctx.text(\"Provider config error\", 500);\n }\n\n ctx.res.headers.set(\"Set-Cookie\", `oauth_state=${state}; Path=/; HttpOnly; Max-Age=600`);\n if (codeVerifier) {\n ctx.res.headers.append(\"Set-Cookie\", `oauth_verifier=${codeVerifier}; Path=/; HttpOnly; Max-Age=600`);\n }\n\n return ctx.redirect(url.toString());\n });\n\n // Callback Route\n this.get(`/auth/${providerName}/callback`, async (ctx) => {\n const url = new URL(ctx.req.url);\n const code = url.searchParams.get(\"code\");\n const state = url.searchParams.get(\"state\");\n\n const cookieHeader = ctx.req.headers.get(\"Cookie\");\n const storedState = cookieHeader?.match(/oauth_state=([^;]+)/)?.[1];\n const storedVerifier = cookieHeader?.match(/oauth_verifier=([^;]+)/)?.[1];\n\n if (!code || !state || !storedState || state !== storedState) {\n return ctx.text(\"Invalid state or code\", 400);\n }\n\n try {\n let tokens: any;\n let idToken: string | undefined;\n\n if (provider instanceof GitHub) {\n tokens = await provider.validateAuthorizationCode(code);\n } else if (provider instanceof Google || provider instanceof MicrosoftEntraId) {\n if (!storedVerifier) return ctx.text(\"Missing verifier\", 400);\n tokens = await provider.validateAuthorizationCode(code, storedVerifier);\n } else if (provider instanceof Auth0 || provider instanceof Okta) {\n tokens = await (provider as any).validateAuthorizationCode(code, storedVerifier || \"\");\n } else if (provider instanceof Apple) {\n tokens = await provider.validateAuthorizationCode(code);\n idToken = tokens.idToken;\n } else if (provider instanceof OAuth2Client) {\n if (!providerConfig.tokenUrl) return ctx.text(\"Config error: tokenUrl required for oauth2\", 500);\n tokens = await provider.validateAuthorizationCode(providerConfig.tokenUrl, code, null);\n }\n\n const accessToken = tokens.accessToken || tokens.access_token;\n const user = await this.fetchUser(providerName, accessToken, providerConfig, idToken);\n\n if (this.authConfig.onSuccess) {\n const res = await this.authConfig.onSuccess(user, ctx);\n if (res) return res; // Allow override response\n }\n\n // Default behavior: create encoded session and returning it or redirect\n const jwt = await this.createSession(user, ctx);\n return ctx.json({ token: jwt, user });\n\n } catch (e: any) {\n console.error(\"Auth Error\", e);\n return ctx.text(\"Authentication failed: \" + e.message + \"\\n\" + e.stack, 500);\n }\n });\n }\n }\n\n private async fetchUser(provider: string, token: string, config: ProviderConfig, idToken?: string): Promise<AuthUser> {\n let user: AuthUser = { id: 'unknown', provider };\n\n if (provider === 'github') {\n const res = await fetch(\"https://api.github.com/user\", {\n headers: { Authorization: `Bearer ${token}` }\n });\n const data = await res.json() as any;\n user = {\n id: String(data.id),\n name: data.name || data.login,\n email: data.email,\n picture: data.avatar_url,\n provider,\n raw: data\n };\n }\n else if (provider === 'google') {\n const res = await fetch(\"https://openidconnect.googleapis.com/v1/userinfo\", {\n headers: { Authorization: `Bearer ${token}` }\n });\n const data = await res.json() as any;\n user = {\n id: data.sub,\n name: data.name,\n email: data.email,\n picture: data.picture,\n provider,\n raw: data\n };\n }\n else if (provider === 'microsoft') {\n const res = await fetch(\"https://graph.microsoft.com/v1.0/me\", {\n headers: { Authorization: `Bearer ${token}` }\n });\n const data = await res.json() as any;\n user = {\n id: data.id,\n name: data.displayName,\n email: data.mail || data.userPrincipalName,\n provider,\n raw: data\n };\n }\n else if (provider === 'auth0' || provider === 'okta') {\n const domain = config.domain!.startsWith('http') ? config.domain! : `https://${config.domain}`;\n const endpoint = provider === 'auth0' ? `${domain}/userinfo` : `${domain}/oauth2/v1/userinfo`;\n\n const res = await fetch(endpoint, {\n headers: { Authorization: `Bearer ${token}` }\n });\n const data = await res.json() as any;\n user = {\n id: data.sub,\n name: data.name,\n email: data.email,\n picture: data.picture,\n provider,\n raw: data\n };\n }\n else if (provider === 'apple') {\n // Apple user info is in the ID Token\n if (idToken) {\n const payload = jose.decodeJwt(idToken);\n user = {\n id: payload.sub!,\n email: payload['email'] as string,\n provider,\n raw: payload\n };\n }\n }\n else if (provider === 'oauth2') {\n if (config.userInfoUrl) {\n const res = await fetch(config.userInfoUrl, {\n headers: { Authorization: `Bearer ${token}` }\n });\n const data = await res.json() as any;\n user = {\n id: data.id || data.sub || 'unknown',\n name: data.name,\n email: data.email,\n picture: data.picture,\n provider,\n raw: data\n };\n }\n }\n\n return user;\n }\n\n /**\n * Middleware to verify JWT\n */\n public middleware() {\n return async (ctx: ShokupanContext, next: () => Promise<any>) => {\n const authHeader = ctx.req.headers.get(\"Authorization\");\n let token = authHeader?.startsWith(\"Bearer \") ? authHeader.substring(7) : null;\n\n if (!token) {\n // Try cookie\n const cookieHeader = ctx.req.headers.get(\"Cookie\");\n token = cookieHeader?.match(/auth_token=([^;]+)/)?.[1] || null;\n }\n\n if (token) {\n try {\n const { payload } = await jose.jwtVerify(token, this.secret);\n (ctx as any).user = payload;\n } catch {\n // Invalid token, just proceed without user or throw?\n // Usually proceed, let guard handle it if required\n }\n }\n return next();\n };\n }\n}\n","import type { ShokupanContext } from \"../context\";\nimport type { Middleware, NextFn } from \"../types\";\n\nexport interface CompressionOptions {\n threshold?: number; // Minimum byte size to compress\n}\n\nexport function Compression(options: CompressionOptions = {}): Middleware {\n const threshold = options.threshold ?? 1024; // 1KB default\n\n return async (ctx: ShokupanContext, next: NextFn) => {\n const acceptEncoding = ctx.headers.get(\"accept-encoding\") || \"\";\n\n // Check if compression is supported\n let method: 'br' | 'gzip' | 'deflate' | null = null;\n if (acceptEncoding.includes(\"br\")) method = \"br\";\n else if (acceptEncoding.includes(\"gzip\")) method = \"gzip\";\n else if (acceptEncoding.includes(\"deflate\")) method = \"deflate\";\n\n if (!method) return next();\n\n const response = await next();\n\n if (response instanceof Response) {\n // Don't compress if already compressed\n if (response.headers.has(\"Content-Encoding\")) return response;\n\n // Check Content-Type (optional, mostly text/json/xml)\n // For now, let's just compress if we can read the body easily.\n\n // Cloning response to read body\n // Note: This might be expensive for streams. \n // We only support basic compression for now (string/buffer bodies).\n // If body is a ReadableStream, Bun.gzip/deflateSync won't work directly on it mostly.\n\n // Let's try to read as ArrayBuffer\n const body = await response.arrayBuffer();\n\n if (body.byteLength < threshold) {\n // Return new response with original body because we consumed it\n return new Response(body, {\n status: response.status,\n statusText: response.statusText,\n headers: response.headers\n });\n }\n\n let compressed: Uint8Array;\n if (method === \"br\") {\n // Configurable params could be added later\n compressed = require(\"node:zlib\").brotliCompressSync(body);\n } else if (method === \"gzip\") {\n compressed = Bun.gzipSync(body);\n } else {\n compressed = Bun.deflateSync(body);\n }\n\n const headers = new Headers(response.headers);\n headers.set(\"Content-Encoding\", method);\n headers.set(\"Content-Length\", String(compressed.length));\n headers.delete(\"Content-Length\"); // Remove original length if present\n\n return new Response(compressed, {\n status: response.status,\n statusText: response.statusText,\n headers\n });\n }\n\n return response;\n };\n}\n","import type { ShokupanContext } from \"../context\";\nimport type { Middleware, NextFn } from \"../types\";\n\nexport interface CorsOptions {\n origin?: string | string[] | ((ctx: ShokupanContext) => string | undefined | null | boolean);\n methods?: string | string[];\n allowedHeaders?: string | string[];\n exposedHeaders?: string | string[];\n credentials?: boolean;\n maxAge?: number;\n}\n\nexport function Cors(options: CorsOptions = {}): Middleware {\n const defaults: CorsOptions = {\n origin: \"*\",\n methods: \"GET,HEAD,PUT,PATCH,POST,DELETE\",\n preflightContinue: false,\n optionsSuccessStatus: 204\n } as any;\n\n const opts = { ...defaults, ...options };\n\n return async (ctx: ShokupanContext, next: NextFn) => {\n const headers = new Headers();\n const origin = ctx.headers.get(\"origin\");\n\n const set = (k: string, v: string) => headers.set(k, v);\n const append = (k: string, v: string) => headers.append(k, v);\n\n // Set Access-Control-Allow-Origin\n if (opts.origin === \"*\") {\n set(\"Access-Control-Allow-Origin\", \"*\");\n } else if (typeof opts.origin === \"string\") {\n set(\"Access-Control-Allow-Origin\", opts.origin);\n } else if (Array.isArray(opts.origin)) {\n if (origin && opts.origin.includes(origin)) {\n set(\"Access-Control-Allow-Origin\", origin);\n append(\"Vary\", \"Origin\");\n }\n } else if (typeof opts.origin === \"function\") {\n const allowed = opts.origin(ctx);\n if (allowed === true && origin) {\n set(\"Access-Control-Allow-Origin\", origin);\n append(\"Vary\", \"Origin\");\n } else if (typeof allowed === 'string') {\n set(\"Access-Control-Allow-Origin\", allowed);\n append(\"Vary\", \"Origin\");\n }\n }\n\n // Access-Control-Allow-Credentials\n if (opts.credentials) {\n set(\"Access-Control-Allow-Credentials\", \"true\");\n }\n\n // Access-Control-Expose-Headers\n if (opts.exposedHeaders) {\n const exposed = Array.isArray(opts.exposedHeaders) ? opts.exposedHeaders.join(\",\") : opts.exposedHeaders;\n if (exposed) set(\"Access-Control-Expose-Headers\", exposed);\n }\n\n // Handle Preflight\n if (ctx.method === \"OPTIONS\") {\n // Access-Control-Allow-Methods\n if (opts.methods) {\n const methods = Array.isArray(opts.methods) ? opts.methods.join(\",\") : opts.methods;\n set(\"Access-Control-Allow-Methods\", methods);\n }\n\n // Access-Control-Allow-Headers\n if (opts.allowedHeaders) {\n const h = Array.isArray(opts.allowedHeaders) ? opts.allowedHeaders.join(\",\") : opts.allowedHeaders;\n set(\"Access-Control-Allow-Headers\", h);\n } else {\n // Reflect request headers if not specified\n const reqHeaders = ctx.headers.get(\"access-control-request-headers\");\n if (reqHeaders) {\n set(\"Access-Control-Allow-Headers\", reqHeaders);\n append(\"Vary\", \"Access-Control-Request-Headers\");\n }\n }\n\n // Access-Control-Max-Age\n if (opts.maxAge) {\n set(\"Access-Control-Max-Age\", String(opts.maxAge));\n }\n\n return new Response(null, {\n status: (opts as any).optionsSuccessStatus || 204,\n headers\n });\n }\n\n const response = await next();\n\n if (response instanceof Response) {\n for (const [key, value] of headers.entries()) {\n response.headers.set(key, value);\n }\n }\n\n return response;\n };\n}\n","import type { ShokupanContext } from \"../context\";\nimport type { Middleware, NextFn } from \"../types\";\n\nexport interface RateLimitOptions {\n windowMs?: number;\n max?: number;\n message?: string | object;\n statusCode?: number;\n headers?: boolean;\n keyGenerator?: (ctx: ShokupanContext) => string;\n skip?: (ctx: ShokupanContext) => boolean;\n}\n\ninterface HitRecord {\n hits: number;\n resetTime: number;\n}\n\nexport function RateLimit(options: RateLimitOptions = {}): Middleware {\n const windowMs = options.windowMs || 60 * 1000; // 1 minute\n const max = options.max || 5; // 5 requests per window\n const message = options.message || \"Too many requests, please try again later.\";\n const statusCode = options.statusCode || 429;\n const headers = options.headers !== false;\n const keyGenerator = options.keyGenerator || ((ctx) => {\n // Use IP if available (Bun specific property on server, but not exposed in generic Request easily without server context)\n // Fallback to simpler key or x-forwarded-for\n return ctx.headers.get(\"x-forwarded-for\") || ctx.url.hostname || \"unknown\";\n });\n const skip = options.skip || (() => false);\n\n // In-memory store\n // Note: For production with multiple instances, use Redis or similar external store.\n const hits = new Map<string, HitRecord>();\n\n // Cleanup interval\n const interval = setInterval(() => {\n const now = Date.now();\n for (const [key, record] of hits.entries()) {\n if (record.resetTime <= now) {\n hits.delete(key);\n }\n }\n }, windowMs);\n // Ensure interval doesn't block process exit\n if (interval.unref) interval.unref();\n\n return async (ctx: ShokupanContext, next: NextFn) => {\n if (skip(ctx)) return next();\n\n const key = keyGenerator(ctx);\n const now = Date.now();\n let record = hits.get(key);\n\n if (!record || record.resetTime <= now) {\n record = {\n hits: 0,\n resetTime: now + windowMs\n };\n hits.set(key, record);\n }\n\n record.hits++;\n\n const remaining = Math.max(0, max - record.hits);\n const resetTime = Math.ceil(record.resetTime / 1000);\n\n if (headers) {\n // We need to set headers on the response. \n // Similar to Helmet, we need to intercept the response or set it on context if supported.\n // For now, let's assume we can attach to the eventual response wrapper or helper.\n // Since we can't modify `ctx.response` directly before it exists, we wrap.\n }\n\n if (record.hits > max) {\n if (headers) {\n // Return immediate response\n const res = typeof message === 'object' ? ctx.json(message, statusCode) : ctx.text(String(message), statusCode);\n res.headers.set(\"X-RateLimit-Limit\", String(max));\n res.headers.set(\"X-RateLimit-Remaining\", \"0\");\n res.headers.set(\"X-RateLimit-Reset\", String(resetTime));\n return res;\n }\n return typeof message === 'object' ? ctx.json(message, statusCode) : ctx.text(String(message), statusCode);\n }\n\n const response = await next();\n\n if (response instanceof Response && headers) {\n response.headers.set(\"X-RateLimit-Limit\", String(max));\n response.headers.set(\"X-RateLimit-Remaining\", String(remaining));\n response.headers.set(\"X-RateLimit-Reset\", String(resetTime));\n }\n\n return response;\n };\n}\n","import type { ApiReferenceConfiguration } from '@scalar/api-reference';\nimport type { OpenAPI } from '@scalar/openapi-types';\nimport { Eta } from 'eta';\nimport { ShokupanRouter } from '../router';\nimport type { DeepPartial } from '../types';\n\nconst eta = new Eta();\n\nexport type ScalarPluginOptions = {\n baseDocument: DeepPartial<OpenAPI.Document>;\n config: Partial<ApiReferenceConfiguration>;\n};\n\nexport class ScalarPlugin extends ShokupanRouter<any> {\n constructor(\n private readonly pluginOptions: ScalarPluginOptions\n ) {\n super();\n this.init();\n }\n\n init() {\n this.get(\"/\", ctx => {\n let path = ctx.url.toString();\n if (!path.endsWith(\"/\")) path += \"/\";\n\n return ctx.html(eta.renderString(`<!doctype html>\n <html>\n <head>\n <title>API Reference</title>\n <meta charset = \"utf-8\" />\n <meta name=\"viewport\" content = \"width=device-width, initial-scale=1\" />\n </head>\n\n <body>\n <div id=\"app\"></div>\n\n <script src=\"<%= it.path %>scalar.js\"></script>\n <script>\n Scalar.createApiReference('#app', [{ ...<%~ JSON.stringify(it.config.baseDocument) %>,\n url: \"<%= it.path %>openapi.json\",\n }\n ])\n </script>\n </body>\n\n </html>`, { path, config: this.pluginOptions }));\n });\n this.get(\"/scalar.js\", (ctx) => {\n return ctx.file(__dirname + \"/../../node_modules/@scalar/api-reference/dist/browser/standalone.js\");\n });\n this.get(\"/openapi.json\", (ctx) => {\n return (this.root || this).generateApiSpec();\n });\n }\n}","import type { ShokupanContext } from \"../context\";\nimport type { Middleware, NextFn } from \"../types\";\n\nexport interface SecurityHeadersOptions {\n contentSecurityPolicy?: boolean | Record<string, any>;\n crossOriginEmbedderPolicy?: boolean;\n crossOriginOpenerPolicy?: boolean;\n crossOriginResourcePolicy?: boolean;\n dnsPrefetchControl?: boolean | { allow: boolean; };\n expectCt?: boolean | { maxAge?: number, enforce?: boolean, reportUri?: string; };\n frameguard?: boolean | { action: 'deny' | 'sameorigin' | 'allow-from', domain?: string; };\n hidePoweredBy?: boolean;\n hsts?: boolean | { maxAge?: number, includeSubDomains?: boolean, preload?: boolean; };\n ieNoOpen?: boolean;\n noSniff?: boolean;\n originAgentCluster?: boolean;\n permittedCrossDomainPolicies?: boolean | { permittedPolicies: 'none' | 'master-only' | 'by-content-type' | 'all'; };\n referrerPolicy?: boolean | { policy: string | string[]; };\n xssFilter?: boolean;\n}\n\nexport function SecurityHeaders(options: SecurityHeadersOptions = {}): Middleware {\n return async (ctx: ShokupanContext, next: NextFn) => {\n const headers: Record<string, string> = {};\n\n // Helper to set header if not already set or force it\n const set = (k: string, v: string) => headers[k] = v;\n\n // X-DNS-Prefetch-Control\n if (options.dnsPrefetchControl !== false) {\n const allow = (options.dnsPrefetchControl as any)?.allow;\n set(\"X-DNS-Prefetch-Control\", allow ? \"on\" : \"off\");\n }\n\n // X-Frame-Options\n if (options.frameguard !== false) {\n const opt = options.frameguard as any || {};\n const action = opt.action || 'sameorigin';\n if (action === 'sameorigin') set('X-Frame-Options', 'SAMEORIGIN');\n else if (action === 'deny') set('X-Frame-Options', 'DENY');\n // 'allow-from' is deprecated/obsolete in modern browsers, but we can support it if needed.\n }\n\n // Strict-Transport-Security\n if (options.hsts !== false) {\n const opt = options.hsts as any || {};\n const maxAge = opt.maxAge || 15552000; // 180 days\n let header = `max-age=${maxAge}`;\n if (opt.includeSubDomains !== false) header += '; includeSubDomains';\n if (opt.preload) header += '; preload';\n set('Strict-Transport-Security', header);\n }\n\n // X-Download-Options\n if (options.ieNoOpen !== false) {\n set('X-Download-Options', 'noopen');\n }\n\n // X-Content-Type-Options\n if (options.noSniff !== false) {\n set('X-Content-Type-Options', 'nosniff');\n }\n\n // X-XSS-Protection (Legacy, but still sometimes used)\n if (options.xssFilter !== false) {\n set('X-XSS-Protection', '0'); // Modern recommendation is to disable it as it can introduce vulns\n }\n\n // Referrer-Policy\n if (options.referrerPolicy !== false) {\n const opt = options.referrerPolicy as any || {};\n const policy = opt.policy || 'no-referrer';\n set('Referrer-Policy', Array.isArray(policy) ? policy.join(',') : policy);\n }\n\n // Content-Security-Policy\n if (options.contentSecurityPolicy !== false) {\n // Basic default CSP if true, or use object\n const opt = options.contentSecurityPolicy;\n if (opt === undefined || opt === true) {\n set('Content-Security-Policy', \"default-src 'self';base-uri 'self';font-src 'self' https: data:;form-action 'self';frame-ancestors 'self';img-src 'self' data:;object-src 'none';script-src 'self';style-src 'self' https: 'unsafe-inline';upgrade-insecure-requests\");\n } else if (typeof opt === 'object') {\n // Construct CSP string from object (simplified)\n // Assuming user passes raw string or we'd need a directive builder.\n // For now, let's assume they pass directives map.\n const parts = [];\n for (const [key, val] of Object.entries(opt)) {\n // directives, etc.\n // This is complex to implement fully without a library like 'helmet' itself.\n // We will support a simple string or custom logic later if requested.\n // For now, skip complex object parsing to keep it simple as per \"standard middleware\" MVP.\n }\n }\n }\n\n if (options.hidePoweredBy !== false) {\n // Note: Shokupan doesn't set X-Powered-By by default, so we usually don't need to remove it.\n // But we can ensure it's not there.\n // We can't delete from response easily before it's created, but we can try to suppress it if we had a hook.\n // Here we might just do nothing as we don't add it.\n }\n\n // Apply headers to context response\n // We need to apply these to the response *after* it's generated, or *before* if we use `ctx.headers` mutation?\n // `ctx.headers` is currently read-only wrapper around `req.headers` in `ShokupanContext`?\n // Wait, `ctx.headers` in `ShokupanContext` getter is `this.request.headers`.\n // We cannot set response headers on the request object.\n // We need to intercept the response.\n\n const response = await next();\n\n if (response instanceof Response) {\n for (const [k, v] of Object.entries(headers)) {\n response.headers.set(k, v);\n }\n return response;\n }\n\n // If next() returned something else (e.g. string/json that router will wrap),\n // we can't easily attach headers here unless we wrap the result in a Response.\n // BUT `compose` and `router` logic allows next() to return result which `router` converts to Response.\n // If middleware runs *before* router, next() returns the router's result.\n\n // If we want to ensure headers are set, we might need to rely on `ctx` having a way to set \"outgoing\" headers \n // that the router respects, OR we must wrap the response.\n\n return response;\n };\n}\n","import { createHmac, randomUUID } from \"crypto\";\nimport { EventEmitter } from \"events\";\nimport { ShokupanContext } from \"../context\";\nimport type { Middleware } from \"../types\";\n\n// --- Types ---\n\nexport interface SessionData {\n cookie: Cookie;\n [key: string]: any;\n}\n\nexport interface SessionCookieOptions {\n maxAge?: number;\n signed?: boolean;\n expires?: Date;\n httpOnly?: boolean;\n path?: string;\n domain?: string;\n secure?: boolean | 'auto';\n sameSite?: boolean | 'lax' | 'strict' | 'none';\n priority?: 'low' | 'medium' | 'high';\n}\n\nexport interface SessionOptions {\n secret: string | string[];\n name?: string;\n store?: Store;\n cookie?: SessionCookieOptions;\n genid?: (ctx: ShokupanContext) => string;\n resave?: boolean;\n saveUninitialized?: boolean;\n rolling?: boolean;\n unset?: 'destroy' | 'keep';\n}\n\nexport interface Store extends EventEmitter {\n get(sid: string, callback: (err: any, session?: SessionData | null) => void): void;\n set(sid: string, session: SessionData, callback?: (err?: any) => void): void;\n destroy(sid: string, callback?: (err?: any) => void): void;\n touch?(sid: string, session: SessionData, callback?: (err?: any) => void): void;\n all?(callback: (err: any, obj?: { [sid: string]: SessionData; } | null) => void): void;\n length?(callback: (err: any, length?: number) => void): void;\n clear?(callback?: (err?: any) => void): void;\n load?(sid: string, fn: (err: any, session?: SessionData | null) => void): void;\n createSession?(req: any, session: SessionData): SessionData;\n}\n\n// --- Cookie Helper ---\n\nclass Cookie implements SessionCookieOptions {\n maxAge?: number;\n signed?: boolean;\n expires?: Date;\n httpOnly?: boolean;\n path?: string;\n domain?: string;\n secure?: boolean | 'auto';\n sameSite?: boolean | 'lax' | 'strict' | 'none';\n originalMaxAge: number | undefined;\n\n constructor(options: SessionCookieOptions = {}) {\n this.path = options.path || '/';\n this.httpOnly = options.httpOnly !== undefined ? options.httpOnly : true;\n this.secure = options.secure;\n this.maxAge = options.maxAge;\n this.sameSite = options.sameSite;\n this.domain = options.domain;\n this.expires = options.expires;\n\n if (this.maxAge !== undefined) {\n this.originalMaxAge = this.maxAge;\n this.expires = new Date(Date.now() + this.maxAge);\n }\n }\n\n serialize(name: string, val: string) {\n let str = `${name}=${encodeURIComponent(val)}`;\n\n if (this.maxAge) {\n const expires = new Date(Date.now() + this.maxAge);\n str += `; Expires=${expires.toUTCString()}`;\n // Also add Max-Age?\n str += `; Max-Age=${Math.floor(this.maxAge / 1000)}`;\n } else if (this.expires) {\n str += `; Expires=${this.expires.toUTCString()}`;\n }\n\n if (this.domain) str += `; Domain=${this.domain}`;\n if (this.path) str += `; Path=${this.path}`;\n if (this.httpOnly) str += `; HttpOnly`;\n if (this.secure) str += `; Secure`;\n if (this.sameSite) {\n const sameSite = typeof this.sameSite === 'string' ?\n this.sameSite.charAt(0).toUpperCase() + this.sameSite.slice(1) : 'Strict';\n str += `; SameSite=${sameSite}`;\n }\n\n return str;\n }\n}\n\n// --- Memory Store ---\n\n\nexport class MemoryStore extends EventEmitter implements Store {\n private sessions: Record<string, string> = {};\n\n get(sid: string, cb: (err: any, session?: SessionData | null) => void) {\n const sess = this.sessions[sid];\n if (!sess) return cb(null, null);\n try {\n const data = JSON.parse(sess);\n // Re-hydrate dates?\n if (data.cookie && data.cookie.expires) {\n data.cookie.expires = new Date(data.cookie.expires);\n }\n cb(null, data);\n } catch (e) {\n cb(e);\n }\n }\n\n set(sid: string, sess: SessionData, cb?: (err?: any) => void) {\n this.sessions[sid] = JSON.stringify(sess);\n cb && cb();\n }\n\n destroy(sid: string, cb?: (err?: any) => void) {\n delete this.sessions[sid];\n cb && cb();\n }\n\n touch(sid: string, sess: SessionData, cb?: (err?: any) => void) {\n const current = this.sessions[sid];\n if (current) {\n // Update the cookie expiry if needed without changing the whole object if we want to be efficient\n // But for MemoryStore, just set is fine\n this.sessions[sid] = JSON.stringify(sess);\n }\n cb && cb();\n }\n\n all(cb: (err: any, obj?: { [sid: string]: SessionData; } | null) => void) {\n const result: Record<string, SessionData> = {};\n for (const sid in this.sessions) {\n try {\n result[sid] = JSON.parse(this.sessions[sid]);\n } catch { }\n }\n cb(null, result);\n }\n\n clear(cb?: (err?: any) => void) {\n this.sessions = {};\n cb && cb();\n }\n}\n\n// --- Crypto Helpers ---\n\nfunction sign(val: string, secret: string) {\n if (typeof val !== 'string') throw new TypeError(\"Cookie value must be provided as a string.\");\n if (typeof secret !== 'string') throw new TypeError(\"Secret string must be provided.\");\n return val + '.' + createHmac('sha256', secret).update(val).digest('base64').replace(/\\=+$/, '');\n}\n\nfunction unsign(input: string, secret: string) {\n if (typeof input !== 'string') throw new TypeError(\"Signed cookie string must be provided.\");\n if (typeof secret !== 'string') throw new TypeError(\"Secret string must be provided.\");\n const tentValue = input.slice(0, input.lastIndexOf('.'));\n const expectedInput = sign(tentValue, secret);\n const expectedBuffer = Buffer.from(expectedInput);\n const inputBuffer = Buffer.from(input);\n if (expectedBuffer.length !== inputBuffer.length) return false;\n // timingSafeEqual\n // crypto.timingSafeEqual is available in node/bun\n const valid = require('crypto').timingSafeEqual(expectedBuffer, inputBuffer);\n return valid ? tentValue : false;\n}\n\n// --- Middleware ---\n\nexport interface SessionContext {\n session: SessionData & {\n id: string;\n regenerate(callback: (err: any) => void): void;\n destroy(callback: (err: any) => void): void;\n reload(callback: (err: any) => void): void;\n save(callback: (err: any) => void): void;\n touch(): void;\n };\n sessionID: string;\n sessionStore: Store;\n}\n\n// Merge into ShokupanContext? TODO: Review.\ndeclare module \"../context\" {\n interface ShokupanContext {\n session: SessionContext['session'];\n sessionID: string;\n sessionStore: Store;\n }\n}\n\nexport function Session(options: SessionOptions): Middleware {\n const store = options.store || new MemoryStore();\n const name = options.name || 'connect.sid';\n const secrets = Array.isArray(options.secret) ? options.secret : [options.secret];\n\n // Validate store\n // (Could add check for .get .set .destroy)\n\n const generateId = options.genid || (() => randomUUID());\n\n const resave = options.resave === undefined ? true : options.resave;\n const saveUninitialized = options.saveUninitialized === undefined ? true : options.saveUninitialized;\n const rolling = options.rolling || false;\n\n return async (ctx: ShokupanContext, next) => {\n // 1. Get Session ID from Cookie\n let reqSessionId: string | null = null;\n let isSigned = false;\n\n // Simple cookie parser\n const cookieHeader = ctx.req.headers.get(\"cookie\");\n const cookies: Record<string, string> = {};\n if (cookieHeader) {\n cookieHeader.split(';').forEach(c => {\n const [k, v] = c.split('=').map(s => s.trim());\n if (k && v) cookies[k] = decodeURIComponent(v);\n });\n }\n\n const rawCookie = cookies[name];\n\n if (rawCookie) {\n if (rawCookie.substr(0, 2) === 's:') {\n // Signed cookie\n const val = unsign(rawCookie.slice(2), secrets[0]);\n if (val) {\n reqSessionId = val as string;\n isSigned = true;\n }\n } else {\n reqSessionId = rawCookie;\n }\n }\n\n // 2. Generate new ID if none\n let sessionID = reqSessionId;\n let isNew = false;\n if (!sessionID) {\n sessionID = generateId(ctx);\n isNew = true;\n }\n\n // 3. Helper to wrap session object\n const createSessionObject = (data: SessionData | null): SessionContext['session'] => {\n const existing = data || { cookie: new Cookie(options.cookie) };\n if (!existing.cookie) existing.cookie = new Cookie(options.cookie);\n else {\n // re-hydrate cookie options methods\n const c = new Cookie(options.cookie); // defaults\n Object.assign(c, existing.cookie);\n // ensure expiry is date\n if (c.expires && typeof c.expires === 'string') c.expires = new Date(c.expires);\n existing.cookie = c;\n }\n\n const sessObj = existing as any;\n\n // Methods\n Object.defineProperty(sessObj, 'id', { value: sessionID, configurable: true });\n\n sessObj.save = (cb: any) => {\n store.set(sessObj.id, sessObj, cb);\n };\n\n sessObj.destroy = (cb: any) => {\n store.destroy(sessObj.id, (err) => {\n // TODO: clear cookie?\n if (cb) cb(err);\n });\n };\n\n sessObj.regenerate = (cb: any) => {\n store.destroy(sessObj.id, (err) => {\n sessionID = generateId(ctx);\n // Create new session object\n // We actually need to replace the whole ctx.session object, which is tricky inside a method of that object.\n // Typically middleware attaches a proxy or the consumer does this.\n // But here we can reset properties.\n for (const key in sessObj) {\n if (key !== 'cookie' && key !== 'id' && typeof sessObj[key] !== 'function') {\n delete sessObj[key];\n }\n }\n Object.defineProperty(sessObj, 'id', { value: sessionID, configurable: true });\n if (cb) cb(err);\n });\n };\n\n sessObj.undefined = () => { }; // Helper? no\n sessObj.reload = (cb: any) => {\n store.get(sessObj.id, (err, sess) => {\n if (err) return cb(err);\n if (!sess) return cb(new Error(\"Session not found\"));\n // Populate\n for (const key in sessObj) {\n if (key !== 'cookie' && key !== 'id' && typeof sessObj[key] !== 'function') {\n delete sessObj[key];\n }\n }\n Object.assign(sessObj, sess);\n cb(null);\n });\n };\n\n sessObj.touch = () => {\n // Reset maxAge\n sessObj.cookie.expires = new Date(Date.now() + (sessObj.cookie.maxAge || 0));\n if (store.touch) store.touch(sessObj.id, sessObj);\n };\n\n return sessObj;\n };\n\n // 4. Load Session from Store\n let sessionData: SessionData | null = null;\n\n if (!isNew && sessionID) {\n await new Promise<void>((resolve) => {\n store.get(sessionID!, (err, sess) => {\n if (err) {\n // if error, treat as new? or error?\n // express-session logs and creates new\n sessionID = generateId(ctx);\n isNew = true;\n } else if (!sess) {\n // Session expired or invalid\n sessionID = generateId(ctx);\n isNew = true;\n } else {\n sessionData = sess;\n }\n resolve();\n });\n });\n }\n\n const sess = createSessionObject(sessionData);\n\n ctx.session = sess;\n ctx.sessionID = sessionID!;\n ctx.sessionStore = store;\n\n // Hash original sessionStr to detect changes\n const originalHash = JSON.stringify(sess);\n\n // 5. Run next\n const result = await next();\n\n // 6. Save Logic\n const currentHash = JSON.stringify(sess);\n const isModified = originalHash !== currentHash;\n\n if (!sessionID) return result; // Destroyed?\n\n let shouldSave = false;\n\n if (isModified) {\n shouldSave = true;\n } else if (isNew && saveUninitialized) {\n shouldSave = true;\n } else if (!isNew && resave) {\n shouldSave = true;\n }\n\n if (shouldSave) {\n await new Promise<void>((resolve, reject) => {\n store.set(sessionID!, sess, (err) => {\n if (err) console.error(\"Failed to save session\", err);\n resolve();\n });\n });\n }\n\n // 7. Set Cookie\n // Only set if new, or modified (rolling)\n // Express-session rules:\n // - if cookie.expires is set, it might need updating if rolling is true\n // - if isNew is true, definitely set cookie\n\n if (rolling && sess.cookie.maxAge) {\n sess.cookie.expires = new Date(Date.now() + sess.cookie.maxAge);\n }\n\n const shouldSetCookie = shouldSave || (!isNew && rolling);\n\n if (shouldSetCookie) {\n // value is just ID, or signed ID\n let val = sessionID;\n // We do simple signing s:id\n // Not enforcing secrets[0] yet\n if (secrets.length > 0) {\n val = 's:' + sign(val, secrets[0]);\n }\n\n const options = sess.cookie;\n // Serialize\n const str = options.serialize(name, val);\n ctx.set(\"Set-Cookie\", str);\n }\n\n return result;\n };\n}\n","import { ShokupanContext } from \"../context\";\nimport type { Middleware } from \"../types\";\n\nexport interface ValidationConfig {\n body?: any;\n query?: any;\n params?: any;\n headers?: any;\n}\n\nexport class ValidationError extends Error {\n public status = 400;\n constructor(public errors: any[]) {\n super(\"Validation Error\");\n }\n}\n\n// --- Adapters ---\n\nfunction isZod(schema: any): boolean {\n return typeof schema?.safeParse === 'function';\n}\n\nasync function validateZod(schema: any, data: any) {\n const result = await schema.safeParseAsync(data);\n if (!result.success) {\n throw new ValidationError(result.error.errors);\n }\n return result.data;\n}\n\nfunction isTypeBox(schema: any): boolean {\n return typeof schema?.Check === 'function' && typeof schema?.Errors === 'function';\n}\n\nfunction validateTypeBox(schema: any, data: any) {\n if (!schema.Check(data)) {\n throw new ValidationError([...schema.Errors(data)]);\n }\n return data;\n}\n\nfunction isAjv(schema: any): boolean {\n return typeof schema === 'function' && 'errors' in schema;\n}\n\nfunction validateAjv(schema: any, data: any) {\n const valid = schema(data);\n if (!valid) {\n throw new ValidationError(schema.errors);\n }\n return data;\n}\n\nexport const valibot = (schema: any, parser: Function) => {\n return {\n _valibot: true,\n schema,\n parser\n };\n};\n\nfunction isValibotWrapper(schema: any): boolean {\n return schema?._valibot === true;\n}\n\nasync function validateValibotWrapper(wrapper: any, data: any) {\n const result = await wrapper.parser(wrapper.schema, data);\n if (!result.success) {\n throw new ValidationError(result.issues);\n }\n return result.output;\n}\n\n\n// --- Body Helper ---\n\nconst safelyGetBody = async (ctx: ShokupanContext) => {\n const req = ctx.req as any;\n\n // Check if already parsed\n if (req._bodyParsed) {\n return req._bodyValue;\n }\n\n try {\n let data: any;\n // Standard Request consumes stream\n // ShokupanRequest (internal) has properties\n if (typeof req.json === 'function') {\n data = await req.json();\n }\n else {\n // Fallback if req is plain object with body property (internal usage)\n data = req.body;\n if (typeof data === 'string') {\n try { data = JSON.parse(data); } catch { }\n }\n }\n\n // Cache it\n req._bodyParsed = true;\n req._bodyValue = data;\n\n // Monkey patch json() to return cached data\n // This ensures subsequent calls (e.g. in handlers) get the same data\n // and don't fail due to stream locked\n Object.defineProperty(req, 'json', {\n value: async () => req._bodyValue,\n configurable: true\n });\n\n return data;\n } catch (e) {\n return {}; // Return empty object if parsing fails (flexible)\n }\n};\n\n\n// --- Main Middleware ---\n\nexport function validate(config: ValidationConfig): Middleware {\n return async (ctx: ShokupanContext, next) => {\n // Validate Params\n if (config.params) {\n ctx.params = await runValidation(config.params, ctx.params);\n }\n\n // Validate Query\n if (config.query) {\n const url = new URL(ctx.req.url);\n const queryObj = Object.fromEntries(url.searchParams.entries());\n const validQuery = await runValidation(config.query, queryObj);\n // We can't easily replace ctx.query as it is likely a getter wrapping URL\n // But we can store it in state\n // Or try to update URL search params?\n // If validation coerced types (e.g. string -> number), updating URL search params converts back to string.\n // So we attach to state.\n // (ctx.state as any).query = validQuery;\n }\n\n // Validate Headers\n if (config.headers) {\n const headersObj = Object.fromEntries(ctx.req.headers.entries());\n await runValidation(config.headers, headersObj);\n }\n\n // Validate Body\n if (config.body) {\n const body = await safelyGetBody(ctx);\n const validBody = await runValidation(config.body, body);\n\n // Update cached body with validated/sanitized version\n const req = ctx.req as any;\n req._bodyValue = validBody;\n\n // Ensure json() returns the validated body\n Object.defineProperty(req, 'json', {\n value: async () => validBody,\n configurable: true\n });\n\n (ctx as any).body = validBody; // Legacy/Convenience\n }\n\n return next();\n };\n}\n\nasync function runValidation(schema: any, data: any): Promise<any> {\n if (isZod(schema)) {\n return validateZod(schema, data);\n }\n if (isTypeBox(schema)) {\n return validateTypeBox(schema, data);\n }\n if (isAjv(schema)) {\n return validateAjv(schema, data);\n }\n if (isValibotWrapper(schema)) {\n return validateValibotWrapper(schema, data);\n }\n\n if (typeof schema === 'function') {\n return schema(data);\n }\n\n throw new Error(\"Unknown validator type provided. Please use a supported library (Zod, Ajv, TypeBox) or a custom function.\");\n}\n"],"names":["path","RouteParamType","Headers","NodeTracerProvider","resourceFromAttributes","ATTR_SERVICE_NAME","SimpleSpanProcessor","OTLPTraceExporter","trace","SpanKind","SpanStatusCode","fn","AsyncLocalStorage","eta","Eta","resolve","join","pattern","basename","stat","readdir","tracer","context","ctx","GitHub","Google","MicrosoftEntraId","Apple","Auth0","Okta","OAuth2Client","jose","provider","generateState","generateCodeVerifier","defaults","EventEmitter","createHmac","randomUUID","sess","options"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAKO,MAAM,iBAAiB;AAAA,EAClB,WAAW,IAAI,QAAA;AAAA,EACf,UAAU;AAAA;AAAA;AAAA;AAAA,EAKlB,IAAI,UAAU;AACV,WAAO,KAAK;AAAA,EAChB;AAAA;AAAA;AAAA;AAAA,EAKA,IAAI,SAAS;AACT,WAAO,KAAK;AAAA,EAChB;AAAA;AAAA;AAAA;AAAA,EAKA,IAAI,OAAO,MAAc;AACrB,SAAK,UAAU;AAAA,EACnB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOO,IAAI,KAAa,OAAe;AACnC,SAAK,SAAS,IAAI,KAAK,KAAK;AAC5B,WAAO;AAAA,EACX;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOO,OAAO,KAAa,OAAe;AACtC,SAAK,SAAS,OAAO,KAAK,KAAK;AAC/B,WAAO;AAAA,EACX;AAAA;AAAA;AAAA;AAAA;AAAA,EAMO,IAAI,KAAa;AACpB,WAAO,KAAK,SAAS,IAAI,GAAG;AAAA,EAChC;AAAA;AAAA;AAAA;AAAA;AAAA,EAMO,IAAI,KAAa;AACpB,WAAO,KAAK,SAAS,IAAI,GAAG;AAAA,EAChC;AACJ;ACxDO,MAAM,gBAAyE;AAAA,EAOlF,YACoB,SAChB,OACF;AAFkB,SAAA,UAAA;AAGhB,SAAK,MAAM,IAAI,IAAI,QAAQ,GAAG;AAC9B,SAAK,QAAQ,SAAS,CAAA;AACtB,SAAK,WAAW,IAAI,iBAAA;AAAA,EACxB;AAAA,EAbgB;AAAA,EACT,SAAiC,CAAA;AAAA,EACjC;AAAA,EAES;AAAA;AAAA;AAAA;AAAA,EAchB,IAAI,MAAM;AAAE,WAAO,KAAK;AAAA,EAAS;AAAA;AAAA;AAAA;AAAA,EAIjC,IAAI,SAAS;AAAE,WAAO,KAAK,QAAQ;AAAA,EAAQ;AAAA;AAAA;AAAA;AAAA,EAI3C,IAAI,OAAO;AAAE,WAAO,KAAK,IAAI;AAAA,EAAU;AAAA;AAAA;AAAA;AAAA,EAIvC,IAAI,QAAQ;AAAE,WAAO,OAAO,YAAY,KAAK,IAAI,YAAY;AAAA,EAAG;AAAA;AAAA;AAAA;AAAA,EAIhE,IAAI,UAAU;AAAE,WAAO,KAAK,QAAQ;AAAA,EAAS;AAAA;AAAA;AAAA;AAAA,EAK7C,IAAI,MAAM;AAAE,WAAO,KAAK;AAAA,EAAU;AAAA;AAAA;AAAA;AAAA,EAK3B,IAAI,KAAa,OAAe;AACnC,SAAK,SAAS,IAAI,KAAK,KAAK;AAC5B,WAAO;AAAA,EACX;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQO,UAAU,MAAc,OAAe,UAAyB,CAAA,GAAI;AACvE,QAAI,SAAS,GAAG,mBAAmB,IAAI,CAAC,IAAI,mBAAmB,KAAK,CAAC;AAErE,QAAI,QAAQ,OAAQ,WAAU,aAAa,KAAK,MAAM,QAAQ,MAAM,CAAC;AACrE,QAAI,QAAQ,QAAS,WAAU,aAAa,QAAQ,QAAQ,aAAa;AACzE,QAAI,QAAQ,SAAU,WAAU;AAChC,QAAI,QAAQ,OAAQ,WAAU;AAC9B,QAAI,QAAQ,OAAQ,WAAU,YAAY,QAAQ,MAAM;AACxD,QAAI,QAAQ,KAAM,WAAU,UAAU,QAAQ,QAAQ,GAAG;AACzD,QAAI,QAAQ,UAAU;AACD,aAAO,QAAQ,aAAa,WACvC,QAAQ,SAAS,gBACjB,QAAQ,WACJ,WACA;AAKV,gBAAU,cAAc,OAAO,QAAQ,aAAa,YAAY,WAAY,QAAQ,SAAS,OAAO,CAAC,EAAE,gBAAgB,QAAQ,SAAS,MAAM,CAAC,CAAE;AAAA,IACrJ;AACA,QAAI,QAAQ,UAAU;AAClB,gBAAU,cAAc,QAAQ,SAAS,OAAO,CAAC,EAAE,YAAA,IAAgB,QAAQ,SAAS,MAAM,CAAC,CAAC;AAAA,IAChG;AAEA,SAAK,SAAS,OAAO,cAAc,MAAM;AACzC,WAAO;AAAA,EACX;AAAA,EAEQ,aAAa,SAAgC;AACjD,UAAM,IAAI,IAAI,QAAQ,KAAK,SAAS,OAAO;AAC3C,QAAI,SAAS;AACT,UAAI,QAAQ,OAAO,EAAE,QAAQ,CAAC,GAAG,MAAM,EAAE,IAAI,GAAG,CAAC,CAAC;AAAA,IACtD;AACA,WAAO;AAAA,EACX;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQO,KAAK,MAAiB,SAAwB;AACjD,UAAM,UAAU,KAAK,aAAa,SAAS,OAAc;AACzD,UAAM,SAAS,SAAS,UAAU,KAAK,SAAS;AAChD,WAAO,IAAI,SAAS,MAAM,EAAE,QAAQ,SAAS;AAAA,EACjD;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,OAA4B;AAC9B,UAAM,cAAc,KAAK,QAAQ,QAAQ,IAAI,cAAc;AAC3D,QAAI,aAAa,SAAS,kBAAkB,GAAG;AAC3C,aAAO,KAAK,QAAQ,KAAA;AAAA,IACxB;AACA,QAAI,aAAa,SAAS,qBAAqB,KAAK,aAAa,SAAS,mCAAmC,GAAG;AAC5G,aAAO,KAAK,QAAQ,SAAA;AAAA,IACxB;AACA,WAAO,KAAK,QAAQ,KAAA;AAAA,EACxB;AAAA;AAAA;AAAA;AAAA,EAKA,KAAK,MAAW,QAAiB,SAAuB;AACpD,UAAM,eAAe,KAAK,aAAa,OAAO;AAC9C,iBAAa,IAAI,gBAAgB,kBAAkB;AACnD,UAAM,cAAc,UAAU,KAAK,SAAS;AAC5C,WAAO,IAAI,SAAS,KAAK,UAAU,IAAI,GAAG,EAAE,QAAQ,aAAa,SAAS,cAAc;AAAA,EAC5F;AAAA;AAAA;AAAA;AAAA,EAKA,KAAK,MAAc,QAAiB,SAAuB;AACvD,UAAM,eAAe,KAAK,aAAa,OAAO;AAC9C,iBAAa,IAAI,gBAAgB,YAAY;AAC7C,UAAM,cAAc,UAAU,KAAK,SAAS;AAC5C,WAAO,IAAI,SAAS,MAAM,EAAE,QAAQ,aAAa,SAAS,cAAc;AAAA,EAC5E;AAAA;AAAA;AAAA;AAAA,EAKA,KAAK,MAAc,QAAiB,SAAuB;AACvD,UAAM,eAAe,KAAK,aAAa,OAAO;AAC9C,iBAAa,IAAI,gBAAgB,WAAW;AAC5C,UAAM,cAAc,UAAU,KAAK,SAAS;AAC5C,WAAO,IAAI,SAAS,MAAM,EAAE,QAAQ,aAAa,SAAS,cAAc;AAAA,EAC5E;AAAA;AAAA;AAAA;AAAA,EAKA,SAAS,KAAa,SAAS,KAAK;AAChC,UAAM,UAAU,KAAK,aAAA;AACrB,YAAQ,IAAI,YAAY,GAAG;AAC3B,WAAO,IAAI,SAAS,MAAM,EAAE,QAAQ,SAAS;AAAA,EACjD;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,OAAO,QAAgB;AACnB,UAAM,UAAU,KAAK,aAAA;AACrB,WAAO,IAAI,SAAS,MAAM,EAAE,QAAQ,SAAS;AAAA,EACjD;AAAA;AAAA;AAAA;AAAA,EAKA,KAAKA,OAAc,aAA+B,iBAAgC;AAC9E,UAAM,UAAU,KAAK,aAAa,iBAAiB,OAAc;AACjE,UAAM,SAAS,iBAAiB,UAAU,KAAK,SAAS;AACxD,WAAO,IAAI,SAAS,IAAI,KAAKA,OAAM,WAAW,GAAG,EAAE,QAAQ,SAAS;AAAA,EACxE;AACJ;ACxLO,MAAM,iBAAiB,uBAAO,IAAI,cAAc;AAChD,MAAM,WAAW,uBAAO,IAAI,mBAAmB;AAC/C,MAAM,oCAAoB,oBAAoB;AAC9C,MAAM,uCAAuB,uBAAuB;AACpD,MAAM,oCAAoB,oBAAoB;AAC9C,MAAM,yCAAyB,yBAAyB;AACxD,MAAM,qCAAqB,qBAAqB;AAChD,MAAM,YAAY,uBAAO,IAAI,iBAAiB;AAC9C,MAAM,UAAU,uBAAO,IAAI,iBAAiB;AAC5C,MAAM,gBAAgB,uBAAO,IAAI,wBAAwB;AACzD,MAAM,oBAAoB,uBAAO,IAAI,4BAA4B;AACjE,MAAM,aAAa,uBAAO,IAAI,qBAAqB;AACnD,MAAM,YAAY,uBAAO,IAAI,mBAAmB;ACuBhD,MAAM,cAAc,CAAC,OAAO,QAAQ,OAAO,UAAU,SAAS,QAAQ,WAAW,KAAK;AAGtF,IAAK,mCAAAC,oBAAL;AACHA,kBAAA,MAAA,IAAO;AACPA,kBAAA,OAAA,IAAQ;AACRA,kBAAA,OAAA,IAAQ;AACRA,kBAAA,QAAA,IAAS;AACTA,kBAAA,SAAA,IAAU;AACVA,kBAAA,SAAA,IAAU;AANF,SAAAA;AAAA,GAAA,kBAAA,CAAA,CAAA;AChCL,SAAS,WAAWD,QAAe,KAAK;AAC3C,SAAO,CAAC,WAAgB;AACpB,WAAO,eAAe,IAAIA;AAAA,EAC9B;AACJ;AAKO,SAAS,OAAO,YAA0B;AAC7C,SAAO,CAAC,QAAa,aAAsB,eAAoC;AAE3E,QAAI,CAAC,aAAa;AACd,YAAM,WAAW,OAAO,WAAW,KAAK,CAAA;AACxC,aAAO,WAAW,IAAI,CAAC,GAAG,UAAU,GAAG,UAAU;AAAA,IACrD,OAEK;AACD,UAAI,CAAC,OAAO,WAAW,GAAG;AACtB,eAAO,WAAW,IAAI,oBAAI,IAAA;AAAA,MAC9B;AACA,YAAM,WAAW,OAAO,WAAW,EAAE,IAAI,WAAW,KAAK,CAAA;AACzD,aAAO,WAAW,EAAE,IAAI,aAAa,CAAC,GAAG,UAAU,GAAG,UAAU,CAAC;AAAA,IACrE;AAAA,EACJ;AACJ;AAIA,SAAS,qBAAqB,MAAsB;AAChD,SAAO,CAAC,SAAkB;AACtB,WAAO,CAAC,QAAa,aAAqB,mBAA2B;AACjE,UAAI,CAAC,OAAO,UAAU,GAAG;AACrB,eAAO,UAAU,IAAI,oBAAI,IAAA;AAAA,MAC7B;AACA,UAAI,CAAC,OAAO,UAAU,EAAE,IAAI,WAAW,GAAG;AACtC,eAAO,UAAU,EAAE,IAAI,aAAa,CAAA,CAAE;AAAA,MAC1C;AACA,aAAO,UAAU,EAAE,IAAI,WAAW,EAAE,KAAK;AAAA,QACrC,OAAO;AAAA,QACP;AAAA,QACA;AAAA,MAAA,CACH;AAAA,IACL;AAAA,EACJ;AACJ;AAEO,MAAM,OAAO,qBAAqB,eAAe,IAAI;AACrD,MAAM,QAAQ,qBAAqB,eAAe,KAAK;AACvD,MAAM,QAAQ,qBAAqB,eAAe,KAAK;AACvD,MAAME,YAAU,qBAAqB,eAAe,MAAM;AAC1D,MAAM,MAAM,qBAAqB,eAAe,OAAO;AACvD,MAAM,MAAM,qBAAqB,eAAe,OAAO;AAM9D,SAAS,sBAAsB,QAAgB;AAC3C,SAAO,CAACF,QAAe,QAAQ;AAC3B,WAAO,CAAC,QAAa,aAAqB,eAAmC;AACzE,UAAI,CAAC,OAAO,aAAa,GAAG;AACxB,eAAO,aAAa,IAAI,oBAAI,IAAA;AAAA,MAChC;AAEA,aAAO,aAAa,EAAE,IAAI,aAAa;AAAA,QACnC;AAAA,QACA,MAAAA;AAAA,MAAA,CACH;AAAA,IACL;AAAA,EACJ;AACJ;AAEO,MAAM,MAAM,sBAAsB,KAAK;AACvC,MAAM,OAAO,sBAAsB,MAAM;AACzC,MAAM,MAAM,sBAAsB,KAAK;AACvC,MAAM,SAAS,sBAAsB,QAAQ;AAC7C,MAAM,QAAQ,sBAAsB,OAAO;AAC3C,MAAM,UAAU,sBAAsB,SAAS;AAC/C,MAAM,OAAO,sBAAsB,MAAM;AACzC,MAAM,MAAM,sBAAsB,KAAK;AClFvC,MAAM,UAAU;AAAA,EACnB,OAAe,WAAW,oBAAI,IAAA;AAAA,EAE9B,OAAc,SAAY,QAAmC,UAAa;AACtE,SAAK,SAAS,IAAI,QAAQ,QAAQ;AAAA,EACtC;AAAA,EAEA,OAAc,IAAO,QAAkD;AACnE,WAAO,KAAK,SAAS,IAAI,MAAM;AAAA,EACnC;AAAA,EAEA,OAAc,IAAI,QAAsB;AACpC,WAAO,KAAK,SAAS,IAAI,MAAM;AAAA,EACnC;AAAA,EAEA,OAAc,QAAW,QAAsC;AAC3D,QAAI,KAAK,SAAS,IAAI,MAAM,GAAG;AAC3B,aAAO,KAAK,SAAS,IAAI,MAAM;AAAA,IACnC;AAMA,UAAM,WAAW,IAAI,OAAA;AACrB,SAAK,SAAS,IAAI,QAAQ,QAAQ;AAClC,WAAO;AAAA,EACX;AACJ;AAKO,SAAS,aAAa;AACzB,SAAO,CAAC,WAAgB;AAAA,EAExB;AACJ;AAKO,SAAS,OAAO,OAAY;AAC/B,SAAO,CAAC,QAAa,QAAgB;AACjC,WAAO,eAAe,QAAQ,KAAK;AAAA,MAC/B,KAAK,MAAM,UAAU,QAAQ,KAAK;AAAA,MAClC,YAAY;AAAA,MACZ,cAAc;AAAA,IAAA,CACjB;AAAA,EACL;AACJ;AC7CA,MAAM,WAAW,IAAIG,aAAAA,mBAAmB;AAAA,EACpC,UAAUC,UAAAA,uBAAuB;AAAA,IAC7B,CAACC,qCAAiB,GAAG;AAAA,EAAA,CACxB;AAAA,EACD,gBAAgB;AAAA,IACZ,IAAIC,aAAAA;AAAAA,MACA,IAAIC,yCAAkB;AAAA,QAClB,KAAK;AAAA;AAAA,MAAA,CACR;AAAA,IAAA;AAAA,EACL;AAER,CAAC;AACD,SAAS,SAAA;AAET,MAAM,SAASC,IAAAA,MAAM,UAAU,qBAAqB;AAK7C,SAAS,gBAAgB,IAAgB,MAA2B;AACvE,QAAM,iBAAyB,GAAG,QAAQ;AAE1C,SAAO,OAAO,KAAK,SAAS;AACxB,WAAO,OAAO,gBAAgB,gBAAgB,cAAc,IAAI;AAAA,MAC5D,MAAMC,IAAAA,SAAS;AAAA,MACf,YAAY;AAAA,QACR,iBAAiB;AAAA,QACjB,aAAa;AAAA,MAAA;AAAA,IACjB,GACD,OAAO,SAAS;AACf,UAAI;AACA,cAAM,SAAS,MAAM,GAAG,KAAK,IAAI;AACjC,eAAO;AAAA,MACX,SACO,KAAU;AACb,aAAK,gBAAgB,GAAG;AACxB,aAAK,UAAU,EAAE,MAAMC,IAAAA,eAAe,OAAO,SAAS,IAAI,SAAS;AACnE,cAAM;AAAA,MACV,UAAA;AAEI,aAAK,IAAA;AAAA,MACT;AAAA,IACJ,CAAC;AAAA,EACL;AACJ;AAKO,SAAS,aAAa,IAAiD,MAA+B;AACzG,SAAO,kBAA8B,MAAa;AAC9C,WAAO,OAAO,gBAAgB,mBAAmB,IAAI,IAAI;AAAA,MACrD,MAAMD,IAAAA,SAAS;AAAA,MACf,YAAY;AAAA,QACR,cAAc;AAAA,QACd,aAAa;AAAA,MAAA;AAAA,IACjB,GACD,OAAO,SAAS;AACf,UAAI;AACA,cAAM,SAAS,MAAO,GAAgB,MAAM,MAAM,IAAI;AACtD,eAAO;AAAA,MACX,SACO,KAAU;AACb,aAAK,gBAAgB,GAAG;AACxB,aAAK,UAAU,EAAE,MAAMC,IAAAA,eAAe,OAAO,SAAS,IAAI,SAAS;AACnE,cAAM;AAAA,MACV,UAAA;AAEI,aAAK,IAAA;AAAA,MACT;AAAA,IACJ,CAAC;AAAA,EACL;AACJ;ACzEO,MAAM,UAAU,CAAC,eAA6B;AACjD,WAAS,GAAG,SAAmC,MAAe;AAC1D,QAAI,SAAiB,SAAS,YAAY;AAAA,IAAE;AAE5C,aAAS,IAAI,WAAW,SAAS,GAAG,KAAK,GAAG,KAAK;AAC7C,YAAMC,MAAK,gBAAgB,WAAW,CAAC,CAAC;AACxC,YAAM,WAAW;AACjB,UAAI,SAAS;AAEb,eAAS,YAAY;AACjB,YAAI,OAAQ,OAAM,IAAI,MAAM,8BAA8B;AAC1D,iBAAS;AACT,eAAOA,IAAG,SAAS,QAAQ;AAAA,MAC/B;AAAA,IACJ;AAEA,WAAO,OAAA;AAAA,EACX;AAEA,SAAO;AACX;ACfA,MAAM,oBAAoB;AAAA,EACtB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EAEA,MAAM,OAAqB;AAAE,WAAO,KAAK,MAAM,KAAK,IAAI;AAAA,EAAG;AAAA,EAC3D,MAAM,OAAwB;AAAE,WAAO,KAAK;AAAA,EAAM;AAAA,EAClD,MAAM,WAA8B;AAChC,QAAI,KAAK,gBAAgB,UAAU;AAC/B,aAAO,KAAK;AAAA,IAChB;AACA,WAAO,IAAI,SAAS,KAAK,MAAM,EAAE,SAAS,KAAK,SAAS,EAAE,SAAA;AAAA,EAC9D;AAAA,EAEA,YAAY,OAA6B;AACrC,WAAO,OAAO,MAAM,KAAK;AACzB,QAAI,EAAE,KAAK,mBAAmB,UAAU;AACpC,WAAK,UAAU,IAAI,QAAQ,KAAK,OAAO;AAAA,IAC3C;AAAA,EACJ;AACJ;AAeO,MAAM,kBAAkB;AC9CxB,MAAM,eAAe,IAAIC,iBAAAA,kBAAA;ACAzB,SAAS,SAAS,MAAwC;AAC7D,SAAQ,QAAQ,OAAO,SAAS,YAAY,CAAC,MAAM,QAAQ,IAAI;AACnE;AASO,SAAS,UAAyC,WAAc,SAA0B;AAC7F,MAAI,CAAC,QAAQ,OAAQ,QAAO;AAC5B,QAAM,SAAS,QAAQ,MAAA;AAEvB,MAAI,SAAS,MAAM,KAAK,SAAS,MAAM,GAAG;AACtC,eAAW,OAAO,QAAQ;AACtB,UAAI,SAAS,OAAO,GAAG,CAAC,GAAG;AACvB,YAAI,CAAC,OAAO,GAAG,EAAG,QAAO,OAAO,QAAQ,EAAE,CAAC,GAAG,GAAG,CAAA,GAAI;AACrD,kBAAU,OAAO,GAAG,GAAG,OAAO,GAAG,CAAC;AAAA,MACtC,WAAW,MAAM,QAAQ,OAAO,GAAG,CAAC,GAAG;AACnC,YAAI,CAAC,OAAO,GAAG,EAAG,QAAO,OAAO,QAAQ,EAAE,CAAC,GAAG,GAAG,CAAA,GAAI;AAKpD,eAAe,GAAG,IAAK,OAAe,GAAG,EAAE,OAAO,OAAO,GAAG,CAAC;AAAA,MAClE,OAAO;AACH,eAAO,OAAO,QAAQ,EAAE,CAAC,GAAG,GAAG,OAAO,GAAG,GAAG;AAAA,MAChD;AAAA,IACJ;AAAA,EACJ;AAEA,SAAO,UAAU,QAAQ,GAAG,OAAO;AACvC;ACrBA,MAAMC,QAAM,IAAIC,MAAAA,IAAA;AAOT,MAAM,qCAAqB,IAAA;AAE3B,MAAM,0BAA0B,CAAA;AAEhC,MAAM,eAAoE;AAAA,EAsB7E,YACqB,QACnB;AADmB,SAAA,SAAA;AAAA,EAErB;AAAA;AAAA,EAvBA,CAAS,cAAc,IAAa;AAAA,EACpC,CAAS,UAAU,IAAa;AAAA,EAChC,CAAS,SAAS,IAAU;AAAA,EAC5B,CAAS,QAAQ;AAAA,EACjB,CAAS,UAAU,IAAY;AAAA,EAE/B,CAAS,OAAO,IAA8B;AAAA,EAC9C,CAAQ,aAAa,IAAyB,CAAA;AAAA,EAC9C,CAAQ,iBAAiB,IAA0B,CAAA;AAAA,EAEnD,IAAI,aAAa;AACb,WAAO,KAAK,QAAQ,GAAG;AAAA,EAC3B;AAAA,EACA,IAAI,OAAO;AACP,WAAO,KAAK,QAAQ;AAAA,EACxB;AAAA,EAEQ,SAA0B,CAAA;AAAA,EAC1B,gBAAyE,CAAA;AAAA,EAOzE,iBAAiB,QAAsH;AAE3I,WAAO,OAAO,WAAW,YAAY,WAAW,QAAQ,aAAa;AAAA,EACzE;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAYO,MAAM,QAAgB,YAA6F;AAEtH,QAAI,KAAK,iBAAiB,UAAU,GAAG;AACnC,UAAI,WAAW,UAAU,GAAG;AACxB,cAAM,IAAI,MAAM,2BAA2B;AAAA,MAC/C;AAEA,iBAAW,UAAU,IAAI;AACzB,WAAK,aAAa,EAAE,KAAK,UAAU;AAMnC,iBAAW,OAAO,IAAI;AAEtB,YAAM,mBAAmB,CAAC,WAA8B;AACpD,eAAO,QAAQ,IAAI,KAAK;AACxB,eAAO,aAAa,EAAE,QAAQ,CAAC,UAAU,iBAAiB,KAAK,CAAC;AAAA,MACpE;AACA,uBAAiB,UAAU;AAI3B,UAAI,KAAK,QAAQ,EAAG;AAGpB,iBAAW,QAAQ,IAAI,KAAK;AAC5B,iBAAW,UAAU,IAAI;AAAA,IAC7B,OAEK;AACD,UAAI,WAAW;AACf,UAAI,OAAO,eAAe,YAAY;AAElC,mBAAW,UAAU,QAAQ,UAAU;AAGvC,cAAM,iBAAkB,WAAmB,eAAe;AAC1D,YAAI,gBAAgB;AAGhB,gBAAM,KAAK,OAAO,SAAS,GAAG,IAAI,OAAO,MAAM,GAAG,EAAE,IAAI;AACxD,gBAAM,KAAK,eAAe,WAAW,GAAG,IAAI,iBAAiB,MAAM;AACnE,mBAAU,KAAK;AAEf,cAAI,CAAC,OAAQ,UAAS;AAAA,QAC1B;AAAA,MACJ;AAEA,eAAS,UAAU,IAAI;AACvB,WAAK,iBAAiB,EAAE,KAAK,QAAe;AAK5C,YAAM,wBAAwB,OAAO,eAAe,aAAc,WAAmB,WAAW,IAAK,SAAiB,WAAW,MAAM,CAAA;AAGvI,YAAM,QAAQ,OAAO,eAAe,QAAQ;AAC5C,YAAM,8BAAc,IAAA;AAGpB,UAAI,UAAU;AACd,aAAO,WAAW,YAAY,OAAO,WAAW;AAC5C,eAAO,oBAAoB,OAAO,EAAE,QAAQ,UAAQ,QAAQ,IAAI,IAAI,CAAC;AACrE,kBAAU,OAAO,eAAe,OAAO;AAAA,MAC3C;AAEA,aAAO,oBAAoB,QAAQ,EAAE,QAAQ,UAAQ,QAAQ,IAAI,IAAI,CAAC;AAEtE,YAAM,kBAAmB,SAAiB,aAAa,KAAM,SAAU,MAAc,aAAa;AAClG,YAAM,gBAAiB,SAAiB,UAAU,KAAM,SAAU,MAAc,UAAU;AAC1F,YAAM,sBAAuB,SAAiB,WAAW,KAAM,SAAU,MAAc,WAAW;AAElG,UAAI,iBAAiB;AACrB,iBAAW,QAAQ,SAAS;AACxB,YAAI,SAAS,cAAe;AAC5B,YAAI,CAAC,aAAa,UAAU,QAAQ,EAAE,SAAS,IAAI,EAAG;AAEtD,cAAM,kBAAmB,SAAiB,IAAI;AAC9C,YAAI,OAAO,oBAAoB,WAAY;AAE3C,YAAI;AACJ,YAAI,UAAU;AAGd,YAAI,mBAAmB,gBAAgB,IAAI,IAAI,GAAG;AAC9C,gBAAM,SAAS,gBAAgB,IAAI,IAAI;AACvC,mBAAS,OAAO;AAChB,oBAAU,OAAO;AAAA,QACrB,OAEK;AAGD,qBAAW,KAAK,aAAa;AACzB,gBAAI,KAAK,YAAA,EAAc,WAAW,CAAC,GAAG;AAClC,uBAAS;AACT,oBAAM,OAAO,KAAK,MAAM,EAAE,MAAM;AAChC,kBAAI,KAAK,WAAW,GAAG;AACnB,0BAAU;AAAA,cACd,OACK;AAED,0BAAU;AACV,oBAAI,SAAS;AACb,sBAAM,QAAQ,MAAM;AAChB,sBAAI,OAAO,SAAS,GAAG;AACnB,+BAAW,MAAM,OAAO,YAAA;AACxB,6BAAS;AAAA,kBACb;AAAA,gBACJ;AACA,yBAAS,IAAI,GAAG,IAAI,KAAK,QAAQ,KAAK;AAClC,wBAAM,OAAO,KAAK,CAAC;AACnB,sBAAI,SAAS,KAAK;AACd,0BAAA;AACA,+BAAW;AACX;AAAA,kBACJ;AAAA,gBAEJ;AACA,0BAAU,KACL,QAAQ,OAAO,IAAI,EACnB,QAAQ,sBAAsB,OAAO,EACrC,YAAA;AAEL,oBAAI,CAAC,QAAQ,WAAW,GAAG,GAAG;AAC1B,4BAAU,MAAM;AAAA,gBACpB;AAAA,cACJ;AACA;AAAA,YACJ;AAAA,UACJ;AAAA,QACJ;AAEA,YAAI,QAAQ;AACR;AAEA,gBAAM,cAAc,OAAO,SAAS,GAAG,IAAI,OAAO,MAAM,GAAG,EAAE,IAAI;AACjE,gBAAM,eAAe,YAAY,MAAM,KAAK;AAE5C,cAAI;AACJ,cAAI,aAAa,WAAW,GAAG;AAC3B,qBAAS;AAAA,UACb,WACS,aAAa,WAAW,GAAG,GAAG;AACnC,qBAAS,cAAc;AAAA,UAC3B,OACK;AACD,qBAAS,cAAc,MAAM;AAAA,UACjC;AAEA,gBAAM,WAAW,UAAU;AAC3B,gBAAM,iBAAiB,SAAS,QAAQ,QAAQ,GAAG;AAInD,gBAAM,WAAY,+BAA+B,MAAQ,oBAAoB,IAAI,IAAI,KAAK,CAAA,IAAM,CAAA;AAChG,gBAAM,gBAAgB,CAAC,GAAG,sBAAsB,GAAG,QAAQ;AAG3D,gBAAM,YAAY,iBAAiB,cAAc,IAAI,IAAI;AAGzD,gBAAM,iBAAiB,OAAO,QAA4B;AAEtD,gBAAI,OAAc,CAAC,GAAG;AAEtB,gBAAI,WAAW,SAAS,GAAG;AACvB,qBAAO,CAAA;AAEP,oBAAM,aAAa,CAAC,GAAG,SAAS,EAAE,KAAK,CAAC,GAAG,MAAM,EAAE,QAAQ,EAAE,KAAK;AAGlE,yBAAW,OAAO,YAAY;AAC1B,wBAAQ,IAAI,MAAA;AAAA,kBACR,KAAK,eAAe;AAChB,yBAAK,IAAI,KAAK,IAAI,MAAM,IAAI,IAAI,OAAO,MAAM,OAAO,CAAA,EAAG;AACvD;AAAA,kBACJ,KAAK,eAAe;AAChB,yBAAK,IAAI,KAAK,IAAI,IAAI,OAAO,IAAI,OAAO,IAAI,IAAI,IAAI,IAAI;AACxD;AAAA,kBACJ,KAAK,eAAe,OAAO;AACvB,0BAAM,MAAM,IAAI,IAAI,IAAI,IAAI,GAAG;AAC/B,yBAAK,IAAI,KAAK,IAAI,IAAI,OAAO,IAAI,aAAa,IAAI,IAAI,IAAI,IAAI,OAAO,YAAY,IAAI,YAAY;AACjG;AAAA,kBACJ;AAAA,kBACA,KAAK,eAAe;AAChB,yBAAK,IAAI,KAAK,IAAI,IAAI,OAAO,IAAI,IAAI,QAAQ,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI;AACrE;AAAA,kBACJ,KAAK,eAAe;AAChB,yBAAK,IAAI,KAAK,IAAI,IAAI;AACtB;AAAA,kBACJ,KAAK,eAAe;AAChB,yBAAK,IAAI,KAAK,IAAI;AAClB;AAAA,gBAAA;AAAA,cAEZ;AAAA,YACJ;AAEA,kBAAM,wBAAwB,aAAa,iBAAiB,cAAc;AAC1E,mBAAO,sBAAsB,MAAM,UAAU,IAAI;AAAA,UACrD;AAGA,cAAI,eAAe;AACnB,cAAI,cAAc,SAAS,GAAG;AAC1B,kBAAM,WAAW,QAAQ,aAAa;AACtC,2BAAe,OAAO,QAAQ;AAC1B,qBAAO,SAAS,KAAK,MAAM,eAAe,GAAG,CAAC;AAAA,YAClD;AAAA,UACJ;AAGA,gBAAM,UAAU,SAAS,YAAY;AAErC,gBAAM,OAAO,EAAE,MAAM,CAAC,OAAO,EAAA;AAE7B,eAAK,IAAI,EAAE,QAAQ,MAAM,gBAAgB,SAAS,cAAc,MAAM;AAAA,QAC1E;AAAA,MACJ;AACA,UAAI,mBAAmB,GAAG;AACtB,gBAAQ,KAAK,oCAAoC,SAAS,YAAY,IAAI,EAAE;AAAA,MAChF;AACA,eAAS,UAAU,IAAI;AAAA,IAC3B;AAEA,WAAO;AAAA,EACX;AAAA;AAAA;AAAA;AAAA,EAKO,YAA8E;AACjF,UAAM,SAAS,KAAK,OAAO,IAAI,CAAA,OAAM;AAAA,MACjC,QAAQ,EAAE;AAAA,MACV,MAAM,EAAE;AAAA,MACR,SAAS,EAAE;AAAA,IAAA,EACb;AAEF,eAAW,SAAS,KAAK,aAAa,GAAG;AACrC,YAAM,cAAc,MAAM,UAAA;AAC1B,iBAAW,SAAS,aAAa;AAC7B,cAAM,cAAc,MAAM,UAAU,EAAE,SAAS,GAAG,IAAI,MAAM,UAAU,EAAE,MAAM,GAAG,EAAE,IAAI,MAAM,UAAU;AACvG,cAAM,YAAY,MAAM,KAAK,WAAW,GAAG,IAAI,MAAM,OAAO,MAAM,MAAM;AACxE,cAAM,WAAY,cAAc,aAAc;AAE9C,eAAO,KAAK;AAAA,UACR,QAAQ,MAAM;AAAA,UACd,MAAM;AAAA,UACN,SAAS,MAAM;AAAA,QAAA,CAClB;AAAA,MACL;AAAA,IACJ;AACA,WAAO;AAAA,EACX;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAa,WAAW,KAKO;AAC3B,UAAM,UAAU,OAAO,QAAQ,WAAW,EAAE,MAAM,QAAQ;AAE1D,UAAM,QAAQ,aAAa,SAAA;AACP,WAAO,IAAI,KAAK;AAEpC,QAAI,MAAM,QAAQ;AAElB,QAAI,CAAC,IAAI,WAAW,MAAM,GAAG;AACzB,YAAM,OAAO,UAAU,KAAK,YAAY,YAAY,WAAW,IAAI,KAAK,WAAW,QAAQ,GAAI;AAG/F,YAAMd,QAAO,IAAI,WAAW,GAAG,IAAI,MAAM,MAAM;AAC/C,YAAM,OAAOA;AAAA,IACjB;AAEA,UAAM,MAAM,IAAI,gBAAgB;AAAA,MAC5B,QAAQ,QAAQ,UAAU;AAAA,MAC1B;AAAA,MACA,SAAS,QAAQ;AAAA,MACjB,MAAM,QAAQ,OAAO,KAAK,UAAU,QAAQ,IAAI,IAAI;AAAA,IAAA,CACvD;AAED,WAAO,KAAK,KAAK,SAAS,EAAE,GAAG;AAAA,EACnC;AAAA;AAAA;AAAA;AAAA,EAKA,MAAa,eAAe,SAAiD;AACzE,QAAI,MAAM,QAAQ,OAAO,QAAQ,QAAQ;AACzC,QAAI,CAAC,IAAI,WAAW,MAAM,GAAG;AACzB,YAAM,OAAO,UAAU,KAAK,YAAY,YAAY,WAAW,IAAI,KAAK,YAAY,QAAQ,GAAI;AAChG,YAAMA,QAAO,IAAI,WAAW,GAAG,IAAI,MAAM,MAAM;AAC/C,YAAM,OAAOA;AAAA,IACjB;AAGA,QAAI,QAAQ,OAAO;AACf,YAAM,IAAI,IAAI,IAAI,GAAG;AACrB,iBAAW,CAAC,GAAG,CAAC,KAAK,OAAO,QAAQ,QAAQ,KAAK,GAAG;AAChD,UAAE,aAAa,IAAI,GAAG,CAAC;AAAA,MAC3B;AACA,YAAM,EAAE,SAAA;AAAA,IACZ;AAEA,UAAM,MAAM,IAAI,gBAAgB;AAAA,MAC5B,QAAS,QAAQ,UAAU;AAAA,MAC3B;AAAA,MACA,SAAS,QAAQ;AAAA,MACjB,MAAM,QAAQ,QAAQ,OAAO,QAAQ,SAAS,WAAW,KAAK,UAAU,QAAQ,IAAI,IAAI,QAAQ;AAAA,IAAA,CACnG;AAOD,UAAM,MAAM,IAAI,gBAAmB,GAAG;AAEtC,QAAI,SAAc;AAClB,QAAI,SAAS;AACb,UAAM,UAAkC,CAAA;AAExC,UAAM,QAAQ,KAAK,KAAK,IAAI,QAAQ,IAAI,IAAI;AAC5C,QAAI,OAAO;AACP,UAAI,SAAS,MAAM;AACnB,UAAI;AACA,iBAAS,MAAM,MAAM,QAAQ,GAAG;AAAA,MACpC,SAAS,KAAU;AACf,gBAAQ,MAAM,GAAG;AACjB,iBAAS,IAAI,UAAU,IAAI,cAAc;AACzC,iBAAS,EAAE,OAAO,IAAI,WAAW,wBAAA;AACjC,YAAI,IAAI,OAAQ,QAAO,SAAS,IAAI;AAAA,MACxC;AAAA,IACJ,OACK;AACD,eAAS;AACT,eAAS;AAAA,IACb;AAOA,QAAI,kBAAkB,UAAU;AAC5B,eAAS,OAAO;AAChB,aAAO,QAAQ,QAAQ,CAAC,GAAG,MAAM,QAAQ,CAAC,IAAI,CAAC;AAE/C,UAAI,QAAQ,cAAc,GAAG,SAAS,kBAAkB,GAAG;AACvD,iBAAS,MAAM,OAAO,KAAA;AAAA,MAC1B,OACK;AACD,iBAAS,MAAM,OAAO,KAAA;AAAA,MAC1B;AAAA,IACJ;AAEA,WAAO;AAAA,MACH;AAAA,MACA;AAAA,MACA,MAAM;AAAA,IAAA;AAAA,EAEd;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQO,KAAK,QAAgBA,OAAuF;AAI/G,eAAW,SAAS,KAAK,QAAQ;AAC7B,UAAI,MAAM,WAAW,SAAS,MAAM,WAAW,OAAQ;AAEvD,YAAM,QAAQ,MAAM,MAAM,KAAKA,KAAI;AACnC,UAAI,OAAO;AAEP,cAAM,SAAiC,CAAA;AACvC,cAAM,KAAK,QAAQ,CAAC,KAAK,UAAU;AAC/B,iBAAO,GAAG,IAAI,MAAM,QAAQ,CAAC;AAAA,QACjC,CAAC;AACD,eAAO,EAAE,SAAS,MAAM,SAAS,OAAA;AAAA,MACrC;AAAA,IACJ;AAGA,eAAW,SAAS,KAAK,aAAa,GAAG;AACrC,YAAM,SAAS,MAAM,UAAU;AAG/B,UAAIA,UAAS,UAAUA,MAAK,WAAW,SAAS,GAAG,GAAG;AAClD,cAAM,UAAUA,MAAK,MAAM,OAAO,MAAM,KAAK;AAC7C,cAAM,QAAQ,MAAM,KAAK,QAAQ,OAAO;AACxC,YAAI,MAAO,QAAO;AAAA,MACtB;AAEA,UAAI,OAAO,SAAS,GAAG,GAAG;AACtB,YAAIA,MAAK,WAAW,MAAM,GAAG;AACzB,gBAAM,UAAUA,MAAK,MAAM,OAAO,MAAM,KAAK;AAC7C,gBAAM,QAAQ,MAAM,KAAK,QAAQ,OAAO;AACxC,cAAI,MAAO,QAAO;AAAA,QACtB;AAAA,MACJ;AAAA,IACJ;AAEA,WAAO;AAAA,EACX;AAAA,EAEQ,UAAUA,OAAkD;AAChE,UAAM,OAAiB,CAAA;AACvB,UAAM,UAAUA,MACX,QAAQ,qBAAqB,CAAC,GAAG,QAAQ;AACtC,WAAK,KAAK,GAAG;AACb,aAAO;AAAA,IACX,CAAC,EACA,QAAQ,OAAO,IAAI;AAExB,WAAO;AAAA,MACH,OAAO,IAAI,OAAO,IAAI,OAAO,GAAG;AAAA,MAChC;AAAA,IAAA;AAAA,EAER;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAYO,IAAI,EAAE,QAAQ,MAAAA,OAAM,MAAM,SAAS,OAAO,aAAa,SAO3D;AACC,UAAM,EAAE,OAAO,SAAS,cAClB,EAAE,OAAO,aAAa,MAAM,CAAA,EAAC,IAC7B,KAAK,UAAUA,KAAI;AAGzB,QAAI,iBAAiB;AACrB,UAAM,cAAc,CAAC,GAAG,KAAK,aAAa;AAE1C,QAAI,YAAY,SAAS,GAAG;AACxB,uBAAiB,OAAO,QAA4B;AAEhD,mBAAW,SAAS,aAAa;AAC7B,cAAI,cAAc;AAClB,cAAI,aAAa;AAGjB,gBAAM,OAAO,MAAM;AACf,yBAAa;AACb,mBAAO,QAAQ,QAAA;AAAA,UACnB;AAEA,cAAI;AACA,kBAAM,SAAS,MAAM,MAAM,QAAQ,KAAK,IAAI;AAG5C,gBAAI,WAAW,QAAQ,YAAY;AAC/B,4BAAc;AAAA,YAClB,WAES,WAAW,UAAa,WAAW,QAAQ,WAAW,OAAO;AAClE,qBAAO;AAAA,YACX,OAEK;AACD,qBAAO,IAAI,KAAK,EAAE,OAAO,YAAA,GAAe,GAAG;AAAA,YAC/C;AAAA,UACJ,SACO,OAAO;AAEV,kBAAM;AAAA,UACV;AAEA,cAAI,CAAC,aAAa;AACd,mBAAO,IAAI,KAAK,EAAE,OAAO,YAAA,GAAe,GAAG;AAAA,UAC/C;AAAA,QACJ;AAGA,eAAO,QAAQ,GAAG;AAAA,MACtB;AAAA,IACJ;AAEA,SAAK,OAAO,KAAK;AAAA,MACb;AAAA,MACA,MAAAA;AAAA,MACA;AAAA,MACA;AAAA,MACA,SAAS;AAAA,MACT,aAAa;AAAA,MACb;AAAA,MACA,QAAQ,YAAY,SAAS,IAAI,cAAc;AAAA,IAAA,CAClD;AAED,WAAO;AAAA,EACX;AAAA,EAiBO,IAAIA,UAAiB,MAA8C;AACtE,SAAK,WAAW,OAAOA,OAAM,GAAG,IAAI;AACpC,WAAO;AAAA,EACX;AAAA,EAiBO,KAAKA,UAAiB,MAA8C;AACvE,SAAK,WAAW,QAAQA,OAAM,GAAG,IAAI;AACrC,WAAO;AAAA,EACX;AAAA,EAiBO,IAAIA,UAAiB,MAA8C;AACtE,SAAK,WAAW,OAAOA,OAAM,GAAG,IAAI;AACpC,WAAO;AAAA,EACX;AAAA,EAiBO,OAAOA,UAAiB,MAA8C;AACzE,SAAK,WAAW,UAAUA,OAAM,GAAG,IAAI;AACvC,WAAO;AAAA,EACX;AAAA,EAiBO,MAAMA,UAAiB,MAA8C;AACxE,SAAK,WAAW,SAASA,OAAM,GAAG,IAAI;AACtC,WAAO;AAAA,EACX;AAAA,EAiBO,QAAQA,UAAiB,MAA8C;AAC1E,SAAK,WAAW,WAAWA,OAAM,GAAG,IAAI;AACxC,WAAO;AAAA,EACX;AAAA,EAiBO,KAAKA,UAAiB,MAA8C;AACvE,SAAK,WAAW,QAAQA,OAAM,GAAG,IAAI;AACrC,WAAO;AAAA,EACX;AAAA,EAiBO,MAAM,eAAkD,SAA8B;AACzF,UAAM,OAAO,OAAO,kBAAkB,aAAa,SAAY;AAC/D,UAAM,eAAe,OAAO,kBAAkB,aAAa,gBAAsC;AAEjG,SAAK,cAAc,KAAK,EAAE,SAAS,cAAc,MAAM;AAEvD,WAAO;AAAA,EACX;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOO,OAAO,SAAiB,SAAyC;AACpE,UAAM,SAAgC,OAAO,YAAY,WAAW,EAAE,MAAM,YAAY;AACxF,UAAM,WAAWe,KAAAA,QAAQ,OAAO,QAAQ,GAAG;AAE3C,UAAM,SAAS,QAAQ,WAAW,GAAG,IAAI,UAAU,MAAM;AACzD,UAAM,mBAAmB,OAAO,SAAS,GAAG,KAAK,WAAW,MAAM,OAAO,MAAM,GAAG,EAAE,IAAI;AAExF,UAAM,UAAU,OAAO,QAA4B;AAI/C,UAAI,WAAW,IAAI,KAAK,MAAM,iBAAiB,MAAM;AACrD,UAAI,CAAC,SAAS,WAAW,GAAG,KAAK,SAAS,SAAS,EAAG,YAAW,MAAM;AACvE,UAAI,SAAS,WAAW,EAAG,YAAW;AAGtC,iBAAW,mBAAmB,QAAQ;AAGtC,YAAM,cAAcC,KAAAA,KAAK,UAAU,QAAQ;AAC3C,UAAI,CAAC,YAAY,WAAW,QAAQ,GAAG;AACnC,eAAO,IAAI,KAAK,EAAE,OAAO,YAAA,GAAe,GAAG;AAAA,MAC/C;AAGA,UAAI,YAAY,SAAS,IAAI,GAAG;AAC5B,eAAO,IAAI,KAAK,EAAE,OAAO,YAAA,GAAe,GAAG;AAAA,MAC/C;AAGA,UAAI,OAAO,OAAO,WAAW;AACzB,cAAM,MAAM,MAAM,OAAO,MAAM,UAAU,GAAG;AAC5C,YAAI,IAAK,QAAO;AAAA,MACpB;AAGA,UAAI,OAAO,SAAS;AAChB,mBAAWC,YAAW,OAAO,SAAS;AAClC,cAAIA,oBAAmB,QAAQ;AAC3B,gBAAIA,SAAQ,KAAK,QAAQ,EAAG,QAAO,IAAI,KAAK,EAAE,OAAO,YAAA,GAAe,GAAG;AAAA,UAC3E,WAAW,OAAOA,aAAY,UAAU;AACpC,gBAAI,SAAS,SAASA,QAAO,EAAG,QAAO,IAAI,KAAK,EAAE,OAAO,YAAA,GAAe,GAAG;AAAA,UAC/E;AAAA,QACJ;AAAA,MACJ;AAGA,UAAIC,KAAAA,SAAS,WAAW,EAAE,WAAW,GAAG,GAAG;AACvC,cAAM,WAAW,OAAO,YAAY;AACpC,YAAI,aAAa,OAAQ,QAAO,IAAI,KAAK,EAAE,OAAO,YAAA,GAAe,GAAG;AACpE,YAAI,aAAa,SAAU,QAAO,IAAI,KAAK,EAAE,OAAO,YAAA,GAAe,GAAG;AAAA,MAC1E;AAEA,UAAI,YAAY;AAChB,UAAI;AAEJ,UAAI;AACA,gBAAQ,MAAMC,SAAAA,KAAK,WAAW;AAAA,MAClC,SAAS,GAAG;AAER,YAAI,OAAO,YAAY;AACnB,qBAAW,OAAO,OAAO,YAAY;AACjC,kBAAM,IAAI,eAAe,IAAI,WAAW,GAAG,IAAI,MAAM,MAAM;AAC3D,gBAAI;AACA,oBAAM,IAAI,MAAMA,SAAAA,KAAK,CAAC;AACtB,kBAAI,EAAE,UAAU;AACZ,4BAAY;AACZ,wBAAQ;AACR;AAAA,cACJ;AAAA,YACJ,QAAQ;AAAA,YAAE;AAAA,UACd;AAAA,QACJ;AACA,YAAI,CAAC,MAAO,QAAO,IAAI,KAAK,EAAE,OAAO,YAAA,GAAe,GAAG;AAAA,MAC3D;AAGA,UAAI,MAAM,eAAe;AAGrB,YAAI,CAAC,IAAI,KAAK,SAAS,GAAG,GAAG;AACzB,gBAAM,QAAQ,IAAI,IAAI;AACtB,iBAAO,IAAI,SAAS,IAAI,OAAO,MAAM,OAAO,GAAG;AAAA,QACnD;AAGA,YAAI,UAAoB,CAAA;AACxB,YAAI,OAAO,UAAU,QAAW;AAC5B,oBAAU,CAAC,cAAc,WAAW;AAAA,QACxC,WACS,MAAM,QAAQ,OAAO,KAAK,GAAG;AAClC,oBAAU,OAAO;AAAA,QACrB,WACS,OAAO,OAAO;AACnB,oBAAU,CAAC,OAAO,KAAK;AAAA,QAC3B;AAEA,YAAI,aAAa;AACjB,mBAAW,OAAO,SAAS;AACvB,gBAAM,UAAUH,KAAAA,KAAK,WAAW,GAAG;AACnC,cAAI;AACA,kBAAM,WAAW,MAAMG,SAAAA,KAAK,OAAO;AACnC,gBAAI,SAAS,UAAU;AACnB,0BAAY;AACZ,2BAAa;AACb;AAAA,YACJ;AAAA,UACJ,QAAQ;AAAA,UAAE;AAAA,QACd;AAEA,YAAI,CAAC,YAAY;AACb,cAAI,OAAO,eAAe;AAEtB,gBAAI;AACA,oBAAM,QAAQ,MAAMC,SAAAA,QAAQ,WAAW;AAEvC,oBAAM,UAAUP,MAAI,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,+BA0B9B,EAAE,UAAU,OAAA,MAAOG,KAAAA,KAAA,CAAM;AAC5B,qBAAO,IAAI,SAAS,SAAS,EAAE,SAAS,EAAE,gBAAgB,YAAA,GAAe;AAAA,YAC7E,SAAS,GAAG;AACR,qBAAO,IAAI,KAAK,EAAE,OAAO,wBAAA,GAA2B,GAAG;AAAA,YAC3D;AAAA,UACJ,OAAO;AAGH,mBAAO,IAAI,KAAK,EAAE,OAAO,YAAA,GAAe,GAAG;AAAA,UAC/C;AAAA,QACJ;AAAA,MACJ;AAIA,YAAM,OAAO,IAAI,KAAK,SAAS;AAC/B,UAAI,WAAW,IAAI,SAAS,IAAI;AAEhC,UAAI,OAAO,OAAO,YAAY;AAC1B,cAAM,SAAS,MAAM,OAAO,MAAM,WAAW,KAAK,QAAQ;AAC1D,YAAI,OAAQ,YAAW;AAAA,MAC3B;AACA,aAAO;AAAA,IACX;AAKA,QAAI,YAAY;AAChB,UAAM,WAAW,iBAAiB,MAAM,GAAG,EAAE,OAAO,OAAO;AAC3D,QAAI,SAAS,SAAS,GAAG;AACrB,YAAM,OAAO,SAAS,SAAS,SAAS,CAAC;AACzC,kBAAY,KAAK,OAAO,CAAC,EAAE,gBAAgB,KAAK,MAAM,CAAC;AAAA,IAC3D;AAEA,UAAM,cAAc;AAAA,MAChB,SAAS;AAAA,MACT,aAAa,8BAA8B;AAAA,MAC3C,MAAM,CAAC,SAAS;AAAA,IAAA;AAEpB,UAAM,OAAO,OAAO,UAAU,OAAO,UAAU;AAC/C,QAAI,CAAC,KAAK,KAAM,MAAK,OAAO,CAAC,SAAS;AAAA,aAC7B,CAAC,KAAK,KAAK,SAAS,SAAS,EAAG,MAAK,KAAK,KAAK,SAAS;AAEjE,UAAM,UAAU,IAAI,gBAAgB;AACpC,UAAM,QAAQ,IAAI,OAAO,OAAO;AAGhC,UAAM,cAAc,qBAAqB,MAAM,OAAO,mBAAmB;AAEzE,SAAK,IAAI,EAAE,QAAQ,OAAO,MAAM,aAAa,SAAS,MAAM,OAAO;AACnE,SAAK,IAAI,EAAE,QAAQ,QAAQ,MAAM,aAAa,SAAS,MAAM,OAAO;AAEpE,WAAO;AAAA,EACX;AAAA;AAAA;AAAA;AAAA;AAAA,EAOQ,WAAW,QAAgBhB,UAAiB,MAA8C;AAC9F,QAAI;AACJ,QAAI,WAAiC,CAAA;AAErC,QAAI,KAAK,SAAS,GAAG;AAEjB,UAAI,OAAO,KAAK,CAAC,MAAM,YAAY,KAAK,CAAC,MAAM,MAAM;AACjD,eAAO,KAAK,CAAC;AACb,mBAAW,KAAK,MAAM,CAAC;AAAA,MAC3B,OAAO;AACH,mBAAW;AAAA,MACf;AAAA,IACJ;AAEA,QAAI,SAAS,WAAW,GAAG;AAEvB;AAAA,IACJ;AAEA,QAAI,eAAe,SAAS,SAAS,SAAS,CAAC;AAO/C,QAAI,SAAS,SAAS,GAAG;AAIrB,YAAM,KAAK,QAAQ,QAAe;AAClC,qBAAe,CAAC,QAAQ,GAAG,GAAG;AAAA,IAClC;AAEA,SAAK,IAAI;AAAA,MACL;AAAA,MACA,MAAAA;AAAA,MACA;AAAA,MACA,SAAS;AAAA,IAAA,CACZ;AAAA,EACL;AAAA;AAAA;AAAA;AAAA,EAKO,gBAAgB,UAA0B,IAAsB;AACnE,UAAM,QAAmC,CAAA;AACzC,UAAM,gCAAgB,IAAA;AAEtB,UAAM,kBAAkB,QAAQ,mBAAmB;AACnD,UAAM,iBAAiB,QAAQ,cAAc;AAG7C,UAAM,UAAU,CAAC,QAA2B,SAAS,IAAI,eAAe,iBAAiB,aAAa,mBAAmB;AAErH,UAAI,QAAQ;AACZ,UAAI,MAAM;AAGV,UAAI,OAAO,QAAQ,OAAO;AACtB,gBAAQ,OAAO,OAAO;AAAA,MAC1B;AAQA,UAAI,OAAO,QAAQ,MAAM;AACrB,cAAM,OAAO,OAAO;AAAA,MACxB,OAAO;AAEH,cAAM,YAAY,OAAO,UAAU;AACnC,YAAI,aAAa,cAAc,KAAK;AAGhC,gBAAM,WAAW,UAAU,MAAM,GAAG,EAAE,OAAO,OAAO;AACpD,cAAI,SAAS,SAAS,GAAG;AACrB,kBAAM,cAAc,SAAS,SAAS,SAAS,CAAC;AAEhD,kBAAM,YAAY,YACb,QAAQ,SAAS,GAAG,EACpB,QAAQ,SAAS,CAAA,MAAK,EAAE,YAAA,CAAa;AAE1C,kBAAM;AAAA,UACV;AAAA,QACJ;AAAA,MACJ;AAGA,UAAI,CAAC,UAAU,IAAI,KAAK,GAAG;AACvB,kBAAU,IAAI,OAAO,oBAAI,IAAA,CAAK;AAAA,MAClC;AAGA,iBAAW,SAAS,OAAO,QAAQ;AAE/B,cAAM,aAAa,MAAM,SAAS;AAGlC,cAAM,cAAc,OAAO,SAAS,GAAG,IAAI,OAAO,MAAM,GAAG,EAAE,IAAI;AACjE,cAAM,eAAe,MAAM,KAAK,WAAW,GAAG,IAAI,MAAM,OAAO,MAAM,MAAM;AAC3E,YAAI,WAAY,cAAc,gBAAiB;AAG/C,mBAAW,SAAS,QAAQ,qBAAqB,MAAM;AAGvD,YAAI,CAAC,MAAM,QAAQ,GAAG;AAClB,gBAAM,QAAQ,IAAI,CAAA;AAAA,QACtB;AAGA,cAAM,YAA+B;AAAA,UACjC,WAAW;AAAA,YACP,KAAK,EAAE,aAAa,KAAA;AAAA,UAAK;AAAA,QAC7B;AAIJ,YAAI,MAAM,KAAK,SAAS,GAAG;AACvB,oBAAU,aAAa,MAAM,KAAK,IAAI,CAAA,SAAQ;AAAA,YAC1C,MAAM;AAAA,YACN,IAAI;AAAA,YACJ,UAAU;AAAA,YACV,QAAQ,EAAE,MAAM,SAAA;AAAA,UAAS,EAC3B;AAAA,QACN;AAGA,YAAI,MAAM,QAAQ;AACd,qBAAW,SAAS,MAAM,QAAQ;AAC9B,gBAAI,MAAM,MAAM;AACZ,wBAAU,WAAW,MAAM,IAAI;AAAA,YACnC;AAAA,UACJ;AAAA,QACJ;AAGA,YAAI,MAAM,aAAa;AACnB,oBAAU,WAAW,MAAM,WAAW;AAAA,QAC1C;AAGA,YAAI,CAAC,UAAU,QAAQ,UAAU,KAAK,WAAW,GAAG;AAChD,oBAAU,OAAO,CAAC,GAAG;AAAA,QACzB;AAGA,YAAI,UAAU,MAAM;AAChB,oBAAU,OAAO,MAAM,KAAK,IAAI,IAAI,UAAU,IAAI,CAAC;AAEnD,qBAAW,KAAK,UAAU,MAAM;AAE5B,gBAAI,CAAC,UAAU,IAAI,UAAU,GAAG;AAC5B,wBAAU,IAAI,YAAY,oBAAI,IAAA,CAAK;AAAA,YACvC;AACA,sBAAU,IAAI,UAAU,GAAG,IAAI,CAAC;AAAA,UACpC;AAAA,QACJ;AAGA,cAAM,cAAc,MAAM,OAAO,YAAA;AACjC,YAAI,gBAAgB,OAAO;AACvB,WAAC,OAAO,QAAQ,OAAO,UAAU,OAAO,EAAE,QAAQ,CAAA,MAAK;AACnD,gBAAI,CAAE,MAAc,QAAQ,EAAE,CAAC,GAAG;AAC7B,oBAAc,QAAQ,EAAE,CAAC,IAAI,EAAE,GAAG,UAAA;AAAA,YACvC;AAAA,UACJ,CAAC;AAAA,QACL,OAAO;AACF,gBAAc,QAAQ,EAAE,WAAW,IAAI;AAAA,QAC5C;AAAA,MACJ;AAGA,iBAAW,cAAc,OAAO,iBAAiB,GAAG;AAChD,cAAM,YAAa,WAAmB,UAAU,KAAK;AAEjC,eAAO,SAAS,GAAG,IAAI,OAAO,MAAM,GAAG,EAAE,IAAI;AAC9C,kBAAU,WAAW,GAAG,IAAI,YAAY,MAAM;AAIjE,cAAM,iBAAiB,WAAW,YAAY,QAAQ;AACtD,kBAAU,IAAI,KAAK,GAAG,IAAI,cAAc;AAAA,MA2B5C;AAGA,iBAAW,SAAS,OAAO,aAAa,GAAG;AACvC,cAAM,YAAY,MAAM,UAAU;AAClC,cAAM,cAAc,OAAO,SAAS,GAAG,IAAI,OAAO,MAAM,GAAG,EAAE,IAAI;AACjE,cAAM,aAAa,UAAU,WAAW,GAAG,IAAI,YAAY,MAAM;AACjE,cAAM,aAAc,cAAc,cAAe;AAEjD,gBAAQ,OAAO,YAAY,OAAO,GAAG;AAAA,MACzC;AAAA,IACJ;AAMA,YAAQ,IAAI;AAGZ,UAAM,aAAkD,CAAA;AACxD,eAAW,CAAC,MAAM,IAAI,KAAK,WAAW;AAClC,iBAAW,KAAK;AAAA,QACZ;AAAA,QACA,MAAM,MAAM,KAAK,IAAI,EAAE,KAAA;AAAA,MAAK,CAC/B;AAAA,IACL;AAEA,WAAO;AAAA,MACH,SAAS;AAAA,MACT,MAAM;AAAA,QACF,OAAO;AAAA,QACP,SAAS;AAAA,QACT,GAAG,QAAQ;AAAA,MAAA;AAAA,MAEf;AAAA,MACA,YAAY,QAAQ;AAAA,MACpB,SAAS,QAAQ;AAAA,MACjB,MAAM,QAAQ;AAAA,MACd,cAAc,QAAQ;AAAA,MACtB,eAAe;AAAA,IAAA;AAAA,EAEvB;AACJ;ACrrCA,MAAM,WAA2B;AAAA,EAC7B,MAAM;AAAA,EACN,UAAU;AAAA,EACV,aAAa,QAAQ,IAAI,aAAa;AAAA,EACtC,yBAAyB;AAC7B;AACeQ,IAAAA,MAAM,UAAU,sBAAsB;AAG9C,MAAM,iBAA0B,eAAkB;AAAA,EAC5C,oBAAoC,CAAA;AAAA,EACrC,aAA2B,CAAA;AAAA,EAEnC,IAAI,SAAS;AACT,WAAO,KAAK,kBAAkB;AAAA,EAClC;AAAA,EAEA,YACI,oBAAoC,IACtC;AACE,UAAA;AACA,SAAK,cAAc,IAAI;AACvB,SAAK,QAAQ,IAAI;AACjB,WAAO,OAAO,KAAK,mBAAmB,UAAU,iBAAiB;AAAA,EACrE;AAAA;AAAA;AAAA;AAAA,EAKO,IAAI,YAAwB;AAC/B,SAAK,WAAW,KAAK,UAAU;AAC/B,WAAO;AAAA,EACX;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQO,OAAO,MAAe;AACzB,UAAM,YAAY,QAAQ,KAAK,kBAAkB,QAAQ;AAEzD,QAAI,YAAY,KAAK,YAAY,OAAO;AACpC,YAAM,IAAI,MAAM,qBAAqB;AAAA,IACzC;AAEA,QAAI,SAAS,KAAK,QAAQ,aAAa,QAAS;AAIhD,UAAM,SAAS,IAAI,MAAM;AAAA,MACrB,MAAM;AAAA,MACN,UAAU,KAAK,kBAAkB;AAAA,MACjC,aAAa,KAAK,kBAAkB;AAAA,MACpC,OAAO,KAAK,MAAM,KAAK,IAAI;AAAA,IAAA,CAC9B;AAED,YAAQ,IAAI,uCAAuC,OAAO,QAAQ,IAAI,OAAO,IAAI,EAAE;AACnF,WAAO;AAAA,EACX;AAAA,EAEA,CAAQ,SAAS,EAAE,KAAyB;AACxC,WAAO,KAAK,MAAM,GAAyB;AAAA,EAC/C;AAAA;AAAA;AAAA;AAAA,EAKA,MAAsB,eAAe,SAAiD;AAClF,QAAI,MAAM,QAAQ,OAAO,QAAQ,QAAQ;AACzC,QAAI,CAAC,IAAI,WAAW,MAAM,GAAG;AACzB,YAAM,OAAO,UAAU,KAAK,kBAAkB,YAAY,WAAW,IAAI,KAAK,kBAAkB,QAAQ,GAAI;AAC5G,YAAMR,QAAO,IAAI,WAAW,GAAG,IAAI,MAAM,MAAM;AAC/C,YAAM,OAAOA;AAAA,IACjB;AAEA,QAAI,QAAQ,OAAO;AACf,YAAM,IAAI,IAAI,IAAI,GAAG;AACrB,iBAAW,CAAC,GAAG,CAAC,KAAK,OAAO,QAAQ,QAAQ,KAAK,GAAG;AAChD,UAAE,aAAa,IAAI,GAAG,CAAC;AAAA,MAC3B;AACA,YAAM,EAAE,SAAA;AAAA,IACZ;AAGA,UAAM,MAAM,IAAI,gBAAgB;AAAA,MAC5B,QAAS,QAAQ,UAAU;AAAA,MAC3B;AAAA,MACA,SAAS,QAAQ;AAAA,MACjB,MAAM,QAAQ,QAAQ,OAAO,QAAQ,SAAS,WAAW,KAAK,UAAU,QAAQ,IAAI,IAAI,QAAQ;AAAA,IAAA,CACnG;AAED,UAAM,MAAM,MAAM,KAAK,MAAM,GAAyB;AAGtD,UAAM,SAAS,IAAI;AACnB,UAAM,UAAkC,CAAA;AACxC,QAAI,QAAQ,QAAQ,CAAC,GAAG,MAAM,QAAQ,CAAC,IAAI,CAAC;AAE5C,QAAI;AACJ,QAAI,QAAQ,cAAc,GAAG,SAAS,kBAAkB,GAAG;AACvD,aAAO,MAAM,IAAI,KAAA;AAAA,IACrB,OACK;AACD,aAAO,MAAM,IAAI,KAAA;AAAA,IACrB;AAEA,WAAO;AAAA,MACH;AAAA,MACA;AAAA,MACA;AAAA,IAAA;AAAA,EAER;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,MAAa,MAAM,KAAiC;AAChD,UAAMqB,UAASb,IAAAA,MAAM,UAAU,sBAAsB;AACrD,UAAM,QAAQ,aAAa,SAAA;AAE3B,UAAM,QAAQ;AAAA,MACV,YAAY;AAAA,QACR,YAAY,IAAI;AAAA,QAChB,eAAe,IAAI;AAAA,MAAA;AAAA,IACvB;AAGJ,UAAM,SAAS,OAAO,IAAI,MAAM;AAChC,UAAM,MAAM,SAASA,UAAM,QAAQc,IAAAA,QAAQ,OAAA,GAAU,MAAM,IAAI;AAC/D,WAAOD,QAAO,gBAAgB,GAAG,IAAI,MAAM,IAAI,IAAI,IAAI,IAAI,GAAG,EAAE,QAAQ,IAAI,OAAO,KAAK,CAAA,SAAQ;AAC5F,YAAM,6BAAa,IAAA;AACnB,aAAO,IAAI,QAAQ,IAAI;AACvB,aAAO,IAAI,WAAW,GAAG;AAEzB,YAAM,cAAc,MAAM;AAGtB,cAAM,UAAU;AAEhB,cAAM,SAAS,YAAY;AACvB,gBAAME,OAAM,IAAI,gBAAmB,OAAO;AAG1C,gBAAM,KAAK,QAAQ,KAAK,UAAU;AAGlC,cAAI;AAEA,kBAAM,SAAS,MAAM,GAAGA,MAAK,YAAY;AACrC,oBAAM,QAAQ,KAAK,KAAK,IAAI,QAAQA,KAAI,IAAI;AAC5C,kBAAI,OAAO;AACPA,qBAAI,SAAS,MAAM;AACnB,uBAAO,MAAM,QAAQA,IAAG;AAAA,cAC5B;AACA,qBAAO;AAAA,YACX,CAAC;AAED,gBAAI,kBAAkB,UAAU;AAC5B,qBAAO;AAAA,YACX;AACA,gBAAI,WAAW,QAAQ,WAAW,QAAW;AACzC,mBAAK,aAAa,oBAAoB,GAAG;AACzC,qBAAOA,KAAI,KAAK,aAAa,GAAG;AAAA,YACpC;AACA,gBAAI,OAAO,WAAW,UAAU;AAC5B,qBAAOA,KAAI,KAAK,MAAM;AAAA,YAC1B;AAEA,mBAAOA,KAAI,KAAK,OAAO,MAAM,CAAC;AAAA,UAElC,SACO,KAAU;AACb,oBAAQ,MAAM,GAAG;AACjB,iBAAK,gBAAgB,GAAG;AACxB,iBAAK,UAAU,EAAE,MAAM,EAAA,CAAG;AAC1B,kBAAM,SAAS,IAAI,UAAU,IAAI,cAAc;AAC/C,kBAAM,OAAY,EAAE,OAAO,IAAI,WAAW,wBAAA;AAC1C,gBAAI,IAAI,OAAQ,MAAK,SAAS,IAAI;AAClC,mBAAOA,KAAI,KAAK,MAAM,MAAM;AAAA,UAChC;AAAA,QACJ;AAEA,eAAO,SACF,QAAQ,MAAM,KAAK,KAAK;AAAA,MACjC;AAEA,UAAI,KAAK,kBAAkB,yBAAyB;AAChD,eAAO,aAAa,IAAI,QAAQ,WAAW;AAAA,MAC/C,OACK;AACD,eAAO,YAAA;AAAA,MACX;AAAA,IACJ,CAAC;AAAA,EACL;AACJ;ACxJO,MAAM,mBAAmB,eAAoB;AAAA,EAGhD,YAAoB,YAAwB;AACxC,UAAA;AADgB,SAAA,aAAA;AAEhB,SAAK,SAAS,OAAO,WAAW,cAAc,WACxC,IAAI,YAAA,EAAc,OAAO,WAAW,SAAS,IAC7C,WAAW;AAEjB,SAAK,KAAA;AAAA,EACT;AAAA,EATQ;AAAA,EAWA,oBAAoB,MAAc,GAAmB;AACzD,YAAQ,MAAA;AAAA,MACJ,KAAK;AACD,eAAO,IAAIC,OAAAA,OAAO,EAAE,UAAU,EAAE,cAAc,EAAE,WAAW;AAAA,MAC/D,KAAK;AACD,eAAO,IAAIC,OAAAA,OAAO,EAAE,UAAU,EAAE,cAAc,EAAE,WAAW;AAAA,MAC/D,KAAK;AACD,eAAO,IAAIC,OAAAA,iBAAiB,EAAE,UAAW,EAAE,UAAU,EAAE,cAAc,EAAE,WAAW;AAAA,MACtF,KAAK;AAED,eAAO,IAAIC,OAAAA;AAAAA,UACP,EAAE;AAAA,UACF,EAAE;AAAA,UACF,EAAE;AAAA,UACF,EAAE;AAAA,UACF,EAAE;AAAA,QAAA;AAAA,MAEV,KAAK;AACD,eAAO,IAAIC,OAAAA,MAAM,EAAE,QAAS,EAAE,UAAU,EAAE,cAAc,EAAE,WAAW;AAAA,MACzE,KAAK;AACD,eAAO,IAAIC,OAAAA,KAAK,EAAE,QAAS,EAAE,SAAS,EAAE,UAAU,EAAE,cAAc,EAAE,WAAW;AAAA,MACnF,KAAK;AACD,eAAO,IAAIC,OAAAA,aAAa,EAAE,UAAU,EAAE,cAAc,EAAE,WAAW;AAAA,MACrE;AACI,eAAO;AAAA,IAAA;AAAA,EAEnB;AAAA,EAEA,MAAc,cAAc,MAAgB,KAAsB;AAC9D,UAAM,MAAM;AACZ,UAAM,MAAM,MAAM,IAAIC,gBAAK,QAAQ,EAAE,GAAG,KAAA,CAAM,EACzC,mBAAmB,EAAE,KAAK,EAC1B,YAAA,EACA,kBAAkB,KAAK,WAAW,iBAAiB,KAAK,EACxD,KAAK,KAAK,MAAM;AAGrB,UAAM,OAAO,KAAK,WAAW,iBAAiB,CAAA;AAC9C,QAAI,SAAS,cAAc,GAAG,UAAU,KAAK,QAAQ,GAAG;AACxD,QAAI,KAAK,OAAQ,WAAU;AAC3B,QAAI,KAAK,SAAU,WAAU,cAAc,KAAK,QAAQ;AACxD,QAAI,KAAK,OAAQ,WAAU,aAAa,KAAK,MAAM;AAEnD,QAAI,IAAI,cAAc,MAAM;AAE5B,WAAO;AAAA,EACX;AAAA,EAEQ,OAAO;AACX,eAAW,CAAC,cAAc,cAAc,KAAK,OAAO,QAAQ,KAAK,WAAW,SAAS,GAAG;AACpF,UAAI,CAAC,eAAgB;AAErB,YAAMC,YAAW,KAAK,oBAAoB,cAAc,cAAc;AACtE,UAAI,CAACA,WAAU;AAIX;AAAA,MACJ;AAGA,WAAK,IAAI,SAAS,YAAY,UAAU,OAAO,QAAQ;AACnD,cAAM,QAAQC,OAAAA,cAAA;AACd,cAAM,eAAgB,iBAAiB,YAAY,iBAAiB,eAAe,iBAAiB,WAAW,iBAAiB,SAC1HC,OAAAA,qBAAA,IAAyB;AAG/B,cAAM,SAAS,eAAe,UAAU,CAAA;AACxC,YAAI;AAEJ,YAAIF,qBAAoBR,OAAAA,QAAQ;AAC5B,gBAAM,MAAMQ,UAAS,uBAAuB,OAAO,MAAM;AAAA,QAC7D,WAAWA,qBAAoBP,OAAAA,UAAUO,qBAAoBN,OAAAA,oBAAoBM,qBAAoBJ,OAAAA,SAASI,qBAAoBH,aAAM;AAGpI,gBAAM,MAAOG,UAAiB,uBAAuB,OAAO,cAAe,MAAM;AAAA,QACrF,WAAWA,qBAAoBL,cAAO;AAClC,gBAAM,MAAMK,UAAS,uBAAuB,OAAO,MAAM;AAAA,QAC7D,WAAWA,qBAAoBF,qBAAc;AACzC,cAAI,CAAC,eAAe,gBAAgB,IAAI,KAAK,6CAA6C,GAAG;AAC7F,gBAAM,MAAME,UAAS,uBAAuB,eAAe,SAAS,OAAO,MAAM;AAAA,QACrF,OAAO;AACH,iBAAO,IAAI,KAAK,yBAAyB,GAAG;AAAA,QAChD;AAEA,YAAI,IAAI,QAAQ,IAAI,cAAc,eAAe,KAAK,iCAAiC;AACvF,YAAI,cAAc;AACd,cAAI,IAAI,QAAQ,OAAO,cAAc,kBAAkB,YAAY,iCAAiC;AAAA,QACxG;AAEA,eAAO,IAAI,SAAS,IAAI,SAAA,CAAU;AAAA,MACtC,CAAC;AAGD,WAAK,IAAI,SAAS,YAAY,aAAa,OAAO,QAAQ;AACtD,cAAM,MAAM,IAAI,IAAI,IAAI,IAAI,GAAG;AAC/B,cAAM,OAAO,IAAI,aAAa,IAAI,MAAM;AACxC,cAAM,QAAQ,IAAI,aAAa,IAAI,OAAO;AAE1C,cAAM,eAAe,IAAI,IAAI,QAAQ,IAAI,QAAQ;AACjD,cAAM,cAAc,cAAc,MAAM,qBAAqB,IAAI,CAAC;AAClE,cAAM,iBAAiB,cAAc,MAAM,wBAAwB,IAAI,CAAC;AAExE,YAAI,CAAC,QAAQ,CAAC,SAAS,CAAC,eAAe,UAAU,aAAa;AAC1D,iBAAO,IAAI,KAAK,yBAAyB,GAAG;AAAA,QAChD;AAEA,YAAI;AACA,cAAI;AACJ,cAAI;AAEJ,cAAIA,qBAAoBR,OAAAA,QAAQ;AAC5B,qBAAS,MAAMQ,UAAS,0BAA0B,IAAI;AAAA,UAC1D,WAAWA,qBAAoBP,iBAAUO,qBAAoBN,OAAAA,kBAAkB;AAC3E,gBAAI,CAAC,eAAgB,QAAO,IAAI,KAAK,oBAAoB,GAAG;AAC5D,qBAAS,MAAMM,UAAS,0BAA0B,MAAM,cAAc;AAAA,UAC1E,WAAWA,qBAAoBJ,gBAASI,qBAAoBH,OAAAA,MAAM;AAC9D,qBAAS,MAAOG,UAAiB,0BAA0B,MAAM,kBAAkB,EAAE;AAAA,UACzF,WAAWA,qBAAoBL,cAAO;AAClC,qBAAS,MAAMK,UAAS,0BAA0B,IAAI;AACtD,sBAAU,OAAO;AAAA,UACrB,WAAWA,qBAAoBF,qBAAc;AACzC,gBAAI,CAAC,eAAe,iBAAiB,IAAI,KAAK,8CAA8C,GAAG;AAC/F,qBAAS,MAAME,UAAS,0BAA0B,eAAe,UAAU,MAAM,IAAI;AAAA,UACzF;AAEA,gBAAM,cAAc,OAAO,eAAe,OAAO;AACjD,gBAAM,OAAO,MAAM,KAAK,UAAU,cAAc,aAAa,gBAAgB,OAAO;AAEpF,cAAI,KAAK,WAAW,WAAW;AAC3B,kBAAM,MAAM,MAAM,KAAK,WAAW,UAAU,MAAM,GAAG;AACrD,gBAAI,IAAK,QAAO;AAAA,UACpB;AAGA,gBAAM,MAAM,MAAM,KAAK,cAAc,MAAM,GAAG;AAC9C,iBAAO,IAAI,KAAK,EAAE,OAAO,KAAK,MAAM;AAAA,QAExC,SAAS,GAAQ;AACb,kBAAQ,MAAM,cAAc,CAAC;AAC7B,iBAAO,IAAI,KAAK,4BAA4B,EAAE,UAAU,OAAO,EAAE,OAAO,GAAG;AAAA,QAC/E;AAAA,MACJ,CAAC;AAAA,IACL;AAAA,EACJ;AAAA,EAEA,MAAc,UAAUA,WAAkB,OAAe,QAAwB,SAAqC;AAClH,QAAI,OAAiB,EAAE,IAAI,WAAW,UAAAA,UAAA;AAEtC,QAAIA,cAAa,UAAU;AACvB,YAAM,MAAM,MAAM,MAAM,+BAA+B;AAAA,QACnD,SAAS,EAAE,eAAe,UAAU,KAAK,GAAA;AAAA,MAAG,CAC/C;AACD,YAAM,OAAO,MAAM,IAAI,KAAA;AACvB,aAAO;AAAA,QACH,IAAI,OAAO,KAAK,EAAE;AAAA,QAClB,MAAM,KAAK,QAAQ,KAAK;AAAA,QACxB,OAAO,KAAK;AAAA,QACZ,SAAS,KAAK;AAAA,QACd,UAAAA;AAAA,QACA,KAAK;AAAA,MAAA;AAAA,IAEb,WACSA,cAAa,UAAU;AAC5B,YAAM,MAAM,MAAM,MAAM,oDAAoD;AAAA,QACxE,SAAS,EAAE,eAAe,UAAU,KAAK,GAAA;AAAA,MAAG,CAC/C;AACD,YAAM,OAAO,MAAM,IAAI,KAAA;AACvB,aAAO;AAAA,QACH,IAAI,KAAK;AAAA,QACT,MAAM,KAAK;AAAA,QACX,OAAO,KAAK;AAAA,QACZ,SAAS,KAAK;AAAA,QACd,UAAAA;AAAA,QACA,KAAK;AAAA,MAAA;AAAA,IAEb,WACSA,cAAa,aAAa;AAC/B,YAAM,MAAM,MAAM,MAAM,uCAAuC;AAAA,QAC3D,SAAS,EAAE,eAAe,UAAU,KAAK,GAAA;AAAA,MAAG,CAC/C;AACD,YAAM,OAAO,MAAM,IAAI,KAAA;AACvB,aAAO;AAAA,QACH,IAAI,KAAK;AAAA,QACT,MAAM,KAAK;AAAA,QACX,OAAO,KAAK,QAAQ,KAAK;AAAA,QACzB,UAAAA;AAAA,QACA,KAAK;AAAA,MAAA;AAAA,IAEb,WACSA,cAAa,WAAWA,cAAa,QAAQ;AAClD,YAAM,SAAS,OAAO,OAAQ,WAAW,MAAM,IAAI,OAAO,SAAU,WAAW,OAAO,MAAM;AAC5F,YAAM,WAAWA,cAAa,UAAU,GAAG,MAAM,cAAc,GAAG,MAAM;AAExE,YAAM,MAAM,MAAM,MAAM,UAAU;AAAA,QAC9B,SAAS,EAAE,eAAe,UAAU,KAAK,GAAA;AAAA,MAAG,CAC/C;AACD,YAAM,OAAO,MAAM,IAAI,KAAA;AACvB,aAAO;AAAA,QACH,IAAI,KAAK;AAAA,QACT,MAAM,KAAK;AAAA,QACX,OAAO,KAAK;AAAA,QACZ,SAAS,KAAK;AAAA,QACd,UAAAA;AAAA,QACA,KAAK;AAAA,MAAA;AAAA,IAEb,WACSA,cAAa,SAAS;AAE3B,UAAI,SAAS;AACT,cAAM,UAAUD,gBAAK,UAAU,OAAO;AACtC,eAAO;AAAA,UACH,IAAI,QAAQ;AAAA,UACZ,OAAO,QAAQ,OAAO;AAAA,UACtB,UAAAC;AAAA,UACA,KAAK;AAAA,QAAA;AAAA,MAEb;AAAA,IACJ,WACSA,cAAa,UAAU;AAC5B,UAAI,OAAO,aAAa;AACpB,cAAM,MAAM,MAAM,MAAM,OAAO,aAAa;AAAA,UACxC,SAAS,EAAE,eAAe,UAAU,KAAK,GAAA;AAAA,QAAG,CAC/C;AACD,cAAM,OAAO,MAAM,IAAI,KAAA;AACvB,eAAO;AAAA,UACH,IAAI,KAAK,MAAM,KAAK,OAAO;AAAA,UAC3B,MAAM,KAAK;AAAA,UACX,OAAO,KAAK;AAAA,UACZ,SAAS,KAAK;AAAA,UACd,UAAAA;AAAA,UACA,KAAK;AAAA,QAAA;AAAA,MAEb;AAAA,IACJ;AAEA,WAAO;AAAA,EACX;AAAA;AAAA;AAAA;AAAA,EAKO,aAAa;AAChB,WAAO,OAAO,KAAsB,SAA6B;AAC7D,YAAM,aAAa,IAAI,IAAI,QAAQ,IAAI,eAAe;AACtD,UAAI,QAAQ,YAAY,WAAW,SAAS,IAAI,WAAW,UAAU,CAAC,IAAI;AAE1E,UAAI,CAAC,OAAO;AAER,cAAM,eAAe,IAAI,IAAI,QAAQ,IAAI,QAAQ;AACjD,gBAAQ,cAAc,MAAM,oBAAoB,IAAI,CAAC,KAAK;AAAA,MAC9D;AAEA,UAAI,OAAO;AACP,YAAI;AACA,gBAAM,EAAE,YAAY,MAAMD,gBAAK,UAAU,OAAO,KAAK,MAAM;AAC1D,cAAY,OAAO;AAAA,QACxB,QAAQ;AAAA,QAGR;AAAA,MACJ;AACA,aAAO,KAAA;AAAA,IACX;AAAA,EACJ;AACJ;ACzUO,SAAS,YAAY,UAA8B,IAAgB;AACtE,QAAM,YAAY,QAAQ,aAAa;AAEvC,SAAO,OAAO,KAAsB,SAAiB;AACjD,UAAM,iBAAiB,IAAI,QAAQ,IAAI,iBAAiB,KAAK;AAG7D,QAAI,SAA2C;AAC/C,QAAI,eAAe,SAAS,IAAI,EAAG,UAAS;AAAA,aACnC,eAAe,SAAS,MAAM,EAAG,UAAS;AAAA,aAC1C,eAAe,SAAS,SAAS,EAAG,UAAS;AAEtD,QAAI,CAAC,OAAQ,QAAO,KAAA;AAEpB,UAAM,WAAW,MAAM,KAAA;AAEvB,QAAI,oBAAoB,UAAU;AAE9B,UAAI,SAAS,QAAQ,IAAI,kBAAkB,EAAG,QAAO;AAWrD,YAAM,OAAO,MAAM,SAAS,YAAA;AAE5B,UAAI,KAAK,aAAa,WAAW;AAE7B,eAAO,IAAI,SAAS,MAAM;AAAA,UACtB,QAAQ,SAAS;AAAA,UACjB,YAAY,SAAS;AAAA,UACrB,SAAS,SAAS;AAAA,QAAA,CACrB;AAAA,MACL;AAEA,UAAI;AACJ,UAAI,WAAW,MAAM;AAEjB,qBAAa,QAAQ,WAAW,EAAE,mBAAmB,IAAI;AAAA,MAC7D,WAAW,WAAW,QAAQ;AAC1B,qBAAa,IAAI,SAAS,IAAI;AAAA,MAClC,OAAO;AACH,qBAAa,IAAI,YAAY,IAAI;AAAA,MACrC;AAEA,YAAM,UAAU,IAAI,QAAQ,SAAS,OAAO;AAC5C,cAAQ,IAAI,oBAAoB,MAAM;AACtC,cAAQ,IAAI,kBAAkB,OAAO,WAAW,MAAM,CAAC;AACvD,cAAQ,OAAO,gBAAgB;AAE/B,aAAO,IAAI,SAAS,YAAY;AAAA,QAC5B,QAAQ,SAAS;AAAA,QACjB,YAAY,SAAS;AAAA,QACrB;AAAA,MAAA,CACH;AAAA,IACL;AAEA,WAAO;AAAA,EACX;AACJ;AC3DO,SAAS,KAAK,UAAuB,IAAgB;AACxD,QAAMI,YAAwB;AAAA,IAC1B,QAAQ;AAAA,IACR,SAAS;AAAA,IACT,mBAAmB;AAAA,IACnB,sBAAsB;AAAA,EAAA;AAG1B,QAAM,OAAO,EAAE,GAAGA,WAAU,GAAG,QAAA;AAE/B,SAAO,OAAO,KAAsB,SAAiB;AACjD,UAAM,UAAU,IAAI,QAAA;AACpB,UAAM,SAAS,IAAI,QAAQ,IAAI,QAAQ;AAEvC,UAAM,MAAM,CAAC,GAAW,MAAc,QAAQ,IAAI,GAAG,CAAC;AACtD,UAAM,SAAS,CAAC,GAAW,MAAc,QAAQ,OAAO,GAAG,CAAC;AAG5D,QAAI,KAAK,WAAW,KAAK;AACrB,UAAI,+BAA+B,GAAG;AAAA,IAC1C,WAAW,OAAO,KAAK,WAAW,UAAU;AACxC,UAAI,+BAA+B,KAAK,MAAM;AAAA,IAClD,WAAW,MAAM,QAAQ,KAAK,MAAM,GAAG;AACnC,UAAI,UAAU,KAAK,OAAO,SAAS,MAAM,GAAG;AACxC,YAAI,+BAA+B,MAAM;AACzC,eAAO,QAAQ,QAAQ;AAAA,MAC3B;AAAA,IACJ,WAAW,OAAO,KAAK,WAAW,YAAY;AAC1C,YAAM,UAAU,KAAK,OAAO,GAAG;AAC/B,UAAI,YAAY,QAAQ,QAAQ;AAC5B,YAAI,+BAA+B,MAAM;AACzC,eAAO,QAAQ,QAAQ;AAAA,MAC3B,WAAW,OAAO,YAAY,UAAU;AACpC,YAAI,+BAA+B,OAAO;AAC1C,eAAO,QAAQ,QAAQ;AAAA,MAC3B;AAAA,IACJ;AAGA,QAAI,KAAK,aAAa;AAClB,UAAI,oCAAoC,MAAM;AAAA,IAClD;AAGA,QAAI,KAAK,gBAAgB;AACrB,YAAM,UAAU,MAAM,QAAQ,KAAK,cAAc,IAAI,KAAK,eAAe,KAAK,GAAG,IAAI,KAAK;AAC1F,UAAI,QAAS,KAAI,iCAAiC,OAAO;AAAA,IAC7D;AAGA,QAAI,IAAI,WAAW,WAAW;AAE1B,UAAI,KAAK,SAAS;AACd,cAAM,UAAU,MAAM,QAAQ,KAAK,OAAO,IAAI,KAAK,QAAQ,KAAK,GAAG,IAAI,KAAK;AAC5E,YAAI,gCAAgC,OAAO;AAAA,MAC/C;AAGA,UAAI,KAAK,gBAAgB;AACrB,cAAM,IAAI,MAAM,QAAQ,KAAK,cAAc,IAAI,KAAK,eAAe,KAAK,GAAG,IAAI,KAAK;AACpF,YAAI,gCAAgC,CAAC;AAAA,MACzC,OAAO;AAEH,cAAM,aAAa,IAAI,QAAQ,IAAI,gCAAgC;AACnE,YAAI,YAAY;AACZ,cAAI,gCAAgC,UAAU;AAC9C,iBAAO,QAAQ,gCAAgC;AAAA,QACnD;AAAA,MACJ;AAGA,UAAI,KAAK,QAAQ;AACb,YAAI,0BAA0B,OAAO,KAAK,MAAM,CAAC;AAAA,MACrD;AAEA,aAAO,IAAI,SAAS,MAAM;AAAA,QACtB,QAAS,KAAa,wBAAwB;AAAA,QAC9C;AAAA,MAAA,CACH;AAAA,IACL;AAEA,UAAM,WAAW,MAAM,KAAA;AAEvB,QAAI,oBAAoB,UAAU;AAC9B,iBAAW,CAAC,KAAK,KAAK,KAAK,QAAQ,WAAW;AAC1C,iBAAS,QAAQ,IAAI,KAAK,KAAK;AAAA,MACnC;AAAA,IACJ;AAEA,WAAO;AAAA,EACX;AACJ;ACrFO,SAAS,UAAU,UAA4B,IAAgB;AAClE,QAAM,WAAW,QAAQ,YAAY,KAAK;AAC1C,QAAM,MAAM,QAAQ,OAAO;AAC3B,QAAM,UAAU,QAAQ,WAAW;AACnC,QAAM,aAAa,QAAQ,cAAc;AACzC,QAAM,UAAU,QAAQ,YAAY;AACpC,QAAM,eAAe,QAAQ,iBAAiB,CAAC,QAAQ;AAGnD,WAAO,IAAI,QAAQ,IAAI,iBAAiB,KAAK,IAAI,IAAI,YAAY;AAAA,EACrE;AACA,QAAM,OAAO,QAAQ,SAAS,MAAM;AAIpC,QAAM,2BAAW,IAAA;AAGjB,QAAM,WAAW,YAAY,MAAM;AAC/B,UAAM,MAAM,KAAK,IAAA;AACjB,eAAW,CAAC,KAAK,MAAM,KAAK,KAAK,WAAW;AACxC,UAAI,OAAO,aAAa,KAAK;AACzB,aAAK,OAAO,GAAG;AAAA,MACnB;AAAA,IACJ;AAAA,EACJ,GAAG,QAAQ;AAEX,MAAI,SAAS,MAAO,UAAS,MAAA;AAE7B,SAAO,OAAO,KAAsB,SAAiB;AACjD,QAAI,KAAK,GAAG,EAAG,QAAO,KAAA;AAEtB,UAAM,MAAM,aAAa,GAAG;AAC5B,UAAM,MAAM,KAAK,IAAA;AACjB,QAAI,SAAS,KAAK,IAAI,GAAG;AAEzB,QAAI,CAAC,UAAU,OAAO,aAAa,KAAK;AACpC,eAAS;AAAA,QACL,MAAM;AAAA,QACN,WAAW,MAAM;AAAA,MAAA;AAErB,WAAK,IAAI,KAAK,MAAM;AAAA,IACxB;AAEA,WAAO;AAEP,UAAM,YAAY,KAAK,IAAI,GAAG,MAAM,OAAO,IAAI;AAC/C,UAAM,YAAY,KAAK,KAAK,OAAO,YAAY,GAAI;AASnD,QAAI,OAAO,OAAO,KAAK;AACnB,UAAI,SAAS;AAET,cAAM,MAAM,OAAO,YAAY,WAAW,IAAI,KAAK,SAAS,UAAU,IAAI,IAAI,KAAK,OAAO,OAAO,GAAG,UAAU;AAC9G,YAAI,QAAQ,IAAI,qBAAqB,OAAO,GAAG,CAAC;AAChD,YAAI,QAAQ,IAAI,yBAAyB,GAAG;AAC5C,YAAI,QAAQ,IAAI,qBAAqB,OAAO,SAAS,CAAC;AACtD,eAAO;AAAA,MACX;AACA,aAAO,OAAO,YAAY,WAAW,IAAI,KAAK,SAAS,UAAU,IAAI,IAAI,KAAK,OAAO,OAAO,GAAG,UAAU;AAAA,IAC7G;AAEA,UAAM,WAAW,MAAM,KAAA;AAEvB,QAAI,oBAAoB,YAAY,SAAS;AACzC,eAAS,QAAQ,IAAI,qBAAqB,OAAO,GAAG,CAAC;AACrD,eAAS,QAAQ,IAAI,yBAAyB,OAAO,SAAS,CAAC;AAC/D,eAAS,QAAQ,IAAI,qBAAqB,OAAO,SAAS,CAAC;AAAA,IAC/D;AAEA,WAAO;AAAA,EACX;AACJ;AC1FA,MAAM,MAAM,IAAIrB,MAAAA,IAAA;AAOT,MAAM,qBAAqB,eAAoB;AAAA,EAClD,YACqB,eACnB;AACE,UAAA;AAFiB,SAAA,gBAAA;AAGjB,SAAK,KAAA;AAAA,EACT;AAAA,EAEA,OAAO;AACH,SAAK,IAAI,KAAK,CAAA,QAAO;AACjB,UAAId,QAAO,IAAI,IAAI,SAAA;AACnB,UAAI,CAACA,MAAK,SAAS,GAAG,EAAG,CAAAA,SAAQ;AAEjC,aAAO,IAAI,KAAK,IAAI,aAAa;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,0BAoBnB,EAAE,MAAAA,OAAM,QAAQ,KAAK,cAAA,CAAe,CAAC;AAAA,IACvD,CAAC;AACD,SAAK,IAAI,cAAc,CAAC,QAAQ;AAC5B,aAAO,IAAI,KAAK,YAAY,sEAAsE;AAAA,IACtG,CAAC;AACD,SAAK,IAAI,iBAAiB,CAAC,QAAQ;AAC/B,cAAQ,KAAK,QAAQ,MAAM,gBAAA;AAAA,IAC/B,CAAC;AAAA,EACL;AACJ;AClCO,SAAS,gBAAgB,UAAkC,IAAgB;AAC9E,SAAO,OAAO,KAAsB,SAAiB;AACjD,UAAM,UAAkC,CAAA;AAGxC,UAAM,MAAM,CAAC,GAAW,MAAc,QAAQ,CAAC,IAAI;AAGnD,QAAI,QAAQ,uBAAuB,OAAO;AACtC,YAAM,QAAS,QAAQ,oBAA4B;AACnD,UAAI,0BAA0B,QAAQ,OAAO,KAAK;AAAA,IACtD;AAGA,QAAI,QAAQ,eAAe,OAAO;AAC9B,YAAM,MAAM,QAAQ,cAAqB,CAAA;AACzC,YAAM,SAAS,IAAI,UAAU;AAC7B,UAAI,WAAW,aAAc,KAAI,mBAAmB,YAAY;AAAA,eACvD,WAAW,OAAQ,KAAI,mBAAmB,MAAM;AAAA,IAE7D;AAGA,QAAI,QAAQ,SAAS,OAAO;AACxB,YAAM,MAAM,QAAQ,QAAe,CAAA;AACnC,YAAM,SAAS,IAAI,UAAU;AAC7B,UAAI,SAAS,WAAW,MAAM;AAC9B,UAAI,IAAI,sBAAsB,MAAO,WAAU;AAC/C,UAAI,IAAI,QAAS,WAAU;AAC3B,UAAI,6BAA6B,MAAM;AAAA,IAC3C;AAGA,QAAI,QAAQ,aAAa,OAAO;AAC5B,UAAI,sBAAsB,QAAQ;AAAA,IACtC;AAGA,QAAI,QAAQ,YAAY,OAAO;AAC3B,UAAI,0BAA0B,SAAS;AAAA,IAC3C;AAGA,QAAI,QAAQ,cAAc,OAAO;AAC7B,UAAI,oBAAoB,GAAG;AAAA,IAC/B;AAGA,QAAI,QAAQ,mBAAmB,OAAO;AAClC,YAAM,MAAM,QAAQ,kBAAyB,CAAA;AAC7C,YAAM,SAAS,IAAI,UAAU;AAC7B,UAAI,mBAAmB,MAAM,QAAQ,MAAM,IAAI,OAAO,KAAK,GAAG,IAAI,MAAM;AAAA,IAC5E;AAGA,QAAI,QAAQ,0BAA0B,OAAO;AAEzC,YAAM,MAAM,QAAQ;AACpB,UAAI,QAAQ,UAAa,QAAQ,MAAM;AACnC,YAAI,2BAA2B,sOAAsO;AAAA,MACzQ,WAAW,OAAO,QAAQ,UAAU;AAKhC,mBAAW,CAAC,KAAK,GAAG,KAAK,OAAO,QAAQ,GAAG,GAAG;AAAA,QAK9C;AAAA,MACJ;AAAA,IACJ;AAEA,QAAI,QAAQ,kBAAkB,MAAO;AAcrC,UAAM,WAAW,MAAM,KAAA;AAEvB,QAAI,oBAAoB,UAAU;AAC9B,iBAAW,CAAC,GAAG,CAAC,KAAK,OAAO,QAAQ,OAAO,GAAG;AAC1C,iBAAS,QAAQ,IAAI,GAAG,CAAC;AAAA,MAC7B;AACA,aAAO;AAAA,IACX;AAUA,WAAO;AAAA,EACX;AACJ;AC9EA,MAAM,OAAuC;AAAA,EACzC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EAEA,YAAY,UAAgC,IAAI;AAC5C,SAAK,OAAO,QAAQ,QAAQ;AAC5B,SAAK,WAAW,QAAQ,aAAa,SAAY,QAAQ,WAAW;AACpE,SAAK,SAAS,QAAQ;AACtB,SAAK,SAAS,QAAQ;AACtB,SAAK,WAAW,QAAQ;AACxB,SAAK,SAAS,QAAQ;AACtB,SAAK,UAAU,QAAQ;AAEvB,QAAI,KAAK,WAAW,QAAW;AAC3B,WAAK,iBAAiB,KAAK;AAC3B,WAAK,UAAU,IAAI,KAAK,KAAK,IAAA,IAAQ,KAAK,MAAM;AAAA,IACpD;AAAA,EACJ;AAAA,EAEA,UAAU,MAAc,KAAa;AACjC,QAAI,MAAM,GAAG,IAAI,IAAI,mBAAmB,GAAG,CAAC;AAE5C,QAAI,KAAK,QAAQ;AACb,YAAM,UAAU,IAAI,KAAK,KAAK,IAAA,IAAQ,KAAK,MAAM;AACjD,aAAO,aAAa,QAAQ,YAAA,CAAa;AAEzC,aAAO,aAAa,KAAK,MAAM,KAAK,SAAS,GAAI,CAAC;AAAA,IACtD,WAAW,KAAK,SAAS;AACrB,aAAO,aAAa,KAAK,QAAQ,YAAA,CAAa;AAAA,IAClD;AAEA,QAAI,KAAK,OAAQ,QAAO,YAAY,KAAK,MAAM;AAC/C,QAAI,KAAK,KAAM,QAAO,UAAU,KAAK,IAAI;AACzC,QAAI,KAAK,SAAU,QAAO;AAC1B,QAAI,KAAK,OAAQ,QAAO;AACxB,QAAI,KAAK,UAAU;AACf,YAAM,WAAW,OAAO,KAAK,aAAa,WACtC,KAAK,SAAS,OAAO,CAAC,EAAE,gBAAgB,KAAK,SAAS,MAAM,CAAC,IAAI;AACrE,aAAO,cAAc,QAAQ;AAAA,IACjC;AAEA,WAAO;AAAA,EACX;AACJ;AAKO,MAAM,oBAAoBoC,OAAAA,aAA8B;AAAA,EACnD,WAAmC,CAAA;AAAA,EAE3C,IAAI,KAAa,IAAsD;AACnE,UAAM,OAAO,KAAK,SAAS,GAAG;AAC9B,QAAI,CAAC,KAAM,QAAO,GAAG,MAAM,IAAI;AAC/B,QAAI;AACA,YAAM,OAAO,KAAK,MAAM,IAAI;AAE5B,UAAI,KAAK,UAAU,KAAK,OAAO,SAAS;AACpC,aAAK,OAAO,UAAU,IAAI,KAAK,KAAK,OAAO,OAAO;AAAA,MACtD;AACA,SAAG,MAAM,IAAI;AAAA,IACjB,SAAS,GAAG;AACR,SAAG,CAAC;AAAA,IACR;AAAA,EACJ;AAAA,EAEA,IAAI,KAAa,MAAmB,IAA0B;AAC1D,SAAK,SAAS,GAAG,IAAI,KAAK,UAAU,IAAI;AACxC,UAAM,GAAA;AAAA,EACV;AAAA,EAEA,QAAQ,KAAa,IAA0B;AAC3C,WAAO,KAAK,SAAS,GAAG;AACxB,UAAM,GAAA;AAAA,EACV;AAAA,EAEA,MAAM,KAAa,MAAmB,IAA0B;AAC5D,UAAM,UAAU,KAAK,SAAS,GAAG;AACjC,QAAI,SAAS;AAGT,WAAK,SAAS,GAAG,IAAI,KAAK,UAAU,IAAI;AAAA,IAC5C;AACA,UAAM,GAAA;AAAA,EACV;AAAA,EAEA,IAAI,IAAsE;AACtE,UAAM,SAAsC,CAAA;AAC5C,eAAW,OAAO,KAAK,UAAU;AAC7B,UAAI;AACA,eAAO,GAAG,IAAI,KAAK,MAAM,KAAK,SAAS,GAAG,CAAC;AAAA,MAC/C,QAAQ;AAAA,MAAE;AAAA,IACd;AACA,OAAG,MAAM,MAAM;AAAA,EACnB;AAAA,EAEA,MAAM,IAA0B;AAC5B,SAAK,WAAW,CAAA;AAChB,UAAM,GAAA;AAAA,EACV;AACJ;AAIA,SAAS,KAAK,KAAa,QAAgB;AACvC,MAAI,OAAO,QAAQ,SAAU,OAAM,IAAI,UAAU,4CAA4C;AAC7F,MAAI,OAAO,WAAW,SAAU,OAAM,IAAI,UAAU,iCAAiC;AACrF,SAAO,MAAM,MAAMC,OAAAA,WAAW,UAAU,MAAM,EAAE,OAAO,GAAG,EAAE,OAAO,QAAQ,EAAE,QAAQ,QAAQ,EAAE;AACnG;AAEA,SAAS,OAAO,OAAe,QAAgB;AAC3C,MAAI,OAAO,UAAU,SAAU,OAAM,IAAI,UAAU,wCAAwC;AAC3F,MAAI,OAAO,WAAW,SAAU,OAAM,IAAI,UAAU,iCAAiC;AACrF,QAAM,YAAY,MAAM,MAAM,GAAG,MAAM,YAAY,GAAG,CAAC;AACvD,QAAM,gBAAgB,KAAK,WAAW,MAAM;AAC5C,QAAM,iBAAiB,OAAO,KAAK,aAAa;AAChD,QAAM,cAAc,OAAO,KAAK,KAAK;AACrC,MAAI,eAAe,WAAW,YAAY,OAAQ,QAAO;AAGzD,QAAM,QAAQ,QAAQ,QAAQ,EAAE,gBAAgB,gBAAgB,WAAW;AAC3E,SAAO,QAAQ,YAAY;AAC/B;AA0BO,SAAS,QAAQ,SAAqC;AACzD,QAAM,QAAQ,QAAQ,SAAS,IAAI,YAAA;AACnC,QAAM,OAAO,QAAQ,QAAQ;AAC7B,QAAM,UAAU,MAAM,QAAQ,QAAQ,MAAM,IAAI,QAAQ,SAAS,CAAC,QAAQ,MAAM;AAKhF,QAAM,aAAa,QAAQ,UAAU,MAAMC,OAAAA,WAAA;AAE3C,QAAM,SAAS,QAAQ,WAAW,SAAY,OAAO,QAAQ;AAC7D,QAAM,oBAAoB,QAAQ,sBAAsB,SAAY,OAAO,QAAQ;AACnF,QAAM,UAAU,QAAQ,WAAW;AAEnC,SAAO,OAAO,KAAsB,SAAS;AAEzC,QAAI,eAA8B;AAIlC,UAAM,eAAe,IAAI,IAAI,QAAQ,IAAI,QAAQ;AACjD,UAAM,UAAkC,CAAA;AACxC,QAAI,cAAc;AACd,mBAAa,MAAM,GAAG,EAAE,QAAQ,CAAA,MAAK;AACjC,cAAM,CAAC,GAAG,CAAC,IAAI,EAAE,MAAM,GAAG,EAAE,IAAI,CAAA,MAAK,EAAE,KAAA,CAAM;AAC7C,YAAI,KAAK,EAAG,SAAQ,CAAC,IAAI,mBAAmB,CAAC;AAAA,MACjD,CAAC;AAAA,IACL;AAEA,UAAM,YAAY,QAAQ,IAAI;AAE9B,QAAI,WAAW;AACX,UAAI,UAAU,OAAO,GAAG,CAAC,MAAM,MAAM;AAEjC,cAAM,MAAM,OAAO,UAAU,MAAM,CAAC,GAAG,QAAQ,CAAC,CAAC;AACjD,YAAI,KAAK;AACL,yBAAe;AAAA,QAEnB;AAAA,MACJ,OAAO;AACH,uBAAe;AAAA,MACnB;AAAA,IACJ;AAGA,QAAI,YAAY;AAChB,QAAI,QAAQ;AACZ,QAAI,CAAC,WAAW;AACZ,kBAAY,WAAW,GAAG;AAC1B,cAAQ;AAAA,IACZ;AAGA,UAAM,sBAAsB,CAAC,SAAwD;AACjF,YAAM,WAAW,QAAQ,EAAE,QAAQ,IAAI,OAAO,QAAQ,MAAM,EAAA;AAC5D,UAAI,CAAC,SAAS,OAAQ,UAAS,SAAS,IAAI,OAAO,QAAQ,MAAM;AAAA,WAC5D;AAED,cAAM,IAAI,IAAI,OAAO,QAAQ,MAAM;AACnC,eAAO,OAAO,GAAG,SAAS,MAAM;AAEhC,YAAI,EAAE,WAAW,OAAO,EAAE,YAAY,SAAU,GAAE,UAAU,IAAI,KAAK,EAAE,OAAO;AAC9E,iBAAS,SAAS;AAAA,MACtB;AAEA,YAAM,UAAU;AAGhB,aAAO,eAAe,SAAS,MAAM,EAAE,OAAO,WAAW,cAAc,MAAM;AAE7E,cAAQ,OAAO,CAAC,OAAY;AACxB,cAAM,IAAI,QAAQ,IAAI,SAAS,EAAE;AAAA,MACrC;AAEA,cAAQ,UAAU,CAAC,OAAY;AAC3B,cAAM,QAAQ,QAAQ,IAAI,CAAC,QAAQ;AAE/B,cAAI,OAAO,GAAG;AAAA,QAClB,CAAC;AAAA,MACL;AAEA,cAAQ,aAAa,CAAC,OAAY;AAC9B,cAAM,QAAQ,QAAQ,IAAI,CAAC,QAAQ;AAC/B,sBAAY,WAAW,GAAG;AAK1B,qBAAW,OAAO,SAAS;AACvB,gBAAI,QAAQ,YAAY,QAAQ,QAAQ,OAAO,QAAQ,GAAG,MAAM,YAAY;AACxE,qBAAO,QAAQ,GAAG;AAAA,YACtB;AAAA,UACJ;AACA,iBAAO,eAAe,SAAS,MAAM,EAAE,OAAO,WAAW,cAAc,MAAM;AAC7E,cAAI,OAAO,GAAG;AAAA,QAClB,CAAC;AAAA,MACL;AAEA,cAAQ,YAAY,MAAM;AAAA,MAAE;AAC5B,cAAQ,SAAS,CAAC,OAAY;AAC1B,cAAM,IAAI,QAAQ,IAAI,CAAC,KAAKC,UAAS;AACjC,cAAI,IAAK,QAAO,GAAG,GAAG;AACtB,cAAI,CAACA,MAAM,QAAO,GAAG,IAAI,MAAM,mBAAmB,CAAC;AAEnD,qBAAW,OAAO,SAAS;AACvB,gBAAI,QAAQ,YAAY,QAAQ,QAAQ,OAAO,QAAQ,GAAG,MAAM,YAAY;AACxE,qBAAO,QAAQ,GAAG;AAAA,YACtB;AAAA,UACJ;AACA,iBAAO,OAAO,SAASA,KAAI;AAC3B,aAAG,IAAI;AAAA,QACX,CAAC;AAAA,MACL;AAEA,cAAQ,QAAQ,MAAM;AAElB,gBAAQ,OAAO,UAAU,IAAI,KAAK,KAAK,SAAS,QAAQ,OAAO,UAAU,EAAE;AAC3E,YAAI,MAAM,MAAO,OAAM,MAAM,QAAQ,IAAI,OAAO;AAAA,MACpD;AAEA,aAAO;AAAA,IACX;AAGA,QAAI,cAAkC;AAEtC,QAAI,CAAC,SAAS,WAAW;AACrB,YAAM,IAAI,QAAc,CAAC,YAAY;AACjC,cAAM,IAAI,WAAY,CAAC,KAAKA,UAAS;AACjC,cAAI,KAAK;AAGL,wBAAY,WAAW,GAAG;AAC1B,oBAAQ;AAAA,UACZ,WAAW,CAACA,OAAM;AAEd,wBAAY,WAAW,GAAG;AAC1B,oBAAQ;AAAA,UACZ,OAAO;AACH,0BAAcA;AAAAA,UAClB;AACA,kBAAA;AAAA,QACJ,CAAC;AAAA,MACL,CAAC;AAAA,IACL;AAEA,UAAM,OAAO,oBAAoB,WAAW;AAE5C,QAAI,UAAU;AACd,QAAI,YAAY;AAChB,QAAI,eAAe;AAGnB,UAAM,eAAe,KAAK,UAAU,IAAI;AAGxC,UAAM,SAAS,MAAM,KAAA;AAGrB,UAAM,cAAc,KAAK,UAAU,IAAI;AACvC,UAAM,aAAa,iBAAiB;AAEpC,QAAI,CAAC,UAAW,QAAO;AAEvB,QAAI,aAAa;AAEjB,QAAI,YAAY;AACZ,mBAAa;AAAA,IACjB,WAAW,SAAS,mBAAmB;AACnC,mBAAa;AAAA,IACjB,WAAW,CAAC,SAAS,QAAQ;AACzB,mBAAa;AAAA,IACjB;AAEA,QAAI,YAAY;AACZ,YAAM,IAAI,QAAc,CAAC,SAAS,WAAW;AACzC,cAAM,IAAI,WAAY,MAAM,CAAC,QAAQ;AACjC,cAAI,IAAK,SAAQ,MAAM,0BAA0B,GAAG;AACpD,kBAAA;AAAA,QACJ,CAAC;AAAA,MACL,CAAC;AAAA,IACL;AAQA,QAAI,WAAW,KAAK,OAAO,QAAQ;AAC/B,WAAK,OAAO,UAAU,IAAI,KAAK,KAAK,QAAQ,KAAK,OAAO,MAAM;AAAA,IAClE;AAEA,UAAM,kBAAkB,cAAe,CAAC,SAAS;AAEjD,QAAI,iBAAiB;AAEjB,UAAI,MAAM;AAGV,UAAI,QAAQ,SAAS,GAAG;AACpB,cAAM,OAAO,KAAK,KAAK,QAAQ,CAAC,CAAC;AAAA,MACrC;AAEA,YAAMC,WAAU,KAAK;AAErB,YAAM,MAAMA,SAAQ,UAAU,MAAM,GAAG;AACvC,UAAI,IAAI,cAAc,GAAG;AAAA,IAC7B;AAEA,WAAO;AAAA,EACX;AACJ;ACvZO,MAAM,wBAAwB,MAAM;AAAA,EAEvC,YAAmB,QAAe;AAC9B,UAAM,kBAAkB;AADT,SAAA,SAAA;AAAA,EAEnB;AAAA,EAHO,SAAS;AAIpB;AAIA,SAAS,MAAM,QAAsB;AACjC,SAAO,OAAO,QAAQ,cAAc;AACxC;AAEA,eAAe,YAAY,QAAa,MAAW;AAC/C,QAAM,SAAS,MAAM,OAAO,eAAe,IAAI;AAC/C,MAAI,CAAC,OAAO,SAAS;AACjB,UAAM,IAAI,gBAAgB,OAAO,MAAM,MAAM;AAAA,EACjD;AACA,SAAO,OAAO;AAClB;AAEA,SAAS,UAAU,QAAsB;AACrC,SAAO,OAAO,QAAQ,UAAU,cAAc,OAAO,QAAQ,WAAW;AAC5E;AAEA,SAAS,gBAAgB,QAAa,MAAW;AAC7C,MAAI,CAAC,OAAO,MAAM,IAAI,GAAG;AACrB,UAAM,IAAI,gBAAgB,CAAC,GAAG,OAAO,OAAO,IAAI,CAAC,CAAC;AAAA,EACtD;AACA,SAAO;AACX;AAEA,SAAS,MAAM,QAAsB;AACjC,SAAO,OAAO,WAAW,cAAc,YAAY;AACvD;AAEA,SAAS,YAAY,QAAa,MAAW;AACzC,QAAM,QAAQ,OAAO,IAAI;AACzB,MAAI,CAAC,OAAO;AACR,UAAM,IAAI,gBAAgB,OAAO,MAAM;AAAA,EAC3C;AACA,SAAO;AACX;AAEO,MAAM,UAAU,CAAC,QAAa,WAAqB;AACtD,SAAO;AAAA,IACH,UAAU;AAAA,IACV;AAAA,IACA;AAAA,EAAA;AAER;AAEA,SAAS,iBAAiB,QAAsB;AAC5C,SAAO,QAAQ,aAAa;AAChC;AAEA,eAAe,uBAAuB,SAAc,MAAW;AAC3D,QAAM,SAAS,MAAM,QAAQ,OAAO,QAAQ,QAAQ,IAAI;AACxD,MAAI,CAAC,OAAO,SAAS;AACjB,UAAM,IAAI,gBAAgB,OAAO,MAAM;AAAA,EAC3C;AACA,SAAO,OAAO;AAClB;AAKA,MAAM,gBAAgB,OAAO,QAAyB;AAClD,QAAM,MAAM,IAAI;AAGhB,MAAI,IAAI,aAAa;AACjB,WAAO,IAAI;AAAA,EACf;AAEA,MAAI;AACA,QAAI;AAGJ,QAAI,OAAO,IAAI,SAAS,YAAY;AAChC,aAAO,MAAM,IAAI,KAAA;AAAA,IACrB,OACK;AAED,aAAO,IAAI;AACX,UAAI,OAAO,SAAS,UAAU;AAC1B,YAAI;AAAE,iBAAO,KAAK,MAAM,IAAI;AAAA,QAAG,QAAQ;AAAA,QAAE;AAAA,MAC7C;AAAA,IACJ;AAGA,QAAI,cAAc;AAClB,QAAI,aAAa;AAKjB,WAAO,eAAe,KAAK,QAAQ;AAAA,MAC/B,OAAO,YAAY,IAAI;AAAA,MACvB,cAAc;AAAA,IAAA,CACjB;AAED,WAAO;AAAA,EACX,SAAS,GAAG;AACR,WAAO,CAAA;AAAA,EACX;AACJ;AAKO,SAAS,SAAS,QAAsC;AAC3D,SAAO,OAAO,KAAsB,SAAS;AAEzC,QAAI,OAAO,QAAQ;AACf,UAAI,SAAS,MAAM,cAAc,OAAO,QAAQ,IAAI,MAAM;AAAA,IAC9D;AAGA,QAAI,OAAO,OAAO;AACd,YAAM,MAAM,IAAI,IAAI,IAAI,IAAI,GAAG;AAC/B,YAAM,WAAW,OAAO,YAAY,IAAI,aAAa,SAAS;AAC3C,YAAM,cAAc,OAAO,OAAO,QAAQ;AAAA,IAOjE;AAGA,QAAI,OAAO,SAAS;AAChB,YAAM,aAAa,OAAO,YAAY,IAAI,IAAI,QAAQ,SAAS;AAC/D,YAAM,cAAc,OAAO,SAAS,UAAU;AAAA,IAClD;AAGA,QAAI,OAAO,MAAM;AACb,YAAM,OAAO,MAAM,cAAc,GAAG;AACpC,YAAM,YAAY,MAAM,cAAc,OAAO,MAAM,IAAI;AAGvD,YAAM,MAAM,IAAI;AAChB,UAAI,aAAa;AAGjB,aAAO,eAAe,KAAK,QAAQ;AAAA,QAC/B,OAAO,YAAY;AAAA,QACnB,cAAc;AAAA,MAAA,CACjB;AAEA,UAAY,OAAO;AAAA,IACxB;AAEA,WAAO,KAAA;AAAA,EACX;AACJ;AAEA,eAAe,cAAc,QAAa,MAAyB;AAC/D,MAAI,MAAM,MAAM,GAAG;AACf,WAAO,YAAY,QAAQ,IAAI;AAAA,EACnC;AACA,MAAI,UAAU,MAAM,GAAG;AACnB,WAAO,gBAAgB,QAAQ,IAAI;AAAA,EACvC;AACA,MAAI,MAAM,MAAM,GAAG;AACf,WAAO,YAAY,QAAQ,IAAI;AAAA,EACnC;AACA,MAAI,iBAAiB,MAAM,GAAG;AAC1B,WAAO,uBAAuB,QAAQ,IAAI;AAAA,EAC9C;AAEA,MAAI,OAAO,WAAW,YAAY;AAC9B,WAAO,OAAO,IAAI;AAAA,EACtB;AAEA,QAAM,IAAI,MAAM,2GAA2G;AAC/H;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
1
+ {"version":3,"file":"index.cjs","sources":["../src/response.ts","../src/context.ts","../src/symbol.ts","../src/types.ts","../src/decorators.ts","../src/di.ts","../src/util/instrumentation.ts","../src/middleware.ts","../src/request.ts","../src/util/deep-merge.ts","../src/plugins/openapi.ts","../src/plugins/serve-static.ts","../src/util/async-hooks.ts","../src/router.ts","../src/shokupan.ts","../src/plugins/auth.ts","../src/plugins/compression.ts","../src/plugins/cors.ts","../src/plugins/express.ts","../src/plugins/rate-limit.ts","../src/plugins/scalar.ts","../src/plugins/security-headers.ts","../src/plugins/session.ts","../src/plugins/validation.ts"],"sourcesContent":["\n/**\n * Custom response class to handle response state (headers, status) \n * before the actual Response object is created.\n */\nexport class ShokupanResponse {\n private _headers = new Headers();\n private _status = 200;\n\n /**\n * Get the current headers\n */\n get headers() {\n return this._headers;\n }\n\n /**\n * Get the current status code\n */\n get status() {\n return this._status;\n }\n\n /**\n * Set the status code\n */\n set status(code: number) {\n this._status = code;\n }\n\n /**\n * Set a response header\n * @param key Header name\n * @param value Header value\n */\n public set(key: string, value: string) {\n this._headers.set(key, value);\n return this;\n }\n\n /**\n * Append to a response header\n * @param key Header name\n * @param value Header value\n */\n public append(key: string, value: string) {\n this._headers.append(key, value);\n return this;\n }\n\n /**\n * Get a response header value\n * @param key Header name\n */\n public get(key: string) {\n return this._headers.get(key);\n }\n\n /**\n * Check if a header exists\n * @param key Header name\n */\n public has(key: string) {\n return this._headers.has(key);\n }\n}\n","import type { BodyInit, Server } from 'bun';\nimport type { ShokupanRequest } from './request';\nimport { ShokupanResponse } from './response';\nimport type { Shokupan } from './shokupan';\nimport type { CookieOptions, JSXRenderer } from './types';\n\n// Shim for HeadersInit if not available globally in some envs\ntype HeadersInit = Headers | Record<string, string> | [string, string][];\n\nexport class ShokupanContext<State extends Record<string, any> = Record<string, any>> {\n public readonly url: URL;\n public params: Record<string, string> = {};\n public state: State;\n\n public readonly response: ShokupanResponse;\n\n constructor(\n public readonly request: ShokupanRequest<any>,\n public readonly server?: Server,\n state?: State,\n public readonly app?: Shokupan\n ) {\n this.url = new URL(request.url);\n this.state = state || {} as State;\n this.response = new ShokupanResponse();\n }\n\n /**\n * Base request\n */\n get req() { return this.request; }\n /**\n * HTTP method\n */\n get method() { return this.request.method; }\n /**\n * Request path\n */\n get path() { return this.url.pathname; }\n /**\n * Request query params\n */\n get query() { return Object.fromEntries(this.url.searchParams); }\n\n /**\n * Client IP address\n */\n get ip() { return this.server?.requestIP(this.request as unknown as Request); }\n\n /**\n * Request hostname (e.g. \"localhost\")\n */\n get hostname() { return this.url.hostname; }\n\n /**\n * Request host (e.g. \"localhost:3000\")\n */\n get host() { return this.url.host; }\n\n /**\n * Request protocol (e.g. \"http:\", \"https:\")\n */\n get protocol() { return this.url.protocol; }\n\n /**\n * Whether request is secure (https)\n */\n get secure() { return this.url.protocol === 'https:'; }\n\n /**\n * Request origin (e.g. \"http://localhost:3000\")\n */\n get origin() { return this.url.origin; }\n\n /**\n * Request headers\n */\n get headers() { return this.request.headers; }\n\n /**\n * Get a request header\n * @param name Header name\n */\n public get(name: string) { return this.request.headers.get(name); }\n\n /**\n * Base response object\n */\n get res() { return this.response; }\n\n /**\n * Helper to set a header on the response\n * @param key Header key\n * @param value Header value\n */\n public set(key: string, value: string) {\n this.response.set(key, value);\n return this;\n }\n\n /**\n * Set a cookie\n * @param name Cookie name\n * @param value Cookie value\n * @param options Cookie options\n */\n public setCookie(name: string, value: string, options: CookieOptions = {}) {\n let cookie = `${encodeURIComponent(name)}=${encodeURIComponent(value)}`;\n\n if (options.maxAge) cookie += `; Max-Age=${Math.floor(options.maxAge)}`;\n if (options.expires) cookie += `; Expires=${options.expires.toUTCString()}`;\n if (options.httpOnly) cookie += `; HttpOnly`;\n if (options.secure) cookie += `; Secure`;\n if (options.domain) cookie += `; Domain=${options.domain}`;\n if (options.path) cookie += `; Path=${options.path || '/'}`;\n if (options.sameSite) {\n const sameSite = typeof options.sameSite === 'string'\n ? options.sameSite.toLowerCase()\n : options.sameSite\n ? 'strict'\n : 'lax'; // Default logic if boolean true, though usually explicit string is better\n // Ideally follow specific behavior: express-session/cookies uses boolean to mean strict/lax sometimes?\n // Let's stick to standard strings mostly, but maybe map boolean to Strict/Lax?\n // Standard: SameSite=Lax (default if missing but we are setting it only if present)\n // If strictly boolean true -> Strict, false -> (don't set? or None? usually don't set)\n cookie += `; SameSite=${typeof options.sameSite === 'boolean' ? 'Strict' : (options.sameSite.charAt(0).toUpperCase() + options.sameSite.slice(1))}`;\n }\n if (options.priority) {\n cookie += `; Priority=${options.priority.charAt(0).toUpperCase() + options.priority.slice(1)}`;\n }\n\n this.response.append('Set-Cookie', cookie);\n return this;\n }\n\n private mergeHeaders(headers?: HeadersInit): Headers {\n const h = new Headers(this.response.headers);\n if (headers) {\n new Headers(headers).forEach((v, k) => h.set(k, v));\n }\n return h;\n }\n\n /**\n * Send a response\n * @param body Response body\n * @param options Response options\n * @returns Response\n */\n public send(body?: BodyInit, options?: ResponseInit) {\n const headers = this.mergeHeaders(options?.headers as any);\n const status = options?.status ?? this.response.status;\n return new Response(body, { status, headers });\n }\n\n /**\n * Read request body\n */\n async body<T = any>(): Promise<T> {\n const contentType = this.request.headers.get(\"content-type\");\n if (contentType?.includes(\"application/json\")) {\n return this.request.json() as any;\n }\n if (contentType?.includes(\"multipart/form-data\") || contentType?.includes(\"application/x-www-form-urlencoded\")) {\n return this.request.formData() as any;\n }\n return this.request.text() as any;\n }\n\n /**\n * Respond with a JSON object\n */\n json(data: any, status?: number, headers?: HeadersInit) {\n const finalHeaders = this.mergeHeaders(headers);\n finalHeaders.set(\"content-type\", \"application/json\");\n const finalStatus = status ?? this.response.status;\n return new Response(JSON.stringify(data), { status: finalStatus, headers: finalHeaders });\n }\n\n /**\n * Respond with a text string\n */\n text(data: string, status?: number, headers?: HeadersInit) {\n const finalHeaders = this.mergeHeaders(headers);\n finalHeaders.set(\"content-type\", \"text/plain\");\n const finalStatus = status ?? this.response.status;\n return new Response(data, { status: finalStatus, headers: finalHeaders });\n }\n\n /**\n * Respond with HTML content\n */\n html(html: string, status?: number, headers?: HeadersInit) {\n const finalHeaders = this.mergeHeaders(headers);\n finalHeaders.set(\"content-type\", \"text/html\");\n const finalStatus = status ?? this.response.status;\n return new Response(html, { status: finalStatus, headers: finalHeaders });\n }\n\n /**\n * Respond with a redirect\n */\n redirect(url: string, status = 302) {\n const headers = this.mergeHeaders();\n headers.set('Location', url);\n return new Response(null, { status, headers });\n }\n\n /**\n * Respond with a status code\n * DOES NOT CHAIN!\n */\n status(status: number) {\n const headers = this.mergeHeaders();\n return new Response(null, { status, headers });\n }\n\n /**\n * Respond with a file\n */\n public file(path: string, fileOptions?: BlobPropertyBag, responseOptions?: ResponseInit) {\n const headers = this.mergeHeaders(responseOptions?.headers as any);\n const status = responseOptions?.status ?? this.response.status;\n return new Response(Bun.file(path, fileOptions), { status, headers });\n }\n\n /**\n * JSX Rendering Function\n */\n public renderer?: JSXRenderer;\n\n /**\n * Render a JSX element\n * @param element JSX Element\n * @param status HTTP Status\n * @param headers HTTP Headers\n */\n public async jsx(element: any, args?: Parameters<JSXRenderer>[1], status?: number, headers?: HeadersInit) {\n if (!this.renderer) {\n throw new Error(\"No JSX renderer configured\");\n }\n\n const html = await this.renderer(element, args);\n return this.html(html, status, headers);\n }\n}\n","export const $isApplication = Symbol.for(\"Shokupan.app\");\nexport const $appRoot = Symbol.for(\"Shokupan.app-root\");\nexport const $isMounted = Symbol(\"Shokupan.isMounted\");\nexport const $routeMethods = Symbol(\"Shokupan.routeMethods\");\nexport const $routeArgs = Symbol(\"Shokupan.routeArgs\");\nexport const $controllerPath = Symbol(\"Shokupan.controllerPath\");\nexport const $middleware = Symbol(\"Shokupan.middleware\");\nexport const $isRouter = Symbol.for(\"Shokupan.router\");\nexport const $parent = Symbol.for(\"Shokupan.parent\");\nexport const $childRouters = Symbol.for(\"Shokupan.child-routers\");\nexport const $childControllers = Symbol.for(\"Shokupan.child-controllers\");\nexport const $mountPath = Symbol.for(\"Shokupan.mount-path\");\nexport const $dispatch = Symbol.for(\"Shokupan.dispatch\");\nexport const $routes = Symbol.for(\"Shokupan.routes\");\nexport const $routeSpec = Symbol.for(\"Shokupan.routeSpec\");","import type { OpenAPI } from '@scalar/openapi-types';\nimport type { Server } from 'bun';\nimport type { ShokupanContext } from './context';\nimport { $isRouter } from \"./symbol\";\n\nexport type DeepPartial<T> = T extends Function ? T : T extends object ? {\n [P in keyof T]?: DeepPartial<T[P]>;\n} : T;\n\nexport type MethodAPISpec = OpenAPI.Operation;\nexport type GuardAPISpec = DeepPartial<OpenAPI.Operation>;\nexport type RouterAPISpec = OpenAPI.Operation & Pick<Required<OpenAPI.Operation>, 'tags'> & { group: string; };\n\nexport interface OpenAPIOptions {\n info?: OpenAPI.Document['info'];\n servers?: OpenAPI.Document['servers'];\n components?: OpenAPI.Document['components'];\n tags?: OpenAPI.Document['tags'];\n externalDocs?: OpenAPI.Document['externalDocs'];\n defaultTagGroup?: string;\n defaultTag?: string;\n}\n\nexport interface ShokupanHooks<T = any> {\n onError?: (error: unknown, ctx: ShokupanContext<T>) => void | Promise<void>;\n onRequestStart?: (ctx: ShokupanContext<T>) => void | Promise<void>;\n onRequestEnd?: (ctx: ShokupanContext<T>) => void | Promise<void>;\n onResponseStart?: (ctx: ShokupanContext<T>, response: Response) => void | Promise<void>;\n onResponseEnd?: (ctx: ShokupanContext<T>, response: Response) => void | Promise<void>;\n beforeValidate?: (ctx: ShokupanContext<T>, data: any) => void | Promise<void>;\n afterValidate?: (ctx: ShokupanContext<T>, data: any) => void | Promise<void>;\n onReadTimeout?: (ctx: ShokupanContext<T>) => void | Promise<void>;\n onWriteTimeout?: (ctx: ShokupanContext<T>) => void | Promise<void>;\n onRequestTimeout?: (ctx: ShokupanContext<T>) => void | Promise<void>;\n}\n\nexport interface CookieOptions {\n maxAge?: number;\n expires?: Date;\n httpOnly?: boolean;\n secure?: boolean;\n domain?: string;\n path?: string;\n sameSite?: boolean | 'lax' | 'strict' | 'none' | 'Lax' | 'Strict' | 'None';\n priority?: 'low' | 'medium' | 'high' | 'Low' | 'Medium' | 'High';\n}\n\n\nexport type ShokupanHandler<T extends Record<string, any> = Record<string, any>> = (ctx: ShokupanContext<T>, next?: NextFn) => Promise<any> | any;\nexport const HTTPMethods = [\"GET\", \"POST\", \"PUT\", \"DELETE\", \"PATCH\", \"HEAD\", \"OPTIONS\", \"ALL\"];\nexport type Method = \"GET\" | \"POST\" | \"PUT\" | \"DELETE\" | \"PATCH\" | \"OPTIONS\" | \"HEAD\" | \"ALL\";\n\nexport enum RouteParamType {\n BODY = \"BODY\",\n PARAM = \"PARAM\",\n QUERY = \"QUERY\",\n HEADER = \"HEADER\",\n REQUEST = \"REQUEST\",\n CONTEXT = \"CONTEXT\"\n}\n\nexport interface ServerFactory {\n (options: any): Server | Promise<Server>;\n}\n\nexport type NextFn = () => Promise<any>;\nexport type Middleware = (ctx: ShokupanContext<unknown>, next: NextFn) => Promise<any> | any;\nexport type JSXRenderer = (element: any, args?: unknown) => string | Promise<string>;\n\nexport type ShokupanRouteConfig = DeepPartial<{\n name: string;\n group: string;\n /**\n * Timeout for this specific route (milliseconds).\n */\n requestTimeout: number;\n openapi: DeepPartial<OpenAPI.Operation>;\n /**\n * Custom renderer for this route.\n */\n renderer: JSXRenderer;\n\n /**\n * Hooks for this route/router.\n */\n hooks: ShokupanHooks;\n /**\n * Whether to enforce that only controller classes (constructors) are accepted by the router.\n */\n controllersOnly: boolean;\n}>;\n\nexport type ShokupanRoute = {\n method: Method;\n path: string;\n regex: RegExp;\n keys: string[];\n handler: ShokupanHandler;\n handlerSpec?: MethodAPISpec;\n group?: string;\n guards?: {\n handler: ShokupanHandler;\n spec?: GuardAPISpec;\n }[];\n requestTimeout?: number;\n renderer?: JSXRenderer;\n /**\n * Hooks from the router/route definition\n */\n hooks?: ShokupanHooks;\n};\n\nexport type ShokupanConfig<T extends Record<string, any> = Record<string, any>> = DeepPartial<{\n /**\n * The port to be used for the server.\n * @default 3000\n */\n port: number;\n /**\n * The hostname to be used for the server.\n * @default \"localhost\"\n */\n hostname: string;\n /**\n * Whether to run in development mode.\n * @default process.env.NODE_ENV !== \"production\"\n */\n development: boolean;\n /**\n * Whether to enable AsyncLocalStorage.\n * (Request local storage)\n * @default false\n */\n enableAsyncLocalStorage: boolean;\n /**\n * Whether to enable OpenAPI generation.\n * @default true\n */\n enableOpenApiGen: boolean;\n /**\n * Whether to reuse the port.\n * @default false\n */\n reusePort: boolean;\n /**\n * Whether to enforce that only controller classes (constructors) are accepted by the router.\n * @default false\n */\n controllersOnly: boolean;\n /**\n * HTTP logger function.\n */\n httpLogger: (ctx: ShokupanContext<T>) => void;\n /**\n * Logger object.\n */\n logger: {\n verbose: boolean;\n info: (msg: string, props: Record<string, any>) => void;\n debug: (msg: string, props: Record<string, any>) => void;\n warning: (msg: string, props: Record<string, any>) => void;\n error: (msg: string, props: Record<string, any>) => void;\n /**\n * Something fatally went wrong and the application cannot continue.\n */\n fatal: (msg: string, props: Record<string, any>) => void;\n };\n /**\n * Timeout for reading the request body (milliseconds).\n * Maps to Bun's `idleTimeout`.\n * @default 30000\n */\n readTimeout: number;\n /**\n * Timeout for processing the request (milliseconds).\n * Maps to `server.timeout(req, seconds)`.\n * @default 0 (disabled)\n */\n requestTimeout: number;\n /**\n * Timeout for writing the response (milliseconds).\n * Not currently supported by Bun.serve natively.\n */\n writeTimeout: number;\n\n /**\n * JSX Rendering function.\n */\n renderer: JSXRenderer;\n\n /**\n * Factory function to create the server instance.\n * Defaults to Bun.serve.\n */\n serverFactory: ServerFactory;\n\n /**\n * Lifecycle hooks.\n */\n hooks: ShokupanHooks<T>;\n\n\n // Open for extension\n [key: string]: any;\n}>;\n\n\nexport interface RequestOptions {\n path?: string;\n url?: string;\n method?: Method;\n headers?: Record<string, string>;\n body?: any;\n query?: Record<string, string>;\n}\n\nexport interface ProcessResult {\n status: number;\n headers: Record<string, string>;\n data: any;\n}\n\nexport type ShokupanController<T = any> = (new (...args: any[]) => T) & {\n [$isRouter]?: undefined;\n};\n\nexport interface StaticServeHooks<T extends Record<string, any>> {\n onRequest?: (ctx: ShokupanContext<T>) => Promise<Response | void> | Response | void;\n onResponse?: (ctx: ShokupanContext<T>, response: Response) => Promise<Response> | Response;\n}\n\nexport interface StaticServeOptions<T extends Record<string, any>> {\n /**\n * Root directory to serve files from.\n * Can be an absolute path or relative to the CWD.\n */\n root?: string;\n /**\n * Whether to list directory contents if no index file is found.\n * @default false\n */\n listDirectory?: boolean;\n /**\n * Index file(s) to look for when a directory is requested.\n * @default ['index.html', 'index.htm']\n */\n index?: string | string[];\n /**\n * Hooks to intercept requests/responses.\n */\n hooks?: StaticServeHooks<T>;\n /**\n * How to treat dotfiles (files starting with .)\n * 'allow': Serve them\n * 'deny': Return 403\n * 'ignore': Return 404\n * @default 'ignore'\n */\n dotfiles?: 'allow' | 'deny' | 'ignore';\n /**\n * Regex or glob patterns to exclude\n */\n exclude?: (string | RegExp)[];\n /**\n * Try to append these extensions to the path if the file is not found.\n * e.g. ['html', 'htm']\n */\n extensions?: string[];\n /**\n * OpenAPI specification for the static route.\n */\n openapi?: MethodAPISpec;\n}\n","import { $controllerPath, $middleware, $routeArgs, $routeMethods, $routeSpec } from \"./symbol\";\nimport type { GuardAPISpec, MethodAPISpec } from \"./types\";\nimport { type Method, type Middleware, RouteParamType } from \"./types\";\n\n/**\n * Class Decorator: Defines the base path for a controller.\n */\nexport function Controller(path: string = \"/\") {\n return (target: any) => {\n target[$controllerPath] = path;\n };\n}\n\n/**\n * Decorator: Applies middleware to a class or method.\n */\nexport function Use(...middleware: Middleware[]) {\n return (target: any, propertyKey?: string, descriptor?: PropertyDescriptor) => {\n // If propertyKey is undefined, it's a class decorator\n if (!propertyKey) {\n const existing = target[$middleware] || [];\n target[$middleware] = [...existing, ...middleware];\n }\n // Method decorator\n else {\n if (!target[$middleware]) {\n target[$middleware] = new Map();\n }\n const existing = target[$middleware].get(propertyKey) || [];\n target[$middleware].set(propertyKey, [...existing, ...middleware]);\n }\n };\n}\n\n// --- Parameter Decorators ---\n\nfunction createParamDecorator(type: RouteParamType) {\n return (name?: string) => {\n return (target: any, propertyKey: string, parameterIndex: number) => {\n if (!target[$routeArgs]) {\n target[$routeArgs] = new Map();\n }\n if (!target[$routeArgs].has(propertyKey)) {\n target[$routeArgs].set(propertyKey, []);\n }\n target[$routeArgs].get(propertyKey).push({\n index: parameterIndex,\n type,\n name\n });\n };\n };\n}\n\nexport const Body = createParamDecorator(RouteParamType.BODY);\nexport const Param = createParamDecorator(RouteParamType.PARAM);\nexport const Query = createParamDecorator(RouteParamType.QUERY);\nexport const Headers = createParamDecorator(RouteParamType.HEADER);\nexport const Req = createParamDecorator(RouteParamType.REQUEST);\nexport const Ctx = createParamDecorator(RouteParamType.CONTEXT);\n\n\n/**\n * Decorator: Overrides the OpenAPI specification for a route.\n */\nexport function Spec(spec: MethodAPISpec | GuardAPISpec) {\n return (target: any, propertyKey: string, descriptor: PropertyDescriptor) => {\n if (!target[$routeSpec]) {\n target[$routeSpec] = new Map();\n }\n target[$routeSpec].set(propertyKey, spec);\n };\n}\n\n/**\n * Creates a method decorator for a specific HTTP verb.\n */\nfunction createMethodDecorator(method: Method) {\n return (path: string = \"/\") => {\n return (target: any, propertyKey: string, descriptor: PropertyDescriptor) => {\n if (!target[$routeMethods]) {\n target[$routeMethods] = new Map();\n }\n\n target[$routeMethods].set(propertyKey, {\n method,\n path\n });\n };\n };\n}\n\nexport const Get = createMethodDecorator(\"GET\");\nexport const Post = createMethodDecorator(\"POST\");\nexport const Put = createMethodDecorator(\"PUT\");\nexport const Delete = createMethodDecorator(\"DELETE\");\nexport const Patch = createMethodDecorator(\"PATCH\");\nexport const Options = createMethodDecorator(\"OPTIONS\");\nexport const Head = createMethodDecorator(\"HEAD\");\nexport const All = createMethodDecorator(\"ALL\");\n","\n/**\n * Simple Dependency Injection Container\n */\nexport class Container {\n private static services = new Map<any, any>();\n\n public static register<T>(target: new (...args: any[]) => T, instance: T) {\n this.services.set(target, instance);\n }\n\n public static get<T>(target: new (...args: any[]) => T): T | undefined {\n return this.services.get(target);\n }\n\n public static has(target: any): boolean {\n return this.services.has(target);\n }\n\n public static resolve<T>(target: new (...args: any[]) => T): T {\n if (this.services.has(target)) {\n return this.services.get(target);\n }\n\n // Auto-instantiate if possible (transient)\n // Note: For full DI we would read constructor params here using 'design:paramtypes'\n // But Bun/Esbuild need distinct config for that.\n // For now, we assume simple instantiation or manual registration.\n const instance = new target();\n this.services.set(target, instance);\n return instance;\n }\n}\n\n/**\n * Decorator to mark a class as injectable (Service).\n */\nexport function Injectable() {\n return (target: any) => {\n // Just a marker for now, or could auto-register\n };\n}\n\n/**\n * Property Decorator: Injects a service.\n */\nexport function Inject(token: any) {\n return (target: any, key: string) => {\n Object.defineProperty(target, key, {\n get: () => Container.resolve(token),\n enumerable: true,\n configurable: true\n });\n };\n}\n","import { SpanKind, SpanStatusCode, trace } from \"@opentelemetry/api\";\nimport type { Middleware, ShokupanHandler } from \"../types\";\n\nconst tracer = trace.getTracer(\"shokupan.middleware\");\n\n/**\n * Wraps a middleware function with an OpenTelemetry span.\n */\nexport function traceMiddleware(fn: Middleware, name?: string): Middleware {\n const middlewareName = name || fn.name || \"anonymous middleware\";\n\n return async (ctx, next) => {\n return tracer.startActiveSpan(`middleware - ${middlewareName}`, {\n kind: SpanKind.INTERNAL,\n attributes: {\n \"code.function\": middlewareName,\n \"component\": \"shokupan.middleware\"\n }\n }, async (span) => {\n try {\n const result = await fn(ctx, next);\n return result;\n }\n catch (err: any) {\n span.recordException(err);\n span.setStatus({ code: SpanStatusCode.ERROR, message: err.message });\n throw err;\n }\n finally {\n span.end();\n }\n });\n };\n}\n\n/**\n * Wraps a route handler with an OpenTelemetry span.\n */\nexport function traceHandler(fn: ShokupanHandler | ((...args: any[]) => any), name: string): ShokupanHandler {\n return async function (this: any, ...args: any[]) {\n return tracer.startActiveSpan(`route handler - ${name}`, {\n kind: SpanKind.INTERNAL,\n attributes: {\n \"http.route\": name,\n \"component\": \"shokupan.route\"\n }\n }, async (span) => {\n try {\n const result = await (fn as Function).apply(this, args);\n return result;\n }\n catch (err: any) {\n span.recordException(err);\n span.setStatus({ code: SpanStatusCode.ERROR, message: err.message });\n throw err;\n }\n finally {\n span.end();\n }\n });\n };\n}\n","import type { ShokupanContext } from \"./context\";\nimport type { Middleware, NextFn } from './types';\nimport { traceMiddleware } from \"./util/instrumentation\";\n\n/**\n * Composes a list of middleware into a single function.\n * This is the onion model (Koa-style).\n */\nexport const compose = (middleware: Middleware[]) => {\n function fn(context: ShokupanContext<unknown>, next?: NextFn) {\n let runner: NextFn = next || (async () => { });\n\n for (let i = middleware.length - 1; i >= 0; i--) {\n const fn = traceMiddleware(middleware[i]);\n const nextStep = runner;\n let called = false;\n\n runner = async () => {\n if (called) throw new Error('next() called multiple times');\n called = true;\n return fn(context, nextStep);\n };\n }\n\n return runner();\n };\n\n return fn;\n};\n\n\n","import type { Method } from './types';\n\nexport type ShokupanRequestProps = {\n method: Method;\n url: string;\n headers: Headers;\n body: any;\n};\n\n/**\n * This class is used to create a request object.\n * It is used to make requests to the router.\n */\nclass ShokupanRequestBase {\n method: Method;\n url: string;\n headers: Headers;\n body: any;\n\n async json(): Promise<any> { return JSON.parse(this.body); }\n async text(): Promise<string> { return this.body; }\n async formData(): Promise<FormData> {\n if (this.body instanceof FormData) {\n return this.body;\n }\n return new Response(this.body, { headers: this.headers }).formData() as any;\n }\n\n constructor(props: ShokupanRequestProps) {\n Object.assign(this, props);\n if (!(this.headers instanceof Headers)) {\n this.headers = new Headers(this.headers);\n }\n }\n}\n\n/**\n * This type is used to add properties to the request object.\n */\nexport type ShokupanRequest<T> = ShokupanRequestBase & T;\n\ninterface ShokupanConstructor {\n new <T extends Record<string, any>>(props: ShokupanRequestProps): ShokupanRequest<T>;\n}\n\n/**\n * This class is used to create a request object.\n * It is used to make requests to the router.\n */\nexport const ShokupanRequest = ShokupanRequestBase as ShokupanConstructor;\n","/**\n * Simple object check.\n */\nexport function isObject(item: any): item is Record<string, any> {\n return (item && typeof item === 'object' && !Array.isArray(item));\n}\n\n/**\n * Deep merge two objects.\n * \n * - Arrays are concatenated.\n * - Objects are merged recursively.\n * - Primitives are overwritten.\n */\nexport function deepMerge<T extends Record<string, any>>(target: T, ...sources: Partial<T>[]): T {\n if (!sources.length) return target;\n const source = sources.shift();\n\n if (isObject(target) && isObject(source)) {\n for (const key in source) {\n if (isObject(source[key])) {\n if (!target[key]) Object.assign(target, { [key]: {} });\n deepMerge(target[key], source[key]);\n } else if (Array.isArray(source[key])) {\n if (!target[key]) Object.assign(target, { [key]: [] });\n\n if (key === 'tags') {\n // Start fresh if tags are provided in source (overwrite)\n (target as any)[key] = source[key];\n continue;\n }\n\n // Concat then deduplicate primitives\n const mergedArray = (target as any)[key].concat(source[key]);\n\n // If all items are primitives, unique them\n const isPrimitive = (item: any) =>\n typeof item === 'string' ||\n typeof item === 'number' ||\n typeof item === 'boolean';\n\n if (mergedArray.every(isPrimitive)) {\n (target as any)[key] = Array.from(new Set(mergedArray));\n }\n else {\n (target as any)[key] = mergedArray;\n }\n } else {\n Object.assign(target, { [key]: source[key] });\n }\n }\n }\n\n return deepMerge(target, ...sources);\n}\n","import type { ShokupanRouter } from '../router';\nimport { $childControllers, $childRouters, $mountPath, $routes } from '../symbol';\nimport type { OpenAPIOptions, ShokupanHandler } from '../types';\nimport { deepMerge } from '../util/deep-merge';\n\n/**\n * Analyze a handler function to infer request/response types\n */\nfunction analyzeHandler(handler: ShokupanHandler): { inferredSpec?: any; } {\n const handlerSource = handler.toString();\n const inferredSpec: any = {};\n\n // Detect request body\n if (handlerSource.includes('ctx.body') || handlerSource.includes('await ctx.req.json()')) {\n inferredSpec.requestBody = {\n content: { 'application/json': { schema: { type: 'object' } } }\n };\n }\n\n\n // Detect query parameters with type detection\n const queryParams = new Map<string, { type: string; format?: string; }>();\n\n const queryIntMatch = handlerSource.match(/parseInt\\(ctx\\.query\\.(\\w+)\\)/g);\n if (queryIntMatch) {\n queryIntMatch.forEach(match => {\n const paramName = match.match(/ctx\\.query\\.(\\w+)/)?.[1];\n if (paramName) queryParams.set(paramName, { type: 'integer', format: 'int32' });\n });\n }\n\n const queryFloatMatch = handlerSource.match(/parseFloat\\(ctx\\.query\\.(\\w+)\\)/g);\n if (queryFloatMatch) {\n queryFloatMatch.forEach(match => {\n const paramName = match.match(/ctx\\.query\\.(\\w+)/)?.[1];\n if (paramName) queryParams.set(paramName, { type: 'number', format: 'float' });\n });\n }\n\n const queryNumberMatch = handlerSource.match(/Number\\(ctx\\.query\\.(\\w+)\\)/g);\n if (queryNumberMatch) {\n queryNumberMatch.forEach(match => {\n const paramName = match.match(/ctx\\.query\\.(\\w+)/)?.[1];\n if (paramName && !queryParams.has(paramName)) {\n queryParams.set(paramName, { type: 'number' });\n }\n });\n }\n\n const queryBoolMatch = handlerSource.match(/(?:Boolean\\(ctx\\.query\\.(\\w+)\\)|!+ctx\\.query\\.(\\w+))/g);\n if (queryBoolMatch) {\n queryBoolMatch.forEach(match => {\n const paramName = match.match(/ctx\\.query\\.(\\w+)/)?.[1];\n if (paramName && !queryParams.has(paramName)) {\n queryParams.set(paramName, { type: 'boolean' });\n }\n });\n }\n\n const queryMatch = handlerSource.match(/ctx\\.query\\.(\\w+)/g);\n if (queryMatch) {\n queryMatch.forEach(match => {\n const paramName = match.split('.')[2];\n if (paramName && !queryParams.has(paramName)) {\n queryParams.set(paramName, { type: 'string' });\n }\n });\n }\n\n if (queryParams.size > 0) {\n if (!inferredSpec.parameters) inferredSpec.parameters = [];\n queryParams.forEach((schema, paramName) => {\n inferredSpec.parameters.push({\n name: paramName,\n in: 'query',\n schema: { type: schema.type, ...(schema.format ? { format: schema.format } : {}) }\n });\n });\n }\n\n // Detect path parameters\n const pathParams = new Map<string, { type: string; format?: string; }>();\n\n const paramIntMatch = handlerSource.match(/parseInt\\(ctx\\.params\\.(\\w+)\\)/g);\n if (paramIntMatch) {\n paramIntMatch.forEach(match => {\n const paramName = match.match(/ctx\\.params\\.(\\w+)/)?.[1];\n if (paramName) pathParams.set(paramName, { type: 'integer', format: 'int32' });\n });\n }\n\n const paramFloatMatch = handlerSource.match(/parseFloat\\(ctx\\.params\\.(\\w+)\\)/g);\n if (paramFloatMatch) {\n paramFloatMatch.forEach(match => {\n const paramName = match.match(/ctx\\.params\\.(\\w+)/)?.[1];\n if (paramName) pathParams.set(paramName, { type: 'number', format: 'float' });\n });\n }\n\n if (pathParams.size > 0) {\n if (!inferredSpec.parameters) inferredSpec.parameters = [];\n pathParams.forEach((schema, paramName) => {\n inferredSpec.parameters.push({\n name: paramName,\n in: 'path',\n required: true,\n schema: { type: schema.type, ...(schema.format ? { format: schema.format } : {}) }\n });\n });\n }\n\n // Detect headers\n const headerMatch = handlerSource.match(/ctx\\.get\\(['\"](\\w+)['\"]\\)/g);\n if (headerMatch) {\n if (!inferredSpec.parameters) inferredSpec.parameters = [];\n headerMatch.forEach(match => {\n const headerName = match.match(/['\"](\\w+)['\"]/)?.[1];\n if (headerName) {\n inferredSpec.parameters.push({\n name: headerName,\n in: 'header',\n schema: { type: 'string' }\n });\n }\n });\n }\n\n // Detect response formats from ctx methods\n const responses: any = {};\n\n // Detect ctx.json() → application/json\n if (handlerSource.includes('ctx.json(')) {\n responses['200'] = {\n description: 'Successful response',\n content: {\n 'application/json': { schema: { type: 'object' } }\n }\n };\n }\n\n // Detect ctx.html() → text/html\n if (handlerSource.includes('ctx.html(')) {\n responses['200'] = {\n description: 'Successful response',\n content: {\n 'text/html': { schema: { type: 'string' } }\n }\n };\n }\n\n // Detect ctx.text() → text/plain\n if (handlerSource.includes('ctx.text(')) {\n responses['200'] = {\n description: 'Successful response',\n content: {\n 'text/plain': { schema: { type: 'string' } }\n }\n };\n }\n\n // Detect ctx.file() → application/octet-stream\n if (handlerSource.includes('ctx.file(')) {\n responses['200'] = {\n description: 'File download',\n content: {\n 'application/octet-stream': { schema: { type: 'string', format: 'binary' } }\n }\n };\n }\n\n // Detect ctx.redirect() → 3xx redirect\n if (handlerSource.includes('ctx.redirect(')) {\n responses['302'] = {\n description: 'Redirect'\n };\n }\n\n // Detect plain object return (fallback to JSON) - Pattern: return { ... }\n if (!responses['200'] && /return\\s+\\{/.test(handlerSource)) {\n responses['200'] = {\n description: 'Successful response',\n content: {\n 'application/json': { schema: { type: 'object' } }\n }\n };\n }\n\n // Detect error responses with status codes\n // Pattern: ctx.json({...}, 400) or ctx.text('error', 500)\n const errorStatusMatch = handlerSource.match(/ctx\\.(?:json|text|html)\\([^)]+,\\s*(\\d{3,})\\)/g);\n if (errorStatusMatch) {\n errorStatusMatch.forEach(match => {\n const statusCode = match.match(/,\\s*(\\d{3,})\\)/)?.[1];\n if (statusCode && statusCode !== '200') {\n responses[statusCode] = {\n description: `Error response (${statusCode})`\n };\n }\n });\n }\n\n if (Object.keys(responses).length > 0) {\n inferredSpec.responses = responses;\n }\n\n return { inferredSpec };\n}\n\n/**\n * Statically generate an OpenAPI spec from a ShokupanRouter instance.\n * \n * @param rootRouter - The root router instance to generate the spec tree from.\n * @param options - Optional OpenAPI configuration options.\n * @returns The generated OpenAPI spec.\n */\nexport async function generateOpenApi<T extends Record<string, any>>(rootRouter: ShokupanRouter<T>, options: OpenAPIOptions = {}): Promise<any> {\n const paths: Record<string, any> = {};\n const tagGroups = new Map<string, Set<string>>();\n\n const defaultTagGroup = options.defaultTagGroup || \"General\";\n const defaultTagName = options.defaultTag || \"Application\";\n\n // Step 4: Run AST Analysis if possible\n let astRoutes: any[] = [];\n try {\n // Dynamic import to avoid bundling issues if strictly runtime\n const { OpenAPIAnalyzer } = await import('../analysis/openapi-analyzer');\n const analyzer = new OpenAPIAnalyzer(process.cwd());\n const { applications } = await analyzer.analyze();\n\n // Create a map for easy lookup of apps by name/class\n const appMap = new Map<string, any>();\n applications.forEach(app => {\n appMap.set(app.name, app);\n // Also map by direct className if it's unique enough (heuristic)\n if (app.name !== app.className) {\n appMap.set(app.className, app);\n }\n });\n\n const getExpandedRoutes = (app: any, prefix: string = '', seen = new Set<string>()): any[] => {\n // Prevent infinite recursion in cyclic mounts\n if (seen.has(app.name)) return [];\n const newSeen = new Set(seen);\n newSeen.add(app.name);\n\n const expanded: any[] = [];\n\n // Add app's own routes with accumulated prefix\n for (const route of app.routes) {\n const cleanPrefix = prefix.endsWith('/') ? prefix.slice(0, -1) : prefix;\n const cleanPath = route.path.startsWith('/') ? route.path : '/' + route.path;\n let joined = cleanPrefix + cleanPath;\n if (joined.length > 1 && joined.endsWith('/')) {\n joined = joined.slice(0, -1);\n }\n\n expanded.push({\n ...route,\n path: joined || '/'\n });\n }\n\n // Recurse into mounted apps\n if (app.mounted) {\n for (const mount of app.mounted) {\n const targetApp = appMap.get(mount.target);\n if (targetApp) {\n const cleanPrefix = prefix.endsWith('/') ? prefix.slice(0, -1) : prefix;\n const mountPrefix = mount.prefix.startsWith('/') ? mount.prefix : '/' + mount.prefix;\n expanded.push(...getExpandedRoutes(targetApp, cleanPrefix + mountPrefix, newSeen));\n }\n }\n }\n return expanded;\n };\n\n // Expand routes for all applications\n // This generates variants: e.g. UserController at '/' AND Main->UserController at '/api/user'\n applications.forEach(app => {\n astRoutes.push(...getExpandedRoutes(app));\n });\n\n // Deduplicate AST Routes with Scoring\n // Prioritize: 1. Has Response Schema, 2. Has Handler Source\n const dedupedRoutes = new Map<string, { route: any, score: number; }>();\n\n for (const route of astRoutes) {\n const key = `${route.method.toUpperCase()}:${route.path}`;\n let score = 0;\n if (route.responseSchema) score += 10;\n if (route.handlerSource) score += 5;\n // Prefer longer/specific paths? No, exact path matching handles that.\n\n if (!dedupedRoutes.has(key) || score > dedupedRoutes.get(key)!.score) {\n dedupedRoutes.set(key, { route, score });\n }\n }\n\n astRoutes = Array.from(dedupedRoutes.values()).map(v => v.route);\n\n } catch (e) {\n console.warn(\"OpenAPI AST analysis failed or skipped:\", e);\n }\n\n const collect = (router: ShokupanRouter<T>, prefix = \"\", currentGroup = defaultTagGroup, defaultTag = defaultTagName) => {\n let group = currentGroup;\n let tag = defaultTag;\n\n if (router.config?.group) group = router.config.group;\n if (router.config?.name) {\n tag = router.config.name;\n }\n else {\n const mountPath = router[$mountPath];\n if (mountPath && mountPath !== \"/\") {\n const segments = mountPath.split(\"/\").filter(Boolean);\n if (segments.length > 0) {\n const lastSegment = segments[segments.length - 1];\n tag = lastSegment.replace(/[-_]/g, ' ').replace(/\\b\\w/g, c => c.toUpperCase());\n }\n }\n }\n\n if (!tagGroups.has(group)) tagGroups.set(group, new Set());\n\n const routes = (router as any)[$routes] || [];\n // console.log(`[OpenAPI] Visiting router with ${routes.length} routes. Config:`, router.config, \"Prefix:\", prefix);\n // Debug symbols\n // console.log('[OpenAPI] Router keys:', Reflect.ownKeys(router).map(k => k.toString()));\n // console.log('[OpenAPI] Local $routes symbol:', $routes.toString());\n\n for (const route of routes) {\n const routeGroup = route.group || group;\n const cleanPrefix = prefix.endsWith(\"/\") ? prefix.slice(0, -1) : prefix;\n const cleanSubPath = route.path.startsWith(\"/\") ? route.path : \"/\" + route.path;\n let fullPath = (cleanPrefix + cleanSubPath) || \"/\";\n fullPath = fullPath.replace(/:([a-zA-Z0-9_]+)/g, \"{$1}\");\n\n // Normalize trailing slash\n if (fullPath.length > 1 && fullPath.endsWith('/')) {\n fullPath = fullPath.slice(0, -1);\n }\n\n if (!paths[fullPath]) paths[fullPath] = {};\n\n // Initialize operation structure\n const operation: any = {\n responses: { '200': { description: \"Successful response\" } },\n tags: [tag]\n };\n\n\n\n // Merge metadata from guards (if any)\n if (route.guards) {\n // Iterate guards to harvest security requirements or responses\n for (const guard of route.guards) {\n if (guard.spec) {\n // Merge security (deduplicated)\n if (guard.spec.security) {\n const existing = operation.security || [];\n for (const req of guard.spec.security) {\n const reqStr = JSON.stringify(req);\n if (!existing.some((e: any) => JSON.stringify(e) === reqStr)) {\n existing.push(req);\n }\n }\n operation.security = existing;\n }\n // Merge responses (e.g. 401/403)\n if (guard.spec.responses) {\n operation.responses = { ...operation.responses, ...guard.spec.responses };\n }\n }\n }\n }\n\n // --- Step 4: Base Data from AST ---\n // Find matching AST route\n // Matching logic: Method + Path (normalized) + Handler Source Matching\n\n // 1. Exact Match (Method + Path)\n let astMatch = astRoutes.find(r =>\n r.method.toUpperCase() === route.method.toUpperCase() &&\n r.path === fullPath\n );\n\n // 2. Fallback: Match by Handler Source (ignores Path mismatch due to mounting prefixes)\n if (!astMatch) {\n // Unwrap: If handler is wrapped (e.g. Controller), check originalHandler\n let runtimeSource = route.handler.toString();\n if ((route.handler as any).originalHandler) {\n runtimeSource = (route.handler as any).originalHandler.toString();\n }\n\n const runtimeHandlerSrc = runtimeSource.replace(/\\s+/g, ' ');\n\n // Filter all AST routes with same method\n const sameMethodRoutes = astRoutes.filter(r => r.method.toUpperCase() === route.method.toUpperCase());\n\n // Find one that matches source\n astMatch = sameMethodRoutes.find(r => {\n const astHandlerSrc = (r.handlerSource || r.handlerName || '').replace(/\\s+/g, ' ');\n if (!astHandlerSrc || astHandlerSrc.length < 20) return false; // fast fail on empty/short\n\n const match = runtimeHandlerSrc.includes(astHandlerSrc) ||\n astHandlerSrc.includes(runtimeHandlerSrc) ||\n (r.handlerSource && runtimeHandlerSrc.includes(r.handlerSource.substring(0, 50)));\n\n return match;\n });\n\n if (astMatch) {\n // console.log(`[OpenAPI] MATCHED via source!`);\n }\n }\n\n\n // Disambiguate if multiple routes share the same path/method (but from different apps/files)\n // AND we haven't found a source-based match yet (or we verified exact path match but need to be sure)\n // Actually, if we found a source-based match in step 2, we are good.\n // If we found an exact path match in step 1, we might still have ambiguity if multiple files define same path?\n // Existing disambiguation logic relied on exact path. Let's keep it for exact path cases.\n\n const potentialMatches = astRoutes.filter(r =>\n r.method.toUpperCase() === route.method.toUpperCase() &&\n r.path === fullPath\n );\n\n if (potentialMatches.length > 1) {\n const runtimeHandlerSrc = route.handler.toString().replace(/\\s+/g, ' ');\n // console.log(`[OpenAPI] Disambiguating ${potentialMatches.length} matches for ${fullPath}...`);\n\n // Try to find the best match by checking if AST handler snippet is in Runtime handler source\n const preciseMatch = potentialMatches.find(r => {\n const astHandlerSrc = (r.handlerSource || r.handlerName || '').replace(/\\s+/g, ' ');\n\n // Relaxed matching: check if ONE includes the other (source code containment)\n // limit length to avoid huge string comparisons if not needed\n const match = runtimeHandlerSrc.includes(astHandlerSrc) || astHandlerSrc.includes(runtimeHandlerSrc) ||\n (r.handlerSource && runtimeHandlerSrc.includes(r.handlerSource.substring(0, 50))); /* Fallback to prefix match */\n\n // console.log(`- comparing with AST source: \"${astHandlerSrc.substring(0, 50)}...\"`);\n // console.log(` MATCH: ${match}`);\n return match;\n });\n\n if (preciseMatch) {\n astMatch = preciseMatch;\n }\n }\n\n // Clean up debug logs\n // if (fullPath === \"/\" && route.method.toUpperCase() === \"GET\") { ... }\n\n if (astMatch) {\n if (astMatch.summary) operation.summary = astMatch.summary;\n if (astMatch.description) operation.description = astMatch.description;\n if (astMatch.tags) operation.tags = astMatch.tags;\n if (astMatch.operationId) operation.operationId = astMatch.operationId;\n\n // Merge Request Body\n if (astMatch.requestTypes?.body) {\n operation.requestBody = {\n content: {\n 'application/json': { schema: astMatch.requestTypes.body }\n }\n };\n }\n\n // Merge Responses\n if (astMatch.responseSchema) {\n operation.responses['200'] = {\n description: 'Successful response',\n content: {\n 'application/json': { schema: astMatch.responseSchema }\n }\n };\n }\n else if (astMatch.responseType) {\n const contentType = astMatch.responseType === 'string' ? 'text/plain' : 'application/json';\n operation.responses['200'] = {\n description: 'Successful response',\n content: {\n [contentType]: { schema: { type: astMatch.responseType } }\n }\n };\n }\n\n // Merge Parameters (Query, Path, Header) from AST\n const params: any[] = [];\n if (astMatch.requestTypes?.query) {\n // AST gives us { param: type }, we need to convert to OpenAPI param\n // This part of AST analyzer might need improvement to give types, currently it gives string map?\n // Let's assume the analyzer gives us schema-like objects or we infer basic string\n for (const [name, _type] of Object.entries(astMatch.requestTypes.query)) {\n params.push({ name, in: 'query', schema: { type: 'string' } }); // simplifying for now\n }\n }\n // ... similar for headers\n if (params.length > 0) {\n operation.parameters = params;\n }\n }\n\n // --- Step 5: Decorators / Path Patterns (Runtime) ---\n\n // Path Keys (e.g. /users/:id)\n if (route.keys.length > 0) {\n const pathParams = route.keys.map((key: string) => ({\n name: key,\n in: \"path\",\n required: true,\n schema: { type: \"string\" }\n }));\n // Merge into existing parameters\n const existingParams = operation.parameters || [];\n const mergedParams = [...existingParams];\n\n pathParams.forEach(p => {\n const idx = mergedParams.findIndex(ep => ep.in === 'path' && ep.name === p.name);\n if (idx >= 0) {\n // Overwrite or keep? Usually runtime path keys are the source of truth for existence\n mergedParams[idx] = deepMerge(mergedParams[idx], p);\n } else {\n mergedParams.push(p);\n }\n });\n operation.parameters = mergedParams;\n }\n\n // Runtime analysis (analyzeHandler) - this is the \"detectable code usage\" part from step 2/3 but done at runtime\n // The prompt says Step 2 & 3 is AST. But existing code had `analyzeHandler`.\n // Let's keep `analyzeHandler` as a fallback or supplementary to AST if AST missed it \n // OR if the user meant Step 2/3 to BE the AST part (which is \"Step 4\" in my plan corresponding to user's point 4).\n // User point 5: \"Decorators included in this library\".\n\n // We have route.guards (Decorators sometimes add guards or metadata)\n // But we don't have a direct \"Decorators\" list on the route object itself unless we stored it.\n // `route.handlerSpec` seems to be used for manual overrides in `types.ts`?\n // Wait, existing code used `analyzeHandler`. The user said \"Step 2: ... generates OpenAPI data ... input fields\".\n // And \"Step 4: ... AST ...\".\n // Actually, point 1 says \"reads the TS files\". So Step 2/3 ARE AST.\n // Point 5 is \"Decorators\".\n\n // So `analyzeHandler` (regex based) is probably less reliable than AST and might be redundant if AST works.\n // But if AST fails (e.g. dynamic code), `analyzeHandler` is good.\n // Let's treat `analyzeHandler` as part of Step 5 (Runtime/Decorator logic) or just merge it in.\n const { inferredSpec } = analyzeHandler(route.handler);\n if (inferredSpec) {\n if (inferredSpec.parameters) {\n const existingParams = operation.parameters || [];\n const mergedParams = [...existingParams];\n\n for (const p of inferredSpec.parameters) {\n const idx = mergedParams.findIndex((ep: any) => ep.name === p.name && ep.in === p.in);\n if (idx >= 0) {\n mergedParams[idx] = deepMerge(mergedParams[idx], p);\n } else {\n mergedParams.push(p);\n }\n }\n operation.parameters = mergedParams;\n delete inferredSpec.parameters;\n }\n deepMerge(operation, inferredSpec);\n }\n\n // Merge metadata from runtime route definition (Manual override)\n if (route.handlerSpec) {\n const spec = route.handlerSpec;\n if (spec.summary) operation.summary = spec.summary;\n if (spec.description) operation.description = spec.description;\n if (spec.operationId) operation.operationId = spec.operationId;\n if (spec.tags) operation.tags = spec.tags;\n if (spec.security) operation.security = spec.security;\n\n // Merge responses\n if (spec.responses) {\n operation.responses = { ...operation.responses, ...spec.responses };\n }\n }\n\n // Apply tags\n if (!operation.tags || operation.tags.length === 0) operation.tags = [tag];\n\n if (operation.tags) {\n operation.tags = Array.from(new Set(operation.tags));\n for (const t of operation.tags) {\n if (!tagGroups.has(routeGroup)) tagGroups.set(routeGroup, new Set());\n tagGroups.get(routeGroup)?.add(t);\n }\n }\n\n const methodLower = route.method.toLowerCase();\n if (methodLower === \"all\") {\n [\"get\", \"post\", \"put\", \"delete\", \"patch\"].forEach(m => {\n if (!paths[fullPath][m]) paths[fullPath][m] = { ...operation };\n });\n }\n else {\n paths[fullPath][methodLower] = operation;\n }\n };\n\n for (const controller of router[$childControllers]) {\n const controllerName = controller.constructor.name || \"UnknownController\";\n tagGroups.get(group)?.add(controllerName);\n }\n\n for (const child of router[$childRouters]) {\n const mountPath = child[$mountPath];\n const cleanPrefix = prefix.endsWith(\"/\") ? prefix.slice(0, -1) : prefix;\n const cleanMount = mountPath.startsWith(\"/\") ? mountPath : \"/\" + mountPath;\n const nextPrefix = (cleanPrefix + cleanMount) || \"/\";\n collect(child, nextPrefix, group, tag);\n }\n };\n\n collect(rootRouter);\n\n const xTagGroups: { name: string; tags: string[]; }[] = [];\n for (const [name, tags] of tagGroups) {\n xTagGroups.push({ name, tags: Array.from(tags).sort() });\n }\n\n return {\n openapi: \"3.1.0\",\n info: { title: \"Shokupan API\", version: \"1.0.0\", ...options.info },\n paths,\n components: options.components,\n servers: options.servers,\n tags: options.tags,\n externalDocs: options.externalDocs,\n \"x-tagGroups\": xTagGroups\n };\n}\n","import { Eta } from 'eta';\nimport { readdir, stat } from 'fs/promises';\nimport { basename, join, resolve } from 'path';\nimport type { ShokupanContext } from '../context';\nimport type { StaticServeOptions } from '../types';\n\nconst eta = new Eta();\n\nexport function serveStatic<T extends Record<string, any>>(ctx: ShokupanContext<T>, config: StaticServeOptions<T>, prefix: string) {\n const rootPath = resolve(config.root || \".\");\n const normalizedPrefix = prefix.endsWith('/') && prefix !== '/' ? prefix.slice(0, -1) : prefix;\n\n return async () => {\n // 1. Calculate relative path\n // ctx.path is full path.\n // If prefix is /static, and path is /static/foo.css, relative is /foo.css\n let relative = ctx.path.slice(normalizedPrefix.length);\n if (!relative.startsWith('/') && relative.length > 0) relative = '/' + relative;\n if (relative.length === 0) relative = '/';\n\n // Decode URI components\n relative = decodeURIComponent(relative);\n\n // Security: Prevent directory traversal\n const requestPath = join(rootPath, relative);\n if (!requestPath.startsWith(rootPath)) {\n return ctx.json({ error: 'Forbidden' }, 403);\n }\n\n // check if path includes null byte\n if (requestPath.includes('\\0')) {\n return ctx.json({ error: 'Forbidden' }, 403);\n }\n\n // Hooks: onRequest\n if (config.hooks?.onRequest) {\n const res = await config.hooks.onRequest(ctx);\n if (res) return res;\n }\n\n // Check Excludes\n if (config.exclude) {\n for (const pattern of config.exclude) {\n if (pattern instanceof RegExp) {\n if (pattern.test(relative)) return ctx.json({ error: 'Forbidden' }, 403);\n } else if (typeof pattern === 'string') {\n if (relative.includes(pattern)) return ctx.json({ error: 'Forbidden' }, 403);\n }\n }\n }\n\n // Dotfiles\n if (basename(requestPath).startsWith('.')) {\n const behavior = config.dotfiles || 'ignore';\n if (behavior === 'deny') return ctx.json({ error: 'Forbidden' }, 403);\n if (behavior === 'ignore') return ctx.json({ error: 'Not Found' }, 404);\n }\n\n let finalPath = requestPath;\n let stats;\n\n try {\n stats = await stat(requestPath);\n } catch (e) {\n // Path not found. Try extensions.\n if (config.extensions) {\n for (const ext of config.extensions) {\n const p = requestPath + (ext.startsWith('.') ? ext : '.' + ext);\n try {\n const s = await stat(p);\n if (s.isFile()) {\n finalPath = p;\n stats = s;\n break;\n }\n } catch { }\n }\n }\n if (!stats) return ctx.json({ error: 'Not Found' }, 404);\n }\n\n // Directory handling\n if (stats.isDirectory()) {\n // Return 302 Redirect to add trailing slash if missing and not root\n // This ensures relative paths in served files work correctly.\n if (!ctx.path.endsWith('/')) {\n const query = ctx.url.search;\n return ctx.redirect(ctx.path + '/' + query, 302);\n }\n\n // Try indexes\n let indexes: string[] = [];\n if (config.index === undefined) {\n indexes = ['index.html', 'index.htm'];\n }\n else if (Array.isArray(config.index)) {\n indexes = config.index;\n }\n else if (config.index) {\n indexes = [config.index];\n }\n\n let foundIndex = false;\n for (const idx of indexes) {\n const idxPath = join(finalPath, idx);\n try {\n const idxStats = await stat(idxPath);\n if (idxStats.isFile()) {\n finalPath = idxPath;\n foundIndex = true;\n break;\n }\n } catch { }\n }\n\n if (!foundIndex) {\n if (config.listDirectory) {\n // List directory\n try {\n const files = await readdir(requestPath);\n // Simple HTML listing\n const listing = eta.renderString(`\n <!DOCTYPE html>\n <html>\n <head>\n <title>Index of <%= it.relative %></title>\n <style>\n body { font-family: system-ui, -apple-system, sans-serif; padding: 2rem; max-width: 800px; margin: 0 auto; }\n ul { list-style: none; padding: 0; }\n li { padding: 0.5rem 0; border-bottom: 1px solid #eee; }\n a { text-decoration: none; color: #0066cc; }\n a:hover { text-decoration: underline; }\n h1 { font-size: 1.5rem; margin-bottom: 1rem; }\n </style>\n </head>\n <body>\n <h1>Index of <%= it.relative %></h1>\n <ul>\n <% if (it.relative !== '/') { %>\n <li><a href=\"../\">../</a></li>\n <% } %>\n <% it.files.forEach(function(f) { %>\n <li><a href=\"<%= f %>\"><%= f %></a></li>\n <% }) %>\n </ul>\n </body>\n </html>\n `, { relative, files, join });\n return new Response(listing, { headers: { 'Content-Type': 'text/html' } });\n } catch (e) {\n return ctx.json({ error: 'Internal Server Error' }, 500);\n }\n } else {\n // If no index and no listing, it's 404 or 403. typically 404/403.\n // Nginx returns 403 Forbidden.\n return ctx.json({ error: 'Forbidden' }, 403);\n }\n }\n }\n\n // Serving File\n // @ts-ignore\n const file = Bun.file(finalPath);\n let response = new Response(file);\n\n if (config.hooks?.onResponse) {\n const hooked = await config.hooks.onResponse(ctx, response);\n if (hooked) response = hooked;\n }\n return response;\n };\n}\n","\nimport { AsyncLocalStorage } from \"node:async_hooks\";\n\nexport const asyncContext = new AsyncLocalStorage<Map<string, any>>();\n\nexport function runInContext<T>(callback: () => T, initialStore = new Map<string, any>()): T {\n return asyncContext.run(initialStore, callback);\n}\n","import { ShokupanContext } from './context';\nimport { Container } from './di';\nimport { compose } from './middleware';\nimport { generateOpenApi } from './plugins/openapi';\nimport { serveStatic } from './plugins/serve-static';\nimport { ShokupanRequest } from './request';\nimport type { Shokupan } from './shokupan';\nimport { $appRoot, $childControllers, $childRouters, $controllerPath, $dispatch, $isApplication, $isMounted, $isRouter, $middleware, $mountPath, $parent, $routeArgs, $routeMethods, $routes, $routeSpec } from './symbol';\nimport type { GuardAPISpec, MethodAPISpec, OpenAPIOptions, ProcessResult, RequestOptions, ShokupanRouteConfig, StaticServeOptions } from './types';\nimport { HTTPMethods, RouteParamType, type JSXRenderer, type Method, type ShokupanController, type ShokupanHandler, type ShokupanRoute } from './types';\nimport { asyncContext } from './util/async-hooks';\nimport { traceHandler } from './util/instrumentation';\n\n\n// Shim for HeadersInit if not available globally\ntype HeadersInit = Headers | Record<string, string> | [string, string][];\n\n\nexport const RouterRegistry = new Map<string, ShokupanRouter<any>>();\n\nexport const ShokupanApplicationTree = {};\n\nexport class ShokupanRouter<T extends Record<string, any> = Record<string, any>> {\n // Internal marker to identify Router vs. Application\n private [$isApplication]: boolean = false;\n private [$isMounted]: boolean = false;\n private [$isRouter]: true = true;\n private [$appRoot]: Shokupan;\n public [$mountPath]: string = \"/\"; // Public via Symbol for OpenAPI generator\n\n private [$parent]: ShokupanRouter<T> | null = null;\n public [$childRouters]: ShokupanRouter<T>[] = [];\n public [$childControllers]: ShokupanController[] = [];\n\n get rootConfig() {\n return this[$appRoot]?.applicationConfig;\n }\n get root() {\n return this[$appRoot];\n }\n\n public [$routes]: ShokupanRoute[] = []; // Public via Symbol for OpenAPI generator\n\n private currentGuards: { handler: ShokupanHandler<T>; spec?: GuardAPISpec; }[] = [];\n\n constructor(\n public readonly config?: ShokupanRouteConfig\n ) {\n if (config?.requestTimeout) {\n this.requestTimeout = config.requestTimeout;\n }\n }\n\n private isRouterInstance(target: any): target is ShokupanRouter<T> {\n // Check if it's an object and has your specific symbol\n return typeof target === 'object' && target !== null && $isRouter in target;\n }\n\n /**\n * Mounts a controller instance to a path prefix.\n * \n * Controller can be a convection router or an arbitrary class.\n * \n * Routes are derived from method names:\n * - get(ctx) -> GET /prefix/\n * - getUsers(ctx) -> GET /prefix/users\n * - postCreate(ctx) -> POST /prefix/create\n */\n public mount(prefix: string, controller: ShokupanController | ShokupanController<T> | ShokupanRouter | ShokupanRouter<T> | Record<string, any>) {\n // strict controller check\n const isRouter = this.isRouterInstance(controller);\n const isFunction = typeof controller === 'function';\n const controllersOnly = this.config?.controllersOnly ?? this.rootConfig?.controllersOnly ?? false;\n\n if (controllersOnly && !isFunction && !isRouter) {\n throw new Error(`[Shokupan] strict controller check failed: ${controller.constructor.name || typeof controller} is not a class constructor.`);\n }\n\n if (this.isRouterInstance(controller)) {\n if (controller[$isMounted]) {\n throw new Error(\"Router is already mounted\");\n }\n\n controller[$mountPath] = prefix;\n this[$childRouters].push(controller);\n\n /**\n * Descendants are defined first, then mounted backwards up to the application root.\n * Thus, we have to recurse through the children and assign the root reference.\n */\n controller[$parent] = this;\n\n const setRouterContext = (router: ShokupanRouter<T>) => {\n router[$appRoot] = this.root;\n router[$childRouters].forEach((child) => setRouterContext(child));\n };\n setRouterContext(controller);\n\n\n // If the controller is the root router\n if (this[$appRoot]) {\n // TODO:\n }\n controller[$appRoot] = this.root;\n controller[$isMounted] = true;\n }\n // Controller is an arbitrary class\n else {\n let instance = controller;\n if (typeof controller === 'function') {\n // DI Resolution\n instance = Container.resolve(controller as any);\n\n // Controller Parameter Decorator (@Controller('prefix'))\n const controllerPath = (controller as any)[$controllerPath];\n if (controllerPath) {\n // Combine mount prefix + controller path\n // mount('/api', Ctrl) + @Controller('/users') -> /api/users\n const p1 = prefix.endsWith(\"/\") ? prefix.slice(0, -1) : prefix;\n const p2 = controllerPath.startsWith(\"/\") ? controllerPath : \"/\" + controllerPath;\n prefix = (p1 + p2);\n // Normalize\n if (!prefix) prefix = \"/\";\n }\n }\n else {\n // Controller is an instance, read metadata from constructor\n const ctor = instance.constructor;\n const controllerPath = (ctor as any)[$controllerPath];\n if (controllerPath) {\n const p1 = prefix.endsWith(\"/\") ? prefix.slice(0, -1) : prefix;\n const p2 = controllerPath.startsWith(\"/\") ? controllerPath : \"/\" + controllerPath;\n prefix = (p1 + p2);\n if (!prefix) prefix = \"/\";\n }\n }\n\n instance[$mountPath] = prefix;\n this[$childControllers].push(instance as any);\n\n // Get Middleware for Controller\n // It could be on the Constructor (if passed as class) or Instance (if passed as object and manually set?)\n // Usually decorators set it on Constructor.\n const controllerMiddleware = (typeof controller === 'function' ? (controller as any)[$middleware] : (instance as any)[$middleware]) || [];\n\n // Get all method names from the prototype (for classes)\n const proto = Object.getPrototypeOf(instance);\n const methods = new Set<string>();\n\n // Scan prototype chain\n let current = proto;\n while (current && current !== Object.prototype) {\n Object.getOwnPropertyNames(current).forEach(name => methods.add(name));\n current = Object.getPrototypeOf(current);\n }\n // Also scan own properties (for objects or bound methods)\n Object.getOwnPropertyNames(instance).forEach(name => methods.add(name));\n\n const decoratedRoutes = (instance as any)[$routeMethods] || (proto && (proto as any)[$routeMethods]);\n const decoratedArgs = (instance as any)[$routeArgs] || (proto && (proto as any)[$routeArgs]);\n const methodMiddlewareMap = (instance as any)[$middleware] || (proto && (proto as any)[$middleware]);\n\n let routesAttached = 0;\n for (const name of methods) {\n if (name === \"constructor\") continue;\n if ([\"arguments\", \"caller\", \"callee\"].includes(name)) continue;\n\n const originalHandler = (instance as any)[name];\n if (typeof originalHandler !== \"function\") continue;\n\n let method: Method | undefined;\n let subPath = \"\";\n\n // 1. Check for Decorator Metadata\n if (decoratedRoutes && decoratedRoutes.has(name)) {\n const config = decoratedRoutes.get(name);\n method = config.method;\n subPath = config.path;\n }\n // 2. Fallback to Convention\n else {\n // Simple convention matching\n // Check if name starts with HTTP verb\n for (const m of HTTPMethods) {\n if (name.toUpperCase().startsWith(m)) {\n method = m as Method;\n const rest = name.slice(m.length);\n if (rest.length === 0) {\n subPath = \"/\";\n }\n else {\n // Existing parsing logic...\n subPath = \"\";\n let buffer = \"\";\n const flush = () => {\n if (buffer.length > 0) {\n subPath += \"/\" + buffer.toLowerCase();\n buffer = \"\";\n }\n };\n for (let i = 0; i < rest.length; i++) {\n const char = rest[i];\n if (char === \"$\") {\n flush();\n subPath += \"/:\";\n continue;\n }\n // Revised simple loop\n }\n subPath = rest\n .replace(/\\$/g, \"/:\") // $id -> /:id\n .replace(/([a-z0-9])([A-Z])/g, \"$1/$2\") // camelCase -> camel/Case\n .toLowerCase();\n\n if (!subPath.startsWith(\"/\")) {\n subPath = \"/\" + subPath;\n }\n }\n break;\n }\n }\n }\n\n if (method) {\n routesAttached++;\n // Remove trailing slash from prefix if needed, combine with subPath\n const cleanPrefix = prefix.endsWith(\"/\") ? prefix.slice(0, -1) : prefix;\n const cleanSubPath = subPath === \"/\" ? \"\" : subPath;\n\n let joined: string;\n if (cleanSubPath.length === 0) {\n joined = cleanPrefix;\n }\n else if (cleanSubPath.startsWith(\"/\")) {\n joined = cleanPrefix + cleanSubPath;\n }\n else {\n joined = cleanPrefix + \"/\" + cleanSubPath;\n }\n\n const fullPath = joined || \"/\";\n const normalizedPath = fullPath.replace(/\\/+/g, \"/\");\n\n // -- Compose Handler with Middleware and Param Resolution --\n\n const methodMw = (methodMiddlewareMap instanceof Map) ? (methodMiddlewareMap.get(name) || []) : [];\n const allMiddleware = [...controllerMiddleware, ...methodMw];\n\n // Check for Args\n const routeArgs = decoratedArgs && decoratedArgs.get(name);\n\n // Create Wrapper\n const wrappedHandler = async (ctx: ShokupanContext<T>) => {\n // Resolve Arguments\n let args: any[] = [ctx]; // Default to just context if no decorators\n\n if (routeArgs?.length > 0) {\n args = [];\n // Sort by index\n const sortedArgs = [...routeArgs].sort((a, b) => a.index - b.index);\n\n // Fill args array\n for (const arg of sortedArgs) {\n switch (arg.type) {\n case RouteParamType.BODY:\n args[arg.index] = await ctx.req.json().catch(() => ({}));\n break;\n case RouteParamType.PARAM:\n args[arg.index] = arg.name ? ctx.params[arg.name] : ctx.params;\n break;\n case RouteParamType.QUERY: {\n const url = new URL(ctx.req.url);\n args[arg.index] = arg.name ? url.searchParams.get(arg.name) : Object.fromEntries(url.searchParams);\n break;\n }\n case RouteParamType.HEADER:\n args[arg.index] = arg.name ? ctx.req.headers.get(arg.name) : ctx.req.headers;\n break;\n case RouteParamType.REQUEST:\n args[arg.index] = ctx.req;\n break;\n case RouteParamType.CONTEXT:\n args[arg.index] = ctx;\n break;\n }\n }\n }\n\n const tracedOriginalHandler = traceHandler(originalHandler, normalizedPath);\n return tracedOriginalHandler.apply(instance, args);\n };\n\n // Apply Middleware wrapping\n let finalHandler = wrappedHandler;\n if (allMiddleware.length > 0) {\n const composed = compose(allMiddleware);\n finalHandler = async (ctx) => {\n return composed(ctx, () => wrappedHandler(ctx));\n };\n }\n\n // Expose original handler for OpenAPI analysis\n (finalHandler as any).originalHandler = originalHandler;\n if (finalHandler !== wrappedHandler) {\n (wrappedHandler as any).originalHandler = originalHandler;\n }\n\n // Inject Controller Name as Tag\n const tagName = instance.constructor.name;\n\n // Retrieve @Spec metadata\n const decoratedSpecs = (instance as any)[$routeSpec] || (proto && (proto as any)[$routeSpec]);\n const userSpec = decoratedSpecs && decoratedSpecs.get(name);\n\n // Merge with existing spec from decorator if available\n const spec = { tags: [tagName], ...userSpec };\n\n this.add({ method, path: normalizedPath, handler: finalHandler, spec });\n }\n }\n if (routesAttached === 0) {\n console.warn(`No routes attached to controller ${instance.constructor.name}`);\n }\n instance[$isMounted] = true;\n }\n\n return this;\n }\n\n /**\n * Returns all routes attached to this router and its descendants.\n */\n public getRoutes(): { method: Method, path: string, handler: ShokupanHandler<T>; }[] {\n const routes = this[$routes].map(r => ({\n method: r.method,\n path: r.path,\n handler: r.handler\n }));\n\n for (const child of this[$childRouters]) {\n const childRoutes = child.getRoutes();\n for (const route of childRoutes) {\n const cleanPrefix = child[$mountPath].endsWith(\"/\") ? child[$mountPath].slice(0, -1) : child[$mountPath];\n const cleanPath = route.path.startsWith(\"/\") ? route.path : \"/\" + route.path;\n const fullPath = (cleanPrefix + cleanPath) || \"/\";\n\n routes.push({\n method: route.method as Method,\n path: fullPath,\n handler: route.handler\n });\n }\n }\n return routes;\n }\n\n /**\n * Makes a sub request to this router.\n * This is useful for triggering other methods or route handlers. \n * @param options The request options.\n * @returns The response.\n */\n public async subRequest(arg: {\n path: string;\n method?: Method;\n headers?: HeadersInit;\n body?: any;\n } | string): Promise<Response> {\n const options = typeof arg === \"string\" ? { path: arg } : arg;\n\n const store = asyncContext.getStore();\n const originalReq = store?.get(\"req\") as ShokupanRequest<T>;\n\n let url = options.path;\n // If path is relative, make it absolute (required by Request constructor)\n if (!url.startsWith(\"http\")) {\n const base = `http://${this.rootConfig?.hostname || \"localhost\"}:${this.rootConfig.port || 3000}`;\n\n // Ensure path starts with /\n const path = url.startsWith(\"/\") ? url : \"/\" + url;\n url = base + path;\n }\n\n const req = new ShokupanRequest({\n method: options.method || \"GET\",\n url,\n headers: options.headers as any,\n body: options.body ? JSON.stringify(options.body) : undefined\n });\n\n return this.root[$dispatch](req);\n }\n\n /**\n * Processes a request directly.\n */\n public async processRequest(options: RequestOptions): Promise<ProcessResult> {\n let url = options.url || options.path || \"/\";\n if (!url.startsWith(\"http\")) {\n const base = `http://${this.rootConfig?.hostname || \"localhost\"}:${this.rootConfig?.port || 3000}`;\n const path = url.startsWith(\"/\") ? url : \"/\" + url;\n url = base + path;\n }\n\n // Handle query params in options\n if (options.query) {\n const u = new URL(url);\n for (const [k, v] of Object.entries(options.query)) {\n u.searchParams.set(k, v);\n }\n url = u.toString();\n }\n\n const req = new ShokupanRequest({\n method: (options.method || \"GET\") as Method,\n url,\n headers: options.headers as any,\n body: options.body && typeof options.body === \"object\" ? JSON.stringify(options.body) : options.body\n });\n\n // Basic Dispatch Logic (moved/duplicated from Shokupan.handleRequest but simpler for pure Router)\n // Note: Pure Routers don't have global middleware usually, but if we call processRequest on them, \n // we just run their routing logic.\n // HOWEVER, Shokupan.override will invoke middleware.\n\n const ctx = new ShokupanContext<T>(req);\n\n let result: any = null;\n let status = 200;\n const headers: Record<string, string> = {};\n\n const match = this.find(req.method, ctx.path);\n if (match) {\n ctx.params = match.params;\n try {\n result = await match.handler(ctx);\n } catch (err: any) {\n console.error(err);\n status = err.status || err.statusCode || 500;\n result = { error: err.message || \"Internal Server Error\" };\n if (err.errors) result.errors = err.errors;\n }\n }\n else {\n status = 404;\n result = \"Not Found\";\n }\n\n // Normalize Result\n // If result is Response object, we need to read it back to ProcessResult?\n // The user wants { status, headers, data }.\n // If handler returns Response, we extract data.\n\n if (result instanceof Response) {\n status = result.status;\n result.headers.forEach((v, k) => headers[k] = v);\n\n if (headers['content-type']?.includes('application/json')) {\n result = await result.json();\n }\n else {\n result = await result.text();\n }\n }\n\n return {\n status,\n headers,\n data: result\n };\n }\n\n private applyHooks(match: { handler: ShokupanHandler<T>; params: Record<string, string>; }) {\n if (!this.config?.hooks) return match;\n\n const hooks = this.config.hooks;\n const originalHandler = match.handler;\n\n match.handler = async (ctx: ShokupanContext<T>) => {\n if (hooks.onRequestStart) await hooks.onRequestStart(ctx);\n try {\n const result = await originalHandler(ctx);\n if (hooks.onRequestEnd) await hooks.onRequestEnd(ctx);\n return result;\n } catch (err) {\n if (hooks.onError) {\n try {\n await hooks.onError(err, ctx);\n } catch (e) {\n console.error(\"Error in router onError hook:\", e);\n }\n }\n throw err;\n }\n };\n // Preserve original handler reference for analysis if needed\n (match.handler as any).originalHandler = (originalHandler as any).originalHandler || originalHandler;\n\n return match;\n }\n\n /**\n * Find a route matching the given method and path.\n * @param method HTTP method\n * @param path Request path\n * @returns Route handler and parameters if found, otherwise null\n */\n public find(method: string, path: string): { handler: ShokupanHandler<T>; params: Record<string, string>; } | null {\n // console.log(`[Router] find ${method} ${path} (routes: ${this.routes.length}, children: ${this[$childRouters].length})`);\n\n // 1. Check local routes\n for (const route of this[$routes]) {\n if (route.method !== \"ALL\" && route.method !== method) continue;\n\n const match = route.regex.exec(path);\n if (match) {\n // console.log(` -> Matched route ${route.path}`);\n const params: Record<string, string> = {};\n route.keys.forEach((key, index) => {\n params[key] = match[index + 1];\n });\n return this.applyHooks({ handler: route.handler, params });\n }\n }\n\n // 2. Check child routers\n for (const child of this[$childRouters]) {\n const prefix = child[$mountPath];\n // console.log(` -> Checking child prefix ${prefix}`);\n\n if (path === prefix || path.startsWith(prefix + \"/\")) {\n const subPath = path.slice(prefix.length) || \"/\";\n const match = child.find(method, subPath);\n if (match) return this.applyHooks(match);\n }\n // Handle case where prefix ends with /\n if (prefix.endsWith(\"/\")) {\n if (path.startsWith(prefix)) {\n const subPath = path.slice(prefix.length) || \"/\";\n const match = child.find(method, subPath);\n if (match) return this.applyHooks(match);\n }\n }\n }\n\n return null; // Not found\n }\n\n private parsePath(path: string): { regex: RegExp; keys: string[]; } {\n const keys: string[] = [];\n const pattern = path\n .replace(/:([a-zA-Z0-9_]+)/g, (_, key) => {\n keys.push(key);\n return \"([^/]+)\";\n })\n .replace(/\\*/g, \".*\"); // Wildcard support\n\n return {\n regex: new RegExp(`^${pattern}$`),\n keys\n };\n }\n\n // --- Functional Routing ---\n\n public requestTimeout?: number;\n\n /**\n * Adds a route to the router.\n * \n * @param method - HTTP method\n * @param path - URL path\n * @param spec - OpenAPI specification for the route\n * @param handler - Route handler function\n * @param requestTimeout - Timeout for this route in milliseconds\n */\n public add({ method, path, spec, handler, regex: customRegex, group, requestTimeout, renderer }: {\n method: Method,\n path: string,\n spec?: MethodAPISpec,\n handler: ShokupanHandler<T>;\n regex?: RegExp;\n group?: string;\n requestTimeout?: number;\n renderer?: JSXRenderer;\n }) {\n const { regex, keys } = customRegex\n ? { regex: customRegex, keys: [] }\n : this.parsePath(path);\n\n // Wrap handler with current guards if any exist\n let wrappedHandler = handler;\n const routeGuards = [...this.currentGuards];\n\n // Wrap for Timeout\n // Logic: specific route timeout > router timeout > global config timeout\n // 0 means disabled, but undefined means \"inherit\".\n // Actually, 0 usually means \"no timeout\" (infinite).\n // Let's assume if explicit 0 is passed, it disables.\n // If undefined, fallback.\n const effectiveTimeout = requestTimeout ?? this.requestTimeout ?? this.rootConfig?.requestTimeout;\n\n if (effectiveTimeout !== undefined && effectiveTimeout > 0) {\n const originalHandler = wrappedHandler;\n wrappedHandler = async (ctx: ShokupanContext<T>) => {\n if (ctx.server) {\n // Bun.server.timeout takes seconds\n ctx.server.timeout(ctx.req as unknown as Request, effectiveTimeout / 1000);\n }\n return originalHandler(ctx);\n };\n // Preserve original handler reference for analysis if needed\n (wrappedHandler as any).originalHandler = (originalHandler as any).originalHandler || originalHandler;\n }\n\n if (routeGuards.length > 0) {\n const innerHandler = wrappedHandler;\n wrappedHandler = async (ctx: ShokupanContext<T>) => {\n // Execute guards in order\n for (const guard of routeGuards) {\n let guardPassed = false;\n let nextCalled = false;\n\n // Create next function for middleware-style guards\n const next = () => {\n nextCalled = true;\n return Promise.resolve();\n };\n\n try {\n const result = await guard.handler(ctx, next);\n\n // Check if guard explicitly returned true or called next()\n if (result === true || nextCalled) {\n guardPassed = true;\n }\n // If guard returned a response, return it (short-circuit)\n else if (result !== undefined && result !== null && result !== false) {\n return result;\n }\n // If guard returned false or nothing, block the request\n else {\n return ctx.json({ error: 'Forbidden' }, 403);\n }\n }\n catch (error) {\n // If guard throws, propagate the error to error handling\n throw error;\n }\n\n if (!guardPassed) {\n return ctx.json({ error: 'Forbidden' }, 403);\n }\n }\n\n // All guards passed, execute the actual handler\n return innerHandler(ctx);\n };\n }\n\n // Inject Renderer\n const effectiveRenderer = renderer ?? this.config?.renderer ?? this.rootConfig?.renderer;\n if (effectiveRenderer) {\n const innerHandler = wrappedHandler;\n wrappedHandler = async (ctx: ShokupanContext<T>) => {\n ctx.renderer = effectiveRenderer;\n return innerHandler(ctx);\n };\n }\n\n this[$routes].push({\n method,\n path,\n regex,\n keys,\n handler: wrappedHandler,\n handlerSpec: spec,\n group,\n guards: routeGuards.length > 0 ? routeGuards : undefined,\n requestTimeout: effectiveTimeout // Save for inspection? Or just relying on closure\n });\n\n return this;\n }\n\n /**\n * Adds a GET route to the router.\n * \n * @param path - URL path \n * @param handler - Route handler function \n */\n public get(path: string, ...handlers: ShokupanHandler<T>[]);\n /**\n * Adds a GET route to the router.\n * \n * @param path - URL path \n * @param spec - OpenAPI specification for the route\n * @param handlers - Route handler functions \n */\n public get(path: string, spec: MethodAPISpec, ...handlers: ShokupanHandler<T>[]);\n public get(path: string, ...args: (MethodAPISpec | ShokupanHandler<T>)[]) {\n this.attachVerb(\"GET\", path, ...args);\n return this;\n }\n\n /**\n * Adds a POST route to the router.\n * \n * @param path - URL path \n * @param handler - Route handler function \n */\n public post(path: string, ...handlers: ShokupanHandler<T>[]);\n /**\n * Adds a POST route to the router.\n * \n * @param path - URL path \n * @param spec - OpenAPI specification for the route\n * @param handlers - Route handler functions \n */\n public post(path: string, spec: MethodAPISpec, ...handlers: ShokupanHandler<T>[]);\n public post(path: string, ...args: (MethodAPISpec | ShokupanHandler<T>)[]) {\n this.attachVerb(\"POST\", path, ...args);\n return this;\n }\n\n /**\n * Adds a PUT route to the router.\n * \n * @param path - URL path \n * @param handler - Route handler function \n */\n public put(path: string, ...handlers: ShokupanHandler<T>[]);\n /**\n * Adds a PUT route to the router.\n * \n * @param path - URL path \n * @param spec - OpenAPI specification for the route\n * @param handlers - Route handler functions \n */\n public put(path: string, spec: MethodAPISpec, ...handlers: ShokupanHandler<T>[]);\n public put(path: string, ...args: (MethodAPISpec | ShokupanHandler<T>)[]) {\n this.attachVerb(\"PUT\", path, ...args);\n return this;\n }\n\n /**\n * Adds a DELETE route to the router.\n * \n * @param path - URL path \n * @param handler - Route handler function \n */\n public delete(path: string, ...handlers: ShokupanHandler<T>[]);\n /**\n * Adds a DELETE route to the router.\n * \n * @param path - URL path \n * @param spec - OpenAPI specification for the route\n * @param handlers - Route handler functions \n */\n public delete(path: string, spec: MethodAPISpec, ...handlers: ShokupanHandler<T>[]);\n public delete(path: string, ...args: (MethodAPISpec | ShokupanHandler<T>)[]) {\n this.attachVerb(\"DELETE\", path, ...args);\n return this;\n }\n\n /**\n * Adds a PATCH route to the router.\n * \n * @param path - URL path \n * @param handler - Route handler function \n */\n public patch(path: string, ...handlers: ShokupanHandler<T>[]);\n /**\n * Adds a PATCH route to the router.\n * \n * @param path - URL path \n * @param spec - OpenAPI specification for the route\n * @param handlers - Route handler functions \n */\n public patch(path: string, spec: MethodAPISpec, ...handlers: ShokupanHandler<T>[]);\n public patch(path: string, ...args: (MethodAPISpec | ShokupanHandler<T>)[]) {\n this.attachVerb(\"PATCH\", path, ...args);\n return this;\n }\n\n /**\n * Adds a OPTIONS route to the router.\n * \n * @param path - URL path \n * @param handler - Route handler function \n */\n public options(path: string, ...handlers: ShokupanHandler<T>[]);\n /**\n * Adds a OPTIONS route to the router.\n * \n * @param path - URL path \n * @param spec - OpenAPI specification for the route\n * @param handlers - Route handler functions \n */\n public options(path: string, spec: MethodAPISpec, ...handlers: ShokupanHandler<T>[]);\n public options(path: string, ...args: (MethodAPISpec | ShokupanHandler<T>)[]) {\n this.attachVerb(\"OPTIONS\", path, ...args);\n return this;\n }\n\n /**\n * Adds a HEAD route to the router.\n * \n * @param path - URL path \n * @param handler - Route handler function \n */\n public head(path: string, ...handlers: ShokupanHandler<T>[]);\n /**\n * Adds a HEAD route to the router.\n * \n * @param path - URL path \n * @param spec - OpenAPI specification for the route\n * @param handlers - Route handler functions \n */\n public head(path: string, spec: MethodAPISpec, ...handlers: ShokupanHandler<T>[]);\n public head(path: string, ...args: (MethodAPISpec | ShokupanHandler<T>)[]) {\n this.attachVerb(\"HEAD\", path, ...args);\n return this;\n }\n\n /**\n * Adds a guard to the router that applies to all routes added **after** this point.\n * Guards must return true or call `ctx.next()` to allow the request to continue.\n * \n * @param handler - Guard handler function \n */\n public guard(handler: ShokupanHandler<T>): void;\n /**\n * Adds a guard to the router that applies to all routes added **after** this point.\n * Guards must return true or call `ctx.next()` to allow the request to continue.\n \n * @param spec - OpenAPI specification for the guard\n * @param handler - Guard handler function \n */\n public guard(spec: GuardAPISpec, handler: ShokupanHandler<T>);\n public guard(specOrHandler: GuardAPISpec | ShokupanHandler<T>, handler?: ShokupanHandler<T>) {\n const spec = typeof specOrHandler === \"function\" ? undefined : specOrHandler as GuardAPISpec;\n const guardHandler = typeof specOrHandler === \"function\" ? specOrHandler as ShokupanHandler<T> : handler as ShokupanHandler<T>;\n\n this.currentGuards.push({ handler: guardHandler, spec });\n\n return this;\n }\n\n /**\n * Statically serves a directory with standard options.\n * @param uriPath URL path prefix\n * @param options Configuration options or root directory string\n */\n public static(uriPath: string, options: string | StaticServeOptions<T>) {\n const config: StaticServeOptions<T> = typeof options === 'string' ? { root: options } : options;\n // Normalize path prefix to ensure it has leading slash and no trailing slash for consistent matching\n const prefix = uriPath.startsWith('/') ? uriPath : '/' + uriPath;\n const normalizedPrefix = prefix.endsWith('/') && prefix !== '/' ? prefix.slice(0, -1) : prefix;\n\n const handler = serveStatic(null as any, config, prefix); // Note: bind context later? \n // Wait, serveStatic returns a handler: (ctx) => Promise<Response>\n // But here we need to insert it into `this.add`.\n // `serveStatic` implementation above takes `ctx` as first arg. \n // We probably want `serveStatic` to RETURN a handler, OR adapt it.\n\n // Let's look at how serveStatic was implemented in plugins/serve-static.ts\n // export function serveStatic<T>(ctx: ShokupanContext<T>, config: StaticServeOptions<T>, prefix: string) { ... return async () => { ... } }\n // It seems `serveStatic` IS a factory that returns a \"runner\" but it takes `ctx` immediately?\n // Wait, looking at the previous file content for serveStatic:\n // export function serveStatic<T>(ctx: ShokupanContext<T>, config: StaticServeOptions<T>, prefix: string)\n\n // That seems wrong for a Router method that delegates. \n // The router adds a handler `(ctx) => ...`.\n // So we need `(ctx) => serveStatic(ctx, config, prefix)`.\n // But `serveStatic` as implemented returns `async () => { ... }`.\n\n // Correct usage of the new plugin:\n const routeHandler = async (ctx: ShokupanContext<T>) => {\n // The plugin returns a function that executes the logic\n const runner = serveStatic(ctx, config, prefix);\n return runner();\n };\n\n // Derive Group/Tag name from the path's last segment\n // e.g. /assets -> Assets\n let groupName = \"Static\";\n const segments = normalizedPrefix.split('/').filter(Boolean);\n if (segments.length > 0) {\n const last = segments[segments.length - 1];\n groupName = last.charAt(0).toUpperCase() + last.slice(1);\n }\n\n const defaultSpec = {\n summary: \"Static Content\",\n description: \"Serves static files from \" + normalizedPrefix,\n tags: [groupName]\n };\n const spec = config.openapi ? config.openapi : defaultSpec;\n if (!spec.tags) spec.tags = [groupName];\n else if (!spec.tags.includes(groupName)) spec.tags.push(groupName);\n\n const pattern = `^${normalizedPrefix}(/.*)?$`;\n const regex = new RegExp(pattern);\n\n // Display path in OpenAPI as /prefix/*\n const displayPath = normalizedPrefix === '/' ? '/*' : normalizedPrefix + '/*';\n\n this.add({ method: 'GET', path: displayPath, handler: routeHandler, spec, regex });\n this.add({ method: 'HEAD', path: displayPath, handler: routeHandler, spec, regex });\n\n return this;\n }\n\n\n /**\n * Attach the verb routes with their overload signatures.\n * Use compose to handle multiple handlers (middleware).\n */\n private attachVerb(method: Method, path: string, ...args: (MethodAPISpec | ShokupanHandler<T>)[]) {\n let spec: MethodAPISpec | undefined;\n let handlers: ShokupanHandler<T>[] = [];\n\n if (args.length > 0) {\n // Check if first arg is an object (Spec) and NOT a ShokupanHandler (function)\n if (typeof args[0] === 'object' && args[0] !== null) {\n spec = args[0] as MethodAPISpec;\n handlers = args.slice(1) as ShokupanHandler<T>[];\n } else {\n handlers = args as ShokupanHandler<T>[];\n }\n }\n\n if (handlers.length === 0) {\n // Should potentially throw or warn?\n return;\n }\n\n let finalHandler = handlers[handlers.length - 1]; // Last handler is the main handler?\n // Wait, compose logic: \n // If we have [m1, m2, h], we want m1 -> m2 -> h.\n // compose([m1, m2, h]) does exactly that.\n // However, middleware returns `Promise<any>`.\n // If `handlers.length > 1`, we wrap them.\n\n if (handlers.length > 1) {\n // Since handlers are [ctx, next?], they fit Strict Middleware signature.\n // compose takes Middleware[].\n // We assume ALL provided handlers are valid middleware/handlers.\n const fn = compose(handlers as any);\n finalHandler = (ctx) => fn(ctx);\n }\n\n // if (spec) {\n // console.log(`[Router] attachVerb ${method} ${path} has spec:`, spec);\n // } \n // else {\n // console.log(`[Router] attachVerb ${method} ${path} NO SPEC`);\n // }\n\n this.add({\n method,\n path,\n spec,\n handler: finalHandler\n });\n }\n\n /**\n * Generates an OpenAPI 3.1 Document by recursing through the router and its descendants.\n * Now includes runtime analysis of handler functions to infer request/response types.\n */\n public generateApiSpec(options: OpenAPIOptions = {}): any {\n return generateOpenApi(this, options);\n }\n}\n","import \"./util/instrumentation\";\n\nimport { context, trace } from '@opentelemetry/api';\nimport { ShokupanContext } from \"./context\";\nimport { compose } from \"./middleware\";\nimport { generateOpenApi } from \"./plugins/openapi\";\nimport { ShokupanRequest } from './request';\nimport { ShokupanRouter } from \"./router\";\nimport { $appRoot, $dispatch, $isApplication } from './symbol';\nimport type { Method, Middleware, ProcessResult, RequestOptions, ShokupanConfig } from './types';\nimport { asyncContext } from \"./util/async-hooks\";\n\nconst defaults: ShokupanConfig = {\n port: 3000,\n hostname: \"localhost\",\n development: process.env.NODE_ENV !== \"production\",\n enableAsyncLocalStorage: false,\n reusePort: false,\n};\nconst tracer = trace.getTracer(\"shokupan.application\");\n\n\nexport class Shokupan<T = any> extends ShokupanRouter<T> {\n readonly applicationConfig: ShokupanConfig = {};\n public openApiSpec?: any;\n private middleware: Middleware[] = [];\n\n get logger() {\n return this.applicationConfig.logger;\n }\n\n constructor(\n applicationConfig: ShokupanConfig = {}\n ) {\n super();\n this[$isApplication] = true;\n this[$appRoot] = this;\n Object.assign(this.applicationConfig, defaults, applicationConfig);\n }\n\n /**\n * Adds middleware to the application.\n */\n public use(middleware: Middleware) {\n this.middleware.push(middleware);\n return this;\n }\n\n private startupHooks: (() => Promise<void> | void)[] = [];\n\n /**\n * Registers a callback to be executed before the server starts listening.\n */\n public onStart(callback: () => Promise<void> | void) {\n this.startupHooks.push(callback);\n return this;\n }\n\n /**\n * Starts the application server.\n * \n * @param port - The port to listen on. If not specified, the port from the configuration is used. If that is not specified, port 3000 is used.\n * @returns The server instance.\n */\n public async listen(port?: number) {\n const finalPort = port ?? this.applicationConfig.port ?? 3000;\n\n if (finalPort < 0 || finalPort > 65535) {\n throw new Error(\"Invalid port number\");\n }\n\n // Run startup hooks\n for (const hook of this.startupHooks) {\n await hook();\n }\n\n if (this.applicationConfig.enableOpenApiGen) {\n this.openApiSpec = await generateOpenApi(this);\n }\n\n if (port === 0 && process.platform === \"linux\") {\n\n }\n\n const serveOptions = {\n port: finalPort,\n hostname: this.applicationConfig.hostname,\n development: this.applicationConfig.development,\n fetch: this.fetch.bind(this),\n reusePort: this.applicationConfig.reusePort,\n idleTimeout: this.applicationConfig.readTimeout ? this.applicationConfig.readTimeout / 1000 : undefined,\n };\n\n const server = this.applicationConfig.serverFactory\n ? await this.applicationConfig.serverFactory(serveOptions)\n : Bun.serve(serveOptions);\n\n console.log(`Shokupan server listening on http://${server.hostname}:${server.port}`);\n return server;\n }\n\n public [$dispatch](req: ShokupanRequest<T>) {\n return this.fetch(req as unknown as Request);\n }\n\n /**\n * Processes a request by wrapping the standard fetch method.\n */\n public override async processRequest(options: RequestOptions): Promise<ProcessResult> {\n let url = options.url || options.path || \"/\";\n if (!url.startsWith(\"http\")) {\n const base = `http://${this.applicationConfig.hostname || \"localhost\"}:${this.applicationConfig.port || 3000}`;\n const path = url.startsWith(\"/\") ? url : \"/\" + url;\n url = base + path;\n }\n\n if (options.query) {\n const u = new URL(url);\n for (const [k, v] of Object.entries(options.query)) {\n u.searchParams.set(k, v);\n }\n url = u.toString();\n }\n\n // Create Request to pass to fetch\n const req = new ShokupanRequest({\n method: (options.method || \"GET\") as Method,\n url,\n headers: options.headers as any,\n body: options.body && typeof options.body === \"object\" ? JSON.stringify(options.body) : options.body\n }) as unknown as ShokupanRequest<T>;\n\n const res = await this.fetch(req as unknown as Request);\n\n // Convert Response to ProcessResult\n const status = res.status;\n const headers: Record<string, string> = {};\n res.headers.forEach((v, k) => headers[k] = v);\n\n let data: any;\n if (headers['content-type']?.includes('application/json')) {\n data = await res.json();\n }\n else {\n data = await res.text();\n }\n\n return {\n status,\n headers,\n data\n };\n }\n\n /**\n * Handles an incoming request (Bun.serve interface).\n * This logic contains the middleware chain and router dispatch.\n * \n * @param req - The request to handle.\n * @param server - The server instance.\n * @returns The response to send.\n */\n public async fetch(req: Request, server?: import(\"bun\").Server): Promise<Response> {\n const tracer = trace.getTracer(\"shokupan.application\");\n const store = asyncContext.getStore();\n\n const attrs = {\n attributes: {\n \"http.url\": req.url,\n \"http.method\": req.method\n }\n };\n\n const parent = store?.get(\"span\");\n const ctx = parent ? trace.setSpan(context.active(), parent) : undefined;\n return tracer.startActiveSpan(`${req.method} ${new URL(req.url).pathname}`, attrs, ctx, span => {\n const ctxMap = new Map();\n ctxMap.set(\"span\", span);\n ctxMap.set(\"request\", req);\n\n const runCallback = () => {\n // Cast to ShokupanRequest if needed, though at runtime it's just a Request\n // But ShokupanContext expects ShokupanRequest.\n const request = req as unknown as ShokupanRequest<T>;\n\n const ctx = new ShokupanContext<T>(request, server, undefined, this);\n\n const handle = async () => {\n\n try {\n // Request Start Hook\n if (this.applicationConfig.hooks?.onRequestStart) {\n await this.applicationConfig.hooks.onRequestStart(ctx);\n }\n\n // Compose middleware + router dispatch\n const fn = compose(this.middleware);\n // Object.defineProperty(fn, 'name', { value: \"middleware chain\", configurable: false });\n\n // The \"next\" at the end of the middleware chain is the router dispatch\n const result = await fn(ctx, async () => {\n const match = this.find(req.method, ctx.path);\n // TODO: Execute router-level hooks from match?\n // For now, only app-level hooks are fully supported here.\n if (match) {\n ctx.params = match.params;\n return match.handler(ctx);\n }\n return null;\n });\n\n let response: Response;\n if (result instanceof Response) {\n response = result;\n }\n else if (result === null || result === undefined) {\n span.setAttribute(\"http.status_code\", 404);\n response = ctx.text(\"Not Found\", 404);\n }\n else if (typeof result === \"object\") {\n response = ctx.json(result);\n }\n else {\n response = ctx.text(String(result));\n }\n\n // Request End Hook - Processing finished, response ready\n if (this.applicationConfig.hooks?.onRequestEnd) {\n await this.applicationConfig.hooks.onRequestEnd(ctx);\n }\n\n // Response Start Hook - About to send response\n if (this.applicationConfig.hooks?.onResponseStart) {\n await this.applicationConfig.hooks.onResponseStart(ctx, response);\n }\n\n return response;\n\n }\n catch (err: any) {\n console.error(err);\n span.recordException(err);\n span.setStatus({ code: 2 }); // Error\n const status = err.status || err.statusCode || 500;\n const body: any = { error: err.message || \"Internal Server Error\" };\n if (err.errors) body.errors = err.errors;\n\n // Error Hook\n if (this.applicationConfig.hooks?.onError) {\n try {\n await this.applicationConfig.hooks.onError(err, ctx as any);\n } catch (hookErr) {\n console.error(\"Error in onError hook:\", hookErr);\n }\n }\n\n return ctx.json(body, status);\n }\n };\n\n // Timeout Logic\n let executionPromise = handle();\n const timeoutMs = this.applicationConfig.requestTimeout;\n\n if (timeoutMs && timeoutMs > 0 && this.applicationConfig.hooks?.onRequestTimeout) {\n let timeoutId: any;\n const timeoutPromise = new Promise<Response>((_, reject) => {\n timeoutId = setTimeout(async () => {\n try {\n if (this.applicationConfig.hooks?.onRequestTimeout) {\n await this.applicationConfig.hooks.onRequestTimeout(ctx);\n }\n } catch (e) { console.error(\"Error in onRequestTimeout hook:\", e); }\n\n reject(new Error(\"Request Timeout\"));\n }, timeoutMs);\n });\n\n executionPromise = Promise.race([executionPromise, timeoutPromise])\n .finally(() => clearTimeout(timeoutId));\n }\n\n return executionPromise\n .catch((err) => {\n if (err.message === \"Request Timeout\") {\n return ctx.text(\"Request Timeout\", 408);\n }\n console.error(\"Unexpected error in request execution:\", err);\n return ctx.text(\"Internal Server Error\", 500);\n })\n .then(async (res) => {\n // Response End Hook - Response returned\n // Note: We can't guarantee it's fully sent to client here, but it's handed off to Bun\n if (this.applicationConfig.hooks?.onResponseEnd) {\n await this.applicationConfig.hooks.onResponseEnd(ctx as any, res);\n }\n return res;\n })\n .finally(() => span.end());\n };\n\n if (this.applicationConfig.enableAsyncLocalStorage) {\n return asyncContext.run(ctxMap, runCallback);\n }\n else {\n return runCallback();\n }\n });\n }\n}\n","\nimport {\n Apple, Auth0,\n GitHub, Google, MicrosoftEntraId,\n OAuth2Client,\n Okta,\n generateCodeVerifier,\n generateState\n} from \"arctic\";\nimport * as jose from \"jose\";\nimport { ShokupanContext } from \"../context\";\nimport { ShokupanRouter } from \"../router\";\n\nexport interface AuthUser {\n id: string;\n email?: string;\n name?: string;\n picture?: string;\n provider: string;\n raw?: any;\n}\n\nexport interface ProviderConfig {\n clientId: string;\n clientSecret: string;\n redirectUri: string; // Must be absolute\n scopes?: string[];\n tenantId?: string; // For MS\n domain?: string; // For Auth0, Okta\n teamId?: string; // For Apple\n keyId?: string; // For Apple\n authUrl?: string; // For generic OAuth2\n tokenUrl?: string; // For generic OAuth2\n userInfoUrl?: string; // For generic OAuth2\n}\n\nexport interface AuthConfig {\n jwtSecret: string | Uint8Array;\n jwtExpiration?: string; // e.g. \"2h\"\n cookieOptions?: {\n httpOnly?: boolean;\n secure?: boolean;\n sameSite?: \"Strict\" | \"Lax\" | \"None\";\n path?: string;\n maxAge?: number;\n };\n onSuccess?: (user: AuthUser, ctx: ShokupanContext) => Promise<any> | any;\n providers: {\n github?: ProviderConfig;\n google?: ProviderConfig;\n microsoft?: ProviderConfig;\n apple?: ProviderConfig;\n auth0?: ProviderConfig;\n okta?: ProviderConfig;\n oauth2?: ProviderConfig;\n [key: string]: ProviderConfig | undefined;\n };\n}\n\nexport class AuthPlugin extends ShokupanRouter<any> {\n private secret: Uint8Array;\n\n constructor(private authConfig: AuthConfig) {\n super();\n this.secret = typeof authConfig.jwtSecret === 'string'\n ? new TextEncoder().encode(authConfig.jwtSecret)\n : authConfig.jwtSecret;\n\n this.init();\n }\n\n private getProviderInstance(name: string, p: ProviderConfig) {\n switch (name) {\n case 'github':\n return new GitHub(p.clientId, p.clientSecret, p.redirectUri);\n case 'google':\n return new Google(p.clientId, p.clientSecret, p.redirectUri);\n case 'microsoft':\n return new MicrosoftEntraId(p.tenantId!, p.clientId, p.clientSecret, p.redirectUri);\n case 'apple':\n // TODO: There is a type issue, requires testing.\n return new Apple(\n p.clientId,\n p.teamId!,\n p.keyId!,\n p.clientSecret as any,\n p.redirectUri\n );\n case 'auth0':\n return new Auth0(p.domain!, p.clientId, p.clientSecret, p.redirectUri);\n case 'okta':\n return new Okta(p.domain!, p.authUrl, p.clientId, p.clientSecret, p.redirectUri);\n case 'oauth2':\n return new OAuth2Client(p.clientId, p.clientSecret, p.redirectUri);\n default:\n return null;\n }\n }\n\n private async createSession(user: AuthUser, ctx: ShokupanContext) {\n const alg = 'HS256';\n const jwt = await new jose.SignJWT({ ...user })\n .setProtectedHeader({ alg })\n .setIssuedAt()\n .setExpirationTime(this.authConfig.jwtExpiration || '24h')\n .sign(this.secret);\n\n // Set cookie\n const opts = this.authConfig.cookieOptions || {};\n let cookie = `auth_token=${jwt}; Path=${opts.path || '/'}; HttpOnly`;\n if (opts.secure) cookie += '; Secure';\n if (opts.sameSite) cookie += `; SameSite=${opts.sameSite}`;\n if (opts.maxAge) cookie += `; Max-Age=${opts.maxAge}`;\n\n ctx.set('Set-Cookie', cookie);\n\n return jwt;\n }\n\n private init() {\n for (const [providerName, providerConfig] of Object.entries(this.authConfig.providers)) {\n if (!providerConfig) continue;\n\n const provider = this.getProviderInstance(providerName, providerConfig);\n if (!provider) {\n // Try treating as generic oauth2 if it has configured urls? \n // But for now strict mapping based on key unless we add logic.\n // We'll skip if unknown.\n continue;\n }\n\n // Login Route\n this.get(`/auth/${providerName}/login`, async (ctx) => {\n const state = generateState();\n const codeVerifier = (providerName === 'google' || providerName === 'microsoft' || providerName === 'auth0' || providerName === 'okta')\n ? generateCodeVerifier() : undefined; // PKCE for some\n\n // Store state/verifier in cookie for verification\n const scopes = providerConfig.scopes || [];\n let url: URL;\n\n if (provider instanceof GitHub) {\n url = await provider.createAuthorizationURL(state, scopes);\n } else if (provider instanceof Google || provider instanceof MicrosoftEntraId || provider instanceof Auth0 || provider instanceof Okta) {\n // These all support PKCE in recent versions\n // Types might vary slightly but usually createAuthorizationURL(state, codeVerifier, scopes)\n url = await (provider as any).createAuthorizationURL(state, codeVerifier!, scopes);\n } else if (provider instanceof Apple) {\n url = await provider.createAuthorizationURL(state, scopes);\n } else if (provider instanceof OAuth2Client) {\n if (!providerConfig.authUrl) return ctx.text(\"Config error: authUrl required for oauth2\", 500);\n url = await provider.createAuthorizationURL(providerConfig.authUrl, state, scopes);\n } else {\n return ctx.text(\"Provider config error\", 500);\n }\n\n ctx.res.headers.set(\"Set-Cookie\", `oauth_state=${state}; Path=/; HttpOnly; Max-Age=600`);\n if (codeVerifier) {\n ctx.res.headers.append(\"Set-Cookie\", `oauth_verifier=${codeVerifier}; Path=/; HttpOnly; Max-Age=600`);\n }\n\n return ctx.redirect(url.toString());\n });\n\n // Callback Route\n this.get(`/auth/${providerName}/callback`, async (ctx) => {\n const url = new URL(ctx.req.url);\n const code = url.searchParams.get(\"code\");\n const state = url.searchParams.get(\"state\");\n\n const cookieHeader = ctx.req.headers.get(\"Cookie\");\n const storedState = cookieHeader?.match(/oauth_state=([^;]+)/)?.[1];\n const storedVerifier = cookieHeader?.match(/oauth_verifier=([^;]+)/)?.[1];\n\n if (!code || !state || !storedState || state !== storedState) {\n return ctx.text(\"Invalid state or code\", 400);\n }\n\n try {\n let tokens: any;\n let idToken: string | undefined;\n\n if (provider instanceof GitHub) {\n tokens = await provider.validateAuthorizationCode(code);\n } else if (provider instanceof Google || provider instanceof MicrosoftEntraId) {\n if (!storedVerifier) return ctx.text(\"Missing verifier\", 400);\n tokens = await provider.validateAuthorizationCode(code, storedVerifier);\n } else if (provider instanceof Auth0 || provider instanceof Okta) {\n tokens = await (provider as any).validateAuthorizationCode(code, storedVerifier || \"\");\n } else if (provider instanceof Apple) {\n tokens = await provider.validateAuthorizationCode(code);\n idToken = tokens.idToken;\n } else if (provider instanceof OAuth2Client) {\n if (!providerConfig.tokenUrl) return ctx.text(\"Config error: tokenUrl required for oauth2\", 500);\n tokens = await provider.validateAuthorizationCode(providerConfig.tokenUrl, code, null);\n }\n\n const accessToken = tokens.accessToken || tokens.access_token;\n const user = await this.fetchUser(providerName, accessToken, providerConfig, idToken);\n\n if (this.authConfig.onSuccess) {\n const res = await this.authConfig.onSuccess(user, ctx);\n if (res) return res; // Allow override response\n }\n\n // Default behavior: create encoded session and returning it or redirect\n const jwt = await this.createSession(user, ctx);\n return ctx.json({ token: jwt, user });\n\n } catch (e: any) {\n console.error(\"Auth Error\", e);\n return ctx.text(\"Authentication failed: \" + e.message + \"\\n\" + e.stack, 500);\n }\n });\n }\n }\n\n private async fetchUser(provider: string, token: string, config: ProviderConfig, idToken?: string): Promise<AuthUser> {\n let user: AuthUser = { id: 'unknown', provider };\n\n if (provider === 'github') {\n const res = await fetch(\"https://api.github.com/user\", {\n headers: { Authorization: `Bearer ${token}` }\n });\n const data = await res.json() as any;\n user = {\n id: String(data.id),\n name: data.name || data.login,\n email: data.email,\n picture: data.avatar_url,\n provider,\n raw: data\n };\n }\n else if (provider === 'google') {\n const res = await fetch(\"https://openidconnect.googleapis.com/v1/userinfo\", {\n headers: { Authorization: `Bearer ${token}` }\n });\n const data = await res.json() as any;\n user = {\n id: data.sub,\n name: data.name,\n email: data.email,\n picture: data.picture,\n provider,\n raw: data\n };\n }\n else if (provider === 'microsoft') {\n const res = await fetch(\"https://graph.microsoft.com/v1.0/me\", {\n headers: { Authorization: `Bearer ${token}` }\n });\n const data = await res.json() as any;\n user = {\n id: data.id,\n name: data.displayName,\n email: data.mail || data.userPrincipalName,\n provider,\n raw: data\n };\n }\n else if (provider === 'auth0' || provider === 'okta') {\n const domain = config.domain!.startsWith('http') ? config.domain! : `https://${config.domain}`;\n const endpoint = provider === 'auth0' ? `${domain}/userinfo` : `${domain}/oauth2/v1/userinfo`;\n\n const res = await fetch(endpoint, {\n headers: { Authorization: `Bearer ${token}` }\n });\n const data = await res.json() as any;\n user = {\n id: data.sub,\n name: data.name,\n email: data.email,\n picture: data.picture,\n provider,\n raw: data\n };\n }\n else if (provider === 'apple') {\n // Apple user info is in the ID Token\n if (idToken) {\n const payload = jose.decodeJwt(idToken);\n user = {\n id: payload.sub!,\n email: payload['email'] as string,\n provider,\n raw: payload\n };\n }\n }\n else if (provider === 'oauth2') {\n if (config.userInfoUrl) {\n const res = await fetch(config.userInfoUrl, {\n headers: { Authorization: `Bearer ${token}` }\n });\n const data = await res.json() as any;\n user = {\n id: data.id || data.sub || 'unknown',\n name: data.name,\n email: data.email,\n picture: data.picture,\n provider,\n raw: data\n };\n }\n }\n\n return user;\n }\n\n /**\n * Middleware to verify JWT\n */\n public middleware() {\n return async (ctx: ShokupanContext, next: () => Promise<any>) => {\n const authHeader = ctx.req.headers.get(\"Authorization\");\n let token = authHeader?.startsWith(\"Bearer \") ? authHeader.substring(7) : null;\n\n if (!token) {\n // Try cookie\n const cookieHeader = ctx.req.headers.get(\"Cookie\");\n token = cookieHeader?.match(/auth_token=([^;]+)/)?.[1] || null;\n }\n\n if (token) {\n try {\n const { payload } = await jose.jwtVerify(token, this.secret);\n (ctx as any).user = payload;\n } catch {\n // Invalid token, just proceed without user or throw?\n // Usually proceed, let guard handle it if required\n }\n }\n return next();\n };\n }\n}\n","import type { ShokupanContext } from \"../context\";\nimport type { Middleware, NextFn } from \"../types\";\n\nexport interface CompressionOptions {\n threshold?: number; // Minimum byte size to compress\n}\n\nexport function Compression(options: CompressionOptions = {}): Middleware {\n const threshold = options.threshold ?? 1024; // 1KB default\n\n return async (ctx: ShokupanContext, next: NextFn) => {\n const acceptEncoding = ctx.headers.get(\"accept-encoding\") || \"\";\n\n // Check if compression is supported\n let method: 'br' | 'gzip' | 'deflate' | null = null;\n if (acceptEncoding.includes(\"br\")) method = \"br\";\n else if (acceptEncoding.includes(\"gzip\")) method = \"gzip\";\n else if (acceptEncoding.includes(\"deflate\")) method = \"deflate\";\n\n if (!method) return next();\n\n const response = await next();\n\n if (response instanceof Response) {\n // Don't compress if already compressed\n if (response.headers.has(\"Content-Encoding\")) return response;\n\n // Check Content-Type (optional, mostly text/json/xml)\n // For now, let's just compress if we can read the body easily.\n\n // Cloning response to read body\n // Note: This might be expensive for streams. \n // We only support basic compression for now (string/buffer bodies).\n // If body is a ReadableStream, Bun.gzip/deflateSync won't work directly on it mostly.\n\n // Let's try to read as ArrayBuffer\n const body = await response.arrayBuffer();\n\n if (body.byteLength < threshold) {\n // Return new response with original body because we consumed it\n return new Response(body, {\n status: response.status,\n statusText: response.statusText,\n headers: response.headers\n });\n }\n\n let compressed: Uint8Array;\n if (method === \"br\") {\n // Configurable params could be added later\n compressed = require(\"node:zlib\").brotliCompressSync(body);\n } else if (method === \"gzip\") {\n compressed = Bun.gzipSync(body);\n } else {\n compressed = Bun.deflateSync(body);\n }\n\n const headers = new Headers(response.headers);\n headers.set(\"Content-Encoding\", method);\n headers.set(\"Content-Length\", String(compressed.length));\n headers.delete(\"Content-Length\"); // Remove original length if present\n\n return new Response(compressed, {\n status: response.status,\n statusText: response.statusText,\n headers\n });\n }\n\n return response;\n };\n}\n","import type { ShokupanContext } from \"../context\";\nimport type { Middleware, NextFn } from \"../types\";\n\nexport interface CorsOptions {\n origin?: string | string[] | ((ctx: ShokupanContext) => string | undefined | null | boolean);\n methods?: string | string[];\n allowedHeaders?: string | string[];\n exposedHeaders?: string | string[];\n credentials?: boolean;\n maxAge?: number;\n}\n\nexport function Cors(options: CorsOptions = {}): Middleware {\n const defaults: CorsOptions = {\n origin: \"*\",\n methods: \"GET,HEAD,PUT,PATCH,POST,DELETE\",\n preflightContinue: false,\n optionsSuccessStatus: 204\n } as any;\n\n const opts = { ...defaults, ...options };\n\n return async (ctx: ShokupanContext, next: NextFn) => {\n const headers = new Headers();\n const origin = ctx.headers.get(\"origin\");\n\n const set = (k: string, v: string) => headers.set(k, v);\n const append = (k: string, v: string) => headers.append(k, v);\n\n // Set Access-Control-Allow-Origin\n if (opts.origin === \"*\") {\n set(\"Access-Control-Allow-Origin\", \"*\");\n } else if (typeof opts.origin === \"string\") {\n set(\"Access-Control-Allow-Origin\", opts.origin);\n } else if (Array.isArray(opts.origin)) {\n if (origin && opts.origin.includes(origin)) {\n set(\"Access-Control-Allow-Origin\", origin);\n append(\"Vary\", \"Origin\");\n }\n } else if (typeof opts.origin === \"function\") {\n const allowed = opts.origin(ctx);\n if (allowed === true && origin) {\n set(\"Access-Control-Allow-Origin\", origin);\n append(\"Vary\", \"Origin\");\n } else if (typeof allowed === 'string') {\n set(\"Access-Control-Allow-Origin\", allowed);\n append(\"Vary\", \"Origin\");\n }\n }\n\n // Access-Control-Allow-Credentials\n if (opts.credentials) {\n set(\"Access-Control-Allow-Credentials\", \"true\");\n }\n\n // Access-Control-Expose-Headers\n if (opts.exposedHeaders) {\n const exposed = Array.isArray(opts.exposedHeaders) ? opts.exposedHeaders.join(\",\") : opts.exposedHeaders;\n if (exposed) set(\"Access-Control-Expose-Headers\", exposed);\n }\n\n // Handle Preflight\n if (ctx.method === \"OPTIONS\") {\n // Access-Control-Allow-Methods\n if (opts.methods) {\n const methods = Array.isArray(opts.methods) ? opts.methods.join(\",\") : opts.methods;\n set(\"Access-Control-Allow-Methods\", methods);\n }\n\n // Access-Control-Allow-Headers\n if (opts.allowedHeaders) {\n const h = Array.isArray(opts.allowedHeaders) ? opts.allowedHeaders.join(\",\") : opts.allowedHeaders;\n set(\"Access-Control-Allow-Headers\", h);\n } else {\n // Reflect request headers if not specified\n const reqHeaders = ctx.headers.get(\"access-control-request-headers\");\n if (reqHeaders) {\n set(\"Access-Control-Allow-Headers\", reqHeaders);\n append(\"Vary\", \"Access-Control-Request-Headers\");\n }\n }\n\n // Access-Control-Max-Age\n if (opts.maxAge) {\n set(\"Access-Control-Max-Age\", String(opts.maxAge));\n }\n\n return new Response(null, {\n status: (opts as any).optionsSuccessStatus || 204,\n headers\n });\n }\n\n const response = await next();\n\n if (response instanceof Response) {\n for (const [key, value] of headers.entries()) {\n response.headers.set(key, value);\n }\n }\n\n return response;\n };\n}\n","import type { Middleware } from '../types';\n\n/**\n * Adapter to use legacy Express middleware.\n * NOTE: This provides a PARTIAL mock of req/res.\n */\nexport function useExpress(expressMiddleware: any): Middleware {\n return async (ctx, next) => {\n return new Promise((resolve, reject) => {\n // Mock Request\n // Express middleware often mutates req, but Request is readonly.\n // We use a Proxy to intercept writes and store them locally.\n const reqStore: any = {\n method: ctx.method,\n url: ctx.url.pathname + ctx.url.search,\n path: ctx.url.pathname,\n query: ctx.query,\n headers: ctx.headers,\n get: (name: string) => ctx.headers.get(name)\n };\n\n const req = new Proxy(ctx.request, {\n get(target, prop) {\n if (prop in reqStore) return reqStore[prop];\n const val = (target as any)[prop];\n if (typeof val === 'function') return val.bind(target);\n return val;\n },\n set(target, prop, value) {\n reqStore[prop] = value;\n ctx.state[prop as string] = value;\n return true;\n }\n });\n\n // Mock Response (res)\n const res: any = {\n locals: {},\n statusCode: 200,\n setHeader: (name: string, value: string) => {\n ctx.response.headers.set(name, value);\n },\n set: (name: string, value: string) => {\n ctx.response.headers.set(name, value);\n },\n end: (chunk: any) => {\n resolve(new Response(chunk, { status: res.statusCode }));\n },\n status: (code: number) => {\n res.statusCode = code;\n return res;\n },\n send: (body: any) => {\n let content = body;\n if (typeof body === 'object') content = JSON.stringify(body);\n resolve(new Response(content, { status: res.statusCode }));\n },\n json: (body: any) => {\n resolve(Response.json(body, { status: res.statusCode }));\n }\n };\n\n // Execute\n try {\n expressMiddleware(req, res, (err: any) => {\n if (err) return reject(err);\n resolve(next());\n });\n } catch (err) {\n reject(err);\n }\n });\n };\n}","import type { ShokupanContext } from \"../context\";\nimport type { Middleware, NextFn } from \"../types\";\n\nexport interface RateLimitOptions {\n windowMs?: number;\n max?: number;\n message?: string | object;\n statusCode?: number;\n headers?: boolean;\n keyGenerator?: (ctx: ShokupanContext) => string;\n skip?: (ctx: ShokupanContext) => boolean;\n}\n\ninterface HitRecord {\n hits: number;\n resetTime: number;\n}\n\nexport function RateLimit(options: RateLimitOptions = {}): Middleware {\n const windowMs = options.windowMs || 60 * 1000; // 1 minute\n const max = options.max || 5; // 5 requests per window\n const message = options.message || \"Too many requests, please try again later.\";\n const statusCode = options.statusCode || 429;\n const headers = options.headers !== false;\n const keyGenerator = options.keyGenerator || ((ctx) => {\n // Use IP if available (Bun specific property on server, but not exposed in generic Request easily without server context)\n // Fallback to simpler key or x-forwarded-for\n return ctx.headers.get(\"x-forwarded-for\") || ctx.url.hostname || \"unknown\";\n });\n const skip = options.skip || (() => false);\n\n // In-memory store\n // Note: For production with multiple instances, use Redis or similar external store.\n const hits = new Map<string, HitRecord>();\n\n // Cleanup interval\n const interval = setInterval(() => {\n const now = Date.now();\n for (const [key, record] of hits.entries()) {\n if (record.resetTime <= now) {\n hits.delete(key);\n }\n }\n }, windowMs);\n // Ensure interval doesn't block process exit\n if (interval.unref) interval.unref();\n\n return async (ctx: ShokupanContext, next: NextFn) => {\n if (skip(ctx)) return next();\n\n const key = keyGenerator(ctx);\n const now = Date.now();\n let record = hits.get(key);\n\n if (!record || record.resetTime <= now) {\n record = {\n hits: 0,\n resetTime: now + windowMs\n };\n hits.set(key, record);\n }\n\n record.hits++;\n\n const remaining = Math.max(0, max - record.hits);\n const resetTime = Math.ceil(record.resetTime / 1000);\n\n if (headers) {\n // We need to set headers on the response. \n // Similar to Helmet, we need to intercept the response or set it on context if supported.\n // For now, let's assume we can attach to the eventual response wrapper or helper.\n // Since we can't modify `ctx.response` directly before it exists, we wrap.\n }\n\n if (record.hits > max) {\n if (headers) {\n // Return immediate response\n const res = typeof message === 'object' ? ctx.json(message, statusCode) : ctx.text(String(message), statusCode);\n res.headers.set(\"X-RateLimit-Limit\", String(max));\n res.headers.set(\"X-RateLimit-Remaining\", \"0\");\n res.headers.set(\"X-RateLimit-Reset\", String(resetTime));\n return res;\n }\n return typeof message === 'object' ? ctx.json(message, statusCode) : ctx.text(String(message), statusCode);\n }\n\n const response = await next();\n\n if (response instanceof Response && headers) {\n response.headers.set(\"X-RateLimit-Limit\", String(max));\n response.headers.set(\"X-RateLimit-Remaining\", String(remaining));\n response.headers.set(\"X-RateLimit-Reset\", String(resetTime));\n }\n\n return response;\n };\n}\n","import type { ApiReferenceConfiguration } from '@scalar/api-reference';\nimport type { OpenAPI } from '@scalar/openapi-types';\nimport { Eta } from 'eta';\nimport { OpenAPIAnalyzer } from '../analysis/openapi-analyzer';\nimport { ShokupanRouter } from '../router';\nimport type { DeepPartial } from '../types';\nimport { deepMerge } from '../util/deep-merge';\n\nconst eta = new Eta();\n\nexport type ScalarPluginOptions = {\n baseDocument?: DeepPartial<OpenAPI.Document>;\n config: Partial<ApiReferenceConfiguration>;\n enableStaticAnalysis?: boolean;\n};\n\nexport class ScalarPlugin extends ShokupanRouter<any> {\n constructor(\n private readonly pluginOptions: ScalarPluginOptions\n ) {\n super();\n this.init();\n }\n\n init() {\n this.get(\"/\", ctx => {\n let path = ctx.url.toString();\n if (!path.endsWith(\"/\")) path += \"/\";\n\n return ctx.html(eta.renderString(`<!doctype html>\n <html>\n <head>\n <title>API Reference</title>\n <meta charset = \"utf-8\" />\n <meta name=\"viewport\" content = \"width=device-width, initial-scale=1\" />\n </head>\n\n <body>\n <div id=\"app\"></div>\n\n <script src=\"<%= it.path %>scalar.js\"></script>\n <script>\n Scalar.createApiReference('#app', [{ ...<%~ JSON.stringify(it.config.baseDocument) %>,\n url: \"<%= it.path %>openapi.json\",\n }\n ])\n </script>\n </body>\n\n </html>`, { path, config: this.pluginOptions }));\n });\n\n this.get(\"/scalar.js\", (ctx) => {\n return ctx.file(__dirname + \"/../../node_modules/@scalar/api-reference/dist/browser/standalone.js\");\n });\n\n this.get(\"/openapi.json\", async (ctx) => {\n let spec: any;\n // Use pre-generated spec if available (from startup)\n if ((this.root as any).openApiSpec) {\n try {\n spec = structuredClone((this.root as any).openApiSpec);\n } catch (e) {\n // Fallback if structuredClone fails (e.g. non-cloneable types)\n spec = Object.assign({}, (this.root as any).openApiSpec);\n }\n }\n else {\n // Fallback to on-demand generation\n spec = await (this.root || this).generateApiSpec();\n }\n\n // If static analysis ran in onStart, baseDocument is already populated.\n // If NOT (e.g. strict mode or unit test without listen), we might need to lazy load?\n // For now, assume baseDocument has it.\n // But we still need to merge baseDocument (static) + spec (runtime).\n\n if (this.pluginOptions.baseDocument) {\n deepMerge(spec, this.pluginOptions.baseDocument);\n }\n\n return ctx.json(spec);\n });\n }\n\n // New lifecycle method to be called by router.mount\n public onMount(parent: ShokupanRouter<any>) {\n if ((parent as any).onStart) {\n (parent as any).onStart(async () => {\n if (this.pluginOptions.enableStaticAnalysis) {\n try {\n const entrypoint = process.argv[1];\n console.log(`[ScalarPlugin] Running eager static analysis on entrypoint: ${entrypoint}`);\n const analyzer = new OpenAPIAnalyzer(process.cwd(), entrypoint);\n let staticSpec = await analyzer.analyze();\n\n if (!this.pluginOptions.baseDocument) this.pluginOptions.baseDocument = {};\n deepMerge(this.pluginOptions.baseDocument as any, staticSpec);\n console.log('[ScalarPlugin] Static analysis completed successfully.');\n } catch (err) {\n console.error('[ScalarPlugin] Failed to run static analysis:', err);\n }\n }\n });\n }\n }\n}","import type { ShokupanContext } from \"../context\";\nimport type { Middleware, NextFn } from \"../types\";\n\nexport interface SecurityHeadersOptions {\n contentSecurityPolicy?: boolean | Record<string, any>;\n crossOriginEmbedderPolicy?: boolean;\n crossOriginOpenerPolicy?: boolean;\n crossOriginResourcePolicy?: boolean;\n dnsPrefetchControl?: boolean | { allow: boolean; };\n expectCt?: boolean | { maxAge?: number, enforce?: boolean, reportUri?: string; };\n frameguard?: boolean | { action: 'deny' | 'sameorigin' | 'allow-from', domain?: string; };\n hidePoweredBy?: boolean;\n hsts?: boolean | { maxAge?: number, includeSubDomains?: boolean, preload?: boolean; };\n ieNoOpen?: boolean;\n noSniff?: boolean;\n originAgentCluster?: boolean;\n permittedCrossDomainPolicies?: boolean | { permittedPolicies: 'none' | 'master-only' | 'by-content-type' | 'all'; };\n referrerPolicy?: boolean | { policy: string | string[]; };\n xssFilter?: boolean;\n}\n\nexport function SecurityHeaders(options: SecurityHeadersOptions = {}): Middleware {\n return async (ctx: ShokupanContext, next: NextFn) => {\n const headers: Record<string, string> = {};\n\n // Helper to set header if not already set or force it\n const set = (k: string, v: string) => headers[k] = v;\n\n // X-DNS-Prefetch-Control\n if (options.dnsPrefetchControl !== false) {\n const allow = (options.dnsPrefetchControl as any)?.allow;\n set(\"X-DNS-Prefetch-Control\", allow ? \"on\" : \"off\");\n }\n\n // X-Frame-Options\n if (options.frameguard !== false) {\n const opt = options.frameguard as any || {};\n const action = opt.action || 'sameorigin';\n if (action === 'sameorigin') set('X-Frame-Options', 'SAMEORIGIN');\n else if (action === 'deny') set('X-Frame-Options', 'DENY');\n // 'allow-from' is deprecated/obsolete in modern browsers, but we can support it if needed.\n }\n\n // Strict-Transport-Security\n if (options.hsts !== false) {\n const opt = options.hsts as any || {};\n const maxAge = opt.maxAge || 15552000; // 180 days\n let header = `max-age=${maxAge}`;\n if (opt.includeSubDomains !== false) header += '; includeSubDomains';\n if (opt.preload) header += '; preload';\n set('Strict-Transport-Security', header);\n }\n\n // X-Download-Options\n if (options.ieNoOpen !== false) {\n set('X-Download-Options', 'noopen');\n }\n\n // X-Content-Type-Options\n if (options.noSniff !== false) {\n set('X-Content-Type-Options', 'nosniff');\n }\n\n // X-XSS-Protection (Legacy, but still sometimes used)\n if (options.xssFilter !== false) {\n set('X-XSS-Protection', '0'); // Modern recommendation is to disable it as it can introduce vulns\n }\n\n // Referrer-Policy\n if (options.referrerPolicy !== false) {\n const opt = options.referrerPolicy as any || {};\n const policy = opt.policy || 'no-referrer';\n set('Referrer-Policy', Array.isArray(policy) ? policy.join(',') : policy);\n }\n\n // Content-Security-Policy\n if (options.contentSecurityPolicy !== false) {\n // Basic default CSP if true, or use object\n const opt = options.contentSecurityPolicy;\n if (opt === undefined || opt === true) {\n set('Content-Security-Policy', \"default-src 'self';base-uri 'self';font-src 'self' https: data:;form-action 'self';frame-ancestors 'self';img-src 'self' data:;object-src 'none';script-src 'self';style-src 'self' https: 'unsafe-inline';upgrade-insecure-requests\");\n } else if (typeof opt === 'object') {\n // Construct CSP string from object (simplified)\n // Assuming user passes raw string or we'd need a directive builder.\n // For now, let's assume they pass directives map.\n const parts = [];\n for (const [key, val] of Object.entries(opt)) {\n // directives, etc.\n // This is complex to implement fully without a library like 'helmet' itself.\n // We will support a simple string or custom logic later if requested.\n // For now, skip complex object parsing to keep it simple as per \"standard middleware\" MVP.\n }\n }\n }\n\n if (options.hidePoweredBy !== false) {\n // Note: Shokupan doesn't set X-Powered-By by default, so we usually don't need to remove it.\n // But we can ensure it's not there.\n // We can't delete from response easily before it's created, but we can try to suppress it if we had a hook.\n // Here we might just do nothing as we don't add it.\n }\n\n // Apply headers to context response\n // We need to apply these to the response *after* it's generated, or *before* if we use `ctx.headers` mutation?\n // `ctx.headers` is currently read-only wrapper around `req.headers` in `ShokupanContext`?\n // Wait, `ctx.headers` in `ShokupanContext` getter is `this.request.headers`.\n // We cannot set response headers on the request object.\n // We need to intercept the response.\n\n const response = await next();\n\n if (response instanceof Response) {\n for (const [k, v] of Object.entries(headers)) {\n response.headers.set(k, v);\n }\n return response;\n }\n\n // If next() returned something else (e.g. string/json that router will wrap),\n // we can't easily attach headers here unless we wrap the result in a Response.\n // BUT `compose` and `router` logic allows next() to return result which `router` converts to Response.\n // If middleware runs *before* router, next() returns the router's result.\n\n // If we want to ensure headers are set, we might need to rely on `ctx` having a way to set \"outgoing\" headers \n // that the router respects, OR we must wrap the response.\n\n return response;\n };\n}\n","import { createHmac, randomUUID } from \"crypto\";\nimport { EventEmitter } from \"events\";\nimport { ShokupanContext } from \"../context\";\nimport type { Middleware } from \"../types\";\n\n// --- Types ---\n\nexport interface SessionData {\n cookie: Cookie;\n [key: string]: any;\n}\n\nexport interface SessionCookieOptions {\n maxAge?: number;\n signed?: boolean;\n expires?: Date;\n httpOnly?: boolean;\n path?: string;\n domain?: string;\n secure?: boolean | 'auto';\n sameSite?: boolean | 'lax' | 'strict' | 'none';\n priority?: 'low' | 'medium' | 'high';\n}\n\nexport interface SessionOptions {\n secret: string | string[];\n name?: string;\n store?: Store;\n cookie?: SessionCookieOptions;\n genid?: (ctx: ShokupanContext) => string;\n resave?: boolean;\n saveUninitialized?: boolean;\n rolling?: boolean;\n unset?: 'destroy' | 'keep';\n}\n\nexport interface Store extends EventEmitter {\n get(sid: string, callback: (err: any, session?: SessionData | null) => void): void;\n set(sid: string, session: SessionData, callback?: (err?: any) => void): void;\n destroy(sid: string, callback?: (err?: any) => void): void;\n touch?(sid: string, session: SessionData, callback?: (err?: any) => void): void;\n all?(callback: (err: any, obj?: { [sid: string]: SessionData; } | null) => void): void;\n length?(callback: (err: any, length?: number) => void): void;\n clear?(callback?: (err?: any) => void): void;\n load?(sid: string, fn: (err: any, session?: SessionData | null) => void): void;\n createSession?(req: any, session: SessionData): SessionData;\n}\n\n// --- Cookie Helper ---\n\nclass Cookie implements SessionCookieOptions {\n maxAge?: number;\n signed?: boolean;\n expires?: Date;\n httpOnly?: boolean;\n path?: string;\n domain?: string;\n secure?: boolean | 'auto';\n sameSite?: boolean | 'lax' | 'strict' | 'none';\n originalMaxAge: number | undefined;\n\n constructor(options: SessionCookieOptions = {}) {\n this.path = options.path || '/';\n this.httpOnly = options.httpOnly !== undefined ? options.httpOnly : true;\n this.secure = options.secure;\n this.maxAge = options.maxAge;\n this.sameSite = options.sameSite;\n this.domain = options.domain;\n this.expires = options.expires;\n\n if (this.maxAge !== undefined) {\n this.originalMaxAge = this.maxAge;\n this.expires = new Date(Date.now() + this.maxAge);\n }\n }\n\n serialize(name: string, val: string) {\n let str = `${name}=${encodeURIComponent(val)}`;\n\n if (this.maxAge) {\n const expires = new Date(Date.now() + this.maxAge);\n str += `; Expires=${expires.toUTCString()}`;\n // Also add Max-Age?\n str += `; Max-Age=${Math.floor(this.maxAge / 1000)}`;\n } else if (this.expires) {\n str += `; Expires=${this.expires.toUTCString()}`;\n }\n\n if (this.domain) str += `; Domain=${this.domain}`;\n if (this.path) str += `; Path=${this.path}`;\n if (this.httpOnly) str += `; HttpOnly`;\n if (this.secure) str += `; Secure`;\n if (this.sameSite) {\n const sameSite = typeof this.sameSite === 'string' ?\n this.sameSite.charAt(0).toUpperCase() + this.sameSite.slice(1) : 'Strict';\n str += `; SameSite=${sameSite}`;\n }\n\n return str;\n }\n}\n\n// --- Memory Store ---\n\n\nexport class MemoryStore extends EventEmitter implements Store {\n private sessions: Record<string, string> = {};\n\n get(sid: string, cb: (err: any, session?: SessionData | null) => void) {\n const sess = this.sessions[sid];\n if (!sess) return cb(null, null);\n try {\n const data = JSON.parse(sess);\n // Re-hydrate dates?\n if (data.cookie && data.cookie.expires) {\n data.cookie.expires = new Date(data.cookie.expires);\n }\n cb(null, data);\n } catch (e) {\n cb(e);\n }\n }\n\n set(sid: string, sess: SessionData, cb?: (err?: any) => void) {\n this.sessions[sid] = JSON.stringify(sess);\n cb && cb();\n }\n\n destroy(sid: string, cb?: (err?: any) => void) {\n delete this.sessions[sid];\n cb && cb();\n }\n\n touch(sid: string, sess: SessionData, cb?: (err?: any) => void) {\n const current = this.sessions[sid];\n if (current) {\n // Update the cookie expiry if needed without changing the whole object if we want to be efficient\n // But for MemoryStore, just set is fine\n this.sessions[sid] = JSON.stringify(sess);\n }\n cb && cb();\n }\n\n all(cb: (err: any, obj?: { [sid: string]: SessionData; } | null) => void) {\n const result: Record<string, SessionData> = {};\n for (const sid in this.sessions) {\n try {\n result[sid] = JSON.parse(this.sessions[sid]);\n } catch { }\n }\n cb(null, result);\n }\n\n clear(cb?: (err?: any) => void) {\n this.sessions = {};\n cb && cb();\n }\n}\n\n// --- Crypto Helpers ---\n\nfunction sign(val: string, secret: string) {\n if (typeof val !== 'string') throw new TypeError(\"Cookie value must be provided as a string.\");\n if (typeof secret !== 'string') throw new TypeError(\"Secret string must be provided.\");\n return val + '.' + createHmac('sha256', secret).update(val).digest('base64').replace(/\\=+$/, '');\n}\n\nfunction unsign(input: string, secret: string) {\n if (typeof input !== 'string') throw new TypeError(\"Signed cookie string must be provided.\");\n if (typeof secret !== 'string') throw new TypeError(\"Secret string must be provided.\");\n const tentValue = input.slice(0, input.lastIndexOf('.'));\n const expectedInput = sign(tentValue, secret);\n const expectedBuffer = Buffer.from(expectedInput);\n const inputBuffer = Buffer.from(input);\n if (expectedBuffer.length !== inputBuffer.length) return false;\n // timingSafeEqual\n // crypto.timingSafeEqual is available in node/bun\n const valid = require('crypto').timingSafeEqual(expectedBuffer, inputBuffer);\n return valid ? tentValue : false;\n}\n\n// --- Middleware ---\n\nexport interface SessionContext {\n session: SessionData & {\n id: string;\n regenerate(callback: (err: any) => void): void;\n destroy(callback: (err: any) => void): void;\n reload(callback: (err: any) => void): void;\n save(callback: (err: any) => void): void;\n touch(): void;\n };\n sessionID: string;\n sessionStore: Store;\n}\n\n// Merge into ShokupanContext? TODO: Review.\ndeclare module \"../context\" {\n interface ShokupanContext {\n session: SessionContext['session'];\n sessionID: string;\n sessionStore: Store;\n }\n}\n\nexport function Session(options: SessionOptions): Middleware {\n const store = options.store || new MemoryStore();\n const name = options.name || 'connect.sid';\n const secrets = Array.isArray(options.secret) ? options.secret : [options.secret];\n\n // Validate store\n // (Could add check for .get .set .destroy)\n\n const generateId = options.genid || (() => randomUUID());\n\n const resave = options.resave === undefined ? true : options.resave;\n const saveUninitialized = options.saveUninitialized === undefined ? true : options.saveUninitialized;\n const rolling = options.rolling || false;\n\n return async (ctx: ShokupanContext, next) => {\n // 1. Get Session ID from Cookie\n let reqSessionId: string | null = null;\n let isSigned = false;\n\n // Simple cookie parser\n const cookieHeader = ctx.req.headers.get(\"cookie\");\n const cookies: Record<string, string> = {};\n if (cookieHeader) {\n cookieHeader.split(';').forEach(c => {\n const [k, v] = c.split('=').map(s => s.trim());\n if (k && v) cookies[k] = decodeURIComponent(v);\n });\n }\n\n const rawCookie = cookies[name];\n\n if (rawCookie) {\n if (rawCookie.substr(0, 2) === 's:') {\n // Signed cookie\n const val = unsign(rawCookie.slice(2), secrets[0]);\n if (val) {\n reqSessionId = val as string;\n isSigned = true;\n }\n } else {\n reqSessionId = rawCookie;\n }\n }\n\n // 2. Generate new ID if none\n let sessionID = reqSessionId;\n let isNew = false;\n if (!sessionID) {\n sessionID = generateId(ctx);\n isNew = true;\n }\n\n // 3. Helper to wrap session object\n const createSessionObject = (data: SessionData | null): SessionContext['session'] => {\n const existing = data || { cookie: new Cookie(options.cookie) };\n if (!existing.cookie) existing.cookie = new Cookie(options.cookie);\n else {\n // re-hydrate cookie options methods\n const c = new Cookie(options.cookie); // defaults\n Object.assign(c, existing.cookie);\n // ensure expiry is date\n if (c.expires && typeof c.expires === 'string') c.expires = new Date(c.expires);\n existing.cookie = c;\n }\n\n const sessObj = existing as any;\n\n // Methods\n Object.defineProperty(sessObj, 'id', { value: sessionID, configurable: true });\n\n sessObj.save = (cb: any) => {\n store.set(sessObj.id, sessObj, cb);\n };\n\n sessObj.destroy = (cb: any) => {\n store.destroy(sessObj.id, (err) => {\n // TODO: clear cookie?\n if (cb) cb(err);\n });\n };\n\n sessObj.regenerate = (cb: any) => {\n store.destroy(sessObj.id, (err) => {\n sessionID = generateId(ctx);\n // Create new session object\n // We actually need to replace the whole ctx.session object, which is tricky inside a method of that object.\n // Typically middleware attaches a proxy or the consumer does this.\n // But here we can reset properties.\n for (const key in sessObj) {\n if (key !== 'cookie' && key !== 'id' && typeof sessObj[key] !== 'function') {\n delete sessObj[key];\n }\n }\n Object.defineProperty(sessObj, 'id', { value: sessionID, configurable: true });\n if (cb) cb(err);\n });\n };\n\n sessObj.undefined = () => { }; // Helper? no\n sessObj.reload = (cb: any) => {\n store.get(sessObj.id, (err, sess) => {\n if (err) return cb(err);\n if (!sess) return cb(new Error(\"Session not found\"));\n // Populate\n for (const key in sessObj) {\n if (key !== 'cookie' && key !== 'id' && typeof sessObj[key] !== 'function') {\n delete sessObj[key];\n }\n }\n Object.assign(sessObj, sess);\n cb(null);\n });\n };\n\n sessObj.touch = () => {\n // Reset maxAge\n sessObj.cookie.expires = new Date(Date.now() + (sessObj.cookie.maxAge || 0));\n if (store.touch) store.touch(sessObj.id, sessObj);\n };\n\n return sessObj;\n };\n\n // 4. Load Session from Store\n let sessionData: SessionData | null = null;\n\n if (!isNew && sessionID) {\n await new Promise<void>((resolve) => {\n store.get(sessionID!, (err, sess) => {\n if (err) {\n // if error, treat as new? or error?\n // express-session logs and creates new\n sessionID = generateId(ctx);\n isNew = true;\n } else if (!sess) {\n // Session expired or invalid\n sessionID = generateId(ctx);\n isNew = true;\n } else {\n sessionData = sess;\n }\n resolve();\n });\n });\n }\n\n const sess = createSessionObject(sessionData);\n\n ctx.session = sess;\n ctx.sessionID = sessionID!;\n ctx.sessionStore = store;\n\n // Hash original sessionStr to detect changes\n const originalHash = JSON.stringify(sess);\n\n // 5. Run next\n const result = await next();\n\n // 6. Save Logic\n const currentHash = JSON.stringify(sess);\n const isModified = originalHash !== currentHash;\n\n if (!sessionID) return result; // Destroyed?\n\n let shouldSave = false;\n\n if (isModified) {\n shouldSave = true;\n } else if (isNew && saveUninitialized) {\n shouldSave = true;\n } else if (!isNew && resave) {\n shouldSave = true;\n }\n\n if (shouldSave) {\n await new Promise<void>((resolve, reject) => {\n store.set(sessionID!, sess, (err) => {\n if (err) console.error(\"Failed to save session\", err);\n resolve();\n });\n });\n }\n\n // 7. Set Cookie\n // Only set if new, or modified (rolling)\n // Express-session rules:\n // - if cookie.expires is set, it might need updating if rolling is true\n // - if isNew is true, definitely set cookie\n\n if (rolling && sess.cookie.maxAge) {\n sess.cookie.expires = new Date(Date.now() + sess.cookie.maxAge);\n }\n\n const shouldSetCookie = shouldSave || (!isNew && rolling);\n\n if (shouldSetCookie) {\n // value is just ID, or signed ID\n let val = sessionID;\n // We do simple signing s:id\n // Not enforcing secrets[0] yet\n if (secrets.length > 0) {\n val = 's:' + sign(val, secrets[0]);\n }\n\n const options = sess.cookie;\n // Serialize\n const str = options.serialize(name, val);\n ctx.set(\"Set-Cookie\", str);\n }\n\n return result;\n };\n}\n","import { plainToInstance } from \"class-transformer\";\nimport { validateOrReject } from \"class-validator\";\nimport { ShokupanContext } from \"../context\";\nimport type { Middleware } from \"../types\";\n\nexport interface ValidationConfig {\n body?: any;\n query?: any;\n params?: any;\n headers?: any;\n}\n\nexport class ValidationError extends Error {\n public status = 400;\n constructor(public errors: any[]) {\n super(\"Validation Error\");\n }\n}\n\n// --- Adapters ---\n\nfunction isZod(schema: any): boolean {\n return typeof schema?.safeParse === 'function';\n}\n\nasync function validateZod(schema: any, data: any) {\n const result = await schema.safeParseAsync(data);\n if (!result.success) {\n throw new ValidationError(result.error.errors);\n }\n return result.data;\n}\n\nfunction isTypeBox(schema: any): boolean {\n return typeof schema?.Check === 'function' && typeof schema?.Errors === 'function';\n}\n\nfunction validateTypeBox(schema: any, data: any) {\n if (!schema.Check(data)) {\n throw new ValidationError([...schema.Errors(data)]);\n }\n return data;\n}\n\nfunction isAjv(schema: any): boolean {\n return typeof schema === 'function' && 'errors' in schema;\n}\n\nfunction validateAjv(schema: any, data: any) {\n const valid = schema(data);\n if (!valid) {\n throw new ValidationError(schema.errors);\n }\n return data;\n}\n\nexport const valibot = (schema: any, parser: Function) => {\n return {\n _valibot: true,\n schema,\n parser\n };\n};\n\nfunction isValibotWrapper(schema: any): boolean {\n return schema?._valibot === true;\n}\n\nasync function validateValibotWrapper(wrapper: any, data: any) {\n const result = await wrapper.parser(wrapper.schema, data);\n if (!result.success) {\n throw new ValidationError(result.issues);\n }\n return result.output;\n}\n\nfunction isClass(schema: any): boolean {\n // Check if it's a constructor for a class\n // Usually classes have names and are functions, but plain functions are also functions.\n // A robust check for a class constructor (especially with decorators) is tricky but checking for prototype \n // and if it looks like a constructor is a start.\n // However, for class-validator/transformer usages, compiling consumers typically pass the class Constructor.\n try {\n if (typeof schema === 'function' && /^\\s*class\\s+/.test(schema.toString())) {\n return true;\n }\n // Fallback for some complied outputs or if it just has a name and prototype\n // But we want to avoid treating `z.string()` (which might yield a function?) \n // actually Zod schemas are objects. Custom validation functions are functions.\n // We can assume if the user passes a class constructor it intends for class-validator.\n return typeof schema === 'function' && schema.prototype && schema.name;\n } catch {\n return false;\n }\n}\n\nasync function validateClassValidator(schema: any, data: any) {\n // Transform plain object to class instance\n const object = plainToInstance(schema, data);\n try {\n await validateOrReject(object as any);\n return object;\n } catch (errors: any) {\n // Flatten errors or just return them\n // class-validator returns Array<ValidationError>\n // We'll wrap in our ValidationError\n const formattedErrors = Array.isArray(errors)\n ? errors.map((err: any) => ({\n property: err.property,\n constraints: err.constraints,\n children: err.children\n }))\n : errors;\n\n throw new ValidationError(formattedErrors);\n }\n}\n\n\n// --- Body Helper ---\n\nconst safelyGetBody = async (ctx: ShokupanContext) => {\n const req = ctx.req as any;\n\n // Check if already parsed\n if (req._bodyParsed) {\n return req._bodyValue;\n }\n\n try {\n let data: any;\n // Standard Request consumes stream\n // ShokupanRequest (internal) has properties\n if (typeof req.json === 'function') {\n data = await req.json();\n }\n else {\n // Fallback if req is plain object with body property (internal usage)\n data = req.body;\n if (typeof data === 'string') {\n try { data = JSON.parse(data); } catch { }\n }\n }\n\n // Cache it\n req._bodyParsed = true;\n req._bodyValue = data;\n\n // Monkey patch json() to return cached data\n // This ensures subsequent calls (e.g. in handlers) get the same data\n // and don't fail due to stream locked\n Object.defineProperty(req, 'json', {\n value: async () => req._bodyValue,\n configurable: true\n });\n\n return data;\n } catch (e) {\n return {}; // Return empty object if parsing fails (flexible)\n }\n};\n\n\n// --- Main Middleware ---\n\nexport function validate(config: ValidationConfig): Middleware {\n return async (ctx: ShokupanContext, next) => {\n // Prepare data for beforeValidate hook\n const dataToValidate: any = {};\n if (config.params) dataToValidate.params = ctx.params;\n let queryObj: Record<string, string> | undefined;\n if (config.query) {\n const url = new URL(ctx.req.url);\n queryObj = Object.fromEntries(url.searchParams.entries());\n dataToValidate.query = queryObj;\n }\n if (config.headers) dataToValidate.headers = Object.fromEntries(ctx.req.headers.entries());\n\n let body: any;\n if (config.body) {\n body = await safelyGetBody(ctx);\n dataToValidate.body = body;\n }\n\n // Call beforeValidate Hook\n if (ctx.app?.applicationConfig.hooks?.beforeValidate) {\n await ctx.app.applicationConfig.hooks.beforeValidate(ctx, dataToValidate);\n }\n\n // Validate Params\n if (config.params) {\n ctx.params = await runValidation(config.params, ctx.params);\n }\n\n // Validate Query\n let validQuery: any;\n if (config.query && queryObj) {\n validQuery = await runValidation(config.query, queryObj);\n // We can't easily replace ctx.query as it is likely a getter wrapping URL\n // But we can store it in state\n // Or try to update URL search params?\n // If validation coerced types (e.g. string -> number), updating URL search params converts back to string.\n // So we attach to state.\n // (ctx.state as any).query = validQuery;\n }\n\n // Validate Headers\n if (config.headers) {\n const headersObj = Object.fromEntries(ctx.req.headers.entries());\n await runValidation(config.headers, headersObj);\n }\n\n // Validate Body\n let validBody: any;\n if (config.body) {\n // Re-use body accessed above or get again (it's cached)\n const b = body ?? await safelyGetBody(ctx);\n validBody = await runValidation(config.body, b);\n\n // Update cached body with validated/sanitized version\n const req = ctx.req as any;\n req._bodyValue = validBody;\n\n // Ensure json() returns the validated body\n Object.defineProperty(req, 'json', {\n value: async () => validBody,\n configurable: true\n });\n\n (ctx as any).body = validBody; // Legacy/Convenience\n }\n\n // Call afterValidate Hook\n if (ctx.app?.applicationConfig.hooks?.afterValidate) {\n const validatedData: any = { ...dataToValidate };\n if (config.params) validatedData.params = ctx.params;\n if (config.query) validatedData.query = validQuery;\n if (config.body) validatedData.body = validBody;\n // headers not easily updated on ctx in a way we can retrieve as \"validated object\" unless we return it\n\n await ctx.app.applicationConfig.hooks.afterValidate(ctx, validatedData);\n }\n\n return next();\n };\n}\n\nasync function runValidation(schema: any, data: any): Promise<any> {\n if (isZod(schema)) {\n return validateZod(schema, data);\n }\n if (isTypeBox(schema)) {\n return validateTypeBox(schema, data);\n }\n if (isAjv(schema)) {\n return validateAjv(schema, data);\n }\n if (isValibotWrapper(schema)) {\n return validateValibotWrapper(schema, data);\n }\n\n // Check custom function first? Or check Class first?\n // isClass might yield true for simple functions if our check is loose.\n // But if we use class-syntax check it's safer.\n // Let's try isClass specific check.\n if (isClass(schema)) {\n return validateClassValidator(schema, data);\n }\n if (isTypeBox(schema)) {\n return validateTypeBox(schema, data);\n }\n if (isAjv(schema)) {\n return validateAjv(schema, data);\n }\n if (isValibotWrapper(schema)) {\n return validateValibotWrapper(schema, data);\n }\n\n if (typeof schema === 'function') {\n return schema(data);\n }\n\n throw new Error(\"Unknown validator type provided. Please use a supported library (Zod, Ajv, TypeBox) or a custom function.\");\n}\n"],"names":["path","RouteParamType","Headers","trace","SpanKind","SpanStatusCode","fn","eta","Eta","resolve","join","basename","stat","readdir","AsyncLocalStorage","tracer","context","ctx","GitHub","Google","MicrosoftEntraId","Apple","Auth0","Okta","OAuth2Client","jose","generateState","generateCodeVerifier","defaults","OpenAPIAnalyzer","EventEmitter","createHmac","randomUUID","sess","options","plainToInstance","validateOrReject"],"mappings":"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"}