shokupan 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1669 -0
- package/dist/cli/index.d.ts +2 -0
- package/dist/cli.cjs +154 -0
- package/dist/cli.cjs.map +1 -0
- package/dist/cli.js +136 -0
- package/dist/cli.js.map +1 -0
- package/dist/context.d.ts +88 -0
- package/dist/decorators.d.ts +23 -0
- package/dist/di.d.ts +18 -0
- package/dist/index.cjs +2305 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.ts +18 -0
- package/dist/index.js +2288 -0
- package/dist/index.js.map +1 -0
- package/dist/middleware.d.ts +7 -0
- package/dist/plugins/auth.d.ts +58 -0
- package/dist/plugins/compression.d.ts +5 -0
- package/dist/plugins/cors.d.ts +11 -0
- package/dist/plugins/express.d.ts +6 -0
- package/dist/plugins/rate-limit.d.ts +12 -0
- package/dist/plugins/scalar.d.ts +13 -0
- package/dist/plugins/security-headers.d.ts +36 -0
- package/dist/plugins/session.d.ts +87 -0
- package/dist/plugins/validation.d.ts +18 -0
- package/dist/request.d.ts +34 -0
- package/dist/response.d.ts +42 -0
- package/dist/router.d.ts +237 -0
- package/dist/shokupan.d.ts +41 -0
- package/dist/symbol.d.ts +13 -0
- package/dist/types.d.ts +142 -0
- package/dist/util/async-hooks.d.ts +3 -0
- package/dist/util/deep-merge.d.ts +12 -0
- package/dist/util/instrumentation.d.ts +9 -0
- package/package.json +82 -0
|
@@ -0,0 +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":"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"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
export * from './context';
|
|
2
|
+
export * from './decorators';
|
|
3
|
+
export * from './di';
|
|
4
|
+
export * from './middleware';
|
|
5
|
+
export * from './request';
|
|
6
|
+
export * from './response';
|
|
7
|
+
export * from './router';
|
|
8
|
+
export * from './shokupan';
|
|
9
|
+
export * from './symbol';
|
|
10
|
+
export * from './types';
|
|
11
|
+
export * from './plugins/auth';
|
|
12
|
+
export * from './plugins/compression';
|
|
13
|
+
export * from './plugins/cors';
|
|
14
|
+
export * from './plugins/rate-limit';
|
|
15
|
+
export * from './plugins/scalar';
|
|
16
|
+
export * from './plugins/security-headers';
|
|
17
|
+
export * from './plugins/session';
|
|
18
|
+
export * from './plugins/validation';
|