oakbun 0.2.1 → 0.2.2
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/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/events/index.ts","../src/errors/index.ts","../src/app/logger.ts","../src/app/types.ts","../src/db/sql.ts","../src/db/index.ts","../src/index.ts","../src/adapter/resolve.ts","../src/schema/column.ts","../src/schema/table.ts","../src/schema/audit.ts","../src/hooks/executor.ts","../src/db/migrations/runner.ts","../src/db/migrations/tracker.ts","../src/db/migrations/migrator.ts","../src/db/migrations/generator.ts","../src/db/migrations/introspect.ts","../src/db/migrations/diff.ts","../src/events/handler.ts","../src/model/index.ts","../src/service/index.ts","../src/app/middleware.ts","../src/app/index.ts","../src/openapi/zod-to-schema.ts","../src/openapi/generator.ts","../src/cron/index.ts","../src/app/system-ctx.ts","../src/app/router.ts","../src/app/audit-wiring.ts","../src/app/cookies.ts","../src/app/module.ts","../src/app/plugin.ts","../src/app/secure-headers.ts","../src/app/rate-limit.ts","../src/app/csrf.ts","../src/app/scalar.ts","../src/app/body-size-limit.ts","../src/app/cors.ts","../src/app/request-id.ts","../src/app/compression.ts","../src/app/health.ts","../src/client/error.ts","../src/client/proxy.ts","../src/client/test-client.ts","../src/client/index.ts","../src/resource/zod-table.ts","../src/resource/errors.ts","../src/resource/index.ts","../src/cli/config/types.ts"],"sourcesContent":["import type { PendingEvent } from '../db/index'\n\nexport type EventHandler = (payload: unknown, ctx: unknown) => Promise<void> | void\n\n// ── RequestEventQueue ────────────────────────────────────────────────────────\n// Per-request buffer. HookExecutor collects events here instead of emitting\n// immediately. fetch() flushes the queue after onResponse — guaranteeing that\n// events never fire on guard block, handler error, or rollback.\n\nexport class RequestEventQueue {\n private readonly buffer: PendingEvent[] = []\n\n collect(name: string, payload: unknown): void {\n this.buffer.push({ name, payload })\n }\n\n async flush(ctx: unknown, bus: EventBusAdapter | InMemoryEventBus): Promise<void> {\n const events = this.buffer.splice(0)\n for (const e of events) {\n if ('_emit' in bus) {\n (bus as InMemoryEventBus)._emit(e.name, e.payload, ctx)\n } else {\n await bus.emit(e.name, e.payload)\n }\n }\n }\n\n /** Drain — returns collected events and clears the buffer.\n * Used by the TX path to hand events off to TransactionResult. */\n drain(): PendingEvent[] {\n return this.buffer.splice(0)\n }\n\n /** Number of buffered events — useful in tests. */\n get size(): number {\n return this.buffer.length\n }\n}\n\n// VelnEvents — opt-in Declaration Merging escape hatch.\n//\n// STAGING NOTE (Phase 3 → Phase 4):\n// app.on() currently accepts `event: string` because module registration erases\n// the Table's generic types. InferTableEvents<T, M> is already fully defined in\n// schema/table.ts — Phase 4 will wire it into app.on() via a typed overload that\n// accepts Table references directly, making this Declaration Merging unnecessary\n// for Table-derived events. Use VelnEvents only for events without a Table source\n// (e.g. 'app.started', 'request.error').\nexport interface VelnEvents {}\n\nexport type EventBusErrorHandler = (event: string, error: unknown) => void\n\nexport interface EventBusOptions {\n /** Called when an event handler throws. Defaults to console.error. */\n onError?: EventBusErrorHandler\n}\n\n/**\n * EventBusAdapter — minimal interface for event bus implementations.\n *\n * Default: InMemoryEventBus (single-process, zero latency)\n *\n * For multi-worker deployments: BroadcastChannelAdapter (@oakbun/broadcast, roadmap)\n * For multi-server deployments: RedisAdapter (@oakbun/redis, roadmap)\n *\n * NOTE: EventBus is single-process by default. Events fired on instance A\n * will NOT reach instance B without a distributed adapter.\n */\nexport interface EventBusAdapter {\n on(event: string, handler: (payload: unknown) => void): void\n emit(event: string, payload: unknown): Promise<void>\n}\n\nexport class InMemoryEventBus {\n private readonly handlers = new Map<string, EventHandler[]>()\n private readonly _onError: EventBusErrorHandler\n\n constructor(options?: EventBusOptions) {\n this._onError = options?.onError ??\n ((event, err) => console.error(`[EventBus] Error in handler for \"${event}\":`, err))\n }\n\n // Typed overload for events declared via VelnEvents Declaration Merging\n on<K extends keyof VelnEvents>(\n event: K,\n handler: (payload: VelnEvents[K], ctx: unknown) => Promise<void> | void,\n ): this\n // String fallback — Phase 4 will add a Table-reference overload here that uses\n // InferTableEvents<T, M> directly, making Declaration Merging unnecessary for\n // Table-derived events.\n on(event: string, handler: EventHandler): this\n on(event: string, handler: EventHandler): this {\n if (!this.handlers.has(event)) this.handlers.set(event, [])\n this.handlers.get(event)!.push(handler)\n return this\n }\n\n // _emit — internal. fire & forget — errors in handlers are caught by onError, never thrown.\n // Only HookExecutor and flush() call this. Underscore signals \"not for user-code\".\n _emit(event: string, payload: unknown, ctx: unknown): void {\n const handlers = this.handlers.get(event) ?? []\n for (const h of handlers) {\n // Wrap in Promise constructor to catch both sync throws and async rejections\n new Promise<void>((resolve) => resolve(h(payload, ctx) as void)).catch((err) =>\n this._onError(event, err)\n )\n }\n }\n\n // EventBusAdapter.emit — ctx-free emit for external adapter compatibility.\n // Calls _emit with undefined ctx — handlers that need ctx are registered via on() directly.\n async emit(event: string, payload: unknown): Promise<void> {\n this._emit(event, payload, undefined)\n }\n\n // flush pending events after transaction commit\n async flush(events: PendingEvent[], ctx: unknown): Promise<void> {\n for (const e of events) {\n this._emit(e.name, e.payload, ctx)\n }\n }\n}\n\n/** @deprecated Use InMemoryEventBus instead. EventBus will be removed in a future version. */\nexport const EventBus = InMemoryEventBus\nexport type EventBus = InMemoryEventBus\n","export class VelnError extends Error {\n constructor(\n message: string,\n readonly status: number,\n readonly code: string,\n ) {\n super(message)\n this.name = 'VelnError'\n }\n}\n\nexport class BadRequestError extends VelnError {\n constructor(message = 'Bad Request', code = 'BAD_REQUEST') {\n super(message, 400, code)\n this.name = 'BadRequestError'\n }\n}\n\nexport class UnauthorizedError extends VelnError {\n constructor(message = 'Unauthorized', code = 'UNAUTHORIZED') {\n super(message, 401, code)\n this.name = 'UnauthorizedError'\n }\n}\n\nexport class ForbiddenError extends VelnError {\n constructor(message = 'Forbidden', code = 'FORBIDDEN') {\n super(message, 403, code)\n this.name = 'ForbiddenError'\n }\n}\n\nexport class NotFoundError extends VelnError {\n constructor(message = 'Not Found', code = 'NOT_FOUND') {\n super(message, 404, code)\n this.name = 'NotFoundError'\n }\n}\n\nexport class ConflictError extends VelnError {\n constructor(message = 'Conflict', code = 'CONFLICT') {\n super(message, 409, code)\n this.name = 'ConflictError'\n }\n}\n\nexport class UnprocessableError extends VelnError {\n constructor(message = 'Unprocessable Entity', code = 'UNPROCESSABLE') {\n super(message, 422, code)\n this.name = 'UnprocessableError'\n }\n}\n\nexport class TooManyRequestsError extends VelnError {\n constructor(message = 'Too Many Requests', code = 'TOO_MANY_REQUESTS') {\n super(message, 429, code)\n this.name = 'TooManyRequestsError'\n }\n}\n\nexport class InternalError extends VelnError {\n constructor(message = 'Internal Server Error', code = 'INTERNAL_ERROR') {\n super(message, 500, code)\n this.name = 'InternalError'\n }\n}\n","import type { Logger, LogOptions } from './types'\n\n// ── LogLevel ──────────────────────────────────────────────────────────────────\n\nexport type LogLevel = 'debug' | 'info' | 'warn' | 'error'\n\nconst LEVEL_ORDER: Record<LogLevel, number> = {\n debug: 0,\n info: 1,\n warn: 2,\n error: 3,\n}\n\n// ── ANSI ──────────────────────────────────────────────────────────────────────\n\nconst RESET = '\\x1b[0m'\nconst DIM = '\\x1b[2m'\n\nconst SCOPE_COLORS: Record<string, string> = {\n service: '\\x1b[34m', // Blue\n model: '\\x1b[36m', // Cyan\n plugin: '\\x1b[35m', // Magenta\n cron: '\\x1b[33m', // Yellow\n guard: '\\x1b[31m', // Red\n middleware: '\\x1b[32m', // Green\n event: '\\x1b[38;5;208m', // Orange\n module: '\\x1b[34m', // Blue\n resource: '\\x1b[36m', // Cyan\n}\n\nconst LEVEL_COLORS: Record<LogLevel, string> = {\n debug: '\\x1b[2m', // Dim\n info: '', // No extra color — scope is enough\n warn: '\\x1b[33m', // Yellow\n error: '\\x1b[31m', // Red\n}\n\n// TTY detection — no ANSI in pipes/files\nconst isTTY: boolean = process.stdout.isTTY ?? false\n\nfunction colorScope(scope: string): string {\n if (!isTTY) return `[${scope}]`\n const prefix = scope.split(':')[0]\n const color = SCOPE_COLORS[prefix] ?? ''\n return `${color}[${scope}]${RESET}`\n}\n\nfunction formatData(\n data: Record<string, unknown>,\n maskKeys: Set<string>,\n): string {\n const entries = Object.entries(data)\n if (entries.length === 0) return ''\n\n const masked: Array<[string, unknown]> = entries.map(([k, v]) => [\n k,\n maskKeys.has(k.toLowerCase()) ? '***' : v,\n ])\n\n if (masked.length <= 3) {\n const inline = masked\n .map(([k, v]) => (isTTY ? `${DIM}${k}${RESET}=${JSON.stringify(v)}` : `${k}=${JSON.stringify(v)}`))\n .join(' ')\n return ` ${inline}`\n }\n\n const lines = masked\n .map(([k, v]) => (isTTY ? ` ${DIM}${k}${RESET}=${JSON.stringify(v)}` : ` ${k}=${JSON.stringify(v)}`))\n .join('\\n')\n return `\\n${lines}`\n}\n\n// ── createMinimalLogger ───────────────────────────────────────────────────────\n// Pure console-based logger — no @veln/logger dependency.\n// Used by defineService (.options({ log })), defineModel (.options({ log })),\n// and defineCron (.options({ log })) when no external logger plugin is registered.\n\nexport function createMinimalLogger(scope: string, opts?: LogOptions): Logger {\n if (opts?.silent) return noopLogger()\n\n const minLevel = LEVEL_ORDER[opts?.level ?? 'info']\n const maskKeys = new Set((opts?.mask ?? []).map((k) => k.toLowerCase()))\n const scopeLabel = colorScope(scope)\n\n function log(method: LogLevel, msg: string, args: unknown[]): void {\n if (LEVEL_ORDER[method] < minLevel) return\n\n // Extract first object arg as structured data\n const [first, ...rest] = args\n const isDataObj =\n first !== null &&\n first !== undefined &&\n typeof first === 'object' &&\n !Array.isArray(first)\n\n const dataStr = isDataObj\n ? formatData(first as Record<string, unknown>, maskKeys)\n : ''\n\n const levelColor = isTTY ? LEVEL_COLORS[method] : ''\n const msgPart = levelColor ? `${levelColor}${msg}${RESET}` : msg\n const line = `${scopeLabel} ${msgPart}${dataStr}`\n\n // Remaining args (beyond the first data object) appended as-is\n const extra = isDataObj ? rest : args\n\n if (method === 'error') {\n console.error(line, ...extra)\n } else if (method === 'warn') {\n console.warn(line, ...extra)\n } else {\n console.log(line, ...extra)\n }\n }\n\n return {\n info(msg: string, ...args: unknown[]) { log('info', msg, args) },\n warn(msg: string, ...args: unknown[]) { log('warn', msg, args) },\n error(msg: string, ...args: unknown[]) { log('error', msg, args) },\n debug(msg: string, ...args: unknown[]) { log('debug', msg, args) },\n }\n}\n\nfunction noopLogger(): Logger {\n return {\n debug: () => {},\n info: () => {},\n warn: () => {},\n error: () => {},\n }\n}\n","import type { EventBus, VelnEvents } from '../events/index'\nimport type { BoundVelnDB } from '../db/index'\nimport type { ZodTypeAny, ZodIssue } from 'zod'\nimport { VelnError } from '../errors/index'\nimport { createMinimalLogger } from './logger'\n\n// ── VelnWsAdapter — extension point for @veln/ws ─────────────────────────────\n// Core holds only this minimal interface. @veln/ws provides the full implementation.\n// Registered via app.registerWsAdapter(adapter).\nexport interface VelnWsAdapter {\n /** Called in fetch() when an HTTP Upgrade: websocket request arrives. */\n handleUpgrade(\n req: Request,\n server: import('bun').Server<unknown>,\n baseCtx: BaseCtx,\n plugins: ReadonlyArray<import('./plugin').Plugin<any, any>>,\n installedPlugins: { value: boolean },\n installedModulePlugins: Set<string>,\n ): Promise<Response | null>\n /** Returns the Bun websocket handler config. Passed to Bun.serve(). */\n getWebsocketConfig(): import('bun').WebSocketHandler<Record<string, unknown>>\n /** Registers a WS route. Called from app.ws() and app.register(). */\n registerRoute(path: string, route: WsRouteShape): void\n /** Reads all registered WS routes — used by module registration. */\n getRoute(path: string): WsRouteShape | undefined\n}\n\n/** Minimal WS route shape that Core knows about. Full type lives in @veln/ws. */\nexport interface WsRouteShape {\n path: string\n _module: unknown | null\n [key: string]: unknown\n}\n\n\n// ── Auth Payload ──────────────────────────────────────────────────────────────\n// Minimal JWT/session payload shape used by WsCtx and plugins.\n// @veln/jwt re-exports this as JwtPayload for backward compatibility.\nexport interface AuthPayload {\n sub?: string\n iat?: number\n exp?: number\n nbf?: number\n aud?: string | string[]\n iss?: string\n jti?: string\n [key: string]: unknown\n}\n\n// Key-Format: 'GET /users/:id'\nexport type RouteKey = `${'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE'} /${string}`\n\nexport interface RouteEntry {\n params?: ZodTypeAny\n query?: ZodTypeAny\n body?: ZodTypeAny\n response?: ZodTypeAny\n // Phantom field — carries the module prefix so InferProxyClient can group routes.\n // Never set at runtime. Only present when registered via defineModule().\n readonly _prefix?: string\n}\n\nexport type RouteMap = Record<RouteKey, RouteEntry>\n\n// ValidationError — thrown by validation middleware, caught by error cascade\nexport class ValidationError extends VelnError {\n readonly issues: ZodIssue[]\n\n constructor(zodError: import('zod').ZodError) {\n super('Validation failed', 422, 'VALIDATION_ERROR')\n this.name = 'ValidationError'\n this.issues = zodError.issues\n }\n}\n\n// Route Schema — all fields optional\nexport interface RouteSchema {\n params?: ZodTypeAny\n query?: ZodTypeAny\n body?: ZodTypeAny\n response?: ZodTypeAny // runtime no-op in Phase 4a — used by Phase 4b RPC Client\n}\n\n/** Additional response code definition for OpenAPI docs (e.g. 401, 404). */\nexport interface RouteResponseDoc {\n description: string\n}\n\n// RouteDocs — optional OpenAPI documentation override per route\nexport interface RouteDocs {\n /** Human-readable route summary shown in Scalar / Swagger UI. Auto-generated if absent. */\n summary?: string\n /** Longer description rendered below the summary. Markdown supported. */\n description?: string\n /** Unique operationId. Auto-generated if absent (e.g. \"listUsers\", \"getUserById\"). */\n operationId?: string\n /**\n * Additional HTTP response codes to document in the OpenAPI spec.\n * The 200 success response is always generated automatically.\n * Use this to document error responses like 401, 403, 404, 422, etc.\n *\n * @example\n * docs: {\n * responses: {\n * 401: { description: 'Unauthorized' },\n * 404: { description: 'Not found' },\n * }\n * }\n */\n responses?: Record<number, RouteResponseDoc>\n}\n\n// Typed ctx when schemas are defined\nexport type InferCtx<TCtx, S extends RouteSchema> = Omit<TCtx, 'params' | 'query'> & {\n params: S['params'] extends ZodTypeAny ? import('zod').infer<S['params']> : Record<string, string>\n query: S['query'] extends ZodTypeAny ? import('zod').infer<S['query']> : Record<string, string | string[]>\n body: S['body'] extends ZodTypeAny ? import('zod').infer<S['body']> : unknown\n}\n\n// Extended RouteHandler — supports optional schema\nexport interface RouteHandlerWithSchema<TCtx, S extends RouteSchema> {\n params?: S['params']\n query?: S['query']\n body?: S['body']\n response?: S['response']\n /** Optional OpenAPI documentation override for this route. */\n docs?: RouteDocs\n /** Optional route-level guard — runs before the handler. Use `false` to opt out of a module-level guard. */\n guard?: Guard<TCtx> | false\n handler: (ctx: InferCtx<TCtx, S>) => Response | Promise<Response>\n}\n\n// ─── Streaming Support ────────────────────────────────────────────────────────\n\n/** Controls a streaming response. Passed to the ctx.stream() writer callback. */\nexport interface StreamController {\n /** Push a string or binary chunk to the stream. */\n send(chunk: string | Uint8Array): void\n /** Close the stream. Must be called to end the response. */\n close(): void\n}\n\n/** Options for ctx.stream(). */\nexport interface StreamOptions {\n /**\n * Content-Type header for the streaming response.\n * Defaults to `'text/plain'`.\n * Use `'text/event-stream'` for SSE, `'application/x-ndjson'` for NDJSON.\n */\n contentType?: string\n /** Additional headers to include in the response. */\n headers?: Record<string, string>\n /** HTTP status code. Defaults to 200. */\n status?: number\n}\n\n// ─── SSE Support ──────────────────────────────────────────────────────────────\n\n/**\n * Controls a Server-Sent Events stream.\n * Passed to the ctx.sse() writer callback.\n *\n * SSE wire format:\n * event: <name>\\ndata: <json>\\n\\n — named event\n * data: <json>\\n\\n — unnamed event\n * : <text>\\n\\n — comment / keepalive\n * id: <value>\\n — event ID for reconnect\n * retry: <ms>\\n — reconnect interval\n */\nexport interface SseController {\n /** Send a named event with a JSON-serializable payload. */\n event(name: string, data: unknown): Promise<void>\n /** Send an unnamed data event. */\n data(data: unknown): Promise<void>\n /** Send an SSE comment (e.g. keepalive ping). */\n comment(text?: string): Promise<void>\n /** Set the last event ID (used by the browser for reconnect). */\n id(id: string): Promise<void>\n /** Tell the browser how long to wait before reconnecting (milliseconds). */\n retry(ms: number): Promise<void>\n}\n\n// Logger interface — no external dependency\nexport interface Logger {\n info(msg: string, ...args: unknown[]): void\n warn(msg: string, ...args: unknown[]): void\n error(msg: string, ...args: unknown[]): void\n debug(msg: string, ...args: unknown[]): void\n}\n\n// LogOptions — controls the minimal logger behaviour across all define* builders\nexport interface LogOptions {\n /** Minimum level to emit. Defaults to 'info'. */\n level?: 'debug' | 'info' | 'warn' | 'error'\n /** Keys whose values are replaced with '***' in structured data. Case-insensitive. */\n mask?: string[]\n /** Suppress all output — useful in tests. */\n silent?: boolean\n}\n\n// BaseOptions — base for all define* builder .options() calls\nexport interface BaseOptions {\n log?: LogOptions\n}\n\n// ── AuthAdapter — minimal auth interface ──────────────────────────────────────\n// Core only knows this interface. The concrete implementation lives in @oakbun/auth.\n// Passed to createApp({ auth }) — if omitted the app works without auth.\n\nexport interface AuthUser {\n id: string\n permissions: string[]\n}\n\nexport interface AuthAdapter {\n getUser(ctx: BaseCtx): Promise<AuthUser | null>\n hasPermission(user: AuthUser, permission: string): boolean\n}\n\n// ── BaseCtx — available in every request handler ──────────────────────────────\n// ctx.events is optional — only present when eventBusPlugin() is registered\n// ctx.db is optional — only present when dbPlugin() is registered\n// ctx.logger is optional — only present when loggerPlugin() is registered\nexport interface BaseCtx {\n req: Request\n params: Record<string, string>\n query: Record<string, string | string[]>\n body?: unknown // populated by validation middleware when body schema is defined\n json: <T>(data: T, status?: number) => Response\n text: (data: string, status?: number) => Response\n html: (data: string, status?: number) => Response\n /**\n * Returns a streaming Response backed by a ReadableStream.\n *\n * The callback receives a StreamController — call `send(chunk)` to push data\n * and `close()` to end the stream. Errors thrown inside are caught automatically.\n *\n * Set `contentType` for SSE (`'text/event-stream'`) or NDJSON (`'application/x-ndjson'`).\n * Compression is automatically skipped for streaming responses.\n *\n * @example\n * return ctx.stream((stream) => {\n * stream.send('data: hello\\n\\n')\n * stream.send('data: world\\n\\n')\n * stream.close()\n * }, { contentType: 'text/event-stream' })\n */\n stream: (\n writer: (controller: StreamController) => void | Promise<void>,\n options?: StreamOptions,\n ) => Response\n /**\n * Returns a Server-Sent Events Response.\n *\n * The callback receives an SseController — call `event()`, `data()`,\n * `comment()`, `id()`, or `retry()` to push SSE frames, then let the\n * callback return (or the async iterator complete) to close the stream.\n *\n * @example\n * return ctx.sse(async (sse) => {\n * await sse.event('connected', { userId: '42' })\n * for await (const update of source()) {\n * await sse.event('update', update)\n * await sse.comment('keepalive')\n * }\n * })\n */\n sse: (writer: (controller: SseController) => void | Promise<void>) => Response\n events?: EventBus\n logger?: Logger\n db?: BoundVelnDB\n cookie: import('./cookies').CookieJar\n // Typed event emission into the per-request RequestEventQueue.\n // Fire & forget — buffered until after onResponse, then flushed to EventBus.\n emit: <K extends keyof VelnEvents>(event: K, payload: VelnEvents[K]) => void\n // _requestQueue: framework-internal. Set by fetch() before plugins run.\n // dbPlugin reads it to bind the queue to BoundVelnDB.\n // Never exposed to user-land handlers — prefixed _ to signal framework-only.\n _requestQueue?: import('../events/index').RequestEventQueue\n // _queryLog: framework-internal. Set by fetch() when N+1 detection is enabled.\n // dbPlugin reads it and passes it to BoundVelnDB to count queries per request.\n // Never exposed to user-land handlers — prefixed _ to signal framework-only.\n _queryLog?: import('../db/index').QueryLog\n // _startTime: optional timing field, set by timing middleware.\n _startTime?: number\n}\n\n// Guard — pure predicate, never extends ctx\nexport type Guard<TCtx> = (ctx: TCtx) => Response | null | Promise<Response | null>\n\n// createGuard — typing helper. TAdd is the ctx extension the guard needs.\n// BaseCtx is always present — user only declares what they add on top.\n// @deprecated Use defineGuard() for the fluent builder API.\nexport function createGuard<TAdd extends object = object>(\n fn: (ctx: BaseCtx & TAdd) => Response | null | Promise<Response | null>,\n): Guard<BaseCtx & TAdd> {\n return fn\n}\n\n// ── defineGuard — fluent builder ──────────────────────────────────────────────\n\n/**\n * defineGuard — creates a named guard that protects routes or modules.\n *\n * Call `.check(fn)` to seal into a `Guard`. Throw any error or return a `Response`\n * inside `fn` to block the request; return normally to allow it through.\n *\n * @param name Used in log output for tracing which guard triggered.\n *\n * @example\n * const authGuard = defineGuard('auth')\n * .check<{ user: AuthUser }>((ctx) => {\n * if (!ctx.user) throw new UnauthorizedError()\n * })\n */\nclass GuardBuilder {\n private _options: BaseOptions = {}\n\n constructor(private readonly _name: string) {}\n\n options(opts: BaseOptions): this {\n this._options = opts\n return this\n }\n\n check<TAdd extends object = object>(\n fn: (ctx: BaseCtx & TAdd) => void | Promise<void>,\n ): Guard<BaseCtx & TAdd> {\n const logger = createMinimalLogger(`guard:${this._name}`, this._options.log)\n const name = this._name\n return async (ctx: BaseCtx & TAdd): Promise<Response | null> => {\n logger.debug('check', { guard: name })\n try {\n await fn(ctx)\n return null\n } catch (err) {\n logger.warn('blocked', { guard: name })\n throw err\n }\n }\n }\n}\n\n/** @see GuardBuilder */\nexport function defineGuard(name: string): GuardBuilder {\n return new GuardBuilder(name)\n}\n\n// ErrorHandler\nexport type ErrorHandler<TCtx = BaseCtx> = (err: unknown, ctx: TCtx) => Response | Promise<Response>\n\n// Route handler — object style so Phase 4 can add body/params/query schemas non-breakingly\nexport interface RouteHandler<TCtx> {\n handler: (ctx: TCtx) => Response | Promise<Response>\n}\n\n// ─── Lifecycle Hook Types ──────────────────────────────────────────────────────\n//\n// Three distinct phases — framework always runs them in this order regardless\n// of registration order:\n// 1. onRequest — fires before plugins; always runs (even on guard block / plugin error)\n// 2. onBeforeHandle — fires after guards pass; skipped when a guard blocks\n// 3. onResponse — fires after handler (or after error); always runs\n//\n// TCtx for onRequest is BaseCtx (plugins not yet applied).\n// TCtx for onBeforeHandle / onResponse is the full ctx including plugin extensions.\n\n// onRequest: receives raw BaseCtx — plugins have NOT run yet.\n// Return a Response to short-circuit (replaces 404 / guard / handler entirely).\n// Return void to continue.\nexport type OnRequestFn<TCtx extends BaseCtx = BaseCtx> = (\n ctx: TCtx,\n) => Response | void | Promise<Response | void>\n\n// onBeforeHandle: runs after guards pass, before handler.\n// Return a Response to short-circuit the handler.\n// Return void to continue.\nexport type OnBeforeHandleFn<TCtx extends BaseCtx = BaseCtx> = (\n ctx: TCtx,\n) => Response | void | Promise<Response | void>\n\n// onResponse: always runs; receives the final response (or undefined on plugin/guard error\n// before a response was produced — framework provides a 500 fallback in that case).\n// Return a new Response to replace it, or void to keep the current response.\nexport type OnResponseFn<TCtx extends BaseCtx = BaseCtx> = (\n ctx: TCtx,\n response: Response,\n) => Response | void | Promise<Response | void>\n\n// Tagged wrappers — distinguishable from plain functions at runtime\nexport interface OnRequestHook<TCtx extends BaseCtx = BaseCtx> {\n readonly _phase: 'onRequest'\n readonly _fn: OnRequestFn<TCtx>\n}\n\nexport interface OnBeforeHandleHook<TCtx extends BaseCtx = BaseCtx> {\n readonly _phase: 'onBeforeHandle'\n readonly _fn: OnBeforeHandleFn<TCtx>\n}\n\nexport interface OnResponseHook<TCtx extends BaseCtx = BaseCtx> {\n readonly _phase: 'onResponse'\n readonly _fn: OnResponseFn<TCtx>\n}\n\n// ─── createX helpers ──────────────────────────────────────────────────────────\n// TAdd is the ctx extension needed; user doesn't write BaseCtx & TAdd\n\nexport function createOnRequest<TAdd extends object = object>(\n fn: OnRequestFn<BaseCtx & TAdd>,\n): OnRequestHook<BaseCtx & TAdd> {\n return { _phase: 'onRequest', _fn: fn }\n}\n\nexport function createOnBeforeHandle<TAdd extends object = object>(\n fn: OnBeforeHandleFn<BaseCtx & TAdd>,\n): OnBeforeHandleHook<BaseCtx & TAdd> {\n return { _phase: 'onBeforeHandle', _fn: fn }\n}\n\nexport function createOnResponse<TAdd extends object = object>(\n fn: OnResponseFn<BaseCtx & TAdd>,\n): OnResponseHook<BaseCtx & TAdd> {\n return { _phase: 'onResponse', _fn: fn }\n}\n\n// Internal route record\nexport interface Route<TCtx = BaseCtx> {\n method: 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE'\n path: string // e.g. '/users/:id'\n summary?: string\n description?: string\n /** OpenAPI documentation override set via the `docs` option on route registration. */\n docs?: RouteDocs\n handler: RouteHandler<TCtx>\n guards: Guard<TCtx>[]\n onError?: ErrorHandler<TCtx>\n schema?: RouteSchema\n visibility?: 'public' | 'hidden'\n // Set when the route definition has guard: false — skips module-level guards for this route.\n moduleGuardOptOut?: true\n // Reference to the module this route belongs to (set during registration)\n _module?: import('./module').VelnModule\n // Plugin that contributed this route via .modules() — set by app.plugin() so the\n // permission check in _runRoute can look up the right plugin without a separate Map.\n _pluginName?: string\n}\n","import type { BindingValue } from '../adapter/types'\nimport type { TableDef, SchemaMap } from '../schema/table'\nimport type { Column } from '../schema/column'\nimport { VelnError } from '../errors/index'\n\n// ── SubqueryResult ────────────────────────────────────────────────────────────\n\n/**\n * Phantom-typed wrapper for a subquery SQL fragment.\n * Col and T are used only at compile time — _phantom is never read at runtime.\n *\n * Produced by SelectBuilder.columns(col).subquery().\n * Accepted by WhereOp IN / NOT IN in place of an array.\n */\nexport interface SubqueryResult<Col extends string, T> {\n readonly _sql: string\n readonly _params: BindingValue[]\n readonly _phantom: { col: Col; type: T }\n}\n\n/**\n * Build a SubqueryResult from a complete SELECT SQL string + params.\n * Wraps the SQL in parentheses (required by SQL syntax).\n *\n * The T generic is a phantom — it is never instantiated at runtime.\n * The only permitted cast in this file is `undefined as unknown as T`.\n */\nexport function buildSubquery<Col extends string, T>(\n sql: string,\n params: BindingValue[],\n col: Col,\n): SubqueryResult<Col, T> {\n if (!sql) throw new Error('buildSubquery: sql must not be empty')\n return {\n _sql: `(${sql})`,\n _params: params,\n _phantom: { col, type: undefined as unknown as T },\n }\n}\n\n// ── JOIN types ────────────────────────────────────────────────────────────────\n\nexport interface JoinClause {\n type: 'INNER' | 'LEFT' | 'RIGHT' | 'FULL'\n table: string\n on: string\n}\n\n// ── validateAndQuoteOnClause ──────────────────────────────────────────────────\n// Validates and quotes a JOIN ON clause to prevent SQL injection.\n// Only allows the format: word.word = word.word (table.column = table.column)\n// Throws VelnError(500, INVALID_JOIN_ON) for anything that doesn't match.\n\nconst ON_CLAUSE_PATTERN = /^([\\w]+)\\.([\\w]+)\\s*=\\s*([\\w]+)\\.([\\w]+)$/\n\nexport function validateAndQuoteOnClause(on: string): string {\n const trimmed = on.trim()\n const match = ON_CLAUSE_PATTERN.exec(trimmed)\n if (!match) {\n throw new VelnError(\n `Invalid JOIN ON clause: \"${on}\". Must be in format \"table.column = table.column\"`,\n 500,\n 'INVALID_JOIN_ON',\n )\n }\n const [, t1, c1, t2, c2] = match\n return `\"${t1}\".\"${c1}\" = \"${t2}\".\"${c2}\"`\n}\n\n// ── WHERE operator types ──────────────────────────────────────────────────────\n\n/** SQL dialect — used for ILIKE fallback on non-Postgres adapters. */\nexport type SqlDialect = 'sqlite' | 'postgres' | 'mysql'\n\n/** Accepted value for IN / NOT IN — either a plain array or a typed subquery. */\nexport type InValue<T> = T[] | SubqueryResult<string, T>\n\n/** Explicit operator condition for a single column. */\nexport type WhereOp<T> =\n | { op: '='; value: T }\n | { op: '!='; value: T }\n | { op: '>'; value: T }\n | { op: '>='; value: T }\n | { op: '<'; value: T }\n | { op: '<='; value: T }\n | { op: 'IN'; value: InValue<T> }\n | { op: 'NOT IN'; value: InValue<T> }\n | { op: 'LIKE'; value: string }\n | { op: 'ILIKE'; value: string }\n | { op: 'IS NULL' }\n | { op: 'IS NOT NULL' }\n\n/** Per-field condition — shorthand (plain value = equality) or explicit operator. */\nexport type FieldCondition<T> = T | WhereOp<T>\n\n/** Map of column conditions — each field is optional. */\nexport type WhereConditions<TRow> = {\n [K in keyof TRow]?: FieldCondition<TRow[K]>\n}\n\n/**\n * Full WHERE input — either a flat conditions map, OR-group, or AND-group.\n * OR/AND values are recursively WhereInput allowing nesting.\n */\nexport type WhereInput<TRow> =\n | WhereConditions<TRow>\n | { OR: WhereInput<TRow>[] }\n | { AND: WhereInput<TRow>[] }\n\n// ── Helpers ────────────────────────────────────────────────────────────────\n\n/**\n * Filter out undefined values from a record.\n * null is a valid BindingValue and is kept.\n */\nfunction filterDefined(data: Record<string, unknown>): [string, BindingValue][] {\n return Object.entries(data).filter(\n (entry): entry is [string, BindingValue] => entry[1] !== undefined,\n )\n}\n\n/** Type guard: is the value a WhereOp object (has an `op` string key)? */\nfunction isWhereOp(val: unknown): val is WhereOp<unknown> {\n return typeof val === 'object' && val !== null && 'op' in val && typeof (val as Record<string, unknown>)['op'] === 'string'\n}\n\n/** Type guard: is the value a SubqueryResult (has _sql + _params fields)? */\nfunction isSubqueryResult(val: unknown): val is SubqueryResult<string, unknown> {\n return (\n typeof val === 'object' &&\n val !== null &&\n '_sql' in val &&\n '_params' in val\n )\n}\n\n/**\n * Compile a single column + condition into SQL fragment + params.\n * Handles all WhereOp variants and the shorthand equality case.\n */\nfunction buildFieldCondition(\n key: string,\n condition: unknown,\n dialect: SqlDialect,\n): { sql: string; params: BindingValue[] } {\n if (!isWhereOp(condition)) {\n // Shorthand: plain value → equality\n return { sql: `\"${key}\" = ?`, params: [condition as BindingValue] }\n }\n\n const op = condition as WhereOp<unknown>\n\n switch (op.op) {\n case '=':\n return { sql: `\"${key}\" = ?`, params: [op.value as BindingValue] }\n case '!=':\n return { sql: `\"${key}\" != ?`, params: [op.value as BindingValue] }\n case '>':\n return { sql: `\"${key}\" > ?`, params: [op.value as BindingValue] }\n case '>=':\n return { sql: `\"${key}\" >= ?`, params: [op.value as BindingValue] }\n case '<':\n return { sql: `\"${key}\" < ?`, params: [op.value as BindingValue] }\n case '<=':\n return { sql: `\"${key}\" <= ?`, params: [op.value as BindingValue] }\n case 'IN': {\n const inVal = op.value as InValue<unknown>\n if (isSubqueryResult(inVal)) {\n return { sql: `\"${key}\" IN ${inVal._sql}`, params: inVal._params }\n }\n const vals = inVal as unknown[]\n if (vals.length === 0) {\n // IN () is invalid SQL — use a false literal so no rows match\n return { sql: '1 = 0', params: [] }\n }\n const placeholders = vals.map(() => '?').join(', ')\n return { sql: `\"${key}\" IN (${placeholders})`, params: vals as BindingValue[] }\n }\n case 'NOT IN': {\n const inVal = op.value as InValue<unknown>\n if (isSubqueryResult(inVal)) {\n return { sql: `\"${key}\" NOT IN ${inVal._sql}`, params: inVal._params }\n }\n const vals = inVal as unknown[]\n if (vals.length === 0) {\n // NOT IN () matches everything — use a true literal\n return { sql: '1 = 1', params: [] }\n }\n const placeholders = vals.map(() => '?').join(', ')\n return { sql: `\"${key}\" NOT IN (${placeholders})`, params: vals as BindingValue[] }\n }\n case 'LIKE':\n return { sql: `\"${key}\" LIKE ?`, params: [op.value as BindingValue] }\n case 'ILIKE':\n if (dialect === 'postgres') {\n return { sql: `\"${key}\" ILIKE ?`, params: [op.value as BindingValue] }\n }\n // SQLite / MySQL fallback: LOWER(col) LIKE LOWER(?)\n return { sql: `LOWER(\"${key}\") LIKE LOWER(?)`, params: [op.value as BindingValue] }\n case 'IS NULL':\n return { sql: `\"${key}\" IS NULL`, params: [] }\n case 'IS NOT NULL':\n return { sql: `\"${key}\" IS NOT NULL`, params: [] }\n }\n}\n\n// ── Pure SQL generation functions (SQLite dialect — ? as placeholder) ──────\n\n/**\n * Build a WHERE clause from a WhereInput.\n *\n * Supports:\n * - Shorthand equality: { name: 'Alice' } → \"name\" = ?\n * - Explicit operator: { age: { op: '>=', value: 18 } }\n * - IN / NOT IN: { id: { op: 'IN', value: [1,2,3] } }\n * - IS NULL / IS NOT NULL\n * - LIKE / ILIKE (ILIKE falls back to LOWER() on SQLite/MySQL)\n * - OR groups: { OR: [{ role: 'admin' }, { role: 'mod' }] }\n * - AND groups: { AND: [...] }\n * - Nested OR/AND\n *\n * Returns { sql: '', params: [] } for empty / all-undefined conditions.\n */\nexport function buildWhere(\n conditions: WhereInput<Record<string, unknown>>,\n dialect: SqlDialect = 'sqlite',\n): { sql: string; params: BindingValue[] } {\n // OR group\n if ('OR' in conditions && Array.isArray((conditions as { OR: unknown }).OR)) {\n const branches = (conditions as { OR: WhereInput<Record<string, unknown>>[] }).OR\n const parts: string[] = []\n const params: BindingValue[] = []\n for (const branch of branches) {\n const { sql, params: p } = buildWhere(branch, dialect)\n if (sql) {\n parts.push(sql)\n params.push(...p)\n }\n }\n if (parts.length === 0) return { sql: '', params: [] }\n if (parts.length === 1) return { sql: parts[0]!, params }\n return { sql: `(${parts.join(' OR ')})`, params }\n }\n\n // AND group\n if ('AND' in conditions && Array.isArray((conditions as { AND: unknown }).AND)) {\n const branches = (conditions as { AND: WhereInput<Record<string, unknown>>[] }).AND\n const parts: string[] = []\n const params: BindingValue[] = []\n for (const branch of branches) {\n const { sql, params: p } = buildWhere(branch, dialect)\n if (sql) {\n parts.push(sql)\n params.push(...p)\n }\n }\n if (parts.length === 0) return { sql: '', params: [] }\n if (parts.length === 1) return { sql: parts[0]!, params }\n return { sql: `(${parts.join(' AND ')})`, params }\n }\n\n // Flat conditions map\n const entries = Object.entries(conditions).filter(([, v]) => v !== undefined)\n if (entries.length === 0) return { sql: '', params: [] }\n\n const sqlParts: string[] = []\n const params: BindingValue[] = []\n\n for (const [key, value] of entries) {\n const { sql, params: p } = buildFieldCondition(key, value, dialect)\n sqlParts.push(sql)\n params.push(...p)\n }\n\n return { sql: sqlParts.join(' AND '), params }\n}\n\n/**\n * Build an INSERT statement.\n * INSERT INTO \"table\" (\"col1\", \"col2\") VALUES (?, ?) RETURNING *\n *\n * RETURNING * (SQLite ≥ 3.35, PostgreSQL) returns the inserted row, avoiding\n * a second SELECT round-trip. Pass returning: false for databases that do not\n * support RETURNING (MySQL).\n */\nexport function buildInsert(\n tableName: string,\n data: Record<string, unknown>,\n returning = true,\n): { sql: string; params: BindingValue[] } {\n const entries = filterDefined(data)\n const cols = entries.map(([key]) => `\"${key}\"`).join(', ')\n const placeholders = entries.map(() => '?').join(', ')\n const params = entries.map(([, val]) => val)\n const returning_clause = returning ? ' RETURNING *' : ''\n const sql = `INSERT INTO \"${tableName}\" (${cols}) VALUES (${placeholders})${returning_clause}`\n return { sql, params }\n}\n\n/**\n * Build a multi-row INSERT statement.\n * INSERT INTO \"table\" (\"col1\", \"col2\") VALUES (?, ?), (?, ?) RETURNING *\n *\n * Column order is derived from rows[0] — all subsequent rows must have the same keys.\n * Pass returning: false for databases that do not support RETURNING (MySQL).\n * Throws if rows is empty or any row contains undefined values.\n */\nexport function buildInsertMany(\n tableName: string,\n rows: Record<string, BindingValue>[],\n returning = true,\n): { sql: string; params: BindingValue[] } {\n if (rows.length === 0) {\n throw new Error('insertMany: rows array must not be empty')\n }\n\n const columns = Object.keys(rows[0]!)\n const quotedCols = columns.map((c) => `\"${c}\"`).join(', ')\n const params: BindingValue[] = []\n const valueClauses: string[] = []\n\n for (const row of rows) {\n const placeholders: string[] = []\n for (const col of columns) {\n const val = row[col]\n if (val === undefined) {\n throw new Error(`insertMany: column \"${col}\" has undefined value — apply defaults before calling buildInsertMany`)\n }\n params.push(val)\n placeholders.push('?')\n }\n valueClauses.push(`(${placeholders.join(', ')})`)\n }\n\n const returning_clause = returning ? ' RETURNING *' : ''\n const sql = `INSERT INTO \"${tableName}\" (${quotedCols}) VALUES ${valueClauses.join(', ')}${returning_clause}`\n return { sql, params }\n}\n\n/**\n * Build a soft-delete or restore UPDATE statement.\n * UPDATE \"table\" SET \"col\" = ? [WHERE ...]\n *\n * value is the new column value: Date (serialized to ISO string) for soft delete,\n * null for restore.\n */\nexport function buildSoftDeleteUpdate(\n tableName: string,\n col: string,\n value: Date | null,\n where: WhereInput<Record<string, unknown>>,\n dialect: SqlDialect = 'sqlite',\n): { sql: string; params: BindingValue[] } {\n const serialized: BindingValue = value instanceof Date ? value.toISOString() : null\n const { sql: whereSql, params: whereParams } = buildWhere(where, dialect)\n const setSql = `\"${col}\" = ?`\n const sql = whereSql\n ? `UPDATE \"${tableName}\" SET ${setSql} WHERE ${whereSql}`\n : `UPDATE \"${tableName}\" SET ${setSql}`\n return { sql, params: [serialized, ...whereParams] }\n}\n\n/**\n * Build an UPDATE statement.\n * UPDATE \"table\" SET \"col1\" = ?, \"col2\" = ? WHERE \"pk\" = ?\n * The pk param is always last in params.\n */\nexport function buildUpdate(\n tableName: string,\n patch: Record<string, unknown>,\n pk: string,\n pkValue: BindingValue,\n): { sql: string; params: BindingValue[] } {\n const entries = filterDefined(patch)\n const sets = entries.map(([key]) => `\"${key}\" = ?`).join(', ')\n const params: BindingValue[] = [...entries.map(([, val]) => val), pkValue]\n const sql = `UPDATE \"${tableName}\" SET ${sets} WHERE \"${pk}\" = ?`\n return { sql, params }\n}\n\n/**\n * Build a DELETE statement.\n * DELETE FROM \"table\" WHERE \"pk\" = ?\n */\nexport function buildDelete(\n tableName: string,\n pk: string,\n pkValue: BindingValue,\n): { sql: string; params: BindingValue[] } {\n const sql = `DELETE FROM \"${tableName}\" WHERE \"${pk}\" = ?`\n return { sql, params: [pkValue] }\n}\n\n/**\n * Deserialize a raw DB row into the typed T shape.\n * Consolidated here to avoid duplication between SelectBuilder and InsertBuilder.\n * Handles TIMESTAMP columns: SQLite stores them as ISO strings, we convert back to Date.\n */\nexport function deserializeRow<T, S extends SchemaMap>(\n table: TableDef<T, S>,\n row: Record<string, unknown>,\n): T {\n const result: Record<string, unknown> = {}\n for (const [key, col] of Object.entries(table.schema)) {\n const c = col as Column<unknown>\n const raw = row[key]\n if (c.def.type === 'TIMESTAMP' && raw !== null && raw !== undefined) {\n result[key] = new Date(raw as string)\n } else {\n result[key] = raw\n }\n }\n return result as T\n}\n\n/** A single aggregate expression: FN(\"col\") AS alias. */\nexport interface AggregateClause {\n alias: string\n fn: 'COUNT' | 'SUM' | 'AVG' | 'MIN' | 'MAX'\n col?: string // undefined → COUNT(*)\n}\n\nexport interface SelectOptions {\n limit?: number\n offset?: number\n orderBy?: { col: string; dir: 'ASC' | 'DESC' }[]\n columns?: string[] // explicit column list — overrides SELECT *\n groupBy?: string[] // GROUP BY columns\n aggregates?: AggregateClause[] // aggregate expressions added to SELECT\n having?: WhereInput<Record<string, unknown>> // HAVING clause\n distinct?: boolean // SELECT DISTINCT when true\n}\n\n/** Build the SELECT column list from options. Exported for use in SelectBuilder's raw-where path. */\nexport function buildSelectListFromOptions(options?: SelectOptions): string {\n const cols: string[] = []\n\n // Explicit column selection\n if (options?.columns && options.columns.length > 0) {\n cols.push(...options.columns.map((c) => `\"${c}\"`))\n } else if (!options?.aggregates || options.aggregates.length === 0) {\n // No columns + no aggregates → SELECT *\n cols.push('*')\n } else if (options?.groupBy && options.groupBy.length > 0) {\n // Aggregates + GROUP BY → include the group-by columns so they appear in results\n cols.push(...options.groupBy.map((c) => `\"${c}\"`))\n } else {\n // Aggregates only (no groupBy columns) → e.g. SELECT COUNT(*)\n }\n\n // Aggregate expressions appended after regular columns\n if (options?.aggregates && options.aggregates.length > 0) {\n for (const agg of options.aggregates) {\n const colExpr = agg.col ? `\"${agg.col}\"` : '*'\n cols.push(`${agg.fn}(${colExpr}) AS \"${agg.alias}\"`)\n }\n }\n\n return cols.length > 0 ? cols.join(', ') : '*'\n}\n\n/** Append ORDER BY / LIMIT / OFFSET to parts[]. Shared between buildSelect paths. */\nfunction appendPaginationAndOrder(\n parts: string[],\n options?: SelectOptions,\n): void {\n if (options?.orderBy && options.orderBy.length > 0) {\n const clause = options.orderBy\n .map(({ col, dir }) => `\"${col}\" ${dir}`)\n .join(', ')\n parts.push(`ORDER BY ${clause}`)\n }\n\n // LIMIT and OFFSET are always non-negative integers supplied by framework code,\n // never from raw user input — safe to inline as literals.\n // SQLite does not support ? placeholders in LIMIT/OFFSET positions.\n // SQLite also requires LIMIT to precede OFFSET — if only offset is set,\n // use LIMIT -1 (SQLite's \"unlimited\" sentinel).\n if (options?.limit !== undefined || options?.offset !== undefined) {\n const limitVal = options?.limit !== undefined\n ? Math.trunc(Math.max(0, options.limit))\n : -1 // -1 = unlimited in SQLite/PostgreSQL/MySQL\n parts.push(`LIMIT ${limitVal}`)\n\n if (options?.offset !== undefined) {\n parts.push(`OFFSET ${Math.trunc(Math.max(0, options.offset))}`)\n }\n }\n}\n\n/**\n * Build a UNION or UNION ALL query from two or more SELECT SQL fragments.\n * Optionally appends ORDER BY + LIMIT to the combined query.\n *\n * Throws if fewer than 2 parts are provided.\n */\nexport function buildUnion(\n parts: Array<{ sql: string; params: BindingValue[] }>,\n kind: 'UNION' | 'UNION ALL',\n options: { orderBy?: { col: string; dir: 'ASC' | 'DESC' }; limit?: number } = {},\n): { sql: string; params: BindingValue[] } {\n if (parts.length < 2) {\n throw new Error('buildUnion: at least 2 parts required')\n }\n const sqls = parts.map((p) => p.sql)\n const params = parts.flatMap((p) => p.params)\n let sql = sqls.join(` ${kind} `)\n if (options.orderBy) {\n sql += ` ORDER BY \"${options.orderBy.col}\" ${options.orderBy.dir ?? 'ASC'}`\n }\n if (options.limit !== undefined) {\n sql += ` LIMIT ${Math.trunc(Math.max(0, options.limit))}`\n }\n return { sql, params }\n}\n\n/**\n * Build a SELECT statement.\n * SELECT [cols] FROM \"table\" [WHERE ...] [GROUP BY ...] [HAVING ...] [ORDER BY ...] [LIMIT n] [OFFSET n]\n */\nexport function buildSelect(\n tableName: string,\n conditions: WhereInput<Record<string, unknown>>,\n options?: SelectOptions,\n dialect: SqlDialect = 'sqlite',\n): { sql: string; params: BindingValue[] } {\n const selectList = buildSelectListFromOptions(options)\n const { sql: whereSql, params } = buildWhere(conditions, dialect)\n const selectKeyword = options?.distinct ? 'SELECT DISTINCT' : 'SELECT'\n\n const parts: string[] = [\n whereSql\n ? `${selectKeyword} ${selectList} FROM \"${tableName}\" WHERE ${whereSql}`\n : `${selectKeyword} ${selectList} FROM \"${tableName}\"`,\n ]\n\n // GROUP BY\n if (options?.groupBy && options.groupBy.length > 0) {\n parts.push(`GROUP BY ${options.groupBy.map((c) => `\"${c}\"`).join(', ')}`)\n }\n\n // HAVING — uses same buildWhere system as WHERE\n if (options?.having) {\n const { sql: havingSql, params: havingParams } = buildWhere(options.having, dialect)\n if (havingSql) {\n parts.push(`HAVING ${havingSql}`)\n params.push(...havingParams)\n }\n }\n\n appendPaginationAndOrder(parts, options)\n\n return { sql: parts.join(' '), params }\n}\n\n/**\n * Build a SELECT statement with JOIN clauses and a raw WHERE condition.\n *\n * columns — explicit column list (e.g. ['orders.id', 'users.name']); defaults to *\n * joins — ordered list of JOIN clauses\n * where — optional raw SQL fragment (e.g. 'orders.status = ?')\n * params — bind values for the where clause\n */\n// ── quoteColumnRef ────────────────────────────────────────────────────────────\n// Quotes a column reference: \"table\".\"column\", \"*\", or \"column\".\n\nfunction quoteColumnRef(col: string): string {\n if (col === '*') return '*'\n const dotIdx = col.indexOf('.')\n if (dotIdx !== -1) {\n const table = col.slice(0, dotIdx)\n const column = col.slice(dotIdx + 1)\n if (column === '*') return `\"${table}\".*`\n return `\"${table}\".\"${column}\"`\n }\n return `\"${col}\"`\n}\n\nexport function buildJoinSelect(\n tableName: string,\n columns: string[],\n joins: JoinClause[],\n where: string,\n params: BindingValue[],\n options?: SelectOptions,\n): { sql: string; params: BindingValue[] } {\n const cols = columns.length > 0\n ? columns.map(quoteColumnRef).join(', ')\n : '*'\n const parts: string[] = [`SELECT ${cols} FROM \"${tableName}\"`]\n\n for (const j of joins) {\n const quotedOn = validateAndQuoteOnClause(j.on)\n parts.push(`${j.type} JOIN \"${j.table}\" ON ${quotedOn}`)\n }\n\n if (where) parts.push(`WHERE ${where}`)\n\n // Mutable copy — no additional params needed (pagination uses literals)\n const allParams = [...params]\n\n appendPaginationAndOrder(parts, options)\n\n return { sql: parts.join('\\n'), params: allParams }\n}\n","import type { VelnAdapter, BindingValue, QueryLogEntry } from '../adapter/types'\nimport type { SchemaMap, TableDef, InferInsert, InferUpdate, RelationMeta, RelationsMap, WithRelations } from '../schema/table'\nimport type { HookExecutor } from '../hooks/executor'\nimport { RequestEventQueue } from '../events/index'\nimport { ValidationError } from '../app/types'\nimport { buildInsert, buildInsertMany, buildUpdate, buildDelete, buildSelect, buildJoinSelect, buildWhere, buildSelectListFromOptions, deserializeRow, buildSubquery, buildSoftDeleteUpdate, buildUnion } from './sql'\nimport type { JoinClause, SelectOptions, WhereInput, SqlDialect, AggregateClause, SubqueryResult } from './sql'\n\n// ── QueryLog — per-request query accumulator ──────────────────────────────\n\nexport interface QueryLog {\n /** Total number of queries executed during this request. */\n queries: number\n /** Cumulative wall-clock duration of all queries in ms. */\n totalMs: number\n /** Individual query entries — populated only when logQueries is true. */\n entries: QueryLogEntry[]\n /** Warning threshold — exceeded → N+1 warning. */\n threshold: number\n /** Whether individual query entries should be captured (for logQueries). */\n logQueries: boolean\n}\n\n// ── Event Buffering Stub — Phase 3 fills the flush mechanism ──────────────\n\nexport interface PendingEvent {\n name: string\n payload: unknown\n}\n\nexport interface TransactionResult<T> {\n result: T\n events: PendingEvent[] // always [] in Phase 2; Phase 3 wires EventBus here\n}\n\n// ── EventBus interface — optional on ctx, Phase 3 provides the implementation\n\nexport interface EventBus {\n _emit(event: string, payload: unknown, ctx: unknown): void\n on(event: string, handler: (payload: unknown, ctx: unknown) => Promise<void> | void): this\n flush(events: PendingEvent[], ctx: unknown): Promise<void>\n}\n\n// ── VelnDB ─────────────────────────────────────────────────────────────────\n\nexport class VelnDB {\n constructor(\n private readonly adapter: VelnAdapter,\n private readonly hooks: HookExecutor,\n ) {}\n\n /** Return a new BoundVelnDB scoped to the given context. Never mutates this. */\n withCtx(ctx: unknown, queue?: RequestEventQueue, queryLog?: QueryLog): BoundVelnDB {\n return new BoundVelnDB(this.adapter, this.hooks, ctx, queue, queryLog)\n }\n}\n\n// ── BoundVelnDB ────────────────────────────────────────────────────────────\n\nexport class BoundVelnDB {\n /** Per-request query counter — incremented for every query() and execute() call on this instance. */\n _queryCount = 0\n private readonly adapter: VelnAdapter\n\n constructor(\n adapter: VelnAdapter,\n private readonly hooks: HookExecutor,\n private readonly ctx: unknown,\n // queue is undefined when used outside HTTP context (CLI, tests, background jobs)\n private readonly queue?: RequestEventQueue,\n // Optional per-request QueryLog. When provided, every query() and execute() call\n // increments the log's counters. Never mutates adapter.onQuery — avoids shared-state\n // races when multiple requests run concurrently on the same adapter instance.\n queryLog?: QueryLog,\n private readonly dialect: SqlDialect = 'sqlite',\n ) {\n if (queryLog) {\n const log = queryLog\n this.adapter = {\n query: async <T>(sql: string, params: BindingValue[] = []) => {\n const t0 = performance.now()\n const rows = await adapter.query<T>(sql, params)\n const durationMs = performance.now() - t0\n this._queryCount++\n log.queries++\n log.totalMs += durationMs\n if (log.logQueries) log.entries.push({ sql, params, durationMs, type: 'query' })\n return rows\n },\n execute: async (sql: string, params: BindingValue[] = []) => {\n const t0 = performance.now()\n const result = await adapter.execute(sql, params)\n const durationMs = performance.now() - t0\n this._queryCount++\n log.queries++\n log.totalMs += durationMs\n if (log.logQueries) log.entries.push({ sql, params, durationMs, type: 'execute' })\n return result\n },\n transaction: (fn) => adapter.transaction(fn),\n close: () => adapter.close(),\n onQuery: adapter.onQuery,\n }\n } else {\n this.adapter = adapter\n }\n }\n\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n from<T, S extends SchemaMap, TRelations extends RelationsMap>(\n table: TableDef<T, S, any, TRelations>,\n ): SelectBuilder<T, S, TRelations> {\n return new SelectBuilder<T, S, TRelations>(this.adapter, this.hooks, this.ctx, this.queue, table as TableDef<T, S, any, TRelations>, {})\n }\n\n /**\n * Start a JOIN query from the given table name.\n * Returns a JoinBuilder — call .join()/.leftJoin() etc. to add clauses,\n * then .select() to execute and get Record<string, unknown>[] results.\n *\n * @example\n * const rows = await db.join('orders')\n * .columns(['orders.id', 'users.name'])\n * .join('users', 'orders.user_id = users.id')\n * .where('orders.status = ?', ['pending'])\n * .select()\n */\n join(tableName: string): JoinBuilder {\n return new JoinBuilder(this.adapter, tableName, [], [], '', [])\n }\n\n into<T, S extends SchemaMap>(table: TableDef<T, S>): InsertBuilder<T, S> {\n return new InsertBuilder<T, S>(this.adapter, this.hooks, this.ctx, this.queue, table, this.dialect)\n }\n\n /**\n * DataLoader-pattern relation fetch — single IN-query, no N+1.\n * Returns a Map keyed by the foreign-key value; each entry is an array of\n * matching child rows (for one-to-many relations).\n *\n * Two call forms:\n *\n * @example — explicit (original)\n * const authorMap = await db.loadRelation(posts, 'authorId', usersTable, 'id')\n *\n * @example — name-based (reads relation metadata declared on the table)\n * const authorMap = await db.loadRelation(posts, 'author', postsTable)\n */\n // Overload 1 — explicit, original signature (unchanged)\n loadRelation<\n TParent extends Record<string, unknown>,\n TChild,\n TFk extends keyof TParent & string,\n TPk extends keyof TChild & string,\n >(\n parents: TParent[],\n foreignKey: TFk,\n childTable: TableDef<TChild>,\n primaryKey: TPk,\n ): Promise<Map<TParent[TFk], TChild[]>>\n // Overload 2 — name-based, reads from sourceTable.relations\n loadRelation<TParent extends Record<string, unknown>>(\n parents: TParent[],\n relationName: string,\n sourceTable: TableDef<any>,\n ): Promise<Map<unknown, unknown>>\n // Implementation\n async loadRelation<\n TParent extends Record<string, unknown>,\n TChild,\n TFk extends keyof TParent & string,\n TPk extends keyof TChild & string,\n >(\n parents: TParent[],\n keyOrRelationName: TFk | string,\n tableOrSource: TableDef<TChild> | TableDef<unknown>,\n primaryKey?: TPk,\n ): Promise<Map<unknown, unknown>> {\n // Name-based path: no primaryKey arg\n if (primaryKey === undefined) {\n return this._loadRelationByName(\n parents,\n keyOrRelationName,\n tableOrSource as TableDef<unknown>,\n 'many',\n )\n }\n\n // Explicit path — original behaviour\n const foreignKey = keyOrRelationName as TFk\n const childTable = tableOrSource as TableDef<TChild>\n const result = new Map<TParent[TFk], TChild[]>()\n if (parents.length === 0) return result\n\n const ids = [...new Set(parents.map((p) => p[foreignKey]))]\n const children = await this.from(childTable)\n .where({ [primaryKey]: { op: 'IN', value: ids } } as WhereInput<TChild>)\n .select()\n\n for (const child of children) {\n const key = child[primaryKey] as unknown as TParent[TFk]\n const group = result.get(key)\n if (group) {\n group.push(child)\n } else {\n result.set(key, [child])\n }\n }\n return result\n }\n\n /**\n * Convenience variant of loadRelation for belongs-to (many-to-one) relations.\n * Returns Map<fkValue, TChild> — single child per key instead of an array.\n *\n * Two call forms:\n *\n * @example — explicit (original)\n * const authorMap = await db.loadRelationOne(posts, 'authorId', usersTable, 'id')\n *\n * @example — name-based\n * const authorMap = await db.loadRelationOne(posts, 'author', postsTable)\n */\n // Overload 1 — explicit\n loadRelationOne<\n TParent extends Record<string, unknown>,\n TChild,\n TFk extends keyof TParent & string,\n TPk extends keyof TChild & string,\n >(\n parents: TParent[],\n foreignKey: TFk,\n childTable: TableDef<TChild>,\n primaryKey: TPk,\n ): Promise<Map<TParent[TFk], TChild>>\n // Overload 2 — name-based\n loadRelationOne<TParent extends Record<string, unknown>>(\n parents: TParent[],\n relationName: string,\n sourceTable: TableDef<any>,\n ): Promise<Map<unknown, unknown>>\n // Implementation\n async loadRelationOne<\n TParent extends Record<string, unknown>,\n TChild,\n TFk extends keyof TParent & string,\n TPk extends keyof TChild & string,\n >(\n parents: TParent[],\n keyOrRelationName: TFk | string,\n tableOrSource: TableDef<TChild> | TableDef<unknown>,\n primaryKey?: TPk,\n ): Promise<Map<unknown, unknown>> {\n // Name-based path\n if (primaryKey === undefined) {\n return this._loadRelationByName(\n parents,\n keyOrRelationName,\n tableOrSource as TableDef<unknown>,\n 'one',\n )\n }\n\n // Explicit path — original behaviour\n const foreignKey = keyOrRelationName as TFk\n const childTable = tableOrSource as TableDef<TChild>\n const result = new Map<TParent[TFk], TChild>()\n if (parents.length === 0) return result\n\n const ids = [...new Set(parents.map((p) => p[foreignKey]))]\n const children = await this.from(childTable)\n .where({ [primaryKey]: { op: 'IN', value: ids } } as WhereInput<TChild>)\n .select()\n\n for (const child of children) {\n result.set(child[primaryKey] as unknown as TParent[TFk], child)\n }\n return result\n }\n\n /**\n * Shared implementation for name-based loadRelation / loadRelationOne.\n * Reads RelationMeta from sourceTable.relations, validates the kind,\n * and delegates to the explicit overload.\n */\n private async _loadRelationByName(\n parents: Record<string, unknown>[],\n relationName: string,\n sourceTable: TableDef<unknown>,\n mode: 'many' | 'one',\n ): Promise<Map<unknown, unknown>> {\n const rel = sourceTable.relations[relationName] as RelationMeta | undefined\n\n if (rel === undefined) {\n const available = Object.keys(sourceTable.relations).join(', ') || '(none)'\n throw new Error(\n `Relation '${relationName}' is not defined on table '${sourceTable.name}'. ` +\n `Available relations: ${available}`,\n )\n }\n\n if (rel.kind === 'manyToMany') {\n throw new Error(\n `manyToMany relations are not yet supported in loadRelation. ` +\n `Use a manual JOIN for relation '${relationName}' on table '${sourceTable.name}'.`,\n )\n }\n\n if (mode === 'one' && rel.kind === 'hasMany') {\n throw new Error(\n `loadRelationOne cannot be used with hasMany relation '${relationName}' on table '${sourceTable.name}'. ` +\n `Use loadRelation to get an array of results.`,\n )\n }\n\n const foreignTable = rel.getTable()\n const pk = foreignTable.primaryKey as string\n\n if (rel.kind === 'belongsTo') {\n // FK is on the parent (source) table; PK is on the foreign table.\n // We cast to the explicit overload signature — runtime is correct,\n // TypeScript can't narrow keyof unknown here.\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const ft = foreignTable as TableDef<any>\n const fk = rel.foreignKey as keyof typeof parents[0] & string\n if (mode === 'one') {\n return this.loadRelationOne(parents, fk, ft, pk)\n }\n return this.loadRelation(parents, fk, ft, pk)\n }\n\n // hasMany: FK is on the foreign table; we group by FK value\n // parents is keyed by their PK, foreign rows have rel.foreignKey pointing back\n const parentPk = sourceTable.primaryKey as string\n const result = new Map<unknown, unknown[]>()\n if (parents.length === 0) return result\n\n const ids = [...new Set(parents.map((p) => p[parentPk]))]\n const children = await this.from(foreignTable)\n .where({ [rel.foreignKey]: { op: 'IN', value: ids } } as WhereInput<typeof foreignTable>)\n .select()\n\n for (const child of children as Record<string, unknown>[]) {\n const key = child[rel.foreignKey]\n const group = result.get(key)\n if (group) {\n group.push(child)\n } else {\n result.set(key, [child])\n }\n }\n return result\n }\n\n async transaction<T>(fn: (db: BoundVelnDB) => Promise<T>): Promise<TransactionResult<T>> {\n // TX path: events collected inside the TX go into a dedicated txQueue.\n // If the TX commits successfully, txQueue.drain() returns the buffered events.\n // These are handed back via TransactionResult.events so the caller can flush\n // them at the right moment (after TX commit, not during).\n // This is intentionally separate from the per-request queue so that TX events\n // are never prematurely flushed if the request queue drains first.\n const txQueue = new RequestEventQueue()\n\n const result = await this.adapter.transaction(async (txAdapter) => {\n const txBound = new BoundVelnDB(txAdapter, this.hooks, this.ctx, txQueue)\n return fn(txBound)\n })\n // TX committed — drain buffered events into TransactionResult\n return { result, events: txQueue.drain() }\n }\n\n /**\n * Execute raw SQL and return typed rows.\n *\n * Without a schema the return type is `Record<string, unknown>[]`.\n * With a schema (e.g. a Zod object) every row is validated at runtime\n * and the return type is inferred from the schema.\n *\n * @example\n * // Untyped\n * const rows = await ctx.db.raw('SELECT * FROM orders WHERE amount > ?', [100])\n *\n * // Typed + validated\n * const schema = z.object({ id: z.number(), amount: z.number() })\n * const rows = await ctx.db.raw('SELECT id, amount FROM orders WHERE amount > ?', [100], schema)\n */\n async raw<T = Record<string, unknown>>(\n sql: string,\n params: BindingValue[] = [],\n schema?: { parse: (row: unknown) => T },\n ): Promise<T[]> {\n const rows = await this.adapter.query<Record<string, unknown>>(sql, params)\n if (!schema) return rows as T[]\n return rows.map((row) => {\n try {\n return schema.parse(row)\n } catch (err) {\n // @ts-ignore — ValidationError constructor expects ZodError; caller's schema.parse throws ZodError at runtime\n throw new ValidationError(err instanceof Error ? err.message : String(err))\n }\n })\n }\n}\n\n// ── mergeWhereInput — AND-merge two WhereInput values ─────────────────────────\n// When both are plain objects (no OR/AND key), spread them.\n// Otherwise wrap both in an AND group.\n\nfunction mergeWhereAnd<T>(\n a: WhereInput<T>,\n b: WhereInput<T>,\n): WhereInput<T> {\n const aIsPlain = !('OR' in a) && !('AND' in a)\n const bIsPlain = !('OR' in b) && !('AND' in b)\n if (aIsPlain && bIsPlain) {\n return { ...(a as object), ...(b as object) } as WhereInput<T>\n }\n return { AND: [a, b] }\n}\n\n// ── SelectBuilder ──────────────────────────────────────────────────────────\n\nexport class SelectBuilder<T, S extends SchemaMap, TRelations extends RelationsMap = RelationsMap> {\n constructor(\n private readonly adapter: VelnAdapter,\n private readonly hooks: HookExecutor,\n private readonly ctx: unknown,\n private readonly queue: RequestEventQueue | undefined,\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n private readonly table: TableDef<T, S, any, TRelations>,\n private readonly conditions: WhereInput<T>,\n private readonly _options: SelectOptions = {},\n // Raw SQL fragments appended with AND. Each entry is { sql, params }.\n private readonly _rawWhere: { sql: string; params: BindingValue[] }[] = [],\n private readonly _dialect: SqlDialect = 'sqlite',\n private readonly _withRelations: string[] = [],\n // When true, the soft-delete IS NULL filter is skipped.\n private readonly _includeDeleted: boolean = false,\n ) {}\n\n private _cloneWith(\n conditions: WhereInput<T>,\n rawWhere?: { sql: string; params: BindingValue[] }[],\n ): SelectBuilder<T, S, TRelations> {\n return new SelectBuilder<T, S, TRelations>(\n this.adapter,\n this.hooks,\n this.ctx,\n this.queue,\n this.table,\n conditions,\n this._options,\n rawWhere ?? this._rawWhere,\n this._dialect,\n this._withRelations,\n this._includeDeleted,\n )\n }\n\n private _clone(patch: Partial<SelectOptions>): SelectBuilder<T, S, TRelations> {\n return new SelectBuilder<T, S, TRelations>(\n this.adapter,\n this.hooks,\n this.ctx,\n this.queue,\n this.table,\n this.conditions,\n { ...this._options, ...patch },\n this._rawWhere,\n this._dialect,\n this._withRelations,\n this._includeDeleted,\n )\n }\n\n /**\n * Eager-load relations alongside the main query.\n * One additional IN-query per relation — never N+1 regardless of row count.\n *\n * @example\n * const posts = await db.from(postsTable).with({ author: true }).select()\n * posts[0].author // → User | null (fully typed)\n * posts[0].title // → string (original fields preserved)\n */\n with<Keys extends keyof TRelations & string>(\n relations: { [K in Keys]: true },\n ): SelectBuilder<WithRelations<T, { relations: TRelations }, Keys>, S, TRelations> {\n const keys = Object.keys(relations) as Keys[]\n return new SelectBuilder<WithRelations<T, { relations: TRelations }, Keys>, S, TRelations>(\n this.adapter,\n this.hooks,\n this.ctx,\n this.queue,\n // table type cast: the schema/relations are unchanged; only T changes in the generic\n this.table as unknown as TableDef<WithRelations<T, { relations: TRelations }, Keys>, S, any, TRelations>,\n this.conditions as unknown as WhereInput<WithRelations<T, { relations: TRelations }, Keys>>,\n this._options,\n this._rawWhere,\n this._dialect,\n [...this._withRelations, ...keys],\n this._includeDeleted,\n )\n }\n\n /**\n * Include soft-deleted rows in the query result.\n * By default, tables with `.withSoftDelete()` automatically exclude rows\n * where the soft-delete column is not null.\n *\n * Has no effect on tables without soft delete configured.\n *\n * @example\n * const allUsers = await db.from(usersTable).withDeleted().select()\n */\n withDeleted(): SelectBuilder<T, S, TRelations> {\n return new SelectBuilder<T, S, TRelations>(\n this.adapter,\n this.hooks,\n this.ctx,\n this.queue,\n this.table,\n this.conditions,\n this._options,\n this._rawWhere,\n this._dialect,\n this._withRelations,\n true,\n )\n }\n\n /**\n * Add WHERE conditions. Accepts:\n * - Plain equality map: `.where({ role: 'admin' })`\n * - Operator condition: `.where({ age: { op: '>=', value: 18 } })`\n * - OR group: `.where({ OR: [{ role: 'admin' }, { role: 'mod' }] })`\n * - AND group: `.where({ AND: [...] })`\n *\n * Multiple `.where()` calls are combined with AND.\n */\n where(conditions: WhereInput<T>): SelectBuilder<T, S, TRelations> {\n const merged = mergeWhereAnd(this.conditions, conditions)\n return this._cloneWith(merged)\n }\n\n /**\n * Append a raw SQL WHERE fragment, combined with AND.\n * Use for conditions the builder cannot express.\n *\n * @example\n * .whereRaw('\"score\" > \"threshold\"', [])\n * .whereRaw('\"created_at\" > ?', ['2024-01-01'])\n */\n whereRaw(sql: string, params: BindingValue[]): SelectBuilder<T, S, TRelations> {\n return this._cloneWith(this.conditions, [...this._rawWhere, { sql, params }])\n }\n\n /**\n * Apply SELECT DISTINCT — deduplicate rows in the result set.\n * Combine with `.columns()` to deduplicate on specific columns.\n *\n * @example\n * await db.from(usersTable).columns('name').distinct().select()\n * // → SELECT DISTINCT \"name\" FROM \"users\"\n */\n distinct(): SelectBuilder<T, S, TRelations> {\n return this._clone({ distinct: true })\n }\n\n /** Limit the number of rows returned. Bound as a parameter — never interpolated. */\n limit(n: number): SelectBuilder<T, S, TRelations> {\n return this._clone({ limit: n })\n }\n\n /** Skip the first n rows. Bound as a parameter — never interpolated. */\n offset(n: number): SelectBuilder<T, S, TRelations> {\n return this._clone({ offset: n })\n }\n\n /** Add an ORDER BY clause. Multiple calls accumulate in order. */\n orderBy(col: keyof T & string, dir: 'ASC' | 'DESC' = 'ASC'): SelectBuilder<T, S, TRelations> {\n const existing = this._options.orderBy ?? []\n return this._clone({ orderBy: [...existing, { col, dir }] })\n }\n\n /**\n * Convenience helper for cursor-based pagination.\n * page(1, 10) → LIMIT 10 OFFSET 0\n * page(2, 10) → LIMIT 10 OFFSET 10\n */\n page(page: number, size: number): SelectBuilder<T, S, TRelations> {\n return this._clone({ limit: size, offset: (page - 1) * size })\n }\n\n /**\n * Restrict which columns are returned.\n *\n * Single-column form returns a ColumnRestrictedBuilder, enabling .subquery():\n * db.from(usersTable).columns('id').subquery() // → SubqueryResult<'id', number>\n *\n * Multi-column form returns a narrowed SelectBuilder:\n * db.from(usersTable).columns('id', 'name') // → SelectBuilder<Pick<User, 'id'|'name'>, ...>\n */\n columns<K extends keyof T & string>(col: K): ColumnRestrictedBuilder<K, T[K], S, TRelations>\n columns<K extends keyof T & string>(...cols: K[]): SelectBuilder<Pick<T, K>, S, TRelations>\n columns<K extends keyof T & string>(...cols: K[]): SelectBuilder<Pick<T, K>, S, TRelations> | ColumnRestrictedBuilder<K, T[K], S, TRelations> {\n const cloned = this._clone({ columns: cols }) as unknown as SelectBuilder<unknown, S, TRelations>\n if (cols.length === 1) {\n return new ColumnRestrictedBuilder<K, T[K], S, TRelations>(cloned, cols[0]!)\n }\n return cloned as unknown as SelectBuilder<Pick<T, K>, S, TRelations>\n }\n\n /**\n * Build SELECT SQL + params without executing the query.\n * Used internally by ColumnRestrictedBuilder.subquery().\n */\n /** Internal accessor for ColumnRestrictedBuilder / UnionBuilder — returns the adapter. */\n _getAdapter(): VelnAdapter { return this.adapter }\n /** Internal accessor for ColumnRestrictedBuilder / UnionBuilder — returns the SQL dialect. */\n _getDialect(): SqlDialect { return this._dialect }\n\n /**\n * Returns the effective WHERE conditions, injecting the soft-delete IS NULL\n * filter when the table has a soft-delete column and .withDeleted() was not called.\n */\n private _effectiveConditions(): WhereInput<T> {\n const col = this.table.softDeleteColumn\n if (col === null || this._includeDeleted) return this.conditions\n const softFilter = { [col]: { op: 'IS NULL' } } as WhereInput<T>\n return mergeWhereAnd(this.conditions, softFilter)\n }\n\n _buildSelectSQL(): { sql: string; params: BindingValue[] } {\n const conditions = this._effectiveConditions()\n if (this._rawWhere.length === 0) {\n return buildSelect(\n this.table.name,\n conditions as WhereInput<Record<string, unknown>>,\n this._options,\n this._dialect,\n )\n }\n // Raw WHERE path — mirrors select() logic but without executing\n const { sql: whereSql, params: whereParams } = buildWhere(\n conditions as WhereInput<Record<string, unknown>>,\n this._dialect,\n )\n const allWhereParts: string[] = []\n const allParams: BindingValue[] = [...whereParams]\n if (whereSql) allWhereParts.push(whereSql)\n for (const raw of this._rawWhere) {\n allWhereParts.push(raw.sql)\n allParams.push(...raw.params)\n }\n const combinedWhere = allWhereParts.join(' AND ')\n const selectList = buildSelectListFromOptions(this._options)\n const selectKeyword = this._options.distinct ? 'SELECT DISTINCT' : 'SELECT'\n const parts: string[] = [\n combinedWhere\n ? `${selectKeyword} ${selectList} FROM \"${this.table.name}\" WHERE ${combinedWhere}`\n : `${selectKeyword} ${selectList} FROM \"${this.table.name}\"`,\n ]\n if (this._options.orderBy && this._options.orderBy.length > 0) {\n const clause = this._options.orderBy.map(({ col, dir }) => `\"${col}\" ${dir}`).join(', ')\n parts.push(`ORDER BY ${clause}`)\n }\n if (this._options.limit !== undefined || this._options.offset !== undefined) {\n const limitVal = this._options.limit !== undefined\n ? Math.trunc(Math.max(0, this._options.limit))\n : -1\n parts.push(`LIMIT ${limitVal}`)\n if (this._options.offset !== undefined) {\n parts.push(`OFFSET ${Math.trunc(Math.max(0, this._options.offset))}`)\n }\n }\n return { sql: parts.join(' '), params: allParams }\n }\n\n /**\n * Add a GROUP BY clause. Multiple columns are comma-separated.\n * Combine with .aggregate() to get grouped aggregate results.\n */\n groupBy(...cols: (keyof T & string)[]): SelectBuilder<T, S, TRelations> {\n return this._clone({ groupBy: cols as string[] })\n }\n\n /**\n * Add a HAVING clause — filters aggregate groups.\n * Uses the same WhereInput system as .where() (supports operators, OR/AND).\n *\n * @example\n * .groupBy('role').aggregate({ cnt: { fn: 'COUNT' } }).having({ cnt: { op: '>', value: 1 } })\n */\n having(conditions: WhereInput<Record<string, unknown>>): SelectBuilder<T, S, TRelations> {\n return this._clone({ having: conditions })\n }\n\n /**\n * Execute a GROUP BY + aggregate query.\n * Returns typed rows with group-by columns + aggregate aliases.\n *\n * @example\n * const rows = await db.from(orders)\n * .groupBy('status')\n * .aggregate({ total: { fn: 'SUM', col: 'amount' }, cnt: { fn: 'COUNT' } })\n * // rows: { status: string; total: number; cnt: number }[]\n */\n async aggregate<TAgg extends Record<string, number | string | null>>(\n aggregates: { [K in keyof TAgg]: { fn: 'COUNT' | 'SUM' | 'AVG' | 'MIN' | 'MAX'; col?: keyof T & string } },\n ): Promise<(Partial<T> & TAgg)[]> {\n const aggClauses: AggregateClause[] = Object.entries(aggregates).map(([alias, def]) => ({\n alias,\n fn: (def as { fn: AggregateClause['fn']; col?: string }).fn,\n col: (def as { fn: AggregateClause['fn']; col?: string }).col,\n }))\n\n // Merge aggregate clauses into current options and execute via select()\n const { sql, params } = buildSelect(\n this.table.name,\n this._effectiveConditions() as WhereInput<Record<string, unknown>>,\n { ...this._options, aggregates: aggClauses },\n this._dialect,\n )\n\n const rows = await this.adapter.query<Record<string, unknown>>(sql, params)\n return rows as (Partial<T> & TAgg)[]\n }\n\n // ── Scalar aggregate terminals ─────────────────────────────────────────────\n // These execute immediately and return a single value.\n\n /** COUNT(*) or COUNT(\"col\") — returns the count as a number. */\n async count(col?: keyof T & string): Promise<number> {\n return this._scalarAggregate('COUNT', col)\n }\n\n /** SUM(\"col\") — returns the sum as a number (0 if no rows). */\n async sum(col: keyof T & string): Promise<number> {\n return this._scalarAggregate('SUM', col)\n }\n\n /** AVG(\"col\") — returns the average as a number (0 if no rows). */\n async avg(col: keyof T & string): Promise<number> {\n return this._scalarAggregate('AVG', col)\n }\n\n /** MIN(\"col\") — returns the minimum value. */\n async min(col: keyof T & string): Promise<number | string | null> {\n return this._scalarAggregateRaw('MIN', col)\n }\n\n /** MAX(\"col\") — returns the maximum value. */\n async max(col: keyof T & string): Promise<number | string | null> {\n return this._scalarAggregateRaw('MAX', col)\n }\n\n private async _scalarAggregate(fn: AggregateClause['fn'], col?: keyof T & string): Promise<number> {\n const val = await this._scalarAggregateRaw(fn, col)\n if (val === null || val === undefined) return 0\n return Number(val)\n }\n\n private async _scalarAggregateRaw(fn: AggregateClause['fn'], col?: keyof T & string): Promise<number | string | null> {\n const alias = '_agg'\n const colExpr = col ? `\"${col as string}\"` : '*'\n const { sql: whereSql, params } = buildWhere(\n this._effectiveConditions() as WhereInput<Record<string, unknown>>,\n this._dialect,\n )\n\n let sqlStr: string\n let finalParams: BindingValue[]\n\n if (this._rawWhere.length > 0) {\n const allWhereParts: string[] = []\n const allParams: BindingValue[] = [...params]\n if (whereSql) allWhereParts.push(whereSql)\n for (const raw of this._rawWhere) {\n allWhereParts.push(raw.sql)\n allParams.push(...raw.params)\n }\n const combined = allWhereParts.join(' AND ')\n sqlStr = combined\n ? `SELECT ${fn}(${colExpr}) AS \"${alias}\" FROM \"${this.table.name}\" WHERE ${combined}`\n : `SELECT ${fn}(${colExpr}) AS \"${alias}\" FROM \"${this.table.name}\"`\n finalParams = allParams\n } else {\n sqlStr = whereSql\n ? `SELECT ${fn}(${colExpr}) AS \"${alias}\" FROM \"${this.table.name}\" WHERE ${whereSql}`\n : `SELECT ${fn}(${colExpr}) AS \"${alias}\" FROM \"${this.table.name}\"`\n finalParams = params\n }\n\n const row = await this.adapter.query<Record<string, unknown>>(sqlStr, finalParams)\n return (row[0]?.[alias] ?? null) as number | string | null\n }\n\n async select(): Promise<T[]> {\n let finalSql: string\n let finalParams: BindingValue[]\n\n const effectiveConditions = this._effectiveConditions()\n if (this._rawWhere.length === 0) {\n // Fast path: no raw fragments — buildSelect handles everything\n const { sql, params } = buildSelect(\n this.table.name,\n effectiveConditions as WhereInput<Record<string, unknown>>,\n this._options,\n this._dialect,\n )\n finalSql = sql\n finalParams = params\n } else {\n // Merge structured WHERE + raw fragments via AND, then bolt on options\n const { sql: whereSql, params: whereParams } = buildWhere(\n effectiveConditions as WhereInput<Record<string, unknown>>,\n this._dialect,\n )\n const allWhereParts: string[] = []\n const allParams: BindingValue[] = [...whereParams]\n if (whereSql) allWhereParts.push(whereSql)\n for (const raw of this._rawWhere) {\n allWhereParts.push(raw.sql)\n allParams.push(...raw.params)\n }\n const combinedWhere = allWhereParts.join(' AND ')\n\n // Delegate to buildSelect with a synthetic empty-conditions call so\n // GROUP BY / HAVING / ORDER BY / LIMIT are handled consistently,\n // but inject our merged WHERE manually.\n const selectList = buildSelectListFromOptions(this._options)\n const parts: string[] = [\n combinedWhere\n ? `SELECT ${selectList} FROM \"${this.table.name}\" WHERE ${combinedWhere}`\n : `SELECT ${selectList} FROM \"${this.table.name}\"`,\n ]\n if (this._options.groupBy && this._options.groupBy.length > 0) {\n parts.push(`GROUP BY ${this._options.groupBy.map((c) => `\"${c}\"`).join(', ')}`)\n }\n if (this._options.having) {\n const { sql: havSql, params: havParams } = buildWhere(this._options.having, this._dialect)\n if (havSql) {\n parts.push(`HAVING ${havSql}`)\n allParams.push(...havParams)\n }\n }\n if (this._options.orderBy && this._options.orderBy.length > 0) {\n const clause = this._options.orderBy\n .map(({ col, dir }) => `\"${col}\" ${dir}`)\n .join(', ')\n parts.push(`ORDER BY ${clause}`)\n }\n if (this._options.limit !== undefined || this._options.offset !== undefined) {\n const limitVal = this._options.limit !== undefined\n ? Math.trunc(Math.max(0, this._options.limit))\n : -1\n parts.push(`LIMIT ${limitVal}`)\n if (this._options.offset !== undefined) {\n parts.push(`OFFSET ${Math.trunc(Math.max(0, this._options.offset))}`)\n }\n }\n finalSql = parts.join(' ')\n finalParams = allParams\n }\n\n const rawRows = await this.adapter.query<Record<string, unknown>>(finalSql, finalParams)\n // When columns are restricted, only deserialize the selected columns\n let rows: T[]\n if (this._options.columns && this._options.columns.length > 0) {\n rows = rawRows as unknown as T[]\n } else {\n rows = rawRows.map((row) => deserializeRow(this.table, row))\n }\n\n if (this._withRelations.length === 0) return rows\n return this._executeWith(rows)\n }\n\n async first(): Promise<T | null> {\n const rows = await this.select()\n return rows[0] ?? null\n }\n\n // ── Eager loading — _executeWith ────────────────────────────────────────\n\n private async _executeWith(rows: T[]): Promise<T[]> {\n if (rows.length === 0) return rows\n\n const mutableRows = rows.map((r) => ({ ...(r as Record<string, unknown>) })) as T[]\n\n for (const relationName of this._withRelations) {\n const meta = this.table.relations[relationName] as RelationMeta | undefined\n if (!meta) continue\n\n if (meta.kind === 'manyToMany') {\n throw new Error(\n `manyToMany eager loading is not yet supported. ` +\n `Use loadRelation manually for relation '${relationName}'.`,\n )\n }\n\n if (meta.kind === 'belongsTo') {\n await this._attachBelongsTo(mutableRows as Record<string, unknown>[], relationName, meta)\n } else if (meta.kind === 'hasMany') {\n await this._attachHasMany(mutableRows as Record<string, unknown>[], relationName, meta)\n }\n }\n\n return mutableRows\n }\n\n private async _attachBelongsTo(\n rows: Record<string, unknown>[],\n relationName: string,\n meta: RelationMeta,\n ): Promise<void> {\n const foreignTable = meta.getTable()\n const fkValues = rows\n .map((r) => r[meta.foreignKey])\n .filter((v): v is BindingValue => v !== null && v !== undefined)\n\n if (fkValues.length === 0) {\n for (const r of rows) r[relationName] = null\n return\n }\n\n const uniqueFkValues = [...new Set(fkValues)]\n const pk = foreignTable.primaryKey as string\n const baseConditions: Record<string, unknown> = { [pk]: { op: 'IN', value: uniqueFkValues } }\n if (foreignTable.softDeleteColumn !== null) {\n baseConditions[foreignTable.softDeleteColumn as string] = { op: 'IS NULL' }\n }\n const { sql, params } = buildSelect(\n foreignTable.name,\n baseConditions as WhereInput<Record<string, unknown>>,\n {},\n this._dialect,\n )\n const related = await this.adapter.query<Record<string, unknown>>(sql, params)\n const relatedMap = new Map<unknown, unknown>()\n for (const r of related) {\n relatedMap.set(r[pk], deserializeRow(foreignTable, r))\n }\n\n for (const r of rows) {\n r[relationName] = relatedMap.get(r[meta.foreignKey]) ?? null\n }\n }\n\n private async _attachHasMany(\n rows: Record<string, unknown>[],\n relationName: string,\n meta: RelationMeta,\n ): Promise<void> {\n const foreignTable = meta.getTable()\n const pk = this.table.primaryKey as string\n const pkValues = rows.map((r) => r[pk]).filter((v): v is BindingValue => v !== null && v !== undefined)\n\n if (pkValues.length === 0) {\n for (const r of rows) r[relationName] = []\n return\n }\n\n const hasManyConditions: Record<string, unknown> = { [meta.foreignKey]: { op: 'IN', value: pkValues } }\n if (foreignTable.softDeleteColumn !== null) {\n hasManyConditions[foreignTable.softDeleteColumn as string] = { op: 'IS NULL' }\n }\n const { sql, params } = buildSelect(\n foreignTable.name,\n hasManyConditions as WhereInput<Record<string, unknown>>,\n {},\n this._dialect,\n )\n const related = await this.adapter.query<Record<string, unknown>>(sql, params)\n\n const grouped = new Map<unknown, unknown[]>()\n for (const pkVal of pkValues) grouped.set(pkVal, [])\n\n for (const r of related) {\n const fkVal = r[meta.foreignKey]\n const deserialized = deserializeRow(foreignTable, r)\n const group = grouped.get(fkVal)\n if (group) {\n group.push(deserialized)\n } else {\n grouped.set(fkVal, [deserialized])\n }\n }\n\n for (const r of rows) {\n r[relationName] = grouped.get(r[pk]) ?? []\n }\n }\n\n async update(patch: Partial<T>): Promise<T> {\n const hasConditions = !(\n Object.keys(this.conditions).length === 0 && this._rawWhere.length === 0\n )\n if (!hasConditions) {\n throw new Error('update() requires .where() conditions')\n }\n\n // Load current row\n const current = await this.first()\n if (current === null) {\n throw new Error('Record not found for update')\n }\n\n // Run beforeUpdate hooks (may transform patch)\n const finalPatch = await this.hooks.runBeforeUpdate(this.table, this.ctx, current, patch)\n\n // Execute UPDATE\n const pk = this.table.primaryKey\n const pkValue = (current as Record<string, unknown>)[pk as string] as BindingValue\n const { sql, params } = buildUpdate(\n this.table.name,\n finalPatch as Record<string, unknown>,\n pk,\n pkValue,\n )\n await this.adapter.execute(sql, params)\n\n // Construct updated result from known data — avoids a second SELECT round-trip.\n // We know exactly what was in the row before (current) and what was patched (finalPatch),\n // so the result is the merge of both. deserializeRow handles Date deserialization.\n const updatedRow: Record<string, unknown> = {\n ...(current as Record<string, unknown>),\n ...(finalPatch as Record<string, unknown>),\n }\n const result = deserializeRow(this.table, updatedRow)\n\n // Run afterUpdate hooks — events collected into queue, not emitted immediately\n await this.hooks.runAfterUpdate(this.table, this.ctx, result, current, this.queue)\n\n return result\n }\n\n /**\n * Update multiple rows atomically inside a single transaction.\n * Each row must include the primary key. beforeUpdate and afterUpdate hooks\n * run per row. If any row fails, the entire transaction rolls back.\n *\n * @example\n * const updated = await db.from(usersTable).updateMany([\n * { id: 1, name: 'Alice Updated' },\n * { id: 2, role: 'admin' },\n * ])\n */\n async updateMany(rows: InferUpdate<S>[]): Promise<T[]> {\n if (rows.length === 0) return []\n\n const pk = this.table.primaryKey\n\n const results: T[] = await this.adapter.transaction(async (txAdapter) => {\n // Build a transaction-scoped SelectBuilder that uses the tx adapter\n const txQueue = new RequestEventQueue()\n const inner: T[] = []\n\n for (const row of rows) {\n const pkValue = (row as Record<string, unknown>)[pk as string]\n if (pkValue === undefined || pkValue === null) {\n throw new Error(\n `updateMany: row is missing primary key \"${pk as string}\" — every row must include the PK`,\n )\n }\n\n // Load current row via the tx adapter (so read is within the same TX)\n const selectSql = `SELECT * FROM \"${this.table.name}\" WHERE \"${pk as string}\" = ?`\n const currentRows = await txAdapter.query<Record<string, unknown>>(selectSql, [pkValue as BindingValue])\n if (currentRows.length === 0) {\n throw new Error(`updateMany: record with ${pk as string}=${String(pkValue)} not found`)\n }\n const current = deserializeRow(this.table, currentRows[0]!)\n\n // Extract patch — everything except the PK\n const { [pk as string]: _pk, ...patchWithoutPk } = row as Record<string, unknown>\n const patch = patchWithoutPk as Partial<T>\n\n // Run beforeUpdate hooks (may transform patch)\n const finalPatch = await this.hooks.runBeforeUpdate(this.table, this.ctx, current, patch)\n\n // Execute UPDATE\n const { sql, params } = buildUpdate(\n this.table.name,\n finalPatch as Record<string, unknown>,\n pk,\n pkValue as BindingValue,\n )\n await txAdapter.execute(sql, params)\n\n // Construct updated result\n const updatedRow: Record<string, unknown> = {\n ...(current as Record<string, unknown>),\n ...(finalPatch as Record<string, unknown>),\n }\n const result = deserializeRow(this.table, updatedRow)\n\n // Run afterUpdate hooks — collect into txQueue\n await this.hooks.runAfterUpdate(this.table, this.ctx, result, current, txQueue)\n\n inner.push(result)\n }\n\n return inner\n })\n\n return results\n }\n\n async delete(): Promise<T> {\n const hasConditions = !(\n Object.keys(this.conditions).length === 0 && this._rawWhere.length === 0\n )\n if (!hasConditions) {\n throw new Error('delete() requires .where() conditions')\n }\n\n // Load current row\n const current = await this.first()\n if (current === null) {\n throw new Error('Record not found for delete')\n }\n\n // Run beforeDelete hooks (can throw to cancel)\n await this.hooks.runBeforeDelete(this.table, this.ctx, current)\n\n // Execute DELETE\n const pk = this.table.primaryKey\n const pkValue = (current as Record<string, unknown>)[pk as string] as BindingValue\n const { sql, params } = buildDelete(this.table.name, pk, pkValue)\n await this.adapter.execute(sql, params)\n\n // Run afterDelete hooks — events collected into queue, not emitted immediately\n await this.hooks.runAfterDelete(this.table, this.ctx, current, this.queue)\n\n return current\n }\n\n /**\n * Soft-delete rows by setting the soft-delete column to the current timestamp.\n * The table must have `.withSoftDelete()` configured — throws otherwise (at execute() time).\n *\n * Does NOT call beforeUpdate/afterUpdate hooks.\n * Without .where(), all rows in the table are soft-deleted.\n *\n * @example\n * await db.from(usersTable).softDelete().where({ id: 1 }).execute()\n */\n softDelete(): SoftDeleteBuilder<T, S> {\n return new SoftDeleteBuilder<T, S>(this.adapter, this.table, new Date(), this._dialect)\n }\n\n /**\n * Restore soft-deleted rows by setting the soft-delete column back to null.\n * The table must have `.withSoftDelete()` configured — throws otherwise (at execute() time).\n *\n * @example\n * await db.from(usersTable).restore().where({ id: 1 }).execute()\n */\n restore(): SoftDeleteBuilder<T, S> {\n return new SoftDeleteBuilder<T, S>(this.adapter, this.table, null, this._dialect)\n }\n}\n\n// ── ColumnRestrictedBuilder ────────────────────────────────────────────────\n// Returned by SelectBuilder.columns(singleCol). Exposes only the ops needed\n// to build a subquery: .where(), .limit(), .orderBy(), and .subquery().\n// .select(), .with(), .update(), .delete() are intentionally absent.\n\nexport class ColumnRestrictedBuilder<Col extends string, TCol, S extends SchemaMap, TRelations extends RelationsMap> {\n // _builder is typed as SelectBuilder<unknown, ...> to avoid variance issues\n // when constructing from SelectBuilder<Pick<T,K>, ...> — the runtime shape is identical.\n constructor(\n private readonly _builder: SelectBuilder<unknown, S, TRelations>,\n private readonly _col: Col,\n ) {}\n\n where(conditions: WhereInput<Record<string, unknown>>): ColumnRestrictedBuilder<Col, TCol, S, TRelations> {\n return new ColumnRestrictedBuilder<Col, TCol, S, TRelations>(\n this._builder.where(conditions),\n this._col,\n )\n }\n\n limit(n: number): ColumnRestrictedBuilder<Col, TCol, S, TRelations> {\n return new ColumnRestrictedBuilder<Col, TCol, S, TRelations>(\n this._builder.limit(n),\n this._col,\n )\n }\n\n orderBy(col: Col, dir: 'ASC' | 'DESC' = 'ASC'): ColumnRestrictedBuilder<Col, TCol, S, TRelations> {\n return new ColumnRestrictedBuilder<Col, TCol, S, TRelations>(\n // _builder is SelectBuilder<unknown,...> so keyof unknown = never;\n // col is a valid schema key at runtime — cast is safe.\n this._builder.orderBy(col as never, dir),\n this._col,\n )\n }\n\n /**\n * Build the SQL for this query as a subquery fragment.\n * The result can be used directly in WHERE IN / NOT IN conditions.\n *\n * @example\n * const activeIds = db.from(usersTable).columns('id').where({ active: true }).subquery()\n * // → SubqueryResult<'id', number>\n *\n * const posts = await db.from(postsTable)\n * .where({ authorId: { op: 'IN', value: activeIds } })\n * .select()\n */\n subquery(): SubqueryResult<Col, TCol> {\n const { sql, params } = this._builder._buildSelectSQL()\n return buildSubquery<Col, TCol>(sql, params, this._col)\n }\n\n /** Build raw SELECT SQL + params without parentheses (for UNION). */\n _buildRawSQL(): { sql: string; params: BindingValue[] } {\n return this._builder._buildSelectSQL()\n }\n\n /**\n * Combine this query with another same-type column query via UNION (deduplicates).\n * Both sides must produce the same column type — enforced at compile time.\n *\n * @example\n * db.from(usersTable).columns('id')\n * .union(db.from(adminsTable).columns('id'))\n * .select()\n */\n union(other: ColumnRestrictedBuilder<string, TCol, SchemaMap, RelationsMap>): UnionBuilder<TCol> {\n return new UnionBuilder<TCol>(\n [this._buildRawSQL(), other._buildRawSQL()],\n 'UNION',\n this._builder._getAdapter(),\n this._builder._getDialect(),\n )\n }\n\n /**\n * Combine via UNION ALL — keeps duplicate rows.\n */\n unionAll(other: ColumnRestrictedBuilder<string, TCol, SchemaMap, RelationsMap>): UnionBuilder<TCol> {\n return new UnionBuilder<TCol>(\n [this._buildRawSQL(), other._buildRawSQL()],\n 'UNION ALL',\n this._builder._getAdapter(),\n this._builder._getDialect(),\n )\n }\n}\n\n// ── SoftDeleteBuilder ─────────────────────────────────────────────────────\n// Returned by SelectBuilder.softDelete() and SelectBuilder.restore().\n// Accepts .where() for scoping, then .execute() to run the UPDATE.\n// Does NOT call beforeUpdate/afterUpdate hooks — soft delete is a system operation.\n\nexport class SoftDeleteBuilder<T, S extends SchemaMap> {\n private _conditions: WhereInput<T> = {} as WhereInput<T>\n\n constructor(\n private readonly adapter: VelnAdapter,\n private readonly table: TableDef<T, S>,\n private readonly _value: Date | null,\n private readonly _dialect: SqlDialect = 'sqlite',\n ) {}\n\n /**\n * Add WHERE conditions to scope which rows are soft-deleted / restored.\n * Multiple calls accumulate with AND.\n * Without .where(), all rows in the table are affected.\n */\n where(conditions: WhereInput<T>): this {\n this._conditions = mergeWhereAnd(this._conditions, conditions)\n return this\n }\n\n /**\n * Execute the soft-delete or restore UPDATE.\n * Throws if the table has no softDeleteColumn configured.\n */\n async execute(): Promise<void> {\n const col = this.table.softDeleteColumn\n if (col === null) {\n throw new Error(\n `softDelete() called on table '${this.table.name}' which has no soft delete column. ` +\n `Add .withSoftDelete('deletedAt') to the table definition.`,\n )\n }\n const { sql, params } = buildSoftDeleteUpdate(\n this.table.name,\n col as string,\n this._value,\n this._conditions as WhereInput<Record<string, unknown>>,\n this._dialect,\n )\n await this.adapter.execute(sql, params)\n }\n}\n\n// ── UnionBuilder ──────────────────────────────────────────────────────────\n// Returned by ColumnRestrictedBuilder.union() / .unionAll().\n// Chains UNION / UNION ALL queries and executes them as a single query.\n\nexport class UnionBuilder<T> {\n private _orderBy?: { col: string; dir: 'ASC' | 'DESC' }\n private _limit?: number\n\n constructor(\n private readonly _parts: Array<{ sql: string; params: BindingValue[] }>,\n private readonly _kind: 'UNION' | 'UNION ALL',\n private readonly _adapter: VelnAdapter,\n private readonly _dialect: SqlDialect,\n ) {}\n\n /** Append another UNION (deduplicating) leg. */\n union(other: ColumnRestrictedBuilder<string, T, SchemaMap, RelationsMap>): UnionBuilder<T> {\n return new UnionBuilder<T>(\n [...this._parts, other._buildRawSQL()],\n 'UNION',\n this._adapter,\n this._dialect,\n )\n }\n\n /** Append another UNION ALL (keep duplicates) leg. */\n unionAll(other: ColumnRestrictedBuilder<string, T, SchemaMap, RelationsMap>): UnionBuilder<T> {\n return new UnionBuilder<T>(\n [...this._parts, other._buildRawSQL()],\n 'UNION ALL',\n this._adapter,\n this._dialect,\n )\n }\n\n /** Add ORDER BY to the entire UNION result. */\n orderBy(col: string, dir: 'ASC' | 'DESC' = 'ASC'): UnionBuilder<T> {\n const next = new UnionBuilder<T>(this._parts, this._kind, this._adapter, this._dialect)\n next._orderBy = { col, dir }\n next._limit = this._limit\n return next\n }\n\n /** Add LIMIT to the entire UNION result. */\n limit(n: number): UnionBuilder<T> {\n const next = new UnionBuilder<T>(this._parts, this._kind, this._adapter, this._dialect)\n next._orderBy = this._orderBy\n next._limit = n\n return next\n }\n\n /** Execute the UNION query and return typed rows. */\n async select(): Promise<Record<string, T>[]> {\n const { sql, params } = buildUnion(this._parts, this._kind, {\n orderBy: this._orderBy,\n limit: this._limit,\n })\n return this._adapter.query<Record<string, T>>(sql, params)\n }\n\n /**\n * Build the UNION as a subquery — wrapped in parentheses.\n * Usable in WHERE IN / NOT IN conditions.\n *\n * @example\n * const adminOrModIds = db.from(usersTable).columns('id').where({ role: 'admin' })\n * .union(db.from(usersTable).columns('id').where({ role: 'mod' }))\n * .subquery()\n */\n subquery(): SubqueryResult<string, T> {\n const { sql, params } = buildUnion(this._parts, this._kind, {\n orderBy: this._orderBy,\n limit: this._limit,\n })\n return buildSubquery<string, T>(sql, params, '')\n }\n}\n\n// ── InsertBuilder ──────────────────────────────────────────────────────────\n\nexport class InsertBuilder<T, S extends SchemaMap> {\n constructor(\n private readonly adapter: VelnAdapter,\n private readonly hooks: HookExecutor,\n private readonly ctx: unknown,\n private readonly queue: RequestEventQueue | undefined,\n private readonly table: TableDef<T, S>,\n private readonly dialect: SqlDialect = 'sqlite',\n ) {}\n\n async insert(data: InferInsert<S>): Promise<T> {\n const originalInput = { ...data } as Partial<T>\n let current = { ...data } as Partial<T>\n\n // 1. Run beforeInsert hooks (may transform data)\n current = await this.hooks.runBeforeInsert(this.table, this.ctx, current)\n\n // 2. Apply defaultFns and defaultValues for unset fields\n for (const [field, col] of Object.entries(this.table.schema)) {\n // Skip autoIncrement primary keys — DB assigns the value\n if (col.def.primaryKey && col.def.autoIncrement) continue\n\n if ((current as Record<string, unknown>)[field] === undefined) {\n if (col.def.defaultFn !== undefined) {\n ;(current as Record<string, unknown>)[field] = col.def.defaultFn()\n } else if (col.def.defaultValue !== undefined) {\n ;(current as Record<string, unknown>)[field] = col.def.defaultValue\n }\n }\n }\n\n // 3. Serialize values for SQLite (Date → ISO string)\n const serialized = this._serializeForInsert(current as Record<string, unknown>)\n\n // 4. Execute INSERT RETURNING * — single round-trip, no follow-up SELECT needed.\n // SQLite ≥ 3.35 and PostgreSQL both support RETURNING *.\n // We use adapter.query() (not execute()) because RETURNING * yields rows.\n const { sql, params } = buildInsert(this.table.name, serialized, true)\n const rows = await this.adapter.query<Record<string, unknown>>(sql, params)\n const result = deserializeRow(this.table, rows[0]!)\n\n // 6. Run afterInsert hooks — events collected into queue, not emitted immediately\n await this.hooks.runAfterInsert(this.table, this.ctx, result, originalInput, this.queue)\n\n return result\n }\n\n /**\n * Insert multiple rows in a single SQL statement.\n * beforeInsert and afterInsert hooks run per row.\n * Defaults (defaultFn / defaultValue) are applied per row.\n *\n * MySQL is not yet supported (no RETURNING *) — throws an informative error.\n *\n * @example\n * const users = await db.into(usersTable).insertMany([\n * { name: 'Alice', email: 'alice@example.com' },\n * { name: 'Bob', email: 'bob@example.com' },\n * ])\n */\n async insertMany(data: InferInsert<S>[]): Promise<T[]> {\n if (data.length === 0) return []\n\n if (this.dialect === 'mysql') {\n throw new Error(\n 'insertMany is not yet supported for MySQL — MySQL does not support RETURNING *. ' +\n 'Use individual insert() calls inside a transaction() instead.',\n )\n }\n\n // Phase 1: run hooks + apply defaults + serialize — all before touching the adapter\n const serializedRows: Record<string, BindingValue>[] = []\n\n for (const row of data) {\n // a. beforeInsert hooks (may transform data)\n let processed: Partial<T> = await this.hooks.runBeforeInsert(\n this.table,\n this.ctx,\n { ...row } as Partial<T>,\n )\n\n // b. Apply defaultFns and defaultValues for unset fields\n for (const [field, col] of Object.entries(this.table.schema)) {\n if (col.def.primaryKey && col.def.autoIncrement) continue\n if ((processed as Record<string, unknown>)[field] === undefined) {\n if (col.def.defaultFn !== undefined) {\n ;(processed as Record<string, unknown>)[field] = col.def.defaultFn()\n } else if (col.def.defaultValue !== undefined) {\n ;(processed as Record<string, unknown>)[field] = col.def.defaultValue\n }\n }\n }\n\n // c. Serialize (Date → ISO string), cast to BindingValue[] — undefined already removed\n const serialized = this._serializeForInsert(processed as Record<string, unknown>)\n serializedRows.push(serialized as Record<string, BindingValue>)\n }\n\n // Phase 2: single INSERT … VALUES (…), (…) RETURNING *\n const { sql, params } = buildInsertMany(this.table.name, serializedRows, true)\n const rawRows = await this.adapter.query<Record<string, unknown>>(sql, params)\n\n // Phase 3: deserialize results + run afterInsert hooks per row\n const results: T[] = []\n for (const rawRow of rawRows) {\n const deserialized = deserializeRow(this.table, rawRow)\n await this.hooks.runAfterInsert(this.table, this.ctx, deserialized, {}, this.queue)\n results.push(deserialized)\n }\n\n return results\n }\n\n /** Serialize values for storage. Date → ISO string. Drops undefined values. */\n private _serializeForInsert(data: Record<string, unknown>): Record<string, unknown> {\n const result: Record<string, unknown> = {}\n for (const [key, val] of Object.entries(data)) {\n if (val === undefined) continue\n result[key] = val instanceof Date ? val.toISOString() : val\n }\n return result\n }\n}\n\n// ── JoinBuilder ───────────────────────────────────────────────────────────────\n// Immutable fluent builder for SELECT queries with JOIN clauses.\n// Returns Record<string, unknown>[] — results span multiple tables so no single\n// TypeDef can describe the shape.\n\nexport class JoinBuilder {\n constructor(\n private readonly adapter: VelnAdapter,\n private readonly tableName: string,\n private readonly _columns: string[],\n private readonly _joins: JoinClause[],\n private readonly _where: string,\n private readonly _params: BindingValue[],\n private readonly _options: SelectOptions = {},\n ) {}\n\n private _cloneOpts(patch: Partial<SelectOptions>): JoinBuilder {\n return new JoinBuilder(\n this.adapter,\n this.tableName,\n this._columns,\n this._joins,\n this._where,\n this._params,\n { ...this._options, ...patch },\n )\n }\n\n /** Restrict the selected columns (e.g. ['orders.id', 'users.name']). */\n columns(cols: string[]): JoinBuilder {\n return new JoinBuilder(this.adapter, this.tableName, cols, this._joins, this._where, this._params, this._options)\n }\n\n /** Add an INNER JOIN clause. */\n join(table: string, on: string): JoinBuilder {\n return this._addJoin('INNER', table, on)\n }\n\n /** Add a LEFT JOIN clause. */\n leftJoin(table: string, on: string): JoinBuilder {\n return this._addJoin('LEFT', table, on)\n }\n\n /** Add a RIGHT JOIN clause. */\n rightJoin(table: string, on: string): JoinBuilder {\n return this._addJoin('RIGHT', table, on)\n }\n\n /** Add a FULL JOIN clause. */\n fullJoin(table: string, on: string): JoinBuilder {\n return this._addJoin('FULL', table, on)\n }\n\n /**\n * Set a typed WHERE clause from a conditions object.\n * Each key becomes \"key\" = ? — values are bound safely.\n *\n * @example\n * .where({ status: 'pending', userId })\n */\n where(conditions: Record<string, BindingValue>): JoinBuilder\n /**\n * Set a raw WHERE clause.\n * Use ? as placeholder; pass bind values as the second argument.\n *\n * @example\n * .where('orders.status = ? AND orders.user_id = ?', ['pending', userId])\n */\n where(sql: string, params: BindingValue[]): JoinBuilder\n where(conditionsOrSql: Record<string, BindingValue> | string, params?: BindingValue[]): JoinBuilder {\n if (typeof conditionsOrSql === 'string') {\n return new JoinBuilder(this.adapter, this.tableName, this._columns, this._joins, conditionsOrSql, params ?? [], this._options)\n }\n const { sql, params: builtParams } = buildWhere(conditionsOrSql)\n return new JoinBuilder(this.adapter, this.tableName, this._columns, this._joins, sql, builtParams, this._options)\n }\n\n /** Limit the number of rows returned. Bound as a parameter — never interpolated. */\n limit(n: number): JoinBuilder {\n return this._cloneOpts({ limit: n })\n }\n\n /** Skip the first n rows. Bound as a parameter — never interpolated. */\n offset(n: number): JoinBuilder {\n return this._cloneOpts({ offset: n })\n }\n\n /**\n * Add an ORDER BY clause. Multiple calls accumulate in order.\n * @param col Column reference, e.g. 'orders.created_at' or 'name'.\n */\n orderBy(col: string, dir: 'ASC' | 'DESC' = 'ASC'): JoinBuilder {\n const existing = this._options.orderBy ?? []\n return this._cloneOpts({ orderBy: [...existing, { col, dir }] })\n }\n\n /**\n * Convenience helper for cursor-based pagination.\n * page(1, 10) → LIMIT 10 OFFSET 0\n * page(2, 10) → LIMIT 10 OFFSET 10\n */\n page(page: number, size: number): JoinBuilder {\n return this._cloneOpts({ limit: size, offset: (page - 1) * size })\n }\n\n /**\n * Execute the query and return raw rows (no deserialization).\n *\n * @remarks\n * Type parameter T is a manual cast — not validated at runtime.\n * For runtime validation, use db.raw() with a Zod schema instead.\n */\n async select<T = Record<string, unknown>>(): Promise<T[]> {\n const { sql, params } = buildJoinSelect(\n this.tableName,\n this._columns,\n this._joins,\n this._where,\n this._params,\n this._options,\n )\n return this.adapter.query<T>(sql, params)\n }\n\n /**\n * Execute the query and return the first row, or null.\n *\n * @remarks\n * Type parameter T is a manual cast — not validated at runtime.\n */\n async first<T = Record<string, unknown>>(): Promise<T | null> {\n const rows = await this.select<T>()\n return rows[0] ?? null\n }\n\n private _addJoin(type: JoinClause['type'], table: string, on: string): JoinBuilder {\n return new JoinBuilder(\n this.adapter,\n this.tableName,\n this._columns,\n [...this._joins, { type, table, on }],\n this._where,\n this._params,\n this._options,\n )\n }\n}\n","// Adapter\nexport type { VelnAdapter, BindingValue, ExecuteResult, QueryLogEntry } from './adapter/types'\nexport { SQLiteAdapter } from './adapter/sqlite'\nexport type { SQLiteConfig } from './adapter/sqlite'\nexport { PostgresAdapter } from './adapter/postgres'\nexport type { PostgresConfig } from './adapter/postgres'\nexport { MySQLAdapter } from './adapter/mysql'\nexport type { MySQLConfig } from './adapter/mysql'\nexport { resolveAdapter } from './adapter/resolve'\nexport type { AdapterConfig } from './adapter/resolve'\n\n// Schema\nexport { column } from './schema/column'\nexport type { Column, ColumnDef, SqlType } from './schema/column'\nexport { defineTable, toCreateTableSql } from './schema/table'\nexport type {\n SchemaMap, InferRow, InferInsert, InferUpdate, InferTable,\n TableDef, TableHookHandlers,\n TableEventMap, InferTableEvents,\n RelationMeta, RelationKind, RelationsMap,\n BelongsToRelation, HasManyRelation,\n InferRelationResult, WithRelations,\n} from './schema/table'\nexport { defineAuditTable } from './schema/audit'\nexport type { AuditTableDef, AuditLog, AuditConfig } from './schema/audit'\n\n// Hooks\nexport { HookExecutor } from './hooks/executor'\nexport type { ModuleHookHandlers, HookOperation } from './hooks/types'\n\n// Migrations\nexport { createMigrator, generateMigration, compareSchemas, introspectSchema, splitSqlStatements } from './db/migrations/index'\nexport type {\n Migrator, MigratorOptions, MigrationResult, MigrationStatus, MigrationRecord,\n SchemaDiff, TableDiff, TableModification, ColumnDef as MigrationColumnDef,\n IndexDef, ColumnModification,\n GenerateOptions, GenerateResult,\n} from './db/migrations/index'\n\n// DB\nexport { VelnDB, BoundVelnDB, SelectBuilder, InsertBuilder, JoinBuilder, SoftDeleteBuilder, UnionBuilder } from './db/index'\nexport type {\n PendingEvent, TransactionResult, QueryLog,\n} from './db/index'\nexport type { JoinClause, SelectOptions, AggregateClause, WhereInput, WhereOp, WhereConditions, FieldCondition, SqlDialect, InValue, SubqueryResult } from './db/sql'\nexport { buildSubquery, buildUnion } from './db/sql'\n// EventBus interface (structural type from db layer — the class below satisfies it)\nexport type { EventBus as EventBusInterface } from './db/index'\n\n// Events\nexport { InMemoryEventBus, EventBus, RequestEventQueue } from './events/index'\nexport type { EventBusAdapter, EventBusOptions, EventBusErrorHandler } from './events/index'\nexport type { EventHandler, VelnEvents } from './events/index'\nexport { defineEventHandler, EventHandlerBuilder } from './events/handler'\nexport type { EventHandlerDef, EventCallback, EventHandlerFn } from './events/handler'\n\n// Model\nexport { defineModel, ModelBuilder } from './model/index'\nexport type { ModelDef, ModelInstance } from './model/index'\n\n// Service\nexport { defineService } from './service/index'\nexport type { ServiceDef } from './service/index'\n\n// Middleware\nexport { defineMiddleware, MiddlewareBuilder } from './app/middleware'\nexport type { MiddlewareDef } from './app/middleware'\n\n// App\nexport { createApp, Veln } from './app/index'\nexport { createSystemCtx } from './app/system-ctx'\nexport { defineModule, ModuleBuilder } from './app/module'\nexport type { VelnModule, HookDeclaration, AuditDeclaration, ServiceDeclaration } from './app/module'\nexport { loggerPlugin, dbPlugin, eventBusPlugin, createPlugin, definePlugin, PluginBuilder } from './app/plugin'\nexport type { DbPluginConfig, DbLogOptions, NavItem } from './app/plugin'\nexport type { Plugin } from './app/plugin'\nexport type { BaseCtx, Guard, ErrorHandler, RouteHandler, Logger, AuthPayload, LogOptions, BaseOptions, AuthUser, AuthAdapter } from './app/types'\nexport { ValidationError, createGuard, defineGuard, createOnRequest, createOnBeforeHandle, createOnResponse } from './app/types'\nexport { secureHeadersPlugin } from './app/secure-headers'\nexport type { SecureHeadersOptions, CspPreset } from './app/secure-headers'\nexport { rateLimitPlugin, InMemoryStore } from './app/rate-limit'\nexport type { RateLimitOptions, RateLimitStore } from './app/rate-limit'\nexport { csrfPlugin } from './app/csrf'\nexport type { CsrfOptions, CsrfPlugin } from './app/csrf'\nexport { scalarPlugin } from './app/scalar'\nexport type { ScalarOptions } from './app/scalar'\nexport { bodySizeLimitPlugin } from './app/body-size-limit'\nexport type { BodySizeLimitOptions } from './app/body-size-limit'\nexport { corsPlugin } from './app/cors'\nexport type { CorsOptions, CorsPlugin } from './app/cors'\nexport { requestIdPlugin } from './app/request-id'\nexport type { RequestIdOptions, RequestIdCtx, RequestIdPlugin } from './app/request-id'\nexport { compressionPlugin } from './app/compression'\nexport type { CompressionOptions } from './app/compression'\nexport { healthPlugin } from './app/health'\nexport type { HealthPluginOptions, HealthCheck, HealthPlugin } from './app/health'\nexport type { VelnWsAdapter, WsRouteShape } from './app/types'\nexport type { RouteSchema, RouteHandlerWithSchema, InferCtx } from './app/types'\nexport type { RouteMap, RouteEntry, RouteKey } from './app/types'\nexport type { StreamController, StreamOptions, SseController } from './app/types'\nexport type { OnRequestHook, OnBeforeHandleHook, OnResponseHook, OnRequestFn, OnBeforeHandleFn, OnResponseFn } from './app/types'\n\n// Client\nexport { createClient } from './client/index'\nexport { createProxyClient, createModuleClient, pathToClientKey } from './client/index'\nexport type { ClientResult, InferProxyClient, ProxyClientOptions } from './client/index'\nexport { createTestClient } from './client/test-client'\nexport type { TestClientOptions } from './client/test-client'\nexport { VelnClientError } from './client/error'\n\n// OpenAPI\nexport { generateOpenApiSpec } from './openapi/generator'\nexport type { OpenApiSpec } from './openapi/generator'\nexport { zodToJsonSchema } from './openapi/zod-to-schema'\nexport type { JsonSchema } from './openapi/zod-to-schema'\n\n// Resource\nexport { defineResource, ResourceBuilder, NotFoundError, ConflictError, tableToZodInsert, tableToZodRow } from './resource/index'\nexport type { ResourceResult, DefaultModelMethods, ResourceOptions, ModelOverrides, ServiceOverrides, RouteConfig } from './resource/index'\n\n// Cron\nexport { defineCron, resolveExpression, NoOpCronLockAdapter } from './cron/index'\nexport type { CronDef, CronBuilder, CronCtx, CronBuildOptions, LogLevel, CronLockAdapter } from './cron/index'\n\n// CLI config helpers\nexport { defineConfig, defineCommand } from './cli/index'\nexport type { VelnConfig, CommandDef, CommandOption } from './cli/index'\n\n// Errors\nexport {\n VelnError,\n BadRequestError,\n UnauthorizedError,\n ForbiddenError,\n UnprocessableError,\n TooManyRequestsError,\n InternalError,\n} from './errors/index'\n","import type { VelnAdapter } from './types'\n\nexport type AdapterConfig =\n | { adapter: 'sqlite'; path?: string }\n | { adapter: 'postgres'; connectionString: string; maxConnections?: number }\n | { adapter: 'mysql'; connectionString: string; maxConnections?: number }\n\nexport function isVelnAdapter(value: unknown): value is VelnAdapter {\n return (\n typeof value === 'object' &&\n value !== null &&\n typeof (value as VelnAdapter).query === 'function' &&\n typeof (value as VelnAdapter).execute === 'function'\n )\n}\n\nexport function resolveAdapter(config: AdapterConfig | VelnAdapter): VelnAdapter {\n if (isVelnAdapter(config)) return config\n\n const cfg = config as AdapterConfig\n\n if (cfg.adapter === 'sqlite') {\n // eslint-disable-next-line @typescript-eslint/no-require-imports\n const { SQLiteAdapter } = require('./sqlite') as typeof import('./sqlite')\n return new SQLiteAdapter(cfg.path ? { path: cfg.path } : { path: './db.sqlite' })\n }\n\n if (cfg.adapter === 'postgres') {\n // eslint-disable-next-line @typescript-eslint/no-require-imports\n const { PostgresAdapter } = require('./postgres') as typeof import('./postgres')\n return new PostgresAdapter({ url: cfg.connectionString, max: cfg.maxConnections })\n }\n\n if (cfg.adapter === 'mysql') {\n // eslint-disable-next-line @typescript-eslint/no-require-imports\n const { MySQLAdapter } = require('./mysql') as typeof import('./mysql')\n return new MySQLAdapter({ url: cfg.connectionString, max: cfg.maxConnections })\n }\n\n throw new Error(`[oakbun] resolveAdapter: unknown adapter type \"${(cfg as AdapterConfig & { adapter: string }).adapter}\"`)\n}\n","export type SqlType =\n | 'INTEGER'\n | 'TEXT'\n | 'REAL'\n | 'BOOLEAN'\n | 'TIMESTAMP'\n | 'JSON'\n | 'UUID'\n | 'BLOB'\n\nexport interface ColumnDef {\n type: SqlType\n nullable: boolean\n primaryKey: boolean\n autoIncrement: boolean\n unique: boolean\n defaultValue?: unknown\n defaultFn?: () => unknown\n}\n\nexport class Column<T> {\n // Phantom type — exists only at compile time, never assigned at runtime\n declare readonly _: T\n\n constructor(readonly def: Readonly<ColumnDef>) {}\n\n nullable(): Column<T | null> {\n return new Column<T | null>({ ...this.def, nullable: true })\n }\n\n primaryKey(): Column<T> {\n return new Column<T>({ ...this.def, primaryKey: true, autoIncrement: true })\n }\n\n unique(): Column<T> {\n return new Column<T>({ ...this.def, unique: true })\n }\n\n default(value: NonNullable<T>): Column<T> {\n return new Column<T>({ ...this.def, defaultValue: value })\n }\n\n defaultFn(fn: () => NonNullable<T>): Column<T> {\n return new Column<T>({ ...this.def, defaultFn: fn as () => unknown })\n }\n}\n\nconst base = (type: SqlType): ColumnDef => ({\n type,\n nullable: false,\n primaryKey: false,\n autoIncrement: false,\n unique: false,\n})\n\nexport const column = {\n integer: (): Column<number> => new Column<number>({ ...base('INTEGER') }),\n text: (): Column<string> => new Column<string>({ ...base('TEXT') }),\n real: (): Column<number> => new Column<number>({ ...base('REAL') }),\n boolean: (): Column<boolean> => new Column<boolean>({ ...base('BOOLEAN') }),\n timestamp: (): Column<Date> => new Column<Date>({ ...base('TIMESTAMP') }),\n uuid: (): Column<string> => new Column<string>({ ...base('UUID') }),\n blob: (): Column<Uint8Array> => new Column<Uint8Array>({ ...base('BLOB') }),\n json: <T = unknown>(): Column<T> => new Column<T>({ ...base('JSON') }),\n}\n","import type { Column } from './column'\n\nexport type SchemaMap = Record<string, Column<any>>\n\n// Full row type — what you get back from SELECT.\n// Accepts either a SchemaMap directly or a TableDef (extracts its row type T).\nexport type InferRow<T> =\n T extends TableDef<infer R, any, any> ? R :\n T extends SchemaMap ? { [K in keyof T]: T[K] extends Column<infer C> ? C : never } :\n never\n\n// Insert type — PK + defaulted columns are optional, rest required\ntype IsOptionalOnInsert<C extends Column<any>> =\n C['def']['primaryKey'] extends true ? true :\n C['def']['defaultValue'] extends undefined ?\n C['def']['defaultFn'] extends undefined ?\n C['def']['nullable'] extends true ? true : false\n : true\n : true\n\ntype InferInsertFromSchema<S extends SchemaMap> =\n {\n [K in keyof S as IsOptionalOnInsert<S[K]> extends true ? never : K]:\n S[K] extends Column<infer T> ? NonNullable<T> : never\n } & {\n [K in keyof S as IsOptionalOnInsert<S[K]> extends true ? K : never]?:\n S[K] extends Column<infer T> ? T : never\n }\n\n// Accepts either a SchemaMap or a TableDef directly.\nexport type InferInsert<T> =\n T extends TableDef<any, infer S, any> ? InferInsertFromSchema<S> :\n T extends SchemaMap ? InferInsertFromSchema<T> :\n never\n\n// Update type — all fields Partial, primary key fields required.\n// Accepts either a SchemaMap or a TableDef directly.\nexport type InferUpdate<T> =\n T extends TableDef<infer R, infer S, any>\n ? Partial<R> & { [K in keyof S as S[K] extends Column<any> ? S[K]['def']['primaryKey'] extends true ? K : never : never]: R[K & keyof R] }\n : T extends SchemaMap\n ? Partial<{ [K in keyof T]: T[K] extends Column<infer C> ? C : never }>\n : never\n\n// Convenience wrapper — one import gives all three shapes.\nexport type InferTable<T extends TableDef<any, any, any>> = {\n row: InferRow<T>\n insert: InferInsert<T>\n update: InferUpdate<T>\n}\n\n// Table-level hook handlers — no ctx, always fire\nexport interface TableHookHandlers<T> {\n beforeInsert?: (data: Partial<T>) => Partial<T> | void | Promise<Partial<T> | void>\n afterInsert?: (result: T, input: Partial<T>) => void | Promise<void>\n beforeUpdate?: (current: T, patch: Partial<T>) => Partial<T> | void | Promise<Partial<T> | void>\n afterUpdate?: (result: T, before: T) => void | Promise<void>\n beforeDelete?: (current: T) => void | Promise<void>\n afterDelete?: (deleted: T) => void | Promise<void>\n}\n\n// Event map — declared on the Table, enforced by the framework\nexport interface TableEventMap {\n afterInsert?: string // event name to fire after insert\n afterUpdate?: string // event name to fire after update\n afterDelete?: string // event name to fire after delete\n}\n\n// Infer event payload types from a Table + EventMap.\n//\n// STAGING NOTE (Phase 3 → Phase 4):\n// This type is fully computed here at the Table level. However, app.on() currently\n// accepts `event: string` because TypeScript cannot recover these generic types after\n// they pass through VelnModule (which erases them). In Phase 4, the RPC client and\n// a dedicated app.onEvent<T>() overload will use InferTableEvents directly at the\n// call site, without needing Declaration Merging. Until then, Declaration Merging\n// via `interface VelnEvents {}` is the opt-in escape hatch for typed subscribers.\n//\n// Implementation note: three separate mapped types are intersected instead of using\n// a conditional `K extends 'afterUpdate'` inside a single mapped type. The conditional\n// form is deferred by TypeScript when K is generic, causing TMap[K] to resolve as a\n// union of all value types at the call site. The intersection approach produces a\n// concrete object type that TypeScript evaluates eagerly.\nexport type InferTableEvents<T, M extends TableEventMap> =\n (M['afterInsert'] extends string ? { [_ in M['afterInsert']]: T } : Record<never, never>) &\n (M['afterUpdate'] extends string ? { [_ in M['afterUpdate']]: { before: T; after: T } } : Record<never, never>) &\n (M['afterDelete'] extends string ? { [_ in M['afterDelete']]: T } : Record<never, never>)\n\n// ── Relation Metadata ─────────────────────────────────────────────────────\n\nexport type RelationKind = 'belongsTo' | 'hasMany' | 'manyToMany'\n\n/**\n * Metadata for a single declared relation.\n * TForeign captures the foreign table's row type so that WithRelations can\n * produce concrete types (User, Post[]) rather than unknown.\n *\n * `getTable` is a lazy getter to allow circular references between tables.\n */\nexport interface RelationMeta<TForeign = unknown> {\n kind: RelationKind\n name: string\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n getTable: () => TableDef<TForeign, any, any>\n /** FK column name — on this table for belongsTo, on foreign table for hasMany */\n foreignKey: string\n /** manyToMany only */\n pivot?: {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n table: TableDef<any, any, any>\n localKey: string\n foreignKey: string\n }\n}\n\n/** All declared relations on a table, keyed by relation name. */\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport type RelationsMap = Record<string, RelationMeta<any>>\n\n// ── Eager-loading types ────────────────────────────────────────────────────\n\n// Typed relation interfaces — one per kind.\n// WithRelations indexes into these to get a concrete type per relation name.\n// This avoids deferred conditional types (R['kind'] extends 'belongsTo') which\n// TypeScript cannot evaluate when R is still a generic parameter.\n\nexport interface BelongsToRelation<TForeign> extends RelationMeta<TForeign> {\n kind: 'belongsTo'\n}\n\nexport interface HasManyRelation<TForeign> extends RelationMeta<TForeign> {\n kind: 'hasMany'\n}\n\n/**\n * Derives the result type of a single loaded relation.\n * - belongsTo → TForeign | null\n * - hasMany → TForeign[]\n * - manyToMany → never (not supported in Spec B)\n */\nexport type InferRelationResult<R> =\n R extends BelongsToRelation<infer TForeign>\n ? TForeign | null\n : R extends HasManyRelation<infer TForeign>\n ? TForeign[]\n : never\n\n/**\n * Merges a row type T with the requested relations.\n * Keys must be keys of the table's relations map.\n *\n * @example\n * type PostWithAuthor = WithRelations<Post, typeof postsTable, 'author'>\n * // → Post & { author: User | null }\n */\nexport type WithRelations<\n T,\n TTable extends { relations: RelationsMap },\n Keys extends keyof TTable['relations'] & string,\n> = T & {\n [K in Keys]: InferRelationResult<TTable['relations'][K]>\n}\n\nexport interface TableDef<\n T,\n S extends SchemaMap = SchemaMap,\n TEvents extends TableEventMap = TableEventMap,\n TRelations extends RelationsMap = RelationsMap,\n> {\n readonly name: string\n readonly schema: S\n readonly primaryKey: keyof T & string\n readonly hooks: TableHookHandlers<T>[]\n readonly events: TEvents // typed — not just TableEventMap\n // eventMap is the precomputed InferTableEvents<T, TEvents> shape.\n // Storing it as a concrete generic parameter (TMap) lets onEvent() index it\n // directly as TMap[K] without TypeScript deferring the conditional InferTableEvents.\n readonly _eventMap: InferTableEvents<T, TEvents>\n /** Declared relations — concrete typed map so WithRelations can infer foreign types. */\n readonly relations: TRelations\n /** The column used for soft delete, or null if not configured. */\n readonly softDeleteColumn: (keyof T & string) | null\n}\n\nexport class TableBuilder<\n T,\n S extends SchemaMap,\n TEvents extends TableEventMap = Record<string, never>,\n TRelations extends RelationsMap = Record<string, never>,\n> {\n private readonly _hooks: TableHookHandlers<T>[] = []\n private _events: TableEventMap = {}\n private readonly _relations: RelationsMap = {}\n private _softDeleteColumn: (keyof T & string) | null = null\n\n constructor(\n private readonly _name: string,\n private readonly _schema: S,\n ) {}\n\n // Register table-level hook (no ctx)\n hook(handlers: TableHookHandlers<T>): this {\n this._hooks.push(handlers)\n return this\n }\n\n /**\n * Designate a column as the soft-delete timestamp.\n * Once set, all SELECTs automatically add `WHERE \"col\" IS NULL`.\n * Use `.withDeleted()` on the query to opt out.\n *\n * The column must exist in the schema (validated in `build()`).\n *\n * @example\n * const usersTable = defineTable('users', {\n * id: column.integer().primaryKey(),\n * deletedAt: column.timestamp().nullable(),\n * }).withSoftDelete('deletedAt').build()\n */\n withSoftDelete<Col extends keyof T & string>(col: Col): this {\n this._softDeleteColumn = col\n return this\n }\n\n emits<M extends TableEventMap>(map: M): TableBuilder<T, S, M, TRelations> {\n const next = new TableBuilder<T, S, M, TRelations>(this._name, this._schema)\n // copy existing hooks, relations, and softDeleteColumn\n for (const h of this._hooks) (next as unknown as TableBuilder<T, S>)._hooks.push(h)\n ;(next as unknown as TableBuilder<T, S, M, TRelations>)._events = map\n for (const [k, v] of Object.entries(this._relations)) {\n ;(next as unknown as TableBuilder<T, S>)._relations[k] = v\n }\n ;(next as unknown as TableBuilder<T, S>)._softDeleteColumn = this._softDeleteColumn\n return next\n }\n\n /**\n * Declare a belongs-to relation — FK lives on this table.\n * Returns a new builder with the relation type added to TRelations.\n *\n * @example\n * const postsTable = defineTable('posts', { authorId: column.integer() })\n * .belongsTo('author', () => usersTable, 'authorId')\n * .build()\n */\n belongsTo<K extends string, TForeign>(\n name: K,\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n getTable: () => TableDef<TForeign, any, any, any>,\n foreignKey: keyof T & string,\n ): TableBuilder<T, S, TEvents, TRelations & Record<K, BelongsToRelation<TForeign>>> {\n if (name in this._relations) {\n throw new Error(`Relation '${name}' is already defined on table '${this._name}'`)\n }\n const rel: BelongsToRelation<TForeign> = { kind: 'belongsTo', name, getTable, foreignKey }\n this._relations[name] = rel\n return this as unknown as TableBuilder<T, S, TEvents, TRelations & Record<K, BelongsToRelation<TForeign>>>\n }\n\n /**\n * Declare a has-many relation — FK lives on the foreign table.\n * Returns a new builder with the relation type added to TRelations.\n *\n * @example\n * const usersTable = defineTable('users', { id: column.integer().primaryKey() })\n * .hasMany('posts', () => postsTable, 'authorId')\n * .build()\n */\n hasMany<K extends string, TForeign>(\n name: K,\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n getTable: () => TableDef<TForeign, any, any, any>,\n /** The FK column on the *foreign* table that points back to this table's PK. */\n foreignKey: string,\n ): TableBuilder<T, S, TEvents, TRelations & Record<K, HasManyRelation<TForeign>>> {\n if (name in this._relations) {\n throw new Error(`Relation '${name}' is already defined on table '${this._name}'`)\n }\n const rel: HasManyRelation<TForeign> = { kind: 'hasMany', name, getTable, foreignKey }\n this._relations[name] = rel\n return this as unknown as TableBuilder<T, S, TEvents, TRelations & Record<K, HasManyRelation<TForeign>>>\n }\n\n /**\n * Declare a many-to-many relation via a pivot table.\n *\n * @example\n * const postsTable = defineTable('posts', { ... })\n * .manyToMany('tags', () => tagsTable, postTagsTable, 'postId', 'tagId')\n * .build()\n */\n manyToMany<K extends string>(\n name: K,\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n getTable: () => TableDef<any, any, any, any>,\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n pivotTable: TableDef<any, any, any, any>,\n /** FK on pivot pointing to this table's PK */\n localKey: string,\n /** FK on pivot pointing to the foreign table's PK */\n foreignKey: string,\n ): TableBuilder<T, S, TEvents, TRelations & Record<K, RelationMeta>> {\n if (name in this._relations) {\n throw new Error(`Relation '${name}' is already defined on table '${this._name}'`)\n }\n this._relations[name] = {\n kind: 'manyToMany',\n name,\n getTable,\n foreignKey,\n pivot: { table: pivotTable, localKey, foreignKey },\n }\n return this as unknown as TableBuilder<T, S, TEvents, TRelations & Record<K, RelationMeta>>\n }\n\n build(): TableDef<T, S, TEvents, TRelations> {\n if (this._softDeleteColumn !== null && !(this._softDeleteColumn in this._schema)) {\n throw new Error(\n `withSoftDelete: column '${this._softDeleteColumn as string}' is not defined in table '${this._name}'. ` +\n `Add it to the schema: column.timestamp().nullable()`,\n )\n }\n return {\n name: this._name,\n schema: this._schema,\n primaryKey: this._findPrimaryKey() as keyof T & string,\n hooks: [...this._hooks], // copy — immutable after build\n events: { ...this._events } as unknown as TEvents,\n // _eventMap is typed as InferTableEvents<T, TEvents> — the concrete shape.\n // At runtime it's an empty object (events hold only the string names, not payloads).\n // The field exists solely so TypeScript can infer TMap in onEvent() without\n // recomputing the conditional InferTableEvents each time.\n _eventMap: {} as InferTableEvents<T, TEvents>,\n relations: { ...this._relations } as TRelations,\n softDeleteColumn: this._softDeleteColumn,\n }\n }\n\n private _findPrimaryKey(): string {\n for (const [key, col] of Object.entries(this._schema)) {\n if ((col as Column<any>).def.primaryKey) return key\n }\n return 'id' // convention fallback\n }\n}\n\nexport function defineTable<S extends SchemaMap>(\n name: string,\n schema: S,\n): TableBuilder<InferRow<S>, S> {\n return new TableBuilder<InferRow<S>, S>(name, schema)\n}\n\n// Helper: generate CREATE TABLE SQL from a TableDef (SQLite dialect)\nexport function toCreateTableSql<T>(table: TableDef<T>): string {\n const cols = Object.entries(table.schema).map(([name, col]) => {\n const c = col as Column<any>\n let def = `\"${name}\" `\n\n switch (c.def.type) {\n case 'INTEGER': def += 'INTEGER'; break\n case 'TEXT':\n case 'UUID': def += 'TEXT'; break\n case 'REAL': def += 'REAL'; break\n case 'BOOLEAN': def += 'INTEGER'; break // SQLite has no BOOLEAN\n case 'TIMESTAMP': def += 'TEXT'; break // ISO string in SQLite\n case 'JSON': def += 'TEXT'; break\n case 'BLOB': def += 'BLOB'; break\n }\n\n if (c.def.primaryKey) def += ' PRIMARY KEY'\n if (c.def.autoIncrement && c.def.type === 'INTEGER') def += ' AUTOINCREMENT'\n if (!c.def.nullable && !c.def.primaryKey) def += ' NOT NULL'\n if (c.def.unique) def += ' UNIQUE'\n\n return def\n })\n\n return `CREATE TABLE IF NOT EXISTS \"${table.name}\" (${cols.join(', ')})`\n}\n","import { column } from './column'\nimport { defineTable } from './table'\nimport type { SchemaMap, TableDef, InferRow, TableBuilder } from './table'\n\n// ── Base audit fields — internal, never exported ────────────────────────────\n// Users must not depend on this shape directly; they extend via defineAuditTable().\n\nconst _baseAuditFields = {\n id: column.integer().primaryKey(),\n tableName: column.text(),\n operation: column.text(), // 'insert' | 'update' | 'delete'\n actor: column.text().nullable(),\n before: column.text().nullable(), // JSON string | null (null on insert)\n after: column.text().nullable(), // JSON string | null (null on delete)\n changedAt: column.timestamp().defaultFn(() => new Date()),\n} as const\n\ntype BaseAuditSchema = typeof _baseAuditFields\n\n// ── Public API ───────────────────────────────────────────────────────────────\n// defineAuditTable() = defineTable() with base audit fields pre-merged.\n// Users can add custom fields:\n// export const auditLogs = defineAuditTable('audit_logs', {\n// requestId: column.text().nullable(),\n// }).build()\n\nexport function defineAuditTable<S extends SchemaMap = Record<never, never>>(\n name: string,\n extraSchema?: S,\n): TableBuilder<InferRow<BaseAuditSchema & S>, BaseAuditSchema & S> {\n const merged = { ..._baseAuditFields, ...(extraSchema ?? {}) } as BaseAuditSchema & S\n return defineTable(name, merged)\n}\n\n// AuditTableDef — base shape (no extra fields). Useful as a parameter type\n// when a function accepts any audit table regardless of custom fields.\nexport type AuditTableDef<S extends SchemaMap = BaseAuditSchema> =\n TableDef<InferRow<BaseAuditSchema & S>, BaseAuditSchema & S>\n\n// AuditLog — base row type (no extra fields). Extend via InferRow<typeof myAuditTable>\n// for tables with custom fields.\nexport type AuditLog = InferRow<BaseAuditSchema>\n\n// ── AuditConfig — passed to .audit() on ModuleBuilder ───────────────────────\n\nexport interface AuditConfig<TCtx, TRow, S extends SchemaMap = BaseAuditSchema> {\n /** The audit table to write into. */\n storeIn: AuditTableDef<S>\n /** Extract actor identifier from request context. Return null for anonymous. */\n actor: (ctx: TCtx) => string | null | undefined\n /** Field names to replace with '[REDACTED]' in before/after snapshots. */\n redact?: (keyof TRow & string)[]\n /** Called when an audit write fails. Defaults to console.error. */\n onError?: (err: unknown) => void\n}\n\n// ── applyRedact — internal helper ───────────────────────────────────────────\n// Replaces specified fields with '[REDACTED]' in a shallow clone.\n// Never removes fields — '[REDACTED]' is distinguishable from absent/null.\n\nexport function applyRedact<T extends Record<string, unknown>>(\n row: T,\n fields: string[],\n): T {\n if (fields.length === 0) return row\n const copy = { ...row } as Record<string, unknown>\n for (const f of fields) {\n if (f in copy) copy[f] = '[REDACTED]'\n }\n return copy as T\n}\n","import type { VelnAdapter } from '../adapter/types'\nimport type { TableDef } from '../schema/table'\nimport type { ModuleHookHandlers } from './types'\nimport type { RequestEventQueue } from '../events/index'\n\n// ── BEFORE (executor.ts ~line 93-95):\n// Automatic event firing — immediate, fire & forget:\n// if (table.events.afterInsert) {\n// this.eventBus?._emit(table.events.afterInsert, result, ctx)\n// }\n//\n// ── AFTER (executor.ts ~line 93-95):\n// Collect into per-request queue — flushed by fetch() after onResponse:\n// if (table.events.afterInsert) {\n// queue?.collect(table.events.afterInsert, result)\n// }\n\nexport class HookExecutor {\n // tableName → ordered array of module-level handlers\n private readonly registry = new Map<string, ModuleHookHandlers<any, any>[]>()\n\n // Set by dbPlugin at install() — used by app.register() to build audit closures.\n // undefined until dbPlugin installs (no-DB apps never set this).\n private _adapter?: VelnAdapter\n\n // No EventBus held globally — queue is passed per runAfterX call\n constructor() {}\n\n setAdapter(adapter: VelnAdapter): void {\n this._adapter = adapter\n }\n\n getAdapter(): VelnAdapter | undefined {\n return this._adapter\n }\n\n // Called by defineModule when a .hook() is registered\n registerModuleHook<T, TCtx>(\n tableName: string,\n handlers: ModuleHookHandlers<T, TCtx>,\n ): void {\n if (!this.registry.has(tableName)) this.registry.set(tableName, [])\n this.registry.get(tableName)!.push(handlers)\n }\n\n // ── Before operations — can transform data, can throw to cancel ──\n\n async runBeforeInsert<T>(\n table: TableDef<T>,\n ctx: unknown,\n data: Partial<T>,\n ): Promise<Partial<T>> {\n let current = { ...data }\n\n // 1. Table-level (no ctx)\n for (const h of table.hooks) {\n if (!h.beforeInsert) continue\n const result = await h.beforeInsert(current)\n if (result != null) current = result as Partial<T>\n }\n\n // 2. Module-level (ctx-aware)\n for (const h of this._moduleHandlers(table.name)) {\n if (!h.beforeInsert) continue\n const result = await h.beforeInsert(ctx, current)\n if (result != null) current = result as Partial<T>\n }\n\n return current\n }\n\n async runBeforeUpdate<T>(\n table: TableDef<T>,\n ctx: unknown,\n current: T,\n patch: Partial<T>,\n ): Promise<Partial<T>> {\n let currentPatch = { ...patch }\n\n for (const h of table.hooks) {\n if (!h.beforeUpdate) continue\n const result = await h.beforeUpdate(current, currentPatch)\n if (result != null) currentPatch = result as Partial<T>\n }\n\n for (const h of this._moduleHandlers(table.name)) {\n if (!h.beforeUpdate) continue\n const result = await h.beforeUpdate(ctx, current, currentPatch)\n if (result != null) currentPatch = result as Partial<T>\n }\n\n return currentPatch\n }\n\n async runBeforeDelete<T>(table: TableDef<T>, ctx: unknown, current: T): Promise<void> {\n for (const h of table.hooks) {\n if (h.beforeDelete) await h.beforeDelete(current)\n }\n for (const h of this._moduleHandlers(table.name)) {\n if (h.beforeDelete) await h.beforeDelete(ctx, current)\n }\n }\n\n // ── After operations — side effects only, cannot cancel ──\n // queue: per-request RequestEventQueue, or undefined when called outside HTTP context.\n // When undefined (e.g. background jobs, tests, Phase 2 direct usage), events are dropped.\n\n async runAfterInsert<T>(\n table: TableDef<T>,\n ctx: unknown,\n result: T,\n input: Partial<T>,\n queue?: RequestEventQueue,\n ): Promise<void> {\n for (const h of table.hooks) {\n if (h.afterInsert) await h.afterInsert(result, input)\n }\n for (const h of this._moduleHandlers(table.name)) {\n if (h.afterInsert) await h.afterInsert(ctx, result, input)\n }\n // Collect event into request queue — flushed after onResponse, never immediately\n if (table.events.afterInsert) {\n queue?.collect(table.events.afterInsert, result)\n }\n }\n\n async runAfterUpdate<T>(\n table: TableDef<T>,\n ctx: unknown,\n result: T,\n before: T,\n queue?: RequestEventQueue,\n ): Promise<void> {\n for (const h of table.hooks) {\n if (h.afterUpdate) await h.afterUpdate(result, before)\n }\n for (const h of this._moduleHandlers(table.name)) {\n if (h.afterUpdate) await h.afterUpdate(ctx, result, before)\n }\n // Collect event into request queue — flushed after onResponse, never immediately\n if (table.events.afterUpdate) {\n queue?.collect(table.events.afterUpdate, { before, after: result })\n }\n }\n\n async runAfterDelete<T>(\n table: TableDef<T>,\n ctx: unknown,\n deleted: T,\n queue?: RequestEventQueue,\n ): Promise<void> {\n for (const h of table.hooks) {\n if (h.afterDelete) await h.afterDelete(deleted)\n }\n for (const h of this._moduleHandlers(table.name)) {\n if (h.afterDelete) await h.afterDelete(ctx, deleted)\n }\n // Collect event into request queue — flushed after onResponse, never immediately\n if (table.events.afterDelete) {\n queue?.collect(table.events.afterDelete, deleted)\n }\n }\n\n private _moduleHandlers(tableName: string): ModuleHookHandlers<any, any>[] {\n return this.registry.get(tableName) ?? []\n }\n}\n","import { readdir, readFile } from 'node:fs/promises'\nimport { join } from 'node:path'\nimport type { VelnAdapter } from '../../adapter/types'\nimport type { MigrationResult, MigrationStatus, MigratorOptions } from './types'\nimport { ensureTable, getApplied, markApplied, markRolledBack } from './tracker'\n\ninterface MigrationFile {\n name: string\n sql: string\n}\n\nasync function readMigrationFiles(dir: string): Promise<MigrationFile[]> {\n let entries: string[]\n try {\n entries = await readdir(dir)\n } catch {\n return []\n }\n\n const sqlFiles = entries\n .filter(f => f.endsWith('.sql'))\n .sort() // alphabetical — relies on numeric prefix convention\n\n const files: MigrationFile[] = []\n for (const filename of sqlFiles) {\n const sql = await readFile(join(dir, filename), 'utf8')\n files.push({ name: filename, sql })\n }\n return files\n}\n\nexport function splitSqlStatements(sql: string): string[] {\n const statements: string[] = []\n let current = ''\n let inString = false\n let stringChar = ''\n let i = 0\n\n while (i < sql.length) {\n const ch = sql[i]\n\n // Handle single-line comments\n if (!inString && ch === '-' && sql[i + 1] === '-') {\n const newline = sql.indexOf('\\n', i)\n if (newline === -1) {\n current += sql.slice(i)\n i = sql.length\n } else {\n current += sql.slice(i, newline + 1)\n i = newline + 1\n }\n continue\n }\n\n // Handle block comments\n if (!inString && ch === '/' && sql[i + 1] === '*') {\n const end = sql.indexOf('*/', i + 2)\n if (end === -1) {\n current += sql.slice(i)\n i = sql.length\n } else {\n current += sql.slice(i, end + 2)\n i = end + 2\n }\n continue\n }\n\n // Handle string literals\n if (!inString && (ch === \"'\" || ch === '\"')) {\n inString = true\n stringChar = ch\n current += ch\n i++\n continue\n }\n\n if (inString) {\n if (ch === stringChar) {\n // Check for escaped quote (doubled)\n if (sql[i + 1] === stringChar) {\n current += ch + ch\n i += 2\n continue\n }\n inString = false\n stringChar = ''\n }\n current += ch\n i++\n continue\n }\n\n if (ch === ';') {\n const trimmed = current.trim()\n if (trimmed) statements.push(trimmed)\n current = ''\n i++\n continue\n }\n\n current += ch\n i++\n }\n\n const trimmed = current.trim()\n if (trimmed) statements.push(trimmed)\n\n return statements\n}\n\nexport async function run(adapter: VelnAdapter, opts: MigratorOptions): Promise<MigrationResult[]> {\n const tableName = opts.tableName ?? '_veln_migrations'\n\n await ensureTable(adapter, tableName)\n\n const files = await readMigrationFiles(opts.migrationsDir)\n const applied = await getApplied(adapter, tableName)\n const appliedNames = new Set(applied.map(r => r.name))\n\n const pending = files.filter(f => !appliedNames.has(f.name))\n\n const results: MigrationResult[] = []\n for (const migration of pending) {\n const t0 = performance.now()\n try {\n await opts.onBeforeMigrate?.({ name: migration.name, sql: migration.sql })\n const statements = splitSqlStatements(migration.sql)\n for (const stmt of statements) {\n if (stmt.trim()) await adapter.execute(stmt, [])\n }\n await markApplied(adapter, tableName, migration.name)\n const durationMs = performance.now() - t0\n await opts.onAfterMigrate?.({ name: migration.name, sql: migration.sql, durationMs })\n results.push({ name: migration.name, success: true, duration: Math.round(durationMs) })\n } catch (err) {\n const error = err instanceof Error ? err : new Error(String(err))\n await opts.onError?.({ name: migration.name, error })\n results.push({ name: migration.name, success: false, duration: Math.round(performance.now() - t0), error })\n break\n }\n }\n return results\n}\n\nexport async function status(adapter: VelnAdapter, opts: MigratorOptions): Promise<MigrationStatus[]> {\n const tableName = opts.tableName ?? '_veln_migrations'\n\n await ensureTable(adapter, tableName)\n\n const files = await readMigrationFiles(opts.migrationsDir)\n const applied = await getApplied(adapter, tableName)\n const appliedMap = new Map(applied.map(r => [r.name, r]))\n\n return files.map(f => {\n const record = appliedMap.get(f.name)\n if (record) {\n return { name: f.name, status: 'applied' as const, appliedAt: record.appliedAt }\n }\n return { name: f.name, status: 'pending' as const }\n })\n}\n\nexport async function rollback(adapter: VelnAdapter, opts: MigratorOptions): Promise<void> {\n const tableName = opts.tableName ?? '_veln_migrations'\n\n await ensureTable(adapter, tableName)\n\n const applied = await getApplied(adapter, tableName)\n if (applied.length === 0) return\n\n const last = applied[applied.length - 1]\n await markRolledBack(adapter, tableName, last.name)\n}\n","import type { VelnAdapter } from '../../adapter/types'\nimport type { MigrationRecord } from './types'\n\nconst CREATE_TRACKING_TABLE = `\n CREATE TABLE IF NOT EXISTS \"_veln_migrations\" (\n \"id\" INTEGER PRIMARY KEY AUTOINCREMENT,\n \"name\" TEXT NOT NULL UNIQUE,\n \"applied_at\" TEXT NOT NULL\n )\n`\n\nexport async function ensureTable(adapter: VelnAdapter, tableName: string): Promise<void> {\n const sql = CREATE_TRACKING_TABLE.replace('\"_veln_migrations\"', `\"${tableName}\"`)\n await adapter.execute(sql)\n}\n\nexport async function getApplied(adapter: VelnAdapter, tableName: string): Promise<MigrationRecord[]> {\n const rows = await adapter.query<{ id: number; name: string; applied_at: string }>(\n `SELECT \"id\", \"name\", \"applied_at\" FROM \"${tableName}\" ORDER BY \"id\" ASC`,\n )\n return rows.map(r => ({\n id: r.id,\n name: r.name,\n appliedAt: new Date(r.applied_at),\n }))\n}\n\nexport async function markApplied(adapter: VelnAdapter, tableName: string, name: string): Promise<void> {\n await adapter.execute(\n `INSERT INTO \"${tableName}\" (\"name\", \"applied_at\") VALUES (?, ?)`,\n [name, new Date().toISOString()],\n )\n}\n\nexport async function markRolledBack(adapter: VelnAdapter, tableName: string, name: string): Promise<void> {\n await adapter.execute(\n `DELETE FROM \"${tableName}\" WHERE \"name\" = ?`,\n [name],\n )\n}\n","import type { VelnAdapter } from '../../adapter/types'\nimport type { AdapterConfig } from '../../adapter/resolve'\nimport { resolveAdapter } from '../../adapter/resolve'\nimport type { MigrationResult, MigrationStatus, MigratorOptions } from './types'\nimport { run, status, rollback } from './runner'\n\nexport interface Migrator {\n run(): Promise<MigrationResult[]>\n status(): Promise<MigrationStatus[]>\n rollback(): Promise<void>\n}\n\nexport function createMigrator(adapterOrConfig: AdapterConfig | VelnAdapter, options: MigratorOptions): Migrator {\n const adapter = resolveAdapter(adapterOrConfig)\n return {\n run: () => run(adapter, options),\n status: () => status(adapter, options),\n rollback: () => rollback(adapter, options),\n }\n}\n","import { readdir, writeFile } from 'node:fs/promises'\nimport { join } from 'node:path'\nimport type { VelnAdapter } from '../../adapter/types'\nimport type { TableDef } from '../../schema/table'\nimport type { SchemaMap } from '../../schema/table'\nimport type { SchemaDiff, ColumnDef } from './types'\nimport { introspectSchema } from './introspect'\nimport { compareSchemas } from './diff'\n\nexport interface GenerateOptions {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n tables: TableDef<any, SchemaMap>[]\n adapter: VelnAdapter\n migrationsDir: string\n name?: string\n /**\n * When true, generates executable SQL for column drops and type changes\n * instead of commented-out warnings.\n *\n * @remarks\n * ⚠️ DESTRUCTIVE: Generates SQL that permanently drops columns or changes types.\n * Always review generated migrations before applying in production.\n * Back up your database before running destructive migrations.\n */\n allowDestructive?: boolean\n}\n\nexport interface GenerateResult {\n filename: string\n sql: string\n isEmpty: boolean\n}\n\nasync function nextMigrationNumber(dir: string): Promise<number> {\n let entries: string[]\n try {\n entries = await readdir(dir)\n } catch {\n return 1\n }\n\n const nums = entries\n .filter(f => f.endsWith('.sql'))\n .map(f => {\n const match = /^(\\d+)/.exec(f)\n return match ? parseInt(match[1], 10) : 0\n })\n\n return nums.length === 0 ? 1 : Math.max(...nums) + 1\n}\n\nfunction formatNumber(n: number): string {\n return String(n).padStart(4, '0')\n}\n\nfunction columnToSql(col: ColumnDef): string {\n let def = `\"${col.name}\" ${col.type}`\n if (col.primaryKey) def += ' PRIMARY KEY'\n if (!col.nullable && !col.primaryKey) def += ' NOT NULL'\n if (col.unique) def += ' UNIQUE'\n if (col.default !== undefined) def += ` DEFAULT ${col.default}`\n return def\n}\n\nfunction generateSql(diff: SchemaDiff, allowDestructive = false): string {\n const lines: string[] = []\n\n // Added tables → CREATE TABLE IF NOT EXISTS\n for (const table of diff.addedTables) {\n const cols = table.columns.map(columnToSql)\n lines.push(`CREATE TABLE IF NOT EXISTS \"${table.name}\" (`)\n lines.push(cols.map((c, i) => ` ${c}${i < cols.length - 1 ? ',' : ''}`).join('\\n'))\n lines.push(');')\n lines.push('')\n\n for (const idx of table.indexes) {\n const unique = idx.unique ? 'UNIQUE ' : ''\n const cols = idx.columns.map(c => `\"${c}\"`).join(', ')\n lines.push(`CREATE ${unique}INDEX IF NOT EXISTS \"${idx.name}\" ON \"${table.name}\" (${cols});`)\n lines.push('')\n }\n }\n\n // Dropped tables\n for (const name of diff.droppedTables) {\n if (allowDestructive) {\n lines.push(`DROP TABLE IF EXISTS \"${name}\";`)\n } else {\n lines.push(`-- WARNING: DROP TABLE \"${name}\" -- uncomment to apply`)\n }\n lines.push('')\n }\n\n // Modified tables\n for (const mod of diff.modifiedTables) {\n for (const col of mod.addedColumns) {\n const colSql = columnToSql(col)\n lines.push(`ALTER TABLE \"${mod.name}\" ADD COLUMN ${colSql};`)\n lines.push('')\n }\n\n for (const name of mod.droppedColumns) {\n if (allowDestructive) {\n lines.push(`ALTER TABLE \"${mod.name}\" DROP COLUMN \"${name}\";`)\n } else {\n lines.push(`-- WARNING: ALTER TABLE \"${mod.name}\" DROP COLUMN \"${name}\" -- uncomment to apply`)\n }\n lines.push('')\n }\n\n for (const change of mod.modifiedColumns) {\n if (allowDestructive) {\n lines.push(`ALTER TABLE \"${mod.name}\" ALTER COLUMN \"${change.name}\" TYPE ${change.after.type};`)\n } else {\n lines.push(`-- WARNING: column type change for \"${mod.name}\".\"${change.name}\" requires manual migration`)\n lines.push(`-- before: ${change.before.type}`)\n lines.push(`-- after: ${change.after.type}`)\n }\n lines.push('')\n }\n\n for (const idx of mod.addedIndexes) {\n const unique = idx.unique ? 'UNIQUE ' : ''\n const cols = idx.columns.map(c => `\"${c}\"`).join(', ')\n lines.push(`CREATE ${unique}INDEX IF NOT EXISTS \"${idx.name}\" ON \"${mod.name}\" (${cols});`)\n lines.push('')\n }\n\n for (const name of mod.droppedIndexes) {\n lines.push(`DROP INDEX IF EXISTS \"${name}\";`)\n lines.push('')\n }\n }\n\n return lines.join('\\n').trimEnd()\n}\n\nexport async function generateMigration(options: GenerateOptions): Promise<GenerateResult> {\n const current = await introspectSchema(options.adapter)\n const diff = compareSchemas(current, options.tables)\n\n const isEmpty =\n diff.addedTables.length === 0 &&\n diff.droppedTables.length === 0 &&\n diff.modifiedTables.length === 0\n\n const sql = isEmpty ? '' : generateSql(diff, options.allowDestructive ?? false)\n\n const num = await nextMigrationNumber(options.migrationsDir)\n const suffix = options.name ?? new Date().toISOString().replace(/[-T:.Z]/g, '').slice(0, 15)\n const filename = `${formatNumber(num)}_${suffix}.sql`\n\n if (!isEmpty) {\n await writeFile(join(options.migrationsDir, filename), sql + '\\n', 'utf8')\n }\n\n return { filename, sql, isEmpty }\n}\n","import type { VelnAdapter } from '../../adapter/types'\nimport type { TableDiff, ColumnDef, IndexDef } from './types'\n\n// Internal table names to ignore during introspection\nconst IGNORED_TABLES = new Set([\n '_veln_migrations',\n 'sqlite_sequence',\n 'sqlite_stat1',\n 'sqlite_master',\n])\n\ninterface PragmaTableInfo {\n cid: number\n name: string\n type: string\n notnull: number\n dflt_value: string | null\n pk: number\n}\n\ninterface PragmaIndexList {\n seq: number\n name: string\n unique: number\n origin: string\n partial: number\n}\n\ninterface PragmaIndexInfo {\n seqno: number\n cid: number\n name: string\n}\n\ninterface InformationSchemaColumn {\n column_name: string\n data_type: string\n is_nullable: string\n column_default: string | null\n ordinal_position: number\n}\n\ninterface InformationSchemaConstraint {\n column_name: string\n constraint_type: string\n constraint_name: string\n}\n\ninterface MySQLColumn {\n COLUMN_NAME: string\n DATA_TYPE: string\n IS_NULLABLE: string\n COLUMN_DEFAULT: string | null\n COLUMN_KEY: string\n EXTRA: string\n}\n\ninterface MySQLIndex {\n INDEX_NAME: string\n COLUMN_NAME: string\n NON_UNIQUE: number\n}\n\nasync function introspectSQLite(adapter: VelnAdapter): Promise<Map<string, TableDiff>> {\n const tables = await adapter.query<{ name: string }>(\n `SELECT name FROM sqlite_master WHERE type='table' ORDER BY name`,\n )\n\n const result = new Map<string, TableDiff>()\n\n for (const { name } of tables) {\n if (IGNORED_TABLES.has(name)) continue\n\n const columns = await adapter.query<PragmaTableInfo>(`PRAGMA table_info(\"${name}\")`)\n const indexList = await adapter.query<PragmaIndexList>(`PRAGMA index_list(\"${name}\")`)\n\n const columnDefs: ColumnDef[] = columns.map(col => ({\n name: col.name,\n type: col.type.toUpperCase(),\n nullable: col.notnull === 0 && col.pk === 0,\n default: col.dflt_value ?? undefined,\n primaryKey: col.pk > 0,\n unique: false, // determined from indexes\n }))\n\n const indexes: IndexDef[] = []\n for (const idx of indexList) {\n // Skip auto-created indexes for PRIMARY KEY and UNIQUE constraints on columns\n if (idx.origin === 'pk') continue\n\n const idxInfo = await adapter.query<PragmaIndexInfo>(`PRAGMA index_info(\"${idx.name}\")`)\n const idxCols = idxInfo.sort((a, b) => a.seqno - b.seqno).map(i => i.name)\n\n // Mark column as unique if single-column unique index\n if (idx.unique && idxCols.length === 1) {\n const col = columnDefs.find(c => c.name === idxCols[0])\n if (col) col.unique = true\n }\n\n indexes.push({\n name: idx.name,\n columns: idxCols,\n unique: idx.unique === 1,\n })\n }\n\n result.set(name, { name, columns: columnDefs, indexes })\n }\n\n return result\n}\n\nasync function introspectPostgres(adapter: VelnAdapter, tableName?: string): Promise<Map<string, TableDiff>> {\n const tableFilter = tableName ? `AND t.table_name = '${tableName}'` : ''\n\n const columns = await adapter.query<InformationSchemaColumn>(`\n SELECT\n c.column_name,\n c.data_type,\n c.is_nullable,\n c.column_default,\n c.ordinal_position\n FROM information_schema.columns c\n JOIN information_schema.tables t\n ON t.table_name = c.table_name AND t.table_schema = c.table_schema\n WHERE t.table_schema = 'public'\n AND t.table_type = 'BASE TABLE'\n ${tableFilter}\n ORDER BY c.table_name, c.ordinal_position\n `)\n\n const constraints = await adapter.query<InformationSchemaConstraint & { table_name: string }>(`\n SELECT\n kcu.column_name,\n tc.constraint_type,\n tc.constraint_name,\n kcu.table_name\n FROM information_schema.table_constraints tc\n JOIN information_schema.key_column_usage kcu\n ON tc.constraint_name = kcu.constraint_name AND tc.table_schema = kcu.table_schema\n WHERE tc.table_schema = 'public'\n AND tc.constraint_type IN ('PRIMARY KEY', 'UNIQUE')\n `)\n\n const pkMap = new Map<string, Set<string>>()\n const uniqueMap = new Map<string, Set<string>>()\n for (const c of constraints) {\n const tbl = c.table_name\n if (c.constraint_type === 'PRIMARY KEY') {\n if (!pkMap.has(tbl)) pkMap.set(tbl, new Set())\n pkMap.get(tbl)!.add(c.column_name)\n } else if (c.constraint_type === 'UNIQUE') {\n if (!uniqueMap.has(tbl)) uniqueMap.set(tbl, new Set())\n uniqueMap.get(tbl)!.add(c.column_name)\n }\n }\n\n const tableMap = new Map<string, TableDiff>()\n for (const col of columns) {\n // Extract table name from the query — we need to join differently\n // We'll re-query with table_name included\n break\n }\n\n // Re-query with table_name\n const fullColumns = await adapter.query<InformationSchemaColumn & { table_name: string }>(`\n SELECT\n c.table_name,\n c.column_name,\n c.data_type,\n c.is_nullable,\n c.column_default,\n c.ordinal_position\n FROM information_schema.columns c\n JOIN information_schema.tables t\n ON t.table_name = c.table_name AND t.table_schema = c.table_schema\n WHERE t.table_schema = 'public'\n AND t.table_type = 'BASE TABLE'\n ${tableFilter}\n ORDER BY c.table_name, c.ordinal_position\n `)\n\n for (const col of fullColumns) {\n const tbl = col.table_name\n if (IGNORED_TABLES.has(tbl)) continue\n\n if (!tableMap.has(tbl)) tableMap.set(tbl, { name: tbl, columns: [], indexes: [] })\n\n const tableDiff = tableMap.get(tbl)!\n tableDiff.columns.push({\n name: col.column_name,\n type: col.data_type.toUpperCase(),\n nullable: col.is_nullable === 'YES',\n default: col.column_default ?? undefined,\n primaryKey: pkMap.get(tbl)?.has(col.column_name) ?? false,\n unique: uniqueMap.get(tbl)?.has(col.column_name) ?? false,\n })\n }\n\n return tableMap\n}\n\nasync function introspectMySQL(adapter: VelnAdapter): Promise<Map<string, TableDiff>> {\n const dbRow = await adapter.query<{ database: string }>(`SELECT DATABASE() AS \\`database\\``)\n const dbName = dbRow[0]?.database ?? ''\n\n const columns = await adapter.query<MySQLColumn & { TABLE_NAME: string }>(`\n SELECT\n TABLE_NAME,\n COLUMN_NAME,\n DATA_TYPE,\n IS_NULLABLE,\n COLUMN_DEFAULT,\n COLUMN_KEY,\n EXTRA\n FROM information_schema.COLUMNS\n WHERE TABLE_SCHEMA = '${dbName}'\n ORDER BY TABLE_NAME, ORDINAL_POSITION\n `)\n\n const indexes = await adapter.query<MySQLIndex & { TABLE_NAME: string }>(`\n SELECT\n TABLE_NAME,\n INDEX_NAME,\n COLUMN_NAME,\n NON_UNIQUE\n FROM information_schema.STATISTICS\n WHERE TABLE_SCHEMA = '${dbName}'\n ORDER BY TABLE_NAME, INDEX_NAME, SEQ_IN_INDEX\n `)\n\n const tableMap = new Map<string, TableDiff>()\n\n for (const col of columns) {\n const tbl = col.TABLE_NAME\n if (IGNORED_TABLES.has(tbl)) continue\n\n if (!tableMap.has(tbl)) tableMap.set(tbl, { name: tbl, columns: [], indexes: [] })\n\n tableMap.get(tbl)!.columns.push({\n name: col.COLUMN_NAME,\n type: col.DATA_TYPE.toUpperCase(),\n nullable: col.IS_NULLABLE === 'YES',\n default: col.COLUMN_DEFAULT ?? undefined,\n primaryKey: col.COLUMN_KEY === 'PRI',\n unique: col.COLUMN_KEY === 'UNI',\n })\n }\n\n // Group index rows into IndexDef entries\n const indexBuffer = new Map<string, { tableName: string; name: string; columns: string[]; unique: boolean }>()\n for (const idx of indexes) {\n const key = `${idx.TABLE_NAME}.${idx.INDEX_NAME}`\n if (!indexBuffer.has(key)) {\n indexBuffer.set(key, {\n tableName: idx.TABLE_NAME,\n name: idx.INDEX_NAME,\n columns: [],\n unique: idx.NON_UNIQUE === 0,\n })\n }\n indexBuffer.get(key)!.columns.push(idx.COLUMN_NAME)\n }\n\n for (const entry of indexBuffer.values()) {\n const tbl = tableMap.get(entry.tableName)\n if (!tbl) continue\n if (entry.name === 'PRIMARY') continue // already captured via primaryKey flag\n tbl.indexes.push({ name: entry.name, columns: entry.columns, unique: entry.unique })\n }\n\n return tableMap\n}\n\n/**\n * Detect adapter type and introspect the current DB schema.\n * Returns a map of table name → TableDiff.\n */\nexport async function introspectSchema(adapter: VelnAdapter): Promise<Map<string, TableDiff>> {\n // Probe: if sqlite_master exists → SQLite\n try {\n await adapter.query(`SELECT 1 FROM sqlite_master LIMIT 1`)\n return introspectSQLite(adapter)\n } catch {\n // Not SQLite — try Postgres\n }\n\n try {\n await adapter.query(`SELECT current_database()`)\n return introspectPostgres(adapter)\n } catch {\n // Not Postgres — try MySQL\n }\n\n return introspectMySQL(adapter)\n}\n","import type { TableDef as TableDefSchema } from '../../schema/table'\nimport type { Column } from '../../schema/column'\nimport type { SchemaMap } from '../../schema/table'\nimport type {\n SchemaDiff,\n TableDiff,\n TableModification,\n ColumnDef,\n IndexDef,\n ColumnModification,\n} from './types'\n\nfunction tableDefToColumnDefs(schema: SchemaMap): ColumnDef[] {\n return Object.entries(schema).map(([name, col]) => {\n const c = col as Column<unknown>\n\n // Map SqlType → generic SQL type string\n let type: string\n switch (c.def.type) {\n case 'INTEGER': type = 'INTEGER'; break\n case 'TEXT':\n case 'UUID': type = 'TEXT'; break\n case 'REAL': type = 'REAL'; break\n case 'BOOLEAN': type = 'INTEGER'; break // SQLite stores as INTEGER\n case 'TIMESTAMP': type = 'TEXT'; break // ISO string\n case 'JSON': type = 'TEXT'; break\n case 'BLOB': type = 'BLOB'; break\n default: type = 'TEXT'; break\n }\n\n return {\n name,\n type,\n nullable: c.def.nullable,\n default: c.def.defaultValue !== undefined ? String(c.def.defaultValue) : undefined,\n primaryKey: c.def.primaryKey,\n unique: c.def.unique,\n }\n })\n}\n\nfunction columnsEqual(a: ColumnDef, b: ColumnDef): boolean {\n return (\n a.type === b.type &&\n a.nullable === b.nullable &&\n a.primaryKey === b.primaryKey &&\n a.unique === b.unique &&\n (a.default ?? null) === (b.default ?? null)\n )\n}\n\nexport function compareSchemas(\n current: Map<string, TableDiff>,\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n target: TableDefSchema<any, SchemaMap>[],\n): SchemaDiff {\n const addedTables: TableDiff[] = []\n const droppedTables: string[] = []\n const modifiedTables: TableModification[] = []\n\n const targetNames = new Set(target.map(t => t.name))\n\n // Dropped tables: in current but not in target\n for (const [name] of current) {\n if (!targetNames.has(name)) {\n droppedTables.push(name)\n }\n }\n\n for (const table of target) {\n const currentTable = current.get(table.name)\n const targetColumns = tableDefToColumnDefs(table.schema)\n\n if (!currentTable) {\n // New table\n addedTables.push({\n name: table.name,\n columns: targetColumns,\n indexes: [], // TODO: index extraction from schema when supported\n })\n continue\n }\n\n // Compare columns\n const currentColMap = new Map(currentTable.columns.map(c => [c.name, c]))\n const targetColMap = new Map(targetColumns.map(c => [c.name, c]))\n\n const addedColumns: ColumnDef[] = []\n const droppedColumns: string[] = []\n const modifiedColumns: ColumnModification[] = []\n const addedIndexes: IndexDef[] = []\n const droppedIndexes: string[] = []\n\n for (const [name, col] of targetColMap) {\n const existing = currentColMap.get(name)\n if (!existing) {\n addedColumns.push(col)\n } else if (!columnsEqual(existing, col)) {\n modifiedColumns.push({ name, before: existing, after: col })\n }\n }\n\n for (const [name] of currentColMap) {\n if (!targetColMap.has(name)) {\n droppedColumns.push(name)\n }\n }\n\n const hasChanges =\n addedColumns.length > 0 ||\n droppedColumns.length > 0 ||\n modifiedColumns.length > 0 ||\n addedIndexes.length > 0 ||\n droppedIndexes.length > 0\n\n if (hasChanges) {\n modifiedTables.push({\n name: table.name,\n addedColumns,\n droppedColumns,\n modifiedColumns,\n addedIndexes,\n droppedIndexes,\n })\n }\n }\n\n return { addedTables, droppedTables, modifiedTables }\n}\n","import type { VelnEvents } from './index'\nimport type { Logger, BaseOptions } from '../app/types'\nimport type { ServiceDef } from '../service/index'\nimport { createMinimalLogger } from '../app/logger'\n\nexport type EventCallback = (payload: unknown) => void | Promise<void>\nexport type EventHandlerFn<TPayload, TServices extends Record<string, unknown> = Record<never, never>> = (\n payload: TPayload,\n ctx: { logger: Logger } & TServices,\n) => void | Promise<void>\n\n// RawHandler — (payload, ctx) called by app.events() when services are present.\n// ctx is assembled by the caller (logger + instantiated services).\nexport type RawHandler = (payload: unknown, ctx: Record<string, unknown>) => void | Promise<void>\n\nexport interface EventHandlerDef {\n readonly _handlers: Map<string, EventCallback>\n readonly _rawHandlers: Map<string, RawHandler>\n readonly _logger: Logger\n readonly _services: ReadonlyArray<ServiceDef<string, unknown>>\n}\n\n// Structural constraint — matches any TableDef regardless of its generic params\ntype TableLike = { name: string; _eventMap: Record<string, unknown> }\n\n// Infer handler map type from a table's _eventMap\ntype EventHandlerMap<TTable extends TableLike> = Partial<{\n [K in keyof TTable['_eventMap']]: (payload: TTable['_eventMap'][K]) => void | Promise<void>\n}>\n\n// Internal type for stored handlers (payload + ctx)\ntype StoredHandler<TServices extends Record<string, unknown>> = (\n payload: unknown,\n ctx: { logger: Logger } & TServices,\n) => void | Promise<void>\n\n// ── EventHandlerBuilder ───────────────────────────────────────────────────────\n\nexport class EventHandlerBuilder<\n TTable extends TableLike,\n TServices extends Record<string, unknown> = Record<never, never>,\n> {\n private _options: BaseOptions = {}\n private _handlerMap: Map<string, StoredHandler<Record<string, unknown>>> = new Map()\n private _services: ServiceDef<string, unknown>[] = []\n\n constructor(private readonly _table: TTable) {}\n\n options(opts: BaseOptions): this {\n this._options = opts\n return this\n }\n\n use<TKey extends string, TDef>(\n service: ServiceDef<TKey, TDef>,\n ): EventHandlerBuilder<TTable, TServices & Record<TKey, TDef>> {\n const next = new EventHandlerBuilder<TTable, TServices & Record<TKey, TDef>>(this._table)\n next._options = this._options\n next._handlerMap = this._handlerMap\n next._services = [...this._services, service as ServiceDef<string, unknown>]\n return next\n }\n\n on<TEvent extends string & keyof TTable['_eventMap']>(\n event: TEvent,\n handler: (\n payload: TTable['_eventMap'][TEvent],\n ctx: { logger: Logger } & TServices,\n ) => void | Promise<void>,\n ): this {\n this._handlerMap.set(event, handler as StoredHandler<Record<string, unknown>>)\n return this\n }\n\n // Fluent path — wraps all .on() handlers with logger + service injection\n build(): EventHandlerDef\n // Legacy path — builds EventHandlerDef from a plain handler map (no logger injection)\n build(handlers: EventHandlerMap<TTable>): EventHandlerDef\n build(handlers?: EventHandlerMap<TTable>): EventHandlerDef {\n const logger = createMinimalLogger(`event:${this._table.name}`, this._options.log)\n const services = this._services\n\n if (handlers !== undefined) {\n const map = new Map<string, EventCallback>()\n for (const [key, fn] of Object.entries(handlers)) {\n if (fn) map.set(key, fn as EventCallback)\n }\n return {\n _handlers: map,\n _rawHandlers: new Map(),\n _logger: logger,\n _services: [],\n }\n }\n\n // Logger-only fallback in _handlers (used when no services declared).\n // Raw handlers in _rawHandlers (used by app.events() when services are present).\n const wrapped = new Map<string, EventCallback>()\n const rawHandlers = new Map<string, RawHandler>()\n for (const [event, handler] of this._handlerMap) {\n wrapped.set(event, (payload) =>\n handler(payload, { logger } as { logger: Logger } & Record<string, unknown>),\n )\n rawHandlers.set(event, handler as RawHandler)\n }\n return {\n _handlers: wrapped,\n _rawHandlers: rawHandlers,\n _logger: logger,\n _services: services,\n }\n }\n}\n\n// ── defineEventHandler ────────────────────────────────────────────────────────\n\n// Overload 1 — legacy table-bound (two args) → EventHandlerDef directly\nexport function defineEventHandler<TTable extends TableLike>(\n table: TTable,\n handlers: EventHandlerMap<TTable>,\n): EventHandlerDef\n\n// Overload 2 — fluent builder (one table arg) → EventHandlerBuilder\nexport function defineEventHandler<TTable extends TableLike>(\n table: TTable,\n): EventHandlerBuilder<TTable>\n\n// Overload 3 — free (plain string keys, VelnEvents) → EventHandlerDef\nexport function defineEventHandler(\n handlers: Partial<{ [K in keyof VelnEvents]: (payload: VelnEvents[K]) => void | Promise<void> }>,\n): EventHandlerDef\n\nexport function defineEventHandler<TTable extends TableLike>(\n tableOrHandlers: TTable | Partial<Record<string, EventCallback>>,\n maybeHandlers?: EventHandlerMap<TTable>,\n): EventHandlerBuilder<TTable> | EventHandlerDef {\n // Two args → legacy table-bound overload\n if (maybeHandlers !== undefined) {\n return new EventHandlerBuilder(tableOrHandlers as TTable).build(maybeHandlers)\n }\n\n // One arg with `_eventMap` → TableLike → fluent builder\n if ('_eventMap' in tableOrHandlers) {\n return new EventHandlerBuilder(tableOrHandlers as TTable)\n }\n\n // One arg without `_eventMap` → plain handler map → free overload\n const raw = tableOrHandlers as Partial<Record<string, EventCallback>>\n const map = new Map<string, EventCallback>()\n for (const [key, fn] of Object.entries(raw)) {\n if (fn) map.set(key, fn)\n }\n return { _handlers: map, _rawHandlers: new Map(), _logger: createMinimalLogger('event'), _services: [] }\n}\n","import type { BoundVelnDB } from '../db/index'\nimport type { TableDef, SchemaMap } from '../schema/table'\nimport type { Logger, BaseOptions } from '../app/types'\nimport { createMinimalLogger } from '../app/logger'\n\n// ModelInstance — the user's factory result merged with { db: BoundVelnDB }.\n// .db gives direct raw access: UserModel.db.into(usersTable).insert(...)\nexport type ModelInstance<TDef> = TDef & { readonly db: BoundVelnDB }\n\n// ModelDef — carries the name (= dep key) + factory.\n// Never holds a db reference — instantiated per-request via .use().\nexport interface ModelDef<TName extends string, TDef> {\n readonly _modelName: TName\n readonly _factory: (db: BoundVelnDB) => ModelInstance<TDef>\n}\n\n// ── ModelBuilder ──────────────────────────────────────────────────────────────\n\nexport class ModelBuilder<TName extends string, TTable> {\n private _opts: BaseOptions = {}\n\n constructor(\n private readonly _name: TName,\n private readonly _table: TTable,\n ) {}\n\n options(opts: BaseOptions): this {\n this._opts = opts\n return this\n }\n\n define<TDef extends object>(\n factory: (db: BoundVelnDB, ctx: { logger: Logger }) => TDef,\n ): ModelDef<TName, TDef> {\n const name = this._name\n const opts = this._opts\n return {\n _modelName: name,\n _factory: (db: BoundVelnDB): ModelInstance<TDef> => {\n const logger = createMinimalLogger(`model:${name}`, opts.log)\n return { ...factory(db, { logger }), db }\n },\n }\n }\n}\n\n// ── defineModel — entry point ─────────────────────────────────────────────────\n//\n// Two call forms:\n// Builder (new): defineModel(name, table)\n// .options({ log: { level: 'debug' } })\n// .define((db, { logger }) => ({ ... }))\n//\n// Direct (compat): defineModel(name, table, (db) => ({ ... }))\n// The 3-arg form is kept for existing code. Extra { logger } arg\n// is injected but callers that ignore it continue to work.\n\nexport function defineModel<\n TName extends string,\n TTable,\n>(\n name: TName,\n table: TTable,\n): ModelBuilder<TName, TTable>\n\nexport function defineModel<\n TName extends string,\n TTable,\n TDef extends object,\n>(\n name: TName,\n table: TTable,\n factory: (db: BoundVelnDB, ctx: { logger: Logger }) => TDef,\n): ModelDef<TName, TDef>\n\nexport function defineModel<\n TName extends string,\n TTable,\n TDef extends object,\n>(\n name: TName,\n table: TTable,\n factory?: (db: BoundVelnDB, ctx: { logger: Logger }) => TDef,\n): ModelBuilder<TName, TTable> | ModelDef<TName, TDef> {\n if (factory !== undefined) {\n // Direct (compat) form — wrap in builder immediately\n return new ModelBuilder<TName, TTable>(name, table).define(factory)\n }\n return new ModelBuilder<TName, TTable>(name, table)\n}\n","import type { BoundVelnDB } from '../db/index'\nimport type { ModelDef, ModelInstance } from '../model/index'\nimport type { BaseOptions } from '../app/types'\nimport { createMinimalLogger } from '../app/logger'\n\n// ── Dep union — accepted by ServiceBuilder.use() ──────────────────────────\n\n// A dependency is a ModelDef or ServiceDef.\nexport type Dep<TKey extends string, TDef> =\n | ModelDef<TKey, TDef>\n | ServiceDef<TKey, TDef>\n\n// Helper — extract the key from any Dep kind\ntype DepKey<D> = D extends ModelDef<infer K, unknown> ? K\n : D extends ServiceDef<infer K, unknown> ? K\n : never\n\n// Helper — extract the instance type from any Dep kind\ntype DepInst<D> = D extends ModelDef<string, infer T> ? ModelInstance<T>\n : D extends ServiceDef<string, infer T> ? T\n : never\n\n// ── ServiceDef ─────────────────────────────────────────────────────────────\n\nexport interface ServiceDef<TKey extends string, TDef> {\n readonly _serviceKey: TKey\n readonly _deps: ReadonlyArray<Dep<string, unknown>>\n readonly _options: BaseOptions\n readonly _factory: (deps: Record<string, unknown>) => TDef\n}\n\n// ── ServiceBuilder ─────────────────────────────────────────────────────────\n\nexport class ServiceBuilder<TKey extends string, TDeps extends Record<string, unknown>> {\n private constructor(\n private readonly _key: TKey,\n private readonly _deps: ReadonlyArray<Dep<string, unknown>>,\n private readonly _opts: BaseOptions,\n ) {}\n\n static create<TKey extends string>(key: TKey): ServiceBuilder<TKey, Record<never, never>> {\n return new ServiceBuilder<TKey, Record<never, never>>(key, [], {})\n }\n\n use<TDep extends Dep<string, unknown>>(\n dep: TDep,\n ): ServiceBuilder<TKey, TDeps & Record<DepKey<TDep>, DepInst<TDep>>> {\n return new ServiceBuilder<TKey, TDeps & Record<DepKey<TDep>, DepInst<TDep>>>(\n this._key,\n [...this._deps, dep as Dep<string, unknown>],\n this._opts,\n )\n }\n\n options(opts: BaseOptions): ServiceBuilder<TKey, TDeps> {\n return new ServiceBuilder<TKey, TDeps>(\n this._key,\n this._deps,\n opts,\n )\n }\n\n define<TDef>(\n factory: (deps: TDeps & Record<'logger', import('../app/types').Logger>) => TDef,\n ): ServiceDef<TKey, TDef> {\n return {\n _serviceKey: this._key,\n _deps: this._deps,\n _options: this._opts,\n _factory: factory as (deps: Record<string, unknown>) => TDef,\n }\n }\n}\n\nexport function defineService<TKey extends string>(\n key: TKey,\n): ServiceBuilder<TKey, Record<never, never>> {\n return ServiceBuilder.create(key)\n}\n\n// ── Per-request instantiation helpers ────────────────────────────────────\n// Used by the framework in fetch() — not exported from core public API.\n\n// isModelDef — runtime discriminator\nfunction isModelDef(dep: Dep<string, unknown>): dep is ModelDef<string, unknown> {\n return '_modelName' in dep\n}\n\n// isServiceDef — runtime discriminator\nfunction isServiceDef(dep: Dep<string, unknown>): dep is ServiceDef<string, unknown> {\n return '_serviceKey' in dep\n}\n\n// detectCircular — throws if any cycle exists in the dep graph.\n// Called once at startup (first fetch). O(V+E).\nexport function detectCircular(services: ReadonlyArray<ServiceDef<string, unknown>>): void {\n // Build a name → ServiceDef map transitively — includes nested service deps,\n // not just the top-level services passed in.\n const byKey = new Map<string, ServiceDef<string, unknown>>()\n\n function collectAll(svc: ServiceDef<string, unknown>): void {\n if (byKey.has(svc._serviceKey)) return\n byKey.set(svc._serviceKey, svc)\n for (const dep of svc._deps) {\n if (isServiceDef(dep)) {\n collectAll(dep)\n }\n }\n }\n\n for (const svc of services) {\n collectAll(svc)\n }\n\n // DFS with three-color marking: 0=unvisited, 1=in-stack, 2=done\n const state = new Map<string, 0 | 1 | 2>()\n\n function visit(key: string, stack: string[]): void {\n const s = state.get(key) ?? 0\n if (s === 2) return\n if (s === 1) {\n const cycle = [...stack, key].join(' → ')\n throw new Error(`[veln] Circular dependency detected: ${cycle}`)\n }\n state.set(key, 1)\n const svc = byKey.get(key)\n if (svc) {\n for (const dep of svc._deps) {\n if (isServiceDef(dep)) {\n visit(dep._serviceKey, [...stack, key])\n }\n }\n }\n state.set(key, 2)\n }\n\n for (const svc of byKey.values()) {\n visit(svc._serviceKey, [])\n }\n}\n\n// instantiateServices — per-request.\n// Builds all declared services (and their transitive model/service deps) with the given db.\n// Returns a Record<key, instance> to be merged into ctx.\nexport function instantiateServices(\n services: ReadonlyArray<ServiceDef<string, unknown>>,\n db: BoundVelnDB,\n): Record<string, unknown> {\n // Cache within this request — each dep key instantiated at most once\n const cache = new Map<string, unknown>()\n\n function instantiateDep(dep: Dep<string, unknown>, ownerKey: string): unknown {\n if (isModelDef(dep)) {\n const key = dep._modelName\n if (cache.has(key)) return cache.get(key)\n const inst = dep._factory(db)\n cache.set(key, inst)\n return inst\n }\n if (isServiceDef(dep)) {\n const key = dep._serviceKey\n if (cache.has(key)) return cache.get(key)\n const resolvedDeps: Record<string, unknown> = {}\n // Always inject logger for the service being instantiated\n const logger = createMinimalLogger(`service:${key}`, dep._options?.log)\n resolvedDeps['logger'] = logger\n for (const d of dep._deps) {\n const depKey = isModelDef(d) ? d._modelName : d._serviceKey\n resolvedDeps[depKey] = instantiateDep(d, key)\n }\n const inst = dep._factory(resolvedDeps)\n cache.set(key, inst)\n return inst\n }\n throw new Error(`[veln] Unknown dependency type in service '${ownerKey}'`)\n }\n\n const result: Record<string, unknown> = {}\n for (const svc of services) {\n result[svc._serviceKey] = instantiateDep(svc, svc._serviceKey)\n }\n return result\n}\n","import type { Logger, BaseOptions, OnRequestFn, OnResponseFn } from './types'\nimport { createMinimalLogger } from './logger'\n\n// ── MiddlewareDef — sealed result of MiddlewareBuilder.build() ────────────────\n\nexport interface MiddlewareDef {\n readonly _name: string\n readonly _onRequest?: OnRequestFn\n readonly _onResponse?: OnResponseFn\n readonly _logger: Logger\n}\n\n// ── MiddlewareBuilder ─────────────────────────────────────────────────────────\n\nexport class MiddlewareBuilder {\n private _options: BaseOptions = {}\n private _onRequestFn?: OnRequestFn\n private _onResponseFn?: OnResponseFn\n\n constructor(private readonly _name: string) {}\n\n options(opts: BaseOptions): this {\n this._options = opts\n return this\n }\n\n onRequest(fn: OnRequestFn): this {\n this._onRequestFn = fn\n return this\n }\n\n onResponse(fn: OnResponseFn): this {\n this._onResponseFn = fn\n return this\n }\n\n build(): MiddlewareDef {\n const logger = createMinimalLogger(`middleware:${this._name}`, this._options.log)\n return {\n _name: this._name,\n _onRequest: this._onRequestFn,\n _onResponse: this._onResponseFn,\n _logger: logger,\n }\n }\n}\n\n// ── defineMiddleware — entry point ────────────────────────────────────────────\n\nexport function defineMiddleware(name: string): MiddlewareBuilder {\n return new MiddlewareBuilder(name)\n}\n","import type { BaseCtx, Guard, ErrorHandler, RouteHandler, Route, RouteSchema, RouteHandlerWithSchema, InferCtx, RouteMap, OnRequestHook, OnBeforeHandleHook, OnResponseHook, RouteDocs, StreamController, StreamOptions, SseController, VelnWsAdapter, WsRouteShape, AuthAdapter } from './types'\nimport type { NavItem } from './plugin'\nimport { createMinimalLogger } from './logger'\nimport { generateOpenApiSpec } from '../openapi/generator'\nimport type { OpenApiSpec } from '../openapi/generator'\nimport type { ZodTypeAny } from 'zod'\nimport { ValidationError } from './types'\nimport { VelnError, UnauthorizedError, ForbiddenError } from '../errors/index'\nimport type { Plugin } from './plugin'\nimport type { VelnEvents, EventHandler } from '../events/index'\nimport type { EventHandlerDef } from '../events/handler'\nimport type { CronDef, CronLockAdapter } from '../cron/index'\nimport { NoOpCronLockAdapter } from '../cron/index'\nimport { createSystemCtx } from './system-ctx'\nimport { VelnDB } from '../db/index'\nimport type { VelnModule, ServiceDeclaration } from './module'\nimport type { InferTableEvents, TableEventMap, TableDef, SchemaMap } from '../schema/table'\nimport { InMemoryEventBus, RequestEventQueue } from '../events/index'\nimport type { EventBusAdapter } from '../events/index'\nimport { HookExecutor } from '../hooks/executor'\nimport { matchPath, parseQuery } from './router'\nimport { buildAuditHooks } from './audit-wiring'\nimport { createCookieJar } from './cookies'\nimport type { ServiceDef } from '../service/index'\nimport { detectCircular, instantiateServices } from '../service/index'\nimport type { MiddlewareDef } from './middleware'\nimport { createOnRequest, createOnResponse } from './types'\n\ntype HttpMethod = 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE'\n\n// ── ctx.stream() implementation ──────────────────────────────────────────────\n// Creates a ReadableStream from a writer callback.\n// The writer receives a StreamController and can push chunks then close.\nfunction makeStreamResponse(\n writer: (controller: StreamController) => void | Promise<void>,\n options: StreamOptions = {},\n): Response {\n const enc = new TextEncoder()\n const { readable, writable } = new TransformStream<Uint8Array, Uint8Array>()\n const w = writable.getWriter()\n\n const controller: StreamController = {\n send(chunk: string | Uint8Array) {\n const bytes = typeof chunk === 'string' ? enc.encode(chunk) : chunk\n void w.write(bytes)\n },\n close() {\n void w.close()\n },\n }\n\n // Run the writer async — errors close the stream; success path relies on\n // the caller invoking controller.close() explicitly.\n Promise.resolve(writer(controller)).catch(() => { void w.close() })\n\n const headers = new Headers(options.headers)\n headers.set('Content-Type', options.contentType ?? 'text/plain')\n\n return new Response(readable, {\n status: options.status ?? 200,\n headers,\n })\n}\n\n// ── ctx.sse() implementation ──────────────────────────────────────────────────\n// Thin wrapper over makeStreamResponse — enforces SSE headers and wire format.\n//\n// SSE wire format per https://html.spec.whatwg.org/multipage/server-sent-events.html:\n// event: <name>\\n\n// data: <json>\\n\\n\n//\n// data: <json>\\n\\n (unnamed)\n// : <comment>\\n\\n (keepalive)\n// id: <value>\\n\n// retry: <ms>\\n\nfunction makeSSEResponse(\n writer: (controller: SseController) => void | Promise<void>,\n): Response {\n const enc = new TextEncoder()\n const { readable, writable } = new TransformStream<Uint8Array, Uint8Array>()\n const w = writable.getWriter()\n\n function push(frame: string): Promise<void> {\n return w.write(enc.encode(frame))\n }\n\n const controller: SseController = {\n async event(name: string, data: unknown): Promise<void> {\n await push(`event: ${name}\\ndata: ${JSON.stringify(data)}\\n\\n`)\n },\n async data(data: unknown): Promise<void> {\n await push(`data: ${JSON.stringify(data)}\\n\\n`)\n },\n async comment(text = ''): Promise<void> {\n await push(`: ${text}\\n\\n`)\n },\n async id(eventId: string): Promise<void> {\n await push(`id: ${eventId}\\n`)\n },\n async retry(ms: number): Promise<void> {\n await push(`retry: ${ms}\\n`)\n },\n }\n\n // Run the writer — always close the stream when done (success or error).\n // The try/catch on close() guards against Bun throwing when the writer\n // is already in a closing state (e.g. backpressure abort during error path).\n Promise.resolve(writer(controller)).finally(() => { w.close().catch(() => {}) })\n\n return new Response(readable, {\n status: 200,\n headers: {\n 'Content-Type': 'text/event-stream',\n 'Cache-Control': 'no-cache',\n 'Connection': 'keep-alive',\n },\n })\n}\n\n// Bun's BunRequest type — extends Request with .params (populated by native SIMD router)\ntype BunRequest = import('bun').BunRequest<string>\n\n// Type union — function shorthand OR schema object\ntype HandlerArg<TCtx> =\n | ((ctx: TCtx) => Response | Promise<Response>)\n | RouteHandler<TCtx>\n | RouteHandlerWithSchema<TCtx, any>\n\nfunction normalizeHandler<TCtx>(\n handler: HandlerArg<TCtx>,\n): { handler: RouteHandler<TCtx>; schema: RouteSchema | undefined; docs: RouteDocs | undefined } {\n if (typeof handler === 'function') {\n return { handler: { handler: handler as any }, schema: undefined, docs: undefined }\n }\n // RouteHandlerWithSchema has params/query/body/response fields alongside handler\n if ('params' in handler || 'query' in handler || 'body' in handler || 'response' in handler || 'docs' in handler) {\n const h = handler as RouteHandlerWithSchema<TCtx, any>\n return {\n handler: { handler: h.handler as any },\n schema: {\n params: h.params,\n query: h.query,\n body: h.body,\n response: h.response,\n },\n docs: h.docs,\n }\n }\n // Plain RouteHandler { handler: fn }\n return { handler: handler as RouteHandler<TCtx>, schema: undefined, docs: undefined }\n}\n\nexport class Veln<TCtx extends BaseCtx, TRoutes extends RouteMap = Record<never, never>, TPrefixes extends string = never> {\n // Used for type-extraction only — never set or read at runtime\n declare readonly _routes: TRoutes\n declare readonly _prefixes: TPrefixes\n readonly routes: Route<any>[] = []\n private readonly plugins: Plugin<any, any>[] = []\n private readonly globalGuards: Guard<any>[] = []\n // ─── Lifecycle hook registries (strict phase order enforced in fetch()) ───\n private readonly _onRequestHooks: OnRequestHook<any>[] = []\n private readonly _onBeforeHandleHooks: OnBeforeHandleHook<any>[] = []\n private readonly _onResponseHooks: OnResponseHook<any>[] = []\n private globalOnError?: ErrorHandler<any>\n private readonly eventBus: EventBusAdapter\n // Exposed so users can pass it to dbPlugin — app.register() populates this executor\n readonly hooks: HookExecutor\n private installedPlugins = false\n // Tracks which module plugin names have already been installed\n private readonly installedModulePlugins = new Set<string>()\n // Audit declarations collected from register() — wired after plugins install\n private readonly _pendingAuditDeclarations: import('./module').AuditDeclaration<any, any, any>[] = []\n\n private _opts: {\n validateResponse: boolean\n exposeIssues: boolean\n db?: { log?: { enabled?: boolean; n1Threshold?: number; logQueries?: boolean } }\n } = { validateResponse: false, exposeIssues: false }\n // Global service declarations — registered via app.use()\n private readonly _globalServiceDeclarations: ServiceDeclaration<string, unknown>[] = []\n // Circular dep check happens once on first fetch\n private _serviceCircularChecked = false\n // Route-matching cache — keyed by \"METHOD:pathname\", stores match result or null (no match).\n // Only the fetch() fallback path populates this (Bun native routes bypass fetch() entirely).\n // FIFO eviction at _ROUTE_CACHE_MAX entries.\n private _routeCache = new Map<string, { route: Route<unknown>; params: Record<string, string | undefined> } | null>()\n private readonly _ROUTE_CACHE_MAX = 500\n // Cron job definitions — scheduled at listen()\n private readonly _cronDefs: CronDef<Record<string, unknown>>[] = []\n // Registry of running croner instances — populated by _scheduleCrons(), drained by close()\n private readonly _cronJobs: Map<string, import('croner').Cron> = new Map()\n // Lock adapter — prevents duplicate execution across multiple instances\n private readonly _cronLock: CronLockAdapter\n private readonly _onInternalError: (msg: string, err: unknown) => void\n // Optional WS adapter — registered via app.registerWsAdapter(). Null when @oakbun/ws is not used.\n private _wsAdapter: VelnWsAdapter | null = null\n // Optional auth adapter — set via createApp({ auth }). Null when auth is not configured.\n private _authAdapter: AuthAdapter | null = null\n\n constructor(opts: {\n auth?: AuthAdapter\n nav?: { path?: string }\n validation?: { exposeIssues?: boolean }\n eventBus?: EventBusAdapter\n cronLock?: CronLockAdapter\n db?: { log?: { enabled?: boolean; n1Threshold?: number; logQueries?: boolean } }\n onInternalError?: (msg: string, err: unknown) => void\n } = {}) {\n this._onInternalError = opts.onInternalError ?? ((msg, err) => console.error(msg, err))\n this.eventBus = opts.eventBus ?? new InMemoryEventBus()\n this._cronLock = opts.cronLock ?? new NoOpCronLockAdapter()\n this.hooks = new HookExecutor()\n this._authAdapter = opts.auth ?? null\n if (opts.validation?.exposeIssues !== undefined) {\n this._opts = { ...this._opts, exposeIssues: opts.validation.exposeIssues }\n }\n if (opts.db !== undefined) {\n this._opts = { ...this._opts, db: opts.db }\n }\n this._registerNavEndpoint(opts.nav?.path ?? '/nav')\n }\n\n // Register the built-in GET /nav endpoint.\n // Returns all plugin nav items filtered by the current user's permissions.\n // Always public — no user → empty array, no error.\n private _registerNavEndpoint(path: string): void {\n const pluginsRef = this.plugins\n const authAdapterRef = () => this._authAdapter\n this.routes.push({\n method: 'GET',\n path,\n visibility: 'hidden',\n guards: [],\n handler: {\n handler: (ctx: BaseCtx) => {\n const user = ((ctx as unknown as Record<string, unknown>)['user'] ?? null) as import('./types').AuthUser | null\n const nav: NavItem[] = []\n for (const plugin of pluginsRef) {\n if (!plugin.nav || plugin.nav.length === 0) continue\n // If the plugin has permissions, check whether the user has at least one.\n // Uses _authAdapter.hasPermission() — never reads user.permissions directly.\n if (plugin.permissions && plugin.permissions.length > 0) {\n if (user == null) continue // no user → skip permissioned plugin\n const adapter = authAdapterRef()\n const hasAny = adapter\n ? plugin.permissions.some((perm) => adapter.hasPermission(user, perm))\n : false\n if (!hasAny) continue\n }\n nav.push(...plugin.nav)\n }\n // Sort by order (ascending, default 0), then alphabetically by label\n nav.sort((a, b) => {\n const orderDiff = (a.order ?? 0) - (b.order ?? 0)\n return orderDiff !== 0 ? orderDiff : a.label.localeCompare(b.label)\n })\n return ctx.json({ nav })\n },\n },\n })\n }\n\n private _addRoute(\n method: HttpMethod,\n path: string,\n handler: HandlerArg<TCtx>,\n module?: VelnModule,\n ): this {\n const { handler: normalized, schema, docs } = normalizeHandler(handler)\n this.routes.push({\n method,\n path,\n handler: normalized,\n guards: [],\n schema,\n docs,\n _module: module,\n })\n return this\n }\n\n // HTTP method registration.\n // 3-arg overload with schema: accumulates into TRoutes for RPC client type extraction.\n // 2-arg overload: function shorthand, no schema inference needed, TRoutes unchanged.\n\n private _registerMethod(\n method: HttpMethod,\n path: string,\n schemaOrHandler: { body?: ZodTypeAny; params?: ZodTypeAny; query?: ZodTypeAny; response?: ZodTypeAny } | HandlerArg<TCtx>,\n handler?: (ctx: never) => Response | Promise<Response>,\n ): Veln<TCtx, RouteMap, TPrefixes> {\n return handler\n ? this._addRoute(method, path, { ...schemaOrHandler as RouteSchema, handler } as RouteHandlerWithSchema<TCtx, RouteSchema>)\n : this._addRoute(method, path, schemaOrHandler as HandlerArg<TCtx>)\n }\n\n get<\n TBody extends ZodTypeAny,\n TParams extends ZodTypeAny,\n TQuery extends ZodTypeAny,\n TResponse extends ZodTypeAny,\n TPath extends string\n >(\n path: TPath,\n schema: { body?: TBody; params?: TParams; query?: TQuery; response?: TResponse },\n handler: (ctx: TCtx & { body: import('zod').infer<TBody>; params: import('zod').infer<TParams>; query: import('zod').infer<TQuery> }) => Response | Promise<Response>,\n ): Veln<TCtx, TRoutes & Record<`GET ${TPath}`, { body: TBody; params: TParams; query: TQuery; response: TResponse }>>\n get(path: string, handler: HandlerArg<TCtx>): this\n get(path: string, schemaOrHandler: { body?: ZodTypeAny; params?: ZodTypeAny; query?: ZodTypeAny; response?: ZodTypeAny } | HandlerArg<TCtx>, handler?: (ctx: never) => Response | Promise<Response>): Veln<TCtx, RouteMap, TPrefixes> {\n return this._registerMethod('GET', path, schemaOrHandler, handler)\n }\n\n post<\n TBody extends ZodTypeAny,\n TParams extends ZodTypeAny,\n TQuery extends ZodTypeAny,\n TResponse extends ZodTypeAny,\n TPath extends string\n >(\n path: TPath,\n schema: { body?: TBody; params?: TParams; query?: TQuery; response?: TResponse },\n handler: (ctx: TCtx & { body: import('zod').infer<TBody>; params: import('zod').infer<TParams>; query: import('zod').infer<TQuery> }) => Response | Promise<Response>,\n ): Veln<TCtx, TRoutes & Record<`POST ${TPath}`, { body: TBody; params: TParams; query: TQuery; response: TResponse }>>\n post(path: string, handler: HandlerArg<TCtx>): this\n post(path: string, schemaOrHandler: { body?: ZodTypeAny; params?: ZodTypeAny; query?: ZodTypeAny; response?: ZodTypeAny } | HandlerArg<TCtx>, handler?: (ctx: never) => Response | Promise<Response>): Veln<TCtx, RouteMap, TPrefixes> {\n return this._registerMethod('POST', path, schemaOrHandler, handler)\n }\n\n put<\n TBody extends ZodTypeAny,\n TParams extends ZodTypeAny,\n TQuery extends ZodTypeAny,\n TResponse extends ZodTypeAny,\n TPath extends string\n >(\n path: TPath,\n schema: { body?: TBody; params?: TParams; query?: TQuery; response?: TResponse },\n handler: (ctx: TCtx & { body: import('zod').infer<TBody>; params: import('zod').infer<TParams>; query: import('zod').infer<TQuery> }) => Response | Promise<Response>,\n ): Veln<TCtx, TRoutes & Record<`PUT ${TPath}`, { body: TBody; params: TParams; query: TQuery; response: TResponse }>>\n put(path: string, handler: HandlerArg<TCtx>): this\n put(path: string, schemaOrHandler: { body?: ZodTypeAny; params?: ZodTypeAny; query?: ZodTypeAny; response?: ZodTypeAny } | HandlerArg<TCtx>, handler?: (ctx: never) => Response | Promise<Response>): Veln<TCtx, RouteMap, TPrefixes> {\n return this._registerMethod('PUT', path, schemaOrHandler, handler)\n }\n\n patch<\n TBody extends ZodTypeAny,\n TParams extends ZodTypeAny,\n TQuery extends ZodTypeAny,\n TResponse extends ZodTypeAny,\n TPath extends string\n >(\n path: TPath,\n schema: { body?: TBody; params?: TParams; query?: TQuery; response?: TResponse },\n handler: (ctx: TCtx & { body: import('zod').infer<TBody>; params: import('zod').infer<TParams>; query: import('zod').infer<TQuery> }) => Response | Promise<Response>,\n ): Veln<TCtx, TRoutes & Record<`PATCH ${TPath}`, { body: TBody; params: TParams; query: TQuery; response: TResponse }>>\n patch(path: string, handler: HandlerArg<TCtx>): this\n patch(path: string, schemaOrHandler: { body?: ZodTypeAny; params?: ZodTypeAny; query?: ZodTypeAny; response?: ZodTypeAny } | HandlerArg<TCtx>, handler?: (ctx: never) => Response | Promise<Response>): Veln<TCtx, RouteMap, TPrefixes> {\n return this._registerMethod('PATCH', path, schemaOrHandler, handler)\n }\n\n delete<\n TBody extends ZodTypeAny,\n TParams extends ZodTypeAny,\n TQuery extends ZodTypeAny,\n TResponse extends ZodTypeAny,\n TPath extends string\n >(\n path: TPath,\n schema: { body?: TBody; params?: TParams; query?: TQuery; response?: TResponse },\n handler: (ctx: TCtx & { body: import('zod').infer<TBody>; params: import('zod').infer<TParams>; query: import('zod').infer<TQuery> }) => Response | Promise<Response>,\n ): Veln<TCtx, TRoutes & Record<`DELETE ${TPath}`, { body: TBody; params: TParams; query: TQuery; response: TResponse }>>\n delete(path: string, handler: HandlerArg<TCtx>): this\n delete(path: string, schemaOrHandler: { body?: ZodTypeAny; params?: ZodTypeAny; query?: ZodTypeAny; response?: ZodTypeAny } | HandlerArg<TCtx>, handler?: (ctx: never) => Response | Promise<Response>): Veln<TCtx, RouteMap, TPrefixes> {\n return this._registerMethod('DELETE', path, schemaOrHandler, handler)\n }\n\n /**\n * registerWsAdapter() — connect @oakbun/ws to this app.\n *\n * Call this before registering WS routes:\n * import { createWsAdapter } from '@oakbun/ws'\n * app.registerWsAdapter(createWsAdapter())\n */\n registerWsAdapter(adapter: VelnWsAdapter): this {\n this._wsAdapter = adapter\n return this\n }\n\n /**\n * ws() — register a WebSocket route.\n * Requires app.registerWsAdapter(createWsAdapter()) first.\n *\n * Full typing (WsCtx, Zod schema support) is provided when @oakbun/ws is imported.\n * Full type safety (WsCtx, Zod schema support, typed ctx.data) is provided by @oakbun/ws.\n * This base accepts a loose WsRouteShape so Core stays free of @oakbun/ws types.\n */\n ws(path: string, route: WsRouteShape): this {\n if (!this._wsAdapter) {\n throw new VelnError(\n `app.ws('${path}') called but no WS adapter is registered. Call app.registerWsAdapter(createWsAdapter()) first.`,\n 500, 'NO_WS_ADAPTER',\n )\n }\n this._wsAdapter.registerRoute(path, { ...route, path, _module: null })\n return this\n }\n\n\n plugin<TAdd extends object>(p: Plugin<TCtx, TAdd>): Veln<TCtx & TAdd, TRoutes, TPrefixes> {\n // Validate declared dependencies — fail fast with a clear error rather than a\n // mysterious runtime crash when a required plugin's ctx additions are missing.\n if (p.requires && p.requires.length > 0) {\n const registered = new Set(this.plugins.map((r) => r.name))\n for (const dep of p.requires) {\n if (!registered.has(dep)) {\n throw new VelnError(\n `Plugin \"${p.name}\" requires plugin \"${dep}\" to be registered first. ` +\n `Call app.plugin(${dep}Plugin(...)) before app.plugin(${p.name}Plugin(...)).`,\n 500,\n 'PLUGIN_MISSING_DEP',\n )\n }\n }\n }\n this.plugins.push(p)\n if (p.modules) {\n for (const mod of p.modules) {\n this.register(mod)\n // Tag every route that belongs to this plugin so _runRoute can look up\n // its permissions without a separate Map.\n if (p.permissions && p.permissions.length > 0) {\n for (const route of this.routes) {\n if (route._module === mod && route._pluginName === undefined) {\n route._pluginName = p.name\n }\n }\n }\n }\n }\n return this as unknown as Veln<TCtx & TAdd, TRoutes, TPrefixes>\n }\n\n // ── .use() — global service or middleware registration ────────────────────\n // Service overload: ctx[service._serviceKey] available in every route handler.\n // Middleware overload: registers onRequest/onResponse hooks globally.\n use<TKey extends string, TDef>(\n service: ServiceDef<TKey, TDef>,\n ): Veln<TCtx & Record<TKey, TDef>, TRoutes, TPrefixes>\n use(middleware: MiddlewareDef): this\n use<TKey extends string, TDef>(\n serviceOrMiddleware: ServiceDef<TKey, TDef> | MiddlewareDef,\n ): Veln<TCtx & Record<TKey, TDef>, TRoutes, TPrefixes> | this {\n if ('_serviceKey' in serviceOrMiddleware) {\n this._globalServiceDeclarations.push({ service: serviceOrMiddleware as ServiceDef<string, unknown> })\n return this as unknown as Veln<TCtx & Record<TKey, TDef>, TRoutes, TPrefixes>\n }\n // MiddlewareDef\n const m = serviceOrMiddleware as MiddlewareDef\n if (m._onRequest) this._onRequestHooks.push(createOnRequest(m._onRequest))\n if (m._onResponse) this._onResponseHooks.push(createOnResponse(m._onResponse))\n return this\n }\n\n register<TModuleRoutes extends RouteMap, TModulePrefix extends string>(\n mod: VelnModule & { readonly _routes: TModuleRoutes; readonly _prefix: TModulePrefix },\n ): Veln<TCtx, TRoutes & TModuleRoutes, TPrefixes | TModulePrefix>\n register(module: VelnModule): this\n register(module: VelnModule): Veln<TCtx, TRoutes & RouteMap, TPrefixes | string> {\n // 1. Transfer hook declarations to internal HookExecutor\n for (const decl of module.hookDeclarations) {\n this.hooks.registerModuleHook(decl.table.name, decl.handlers)\n }\n\n // 2. Collect audit declarations — wired after plugins install (first fetch())\n for (const decl of module.auditDeclarations) {\n this._pendingAuditDeclarations.push(decl)\n }\n\n // 3. Mount routes with prefix\n for (const route of module.routes) {\n this.routes.push({\n ...route,\n path: module.prefix + route.path,\n _module: module,\n })\n }\n\n // 3b. Mount WS routes with prefix — delegate to wsAdapter if registered\n if (this._wsAdapter && module.wsRoutes.length > 0) {\n for (const wsRoute of module.wsRoutes) {\n const fullPath = module.prefix + wsRoute.path\n this._wsAdapter.registerRoute(fullPath, { ...wsRoute, path: fullPath, _module: module })\n }\n }\n\n // 4. Register event handler defs on the event bus\n for (const def of module.eventHandlerDefs) {\n this.events(def)\n }\n\n // 5. Collect cron defs — merge module service declarations into each cron's _services\n // so module-level .use(Service) is automatically available in the cron handler\n for (const cronDef of module.cronDefs) {\n // Merge module services that aren't already declared on the CronDef itself\n const existingKeys = new Set(cronDef._services.map((s) => s._serviceKey))\n const merged = [\n ...cronDef._services,\n ...module.serviceDeclarations\n .map((d) => d.service)\n .filter((s) => !existingKeys.has(s._serviceKey)),\n ]\n const mergedDef: CronDef<Record<string, unknown>> = {\n ...cronDef,\n _services: merged,\n use: cronDef.use.bind(cronDef),\n }\n this._cronDefs.push(mergedDef)\n }\n\n // Invalidate route cache — new routes may match previously-cached paths differently\n this._routeCache.clear()\n\n return this as unknown as Veln<TCtx, TRoutes & RouteMap, TPrefixes | string>\n }\n\n // Internal helper: collect all service declarations (global + from a given module)\n private _allServiceDecls(mod: VelnModule | null): ReadonlyArray<ServiceDeclaration<string, unknown>> {\n if (mod === null) return this._globalServiceDeclarations\n // Merge global + module, deduplicate by key (module overrides global)\n const seen = new Set<string>()\n const merged: ServiceDeclaration<string, unknown>[] = []\n for (const d of [...mod.serviceDeclarations, ...this._globalServiceDeclarations]) {\n if (!seen.has(d.service._serviceKey)) {\n seen.add(d.service._serviceKey)\n merged.push(d)\n }\n }\n return merged\n }\n\n // Typed overload for events declared via VelnEvents Declaration Merging\n on<K extends keyof VelnEvents>(\n event: K,\n handler: (payload: VelnEvents[K], ctx: unknown) => Promise<void> | void,\n ): this\n // String fallback\n on(event: string, handler: EventHandler): this\n on(event: string, handler: EventHandler): this {\n this.eventBus.on(event, (payload) => handler(payload, undefined))\n return this\n }\n\n // Typed Table-reference overload — uses InferTableEvents<T, TEvents> directly at the call site.\n // No Declaration Merging needed for Table-derived events.\n // Phase 4b RPC Client uses this signature to build AppType.\n //\n // TMap is inferred from table._eventMap — a concrete precomputed object type stored on\n // TableDef. K is constrained via Pick<TMap, K>[K] which forces TypeScript to infer K\n // as the literal type of the event string rather than the full keyof TMap union.\n onEvent<\n TMap extends Record<string, unknown>,\n K extends string & keyof TMap\n >(\n table: { _eventMap: TMap },\n event: K,\n handler: (payload: Pick<TMap, K>[K], ctx: unknown) => void | Promise<void>,\n ): this {\n this.eventBus.on(event as string, (payload) => (handler as EventHandler)(payload, undefined))\n return this\n }\n\n events(def: EventHandlerDef): this {\n const logger = def._logger\n const hasServices = def._services.length > 0\n\n if (hasServices) {\n // Service path — instantiate services per event fire using a system context\n for (const [event, rawHandler] of def._rawHandlers) {\n this.eventBus.on(event, async (payload) => {\n try {\n const adapter = this.hooks.getAdapter()\n const ctx: Record<string, unknown> = { logger }\n if (adapter) {\n const sysCtx = createSystemCtx({ role: 'event' })\n const velnDb = new VelnDB(adapter, this.hooks)\n const boundDb = velnDb.withCtx(sysCtx)\n const services = instantiateServices(def._services, boundDb)\n Object.assign(ctx, services)\n }\n await rawHandler(payload, ctx)\n } catch (err) {\n logger.error('handler error', { event, err })\n }\n })\n }\n } else {\n // Fast path — logger only, callbacks already wrapped in build()\n for (const [event, callback] of def._handlers) {\n this.eventBus.on(event, async (payload) => {\n try {\n await callback(payload)\n } catch (err) {\n logger.error('handler error', { event, err })\n }\n })\n }\n }\n return this\n }\n\n cron<TServices extends Record<string, unknown>>(def: CronDef<TServices>): this {\n this._cronDefs.push(def as CronDef<Record<string, unknown>>)\n return this\n }\n\n onError(handler: ErrorHandler<TCtx>): this {\n this.globalOnError = handler\n return this\n }\n\n // ─── Lifecycle hook registration ─────────────────────────────────────────\n // Registration order within a phase is preserved (FIFO).\n // Phase order is always: onRequest → plugins → guards → onBeforeHandle → handler → onResponse.\n\n onRequest(hook: OnRequestHook<TCtx>): this {\n this._onRequestHooks.push(hook as OnRequestHook<any>)\n return this\n }\n\n onBeforeHandle(hook: OnBeforeHandleHook<TCtx>): this {\n this._onBeforeHandleHooks.push(hook as OnBeforeHandleHook<any>)\n return this\n }\n\n onResponse(hook: OnResponseHook<TCtx>): this {\n this._onResponseHooks.push(hook as OnResponseHook<any>)\n return this\n }\n\n async fetch(req: Request, server?: import('bun').Server<unknown>): Promise<Response> {\n // ─────────────────────────────────────────────────────────────────────────\n // fetch() Lifecycle — strict phase order regardless of registration order:\n //\n // PHASE 1: onRequest — always runs, even on 404 / guard block / plugin error\n // receives BaseCtx (plugins not yet applied)\n // may return Response to short-circuit everything\n // PHASE 2: plugins — build full ctx (global + module-level)\n // PHASE 3: guards — global → module → route guards\n // block returns guard response (wrapped by onResponse)\n // PHASE 4: onBeforeHandle — runs only when all guards pass\n // may return Response to skip handler\n // PHASE 5: handler — route handler\n // PHASE 6: onResponse — always runs (even on handler/guard/plugin error)\n // receives final Response; may return replacement\n // ─────────────────────────────────────────────────────────────────────────\n\n // PHASE 1: Install plugins once (lazy, on first request)\n if (!this.installedPlugins) {\n this.installedPlugins = true\n for (const plugin of this.plugins) {\n if (plugin.install) {\n await plugin.install(this.hooks)\n }\n }\n\n // Wire pending audit declarations now that plugins are installed.\n // dbPlugin.install() called hooks.setAdapter() above — adapter is available.\n if (this._pendingAuditDeclarations.length > 0) {\n const adapter = this.hooks.getAdapter()\n if (!adapter) {\n throw new Error(\n '[veln] .audit() declarations found but no dbPlugin is registered. ' +\n 'Call app.plugin(dbPlugin(...)) before app.register().'\n )\n }\n for (const decl of this._pendingAuditDeclarations) {\n const handlers = buildAuditHooks(decl, adapter)\n this.hooks.registerModuleHook(decl.table.name, handlers)\n }\n this._pendingAuditDeclarations.length = 0\n }\n }\n\n // Parse URL — pathname + query\n const url = new URL(req.url)\n const pathname = url.pathname\n const method = req.method.toUpperCase() as HttpMethod\n\n // Create per-request event queue — collects all DB-generated events during this request.\n // Flushed after onResponse on success paths only.\n // Guard blocks, handler errors, and plugin errors discard the queue (no flush).\n const requestQueue = new RequestEventQueue()\n\n // Create per-request QueryLog when N+1 detection is enabled.\n // Zero-cost when disabled — no object allocation, no wrapper.\n const dbLogCfg = this._opts.db?.log\n const queryLog: import('../db/index').QueryLog | undefined = dbLogCfg?.enabled\n ? {\n queries: 0,\n totalMs: 0,\n entries: [],\n threshold: dbLogCfg.n1Threshold ?? 10,\n logQueries: dbLogCfg.logQueries ?? false,\n }\n : undefined\n\n // Build minimal base ctx for onRequest (plugins not yet applied)\n // _requestQueue is read by dbPlugin to bind the queue to BoundVelnDB.\n // _queryLog is read by dbPlugin to wire N+1 detection into BoundVelnDB.\n const baseCtx: BaseCtx = {\n req,\n params: {},\n query: parseQuery(url.search),\n json: <T>(data: T, status = 200) => Response.json(data, { status }),\n text: (data: string, status = 200) => new Response(data, { status, headers: { 'Content-Type': 'text/plain' } }),\n html: (data: string, status = 200) => new Response(data, { status, headers: { 'Content-Type': 'text/html' } }),\n stream: makeStreamResponse,\n sse: makeSSEResponse,\n cookie: createCookieJar(req),\n emit: (event, payload) => { requestQueue.collect(event as string, payload) },\n _requestQueue: requestQueue,\n _queryLog: queryLog,\n }\n\n // ── Auth: resolve user before onRequest ──────────────────────────────────\n // getUser() runs once per request — result is available in onRequest hooks,\n // plugins, guards, and handlers as ctx.user (AuthUser | null).\n // Written via Object.assign so BaseCtx doesn't need to declare user — avoids\n // type collision with jwtPlugin/betterAuthPlugin which set their own user shape.\n if (this._authAdapter) {\n let resolvedUser: import('./types').AuthUser | null = null\n try {\n resolvedUser = await this._authAdapter.getUser(baseCtx)\n } catch {\n resolvedUser = null\n }\n Object.assign(baseCtx, { user: resolvedUser })\n } else {\n Object.assign(baseCtx, { user: null })\n }\n\n // ── PHASE 1: onRequest — always runs ─────────────────────────────────────\n // Runs before route matching so ctx.params is empty here.\n // If a hook returns a Response, it is wrapped by onResponse (no module yet).\n for (const hook of this._onRequestHooks) {\n let earlyRes: Response | void\n try {\n earlyRes = await hook._fn(baseCtx)\n } catch {\n earlyRes = undefined\n }\n if (earlyRes instanceof Response) {\n return this._runOnResponse(baseCtx, earlyRes, null)\n }\n }\n\n // ── WS UPGRADE: delegate to @oakbun/ws adapter ─────────────────────────────\n // Only attempted when the upgrade header is present, a server is available,\n // and an adapter has been registered via app.registerWsAdapter().\n if (server && this._wsAdapter && req.headers.get('upgrade')?.toLowerCase() === 'websocket') {\n const installedRef = { value: this.installedPlugins }\n const upgradeResponse = await this._wsAdapter.handleUpgrade(\n req,\n server,\n baseCtx,\n this.plugins,\n installedRef,\n this.installedModulePlugins,\n )\n this.installedPlugins = installedRef.value\n if (upgradeResponse !== null) return upgradeResponse\n return undefined as unknown as Response // Bun: undefined after successful upgrade\n }\n\n // Match route — 405 if path matches but method doesn't, 404 if no path match\n // P3: Cache matchPath() results by \"METHOD:pathname\" — FIFO eviction at _ROUTE_CACHE_MAX.\n let matchedRoute: Route<any> | null = null\n let matchedParams: Record<string, string | undefined> = {}\n const allowedMethods = new Set<string>()\n\n const cacheKey = `${method}:${pathname}`\n const cached = this._routeCache.get(cacheKey)\n if (cached !== undefined) {\n // Cache hit — cached is either { route, params } or null (known 404/405)\n if (cached !== null) {\n matchedRoute = cached.route\n matchedParams = cached.params\n allowedMethods.add(cached.route.method)\n }\n } else {\n // Cache miss — scan all routes\n for (const route of this.routes) {\n const result = matchPath(route.path, pathname)\n if (result === null) continue\n allowedMethods.add(route.method)\n if (route.method === method) {\n matchedRoute = route\n matchedParams = result.params\n break\n }\n }\n // Populate cache — evict oldest entry if at capacity\n if (this._routeCache.size >= this._ROUTE_CACHE_MAX) {\n this._routeCache.delete(this._routeCache.keys().next().value!)\n }\n this._routeCache.set(cacheKey, matchedRoute ? { route: matchedRoute, params: matchedParams } : null)\n }\n\n if (matchedRoute === null) {\n if (allowedMethods.size > 0) {\n // Path exists but method not allowed\n const allow = [...allowedMethods].join(', ')\n return this._runOnResponse(\n baseCtx,\n new Response('Method Not Allowed', { status: 405, headers: { Allow: allow } }),\n null,\n )\n }\n return this._runOnResponse(baseCtx, new Response('Not Found', { status: 404 }), null)\n }\n\n // Filter out undefined optional params — ctx.params is Record<string, string>\n const definedParams: Record<string, string> = {}\n for (const [k, v] of Object.entries(matchedParams)) {\n if (v !== undefined) definedParams[k] = v\n }\n\n return this._runRoute(baseCtx, matchedRoute, definedParams, requestQueue)\n }\n\n /**\n * _runRoute — executes the full Veln pipeline for an already-matched route.\n *\n * Called from two places:\n * 1. fetch() — after matchPath() finds the route (used by createTestClient + fallback)\n * 2. Bun native routes — Bun's SIMD router pre-matched the route; params come from req.params\n *\n * baseCtx must already have req, query, cookie, emit set.\n * params is passed in as Record<string, string> (undefined optionals already filtered out).\n */\n private async _runRoute(\n baseCtx: BaseCtx,\n matchedRoute: Route<unknown>,\n params: Record<string, string>,\n requestQueue: RequestEventQueue,\n ): Promise<Response> {\n baseCtx.params = params\n\n const mod = matchedRoute._module ?? null\n\n // Phase 0 — Plugin permission gate\n const permResult = await this._runPermissionGate(baseCtx, matchedRoute, mod)\n if (permResult) return permResult\n\n // Phase 1 — Module onRequest hooks\n const onRequestResult = await this._runModuleOnRequest(baseCtx, matchedRoute, mod)\n if (onRequestResult) return onRequestResult\n\n // Phase 2a — Plugin context building\n const ctx = await this._runPlugins(baseCtx, matchedRoute, mod)\n if (ctx instanceof Response) return ctx\n\n // Phase 2b — Schema validation\n const validationResult = await this._runValidation(ctx, matchedRoute, mod)\n if (validationResult) return validationResult\n\n // Phase 2c — Service instantiation\n await this._runServices(ctx, mod)\n\n // Phase 3 — Guards (global + module + route)\n const guardResult = await this._runGuards(ctx, matchedRoute, mod)\n if (guardResult) return guardResult\n\n // Phase 4 — onBeforeHandle hooks\n const beforeHandleResult = await this._runBeforeHandle(ctx, matchedRoute, mod)\n if (beforeHandleResult) return beforeHandleResult\n\n // Phase 5 + 5.5 + 6 — Handler, response validation, onResponse\n return this._runHandler(baseCtx, ctx, matchedRoute, mod, requestQueue)\n }\n\n // ── Phase 0: Plugin permission gate ─────────────────────────────────────────\n // Runs immediately after route match — before onRequest hooks, before plugin\n // request() calls, before guards. Ensures no plugin side-effects occur for a\n // request that will be blocked anyway.\n //\n // Only applies to routes tagged with _pluginName (contributed via .modules()).\n // Uses AuthAdapter.hasPermission() — never reads ctx.user.permissions directly.\n private async _runPermissionGate(\n baseCtx: BaseCtx,\n matchedRoute: Route<unknown>,\n mod: VelnModule | null,\n ): Promise<Response | null> {\n if (matchedRoute._pluginName === undefined) return null\n\n const gateName = matchedRoute._pluginName\n const gatePlugin = this.plugins.find((p) => p.name === gateName)\n if (!gatePlugin?.permissions || gatePlugin.permissions.length === 0) return null\n\n // user was written via Object.assign — read it back through the record interface\n const user = (baseCtx as unknown as Record<string, unknown>)['user'] as import('./types').AuthUser | null | undefined\n if (user == null) {\n return this._runOnResponse(\n baseCtx,\n await this._handleError(new UnauthorizedError('Authentication required'), baseCtx, matchedRoute),\n mod,\n )\n }\n const adapter = this._authAdapter\n const hasAny = adapter\n ? gatePlugin.permissions.some((perm) => adapter.hasPermission(user, perm))\n : false\n if (!hasAny) {\n return this._runOnResponse(\n baseCtx,\n await this._handleError(new ForbiddenError('Insufficient permissions'), baseCtx, matchedRoute),\n mod,\n )\n }\n return null\n }\n\n // ── Phase 1: Module onRequest hooks ─────────────────────────────────────────\n // Runs after route match, still before plugins. Returns a Response if any hook\n // short-circuits, null otherwise.\n private async _runModuleOnRequest(\n baseCtx: BaseCtx,\n matchedRoute: Route<unknown>,\n mod: VelnModule | null,\n ): Promise<Response | null> {\n if (!mod) return null\n for (const hook of mod.onRequestHooks) {\n let earlyRes: Response | void\n try {\n earlyRes = await hook._fn(baseCtx)\n } catch {\n earlyRes = undefined\n }\n if (earlyRes instanceof Response) {\n return this._runOnResponse(baseCtx, earlyRes, mod)\n }\n }\n return null\n }\n\n // ── Phase 2a: Plugin context building ───────────────────────────────────────\n // Runs global plugins then module plugins (lazy install with Set guard).\n // Returns the enriched ctx, or a Response if a plugin throws.\n private async _runPlugins(\n baseCtx: BaseCtx,\n matchedRoute: Route<unknown>,\n mod: VelnModule | null,\n ): Promise<BaseCtx | Response> {\n let ctx: BaseCtx = baseCtx\n try {\n // P2 analysis: plugins run sequentially — later plugins may read context added by\n // earlier ones (e.g. authPlugin reads ctx.db set by dbPlugin). Promise.all is NOT\n // safe. Object.assign is applied after each plugin so ctx stays current.\n // Each Object.assign call is O(keys) and negligible — no further batching possible.\n for (const plugin of this.plugins) {\n Object.assign(ctx, await plugin.request(ctx))\n }\n\n if (mod) {\n for (const plugin of mod.plugins) {\n // Install module plugin exactly once — lazy, keyed by plugin name.\n //\n // Race-condition analysis (Spec 07):\n // Bun runs on a single-threaded Event Loop — no true parallelism within\n // one process. Concurrent requests interleave only at `await` points.\n // The check (.has) and the mark (.add) are both synchronous and happen\n // before the first `await plugin.install(this.hooks)`, so no other\n // request can observe the un-marked state after .has() returns false:\n //\n // Request A: .has() → false → .add() ← sync, no yield possible here\n // → await install() ← yield point\n // Request B: .has() → true → skip ← sees the mark, install skipped ✓\n //\n // This is the correct \"optimistic add before await\" pattern.\n if (plugin.install && !this.installedModulePlugins.has(plugin.name)) {\n this.installedModulePlugins.add(plugin.name)\n await plugin.install(this.hooks)\n }\n Object.assign(ctx, await plugin.request(ctx))\n }\n\n // Inject module logger if .options({ log }) was set and ctx.logger not already present\n if (mod.options?.log && !ctx.logger) {\n const seg = mod.prefix.split('/').filter(Boolean).pop() ?? 'root'\n ctx.logger = createMinimalLogger(`module:${seg}`, mod.options.log)\n }\n }\n } catch (err) {\n const errRes = await this._handleError(err, ctx, matchedRoute)\n return this._runOnResponse(ctx, errRes, mod)\n }\n return ctx\n }\n\n // ── Phase 2b: Schema validation ──────────────────────────────────────────────\n // Validates params, query, body against Zod schemas if defined.\n // Returns a Response on validation failure, null on success.\n private async _runValidation(\n ctx: BaseCtx,\n matchedRoute: Route<unknown>,\n mod: VelnModule | null,\n ): Promise<Response | null> {\n if (!matchedRoute.schema) return null\n const schema = matchedRoute.schema\n\n if (schema.params) {\n const result = schema.params.safeParse(ctx.params)\n if (!result.success) {\n const errRes = await this._handleError(new ValidationError(result.error), ctx, matchedRoute)\n return this._runOnResponse(ctx, errRes, mod)\n }\n ctx.params = result.data as Record<string, string>\n }\n\n if (schema.query) {\n const result = schema.query.safeParse(ctx.query)\n if (!result.success) {\n const errRes = await this._handleError(new ValidationError(result.error), ctx, matchedRoute)\n return this._runOnResponse(ctx, errRes, mod)\n }\n ctx.query = result.data as Record<string, string | string[]>\n }\n\n if (schema.body) {\n let raw: unknown = null\n try {\n raw = await ctx.req.json()\n } catch {\n // invalid JSON or no body\n }\n const result = schema.body.safeParse(raw)\n if (!result.success) {\n const errRes = await this._handleError(new ValidationError(result.error), ctx, matchedRoute)\n return this._runOnResponse(ctx, errRes, mod)\n }\n ctx.body = result.data\n }\n\n return null\n }\n\n // ── Phase 2c: Service instantiation ─────────────────────────────────────────\n // Instantiates declared services per-request and merges into ctx.\n // Runs after plugins (ctx.db is available) and before guards.\n private async _runServices(\n ctx: BaseCtx,\n mod: VelnModule | null,\n ): Promise<void> {\n const serviceDecls = this._allServiceDecls(mod)\n if (serviceDecls.length === 0) return\n\n // Circular dep check — once per app lifetime, not per-request\n if (!this._serviceCircularChecked) {\n this._serviceCircularChecked = true\n detectCircular(serviceDecls.map((d) => d.service))\n }\n\n if (!ctx.db) {\n throw new Error(\n '[veln] .use() service declarations found but ctx.db is not available. ' +\n 'Register dbPlugin() before declaring services.',\n )\n }\n const serviceInstances = instantiateServices(\n serviceDecls.map((d) => d.service),\n ctx.db,\n )\n for (const [key, inst] of Object.entries(serviceInstances)) {\n (ctx as unknown as Record<string, unknown>)[key] = inst\n }\n }\n\n // ── Phase 3: Guards (global + module + route) ────────────────────────────────\n // Runs all three guard tiers in order. Returns a Response if any guard blocks,\n // null if all pass.\n private async _runGuards(\n ctx: BaseCtx,\n matchedRoute: Route<unknown>,\n mod: VelnModule | null,\n ): Promise<Response | null> {\n // Global guards\n for (const guard of this.globalGuards) {\n let guardResult: Response | null\n try {\n guardResult = await guard(ctx)\n } catch (err) {\n const errRes = await this._handleError(err, ctx, matchedRoute)\n return this._runOnResponse(ctx, errRes, mod)\n }\n if (guardResult !== null) {\n return this._runOnResponse(ctx, guardResult, mod)\n }\n }\n\n // Module guards — skipped when route has guard: false (moduleGuardOptOut)\n if (mod && !matchedRoute.moduleGuardOptOut) {\n for (const guard of mod.guards) {\n let guardResult: Response | null\n try {\n guardResult = await guard(ctx)\n } catch (err) {\n const errRes = await this._handleError(err, ctx, matchedRoute)\n return this._runOnResponse(ctx, errRes, mod)\n }\n if (guardResult !== null) {\n return this._runOnResponse(ctx, guardResult, mod)\n }\n }\n }\n\n // Route guards\n for (const guard of matchedRoute.guards) {\n let guardResult: Response | null\n try {\n guardResult = await guard(ctx)\n } catch (err) {\n const errRes = await this._handleError(err, ctx, matchedRoute)\n return this._runOnResponse(ctx, errRes, mod)\n }\n if (guardResult !== null) {\n return this._runOnResponse(ctx, guardResult, mod)\n }\n }\n\n return null\n }\n\n // ── Phase 4: onBeforeHandle hooks ───────────────────────────────────────────\n // Runs app-level then module-level onBeforeHandle hooks. Only called after all\n // guards pass. Returns a Response if any hook short-circuits, null otherwise.\n private async _runBeforeHandle(\n ctx: BaseCtx,\n matchedRoute: Route<unknown>,\n mod: VelnModule | null,\n ): Promise<Response | null> {\n // App-level hooks\n for (const hook of this._onBeforeHandleHooks) {\n let earlyRes: Response | void\n try {\n earlyRes = await hook._fn(ctx)\n } catch (err) {\n const errRes = await this._handleError(err, ctx, matchedRoute)\n return this._runOnResponse(ctx, errRes, mod)\n }\n if (earlyRes instanceof Response) {\n return this._runOnResponse(ctx, earlyRes, mod)\n }\n }\n\n // Module-level onBeforeHandle hooks\n if (mod) {\n for (const hook of mod.onBeforeHandleHooks) {\n let earlyRes: Response | void\n try {\n earlyRes = await hook._fn(ctx)\n } catch (err) {\n const errRes = await this._handleError(err, ctx, matchedRoute)\n return this._runOnResponse(ctx, errRes, mod)\n }\n if (earlyRes instanceof Response) {\n return this._runOnResponse(ctx, earlyRes, mod)\n }\n }\n }\n\n return null\n }\n\n // ── Phase 5 + 5.5 + 6: Handler, response validation, onResponse ─────────────\n // Executes the route handler, optionally validates the response, then runs\n // onResponse hooks. On error, discards the request queue (no event flush).\n private async _runHandler(\n baseCtx: BaseCtx,\n ctx: BaseCtx,\n matchedRoute: Route<unknown>,\n mod: VelnModule | null,\n requestQueue: RequestEventQueue,\n ): Promise<Response> {\n // Phase 5 — handler\n let response: Response\n try {\n response = await matchedRoute.handler.handler(ctx)\n } catch (err) {\n const errRes = await this._handleError(err, ctx, matchedRoute)\n // Handler threw — discard the request queue (no event flush on error)\n return this._runOnResponse(baseCtx, errRes, mod, undefined)\n }\n\n // Phase 5.5 — response validation (when enabled)\n // P4: Only clone when the response is actually JSON with a body — avoids cloning\n // SSE streams, HTML responses, and 204 No Content responses unnecessarily.\n const shouldValidate = this._opts.validateResponse\n && matchedRoute.schema?.response != null\n && response.headers.get('content-type')?.includes('application/json') === true\n && response.status !== 204\n && response.body !== null\n if (shouldValidate) {\n try {\n const body: unknown = await response.clone().json()\n const result = matchedRoute.schema!.response!.safeParse(body)\n if (!result.success) {\n this._onInternalError('[veln] Response validation failed:', result.error.issues)\n const errRes = new Response('Internal Server Error', { status: 500 })\n return this._runOnResponse(baseCtx, errRes, mod, undefined)\n }\n } catch {\n // Unparseable JSON — skip validation\n }\n }\n\n // Phase 6 — onResponse (success path — pass requestQueue so events are flushed)\n return this._runOnResponse(baseCtx, response, mod, requestQueue)\n }\n\n // Internal: run all onResponse hooks (app-level + module-level for matched route)\n // Always called — even on error paths — so onResponse truly \"always runs\".\n // flushQueue: only set on the success path (handler ran without error).\n // After all onResponse hooks complete, the queue is flushed to the EventBus.\n private async _runOnResponse(ctx: BaseCtx, response: Response, module?: VelnModule | null, flushQueue?: RequestEventQueue): Promise<Response> {\n let current = response\n\n // App-level onResponse hooks\n for (const hook of this._onResponseHooks) {\n let result: Response | void = undefined\n try {\n result = await hook._fn(ctx, current)\n } catch {\n // onResponse errors are swallowed — never break the response\n }\n if (result instanceof Response) {\n current = result\n }\n }\n\n // Module-level onResponse hooks (if module is known)\n if (module) {\n for (const hook of module.onResponseHooks) {\n let result: Response | void = undefined\n try {\n result = await hook._fn(ctx, current)\n } catch {\n // swallow\n }\n if (result instanceof Response) {\n current = result\n }\n }\n }\n\n // N+1 detection — only when db.log.enabled is true and a QueryLog was created in fetch().\n // Zero-cost when disabled: ctx._queryLog is undefined, so no work is done.\n const queryLog = ctx._queryLog\n if (queryLog && queryLog.queries > queryLog.threshold) {\n const url = new URL(ctx.req.url)\n const method = ctx.req.method.toUpperCase()\n console.warn(\n `[db:n+1] ${queryLog.queries} queries in ${method} ${url.pathname} — threshold: ${queryLog.threshold}`,\n )\n if (queryLog.logQueries) {\n for (const entry of queryLog.entries) {\n console.warn(` ${entry.sql} (${entry.durationMs.toFixed(2)}ms)`)\n }\n }\n }\n\n // Flush request-level event queue — only on success path (flushQueue is undefined on errors).\n // This guarantees: events fire AFTER the response is finalized, never on rollback/error.\n if (flushQueue) {\n await flushQueue.flush(ctx, this.eventBus)\n }\n\n // Apply pending Set-Cookie headers from ctx.cookie\n const pendingCookies = ctx.cookie._pending()\n if (pendingCookies.length > 0) {\n const headers = new Headers(current.headers)\n for (const c of pendingCookies) {\n headers.append('Set-Cookie', c)\n }\n current = new Response(current.body, {\n status: current.status,\n statusText: current.statusText,\n headers,\n })\n }\n\n return current\n }\n\n private _handleError(err: unknown, ctx: any, route: Route<any>): Response | Promise<Response> {\n // Error cascade: route onError → module onError → global onError → built-in fallback\n if (route.onError) {\n try {\n return route.onError(err, ctx)\n } catch {\n // fall through\n }\n }\n\n if (route._module?.onError) {\n try {\n return route._module.onError(err, ctx)\n } catch {\n // fall through\n }\n }\n\n if (this.globalOnError) {\n try {\n return this.globalOnError(err, ctx)\n } catch {\n // fall through\n }\n }\n\n // Built-in fallback — structured error responses with machine-readable codes.\n // ValidationError first (subclass of VelnError) — includes issues array.\n // Issues are masked by default (exposeIssues: false) to prevent schema info leaks.\n // Set createApp({ validation: { exposeIssues: true } }) for full Zod details in development.\n if (err instanceof ValidationError) {\n const issues = this._opts.exposeIssues\n ? err.issues\n : err.issues.map((issue) => ({ path: issue.path, message: 'Invalid value' }))\n return Response.json(\n { error: 'Validation Error', code: err.code, message: err.message, issues },\n { status: 422 },\n )\n }\n\n if (err instanceof VelnError) {\n return Response.json(\n { error: err.name, code: err.code, message: err.message },\n { status: err.status },\n )\n }\n\n // Duck-type fallback: handle errors with status+code (e.g. @oakbun/jwt JwtBaseError)\n if (\n err instanceof Error &&\n typeof (err as any).status === 'number' &&\n typeof (err as any).code === 'string'\n ) {\n const e = err as Error & { status: number; code: string }\n return Response.json(\n { error: e.name, code: e.code, message: e.message },\n { status: e.status },\n )\n }\n\n return Response.json(\n { error: 'Internal Server Error', code: 'INTERNAL_ERROR', message: 'An unexpected error occurred' },\n { status: 500 },\n )\n }\n\n options(opts: { validateResponse?: boolean }): this {\n if (opts.validateResponse !== undefined) {\n this._opts = { ...this._opts, validateResponse: opts.validateResponse }\n }\n return this\n }\n\n async close(): Promise<void> {\n // Stop all cron jobs before tearing down plugins\n for (const job of this._cronJobs.values()) {\n job.stop()\n }\n this._cronJobs.clear()\n\n // Call teardown() in reverse registration order\n const reversed = [...this.plugins].reverse()\n for (const plugin of reversed) {\n if (plugin.teardown) {\n try {\n await plugin.teardown()\n } catch (err) {\n // Log but don't rethrow — other teardowns must still run\n this._onInternalError(`[veln] teardown failed for plugin \"${plugin.name}\":`, err)\n }\n }\n }\n }\n\n getOpenApiSpec(options?: { title?: string; version?: string }): OpenApiSpec {\n return generateOpenApiSpec(this.routes, options)\n }\n\n /**\n * getRoutes — returns all registered HTTP routes as a RouteInfo array.\n * Compatible with @oakbun/logger's printRouteTree().\n */\n getRoutes(): Array<{ method: string; path: string; module?: string; protected: boolean }> {\n return this.routes\n .filter(route => route.visibility !== 'hidden')\n .map(route => {\n const mod = route._module\n const moduleName = mod\n ? (mod.meta?.tag ?? mod.prefix.replace(/^\\//, '').split('/')[0])\n : undefined\n return {\n method: route.method,\n path: route.path,\n module: moduleName ?? undefined,\n protected: route.guards.length > 0,\n }\n })\n }\n\n /**\n * printRoutes — prints a simple route list to stdout.\n * For a pretty tree, use printRouteTree from @oakbun/logger.\n */\n printRoutes(options?: { title?: string; version?: string }): void {\n const title = options?.title ?? 'Veln'\n const version = options?.version ? ` ${options.version}` : ''\n console.log(`\\n ${title}${version}\\n`)\n for (const route of this.routes) {\n const guard = route.guards.length > 0 ? ' 🔒' : ''\n console.log(` ${route.method.padEnd(6)} ${route.path}${guard}`)\n }\n console.log()\n }\n\n /**\n * _buildBunRoutes — converts this.routes into Bun's native route object.\n *\n * Called once at listen() time. Bun's SIMD-accelerated router takes over path matching;\n * params are extracted natively and passed via BunRequest.params.\n *\n * Routes with optional params (:name?) are deliberately excluded — Bun does not support\n * the `?` suffix syntax. They are handled by the fetch() fallback via matchPath().\n *\n * The returned object is typed as Record<string, unknown> because the path keys are\n * dynamic strings, not statically known literals. Bun.serve() receives it via `as any`.\n */\n private _buildBunRoutes(): Record<string, unknown> {\n // Group routes by path — multiple HTTP methods can share the same path\n const byPath = new Map<string, Route<unknown>[]>()\n for (const route of this.routes) {\n // Skip routes with optional params — Bun router doesn't support :param? syntax.\n // These fall through to the fetch() fallback which uses matchPath().\n if (route.path.includes('?')) continue\n const existing = byPath.get(route.path)\n if (existing) {\n existing.push(route)\n } else {\n byPath.set(route.path, [route])\n }\n }\n\n const bunRoutes: Record<string, unknown> = {}\n for (const [path, routes] of byPath) {\n const methods: Record<string, (req: BunRequest, srv: import('bun').Server<unknown>) => Promise<Response>> = {}\n for (const route of routes) {\n const captured = route\n methods[captured.method] = async (req: BunRequest, srv: import('bun').Server<unknown>) => {\n // Lazy plugin install (same guard as fetch())\n if (!this.installedPlugins) {\n this.installedPlugins = true\n for (const plugin of this.plugins) {\n if (plugin.install) await plugin.install(this.hooks)\n }\n }\n\n const url = new URL(req.url)\n const requestQueue = new RequestEventQueue()\n\n const baseCtx: BaseCtx = {\n req,\n params: {},\n query: parseQuery(url.search),\n json: <T>(data: T, status = 200) => Response.json(data, { status }),\n text: (data: string, status = 200) => new Response(data, { status, headers: { 'Content-Type': 'text/plain' } }),\n html: (data: string, status = 200) => new Response(data, { status, headers: { 'Content-Type': 'text/html' } }),\n stream: makeStreamResponse,\n sse: makeSSEResponse,\n cookie: createCookieJar(req),\n emit: (event, payload) => { requestQueue.collect(event as string, payload) },\n _requestQueue: requestQueue,\n }\n\n // Run global onRequest hooks (before pipeline — same as fetch())\n for (const hook of this._onRequestHooks) {\n let earlyRes: Response | void\n try {\n earlyRes = await hook._fn(baseCtx)\n } catch {\n earlyRes = undefined\n }\n if (earlyRes instanceof Response) {\n return this._runOnResponse(baseCtx, earlyRes, null)\n }\n }\n\n // WS upgrade requests are handled by the fetch() fallback — skip here.\n // (Bun routes don't receive WS upgrade requests via the method handler.)\n\n // Params come from Bun's SIMD router — already extracted, always strings\n return this._runRoute(baseCtx, captured, req.params, requestQueue)\n }\n }\n bunRoutes[path] = methods\n }\n\n return bunRoutes\n }\n\n listen(\n port: number,\n cb?: (port: number) => void,\n options?: { autoHandleSignals?: boolean },\n ): ReturnType<typeof Bun.serve> {\n // Install plugins eagerly so cron handlers have access to the DB adapter\n if (!this.installedPlugins) {\n this.installedPlugins = true\n for (const plugin of this.plugins) {\n if (plugin.install) {\n const result = plugin.install(this.hooks)\n // If install returns a Promise, ignore it — sync plugins (dbPlugin) work fine here\n if (result && typeof (result as any).then === 'function') {\n (result as Promise<void>).catch((err) =>\n this._onInternalError('[veln] Plugin install error during listen():', err),\n )\n }\n }\n }\n }\n\n // Schedule all registered cron jobs before starting the server\n this._scheduleCrons()\n\n // Start Bun server — include websocket config from adapter if registered\n const server = Bun.serve({\n port,\n routes: this._buildBunRoutes(),\n fetch: (req: Request, srv: import('bun').Server<unknown>) => this.fetch(req, srv),\n ...(this._wsAdapter ? { websocket: this._wsAdapter.getWebsocketConfig() } : {}),\n } as any) // 'as any' needed because Bun types require websocket when upgrade is used\n cb?.(port)\n\n // Auto-register SIGTERM/SIGINT handlers to call app.close() on shutdown.\n // Default: true. Pass { autoHandleSignals: false } to disable.\n const autoHandle = options?.autoHandleSignals !== false\n if (autoHandle) {\n let shuttingDown = false\n const shutdown = async () => {\n if (shuttingDown) return\n shuttingDown = true\n await this.close()\n process.exit(0)\n }\n process.on('SIGTERM', shutdown)\n process.on('SIGINT', shutdown)\n }\n\n return server\n }\n\n // Internal: schedule all cron defs.\n // - mode:'process' (default) — croner runs handler in-process, has access to ctx.db\n // - mode:'os' — Bun.cron delegates to a separate script file (OS-level scheduling)\n // Called once at listen(). Safe to call multiple times (idempotent — _cronDefs not cleared).\n private _scheduleCrons(): void {\n const adapter = this.hooks.getAdapter()\n\n const processJobs = this._cronDefs.filter(d => d._mode !== 'os')\n if (!adapter && processJobs.length > 0) {\n console.warn('[veln] .cron() jobs registered but no dbPlugin found — ctx.db will be unavailable in handlers')\n }\n\n for (const def of this._cronDefs) {\n console.log(`[Cron] ${def._name} — registriert (${def._expression})${def._runOnStart ? ', runOnStart' : ''}`)\n\n if (def._mode === 'os') {\n // OS-level — Bun.cron(script, expression, name)\n ;(Bun as unknown as { cron: (script: string, expr: string, name: string) => void })\n .cron(def._script!, def._expression, def._name)\n continue\n }\n\n // In-process — croner\n // eslint-disable-next-line @typescript-eslint/no-require-imports\n const { Cron } = require('croner') as typeof import('croner')\n\n const cronLogger = def._logger\n\n const runJob = async () => {\n const ttlMs = def._ttlMs ?? 30_000\n const acquired = await this._cronLock.acquire(def._name, ttlMs)\n if (!acquired) return // another instance has the lock\n\n const start = Date.now()\n console.log(`[Cron] ${def._name} — running...`)\n try {\n const sysCtx = createSystemCtx({ role: 'cron' })\n const velnDb = adapter ? new VelnDB(adapter, this.hooks) : null\n const boundDb = velnDb ? velnDb.withCtx(sysCtx) : null as unknown as import('../db/index').BoundVelnDB\n\n const services = def._services.length > 0 && boundDb\n ? instantiateServices(def._services, boundDb)\n : {}\n\n await def._handler!({ db: boundDb, ...services }, cronLogger)\n console.log(`[Cron] ${def._name} — done (${Date.now() - start}ms)`)\n } catch (err) {\n if (def._onError) {\n def._onError(err)\n } else {\n console.error(`[Cron] ${def._name} — error:`, err)\n }\n } finally {\n await this._cronLock.release(def._name)\n }\n }\n\n const job = new Cron(\n def._expression,\n { name: def._name, timezone: def._timezone },\n runJob,\n )\n this._cronJobs.set(def._name, job)\n\n if (def._runOnStart) {\n runJob().catch((err) => {\n if (def._onError) {\n def._onError(err)\n } else {\n console.error(`[Cron] ${def._name} runOnStart error:`, err)\n }\n })\n }\n }\n }\n}\n\n/**\n * createApp — creates a new Veln application instance.\n *\n * @param opts.auth Authentication adapter (e.g. BetterAuth). Enables `ctx.user` and permission gates.\n * @param opts.validation Validation options. Set `exposeIssues: true` to include raw Zod issues in 422\n * responses (development only — masks issue details by default).\n * @param opts.eventBus Custom event bus adapter. Defaults to `InMemoryEventBus` (single-process).\n * For multi-instance deployments, supply a Redis or BroadcastChannel adapter.\n * @param opts.cronLock Distributed lock adapter for cron jobs. Defaults to `NoOpCronLockAdapter`\n * (always acquires). For multi-instance deployments, supply a Redis-backed adapter.\n * @param opts.nav Navigation endpoint options. `path` sets the `/nav` endpoint URL.\n * @param opts.db Database options. `db.log.enabled` enables query logging and N+1 detection.\n * `db.log.n1Threshold` sets the query count threshold (default: 10).\n * `db.log.logQueries` logs all SQL statements when N+1 is detected.\n *\n * @example\n * const app = createApp()\n * app.get('/ping', (ctx) => ctx.json({ ok: true }))\n * app.listen(3000)\n */\nexport function createApp(opts: {\n auth?: AuthAdapter\n nav?: { path?: string }\n validation?: { exposeIssues?: boolean }\n eventBus?: EventBusAdapter\n cronLock?: CronLockAdapter\n db?: { log?: { enabled?: boolean; n1Threshold?: number; logQueries?: boolean } }\n} = {}): Veln<BaseCtx, Record<never, never>, never> {\n return new Veln<BaseCtx, Record<never, never>, never>(opts)\n}\n","import type { ZodTypeAny } from 'zod'\n\nexport type JsonSchema = Record<string, unknown>\n\n// Zod v4 check internal structure\ninterface ZodCheckDef {\n check: string\n value?: number\n inclusive?: boolean\n minimum?: number\n maximum?: number\n format?: string\n}\n\ninterface ZodCheckInternal {\n def: ZodCheckDef\n}\n\ninterface ZodCheckWithInternal {\n _zod: ZodCheckInternal\n def?: ZodCheckDef\n}\n\n/** Extract description from any Zod schema — stored as `.description` on the instance. */\nfunction getDescription(schema: ZodTypeAny): string | undefined {\n return (schema as unknown as { description?: string }).description\n}\n\nexport function zodToJsonSchema(schema: ZodTypeAny): JsonSchema {\n const def = (schema._def as unknown) as Record<string, unknown>\n const typeName = def['type'] as string | undefined\n\n if (typeName === 'string') {\n return withDescription(schema, zodStringToSchema(def))\n }\n if (typeName === 'number') {\n return withDescription(schema, zodNumberToSchema(def))\n }\n if (typeName === 'boolean') {\n return withDescription(schema, { type: 'boolean' })\n }\n if (typeName === 'enum') {\n const entries = def['entries'] as Record<string, string> | undefined\n const values = entries ? Object.values(entries) : []\n return withDescription(schema, { type: 'string', enum: values })\n }\n if (typeName === 'object') {\n return withDescription(schema, zodObjectToSchema(def))\n }\n if (typeName === 'array') {\n const element = def['element'] as ZodTypeAny | undefined\n const result: JsonSchema = { type: 'array' }\n if (element) result['items'] = zodToJsonSchema(element)\n return withDescription(schema, result)\n }\n if (typeName === 'optional') {\n const inner = def['innerType'] as ZodTypeAny\n // description may be on the optional wrapper itself\n const desc = getDescription(schema)\n const innerSchema = zodToJsonSchema(inner)\n return desc ? { ...innerSchema, description: desc } : innerSchema\n }\n if (typeName === 'nullable') {\n const inner = def['innerType'] as ZodTypeAny\n const desc = getDescription(schema)\n const innerSchema = zodToJsonSchema(inner)\n const innerType = innerSchema['type']\n const result: JsonSchema = typeof innerType === 'string'\n ? { ...innerSchema, type: [innerType, 'null'] }\n : innerSchema\n return desc ? { ...result, description: desc } : result\n }\n if (typeName === 'default') {\n const inner = def['innerType'] as ZodTypeAny\n const defaultValue = def['defaultValue']\n const innerSchema = zodToJsonSchema(inner)\n const desc = getDescription(schema)\n const result: JsonSchema = defaultValue !== undefined\n ? { ...innerSchema, default: defaultValue }\n : innerSchema\n return desc ? { ...result, description: desc } : result\n }\n // Unknown type — return empty schema (no crash)\n return {}\n}\n\nfunction withDescription(schema: ZodTypeAny, result: JsonSchema): JsonSchema {\n const desc = getDescription(schema)\n return desc ? { ...result, description: desc } : result\n}\n\nfunction zodStringToSchema(def: Record<string, unknown>): JsonSchema {\n const schema: JsonSchema = { type: 'string' }\n const checks = def['checks'] as ZodCheckWithInternal[] | undefined\n if (!checks) return schema\n for (const check of checks) {\n const checkDef: ZodCheckDef | undefined = check._zod?.def ?? check.def\n if (!checkDef) continue\n const kind = checkDef.check\n if (kind === 'string_format') {\n const fmt = checkDef.format\n if (fmt === 'email') schema['format'] = 'email'\n if (fmt === 'uuid') schema['format'] = 'uuid'\n if (fmt === 'url') schema['format'] = 'uri'\n if (fmt === 'datetime') schema['format'] = 'date-time'\n if (fmt === 'date') schema['format'] = 'date'\n if (fmt === 'time') schema['format'] = 'time'\n }\n if (kind === 'min_length' && checkDef.minimum !== undefined) {\n schema['minLength'] = checkDef.minimum\n }\n if (kind === 'max_length' && checkDef.maximum !== undefined) {\n schema['maxLength'] = checkDef.maximum\n }\n }\n return schema\n}\n\nfunction zodNumberToSchema(def: Record<string, unknown>): JsonSchema {\n const schema: JsonSchema = { type: 'number' }\n const checks = def['checks'] as ZodCheckWithInternal[] | undefined\n if (!checks) return schema\n for (const check of checks) {\n const checkDef: ZodCheckDef | undefined = check._zod?.def ?? check.def\n if (!checkDef) continue\n const kind = checkDef.check\n if (kind === 'greater_than' && checkDef.value !== undefined) {\n if (checkDef.inclusive) {\n schema['minimum'] = checkDef.value\n } else {\n schema['exclusiveMinimum'] = checkDef.value\n }\n }\n if (kind === 'less_than' && checkDef.value !== undefined) {\n if (checkDef.inclusive) {\n schema['maximum'] = checkDef.value\n } else {\n schema['exclusiveMaximum'] = checkDef.value\n }\n }\n if (kind === 'multiple_of' && checkDef.value !== undefined) {\n schema['multipleOf'] = checkDef.value\n }\n }\n return schema\n}\n\nfunction zodObjectToSchema(def: Record<string, unknown>): JsonSchema {\n const shape = def['shape'] as Record<string, ZodTypeAny> | undefined\n const resolvedShape: Record<string, ZodTypeAny> = shape ?? {}\n\n const properties: Record<string, JsonSchema> = {}\n const required: string[] = []\n\n for (const [key, fieldSchema] of Object.entries(resolvedShape)) {\n const fieldDef = (fieldSchema._def as unknown) as Record<string, unknown>\n const isOptional = fieldDef['type'] === 'optional'\n properties[key] = zodToJsonSchema(fieldSchema)\n if (!isOptional) {\n required.push(key)\n }\n }\n\n const result: JsonSchema = { type: 'object', properties }\n if (required.length > 0) {\n result['required'] = required\n }\n return result\n}\n","import type { Route } from '../app/types'\nimport { zodToJsonSchema } from './zod-to-schema'\nimport type { JsonSchema } from './zod-to-schema'\nimport type { ZodTypeAny } from 'zod'\n\nexport interface OpenApiSpec {\n openapi: '3.1.0'\n info: { title: string; version: string; description?: string }\n paths: Record<string, Record<string, OpenApiOperation>>\n components?: {\n securitySchemes?: Record<string, OpenApiSecurityScheme>\n }\n}\n\ninterface OpenApiSecurityScheme {\n type: 'http'\n scheme: 'bearer'\n bearerFormat?: string\n}\n\ninterface OpenApiOperation {\n operationId?: string\n summary?: string\n description?: string\n tags?: string[]\n security?: Array<Record<string, string[]>>\n parameters?: OpenApiParameter[]\n requestBody?: OpenApiRequestBody\n responses: Record<string, OpenApiResponse>\n}\n\ninterface OpenApiParameter {\n name: string\n in: 'path' | 'query'\n required: boolean\n schema: JsonSchema\n}\n\ninterface OpenApiRequestBody {\n required: true\n content: {\n 'application/json': {\n schema: JsonSchema\n }\n }\n}\n\ninterface OpenApiResponse {\n description: string\n content?: {\n 'application/json': {\n schema: JsonSchema\n }\n }\n}\n\n// ── Pure helpers ──────────────────────────────────────────────────────────────\n\nfunction toOpenApiPath(path: string): string {\n return path.replace(/:([a-zA-Z_][a-zA-Z0-9_]*)/g, '{$1}')\n}\n\nfunction extractPathParams(path: string): string[] {\n const matches = path.match(/:([a-zA-Z_][a-zA-Z0-9_]*)/g)\n return matches ? matches.map(m => m.slice(1)) : []\n}\n\nfunction capitalize(s: string): string {\n return s.charAt(0).toUpperCase() + s.slice(1)\n}\n\n/** \"users\" → \"Users\", \"api-keys\" → \"Api Keys\" */\nfunction capitalizeTag(tag: string): string {\n return tag.split('-').map(capitalize).join(' ')\n}\n\n/**\n * Derives a human-readable summary from an HTTP method and path.\n *\n * GET /users/ → \"List users\"\n * GET /users/:id → \"Get users by id\"\n * GET /users/search → \"Search users\"\n * POST /users/ → \"Create users\"\n * POST /users/export → \"Export users\"\n * PATCH /users/:id → \"Update users\"\n * DELETE /users/:id → \"Delete users\"\n */\nfunction inferSummary(method: string, path: string): string {\n const segments = path.split('/').filter(Boolean)\n if (segments.length === 0) return method.toLowerCase()\n\n const isParam = (s: string): boolean => s.startsWith(':')\n const resource = segments.find(s => !isParam(s)) ?? 'resource'\n const lastSeg = segments[segments.length - 1] ?? ''\n const hasTrailingParam = isParam(lastSeg)\n const isLiteralVerb = !isParam(lastSeg) && lastSeg !== resource\n\n if (isLiteralVerb) return `${capitalize(lastSeg)} ${resource}`\n\n const m = method.toUpperCase()\n if (m === 'GET') {\n if (hasTrailingParam) return `Get ${resource} by ${lastSeg.slice(1)}`\n return `List ${resource}`\n }\n if (m === 'POST') return `Create ${resource}`\n if (m === 'PATCH') return `Update ${resource}`\n if (m === 'PUT') return `Update ${resource}`\n if (m === 'DELETE') return `Delete ${resource}`\n return `${m.toLowerCase()} ${resource}`\n}\n\n/**\n * Derives a camelCase operationId from an HTTP method and path.\n *\n * GET /users/ → \"listUsers\"\n * GET /users/:id → \"getUsersById\"\n * GET /users/search → \"searchUsers\"\n * POST /users/ → \"createUsers\"\n * PATCH /users/:id → \"updateUsers\"\n * DELETE /users/:id → \"deleteUsers\"\n */\nfunction inferOperationId(method: string, path: string): string {\n const segments = path.split('/').filter(Boolean)\n if (segments.length === 0) return method.toLowerCase()\n\n const isParam = (s: string): boolean => s.startsWith(':')\n const resource = segments.find(s => !isParam(s)) ?? 'resource'\n const lastSeg = segments[segments.length - 1] ?? ''\n const hasTrailingParam = isParam(lastSeg)\n const isLiteralVerb = !isParam(lastSeg) && lastSeg !== resource\n\n if (isLiteralVerb) return `${lastSeg}${capitalize(resource)}`\n\n const m = method.toUpperCase()\n if (m === 'GET') {\n if (hasTrailingParam) return `get${capitalize(resource)}By${capitalize(lastSeg.slice(1))}`\n return `list${capitalize(resource)}`\n }\n if (m === 'POST') return `create${capitalize(resource)}`\n if (m === 'PATCH') return `update${capitalize(resource)}`\n if (m === 'PUT') return `update${capitalize(resource)}`\n if (m === 'DELETE') return `delete${capitalize(resource)}`\n return `${m.toLowerCase()}${capitalize(resource)}`\n}\n\n// ── Generator ─────────────────────────────────────────────────────────────────\n\nexport function generateOpenApiSpec(\n routes: readonly Route<unknown>[],\n options?: { title?: string; version?: string; description?: string },\n): OpenApiSpec {\n const title = options?.title ?? 'Veln API'\n const version = options?.version ?? '1.0.0'\n\n const info: OpenApiSpec['info'] = { title, version }\n if (options?.description) info.description = options.description\n\n const paths: Record<string, Record<string, OpenApiOperation>> = {}\n let needsBearerScheme = false\n\n for (const route of routes) {\n // Skip hidden routes and routes belonging to hidden modules\n const moduleVisibility = route._module?.visibility ?? 'public'\n const routeVisibility = route.visibility ?? moduleVisibility\n if (routeVisibility === 'hidden') continue\n\n const openApiPath = toOpenApiPath(route.path)\n if (!paths[openApiPath]) paths[openApiPath] = {}\n\n const method = route.method.toLowerCase()\n const schema = route.schema\n\n // Build parameters from path params + query schema\n const parameters: OpenApiParameter[] = []\n\n for (const paramName of extractPathParams(route.path)) {\n let paramSchema: JsonSchema = { type: 'string' }\n if (schema?.params) {\n const paramsDef = (schema.params._def as unknown) as Record<string, unknown>\n const shape = paramsDef['shape'] as Record<string, ZodTypeAny> | undefined\n const resolvedShape: Record<string, ZodTypeAny> = shape ?? {}\n if (resolvedShape[paramName]) {\n paramSchema = zodToJsonSchema(resolvedShape[paramName] as ZodTypeAny)\n }\n }\n parameters.push({ name: paramName, in: 'path', required: true, schema: paramSchema })\n }\n\n if (schema?.query) {\n const queryDef = (schema.query._def as unknown) as Record<string, unknown>\n const shape = queryDef['shape'] as Record<string, ZodTypeAny> | undefined\n const resolvedShape: Record<string, ZodTypeAny> = shape ?? {}\n for (const [key, fieldSchema] of Object.entries(resolvedShape)) {\n const fieldDef = (fieldSchema._def as unknown) as Record<string, unknown>\n const isOptional = fieldDef['type'] === 'optional'\n parameters.push({\n name: key,\n in: 'query',\n required: !isOptional,\n schema: zodToJsonSchema(fieldSchema),\n })\n }\n }\n\n // Request body\n let requestBody: OpenApiRequestBody | undefined\n if (schema?.body) {\n requestBody = {\n required: true,\n content: { 'application/json': { schema: zodToJsonSchema(schema.body) } },\n }\n }\n\n // Response\n const responses: Record<string, OpenApiResponse> = {}\n if (schema?.response) {\n responses['200'] = {\n description: 'Success',\n content: { 'application/json': { schema: zodToJsonSchema(schema.response) } },\n }\n } else {\n responses['200'] = { description: 'Success' }\n }\n // Additional responses from docs.responses (e.g. 401, 404)\n if (route.docs?.responses) {\n for (const [code, doc] of Object.entries(route.docs.responses)) {\n responses[code] = { description: doc.description }\n }\n }\n\n // ── Summary / description / operationId — docs override > route fields > auto ──\n const effectiveSummary = route.docs?.summary ?? route.summary ?? inferSummary(route.method, route.path)\n const effectiveDescription = route.docs?.description ?? route.description ?? undefined\n const effectiveOperationId = route.docs?.operationId ?? inferOperationId(route.method, route.path)\n\n // ── Tag — module meta tag wins; fall back to first path segment ──\n const moduleTag = route._module?.meta?.tag\n const segmentTag = route.path.split('/').filter(Boolean)[0] ?? 'general'\n const tag = capitalizeTag(moduleTag ?? segmentTag)\n\n // ── Security — jwtPlugin on module ──\n const modulePlugins = route._module?.plugins ?? []\n const hasJwt = modulePlugins.some(p => p.name === 'jwt')\n if (hasJwt) needsBearerScheme = true\n\n const operation: OpenApiOperation = { responses }\n operation.operationId = effectiveOperationId\n operation.summary = effectiveSummary\n if (effectiveDescription) operation.description = effectiveDescription\n operation.tags = [tag]\n if (hasJwt) operation.security = [{ bearerAuth: [] }]\n if (parameters.length > 0) operation.parameters = parameters\n if (requestBody) operation.requestBody = requestBody\n\n paths[openApiPath]![method] = operation\n }\n\n const spec: OpenApiSpec = { openapi: '3.1.0', info, paths }\n if (needsBearerScheme) {\n spec.components = {\n securitySchemes: {\n bearerAuth: { type: 'http', scheme: 'bearer', bearerFormat: 'JWT' },\n },\n }\n }\n return spec\n}\n","import type { BoundVelnDB } from '../db/index'\nimport type { ServiceDef } from '../service/index'\nimport type { Logger, LogOptions } from '../app/types'\nimport { createMinimalLogger } from '../app/logger'\n\n// ── CronCtx ───────────────────────────────────────────────────────────────────\n\nexport interface CronCtx {\n db: BoundVelnDB\n [key: string]: unknown\n}\n\n// Re-export LogLevel for consumers\nexport type { LogLevel } from '../app/logger'\n\n// ── Expression Shortcuts ──────────────────────────────────────────────────────\n\nconst CRON_SHORTCUTS: Record<string, string> = {\n '@minute': '* * * * *',\n '@hourly': '0 * * * *',\n '@daily': '0 0 * * *',\n '@midnight': '0 0 * * *',\n '@weekly': '0 0 * * 0',\n '@monthly': '0 0 1 * *',\n '@yearly': '0 0 1 1 *',\n '@annually': '0 0 1 1 *',\n}\n\nexport function resolveExpression(expr: string): string {\n return CRON_SHORTCUTS[expr] ?? expr\n}\n\n// ── CronLockAdapter ───────────────────────────────────────────────────────────\n\n/**\n * CronLockAdapter — prevents duplicate job execution across multiple instances.\n *\n * Default: NoOpCronLockAdapter (always acquires — suitable for single-instance deployments)\n *\n * For multi-instance deployments, implement this interface with Redis SET NX EX\n * or a similar distributed lock mechanism.\n *\n * WARNING: TTL must exceed the maximum expected job duration.\n * Consider implementing a lock heartbeat for long-running jobs.\n *\n * @example\n * createApp({ cronLock: new RedisCronLockAdapter(redisClient) })\n */\nexport interface CronLockAdapter {\n acquire(jobName: string, ttlMs: number): Promise<boolean>\n release(jobName: string): Promise<void>\n}\n\nexport class NoOpCronLockAdapter implements CronLockAdapter {\n async acquire(_jobName: string, _ttlMs: number): Promise<boolean> {\n return true // always acquire — single-process default\n }\n async release(_jobName: string): Promise<void> {\n // no-op\n }\n}\n\n// ── CronDef — sealed result, produced by CronBuilder ─────────────────────────\n\nexport interface CronDef<TServices extends Record<string, unknown> = Record<never, never>> {\n readonly _name: string\n readonly _expression: string\n readonly _timezone: string | undefined\n readonly _runOnStart: boolean\n readonly _ttlMs: number | undefined\n readonly _logger: Logger\n readonly _mode: 'process' | 'os'\n readonly _handler: ((ctx: CronCtx & TServices, logger: Logger) => Promise<void> | void) | undefined\n readonly _services: ReadonlyArray<ServiceDef<string, unknown>>\n readonly _script: string | undefined\n readonly _onError: ((err: unknown) => void) | undefined\n\n // .use() on a sealed CronDef is kept for backwards-compat and for app.register()\n // service-merging (which spreads + re-binds). It erases the TServices type\n // (returns CronDef without param) because merging happens at runtime, not statically.\n use<TKey extends string, TDef>(\n service: ServiceDef<TKey, TDef>,\n ): CronDef<TServices & Record<TKey, TDef>>\n}\n\n// ── CronBuildOptions — timezone / runOnStart passed to defineCron() ───────────\n\nexport interface CronBuildOptions {\n timezone?: string\n runOnStart?: boolean\n ttlMs?: number\n log?: LogOptions\n onError?: (err: unknown) => void\n}\n\n// ── CronBuilder — fluent builder returned by defineCron() ─────────────────────\n// TServices accumulates via .use(). Call .handler() or .os() to seal into CronDef.\n\nexport interface CronBuilder<TServices extends Record<string, unknown>> {\n // Set timezone / runOnStart / log — returns the same builder for continued chaining\n options(opts: CronBuildOptions): CronBuilder<TServices>\n\n // Accumulate a service — handler will receive ctx[key] typed\n use<TKey extends string, TDef>(\n service: ServiceDef<TKey, TDef>,\n ): CronBuilder<TServices & Record<TKey, TDef>>\n\n // Seal into a process-mode CronDef. ctx has full TServices typing.\n // logger is always available as the 2nd arg — no-op (error level only) when log not set.\n handler(\n fn: (ctx: CronCtx & TServices, logger: Logger) => Promise<void> | void,\n ): CronDef<TServices>\n\n // Seal into an OS-level (Bun.cron) CronDef. No handler.\n os(script: string): CronDef<TServices>\n}\n\n// ── Helpers ───────────────────────────────────────────────────────────────────\n\nfunction resolveLogOpts(log: LogOptions | undefined): LogOptions {\n // No log configured → silent: true (suppress all output by default)\n return log ?? { silent: true }\n}\n\n// ── Internal factory ──────────────────────────────────────────────────────────\n\nfunction makeCronDef<TServices extends Record<string, unknown>>(\n name: string,\n expression: string,\n timezone: string | undefined,\n runOnStart: boolean,\n ttlMs: number | undefined,\n logger: Logger,\n mode: 'process' | 'os',\n handler: ((ctx: CronCtx & TServices, logger: Logger) => Promise<void> | void) | undefined,\n services: ReadonlyArray<ServiceDef<string, unknown>>,\n script: string | undefined,\n onError: ((err: unknown) => void) | undefined,\n): CronDef<TServices> {\n const def: CronDef<TServices> = {\n _name: name,\n _expression: resolveExpression(expression),\n _timezone: timezone,\n _runOnStart: runOnStart,\n _ttlMs: ttlMs,\n _logger: logger,\n _mode: mode,\n _handler: handler,\n _services: services,\n _script: script,\n _onError: onError,\n\n use<TKey extends string, TDef>(\n service: ServiceDef<TKey, TDef>,\n ): CronDef<TServices & Record<TKey, TDef>> {\n return makeCronDef<TServices & Record<TKey, TDef>>(\n name, expression, timezone, runOnStart, ttlMs, logger, mode,\n handler as ((ctx: CronCtx & TServices & Record<TKey, TDef>, logger: Logger) => Promise<void> | void) | undefined,\n [...services, service as ServiceDef<string, unknown>],\n script,\n onError,\n )\n },\n }\n return def\n}\n\nfunction makeCronBuilder<TServices extends Record<string, unknown>>(\n name: string,\n expression: string,\n opts: CronBuildOptions,\n services: ReadonlyArray<ServiceDef<string, unknown>>,\n): CronBuilder<TServices> {\n return {\n options(newOpts: CronBuildOptions): CronBuilder<TServices> {\n return makeCronBuilder<TServices>(name, expression, { ...opts, ...newOpts }, services)\n },\n\n use<TKey extends string, TDef>(\n service: ServiceDef<TKey, TDef>,\n ): CronBuilder<TServices & Record<TKey, TDef>> {\n return makeCronBuilder<TServices & Record<TKey, TDef>>(\n name, expression, opts,\n [...services, service as ServiceDef<string, unknown>],\n )\n },\n\n handler(fn: (ctx: CronCtx & TServices, logger: Logger) => Promise<void> | void): CronDef<TServices> {\n const logger = createMinimalLogger(`cron:${name}`, resolveLogOpts(opts.log))\n return makeCronDef<TServices>(\n name, expression, opts.timezone, opts.runOnStart ?? false,\n opts.ttlMs, logger, 'process', fn, services, undefined, opts.onError,\n )\n },\n\n os(script: string): CronDef<TServices> {\n const logger = createMinimalLogger(`cron:${name}`, resolveLogOpts(opts.log))\n return makeCronDef<TServices>(\n name, expression, opts.timezone, opts.runOnStart ?? false,\n opts.ttlMs, logger, 'os', undefined, services, script, opts.onError,\n )\n },\n }\n}\n\n/**\n * defineCron — defines a scheduled background job.\n *\n * @param name Unique job identifier. Used as lock key and in log output.\n * @param expression Cron expression or shortcut (`@daily`, `@hourly`, `@minute`, etc.).\n * @param opts Optional timezone, runOnStart, ttlMs (lock TTL), and log options.\n *\n * Call `.handler(fn)` to run in-process, or `.os(script)` for OS-level scheduling via Bun.\n * Chain `.use(ServiceDef)` to inject services into the handler context.\n *\n * @example\n * defineCron('cleanup', '@daily')\n * .use(JobService)\n * .handler(async (ctx) => { await ctx.jobService.deleteExpired() })\n */\nexport function defineCron(\n name: string,\n expression: string,\n opts?: CronBuildOptions,\n): CronBuilder<Record<never, never>> {\n return makeCronBuilder<Record<never, never>>(name, expression, opts ?? {}, [])\n}\n","import type { BaseCtx } from './types'\nimport type { CookieJar } from './cookies'\n\n// ── createSystemCtx ───────────────────────────────────────────────────────────\n// Builds a complete BaseCtx for use outside the HTTP request lifecycle:\n// background jobs, CLI scripts, cron workers, seeding, etc.\n//\n// A dummy Request is provided so hooks that read ctx.req (e.g. ctx.req.url)\n// don't crash — they receive a stable sentinel URL instead of throwing.\n//\n// extra is spread into the returned object, extending BaseCtx with whatever\n// fields the caller's hooks expect (e.g. { user: { id: 'system', role: 'admin' } }).\n//\n// Usage:\n// const ctx = createSystemCtx({ user: { id: 'cron', role: 'admin' } })\n// const bound = db.withCtx(ctx)\n// await bound.into(usersTable).insert({ name: 'Cron User' })\n// // Hooks see ctx.user.id === 'cron' ✅\n// // Audit actor: 'cron' ✅\n\nconst SYSTEM_URL = 'http://system.local/background'\n\n// Empty CookieJar for system/background contexts — no request cookies, no Set-Cookie headers.\nconst emptyCookieJar: CookieJar = {\n get: () => undefined,\n set: () => {},\n delete: () => {},\n _pending: () => [],\n}\n\nexport function createSystemCtx<TExtra extends object = Record<never, never>>(\n extra?: TExtra,\n): BaseCtx & TExtra {\n const base: BaseCtx = {\n req: new Request(SYSTEM_URL),\n params: {},\n query: {},\n json: (data, status = 200) =>\n new Response(JSON.stringify(data), {\n status,\n headers: { 'Content-Type': 'application/json' },\n }),\n text: (data, status = 200) =>\n new Response(data, { status }),\n html: (data, status = 200) =>\n new Response(data, {\n status,\n headers: { 'Content-Type': 'text/html' },\n }),\n cookie: emptyCookieJar,\n emit: () => {},\n stream: () => { throw new Error('[veln] stream not available in system context') },\n sse: () => { throw new Error('[veln] sse not available in system context') },\n }\n\n return { ...base, ...(extra ?? {}) } as BaseCtx & TExtra\n}\n","export interface MatchResult {\n params: Record<string, string | undefined>\n}\n\nexport function matchPath(pattern: string, pathname: string): MatchResult | null {\n // Normalize trailing slashes (but keep root '/')\n const normPattern = pattern.length > 1 ? pattern.replace(/\\/$/, '') : pattern\n const normPathname = pathname.length > 1 ? pathname.replace(/\\/$/, '') : pathname\n\n // Wildcard: pattern ends with /*\n if (normPattern.endsWith('/*')) {\n const prefix = normPattern.slice(0, -2) // remove /*\n if (normPathname.startsWith(prefix + '/')) {\n const rest = normPathname.slice(prefix.length + 1) // skip leading /\n return { params: { '*': rest } }\n }\n return null\n }\n\n const patternSegments = normPattern.split('/')\n const pathSegments = normPathname.split('/')\n\n const params: Record<string, string | undefined> = {}\n\n let pi = 0 // path index\n for (let i = 0; i < patternSegments.length; i++) {\n const pSeg = patternSegments[i]!\n\n if (pSeg.startsWith(':') && pSeg.endsWith('?')) {\n // Optional param\n const paramName = pSeg.slice(1, -1)\n if (pi < pathSegments.length) {\n params[paramName] = pathSegments[pi]\n pi++\n } else {\n params[paramName] = undefined\n }\n } else if (pSeg.startsWith(':')) {\n // Required param\n if (pi >= pathSegments.length) return null\n params[pSeg.slice(1)] = pathSegments[pi]!\n pi++\n } else {\n // Literal\n if (pi >= pathSegments.length || pathSegments[pi] !== pSeg) return null\n pi++\n }\n }\n\n // All path segments must be consumed (unless optional params left pattern shorter)\n if (pi !== pathSegments.length) return null\n\n return { params }\n}\n\nexport function parseQuery(search: string): Record<string, string | string[]> {\n // Strip leading '?' if present\n const raw = search.startsWith('?') ? search.slice(1) : search\n if (!raw) return {}\n\n const result: Record<string, string | string[]> = {}\n const params = new URLSearchParams(raw)\n\n for (const key of params.keys()) {\n const values = params.getAll(key)\n result[key] = values.length === 1 ? values[0]! : values\n }\n\n return result\n}\n","import type { VelnAdapter } from '../adapter/types'\nimport type { SchemaMap } from '../schema/table'\nimport type { ModuleHookHandlers } from '../hooks/types'\nimport type { AuditDeclaration } from './module'\nimport { buildInsert } from '../db/sql'\nimport { applyRedact } from '../schema/audit'\n\n// ── buildAuditHooks ───────────────────────────────────────────────────────────\n// Called by app.register() for each AuditDeclaration.\n// Returns ModuleHookHandlers that write directly to adapter — no ctx, no cast.\n//\n// actor: (ctx: TCtx) => string | null | undefined\n// ctx is passed by HookExecutor at hook-call time — fully typed at the call site,\n// safely typed as unknown here (this file doesn't need to know TCtx internals).\n//\n// Atomicity note: audit writes use the base adapter, not a TX adapter.\n// This means audit rows survive even if the calling TX is rolled back.\n// That is intentional: audit logs are an append-only record of attempted operations.\n//\n// Audit errors are caught and console.error'd — never thrown to the caller.\n\nexport function buildAuditHooks<T extends Record<string, unknown>, TCtx, S extends SchemaMap>(\n decl: AuditDeclaration<T, TCtx, S>,\n adapter: VelnAdapter,\n): ModuleHookHandlers<T, unknown> {\n const { table, config } = decl\n const redactFields = (config.redact ?? []) as string[]\n const auditTable = config.storeIn\n const onError = config.onError ?? ((err: unknown) => console.error('[audit] write failed:', err))\n\n // before-snapshot: WeakMap keyed on the patch object.\n // Each .update() call gets a fresh patch object — the WeakMap entry is\n // GC'd when the patch goes out of scope. No global state, no leaks.\n const snapshots = new WeakMap<object, Record<string, unknown>>()\n\n async function writeAudit(\n operation: 'insert' | 'update' | 'delete',\n actor: string | null,\n before: Record<string, unknown> | null,\n after: Record<string, unknown> | null,\n ): Promise<void> {\n const row: Record<string, unknown> = {\n tableName: table.name,\n operation,\n actor,\n before: before !== null ? JSON.stringify(before) : null,\n after: after !== null ? JSON.stringify(after) : null,\n changedAt: new Date().toISOString(),\n }\n const { sql, params } = buildInsert(auditTable.name, row)\n await adapter.execute(sql, params)\n }\n\n return {\n afterInsert: async (ctx, result) => {\n try {\n const after = redactFields.length ? applyRedact(result as Record<string, unknown>, redactFields) : result as Record<string, unknown>\n const actor = config.actor(ctx as TCtx) ?? null\n await writeAudit('insert', actor, null, after)\n } catch (err) {\n onError(err)\n }\n },\n\n beforeUpdate: async (_ctx, _current, patch) => {\n // Capture snapshot before the update.\n // patch is a unique object per .update() call — safe WeakMap key.\n if (patch !== null && typeof patch === 'object') {\n snapshots.set(patch, _current as Record<string, unknown>)\n }\n },\n\n afterUpdate: async (ctx, result, before) => {\n try {\n const beforeSnap = redactFields.length ? applyRedact(before as Record<string, unknown>, redactFields) : before as Record<string, unknown>\n const afterSnap = redactFields.length ? applyRedact(result as Record<string, unknown>, redactFields) : result as Record<string, unknown>\n const actor = config.actor(ctx as TCtx) ?? null\n await writeAudit('update', actor, beforeSnap, afterSnap)\n } catch (err) {\n onError(err)\n }\n },\n\n afterDelete: async (ctx, deleted) => {\n try {\n const before = redactFields.length ? applyRedact(deleted as Record<string, unknown>, redactFields) : deleted as Record<string, unknown>\n const actor = config.actor(ctx as TCtx) ?? null\n await writeAudit('delete', actor, before, null)\n } catch (err) {\n onError(err)\n }\n },\n }\n}\n","export interface CookieOptions {\n httpOnly?: boolean\n secure?: boolean\n sameSite?: 'Strict' | 'Lax' | 'None'\n maxAge?: number\n path?: string\n domain?: string\n}\n\nexport interface CookieJar {\n get(name: string): string | undefined\n set(name: string, value: string, options?: CookieOptions): void\n delete(name: string): void\n /** Framework-internal: returns all pending Set-Cookie header values */\n _pending(): string[]\n}\n\nexport function createCookieJar(req: Request): CookieJar {\n const pending: string[] = []\n\n function parseCookies(): Record<string, string> {\n const header = req.headers.get('Cookie') ?? ''\n const result: Record<string, string> = {}\n for (const part of header.split(';')) {\n const trimmed = part.trim()\n const eq = trimmed.indexOf('=')\n if (eq === -1) continue\n const name = trimmed.slice(0, eq).trim()\n const value = trimmed.slice(eq + 1).trim()\n if (name) result[name] = value\n }\n return result\n }\n\n // Parse once, cache\n let parsed: Record<string, string> | undefined\n\n return {\n get(name: string): string | undefined {\n if (!parsed) parsed = parseCookies()\n return parsed[name]\n },\n\n set(name: string, value: string, options: CookieOptions = {}): void {\n const parts: string[] = [`${encodeURIComponent(name)}=${encodeURIComponent(value)}`]\n parts.push(`Path=${options.path ?? '/'}`)\n if (options.maxAge !== undefined) parts.push(`Max-Age=${options.maxAge}`)\n if (options.domain) parts.push(`Domain=${options.domain}`)\n const sameSiteValue = options.sameSite ?? 'Lax'\n parts.push(`SameSite=${sameSiteValue}`)\n if (options.secure ?? true) parts.push('Secure')\n if (options.httpOnly ?? true) parts.push('HttpOnly')\n pending.push(parts.join('; '))\n },\n\n delete(name: string): void {\n const parts = [\n `${encodeURIComponent(name)}=`,\n 'Path=/',\n 'Max-Age=0',\n 'Secure',\n 'HttpOnly',\n ]\n pending.push(parts.join('; '))\n },\n\n _pending(): string[] {\n return [...pending]\n },\n }\n}\n","import type { Guard, ErrorHandler, RouteHandler, Route, OnRequestHook, OnBeforeHandleHook, OnResponseHook, RouteHandlerWithSchema, RouteSchema, RouteMap, RouteDocs, WsRouteShape, BaseOptions } from './types'\nimport { createOnRequest, createOnResponse } from './types'\nimport type { Plugin } from './plugin'\nimport type { TableDef, SchemaMap } from '../schema/table'\nimport type { ModuleHookHandlers } from '../hooks/types'\nimport type { BaseCtx } from './types'\nimport type { AuditConfig } from '../schema/audit'\nimport type { ServiceDef } from '../service/index'\nimport type { ZodTypeAny } from 'zod'\nimport type { EventHandlerDef } from '../events/handler'\nimport type { CronDef } from '../cron/index'\nimport type { MiddlewareDef } from './middleware'\nimport { z } from 'zod'\n\nexport interface HookDeclaration<T, TCtx> {\n table: TableDef<T, any>\n handlers: ModuleHookHandlers<T, TCtx>\n}\n\n// AuditDeclaration — carries table + config only.\n// No adapter, no handler closures here.\n// app.register() injects the adapter and wires the hooks.\nexport interface AuditDeclaration<T, TCtx, S extends SchemaMap> {\n table: TableDef<T, any>\n config: AuditConfig<TCtx, T, S>\n}\n\n// ServiceDeclaration — carries a ServiceDef only.\n// Framework instantiates per-request in fetch() after plugins run.\nexport interface ServiceDeclaration<TKey extends string, TDef> {\n readonly service: ServiceDef<TKey, TDef>\n}\n\nexport interface VelnModule {\n prefix: string\n routes: Route<any>[]\n wsRoutes: WsRouteShape[]\n hookDeclarations: HookDeclaration<any, any>[]\n auditDeclarations: AuditDeclaration<any, any, any>[]\n serviceDeclarations: ReadonlyArray<ServiceDeclaration<string, unknown>>\n plugins: Plugin<any, any>[]\n guards: Guard<any>[]\n onRequestHooks: OnRequestHook<any>[]\n onBeforeHandleHooks: OnBeforeHandleHook<any>[]\n onResponseHooks: OnResponseHook<any>[]\n onError?: ErrorHandler<any>\n eventHandlerDefs: EventHandlerDef[]\n cronDefs: CronDef<Record<string, unknown>>[]\n visibility: 'public' | 'hidden'\n meta?: { tag?: string; description?: string }\n options?: BaseOptions\n}\n\n// ── ModuleBuilderState ───────────────────────────────────────────────────────\n// All builder state in one object — clone() spreads it with one override.\n// Adding a new field costs: (1) add here, (2) add to create(), (3) add to build().\n// Zero call-site changes needed anywhere else.\n\ninterface ModuleBuilderState {\n prefix: string\n plugins: Plugin<any, any>[]\n hookDeclarations: HookDeclaration<any, any>[]\n auditDeclarations: AuditDeclaration<any, any, any>[]\n serviceDeclarations: ReadonlyArray<ServiceDeclaration<string, unknown>>\n routes: Route<any>[]\n wsRoutes: WsRouteShape[]\n guards: Guard<any>[]\n onRequestHooks: OnRequestHook<any>[]\n onBeforeHandleHooks: OnBeforeHandleHook<any>[]\n onResponseHooks: OnResponseHook<any>[]\n onError: ErrorHandler<any> | undefined\n eventHandlerDefs: EventHandlerDef[]\n cronDefs: CronDef<Record<string, unknown>>[]\n visibility: 'public' | 'hidden'\n meta: { tag?: string; description?: string } | undefined\n options: BaseOptions | undefined\n}\n\n// RouteDefinition — used by .route(). Generics kept for type inference at call site.\n// The interface itself stays non-generic to allow storage; the .route() method\n// carries the generics so z.infer<TBody> resolves immediately.\nexport interface RouteDefinition<TCtx extends BaseCtx> {\n method: 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE'\n path: string\n summary?: string\n description?: string\n docs?: RouteDocs\n visibility?: 'public' | 'hidden'\n schema?: RouteSchema\n handler: (ctx: TCtx) => Response | Promise<Response>\n}\n\nexport type HttpMethod = 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE'\n\nfunction normalizeHandler<TCtx, S extends RouteSchema>(\n handler: RouteHandler<TCtx> | ((ctx: TCtx) => Response | Promise<Response>) | RouteHandlerWithSchema<TCtx, S>,\n): { handler: RouteHandler<TCtx>; schema: RouteSchema | undefined; docs: RouteDocs | undefined } {\n if (typeof handler === 'function') {\n return { handler: { handler }, schema: undefined, docs: undefined }\n }\n if ('params' in handler || 'query' in handler || 'body' in handler || 'response' in handler || 'docs' in handler) {\n const h = handler as RouteHandlerWithSchema<TCtx, RouteSchema>\n return {\n handler: { handler: h.handler as (ctx: TCtx) => Response | Promise<Response> },\n schema: { params: h.params, query: h.query, body: h.body, response: h.response },\n docs: h.docs,\n }\n }\n return { handler: handler as RouteHandler<TCtx>, schema: undefined, docs: undefined }\n}\n\nexport class ModuleBuilder<TCtx extends BaseCtx, TPrefix extends string = string, TRoutes extends RouteMap = Record<never, never>> {\n // Phantom fields — never assigned at runtime, used only for type extraction\n declare readonly _routes: TRoutes\n declare readonly _prefix: TPrefix\n\n private constructor(protected readonly _state: ModuleBuilderState) {}\n\n // clone() — the only place new ModuleBuilder is constructed after create().\n // Every builder method calls clone() with one override — adding a field\n // to ModuleBuilderState never requires touching existing methods.\n protected clone<NCtx extends BaseCtx = TCtx, NPrefix extends string = TPrefix, NRoutes extends RouteMap = TRoutes>(\n overrides: Partial<ModuleBuilderState>,\n ): ModuleBuilder<NCtx, NPrefix, NRoutes> {\n return new ModuleBuilder<NCtx, NPrefix, NRoutes>({ ...this._state, ...overrides })\n }\n\n // Framework-internal accessor — used by @veln/ws module augmentation.\n // Not part of the public API — prefixed with _ to signal framework-only.\n get _wsRoutes(): WsRouteShape[] { return this._state.wsRoutes }\n\n static create<TPrefix extends string>(prefix: TPrefix): ModuleBuilder<BaseCtx, TPrefix, Record<never, never>> {\n return new ModuleBuilder<BaseCtx, TPrefix, Record<never, never>>({\n prefix,\n plugins: [],\n hookDeclarations: [],\n auditDeclarations: [],\n serviceDeclarations: [],\n routes: [],\n wsRoutes: [],\n guards: [],\n onRequestHooks: [],\n onBeforeHandleHooks: [],\n onResponseHooks: [],\n onError: undefined,\n eventHandlerDefs: [],\n cronDefs: [],\n visibility: 'public',\n meta: undefined,\n options: undefined,\n })\n }\n\n options(opts: BaseOptions): ModuleBuilder<TCtx, TPrefix, TRoutes> {\n return this.clone({ options: opts })\n }\n\n visibility(v: 'public' | 'hidden'): ModuleBuilder<TCtx, TPrefix, TRoutes> {\n return this.clone({ visibility: v })\n }\n\n plugin<TAdd extends object>(p: Plugin<TCtx, TAdd>): ModuleBuilder<TCtx & TAdd, TPrefix, TRoutes> {\n const next = this.clone({ plugins: [...this._state.plugins, p as Plugin<any, any>] })\n return next as unknown as ModuleBuilder<TCtx & TAdd, TPrefix, TRoutes>\n }\n\n // ── .use() ───────────────────────────────────────────────────────────────\n // Service overload: declares a service dep for this module.\n // Middleware overload: registers onRequest/onResponse hooks module-scoped.\n use<TKey extends string, TDef>(\n service: ServiceDef<TKey, TDef>,\n ): ModuleBuilder<TCtx & Record<TKey, TDef>, TPrefix, TRoutes>\n use(middleware: MiddlewareDef): ModuleBuilder<TCtx, TPrefix, TRoutes>\n use<TKey extends string, TDef>(\n serviceOrMiddleware: ServiceDef<TKey, TDef> | MiddlewareDef,\n ): ModuleBuilder<TCtx & Record<TKey, TDef>, TPrefix, TRoutes> | ModuleBuilder<TCtx, TPrefix, TRoutes> {\n if ('_serviceKey' in serviceOrMiddleware) {\n const decl: ServiceDeclaration<TKey, TDef> = { service: serviceOrMiddleware }\n const next = this.clone({\n serviceDeclarations: [...this._state.serviceDeclarations, decl as ServiceDeclaration<string, unknown>],\n })\n return next as unknown as ModuleBuilder<TCtx & Record<TKey, TDef>, TPrefix, TRoutes>\n }\n // MiddlewareDef — wire hooks\n const m = serviceOrMiddleware as MiddlewareDef\n const overrides: Partial<ModuleBuilderState> = {}\n if (m._onRequest) {\n overrides.onRequestHooks = [...this._state.onRequestHooks, createOnRequest(m._onRequest)]\n }\n if (m._onResponse) {\n overrides.onResponseHooks = [...this._state.onResponseHooks, createOnResponse(m._onResponse)]\n }\n return this.clone(overrides)\n }\n\n guard(g: Guard<TCtx>): ModuleBuilder<TCtx, TPrefix, TRoutes> {\n return this.clone({ guards: [...this._state.guards, g as Guard<any>] })\n }\n\n onRequest(hook: OnRequestHook<TCtx>): ModuleBuilder<TCtx, TPrefix, TRoutes> {\n return this.clone({ onRequestHooks: [...this._state.onRequestHooks, hook as OnRequestHook<any>] })\n }\n\n onBeforeHandle(hook: OnBeforeHandleHook<TCtx>): ModuleBuilder<TCtx, TPrefix, TRoutes> {\n return this.clone({ onBeforeHandleHooks: [...this._state.onBeforeHandleHooks, hook as OnBeforeHandleHook<any>] })\n }\n\n onResponse(hook: OnResponseHook<TCtx>): ModuleBuilder<TCtx, TPrefix, TRoutes> {\n return this.clone({ onResponseHooks: [...this._state.onResponseHooks, hook as OnResponseHook<any>] })\n }\n\n hook<T>(table: TableDef<T, any>, handlers: ModuleHookHandlers<T, TCtx>): ModuleBuilder<TCtx, TPrefix, TRoutes> {\n return this.clone({ hookDeclarations: [...this._state.hookDeclarations, { table, handlers }] })\n }\n\n // ── .audit() ─────────────────────────────────────────────────────────────\n // Declares that this table should be audited with the given config.\n // No hooks are built here — no adapter, no closures.\n // app.register() receives the AuditDeclaration and wires the adapter there.\n audit<T extends Record<string, unknown>, S extends SchemaMap>(\n table: TableDef<T, any>,\n config: AuditConfig<TCtx, T, S>,\n ): ModuleBuilder<TCtx, TPrefix, TRoutes> {\n const decl: AuditDeclaration<T, TCtx, S> = { table, config }\n return this.clone({ auditDeclarations: [...this._state.auditDeclarations, decl] })\n }\n\n events(handler: EventHandlerDef): ModuleBuilder<TCtx, TPrefix, TRoutes> {\n return this.clone({ eventHandlerDefs: [...this._state.eventHandlerDefs, handler] })\n }\n\n cron(def: CronDef): ModuleBuilder<TCtx, TPrefix, TRoutes> {\n return this.clone({ cronDefs: [...this._state.cronDefs, def] })\n }\n\n private _addRoute<S extends RouteSchema>(\n method: HttpMethod,\n path: string,\n handlerArg: RouteHandler<TCtx> | ((ctx: TCtx) => Response | Promise<Response>) | RouteHandlerWithSchema<TCtx, S>,\n ): ModuleBuilder<TCtx, TPrefix, TRoutes> {\n const { handler, schema, docs } = normalizeHandler(handlerArg)\n const guardDef = typeof handlerArg === 'object' && 'handler' in handlerArg && !('_phase' in handlerArg)\n ? (handlerArg as RouteHandlerWithSchema<TCtx, S>).guard\n : undefined\n const route: Route<any> = {\n method, path, handler, schema, docs,\n guards: guardDef != null && guardDef !== false ? [guardDef as Guard<unknown>] : [],\n moduleGuardOptOut: guardDef === false ? true : undefined,\n }\n return this.clone({ routes: [...this._state.routes, route] })\n }\n\n // ── .route() ─────────────────────────────────────────────────────────────\n //\n // Analysis (Spec 05):\n // 1. Method shortcuts ARE wrappers around _registerMethod() → _addRoute().\n // 2. Body/params/query schemas are stored in route.schema; validation runs at\n // request time in the framework fetch() pipeline.\n // 3. Generics TBody/TParams/etc flow into RouteMap via the typed overload return\n // type: Record<`METHOD ${TPrefix}${TPath}`, { body, params, query, response, _prefix }>.\n // 4. Old .route() built the Route object manually, used a nested `schema:{}` wrapper,\n // and returned ModuleBuilder without updating TRoutes.\n //\n // Implementation: delegate to _registerMethod() so validation logic is shared\n // (no duplication). The typed overload updates TRoutes just like .get()/.post() etc.\n // Backward compat: top-level `summary` and nested `schema:{}` both still work.\n\n // Overload 1 — legacy: nested `schema:{}` wrapper (backward compat, tried first so\n // calls with `schema` don't fall through to the flat overload)\n route<\n TBody extends ZodTypeAny = never,\n TParams extends ZodTypeAny = never,\n TQuery extends ZodTypeAny = never,\n >(def: {\n method: HttpMethod\n path: string\n /** @deprecated Use docs.summary instead */\n summary?: string\n description?: string\n docs?: RouteDocs\n visibility?: 'public' | 'hidden'\n schema?: {\n body?: TBody\n params?: TParams\n query?: TQuery\n response?: ZodTypeAny\n }\n handler: (ctx: TCtx & {\n body: z.infer<TBody>\n params: z.infer<TParams>\n query: z.infer<TQuery>\n }) => Response | Promise<Response>\n }): ModuleBuilder<TCtx, TPrefix, TRoutes>\n // Overload 2 — fully typed: flat body/params/query/response + updates RouteMap.\n // NoInfer<TBody/TParams/TQuery> in the handler parameter prevents TypeScript from\n // trying to infer the generics from the handler (which would cause a circular\n // dependency with the `body:`, `params:`, `query:` fields in the same object literal).\n // TypeScript infers the generics from the schema fields first, then contextually\n // types the handler using NoInfer — the same pattern used by tRPC and similar frameworks.\n route<\n TMethod extends HttpMethod = HttpMethod,\n TBody extends ZodTypeAny = never,\n TParams extends ZodTypeAny = never,\n TQuery extends ZodTypeAny = never,\n TResponse extends ZodTypeAny = never,\n TPath extends string = string,\n >(def: {\n method: TMethod\n path: TPath\n body?: TBody\n params?: TParams\n query?: TQuery\n response?: TResponse\n docs?: RouteDocs\n guard?: Guard<TCtx> | false\n /** @deprecated Use docs.summary instead */\n summary?: string\n description?: string\n visibility?: 'public' | 'hidden'\n handler: (ctx: TCtx & {\n body: z.infer<NoInfer<TBody>>\n params: z.infer<NoInfer<TParams>>\n query: z.infer<NoInfer<TQuery>>\n }) => Response | Promise<Response>\n }): ModuleBuilder<TCtx, TPrefix, TRoutes & Record<`${TMethod} ${TPrefix}${TPath}`, { body: TBody; params: TParams; query: TQuery; response: TResponse; _prefix: TPrefix }>>\n // Implementation — handles both overloads\n route(def: {\n method: HttpMethod\n path: string\n body?: ZodTypeAny\n params?: ZodTypeAny\n query?: ZodTypeAny\n response?: ZodTypeAny\n docs?: RouteDocs\n guard?: Guard<TCtx> | false\n summary?: string\n description?: string\n visibility?: 'public' | 'hidden'\n schema?: {\n body?: ZodTypeAny\n params?: ZodTypeAny\n query?: ZodTypeAny\n response?: ZodTypeAny\n }\n handler: (ctx: TCtx) => Response | Promise<Response>\n }): ModuleBuilder<TCtx, TPrefix, RouteMap> {\n // Normalize docs — merge deprecated top-level summary into docs.summary\n let docs = def.docs\n if (def.summary !== undefined) {\n docs = { ...docs, summary: docs?.summary ?? def.summary }\n }\n // Support both flat (new) and nested schema (legacy) forms\n const body = def.body ?? def.schema?.body\n const params = def.params ?? def.schema?.params\n const query = def.query ?? def.schema?.query\n const response = def.response ?? def.schema?.response\n // Build the defOrHandler object for _registerMethod — identical shape to method shortcuts\n const defObj: { body?: ZodTypeAny; params?: ZodTypeAny; query?: ZodTypeAny; response?: ZodTypeAny; docs?: RouteDocs; handler: (ctx: TCtx) => Response | Promise<Response> } = {\n body,\n params,\n query,\n response,\n docs,\n handler: def.handler,\n }\n // Register via shared _registerMethod — no duplication of validation logic.\n // We pre-build the route so we can patch legacy fields (summary, description,\n // visibility, guard) before cloning — all within the same class so _state is accessible.\n const { handler: rh, schema, docs: normalizedDocs } = normalizeHandler(defObj)\n const route: Route<TCtx> = {\n method: def.method,\n path: def.path,\n summary: def.summary,\n description: def.description,\n visibility: def.visibility,\n docs: normalizedDocs,\n handler: rh,\n guards: def.guard != null && def.guard !== false ? [def.guard as Guard<unknown>] : [],\n moduleGuardOptOut: def.guard === false ? true : undefined,\n schema,\n }\n return this.clone({ routes: [...this._state.routes, route] })\n }\n\n meta(m: { tag?: string; description?: string }): ModuleBuilder<TCtx, TPrefix, TRoutes> {\n return this.clone({ meta: m })\n }\n\n // ── HTTP methods ─────────────────────────────────────────────────────────\n // Two overloads per method:\n // 1. (path, { body?, params?, query?, response?, handler }) — separate generics,\n // z.infer<TBody> resolved immediately — no deferred conditional, no unknown body\n // 2. (path, handler) — plain function, no schema\n //\n // The (path, schema, handler) 3-arg form is intentionally omitted — use overload 1.\n\n private _registerMethod(\n method: 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE',\n path: string,\n defOrHandler: { body?: ZodTypeAny; params?: ZodTypeAny; query?: ZodTypeAny; response?: ZodTypeAny; docs?: RouteDocs; guard?: Guard<TCtx> | false; handler: (ctx: any) => Response | Promise<Response> } | RouteHandler<TCtx> | ((ctx: TCtx) => Response | Promise<Response>),\n ): ModuleBuilder<TCtx, TPrefix, RouteMap> {\n if (typeof defOrHandler === 'object' && 'handler' in defOrHandler && typeof defOrHandler.handler === 'function' && !('_phase' in defOrHandler)) {\n const { handler, body, params, query, response, docs, guard } = defOrHandler as { handler: (ctx: TCtx) => Response | Promise<Response>; body?: ZodTypeAny; params?: ZodTypeAny; query?: ZodTypeAny; response?: ZodTypeAny; docs?: RouteDocs; guard?: Guard<TCtx> | false }\n return this._addRoute(method, path, { handler, body, params, query, response, docs, guard } as RouteHandlerWithSchema<TCtx, RouteSchema>)\n }\n return this._addRoute(method, path, defOrHandler as RouteHandler<TCtx> | ((ctx: TCtx) => Response | Promise<Response>))\n }\n\n get<\n TBody extends ZodTypeAny = never,\n TParams extends ZodTypeAny = never,\n TQuery extends ZodTypeAny = never,\n TResponse extends ZodTypeAny = never,\n TPath extends string = string,\n >(path: TPath, def: {\n body?: TBody\n params?: TParams\n query?: TQuery\n response?: TResponse\n docs?: RouteDocs\n guard?: Guard<TCtx> | false\n handler: (ctx: TCtx & { body: z.infer<TBody>; params: z.infer<TParams>; query: z.infer<TQuery> }) => Response | Promise<Response>\n }): ModuleBuilder<TCtx, TPrefix, TRoutes & Record<`GET ${TPrefix}${TPath}`, { body: TBody; params: TParams; query: TQuery; response: TResponse; _prefix: TPrefix }>>\n get(path: string, handler: RouteHandler<TCtx> | ((ctx: TCtx) => Response | Promise<Response>)): ModuleBuilder<TCtx, TPrefix, TRoutes>\n get(path: string, defOrHandler: Parameters<typeof this._registerMethod>[2]): ModuleBuilder<TCtx, TPrefix, RouteMap> {\n return this._registerMethod('GET', path, defOrHandler)\n }\n\n post<\n TBody extends ZodTypeAny = never,\n TParams extends ZodTypeAny = never,\n TQuery extends ZodTypeAny = never,\n TResponse extends ZodTypeAny = never,\n TPath extends string = string,\n >(path: TPath, def: {\n body?: TBody\n params?: TParams\n query?: TQuery\n response?: TResponse\n docs?: RouteDocs\n guard?: Guard<TCtx> | false\n handler: (ctx: TCtx & { body: z.infer<TBody>; params: z.infer<TParams>; query: z.infer<TQuery> }) => Response | Promise<Response>\n }): ModuleBuilder<TCtx, TPrefix, TRoutes & Record<`POST ${TPrefix}${TPath}`, { body: TBody; params: TParams; query: TQuery; response: TResponse; _prefix: TPrefix }>>\n post(path: string, handler: RouteHandler<TCtx> | ((ctx: TCtx) => Response | Promise<Response>)): ModuleBuilder<TCtx, TPrefix, TRoutes>\n post(path: string, defOrHandler: Parameters<typeof this._registerMethod>[2]): ModuleBuilder<TCtx, TPrefix, RouteMap> {\n return this._registerMethod('POST', path, defOrHandler)\n }\n\n put<\n TBody extends ZodTypeAny = never,\n TParams extends ZodTypeAny = never,\n TQuery extends ZodTypeAny = never,\n TResponse extends ZodTypeAny = never,\n TPath extends string = string,\n >(path: TPath, def: {\n body?: TBody\n params?: TParams\n query?: TQuery\n response?: TResponse\n docs?: RouteDocs\n guard?: Guard<TCtx> | false\n handler: (ctx: TCtx & { body: z.infer<TBody>; params: z.infer<TParams>; query: z.infer<TQuery> }) => Response | Promise<Response>\n }): ModuleBuilder<TCtx, TPrefix, TRoutes & Record<`PUT ${TPrefix}${TPath}`, { body: TBody; params: TParams; query: TQuery; response: TResponse; _prefix: TPrefix }>>\n put(path: string, handler: RouteHandler<TCtx> | ((ctx: TCtx) => Response | Promise<Response>)): ModuleBuilder<TCtx, TPrefix, TRoutes>\n put(path: string, defOrHandler: Parameters<typeof this._registerMethod>[2]): ModuleBuilder<TCtx, TPrefix, RouteMap> {\n return this._registerMethod('PUT', path, defOrHandler)\n }\n\n patch<\n TBody extends ZodTypeAny = never,\n TParams extends ZodTypeAny = never,\n TQuery extends ZodTypeAny = never,\n TResponse extends ZodTypeAny = never,\n TPath extends string = string,\n >(path: TPath, def: {\n body?: TBody\n params?: TParams\n query?: TQuery\n response?: TResponse\n docs?: RouteDocs\n guard?: Guard<TCtx> | false\n handler: (ctx: TCtx & { body: z.infer<TBody>; params: z.infer<TParams>; query: z.infer<TQuery> }) => Response | Promise<Response>\n }): ModuleBuilder<TCtx, TPrefix, TRoutes & Record<`PATCH ${TPrefix}${TPath}`, { body: TBody; params: TParams; query: TQuery; response: TResponse; _prefix: TPrefix }>>\n patch(path: string, handler: RouteHandler<TCtx> | ((ctx: TCtx) => Response | Promise<Response>)): ModuleBuilder<TCtx, TPrefix, TRoutes>\n patch(path: string, defOrHandler: Parameters<typeof this._registerMethod>[2]): ModuleBuilder<TCtx, TPrefix, RouteMap> {\n return this._registerMethod('PATCH', path, defOrHandler)\n }\n\n delete<\n TBody extends ZodTypeAny = never,\n TParams extends ZodTypeAny = never,\n TQuery extends ZodTypeAny = never,\n TResponse extends ZodTypeAny = never,\n TPath extends string = string,\n >(path: TPath, def: {\n body?: TBody\n params?: TParams\n query?: TQuery\n response?: TResponse\n docs?: RouteDocs\n guard?: Guard<TCtx> | false\n handler: (ctx: TCtx & { body: z.infer<TBody>; params: z.infer<TParams>; query: z.infer<TQuery> }) => Response | Promise<Response>\n }): ModuleBuilder<TCtx, TPrefix, TRoutes & Record<`DELETE ${TPrefix}${TPath}`, { body: TBody; params: TParams; query: TQuery; response: TResponse; _prefix: TPrefix }>>\n delete(path: string, handler: RouteHandler<TCtx> | ((ctx: TCtx) => Response | Promise<Response>)): ModuleBuilder<TCtx, TPrefix, TRoutes>\n delete(path: string, defOrHandler: Parameters<typeof this._registerMethod>[2]): ModuleBuilder<TCtx, TPrefix, RouteMap> {\n return this._registerMethod('DELETE', path, defOrHandler)\n }\n\n onError(handler: ErrorHandler<TCtx>): ModuleBuilder<TCtx, TPrefix, TRoutes> {\n return this.clone({ onError: handler as ErrorHandler<any> })\n }\n\n build(): VelnModule & { readonly _routes: TRoutes; readonly _prefix: TPrefix } {\n const s = this._state\n const mod: VelnModule = {\n prefix: s.prefix,\n routes: [...s.routes],\n wsRoutes: [...s.wsRoutes],\n hookDeclarations: [...s.hookDeclarations],\n auditDeclarations: [...s.auditDeclarations],\n serviceDeclarations: [...s.serviceDeclarations],\n plugins: [...s.plugins],\n guards: [...s.guards],\n onRequestHooks: [...s.onRequestHooks],\n onBeforeHandleHooks: [...s.onBeforeHandleHooks],\n onResponseHooks: [...s.onResponseHooks],\n onError: s.onError,\n eventHandlerDefs: [...s.eventHandlerDefs],\n cronDefs: [...s.cronDefs],\n visibility: s.visibility,\n meta: s.meta,\n options: s.options,\n }\n // Phantom cast — _routes and _prefix don't exist at runtime,\n // they only carry type information for createProxyClient / .module()\n return mod as VelnModule & { readonly _routes: TRoutes; readonly _prefix: TPrefix }\n }\n}\n\n/**\n * defineModule — groups routes, guards, services, and cron jobs under a shared prefix.\n *\n * @param prefix URL prefix for all routes in this module (e.g. `'/users'`).\n *\n * Supply a `TCtx` generic to get typed handlers without casts:\n * `defineModule<BaseCtx & { user: AuthUser }>('/admin')`\n *\n * @example\n * const usersModule = defineModule('/users')\n * .get('/', (ctx) => ctx.json([]))\n * .build()\n * app.register(usersModule)\n */\nexport function defineModule<TCtx extends BaseCtx = BaseCtx, TPrefix extends string = string>(\n prefix: TPrefix,\n): ModuleBuilder<TCtx, TPrefix, Record<never, never>> {\n // ModuleBuilder.create() always returns ModuleBuilder<BaseCtx, ...>.\n // We cast to the caller-supplied TCtx here — this is the only cast needed,\n // and it's in the framework internals, not user code.\n return ModuleBuilder.create(prefix) as unknown as ModuleBuilder<TCtx, TPrefix, Record<never, never>>\n}\n","import type { BaseCtx, Logger, BaseOptions } from './types'\nimport type { VelnAdapter } from '../adapter/types'\nimport type { HookExecutor } from '../hooks/executor'\nimport type { EventBus } from '../events/index'\nimport type { BoundVelnDB } from '../db/index'\nimport type { VelnModule } from './module'\nimport { createMinimalLogger } from './logger'\nimport { type AdapterConfig, resolveAdapter as resolveAdapterConfig } from '../adapter/resolve'\n\n/** A single navigation item contributed by a plugin via .nav(). */\nexport interface NavItem {\n label: string\n route: string\n icon?: string\n order?: number\n children?: NavItem[]\n}\n\n// ── ModulesInput — Option A (Spec 04) ────────────────────────────────────────\n//\n// .modules() now accepts either a plain array OR a factory function.\n//\n// Factory form: .modules((ctx: TCtx) => [myModule])\n//\n// Purpose: the factory's argument type gives TypeScript the correct ctx for\n// modules defined inside it — purely a compile-time convenience.\n//\n// IMPORTANT: the factory is called at plugin-build time with a dummy empty\n// object. The factory's argument is NEVER used for actual request handling —\n// it exists only to let TypeScript infer the correct ctx type for the modules\n// returned. The resulting VelnModule[] is extracted once and stored as a plain\n// array, identical to the non-factory case.\nexport type ModulesInput<TCtx> = VelnModule[] | ((ctx: TCtx) => VelnModule[])\n\nexport interface Plugin<TCtx, TAdd extends object> {\n name: string\n /**\n * Optional list of plugin names that must be registered before this plugin.\n * app.plugin() validates this at registration time and throws PLUGIN_MISSING_DEP\n * if a required plugin is not yet registered.\n *\n * Example: eventBusPlugin sets requires: ['db'] to enforce registration order.\n */\n requires?: string[]\n /**\n * Optional list of modules this plugin contributes.\n * app.plugin() calls app.register() on each entry automatically.\n *\n * Can also be set to a factory function for typed ctx inference (Option A, Spec 04).\n * The factory is called once with a dummy ctx to extract the module list —\n * it is NEVER called at request time.\n */\n modules?: VelnModule[]\n /**\n * Optional permission gate for all routes contributed via .modules().\n * app.plugin() checks ctx.user before running plugin.request() for those routes.\n * User must have at least one of the listed permissions — checked via AuthAdapter.hasPermission().\n * No user → 401. User without any matching permission → 403.\n */\n permissions?: string[]\n /**\n * Optional nav items contributed by this plugin.\n * GET /nav returns these filtered by the plugin's permissions for the current user.\n */\n nav?: NavItem[]\n // install receives the app's HookExecutor so plugins can register hooks into it.\n // Most plugins ignore it — only dbPlugin uses it to wire itself into the app.\n install?: (hooks: HookExecutor) => Promise<void> | void\n request: (ctx: TCtx) => Promise<TCtx & TAdd> | (TCtx & TAdd)\n teardown?: () => Promise<void> | void\n}\n\n// ── PluginBuilder — fluent builder for definePlugin() ─────────────────────────\n\nexport class PluginBuilder<TAdd extends object> {\n private _options: BaseOptions = {}\n private _requires: string[] = []\n private _modules: VelnModule[] = []\n private _permissions: string[] = []\n private _nav: NavItem[] = []\n\n constructor(private readonly _name: string) {}\n\n options(opts: BaseOptions): this {\n this._options = opts\n return this\n }\n\n requires(deps: string[]): this {\n this._requires = deps\n return this\n }\n\n // Option A (Spec 04): accepts a plain array OR a factory function.\n //\n // Factory form: .modules((ctx: BaseCtx & TAdd) => [myModule])\n //\n // The factory receives a typed ctx so TypeScript can infer the correct ctx\n // type for handlers defined inside the returned modules. This is a pure\n // compile-time feature — the factory is called ONCE here (at plugin-build\n // time) with a dummy empty object to extract the VelnModule[]. The dummy\n // argument is NEVER used for actual request handling and carries no real data.\n // The result is stored as a plain VelnModule[], identical to the array form.\n modules(input: ModulesInput<BaseCtx & TAdd>): this {\n if (typeof input === 'function') {\n // Call factory with a dummy ctx to extract the module array.\n // IMPORTANT: The factory's argument is never used at request time —\n // its sole purpose is to give TypeScript the correct ctx type.\n // We cast the empty object so the runtime call succeeds without `any`.\n this._modules = input({} as BaseCtx & TAdd)\n } else {\n this._modules = input\n }\n return this\n }\n\n permission(perm: string | string[]): this {\n this._permissions = Array.isArray(perm) ? perm : [perm]\n return this\n }\n\n nav(items: NavItem | NavItem[]): this {\n this._nav = Array.isArray(items) ? items : [items]\n return this\n }\n\n // Shorthand: only need to provide a request() factory. Returns Plugin directly (not a factory fn).\n extend(\n fn: (ctx: BaseCtx) => Promise<TAdd> | TAdd,\n ): Plugin<BaseCtx, TAdd> {\n const logger = createMinimalLogger(`plugin:${this._name}`, this._options.log)\n const name = this._name\n const requires = this._requires.length > 0 ? this._requires : undefined\n const modules = this._modules.length > 0 ? this._modules : undefined\n const permissions = this._permissions.length > 0 ? this._permissions : undefined\n const nav = this._nav.length > 0 ? this._nav : undefined\n return {\n name,\n requires,\n modules,\n permissions,\n nav,\n install: undefined,\n request: async (ctx) => {\n logger.debug('request', { plugin: name })\n return { ...ctx, ...await fn(ctx) }\n },\n teardown: undefined,\n }\n }\n\n // Full control — install + request + teardown.\n build(def: {\n install?: (hooks: HookExecutor) => Promise<void> | void\n request: (ctx: BaseCtx) => Promise<TAdd> | TAdd\n teardown?: () => Promise<void> | void\n }): Plugin<BaseCtx, TAdd> {\n const logger = createMinimalLogger(`plugin:${this._name}`, this._options.log)\n const name = this._name\n const requires = this._requires.length > 0 ? this._requires : undefined\n const modules = this._modules.length > 0 ? this._modules : undefined\n const permissions = this._permissions.length > 0 ? this._permissions : undefined\n const nav = this._nav.length > 0 ? this._nav : undefined\n return {\n name,\n requires,\n modules,\n permissions,\n nav,\n install: def.install,\n request: async (ctx) => {\n logger.debug('request', { plugin: name })\n return { ...ctx, ...await def.request(ctx) }\n },\n teardown: def.teardown,\n }\n }\n}\n\n/**\n * definePlugin — creates a named plugin that extends the request context.\n *\n * @param name Unique plugin name. Used for deduplication — a plugin with the same\n * name is installed at most once per app instance.\n *\n * @example\n * const tenantPlugin = definePlugin<{ tenantId: string }>('tenant')\n * .request((ctx) => ({ tenantId: ctx.req.headers.get('x-tenant-id') ?? 'default' }))\n * .build()\n * app.plugin(tenantPlugin)\n */\nexport function definePlugin<TAdd extends object = object>(\n name: string,\n): PluginBuilder<TAdd> {\n return new PluginBuilder<TAdd>(name)\n}\n\n// createPlugin — factory helper that merges TAdd into ctx internally.\n// The user-supplied request() only needs to return TAdd (not { ...ctx, ...TAdd }).\n// The framework spreads ctx internally so user code stays clean.\n// @deprecated Use definePlugin() for the fluent builder API.\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport function createPlugin<TAdd extends object>(\n name: string,\n definition: {\n install?: () => Promise<void> | void\n request: (ctx: BaseCtx) => Promise<TAdd> | TAdd\n teardown?: () => Promise<void> | void\n },\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\n): () => Plugin<any, TAdd> {\n return () => ({\n name,\n install: definition.install ? () => definition.install!() : undefined,\n request: async (ctx) => ({ ...ctx, ...await definition.request(ctx) }),\n teardown: definition.teardown,\n })\n}\n\n// loggerPlugin — adds ctx.logger\n// Generic over TCtx so it composes correctly in a plugin chain that already has other fields.\nexport function loggerPlugin<TCtx extends BaseCtx>(): Plugin<TCtx, { logger: Logger }> {\n const logger: Logger = {\n info: (msg, ...args) => console.log(`[INFO] ${msg}`, ...args),\n warn: (msg, ...args) => console.warn(`[WARN] ${msg}`, ...args),\n error: (msg, ...args) => console.error(`[ERROR] ${msg}`, ...args),\n debug: (msg, ...args) => console.log(`[DEBUG] ${msg}`, ...args),\n }\n return {\n name: 'logger',\n request: (ctx) => ({ ...ctx, logger }),\n }\n}\n\n// eventBusPlugin — adds ctx.events\n// IMPORTANT: register BEFORE dbPlugin — withCtx(ctx) in dbPlugin snapshots the ctx at\n// request time, so ctx.events must already be present for module hooks to access it.\n//\n// Calling with no argument auto-creates an EventBus. Access it via plugin.bus:\n// const eventsPlugin = eventBusPlugin()\n// app.plugin(eventsPlugin)\n// eventsPlugin.bus.on('user.created', handler)\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport function eventBusPlugin(bus?: EventBus): Plugin<any, { events: EventBus }> & { bus: EventBus } {\n // eslint-disable-next-line @typescript-eslint/no-require-imports\n const resolvedBus: EventBus = bus ?? new (require('../events/index') as typeof import('../events/index')).EventBus()\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const plugin: Plugin<any, { events: EventBus }> & { bus: EventBus } = {\n name: 'eventBus',\n bus: resolvedBus,\n request: (ctx) => ({ ...ctx, events: resolvedBus }),\n }\n return plugin\n}\n\n// ── DbPluginConfig — declarative adapter creation ─────────────────────────────\n\nexport type DbPluginConfig = AdapterConfig | VelnAdapter\n\nexport interface DbLogOptions {\n /** Whether query logging is enabled. Default: false. */\n enabled: boolean\n /** Emit a warning for queries that exceed this threshold in milliseconds. */\n slowQueryMs?: number\n /** Log level used for query logging. Default: 'debug'. */\n level?: 'debug' | 'info' | 'warn'\n /** Custom per-query callback. Receives the full QueryLogEntry for each query. */\n onQuery?: (entry: import('../adapter/types').QueryLogEntry) => void\n}\n\n// dbPlugin — adds ctx.db as a BoundVelnDB scoped to the request ctx.\n// The HookExecutor is NOT created here — it is received from the app via install(hooks).\n// This ensures module hook registrations (app.register()) and DB operations share the same executor.\n// IMPORTANT: register AFTER eventBusPlugin/loggerPlugin — withCtx(ctx) snapshots the full\n// ctx at request time, so ctx.events and ctx.logger must already be on ctx before db binds.\nexport function dbPlugin<TCtx extends BaseCtx>(\n config: DbPluginConfig,\n log?: DbLogOptions,\n): Plugin<TCtx, { db: BoundVelnDB }> {\n // eslint-disable-next-line @typescript-eslint/no-require-imports\n const { VelnDB } = require('../db/index') as typeof import('../db/index')\n let velnDB: InstanceType<typeof import('../db/index').VelnDB> | null = null\n\n // Build a global onQuery handler if logging is enabled.\n // This is set once on the adapter and called for every query across all requests.\n // For per-request handling (slow query logging, query counters), see BoundVelnDB.\n let globalOnQuery: ((entry: import('../adapter/types').QueryLogEntry) => void) | undefined\n if (log?.enabled) {\n const slowMs = log.slowQueryMs\n const level = log.level ?? 'debug'\n const custom = log.onQuery\n globalOnQuery = (entry) => {\n const prefix = `[veln:db] ${entry.type} (${entry.durationMs.toFixed(2)}ms)`\n if (slowMs !== undefined && entry.durationMs >= slowMs) {\n console.warn(`[veln:db] SLOW QUERY (${entry.durationMs.toFixed(2)}ms): ${entry.sql}`)\n } else {\n if (level === 'info') console.log(`${prefix} ${entry.sql}`)\n else if (level === 'warn') console.warn(`${prefix} ${entry.sql}`)\n else console.debug(`${prefix} ${entry.sql}`)\n }\n custom?.(entry)\n }\n } else if (log?.onQuery) {\n // enabled is false but a custom handler was supplied — wire it anyway\n globalOnQuery = log.onQuery\n }\n\n return {\n name: 'db',\n install: (hooks) => {\n const adapter = resolveAdapterConfig(config)\n if (globalOnQuery) adapter.onQuery = globalOnQuery\n hooks.setAdapter(adapter)\n velnDB = new VelnDB(adapter, hooks)\n },\n request: (ctx) => {\n if (!velnDB) throw new Error('[veln] dbPlugin not installed — call app.plugin(dbPlugin(...)) before fetch()')\n // Read the per-request QueryLog injected by fetch() via ctx._queryLog.\n // When N+1 detection is enabled, fetch() creates a QueryLog and attaches it\n // to the base ctx before plugins run. dbPlugin reads it here and passes it\n // to BoundVelnDB so each query increments the log's counters.\n const queryLog = (ctx as unknown as Record<string, unknown>)['_queryLog'] as\n import('../db/index').QueryLog | undefined\n return { ...ctx, db: velnDB.withCtx(ctx, ctx._requestQueue, queryLog) }\n },\n }\n}\n","import type { OnResponseHook } from './types'\nimport { createOnResponse } from './types'\n\n/**\n * CSP preset values for `contentSecurityPolicy`.\n *\n * - `'strict'` — no unsafe-inline; suitable for APIs and security-critical apps.\n * - `'relaxed'` — allows unsafe-inline scripts/styles; suitable for dashboards and SSR (default).\n * - `false` — omits the Content-Security-Policy header entirely.\n * - `string` — passed through as the raw header value.\n */\nexport type CspPreset = 'strict' | 'relaxed' | false | string\n\nexport interface SecureHeadersOptions {\n /** Strict-Transport-Security — default: 'max-age=15552000; includeSubDomains' */\n strictTransportSecurity?: string | false\n /** X-Content-Type-Options — default: 'nosniff' */\n xContentTypeOptions?: string | false\n /** X-Frame-Options — default: 'SAMEORIGIN' */\n xFrameOptions?: string | false\n /** X-XSS-Protection — default: '0' (modern recommendation: rely on CSP instead) */\n xXssProtection?: string | false\n /** Referrer-Policy — default: 'strict-origin-when-cross-origin' */\n referrerPolicy?: string | false\n /** Permissions-Policy — default: 'camera=(), microphone=(), geolocation=()' */\n permissionsPolicy?: string | false\n /**\n * Content-Security-Policy — accepts a preset or a raw header string.\n *\n * - `'relaxed'` (default) — allows unsafe-inline scripts/styles.\n * - `'strict'` — no unsafe-inline; for APIs and security-critical apps.\n * - `false` — omit header entirely.\n * - custom string — used as-is.\n */\n contentSecurityPolicy?: CspPreset\n}\n\nconst CSP_STRICT = \"default-src 'self'; script-src 'self'; style-src 'self'; img-src 'self' data:; font-src 'self'; connect-src 'self'; frame-ancestors 'none'\"\nconst CSP_RELAXED = \"default-src 'self'; script-src 'self' 'unsafe-inline'; style-src 'self' 'unsafe-inline'; img-src 'self' data: https:; font-src 'self' data: https:; connect-src 'self'\"\n\nfunction resolveCsp(value: CspPreset | undefined): string | false {\n if (value === false) return false\n if (value === 'strict') return CSP_STRICT\n if (value === 'relaxed' || value === undefined) return CSP_RELAXED\n return value // custom string\n}\n\nconst DEFAULTS: Record<Exclude<keyof SecureHeadersOptions, 'contentSecurityPolicy'>, string> = {\n strictTransportSecurity: 'max-age=15552000; includeSubDomains',\n xContentTypeOptions: 'nosniff',\n xFrameOptions: 'SAMEORIGIN',\n xXssProtection: '0',\n referrerPolicy: 'strict-origin-when-cross-origin',\n permissionsPolicy: 'camera=(), microphone=(), geolocation=()',\n}\n\nconst HEADER_NAMES: Record<Exclude<keyof SecureHeadersOptions, 'contentSecurityPolicy'>, string> = {\n strictTransportSecurity: 'Strict-Transport-Security',\n xContentTypeOptions: 'X-Content-Type-Options',\n xFrameOptions: 'X-Frame-Options',\n xXssProtection: 'X-XSS-Protection',\n referrerPolicy: 'Referrer-Policy',\n permissionsPolicy: 'Permissions-Policy',\n}\n\n/**\n * secureHeadersPlugin — adds security response headers to every response.\n *\n * Returns an OnResponseHook — pass it to app.onResponse():\n * app.onResponse(secureHeadersPlugin())\n * app.onResponse(secureHeadersPlugin({ xFrameOptions: 'DENY', contentSecurityPolicy: 'strict' }))\n *\n * Each option defaults to a secure value. Pass `false` to omit that header entirely.\n * Pass a custom string to override the default value.\n * `contentSecurityPolicy` also accepts `'strict'` (no unsafe-inline) or `'relaxed'` (default).\n *\n * Header resolution runs once at call time — zero overhead per request.\n */\nexport function secureHeadersPlugin(options: SecureHeadersOptions = {}): OnResponseHook {\n // Resolve final header list at plugin-creation time — not per request\n const resolved: Array<[string, string]> = []\n\n // Non-CSP headers\n for (const key of Object.keys(DEFAULTS) as Array<Exclude<keyof SecureHeadersOptions, 'contentSecurityPolicy'>>) {\n const val = key in options ? options[key] : DEFAULTS[key]\n if (val !== false && val !== undefined) {\n resolved.push([HEADER_NAMES[key], val as string])\n }\n }\n\n // CSP — preset-aware resolution\n const cspVal = resolveCsp(options.contentSecurityPolicy)\n if (cspVal !== false) {\n resolved.push(['Content-Security-Policy', cspVal])\n }\n\n return createOnResponse((_ctx, res) => {\n const headers = new Headers(res.headers)\n for (const [name, value] of resolved) {\n // Don't overwrite headers already set by the route handler —\n // allows per-route CSP overrides (e.g. scalarPlugin loosens CSP for /docs)\n if (!headers.has(name)) {\n headers.set(name, value)\n }\n }\n return new Response(res.body, {\n status: res.status,\n statusText: res.statusText,\n headers,\n })\n })\n}\n","import type { BaseCtx, OnRequestHook } from './types'\nimport { createOnRequest } from './types'\n\n// ── Store Interface ────────────────────────────────────────────────────────────\n\nexport interface RateLimitStore {\n /**\n * Increment the counter for `key` within the given window.\n * Returns the new count and the timestamp (ms) when the window resets.\n * If the key is new or expired, the window starts fresh from now.\n */\n increment(key: string, windowMs: number): Promise<{ count: number; resetAt: number }>\n /** Reset the counter for `key` immediately. */\n reset(key: string): Promise<void>\n}\n\n// ── In-Memory Store ────────────────────────────────────────────────────────────\n\ninterface Entry {\n count: number\n resetAt: number\n}\n\nexport class InMemoryStore implements RateLimitStore {\n private readonly _map = new Map<string, Entry>()\n\n // Probabilistic sweep: 1-in-N chance on every increment() call.\n // Amortizes cleanup cost across all requests — no manual calls, no Interval,\n // no process-keep-alive issues. At 1000 req/s with N=100, ~10 sweeps/s.\n private readonly _sweepEvery: number\n\n // Hard cap on map size — prevents memory exhaustion under unique-IP DoS attacks.\n // When the cap is reached, the oldest 20% of entries are evicted before inserting\n // a new key. Only new-key inserts check the cap; increments on existing keys are free.\n private readonly _maxEntries: number\n\n constructor(sweepEvery = 100, maxEntries = 100_000) {\n this._sweepEvery = sweepEvery\n this._maxEntries = maxEntries\n }\n\n async increment(key: string, windowMs: number): Promise<{ count: number; resetAt: number }> {\n const now = Date.now()\n\n // Probabilistic sweep — runs on ~1/sweepEvery calls\n if (Math.random() * this._sweepEvery < 1) {\n this._sweep(now)\n }\n\n const existing = this._map.get(key)\n\n if (existing && now < existing.resetAt) {\n existing.count += 1\n return { count: existing.count, resetAt: existing.resetAt }\n }\n\n // New window — enforce max-entries cap before inserting\n if (this._map.size >= this._maxEntries) {\n this._evictOldest(Math.max(1, Math.floor(this._maxEntries * 0.2)))\n }\n\n const entry: Entry = { count: 1, resetAt: now + windowMs }\n this._map.set(key, entry)\n return { count: 1, resetAt: entry.resetAt }\n }\n\n async reset(key: string): Promise<void> {\n this._map.delete(key)\n }\n\n /** Evict all expired entries. Called automatically on a probabilistic basis\n * during increment(). Can also be called manually for eager cleanup. */\n cleanup(): void {\n this._sweep(Date.now())\n }\n\n private _sweep(now: number): void {\n for (const [key, entry] of this._map) {\n if (now >= entry.resetAt) this._map.delete(key)\n }\n }\n\n // Evict the `count` entries with the smallest resetAt (oldest windows).\n private _evictOldest(count: number): void {\n const sorted = [...this._map.entries()].sort((a, b) => a[1].resetAt - b[1].resetAt)\n for (let i = 0; i < count && i < sorted.length; i++) {\n this._map.delete(sorted[i]![0])\n }\n }\n}\n\n// ── Options ────────────────────────────────────────────────────────────────────\n\nexport interface RateLimitOptions {\n /** Maximum number of requests allowed per window. */\n max: number\n /** Window duration in milliseconds. */\n windowMs: number\n /** Store implementation. Defaults to InMemoryStore. */\n store?: RateLimitStore\n /**\n * Extracts the rate-limit key from a request context.\n * When not specified, uses the default resolver which respects `trustProxy`.\n */\n keyResolver?: (ctx: BaseCtx) => string\n /** Response message when limit is exceeded. Defaults to 'Too many requests'. */\n message?: string\n /**\n * When true, the default keyResolver trusts the X-Forwarded-For header as the\n * real client IP. Only enable this if you are behind a trusted reverse proxy.\n * Default: false\n *\n * Without trustProxy, the default resolver uses x-real-ip or 'unknown'.\n *\n * trustProxy can also be an object for advanced configuration:\n * { strict: true } — returns 400 when the expected proxy header is missing,\n * instead of falling back to 'unknown'. Use this in security-critical deployments\n * where a missing header indicates a misconfigured proxy or direct client access.\n */\n trustProxy?: boolean | { strict: boolean }\n}\n\n// ── Plugin ─────────────────────────────────────────────────────────────────────\n\n/**\n * rateLimitPlugin — sliding-window rate limiter.\n *\n * Returns an OnRequestHook — pass it to app.onRequest() or module.onRequest():\n * app.onRequest(rateLimitPlugin({ max: 100, windowMs: 60_000 }))\n *\n * When the limit is exceeded, returns a 429 response with:\n * - Retry-After: seconds until the window resets\n * - X-RateLimit-Limit: max\n * - X-RateLimit-Remaining: 0\n * - X-RateLimit-Reset: unix timestamp (seconds)\n *\n * Under the limit, the hook returns void — request continues normally.\n */\n// ── Security analysis: X-Forwarded-For header handling ───────────────────────\n//\n// VULNERABILITY (if using first entry): A client can spoof X-Forwarded-For by\n// sending \"FAKE_IP, real_proxy_ip\". If the rate limiter reads the FIRST entry,\n// the attacker controls their own bucket key and bypasses rate limiting entirely.\n//\n// CORRECT behavior: read the LAST entry — set by the outermost trusted proxy,\n// which the client cannot control. The client can prepend values to the list\n// but cannot forge the final entry added by the proxy.\n//\n// Example: client sends X-Forwarded-For: 10.0.0.1\n// proxy appends X-Forwarded-For: 10.0.0.1, 203.0.113.5\n// → correct client IP = last entry = 203.0.113.5\n//\n// MISSING HEADER behavior (trustProxy: true, no X-Forwarded-For):\n// - Default (option A): falls back to 'unknown' + emits a one-time warning.\n// All requests without the header share the same bucket — DoS vector if\n// the proxy is misconfigured. The warning helps operators detect this.\n// - Strict (option B): returns 400 Bad Request immediately. Use this in\n// security-critical deployments where a missing header means a broken proxy.\n\nexport function rateLimitPlugin(options: RateLimitOptions): OnRequestHook {\n const { max, windowMs, message = 'Too many requests' } = options\n const store: RateLimitStore = options.store ?? new InMemoryStore()\n\n const trustProxy = options.trustProxy\n const isStrict = typeof trustProxy === 'object' && trustProxy.strict === true\n const doTrust = trustProxy === true || isStrict\n\n // Pitfall warning: no keyResolver + no trustProxy → default falls back to\n // x-real-ip and then 'unknown'. Behind a proxy that doesn't set x-real-ip,\n // every request maps to the same key — the entire app shares one rate-limit\n // bucket. This is almost certainly unintentional.\n if (!options.keyResolver && !trustProxy) {\n console.warn(\n '[veln:rateLimit] Warning: no keyResolver or trustProxy provided. ' +\n \"If your app runs behind a reverse proxy, the default key resolver may fall back to 'unknown', \" +\n 'causing all clients to share a single rate-limit bucket. ' +\n 'Set trustProxy: true (if behind a trusted proxy) or provide a custom keyResolver.',\n )\n }\n\n // Track whether the missing-header warning has been emitted — once per plugin instance.\n let _missingHeaderWarned = false\n\n const defaultKeyResolver = (ctx: BaseCtx): string | Response => {\n if (doTrust) {\n const forwardedFor = ctx.req.headers.get('x-forwarded-for')\n if (forwardedFor) {\n // Use the LAST entry — set by the outermost trusted proxy, not forgeable by client.\n // Client can prepend fake IPs but cannot control the final proxy-appended entry.\n const parts = forwardedFor.split(',')\n const lastIp = parts[parts.length - 1]?.trim()\n if (lastIp) return lastIp\n }\n\n // Header missing — proxy may be misconfigured\n if (isStrict) {\n // Strict mode: reject the request — a missing header is a hard error\n return new Response(\n JSON.stringify({ error: 'Bad Request', code: 'MISSING_PROXY_HEADER', message: 'X-Forwarded-For header is required' }),\n { status: 400, headers: { 'Content-Type': 'application/json' } },\n )\n }\n\n // Option A: warn once, fall back to 'unknown'\n if (!_missingHeaderWarned) {\n _missingHeaderWarned = true\n console.warn(\n '[veln:rateLimit] trustProxy is enabled but no X-Forwarded-For header found. ' +\n 'All requests may be bucketed under the same IP. ' +\n 'Ensure your reverse proxy sets X-Forwarded-For correctly.',\n )\n }\n }\n\n // Without trustProxy, use x-real-ip or fall back to 'unknown'\n return ctx.req.headers.get('x-real-ip') ?? 'unknown'\n }\n\n const keyResolver = options.keyResolver\n ? (ctx: BaseCtx): string | Response => options.keyResolver!(ctx)\n : defaultKeyResolver\n\n return createOnRequest(async (ctx) => {\n const keyOrResponse = keyResolver(ctx)\n\n // Strict mode returns a Response directly when the proxy header is missing\n if (keyOrResponse instanceof Response) return keyOrResponse\n\n const key = keyOrResponse\n const { count, resetAt } = await store.increment(key, windowMs)\n\n const remaining = Math.max(0, max - count)\n const resetSec = Math.ceil(resetAt / 1000)\n\n if (count > max) {\n const retryAfter = Math.ceil((resetAt - Date.now()) / 1000)\n return new Response(\n JSON.stringify({ error: 'Too Many Requests', code: 'RATE_LIMIT_EXCEEDED', message }),\n {\n status: 429,\n headers: {\n 'Content-Type': 'application/json',\n 'Retry-After': String(retryAfter),\n 'X-RateLimit-Limit': String(max),\n 'X-RateLimit-Remaining': '0',\n 'X-RateLimit-Reset': String(resetSec),\n },\n },\n )\n }\n\n // Under limit — attach informational headers via response hook is not possible\n // from onRequest. We return void and let the request continue.\n // RateLimit info headers (Limit/Remaining/Reset) are intentionally omitted on\n // the success path to avoid leaking rate-limit state to clients by default.\n // Advanced users can add them via a custom onResponse hook if needed.\n void remaining\n void resetSec\n })\n}\n","import type { BaseCtx, OnRequestHook, OnResponseHook } from './types'\nimport { createOnRequest, createOnResponse } from './types'\n\n// ── Constants ──────────────────────────────────────────────────────────────────\n\n// Methods that mutate state — CSRF validation is enforced for these.\nconst STATE_CHANGING_METHODS = new Set(['POST', 'PUT', 'PATCH', 'DELETE'])\n\n// ── Constant-time string comparison ───────────────────────────────────────────\n\n/**\n * Constant-time string comparison to prevent timing attacks.\n * Returns false immediately on length mismatch (length is not secret).\n * XORs all character codes and accumulates into a single result so the\n * comparison time is proportional to the string length, not the first mismatch.\n */\nexport function timingSafeEqual(a: string, b: string): boolean {\n if (a.length !== b.length) return false\n let result = 0\n for (let i = 0; i < a.length; i++) {\n result |= a.charCodeAt(i) ^ b.charCodeAt(i)\n }\n return result === 0\n}\n\n// ── Token generation ───────────────────────────────────────────────────────────\n\nfunction generateToken(): string {\n // crypto is available globally in Bun, Node 19+, and all modern browsers.\n const bytes = new Uint8Array(32)\n crypto.getRandomValues(bytes)\n return Array.from(bytes, (b) => b.toString(16).padStart(2, '0')).join('')\n}\n\n// ── Options ────────────────────────────────────────────────────────────────────\n\nexport interface CsrfOptions {\n /** Cookie name that holds the CSRF token. Default: 'csrf_token' */\n cookieName?: string\n /** Request header that must carry the token on state-changing requests. Default: 'x-csrf-token' */\n headerName?: string\n /** Cookie Max-Age in seconds. Default: 86400 (24h) */\n maxAge?: number\n /** Restrict cookie to HTTPS. Default: true (set false for local development) */\n secure?: boolean\n}\n\n// ── Plugin return type ─────────────────────────────────────────────────────────\n\nexport interface CsrfPlugin {\n /**\n * Register on app.onRequest() or module.onRequest().\n * Validates the CSRF token on state-changing methods (POST/PUT/PATCH/DELETE).\n * Returns a 403 response on mismatch — short-circuits the request lifecycle.\n */\n onRequest: OnRequestHook\n /**\n * Register on app.onResponse() or module.onResponse().\n * Sets a new CSRF token cookie on responses to safe methods (GET/HEAD/OPTIONS)\n * when no valid token cookie exists yet.\n */\n onResponse: OnResponseHook\n}\n\n/**\n * csrfPlugin — Double-Submit Cookie pattern. Stateless, no store required.\n *\n * Usage:\n * const csrf = csrfPlugin()\n * app.onRequest(csrf.onRequest)\n * app.onResponse(csrf.onResponse)\n *\n * How it works:\n * 1. On GET/HEAD/OPTIONS — onResponse sets a readable cookie (httpOnly: false)\n * so the client-side JS can read the token.\n * 2. On POST/PUT/PATCH/DELETE — onRequest reads the cookie value and compares\n * it to the x-csrf-token request header. Mismatch or missing → 403.\n *\n * The Double-Submit Cookie pattern is stateless: the server never stores tokens.\n * Security relies on the same-origin policy: a cross-origin attacker can read\n * neither the cookie nor the custom header value.\n */\nexport function csrfPlugin(options: CsrfOptions = {}): CsrfPlugin {\n const cookieName = options.cookieName ?? 'csrf_token'\n const headerName = options.headerName ?? 'x-csrf-token'\n const maxAge = options.maxAge ?? 86_400\n const secure = options.secure ?? true\n\n const onRequest: OnRequestHook = createOnRequest((ctx: BaseCtx) => {\n const method = ctx.req.method.toUpperCase()\n if (!STATE_CHANGING_METHODS.has(method)) return\n\n const cookieToken = ctx.cookie.get(cookieName)\n const headerToken = ctx.req.headers.get(headerName)\n\n if (!cookieToken || !headerToken || !timingSafeEqual(cookieToken, headerToken)) {\n return new Response(\n JSON.stringify({ error: 'Forbidden', code: 'CSRF_INVALID', message: 'CSRF token mismatch' }),\n {\n status: 403,\n headers: { 'Content-Type': 'application/json' },\n },\n )\n }\n })\n\n const onResponse: OnResponseHook = createOnResponse((ctx: BaseCtx, res: Response) => {\n const method = ctx.req.method.toUpperCase()\n // Only issue tokens on safe methods — no point issuing a fresh token\n // on a request that was just blocked by onRequest.\n if (STATE_CHANGING_METHODS.has(method)) return\n\n // Don't overwrite a valid existing token — avoids invalidating in-flight requests.\n const existing = ctx.cookie.get(cookieName)\n if (existing) return\n\n // Set a new token — httpOnly: false so client-side JS can read it.\n ctx.cookie.set(cookieName, generateToken(), {\n httpOnly: false,\n sameSite: 'Strict',\n maxAge,\n secure,\n path: '/',\n })\n\n // ctx.cookie._pending() is flushed into the response by the framework\n // after onResponse hooks complete — no manual header manipulation needed.\n void res\n })\n\n return { onRequest, onResponse }\n}\n","import type { VelnModule } from './module'\nimport type { Route, BaseCtx } from './types'\nimport { generateOpenApiSpec } from '../openapi/generator'\n\n// ── Options ────────────────────────────────────────────────────────────────────\n\nexport interface ScalarOptions {\n /** Mount path for the Scalar UI. Default: '/scalar' */\n path?: string\n /** API title shown in the Scalar UI. Default: 'Veln API' */\n title?: string\n /** API version shown in the OpenAPI spec. Default: '1.0.0' */\n version?: string\n /** Optional API description shown in the OpenAPI spec info block. Markdown supported. */\n description?: string\n /** Scalar UI theme. Default: 'purple' */\n theme?: string\n /**\n * Cache the generated OpenAPI spec after the first request.\n * Default: false — spec is regenerated on every request (safe for development).\n * Set to true in production to avoid repeated traversal of app.routes.\n */\n cache?: boolean\n}\n\n// ── App reference — minimal shape needed at runtime ───────────────────────────\n\ninterface AppRef {\n routes: Route<unknown>[]\n}\n\n// ── HTML template ──────────────────────────────────────────────────────────────\n\nfunction renderHtml(specJson: string, title: string, theme: string, jsonUrl: string): string {\n return `<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n <meta charset=\"UTF-8\" />\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\" />\n <title>${title}</title>\n</head>\n<body>\n <script id=\"api-reference\" type=\"application/json\">${specJson}</script>\n <script>\n window.__SCALAR_CONFIG__ = { theme: '${theme}' };\n </script>\n <script src=\"https://cdn.jsdelivr.net/npm/@scalar/api-reference\"></script>\n</body>\n</html>`\n}\n\n// ── Plugin factory ─────────────────────────────────────────────────────────────\n\n/**\n * scalarPlugin — mounts a Scalar API reference UI and an OpenAPI JSON endpoint.\n *\n * Usage:\n * app.register(scalarPlugin(app))\n * app.register(scalarPlugin(app, { path: '/docs', title: 'My API', theme: 'blue' }))\n *\n * Registers two routes (both hidden from the OpenAPI spec itself):\n * GET {path} → Scalar UI (HTML, CDN-loaded)\n * GET {path}/openapi.json → Raw OpenAPI 3.1 JSON\n *\n * The app reference is captured by closure so the spec always reflects\n * the current route list at request time — including late-registered modules.\n */\nexport function scalarPlugin(app: AppRef, options: ScalarOptions = {}): VelnModule {\n const mountPath = options.path ?? '/scalar'\n const title = options.title ?? 'Veln API'\n const version = options.version ?? '1.0.0'\n const description = options.description ?? undefined\n const theme = options.theme ?? 'purple'\n const useCache = options.cache ?? false\n const jsonPath = `${mountPath}/openapi.json`\n\n // Cache slot — null until first request when cache: true\n let cachedSpec: ReturnType<typeof generateOpenApiSpec> | null = null\n\n function getSpec(): ReturnType<typeof generateOpenApiSpec> {\n if (useCache) {\n if (!cachedSpec) cachedSpec = generateOpenApiSpec(app.routes, { title, version, description })\n return cachedSpec\n }\n return generateOpenApiSpec(app.routes, { title, version, description })\n }\n\n const jsonRoute: Route<BaseCtx> = {\n method: 'GET',\n path: jsonPath,\n handler: {\n handler: (_ctx) => Response.json(getSpec()),\n },\n guards: [],\n visibility: 'hidden',\n }\n\n const uiRoute: Route<BaseCtx> = {\n method: 'GET',\n path: mountPath,\n handler: {\n handler: (ctx) => {\n const spec = getSpec()\n const specJson = JSON.stringify(spec)\n const html = renderHtml(specJson, title, theme, jsonPath)\n const res = ctx.html(html)\n // Scalar UI requires inline scripts, cdn.jsdelivr.net, proxy.scalar.com,\n // and Google Fonts — override the strict CSP set by secureHeadersPlugin.\n res.headers.set(\n 'Content-Security-Policy',\n [\n \"default-src 'self'\",\n \"script-src 'unsafe-inline' https://cdn.jsdelivr.net\",\n \"style-src 'unsafe-inline' https://cdn.jsdelivr.net https://fonts.googleapis.com\",\n \"font-src *\", // Scalar bundles / loads fonts from varying CDN origins\n \"connect-src 'self' https://proxy.scalar.com https://cdn.jsdelivr.net\",\n \"img-src 'self' data: blob: https://cdn.jsdelivr.net\",\n \"worker-src blob:\",\n ].join('; '),\n )\n return res\n },\n },\n guards: [],\n visibility: 'hidden',\n }\n\n const mod: VelnModule = {\n prefix: '',\n routes: [jsonRoute, uiRoute],\n wsRoutes: [],\n hookDeclarations: [],\n auditDeclarations: [],\n serviceDeclarations: [],\n plugins: [],\n guards: [],\n onRequestHooks: [],\n onBeforeHandleHooks: [],\n onResponseHooks: [],\n onError: undefined,\n eventHandlerDefs: [],\n cronDefs: [],\n visibility: 'hidden',\n meta: { tag: 'scalar', description: 'Scalar API Reference' },\n }\n\n return mod\n}\n","import type { OnRequestHook } from './types'\nimport { createOnRequest } from './types'\n\nexport interface BodySizeLimitOptions {\n /**\n * Maximum allowed body size in bytes.\n * Default: 1_048_576 (1 MB)\n */\n maxSize?: number\n /** Response message when limit is exceeded. Default: 'Payload too large' */\n message?: string\n}\n\n/**\n * bodySizeLimitPlugin — rejects requests whose Content-Length exceeds maxSize.\n *\n * Returns an OnRequestHook — pass it to app.onRequest():\n * app.onRequest(bodySizeLimitPlugin()) // 1MB default\n * app.onRequest(bodySizeLimitPlugin({ maxSize: 512_000 })) // 512KB\n *\n * Checks the Content-Length header only — does not buffer or read the body.\n * Requests without Content-Length are passed through (streaming / chunked).\n * Returns 413 Payload Too Large on violation.\n *\n * @remarks\n * This plugin enforces limits based on the Content-Length header only.\n * Chunked transfer-encoding bypasses this check entirely.\n * For production deployments, configure body size limits at the reverse proxy level:\n * nginx: `client_max_body_size`, Caddy: `request_body { max_size }`.\n */\nexport function bodySizeLimitPlugin(options: BodySizeLimitOptions = {}): OnRequestHook {\n const maxSize = options.maxSize ?? 1_048_576\n const message = options.message ?? 'Payload too large'\n\n return createOnRequest((ctx) => {\n const contentLength = ctx.req.headers.get('content-length')\n if (contentLength === null) return // no length declared — pass through\n\n const bytes = parseInt(contentLength, 10)\n if (isNaN(bytes)) return // unparseable — pass through, let handler deal with it\n\n if (bytes > maxSize) {\n return new Response(\n JSON.stringify({ error: 'Payload Too Large', code: 'PAYLOAD_TOO_LARGE', message }),\n {\n status: 413,\n headers: { 'Content-Type': 'application/json' },\n },\n )\n }\n })\n}\n","import type { OnRequestHook, OnResponseHook } from './types'\nimport { createOnRequest, createOnResponse } from './types'\n\n// ── Options ─────────────────────────────────────────────────────────────────\n\nexport interface CorsOptions {\n /**\n * Allowed origins. Can be:\n * - `'*'` → any origin (not usable with credentials)\n * - `string` → single allowed origin\n * - `string[]` → list of allowed origins (matched against request Origin header)\n * - `(origin: string) => boolean` → custom predicate\n *\n * Default: `'*'`\n */\n origin?: '*' | string | string[] | ((origin: string) => boolean)\n\n /**\n * HTTP methods allowed in CORS requests.\n * Default: `['GET', 'POST', 'PUT', 'PATCH', 'DELETE', 'OPTIONS']`\n */\n methods?: string[]\n\n /**\n * Request headers the client is allowed to send.\n * Default: `['Content-Type', 'Authorization', 'x-csrf-token']`\n */\n allowHeaders?: string[]\n\n /**\n * Response headers that the browser may expose to the client-side script.\n * Default: `[]` (none exposed beyond the CORS-safelisted headers)\n */\n exposeHeaders?: string[]\n\n /**\n * Whether cross-origin requests may include credentials (cookies, auth headers).\n * When true, `origin` must not be `'*'`.\n * Default: `false`\n */\n credentials?: boolean\n\n /**\n * How long (in seconds) the preflight result may be cached.\n * Default: `86400` (24h)\n */\n maxAge?: number\n}\n\n// ── Plugin return type ───────────────────────────────────────────────────────\n\nexport interface CorsPlugin {\n /**\n * Register on `app.onRequest()`.\n * Handles OPTIONS preflight requests — returns a 204 with CORS headers directly,\n * short-circuiting the pipeline (no route handler runs for OPTIONS).\n */\n onRequest: OnRequestHook\n /**\n * Register on `app.onResponse()`.\n * Appends CORS headers to every response.\n */\n onResponse: OnResponseHook\n}\n\n// ── Helpers ──────────────────────────────────────────────────────────────────\n\nfunction resolveOrigin(\n allowedOrigin: CorsOptions['origin'],\n requestOrigin: string | null,\n): string | null {\n if (!requestOrigin) return null\n\n if (allowedOrigin === '*') return '*'\n if (typeof allowedOrigin === 'string') {\n return allowedOrigin === requestOrigin ? requestOrigin : null\n }\n if (Array.isArray(allowedOrigin)) {\n return allowedOrigin.includes(requestOrigin) ? requestOrigin : null\n }\n if (typeof allowedOrigin === 'function') {\n return allowedOrigin(requestOrigin) ? requestOrigin : null\n }\n return null\n}\n\n// ── Plugin factory ───────────────────────────────────────────────────────────\n\n/**\n * corsPlugin — adds CORS headers to responses and handles preflight OPTIONS requests.\n *\n * Usage:\n * const cors = corsPlugin({ origin: 'https://app.example.com', credentials: true })\n * app.onRequest(cors.onRequest)\n * app.onResponse(cors.onResponse)\n *\n * Preflight (OPTIONS) requests are short-circuited with a 204 — no route handler\n * runs. All other requests receive CORS headers in onResponse.\n */\nexport function corsPlugin(options: CorsOptions = {}): CorsPlugin {\n const allowedOrigin = options.origin ?? '*'\n\n // Validate: wildcard origin cannot be combined with credentials\n if ((allowedOrigin === '*') && options.credentials === true) {\n throw new Error(\n \"CORS: origin: '*' cannot be combined with credentials: true. Use a specific origin instead.\",\n )\n }\n const methods = options.methods ?? ['GET', 'POST', 'PUT', 'PATCH', 'DELETE', 'OPTIONS']\n const allowHeaders = options.allowHeaders ?? ['Content-Type', 'Authorization', 'x-csrf-token']\n const exposeHeaders = options.exposeHeaders ?? []\n const credentials = options.credentials ?? false\n const maxAge = options.maxAge ?? 86_400\n\n const methodsStr = methods.join(', ')\n const allowHeadersStr = allowHeaders.join(', ')\n const exposeHeadersStr = exposeHeaders.join(', ')\n const maxAgeStr = String(maxAge)\n\n function buildCorsHeaders(requestOrigin: string | null): Headers {\n const headers = new Headers()\n const resolved = resolveOrigin(allowedOrigin, requestOrigin)\n if (resolved) {\n headers.set('Access-Control-Allow-Origin', resolved)\n // Vary: Origin when not wildcard — required for correct cache behaviour\n if (resolved !== '*') {\n headers.set('Vary', 'Origin')\n }\n }\n if (credentials) {\n headers.set('Access-Control-Allow-Credentials', 'true')\n }\n if (exposeHeadersStr) {\n headers.set('Access-Control-Expose-Headers', exposeHeadersStr)\n }\n return headers\n }\n\n const onRequest: OnRequestHook = createOnRequest((ctx) => {\n if (ctx.req.method.toUpperCase() !== 'OPTIONS') return\n\n const requestOrigin = ctx.req.headers.get('Origin')\n const corsHeaders = buildCorsHeaders(requestOrigin)\n\n // Add preflight-specific headers\n corsHeaders.set('Access-Control-Allow-Methods', methodsStr)\n corsHeaders.set('Access-Control-Allow-Headers', allowHeadersStr)\n corsHeaders.set('Access-Control-Max-Age', maxAgeStr)\n\n return new Response(null, { status: 204, headers: corsHeaders })\n })\n\n const onResponse: OnResponseHook = createOnResponse((ctx, res) => {\n const requestOrigin = ctx.req.headers.get('Origin')\n const corsHeaders = buildCorsHeaders(requestOrigin)\n\n // Don't mutate the original response — rebuild with merged headers\n const merged = new Headers(res.headers)\n for (const [key, value] of corsHeaders) {\n merged.set(key, value)\n }\n\n return new Response(res.body, {\n status: res.status,\n headers: merged,\n })\n })\n\n return { onRequest, onResponse }\n}\n","import type { BaseCtx, OnRequestHook, OnResponseHook } from './types'\nimport { createOnRequest, createOnResponse } from './types'\n\n// ── Options ─────────────────────────────────────────────────────────────────\n\nexport interface RequestIdOptions {\n /**\n * Name of the incoming request header to read an existing ID from.\n * If present and valid, the existing ID is reused (useful for distributed tracing).\n * Default: `'x-request-id'`\n */\n incomingHeader?: string\n\n /**\n * Name of the response header to echo the request ID back to the client.\n * Default: `'x-request-id'`\n */\n responseHeader?: string\n\n /**\n * Custom ID generator. Must return a non-empty string.\n * Default: 16 random hex bytes (128 bits, UUID-compatible entropy)\n */\n generator?: () => string\n}\n\n// ── Plugin return type ───────────────────────────────────────────────────────\n\n/** Context extension added by requestIdPlugin. Available after onRequest. */\nexport interface RequestIdCtx {\n /** Unique ID for this request. Set before any route handler runs. */\n requestId: string\n}\n\nexport interface RequestIdPlugin {\n /**\n * Register on `app.onRequest()`.\n * Assigns `ctx.requestId` — available in all subsequent lifecycle phases.\n */\n onRequest: OnRequestHook<BaseCtx & RequestIdCtx>\n /**\n * Register on `app.onResponse()`.\n * Echoes the request ID back in the response header.\n */\n onResponse: OnResponseHook<BaseCtx & RequestIdCtx>\n}\n\n// ── Helpers ──────────────────────────────────────────────────────────────────\n\nfunction defaultGenerator(): string {\n const bytes = new Uint8Array(16)\n crypto.getRandomValues(bytes)\n return Array.from(bytes, (b) => b.toString(16).padStart(2, '0')).join('')\n}\n\n/** Returns true if the value is a non-empty string containing only safe characters. */\nfunction isSafeId(value: string): boolean {\n return value.length > 0 && value.length <= 128 && /^[\\w\\-]+$/.test(value)\n}\n\n// ── Plugin factory ───────────────────────────────────────────────────────────\n\n/**\n * requestIdPlugin — assigns a unique ID to every request and echoes it back.\n *\n * Usage:\n * const rid = requestIdPlugin()\n * app.onRequest(rid.onRequest)\n * app.onResponse(rid.onResponse)\n *\n * After registration, `ctx.requestId` is available in all handlers, guards,\n * and lifecycle hooks. The ID is echoed back in the `x-request-id` response header.\n *\n * Reuses an existing `x-request-id` header if it passes a safe-characters check,\n * enabling distributed tracing across services.\n */\nexport function requestIdPlugin(options: RequestIdOptions = {}): RequestIdPlugin {\n const incomingHeader = options.incomingHeader ?? 'x-request-id'\n const responseHeader = options.responseHeader ?? 'x-request-id'\n const generate = options.generator ?? defaultGenerator\n\n const onRequest: OnRequestHook<BaseCtx & RequestIdCtx> = createOnRequest<RequestIdCtx>((ctx) => {\n const incoming = ctx.req.headers.get(incomingHeader)\n const id = (incoming && isSafeId(incoming)) ? incoming : generate()\n ctx.requestId = id\n })\n\n const onResponse: OnResponseHook<BaseCtx & RequestIdCtx> = createOnResponse<RequestIdCtx>((ctx, res) => {\n const headers = new Headers(res.headers)\n headers.set(responseHeader, ctx.requestId)\n return new Response(res.body, { status: res.status, headers })\n })\n\n return { onRequest, onResponse }\n}\n","import type { OnResponseHook } from './types'\nimport { createOnResponse } from './types'\n\n// ── Options ─────────────────────────────────────────────────────────────────\n\nexport interface CompressionOptions {\n /**\n * Compression algorithms to offer, in preference order.\n * Default: `['gzip', 'deflate']`\n *\n * Bun 1.x provides `Bun.gzipSync` and `Bun.deflateSync` natively.\n */\n encodings?: Array<'gzip' | 'deflate'>\n\n /**\n * Minimum response body size in bytes before compression is applied.\n * Responses smaller than this are sent uncompressed.\n * Default: `1024` (1 KB)\n */\n threshold?: number\n\n /**\n * Maximum response body size in bytes to attempt compression.\n * Responses larger than this are passed through uncompressed to avoid\n * excessive memory usage when buffering very large responses.\n * Default: `10485760` (10 MB)\n */\n maxSize?: number\n}\n\n// ── Helpers ──────────────────────────────────────────────────────────────────\n\n/** Content-types that benefit from compression. Binary formats are excluded. */\nconst COMPRESSIBLE = /^(text\\/|application\\/(json|xml|javascript|x-www-form-urlencoded|graphql|ld\\+json|geo\\+json|atom\\+xml|rss\\+xml|manifest\\+json))/i\n\nfunction isCompressible(contentType: string | null): boolean {\n if (!contentType) return false\n return COMPRESSIBLE.test(contentType.split(';')[0]!.trim())\n}\n\n/** Pick the best encoding the client accepts from our offered list. */\nfunction negotiateEncoding(\n acceptEncoding: string | null,\n offered: Array<'gzip' | 'deflate'>,\n): 'gzip' | 'deflate' | null {\n if (!acceptEncoding) return null\n for (const enc of offered) {\n if (acceptEncoding.includes(enc)) return enc\n }\n return null\n}\n\n// Bun-native compression — typed interface to avoid `any`\ninterface BunCompress {\n gzipSync(data: Uint8Array): Uint8Array\n deflateSync(data: Uint8Array): Uint8Array\n}\n\nconst bunCompress = Bun as unknown as BunCompress\n\n// ── Plugin factory ───────────────────────────────────────────────────────────\n\n/**\n * compressionPlugin — compresses responses using Bun's native gzip/deflate.\n *\n * Usage:\n * app.onResponse(compressionPlugin())\n * app.onResponse(compressionPlugin({ encodings: ['gzip'], threshold: 512 }))\n *\n * Compression is skipped when:\n * - The client doesn't send Accept-Encoding with a supported algorithm\n * - The Content-Type is binary (images, audio, video, zip, …)\n * - The response body is below the threshold\n * - The response already has a Content-Encoding header (e.g. pre-compressed assets)\n * - The response is a 204 No Content or 304 Not Modified (no body)\n * - The response is a streaming body (Content-Type: text/event-stream)\n */\nconst DEFAULT_MAX_SIZE = 10 * 1024 * 1024 // 10 MB\n\nexport function compressionPlugin(options: CompressionOptions = {}): OnResponseHook {\n const encodings = options.encodings ?? ['gzip', 'deflate']\n const threshold = options.threshold ?? 1024\n const maxSize = options.maxSize ?? DEFAULT_MAX_SIZE\n\n return createOnResponse(async (ctx, res) => {\n // Skip: no-body statuses\n if (res.status === 204 || res.status === 304) return\n\n // Skip: already encoded\n if (res.headers.get('Content-Encoding')) return\n\n // Skip: SSE (streaming — must not buffer)\n const contentType = res.headers.get('Content-Type')\n if (contentType?.includes('text/event-stream')) return\n\n // Skip: non-compressible content type\n if (!isCompressible(contentType)) return\n\n // Negotiate encoding\n const acceptEncoding = ctx.req.headers.get('Accept-Encoding')\n const encoding = negotiateEncoding(acceptEncoding, encodings)\n if (!encoding) return\n\n // Read body — skip if below threshold or empty\n const body = await res.arrayBuffer()\n if (body.byteLength < threshold) return\n\n // Skip: above max size threshold — avoid excessive memory usage\n if (body.byteLength > maxSize) return res\n\n // Compress via Bun-native sync API\n const input = new Uint8Array(body)\n const compressed = encoding === 'gzip'\n ? bunCompress.gzipSync(input)\n : bunCompress.deflateSync(input)\n\n const headers = new Headers(res.headers)\n headers.set('Content-Encoding', encoding)\n headers.set('Content-Length', String(compressed.byteLength))\n headers.set('Vary', 'Accept-Encoding')\n\n return new Response(compressed.buffer as ArrayBuffer, { status: res.status, headers })\n })\n}\n","import type { OnRequestHook } from './types'\nimport { createOnRequest } from './types'\n\n// ── Types ─────────────────────────────────────────────────────────────────────\n\nexport interface HealthCheck {\n (): Promise<{ ok: boolean; details?: Record<string, unknown> }>\n}\n\nexport interface HealthPluginOptions {\n /** Path for the liveness endpoint. Default: '/health' */\n path?: string\n /** Path for the readiness endpoint. Default: '/ready' */\n readyPath?: string\n /** Named checks to run for the readiness endpoint. */\n checks?: Record<string, HealthCheck>\n}\n\n// ── Plugin ────────────────────────────────────────────────────────────────────\n\n/**\n * healthPlugin — adds /health and /ready endpoints for Kubernetes/load balancers.\n *\n * Usage:\n * const health = healthPlugin({ checks: { db: async () => ({ ok: true }) } })\n * app.onRequest(health.onRequest)\n *\n * GET /health → 200 { status: 'ok', uptime: number }\n * Always returns 200. Use for liveness probes (is the process alive?).\n *\n * GET /ready → 200 { status: 'ready', checks: { db: { ok: true } } }\n * → 503 { status: 'not_ready', checks: { db: { ok: false, error: '...' } } }\n * Runs all checks. Use for readiness probes (is the service ready to serve traffic?).\n *\n * The health endpoints are intercepted in the onRequest phase — before auth plugins run.\n */\nexport interface HealthPlugin {\n onRequest: OnRequestHook\n}\n\nexport function healthPlugin(options: HealthPluginOptions = {}): HealthPlugin {\n const healthPath = options.path ?? '/health'\n const readyPath = options.readyPath ?? '/ready'\n const checks = options.checks ?? {}\n\n const onRequest: OnRequestHook = createOnRequest(async (ctx) => {\n const url = new URL(ctx.req.url)\n const path = url.pathname\n const method = ctx.req.method.toUpperCase()\n\n if (method !== 'GET') return\n\n // GET /health — liveness probe\n if (path === healthPath) {\n return Response.json({ status: 'ok', uptime: process.uptime() }, { status: 200 })\n }\n\n // GET /ready — readiness probe\n if (path === readyPath) {\n const checkNames = Object.keys(checks)\n const checkResults: Record<string, { ok: boolean; details?: Record<string, unknown>; error?: string }> = {}\n let allOk = true\n\n for (const name of checkNames) {\n try {\n const result = await checks[name]!()\n checkResults[name] = { ok: result.ok, ...(result.details ? { details: result.details } : {}) }\n if (!result.ok) allOk = false\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err)\n checkResults[name] = { ok: false, error: message }\n allOk = false\n }\n }\n\n if (allOk) {\n return Response.json({ status: 'ready', checks: checkResults }, { status: 200 })\n } else {\n return Response.json({ status: 'not_ready', checks: checkResults }, { status: 503 })\n }\n }\n })\n\n return { onRequest }\n}\n","import type { ZodIssue } from 'zod'\n\nexport class VelnClientError extends Error {\n constructor(\n readonly status: number,\n readonly code: string,\n message: string,\n readonly issues?: ZodIssue[],\n ) {\n super(message)\n this.name = 'VelnClientError'\n }\n}\n","import type { RouteMap, RouteEntry } from '../app/types'\nimport type { ZodTypeAny } from 'zod'\nimport { VelnClientError } from './error'\n\n// ── Type utilities ─────────────────────────────────────────────────────────────\n\n// Response type — only if `response:` schema is defined, otherwise unknown\ntype RouteResponseType<TEntry extends RouteEntry> =\n TEntry['response'] extends ZodTypeAny ? import('zod').infer<TEntry['response']> : unknown\n\n// ClientResult — discriminated union so callers must check ok before accessing data\nexport type ClientResult<T> =\n | { ok: true; data: T; status: number }\n | { ok: false; error: VelnClientError; status: number; code: string; message: string }\n\n// ── Path → client key conversion ──────────────────────────────────────────────\n\nexport function pathToClientKey(prefix: string): string {\n // '/api/users' → 'apiUsers', '/blog-posts' → 'blogPosts', '/v1/orders' → 'v1Orders'\n return prefix\n .replace(/^\\//, '') // strip leading slash\n .split(/[\\/\\-]/) // split on / and -\n .filter(Boolean)\n .map((part, i) => i === 0 ? part : part.charAt(0).toUpperCase() + part.slice(1))\n .join('')\n}\n\n// ── Path → method name conversion ─────────────────────────────────────────────\n\n// Converts a (HTTP method, path-suffix) pair into a camelCase method name.\n// 'GET', '/' → 'index'\n// 'GET', '/:id' → 'show'\n// 'POST', '/' → 'store'\n// 'PATCH', '/:id' → 'update'\n// 'DELETE', '/:id' → 'destroy'\n// 'GET', '/export' → 'getExport'\n// 'POST', '/:id/publish' → 'postByIdPublish'\nfunction pathToMethodName(method: string, suffix: string): string {\n const m = method.toLowerCase()\n // Normalise suffix — strip leading slash\n const s = suffix.replace(/^\\//, '')\n\n // CRUD shorthands\n if (s === '' || s === '/') {\n if (m === 'get') return 'index'\n if (m === 'post') return 'store'\n }\n if (/^:([^/]+)$/.test(s)) {\n if (m === 'get') return 'show'\n if (m === 'patch') return 'update'\n if (m === 'delete') return 'destroy'\n }\n\n // Custom routes — method + path-segments as camelCase\n const segments = s.split('/').filter(Boolean).map((seg) =>\n seg.startsWith(':') ? 'By' + seg.slice(1).charAt(0).toUpperCase() + seg.slice(2) : seg,\n )\n const body = segments\n .map((seg, i) => i === 0 ? seg : seg.charAt(0).toUpperCase() + seg.slice(1))\n .join('')\n return m + body.charAt(0).toUpperCase() + body.slice(1)\n}\n\n// ── Type-level per-module client ───────────────────────────────────────────────\n//\n// Approach: per-module types keep each resolution step small.\n// Each `ModuleRoutes` is a sub-map of routes that share a prefix —\n// TS only traverses the slice it needs, not all routes at once.\n\n// Extract routes whose keys start with a given prefix\ntype ExtractModuleRoutes<TRoutes extends RouteMap, TPrefix extends string> = {\n [K in Extract<keyof TRoutes, `${string} ${TPrefix}${string}`>]: TRoutes[K]\n}\n\n// Suffix after the prefix — e.g. 'GET /users/:id' with prefix '/users' → '/:id'\ntype SuffixAfterPrefix<K extends string, TPrefix extends string> =\n K extends `${infer _Method} ${TPrefix}${infer Suffix}` ? Suffix : never\n\n// Infer the method name for a given route key\ntype MethodOf<K extends string> =\n K extends `GET ${string}` ? 'get' :\n K extends `POST ${string}` ? 'post' :\n K extends `PATCH ${string}` ? 'patch' :\n K extends `DELETE ${string}` ? 'delete' :\n K extends `PUT ${string}` ? 'put' :\n never\n\n// Build one method entry for a route key\n// Returns args as tuple — params before body, then optional request options\n// Note: use [never] extends [TRoutes[K]['body']] to avoid distributing over union,\n// and exclude `never` (the no-body default) from triggering the body branch.\ntype HasBody<TEntry extends RouteEntry> =\n [TEntry['body']] extends [never] ? false :\n [TEntry['body']] extends [ZodTypeAny] ? true : false\n\ntype MethodEntry<TRoutes extends RouteMap, K extends keyof TRoutes & string, TPrefix extends string> =\n HasBody<TRoutes[K] & RouteEntry> extends true\n ? (\n ...args: [\n body: import('zod').infer<TRoutes[K]['body'] & ZodTypeAny>,\n options?: { headers?: Record<string, string>; query?: Record<string, string> },\n ]\n ) => Promise<ClientResult<RouteResponseType<TRoutes[K] & RouteEntry>>>\n : SuffixAfterPrefix<K, TPrefix> extends `/${':'}${string}` | `${string}/${':'}${string}`\n ? (\n ...args: [\n id: number | string,\n options?: { headers?: Record<string, string>; query?: Record<string, string> },\n ]\n ) => Promise<ClientResult<RouteResponseType<TRoutes[K] & RouteEntry>>>\n : (\n options?: { headers?: Record<string, string>; query?: Record<string, string> },\n ) => Promise<ClientResult<RouteResponseType<TRoutes[K] & RouteEntry>>>\n\n// Type-level pathToMethodName — mirrors the runtime function exactly.\n// CRUD shorthands (suffix after stripping leading slash):\n// ''|'/' GET→index POST→store\n// ':x' GET→show PATCH→update DELETE→destroy\n// Custom routes: method + CamelCase(segments)\n// e.g. GET /search → 'getSearch', POST /:id/ban → 'postByIdBan'\n\n// Capitalize first letter of a string\ntype Capitalize1<S extends string> = S extends `${infer F}${infer R}` ? `${Uppercase<F>}${R}` : S\n\n// Convert a single path segment to its camelCase contribution:\n// ':id' → 'ById', ':userId' → 'ByUserId', 'search' → 'Search', 'export' → 'Export'\ntype SegmentToKey<S extends string> =\n S extends `:${infer Param}` ? `By${Capitalize1<Param>}` : Capitalize1<S>\n\n// Convert a slash-separated suffix string to camelCase body (no leading method prefix):\n// 'search' → 'Search'\n// ':id/ban' → 'ByIdBan'\n// 'by-user/:id' → 'By-userById' (runtime splits on / only, not -)\ntype SuffixToCamel<S extends string> =\n S extends `${infer Head}/${infer Tail}`\n ? `${SegmentToKey<Head>}${SuffixToCamel<Tail>}`\n : SegmentToKey<S>\n\n// Full method name: method + Capitalize1(SuffixToCamel(suffix))\ntype CustomMethodName<TMethod extends string, S extends string> =\n `${Lowercase<TMethod>}${Capitalize1<SuffixToCamel<S>>}`\n\ntype RouteMethodName<TMethod extends string, TSuffix extends string> =\n // Strip leading slash before matching\n TSuffix extends `/${infer S}`\n ? RouteMethodNameInner<TMethod, S>\n : RouteMethodNameInner<TMethod, TSuffix>\n\ntype RouteMethodNameInner<TMethod extends string, S extends string> =\n // CRUD: root (empty or just slash)\n S extends '' | '/'\n ? TMethod extends 'get' ? 'index'\n : TMethod extends 'post' ? 'store'\n : CustomMethodName<TMethod, S>\n // CRUD: single bare param segment ':x' — must not contain a slash (no sub-paths)\n : S extends `:${infer _P}` ? _P extends `${string}/${string}`\n ? CustomMethodName<TMethod, S>\n : TMethod extends 'get' ? 'show'\n : TMethod extends 'patch' ? 'update'\n : TMethod extends 'delete' ? 'destroy'\n : CustomMethodName<TMethod, S>\n // Custom route — compute literal name\n : CustomMethodName<TMethod, S>\n\n// Per-module client type — only routes belonging to this prefix, no cross-module bleed.\ntype ModuleClient<TRoutes extends RouteMap, TPrefix extends string> = {\n [K in ModuleRouteKeys<TRoutes, TPrefix> as\n RouteMethodName<MethodOf<K>, SuffixAfterPrefix<K, TPrefix>>\n ]: MethodEntry<TRoutes, K & keyof TRoutes & string, TPrefix>\n}\n\n// ── InferClient — splits app routes into per-module namespaces ─────────────────\n\n// Exact route key filter for a module — uses the _prefix phantom field set by ModuleBuilder.\n// Each route entry has _prefix: TPrefix — filter on exact equality to prevent cross-module bleed.\ntype ModuleRouteKeys<TRoutes extends RouteMap, TPrefix extends string> = {\n [K in keyof TRoutes & string]: TRoutes[K] extends { _prefix: TPrefix } ? K : never\n}[keyof TRoutes & string]\n\n// Type-level pathToClientKey: '/api/users' → 'apiUsers', '/blog-posts' → 'blogPosts'\n// Splits on '/' and '-', capitalizes segments after the first, joins them.\n// TS can do this with recursive template literal inference.\ntype PathToClientKey<S extends string> =\n // Strip leading slash first\n S extends `/${infer Rest}`\n ? PathToClientKey<Rest>\n : PathSegmentsToKey<S>\n\n// Split remaining string on '/' and '-' separators, join as camelCase\ntype PathSegmentsToKey<S extends string> =\n S extends `${infer Head}/${infer Tail}`\n ? `${Head}${Capitalize<PathSegmentsToKey<Tail>>}`\n : S extends `${infer Head}-${infer Tail}`\n ? `${Head}${Capitalize<PathSegmentsToKey<Tail>>}`\n : S\n\n// Public type for consumers\nexport type InferProxyClient<TApp> =\n TApp extends { readonly _routes: infer R; readonly _prefixes: infer P }\n ? R extends RouteMap\n ? [P] extends [string]\n ? ProxyClientFromRoutes<R, P>\n : Record<string, never>\n : Record<string, never>\n : Record<string, never>\n\n// Build the proxy client — one namespace per module prefix, fully typed.\n// P is the union of all registered module prefixes (from app._prefixes).\n// Key is the camelCase version of each prefix, matching pathToClientKey() at runtime.\ntype ProxyClientFromRoutes<TRoutes extends RouteMap, TPrefixes extends string> = {\n [P in TPrefixes as PathToClientKey<P>]: ModuleClient<TRoutes, P>\n}\n\n// ── Runtime implementation ─────────────────────────────────────────────────────\n\nexport interface ProxyClientOptions {\n fetch?: (input: Request) => Promise<Response>\n headers?: Record<string, string>\n throws?: boolean\n}\n\n// Runtime route descriptor — built from app.routes\ninterface RouteDescriptor {\n method: string\n path: string // full path e.g. '/users/:id'\n prefix: string // module prefix e.g. '/users'\n suffix: string // path after prefix e.g. '/:id'\n}\n\nfunction buildDescriptors(routes: Array<{ method: string; path: string; _module?: { prefix: string } | null }>): RouteDescriptor[] {\n return routes.map((r) => {\n const prefix = r._module?.prefix ?? ''\n const suffix = r.path.startsWith(prefix) ? r.path.slice(prefix.length) || '/' : r.path\n return { method: r.method, path: r.path, prefix, suffix }\n })\n}\n\nfunction substitutePathParams(path: string, args: unknown[]): { url: string; remaining: unknown[] } {\n const paramCount = (path.match(/:[^/]+/g) ?? []).length\n const params = args.slice(0, paramCount) as (string | number)[]\n const remaining = args.slice(paramCount)\n let i = 0\n const url = path.replace(/:[^/]+/g, () => String(params[i++] ?? ''))\n return { url, remaining }\n}\n\nasync function executeProxyRequest(\n baseUrl: string,\n descriptor: RouteDescriptor,\n args: unknown[],\n globalHeaders: Record<string, string>,\n fetchFn: (input: Request) => Promise<Response>,\n throwOnError: boolean,\n): Promise<ClientResult<unknown>> {\n // Separate path params (positional) from options (last arg if object without body for GET)\n const hasSuffix = /:[^/]+/.test(descriptor.suffix)\n let pathArgs: unknown[]\n let opts: { body?: unknown; headers?: Record<string, string>; query?: Record<string, string> } | undefined\n\n const isBodyMethod = descriptor.method === 'POST' || descriptor.method === 'PUT' || descriptor.method === 'PATCH'\n\n if (isBodyMethod) {\n // First positional args are path params, then body, then opts\n const paramCount = (descriptor.path.match(/:[^/]+/g) ?? []).length\n pathArgs = args.slice(0, paramCount)\n const bodyArg = args[paramCount]\n const optsArg = args[paramCount + 1] as typeof opts\n opts = { body: bodyArg, headers: optsArg?.headers, query: optsArg?.query }\n } else {\n // GET/DELETE: path params then optional opts object\n const paramCount = (descriptor.path.match(/:[^/]+/g) ?? []).length\n pathArgs = args.slice(0, paramCount)\n opts = args[paramCount] as typeof opts\n }\n\n const { url: substituted } = substitutePathParams(descriptor.path, pathArgs)\n let url = baseUrl.replace(/\\/$/, '') + substituted\n\n if (opts?.query) {\n const qs = new URLSearchParams(opts.query as Record<string, string>).toString()\n if (qs) url += '?' + qs\n }\n\n const headers: Record<string, string> = { ...globalHeaders, ...opts?.headers }\n let bodyStr: string | undefined\n\n if (opts?.body !== undefined && isBodyMethod) {\n bodyStr = JSON.stringify(opts.body)\n headers['Content-Type'] = 'application/json'\n }\n\n let res: Response\n try {\n res = await fetchFn(new Request(url, { method: descriptor.method, headers, body: bodyStr }))\n } catch (networkErr) {\n const msg = networkErr instanceof Error ? networkErr.message : 'Network error'\n const err = new VelnClientError(0, 'NETWORK_ERROR', msg)\n if (throwOnError) throw err\n return { ok: false, error: err, status: 0, code: 'NETWORK_ERROR', message: msg }\n }\n\n if (!res.ok) {\n let code = `HTTP_${res.status}`\n let message = `HTTP ${res.status}`\n try {\n const body = await res.json() as { code?: string; message?: string; error?: string }\n if (body.code) code = body.code\n if (body.message) message = body.message\n else if (body.error) message = body.error\n } catch { /* ignore parse error */ }\n\n const err = new VelnClientError(res.status, code, message)\n if (throwOnError) throw err\n return { ok: false, error: err, status: res.status, code, message }\n }\n\n let data: unknown\n try {\n data = await res.json()\n } catch {\n data = undefined\n }\n\n return { ok: true, data, status: res.status }\n}\n\n// ── Public factory ─────────────────────────────────────────────────────────────\n\nexport function createProxyClient<TApp extends { routes: Array<{ method: string; path: string; _module?: { prefix: string } | null }> }>(\n app: TApp,\n baseUrl: string,\n options?: ProxyClientOptions,\n): InferProxyClient<TApp> {\n const fetchFn = options?.fetch ?? ((req: Request) => globalThis.fetch(req))\n const globalHeaders = options?.headers ?? {}\n const throwOnError = options?.throws ?? false\n\n const descriptors = buildDescriptors(app.routes)\n\n // Group descriptors by prefix → clientKey\n const byKey = new Map<string, RouteDescriptor[]>()\n for (const d of descriptors) {\n const key = pathToClientKey(d.prefix) || 'root'\n if (!byKey.has(key)) byKey.set(key, [])\n byKey.get(key)!.push(d)\n }\n\n // Build namespace → method-map\n const proxy: Record<string, Record<string, (...args: unknown[]) => Promise<ClientResult<unknown>>>> = {}\n\n for (const [key, descs] of byKey) {\n const methods: Record<string, (...args: unknown[]) => Promise<ClientResult<unknown>>> = {}\n for (const desc of descs) {\n const methodName = pathToMethodName(desc.method, desc.suffix)\n methods[methodName] = (...args: unknown[]) =>\n executeProxyRequest(baseUrl, desc, args, globalHeaders, fetchFn, throwOnError)\n }\n proxy[key] = methods\n }\n\n return proxy as InferProxyClient<TApp>\n}\n\n// ── createModuleClient — single-module entry point ────────────────────────────\n\nexport function createModuleClient<TModule extends { routes: Array<{ method: string; path: string; _module?: { prefix: string } | null }>; prefix: string }>(\n module: TModule,\n baseUrl: string,\n options?: ProxyClientOptions,\n): Record<string, (...args: unknown[]) => Promise<ClientResult<unknown>>> {\n const fetchFn = options?.fetch ?? ((req: Request) => globalThis.fetch(req))\n const globalHeaders = options?.headers ?? {}\n const throwOnError = options?.throws ?? false\n\n // Module routes have unprefixed paths — add the module prefix to each\n const prefixedRoutes = module.routes.map((r) => ({\n ...r,\n path: module.prefix + r.path,\n _module: { prefix: module.prefix },\n }))\n\n const descriptors = buildDescriptors(prefixedRoutes)\n const methods: Record<string, (...args: unknown[]) => Promise<ClientResult<unknown>>> = {}\n\n for (const desc of descriptors) {\n const methodName = pathToMethodName(desc.method, desc.suffix)\n methods[methodName] = (...args: unknown[]) =>\n executeProxyRequest(baseUrl, desc, args, globalHeaders, fetchFn, throwOnError)\n }\n\n return methods\n}\n","import { createProxyClient } from './proxy'\nimport type { InferProxyClient, ProxyClientOptions } from './proxy'\n\nexport interface TestClientOptions extends Omit<ProxyClientOptions, 'fetch'> {\n /** Base URL for constructing request URLs. Defaults to 'http://localhost'. */\n baseUrl?: string\n}\n\n/**\n * createTestClient — type-safe test client that calls app.fetch() directly.\n *\n * Identical API to createProxyClient but requires no running HTTP server.\n * Returns InferProxyClient<TApp> — the same fully-typed client as the production proxy.\n *\n * Usage:\n * const client = createTestClient(app)\n * const result = await client.apiUsers.index()\n * expect(result.ok).toBe(true)\n *\n * app.fetch() needs a valid URL to parse pathname/query from,\n * so requests are constructed as 'http://localhost/path' by default.\n */\nexport function createTestClient<\n TApp extends {\n fetch: (req: Request) => Promise<Response>\n routes: Array<{ method: string; path: string; _module?: { prefix: string } | null }>\n }\n>(\n app: TApp,\n options?: TestClientOptions,\n): InferProxyClient<TApp> {\n const { baseUrl = 'http://localhost', ...rest } = options ?? {}\n return createProxyClient(app, baseUrl, {\n ...rest,\n fetch: (req: Request) => app.fetch(req),\n })\n}\n","export { createProxyClient, createModuleClient, pathToClientKey } from './proxy'\nexport type { ClientResult, InferProxyClient, ProxyClientOptions } from './proxy'\nexport { createTestClient } from './test-client'\nexport type { TestClientOptions } from './test-client'\n\nimport type { RouteMap, RouteEntry } from '../app/types'\nimport type { ZodTypeAny } from 'zod'\nimport { VelnClientError } from './error'\nexport { VelnClientError } from './error'\n\n// Helper types — all eager, no conditional on generic parameter\ntype RouteResponse<TEntry extends RouteEntry> =\n TEntry['response'] extends ZodTypeAny ? import('zod').infer<TEntry['response']> : unknown\n\ntype RouteBody<TEntry extends RouteEntry> =\n TEntry['body'] extends ZodTypeAny ? import('zod').infer<TEntry['body']> : never\n\ntype RouteParams<TEntry extends RouteEntry> =\n TEntry['params'] extends ZodTypeAny ? import('zod').infer<TEntry['params']> : never\n\ntype RouteQuery<TEntry extends RouteEntry> =\n TEntry['query'] extends ZodTypeAny ? import('zod').infer<TEntry['query']> : never\n\ntype ClientOptions<TEntry extends RouteEntry> = {\n params?: RouteParams<TEntry>\n query?: RouteQuery<TEntry>\n body?: RouteBody<TEntry>\n headers?: Record<string, string>\n}\n\n// Strip 'METHOD ' prefix from a route key to get just the path.\n// 'POST /items' → '/items'\ntype StripMethod<M extends string, K extends string> =\n K extends `${M} ${infer P}` ? P : never\n\ntype VelnClient<TRoutes extends RouteMap> = {\n get<P extends StripMethod<'GET', Extract<keyof TRoutes, `GET /${string}`>>>(\n path: P,\n options?: ClientOptions<TRoutes[`GET ${P}`]>,\n ): Promise<RouteResponse<TRoutes[`GET ${P}`]>>\n\n post<P extends StripMethod<'POST', Extract<keyof TRoutes, `POST /${string}`>>>(\n path: P,\n options?: ClientOptions<TRoutes[`POST ${P}`]>,\n ): Promise<RouteResponse<TRoutes[`POST ${P}`]>>\n\n put<P extends StripMethod<'PUT', Extract<keyof TRoutes, `PUT /${string}`>>>(\n path: P,\n options?: ClientOptions<TRoutes[`PUT ${P}`]>,\n ): Promise<RouteResponse<TRoutes[`PUT ${P}`]>>\n\n patch<P extends StripMethod<'PATCH', Extract<keyof TRoutes, `PATCH /${string}`>>>(\n path: P,\n options?: ClientOptions<TRoutes[`PATCH ${P}`]>,\n ): Promise<RouteResponse<TRoutes[`PATCH ${P}`]>>\n\n delete<P extends StripMethod<'DELETE', Extract<keyof TRoutes, `DELETE /${string}`>>>(\n path: P,\n options?: ClientOptions<TRoutes[`DELETE ${P}`]>,\n ): Promise<RouteResponse<TRoutes[`DELETE ${P}`]>>\n}\n\ntype ExtractRoutes<TApp> = TApp extends { readonly _routes: infer R } ? R : never\n\nfunction substitutePath(path: string, params?: Record<string, unknown>): string {\n if (!params) return path\n return path.replace(/:([^/]+)/g, (_, key) => String(params[key as string] ?? `:${key}`))\n}\n\n// FetchFn — accepts either globalThis.fetch or app.fetch (which only takes Request)\ntype FetchFn = (input: Request) => Promise<Response>\n\nexport function createClient<TApp>(\n baseUrl: string,\n options?: { fetch?: FetchFn },\n): VelnClient<ExtractRoutes<TApp> extends RouteMap ? ExtractRoutes<TApp> : Record<never, never>> {\n const fetchFn: FetchFn = options?.fetch ?? ((req) => globalThis.fetch(req))\n\n async function request(method: string, path: string, opts?: ClientOptions<RouteEntry>): Promise<unknown> {\n // Extract HTTP method from path key (e.g. \"GET /users/:id\" → path \"/users/:id\")\n // The path argument here is already just the path portion (e.g. \"/users/:id\")\n const substituted = substitutePath(path, opts?.params as Record<string, unknown> | undefined)\n\n let url = baseUrl.replace(/\\/$/, '') + substituted\n\n // Append query params for GET/DELETE\n if (opts?.query && (method === 'GET' || method === 'DELETE')) {\n const qs = new URLSearchParams(opts.query as Record<string, string>).toString()\n if (qs) url += '?' + qs\n }\n\n const headers: Record<string, string> = { ...opts?.headers }\n let body: string | undefined\n\n if (opts?.body !== undefined && (method === 'POST' || method === 'PUT' || method === 'PATCH')) {\n body = JSON.stringify(opts.body)\n headers['Content-Type'] = 'application/json'\n }\n\n const res = await fetchFn(new Request(url, { method, headers, body }))\n\n if (!res.ok) {\n if (res.status === 422) {\n let issues: import('zod').ZodIssue[] | undefined\n try {\n const data = await res.json() as { issues?: import('zod').ZodIssue[] }\n issues = data.issues\n } catch {\n // ignore parse error\n }\n throw new VelnClientError(res.status, 'VALIDATION_ERROR', 'Validation failed', issues)\n }\n throw new VelnClientError(res.status, `HTTP_${res.status}`, `HTTP ${res.status}`)\n }\n\n // Parse JSON response\n try {\n return await res.json()\n } catch {\n return undefined\n }\n }\n\n return {\n get: (path, opts) => request('GET', path as string, opts as ClientOptions<RouteEntry>),\n post: (path, opts) => request('POST', path as string, opts as ClientOptions<RouteEntry>),\n put: (path, opts) => request('PUT', path as string, opts as ClientOptions<RouteEntry>),\n patch: (path, opts) => request('PATCH', path as string, opts as ClientOptions<RouteEntry>),\n delete: (path, opts) => request('DELETE', path as string, opts as ClientOptions<RouteEntry>),\n } as VelnClient<ExtractRoutes<TApp> extends RouteMap ? ExtractRoutes<TApp> : Record<never, never>>\n}\n","import { z } from 'zod'\nimport type { ZodTypeAny } from 'zod'\nimport type { Column } from '../schema/column'\nimport type { SchemaMap, TableDef } from '../schema/table'\n\n// ── columnToZod — map a single Column to its Zod type ────────────────────\n\nfunction columnToZod(col: Column<unknown>): ZodTypeAny {\n let base: ZodTypeAny\n\n switch (col.def.type) {\n case 'INTEGER': base = z.number().int(); break\n case 'REAL': base = z.number(); break\n case 'TEXT': base = z.string(); break\n case 'UUID': base = z.string().uuid(); break\n case 'BOOLEAN': base = z.boolean(); break\n case 'TIMESTAMP': base = z.coerce.date(); break\n case 'JSON': base = z.unknown(); break\n case 'BLOB': base = z.instanceof(Uint8Array); break\n default: base = z.unknown()\n }\n\n if (col.def.nullable) {\n base = base.nullable()\n }\n\n return base\n}\n\n// ── tableToZodInsert — derive insert Zod schema from TableDef ─────────────\n//\n// Rules (mirror InferInsert):\n// - primaryKey + autoIncrement → excluded entirely\n// - nullable → .nullable() applied\n// - defaultValue or defaultFn present → .optional()\n// - otherwise → required\n\nexport function tableToZodInsert<T, S extends SchemaMap>(\n table: TableDef<T, S>,\n): z.ZodObject<Record<string, ZodTypeAny>> {\n const shape: Record<string, ZodTypeAny> = {}\n\n for (const [name, col] of Object.entries(table.schema)) {\n const c = col as Column<unknown>\n\n // Skip auto-increment primary keys — DB assigns the value\n if (c.def.primaryKey && c.def.autoIncrement) continue\n\n let field = columnToZod(c)\n\n // Fields with defaults are optional on insert\n if (c.def.defaultValue !== undefined || c.def.defaultFn !== undefined) {\n field = field.optional()\n }\n\n shape[name] = field\n }\n\n return z.object(shape)\n}\n\n// ── tableToZodRow — full row schema (all fields required except nullable) ─\n\nexport function tableToZodRow<T, S extends SchemaMap>(\n table: TableDef<T, S>,\n): z.ZodObject<Record<string, ZodTypeAny>> {\n const shape: Record<string, ZodTypeAny> = {}\n\n for (const [name, col] of Object.entries(table.schema)) {\n shape[name] = columnToZod(col as Column<unknown>)\n }\n\n return z.object(shape)\n}\n","// Re-export from the central errors module so resource-level imports still work.\n// NotFoundError and ConflictError are now VelnError subclasses with status + code.\nexport { NotFoundError, ConflictError } from '../errors/index'\n","import type { ZodTypeAny } from 'zod'\nimport type { TableDef, SchemaMap, InferRow, InferInsert } from '../schema/table'\nimport type { BoundVelnDB } from '../db/index'\nimport type { BaseCtx, BaseOptions } from '../app/types'\nimport type { Guard, ErrorHandler, OnRequestHook, OnBeforeHandleHook, OnResponseHook } from '../app/types'\nimport type { Plugin } from '../app/plugin'\nimport type { AuditConfig } from '../schema/audit'\nimport type { ModuleHookHandlers } from '../hooks/types'\nimport type { ServiceDef } from '../service/index'\nimport type { EventHandlerDef } from '../events/handler'\nimport { defineModel } from '../model/index'\nimport { defineService } from '../service/index'\nimport { ModuleBuilder, defineModule } from '../app/module'\nimport type { VelnModule } from '../app/module'\nimport { tableToZodInsert, tableToZodRow } from './zod-table'\nimport { NotFoundError } from './errors'\n\nexport { NotFoundError, ConflictError } from './errors'\nexport { tableToZodInsert, tableToZodRow } from './zod-table'\n\n// ── Types ─────────────────────────────────────────────────────────────────────\n\ntype ResourceServiceKey<TName extends string> = `${TName}Resource`\n\n// ── Default model methods ─────────────────────────────────────────────────────\n// These are the methods the built-in model exposes by default.\n// User can override any via ResourceOptions.model.\n\nexport interface DefaultModelMethods<TRow, TInsert> {\n index(): Promise<TRow[]>\n show(id: number): Promise<TRow>\n store(data: TInsert): Promise<TRow>\n update(id: number, data: Partial<TInsert>): Promise<TRow>\n destroy(id: number): Promise<void>\n}\n\n// ResourceOptions.model — user provides (db, ...args) => result for each method override,\n// plus any new methods they want to add.\n// Each override replaces the default implementation entirely.\nexport interface ModelOverrides<TRow, TInsert> {\n index?: (db: BoundVelnDB) => () => Promise<TRow[]>\n show?: (db: BoundVelnDB) => (id: number) => Promise<TRow>\n store?: (db: BoundVelnDB) => (data: TInsert) => Promise<TRow>\n update?: (db: BoundVelnDB) => (id: number, data: Partial<TInsert>) => Promise<TRow>\n destroy?: (db: BoundVelnDB) => (id: number) => Promise<void>\n // Extra methods — any signature\n [key: string]: ((db: BoundVelnDB) => (...args: never[]) => unknown) | undefined\n}\n\n// ServiceOverrides — user provides ({ model }, ...args) => result for each CRUD method.\n// model includes all default + custom model methods.\nexport type ServiceOverrides<TModel, TRow, TInsert> = {\n index?: (deps: { model: TModel }) => () => Promise<TRow[]>\n show?: (deps: { model: TModel }) => (id: number) => Promise<TRow>\n store?: (deps: { model: TModel }) => (data: TInsert) => Promise<TRow>\n update?: (deps: { model: TModel }) => (id: number, data: Partial<TInsert>) => Promise<TRow>\n destroy?: (deps: { model: TModel }) => (id: number) => Promise<void>\n}\n\n// RouteConfig — per-route options\nexport type RouteConfig = {\n guard?: Guard<BaseCtx>\n summary?: string\n} | false\n\nexport interface ResourceOptions<TRow, TInsert> {\n prefix?: string\n model?: ModelOverrides<TRow, TInsert>\n service?: ServiceOverrides<DefaultModelMethods<TRow, TInsert> & Record<string, unknown>, TRow, TInsert>\n routes?: {\n index?: RouteConfig\n show?: RouteConfig\n store?: RouteConfig\n update?: RouteConfig\n destroy?: RouteConfig\n }\n}\n\n// ── buildResourceModel ────────────────────────────────────────────────────────\n\nfunction buildResourceModel<T, S extends SchemaMap>(\n table: TableDef<T, S>,\n overrides: ModelOverrides<InferRow<TableDef<T, S>>, InferInsert<TableDef<T, S>>>,\n) {\n type TRow = InferRow<TableDef<T, S>>\n type TInsert = InferInsert<TableDef<T, S>>\n\n const modelName = `${table.name}Model` as const\n\n return defineModel(modelName, table, (db) => {\n const pk = table.primaryKey as keyof TRow & string\n\n const index = overrides.index\n ? overrides.index(db)\n : () => db.from(table).select() as Promise<TRow[]>\n\n const show = overrides.show\n ? overrides.show(db)\n : async (id: number): Promise<TRow> => {\n const row = await (db.from(table).where({ [pk]: id } as Partial<TRow>).first() as Promise<TRow | null>)\n if (!row) throw new NotFoundError(`${table.name} with id ${id} not found`)\n return row\n }\n\n const store = overrides.store\n ? overrides.store(db)\n : (data: TInsert) => (db.into(table) as { insert(d: unknown): Promise<TRow> }).insert(data)\n\n const update = overrides.update\n ? overrides.update(db)\n : async (id: number, data: Partial<TInsert>): Promise<TRow> => {\n await show(id) // throws NotFoundError if missing\n await db.from(table).where({ [pk]: id } as Partial<TRow>).update(data as Partial<TRow>)\n return show(id)\n }\n\n const destroy = overrides.destroy\n ? overrides.destroy(db)\n : async (id: number): Promise<void> => {\n await show(id) // throws NotFoundError if missing\n await db.from(table).where({ [pk]: id } as Partial<TRow>).delete()\n }\n\n // Build base methods\n const methods: Record<string, unknown> = { index, show, store, update, destroy }\n\n // Add any extra methods from overrides\n for (const [key, factory] of Object.entries(overrides)) {\n if (!['index', 'show', 'store', 'update', 'destroy'].includes(key) && factory) {\n methods[key] = factory(db)\n }\n }\n\n return methods as DefaultModelMethods<TRow, TInsert> & Record<string, unknown>\n })\n}\n\n// ── buildResourceService ──────────────────────────────────────────────────────\n\ntype AnyModel = DefaultModelMethods<unknown, unknown> & Record<string, unknown>\n\nfunction buildResourceService<T, S extends SchemaMap>(\n table: TableDef<T, S>,\n modelDef: ReturnType<typeof buildResourceModel<T, S>>,\n serviceOverrides: ServiceOverrides<AnyModel, InferRow<TableDef<T, S>>, InferInsert<TableDef<T, S>>>,\n): ServiceDef<ResourceServiceKey<string>, DefaultModelMethods<InferRow<TableDef<T, S>>, InferInsert<TableDef<T, S>>>> {\n type TRow = InferRow<TableDef<T, S>>\n type TInsert = InferInsert<TableDef<T, S>>\n\n const serviceKey = `${table.name}Resource` as ResourceServiceKey<string>\n const modelName = modelDef._modelName\n\n return defineService(serviceKey)\n .use(modelDef)\n .define((deps) => {\n const model = (deps as Record<string, AnyModel>)[modelName]\n\n const index = serviceOverrides.index ? serviceOverrides.index({ model }) : () => model.index() as Promise<TRow[]>\n const show = serviceOverrides.show ? serviceOverrides.show({ model }) : (id: number) => model.show(id) as Promise<TRow>\n const store = serviceOverrides.store ? serviceOverrides.store({ model }) : (data: TInsert) => model.store(data) as Promise<TRow>\n const update = serviceOverrides.update ? serviceOverrides.update({ model }) : (id: number, data: Partial<TInsert>) => model.update(id, data) as Promise<TRow>\n const destroy = serviceOverrides.destroy ? serviceOverrides.destroy({ model }) : (id: number) => model.destroy(id) as Promise<void>\n\n return { index, show, store, update, destroy }\n }) as ServiceDef<ResourceServiceKey<string>, DefaultModelMethods<TRow, TInsert>>\n}\n\n// ── buildResourceModule ───────────────────────────────────────────────────────\n\nfunction buildResourceModule<T, S extends SchemaMap>(\n prefix: string,\n table: TableDef<T, S>,\n serviceDef: ServiceDef<ResourceServiceKey<string>, DefaultModelMethods<InferRow<TableDef<T, S>>, InferInsert<TableDef<T, S>>>>,\n routeOptions: ResourceOptions<InferRow<TableDef<T, S>>, InferInsert<TableDef<T, S>>>['routes'],\n): ModuleBuilder<BaseCtx> {\n const serviceKey = serviceDef._serviceKey\n const routes = routeOptions ?? {}\n\n const insertSchema = tableToZodInsert(table)\n const rowSchema = tableToZodRow(table)\n\n type Svc = DefaultModelMethods<InferRow<TableDef<T, S>>, InferInsert<TableDef<T, S>>>\n type Ctx = BaseCtx & Record<typeof serviceKey, Svc>\n\n let builder = defineModule(prefix).use(serviceDef) as unknown as ModuleBuilder<Ctx>\n\n function getSvc(ctx: Ctx): Svc {\n return (ctx as Record<string, unknown>)[serviceKey] as Svc\n }\n\n // GET / — index\n if (routes.index !== false) {\n const cfg = routes.index ?? {}\n let b = builder\n if (cfg && cfg.guard) b = b.guard(cfg.guard as Guard<Ctx>)\n b = b.route({\n method: 'GET',\n path: '/',\n summary: (cfg && cfg.summary) ? cfg.summary : `List ${table.name}`,\n handler: async (ctx) => ctx.json(await getSvc(ctx).index()),\n })\n builder = b\n }\n\n // GET /:id — show\n if (routes.show !== false) {\n const cfg = routes.show ?? {}\n let b = builder\n if (cfg && cfg.guard) b = b.guard(cfg.guard as Guard<Ctx>)\n b = b.route({\n method: 'GET',\n path: '/:id',\n summary: (cfg && cfg.summary) ? cfg.summary : `Get ${table.name} by id`,\n handler: async (ctx) => ctx.json(await getSvc(ctx).show(Number(ctx.params['id']))),\n })\n builder = b\n }\n\n // POST / — store\n if (routes.store !== false) {\n const cfg = routes.store ?? {}\n let b = builder\n if (cfg && cfg.guard) b = b.guard(cfg.guard as Guard<Ctx>)\n b = b.route({\n method: 'POST',\n path: '/',\n summary: (cfg && cfg.summary) ? cfg.summary : `Create ${table.name}`,\n schema: { body: insertSchema, response: rowSchema },\n handler: async (ctx) => ctx.json(await getSvc(ctx).store((ctx as Ctx & { body: InferInsert<TableDef<T, S>> }).body), 201),\n })\n builder = b\n }\n\n // PATCH /:id — update\n if (routes.update !== false) {\n const cfg = routes.update ?? {}\n let b = builder\n if (cfg && cfg.guard) b = b.guard(cfg.guard as Guard<Ctx>)\n b = b.route({\n method: 'PATCH',\n path: '/:id',\n summary: (cfg && cfg.summary) ? cfg.summary : `Update ${table.name}`,\n schema: { body: insertSchema.partial() },\n handler: async (ctx) => {\n const row = await getSvc(ctx).update(\n Number(ctx.params['id']),\n (ctx as Ctx & { body: Partial<InferInsert<TableDef<T, S>>> }).body,\n )\n return ctx.json(row)\n },\n })\n builder = b\n }\n\n // DELETE /:id — destroy\n if (routes.destroy !== false) {\n const cfg = routes.destroy ?? {}\n let b = builder\n if (cfg && cfg.guard) b = b.guard(cfg.guard as Guard<Ctx>)\n b = b.route({\n method: 'DELETE',\n path: '/:id',\n summary: (cfg && cfg.summary) ? cfg.summary : `Delete ${table.name}`,\n handler: async (ctx) => {\n await getSvc(ctx).destroy(Number(ctx.params['id']))\n return ctx.json({ ok: true })\n },\n })\n builder = b\n }\n\n return builder as unknown as ModuleBuilder<BaseCtx>\n}\n\n// ── ResourceResult ────────────────────────────────────────────────────────────\n\nexport interface ResourceResult<T, S extends SchemaMap> {\n Model: ReturnType<typeof buildResourceModel<T, S>>\n Service: ServiceDef<ResourceServiceKey<string>, DefaultModelMethods<InferRow<TableDef<T, S>>, InferInsert<TableDef<T, S>>>>\n module: VelnModule\n}\n\n// ── ResourceBuilder ───────────────────────────────────────────────────────────\n\nexport class ResourceBuilder<TCtx extends BaseCtx, T, S extends SchemaMap> {\n private constructor(\n private readonly _table: TableDef<T, S>,\n private readonly _options: ResourceOptions<InferRow<TableDef<T, S>>, InferInsert<TableDef<T, S>>>,\n private readonly _builderFns: Array<(b: ModuleBuilder<BaseCtx>) => ModuleBuilder<BaseCtx>>,\n ) {}\n\n static create<T, S extends SchemaMap>(\n table: TableDef<T, S>,\n options: ResourceOptions<InferRow<TableDef<T, S>>, InferInsert<TableDef<T, S>>>,\n ): ResourceBuilder<BaseCtx, T, S> {\n return new ResourceBuilder<BaseCtx, T, S>(table, options, [])\n }\n\n // ── Delegate to ModuleBuilder ─────────────────────────────────────────────\n\n options(opts: BaseOptions): ResourceBuilder<TCtx, T, S> {\n return new ResourceBuilder<TCtx, T, S>(\n this._table,\n this._options,\n [...this._builderFns, (b) => b.options(opts)],\n )\n }\n\n plugin<TAdd extends object>(p: Plugin<TCtx, TAdd>): ResourceBuilder<TCtx & TAdd, T, S> {\n return new ResourceBuilder<TCtx & TAdd, T, S>(\n this._table,\n this._options,\n [...this._builderFns, (b) => (b as ModuleBuilder<BaseCtx>).plugin(p as unknown as Plugin<BaseCtx, TAdd>) as unknown as ModuleBuilder<BaseCtx>],\n )\n }\n\n guard(g: Guard<TCtx>): ResourceBuilder<TCtx, T, S> {\n return new ResourceBuilder<TCtx, T, S>(\n this._table,\n this._options,\n [...this._builderFns, (b) => b.guard(g as Guard<BaseCtx>)],\n )\n }\n\n hook(table: TableDef<T, S>, handlers: ModuleHookHandlers<T, TCtx>): ResourceBuilder<TCtx, T, S> {\n return new ResourceBuilder<TCtx, T, S>(\n this._table,\n this._options,\n [...this._builderFns, (b) => b.hook(table, handlers as ModuleHookHandlers<T, BaseCtx>)],\n )\n }\n\n audit<AT extends Record<string, unknown>, AS extends SchemaMap>(\n auditTable: TableDef<AT, AS>,\n config: AuditConfig<TCtx, AT, AS>,\n ): ResourceBuilder<TCtx, T, S> {\n return new ResourceBuilder<TCtx, T, S>(\n this._table,\n this._options,\n [...this._builderFns, (b) => b.audit(auditTable, config as AuditConfig<BaseCtx, AT, AS>)],\n )\n }\n\n use<TKey extends string, TDef>(\n service: ServiceDef<TKey, TDef>,\n ): ResourceBuilder<TCtx & Record<TKey, TDef>, T, S> {\n return new ResourceBuilder<TCtx & Record<TKey, TDef>, T, S>(\n this._table,\n this._options,\n [...this._builderFns, (b) => b.use(service) as ModuleBuilder<BaseCtx>],\n )\n }\n\n onRequest(hook: OnRequestHook<TCtx>): ResourceBuilder<TCtx, T, S> {\n return new ResourceBuilder<TCtx, T, S>(\n this._table,\n this._options,\n [...this._builderFns, (b) => b.onRequest(hook as OnRequestHook<BaseCtx>)],\n )\n }\n\n onBeforeHandle(hook: OnBeforeHandleHook<TCtx>): ResourceBuilder<TCtx, T, S> {\n return new ResourceBuilder<TCtx, T, S>(\n this._table,\n this._options,\n [...this._builderFns, (b) => b.onBeforeHandle(hook as OnBeforeHandleHook<BaseCtx>)],\n )\n }\n\n onResponse(hook: OnResponseHook<TCtx>): ResourceBuilder<TCtx, T, S> {\n return new ResourceBuilder<TCtx, T, S>(\n this._table,\n this._options,\n [...this._builderFns, (b) => b.onResponse(hook as OnResponseHook<BaseCtx>)],\n )\n }\n\n onError(handler: ErrorHandler<TCtx>): ResourceBuilder<TCtx, T, S> {\n return new ResourceBuilder<TCtx, T, S>(\n this._table,\n this._options,\n [...this._builderFns, (b) => b.onError(handler as ErrorHandler<BaseCtx>)],\n )\n }\n\n events(handler: EventHandlerDef): ResourceBuilder<TCtx, T, S> {\n return new ResourceBuilder<TCtx, T, S>(\n this._table,\n this._options,\n [...this._builderFns, (b) => b.events(handler)],\n )\n }\n\n // ── .build() ─────────────────────────────────────────────────────────────\n\n build(): ResourceResult<T, S> {\n const prefix = this._options.prefix ?? `/${this._table.name}`\n const Model = buildResourceModel(this._table, this._options.model ?? {})\n const Service = buildResourceService(this._table, Model, (this._options.service ?? {}) as ServiceOverrides<AnyModel, InferRow<TableDef<T, S>>, InferInsert<TableDef<T, S>>>)\n let moduleBuilder = buildResourceModule(prefix, this._table, Service, this._options.routes)\n for (const fn of this._builderFns) {\n moduleBuilder = fn(moduleBuilder)\n }\n const module = moduleBuilder.build()\n return { Model, Service, module }\n }\n}\n\n// ── defineResource — entry point ─────────────────────────────────────────────\n\n/**\n * defineResource — generates CRUD routes, a Model, and a Service from a table definition.\n *\n * @param table The table definition produced by `defineTable(...).build()`.\n * @param options Route prefix string or `ResourceOptions` for customization.\n *\n * @example\n * const { module } = defineResource(usersTable, '/users').build()\n * app.register(module)\n */\nexport function defineResource<T, S extends SchemaMap>(\n table: TableDef<T, S>,\n options: ResourceOptions<InferRow<TableDef<T, S>>, InferInsert<TableDef<T, S>>> | string = {},\n): ResourceBuilder<BaseCtx, T, S> {\n // Convenience: if options is a string, treat it as the prefix\n const opts: ResourceOptions<InferRow<TableDef<T, S>>, InferInsert<TableDef<T, S>>> =\n typeof options === 'string' ? { prefix: options } : options\n return ResourceBuilder.create(table, opts)\n}\n","export interface VelnConfig {\n features?: string // default: './src/features'\n schema?: string // default: './src/schema'\n tables?: string // default: './src/tables'\n migrations?: string // default: './migrations'\n commands?: string // default: './src/commands'\n}\n\nexport interface CommandOption {\n flag: string\n description: string\n default?: string\n}\n\nexport interface CommandDef {\n _name: string\n _description: string\n _options: CommandOption[]\n _action: (args: Record<string, string>) => Promise<void> | void\n}\n\nclass CommandBuilder {\n private _desc = ''\n private _opts: CommandOption[] = []\n\n constructor(private readonly _name: string) {}\n\n description(desc: string): this {\n this._desc = desc\n return this\n }\n\n option(flag: string, description: string, defaultValue?: string): this {\n this._opts.push({ flag, description, default: defaultValue })\n return this\n }\n\n action(fn: (args: Record<string, string>) => Promise<void> | void): CommandDef {\n return {\n _name: this._name,\n _description: this._desc,\n _options: this._opts,\n _action: fn,\n }\n }\n}\n\nexport function defineConfig(config: VelnConfig): VelnConfig {\n return config\n}\n\nexport function defineCommand(name: string): CommandBuilder {\n return new CommandBuilder(name)\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IASa,mBAgEA,kBAmDA;AA5Hb;AAAA;AAAA;AASO,IAAM,oBAAN,MAAwB;AAAA,MACZ,SAAyB,CAAC;AAAA,MAE3C,QAAQ,MAAc,SAAwB;AAC5C,aAAK,OAAO,KAAK,EAAE,MAAM,QAAQ,CAAC;AAAA,MACpC;AAAA,MAEA,MAAM,MAAM,KAAc,KAAwD;AAChF,cAAM,SAAS,KAAK,OAAO,OAAO,CAAC;AACnC,mBAAW,KAAK,QAAQ;AACtB,cAAI,WAAW,KAAK;AAClB,YAAC,IAAyB,MAAM,EAAE,MAAM,EAAE,SAAS,GAAG;AAAA,UACxD,OAAO;AACL,kBAAM,IAAI,KAAK,EAAE,MAAM,EAAE,OAAO;AAAA,UAClC;AAAA,QACF;AAAA,MACF;AAAA;AAAA;AAAA,MAIA,QAAwB;AACtB,eAAO,KAAK,OAAO,OAAO,CAAC;AAAA,MAC7B;AAAA;AAAA,MAGA,IAAI,OAAe;AACjB,eAAO,KAAK,OAAO;AAAA,MACrB;AAAA,IACF;AAoCO,IAAM,mBAAN,MAAuB;AAAA,MACX,WAAW,oBAAI,IAA4B;AAAA,MAC3C;AAAA,MAEjB,YAAY,SAA2B;AACrC,aAAK,WAAW,SAAS,YACtB,CAAC,OAAO,QAAQ,QAAQ,MAAM,oCAAoC,KAAK,MAAM,GAAG;AAAA,MACrF;AAAA,MAWA,GAAG,OAAe,SAA6B;AAC7C,YAAI,CAAC,KAAK,SAAS,IAAI,KAAK,EAAG,MAAK,SAAS,IAAI,OAAO,CAAC,CAAC;AAC1D,aAAK,SAAS,IAAI,KAAK,EAAG,KAAK,OAAO;AACtC,eAAO;AAAA,MACT;AAAA;AAAA;AAAA,MAIA,MAAM,OAAe,SAAkB,KAAoB;AACzD,cAAM,WAAW,KAAK,SAAS,IAAI,KAAK,KAAK,CAAC;AAC9C,mBAAW,KAAK,UAAU;AAExB,cAAI,QAAc,CAAC,YAAY,QAAQ,EAAE,SAAS,GAAG,CAAS,CAAC,EAAE;AAAA,YAAM,CAAC,QACtE,KAAK,SAAS,OAAO,GAAG;AAAA,UAC1B;AAAA,QACF;AAAA,MACF;AAAA;AAAA;AAAA,MAIA,MAAM,KAAK,OAAe,SAAiC;AACzD,aAAK,MAAM,OAAO,SAAS,MAAS;AAAA,MACtC;AAAA;AAAA,MAGA,MAAM,MAAM,QAAwB,KAA6B;AAC/D,mBAAW,KAAK,QAAQ;AACtB,eAAK,MAAM,EAAE,MAAM,EAAE,SAAS,GAAG;AAAA,QACnC;AAAA,MACF;AAAA,IACF;AAGO,IAAM,WAAW;AAAA;AAAA;;;AC5HxB,IAAa,WAWA,iBAOA,mBAOA,gBAOA,eAOA,eAOA,oBAOA,sBAOA;AA5Db;AAAA;AAAA;AAAO,IAAM,YAAN,cAAwB,MAAM;AAAA,MACnC,YACE,SACSA,SACA,MACT;AACA,cAAM,OAAO;AAHJ,sBAAAA;AACA;AAGT,aAAK,OAAO;AAAA,MACd;AAAA,MALW;AAAA,MACA;AAAA,IAKb;AAEO,IAAM,kBAAN,cAA8B,UAAU;AAAA,MAC7C,YAAY,UAAU,eAAe,OAAO,eAAe;AACzD,cAAM,SAAS,KAAK,IAAI;AACxB,aAAK,OAAO;AAAA,MACd;AAAA,IACF;AAEO,IAAM,oBAAN,cAAgC,UAAU;AAAA,MAC/C,YAAY,UAAU,gBAAgB,OAAO,gBAAgB;AAC3D,cAAM,SAAS,KAAK,IAAI;AACxB,aAAK,OAAO;AAAA,MACd;AAAA,IACF;AAEO,IAAM,iBAAN,cAA6B,UAAU;AAAA,MAC5C,YAAY,UAAU,aAAa,OAAO,aAAa;AACrD,cAAM,SAAS,KAAK,IAAI;AACxB,aAAK,OAAO;AAAA,MACd;AAAA,IACF;AAEO,IAAM,gBAAN,cAA4B,UAAU;AAAA,MAC3C,YAAY,UAAU,aAAa,OAAO,aAAa;AACrD,cAAM,SAAS,KAAK,IAAI;AACxB,aAAK,OAAO;AAAA,MACd;AAAA,IACF;AAEO,IAAM,gBAAN,cAA4B,UAAU;AAAA,MAC3C,YAAY,UAAU,YAAY,OAAO,YAAY;AACnD,cAAM,SAAS,KAAK,IAAI;AACxB,aAAK,OAAO;AAAA,MACd;AAAA,IACF;AAEO,IAAM,qBAAN,cAAiC,UAAU;AAAA,MAChD,YAAY,UAAU,wBAAwB,OAAO,iBAAiB;AACpE,cAAM,SAAS,KAAK,IAAI;AACxB,aAAK,OAAO;AAAA,MACd;AAAA,IACF;AAEO,IAAM,uBAAN,cAAmC,UAAU;AAAA,MAClD,YAAY,UAAU,qBAAqB,OAAO,qBAAqB;AACrE,cAAM,SAAS,KAAK,IAAI;AACxB,aAAK,OAAO;AAAA,MACd;AAAA,IACF;AAEO,IAAM,gBAAN,cAA4B,UAAU;AAAA,MAC3C,YAAY,UAAU,yBAAyB,OAAO,kBAAkB;AACtE,cAAM,SAAS,KAAK,IAAI;AACxB,aAAK,OAAO;AAAA,MACd;AAAA,IACF;AAAA;AAAA;;;ACzBA,SAAS,WAAW,OAAuB;AACzC,MAAI,CAAC,MAAO,QAAO,IAAI,KAAK;AAC5B,QAAM,SAAS,MAAM,MAAM,GAAG,EAAE,CAAC;AACjC,QAAM,QAAS,aAAa,MAAM,KAAK;AACvC,SAAO,GAAG,KAAK,IAAI,KAAK,IAAI,KAAK;AACnC;AAEA,SAAS,WACP,MACA,UACQ;AACR,QAAM,UAAU,OAAO,QAAQ,IAAI;AACnC,MAAI,QAAQ,WAAW,EAAG,QAAO;AAEjC,QAAM,SAAmC,QAAQ,IAAI,CAAC,CAAC,GAAG,CAAC,MAAM;AAAA,IAC/D;AAAA,IACA,SAAS,IAAI,EAAE,YAAY,CAAC,IAAI,QAAQ;AAAA,EAC1C,CAAC;AAED,MAAI,OAAO,UAAU,GAAG;AACtB,UAAM,SAAS,OACZ,IAAI,CAAC,CAAC,GAAG,CAAC,MAAO,QAAQ,GAAG,GAAG,GAAG,CAAC,GAAG,KAAK,IAAI,KAAK,UAAU,CAAC,CAAC,KAAK,GAAG,CAAC,IAAI,KAAK,UAAU,CAAC,CAAC,EAAG,EACjG,KAAK,GAAG;AACX,WAAO,KAAK,MAAM;AAAA,EACpB;AAEA,QAAM,QAAQ,OACX,IAAI,CAAC,CAAC,GAAG,CAAC,MAAO,QAAQ,KAAK,GAAG,GAAG,CAAC,GAAG,KAAK,IAAI,KAAK,UAAU,CAAC,CAAC,KAAK,KAAK,CAAC,IAAI,KAAK,UAAU,CAAC,CAAC,EAAG,EACrG,KAAK,IAAI;AACZ,SAAO;AAAA,EAAK,KAAK;AACnB;AAOO,SAAS,oBAAoB,OAAe,MAA2B;AAC5E,MAAI,MAAM,OAAQ,QAAO,WAAW;AAEpC,QAAM,WAAa,YAAY,MAAM,SAAS,MAAM;AACpD,QAAM,WAAa,IAAI,KAAK,MAAM,QAAQ,CAAC,GAAG,IAAI,CAAC,MAAM,EAAE,YAAY,CAAC,CAAC;AACzE,QAAM,aAAa,WAAW,KAAK;AAEnC,WAAS,IAAI,QAAkB,KAAa,MAAuB;AACjE,QAAI,YAAY,MAAM,IAAI,SAAU;AAGpC,UAAM,CAAC,OAAO,GAAG,IAAI,IAAI;AACzB,UAAM,YACJ,UAAU,QACV,UAAU,UACV,OAAO,UAAU,YACjB,CAAC,MAAM,QAAQ,KAAK;AAEtB,UAAM,UAAU,YACZ,WAAW,OAAkC,QAAQ,IACrD;AAEJ,UAAM,aAAa,QAAQ,aAAa,MAAM,IAAI;AAClD,UAAM,UAAa,aAAa,GAAG,UAAU,GAAG,GAAG,GAAG,KAAK,KAAK;AAChE,UAAM,OAAa,GAAG,UAAU,KAAK,OAAO,GAAG,OAAO;AAGtD,UAAM,QAAQ,YAAY,OAAO;AAEjC,QAAI,WAAW,SAAS;AACtB,cAAQ,MAAM,MAAM,GAAG,KAAK;AAAA,IAC9B,WAAW,WAAW,QAAQ;AAC5B,cAAQ,KAAK,MAAM,GAAG,KAAK;AAAA,IAC7B,OAAO;AACL,cAAQ,IAAI,MAAM,GAAG,KAAK;AAAA,IAC5B;AAAA,EACF;AAEA,SAAO;AAAA,IACL,KAAK,QAAgB,MAAkB;AAAE,UAAI,QAAS,KAAK,IAAI;AAAA,IAAE;AAAA,IACjE,KAAK,QAAgB,MAAkB;AAAE,UAAI,QAAS,KAAK,IAAI;AAAA,IAAE;AAAA,IACjE,MAAM,QAAgB,MAAiB;AAAE,UAAI,SAAS,KAAK,IAAI;AAAA,IAAE;AAAA,IACjE,MAAM,QAAgB,MAAiB;AAAE,UAAI,SAAS,KAAK,IAAI;AAAA,IAAE;AAAA,EACnE;AACF;AAEA,SAAS,aAAqB;AAC5B,SAAO;AAAA,IACL,OAAO,MAAM;AAAA,IAAC;AAAA,IACd,MAAO,MAAM;AAAA,IAAC;AAAA,IACd,MAAO,MAAM;AAAA,IAAC;AAAA,IACd,OAAO,MAAM;AAAA,IAAC;AAAA,EAChB;AACF;AAlIA,IAMM,aASA,OACA,KAEA,cAYA,cAQA;AAtCN;AAAA;AAAA;AAMA,IAAM,cAAwC;AAAA,MAC5C,OAAO;AAAA,MACP,MAAO;AAAA,MACP,MAAO;AAAA,MACP,OAAO;AAAA,IACT;AAIA,IAAM,QAAQ;AACd,IAAM,MAAQ;AAEd,IAAM,eAAuC;AAAA,MAC3C,SAAY;AAAA;AAAA,MACZ,OAAY;AAAA;AAAA,MACZ,QAAY;AAAA;AAAA,MACZ,MAAY;AAAA;AAAA,MACZ,OAAY;AAAA;AAAA,MACZ,YAAY;AAAA;AAAA,MACZ,OAAY;AAAA;AAAA,MACZ,QAAY;AAAA;AAAA,MACZ,UAAY;AAAA;AAAA,IACd;AAEA,IAAM,eAAyC;AAAA,MAC7C,OAAO;AAAA;AAAA,MACP,MAAO;AAAA;AAAA,MACP,MAAO;AAAA;AAAA,MACP,OAAO;AAAA;AAAA,IACT;AAGA,IAAM,QAAiB,QAAQ,OAAO,SAAS;AAAA;AAAA;;;AC+PxC,SAAS,YACd,IACuB;AACvB,SAAO;AACT;AA+CO,SAAS,YAAY,MAA4B;AACtD,SAAO,IAAI,aAAa,IAAI;AAC9B;AA8DO,SAAS,gBACd,IAC+B;AAC/B,SAAO,EAAE,QAAQ,aAAa,KAAK,GAAG;AACxC;AAEO,SAAS,qBACd,IACoC;AACpC,SAAO,EAAE,QAAQ,kBAAkB,KAAK,GAAG;AAC7C;AAEO,SAAS,iBACd,IACgC;AAChC,SAAO,EAAE,QAAQ,cAAc,KAAK,GAAG;AACzC;AAxaA,IAiEa,iBA0PP;AA3TN;AAAA;AAAA;AAGA;AACA;AA6DO,IAAM,kBAAN,cAA8B,UAAU;AAAA,MACpC;AAAA,MAET,YAAY,UAAkC;AAC5C,cAAM,qBAAqB,KAAK,kBAAkB;AAClD,aAAK,OAAO;AACZ,aAAK,SAAS,SAAS;AAAA,MACzB;AAAA,IACF;AAkPA,IAAM,eAAN,MAAmB;AAAA,MAGjB,YAA6B,OAAe;AAAf;AAAA,MAAgB;AAAA,MAAhB;AAAA,MAFrB,WAAwB,CAAC;AAAA,MAIjC,QAAQ,MAAyB;AAC/B,aAAK,WAAW;AAChB,eAAO;AAAA,MACT;AAAA,MAEA,MACE,IACuB;AACvB,cAAM,SAAS,oBAAoB,SAAS,KAAK,KAAK,IAAI,KAAK,SAAS,GAAG;AAC3E,cAAM,OAAO,KAAK;AAClB,eAAO,OAAO,QAAkD;AAC9D,iBAAO,MAAM,SAAS,EAAE,OAAO,KAAK,CAAC;AACrC,cAAI;AACF,kBAAM,GAAG,GAAG;AACZ,mBAAO;AAAA,UACT,SAAS,KAAK;AACZ,mBAAO,KAAK,WAAW,EAAE,OAAO,KAAK,CAAC;AACtC,kBAAM;AAAA,UACR;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAAA;AAAA;;;AC1TO,SAAS,cACd,KACA,QACA,KACwB;AACxB,MAAI,CAAC,IAAK,OAAM,IAAI,MAAM,sCAAsC;AAChE,SAAO;AAAA,IACL,MAAU,IAAI,GAAG;AAAA,IACjB,SAAU;AAAA,IACV,UAAU,EAAE,KAAK,MAAM,OAA0B;AAAA,EACnD;AACF;AAiBO,SAAS,yBAAyB,IAAoB;AAC3D,QAAM,UAAU,GAAG,KAAK;AACxB,QAAM,QAAQ,kBAAkB,KAAK,OAAO;AAC5C,MAAI,CAAC,OAAO;AACV,UAAM,IAAI;AAAA,MACR,4BAA4B,EAAE;AAAA,MAC9B;AAAA,MACA;AAAA,IACF;AAAA,EACF;AACA,QAAM,CAAC,EAAE,IAAI,IAAI,IAAI,EAAE,IAAI;AAC3B,SAAO,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE;AACzC;AAgDA,SAAS,cAAc,MAAyD;AAC9E,SAAO,OAAO,QAAQ,IAAI,EAAE;AAAA,IAC1B,CAAC,UAA2C,MAAM,CAAC,MAAM;AAAA,EAC3D;AACF;AAGA,SAAS,UAAU,KAAuC;AACxD,SAAO,OAAO,QAAQ,YAAY,QAAQ,QAAQ,QAAQ,OAAO,OAAQ,IAAgC,IAAI,MAAM;AACrH;AAGA,SAAS,iBAAiB,KAAsD;AAC9E,SACE,OAAO,QAAQ,YACf,QAAQ,QACR,UAAU,OACV,aAAa;AAEjB;AAMA,SAAS,oBACP,KACA,WACA,SACyC;AACzC,MAAI,CAAC,UAAU,SAAS,GAAG;AAEzB,WAAO,EAAE,KAAK,IAAI,GAAG,SAAS,QAAQ,CAAC,SAAyB,EAAE;AAAA,EACpE;AAEA,QAAM,KAAK;AAEX,UAAQ,GAAG,IAAI;AAAA,IACb,KAAK;AACH,aAAO,EAAE,KAAK,IAAI,GAAG,SAAS,QAAQ,CAAC,GAAG,KAAqB,EAAE;AAAA,IACnE,KAAK;AACH,aAAO,EAAE,KAAK,IAAI,GAAG,UAAU,QAAQ,CAAC,GAAG,KAAqB,EAAE;AAAA,IACpE,KAAK;AACH,aAAO,EAAE,KAAK,IAAI,GAAG,SAAS,QAAQ,CAAC,GAAG,KAAqB,EAAE;AAAA,IACnE,KAAK;AACH,aAAO,EAAE,KAAK,IAAI,GAAG,UAAU,QAAQ,CAAC,GAAG,KAAqB,EAAE;AAAA,IACpE,KAAK;AACH,aAAO,EAAE,KAAK,IAAI,GAAG,SAAS,QAAQ,CAAC,GAAG,KAAqB,EAAE;AAAA,IACnE,KAAK;AACH,aAAO,EAAE,KAAK,IAAI,GAAG,UAAU,QAAQ,CAAC,GAAG,KAAqB,EAAE;AAAA,IACpE,KAAK,MAAM;AACT,YAAM,QAAQ,GAAG;AACjB,UAAI,iBAAiB,KAAK,GAAG;AAC3B,eAAO,EAAE,KAAK,IAAI,GAAG,QAAQ,MAAM,IAAI,IAAI,QAAQ,MAAM,QAAQ;AAAA,MACnE;AACA,YAAM,OAAO;AACb,UAAI,KAAK,WAAW,GAAG;AAErB,eAAO,EAAE,KAAK,SAAS,QAAQ,CAAC,EAAE;AAAA,MACpC;AACA,YAAM,eAAe,KAAK,IAAI,MAAM,GAAG,EAAE,KAAK,IAAI;AAClD,aAAO,EAAE,KAAK,IAAI,GAAG,SAAS,YAAY,KAAK,QAAQ,KAAuB;AAAA,IAChF;AAAA,IACA,KAAK,UAAU;AACb,YAAM,QAAQ,GAAG;AACjB,UAAI,iBAAiB,KAAK,GAAG;AAC3B,eAAO,EAAE,KAAK,IAAI,GAAG,YAAY,MAAM,IAAI,IAAI,QAAQ,MAAM,QAAQ;AAAA,MACvE;AACA,YAAM,OAAO;AACb,UAAI,KAAK,WAAW,GAAG;AAErB,eAAO,EAAE,KAAK,SAAS,QAAQ,CAAC,EAAE;AAAA,MACpC;AACA,YAAM,eAAe,KAAK,IAAI,MAAM,GAAG,EAAE,KAAK,IAAI;AAClD,aAAO,EAAE,KAAK,IAAI,GAAG,aAAa,YAAY,KAAK,QAAQ,KAAuB;AAAA,IACpF;AAAA,IACA,KAAK;AACH,aAAO,EAAE,KAAK,IAAI,GAAG,YAAY,QAAQ,CAAC,GAAG,KAAqB,EAAE;AAAA,IACtE,KAAK;AACH,UAAI,YAAY,YAAY;AAC1B,eAAO,EAAE,KAAK,IAAI,GAAG,aAAa,QAAQ,CAAC,GAAG,KAAqB,EAAE;AAAA,MACvE;AAEA,aAAO,EAAE,KAAK,UAAU,GAAG,oBAAoB,QAAQ,CAAC,GAAG,KAAqB,EAAE;AAAA,IACpF,KAAK;AACH,aAAO,EAAE,KAAK,IAAI,GAAG,aAAa,QAAQ,CAAC,EAAE;AAAA,IAC/C,KAAK;AACH,aAAO,EAAE,KAAK,IAAI,GAAG,iBAAiB,QAAQ,CAAC,EAAE;AAAA,EACrD;AACF;AAmBO,SAAS,WACd,YACA,UAAsB,UACmB;AAEzC,MAAI,QAAQ,cAAc,MAAM,QAAS,WAA+B,EAAE,GAAG;AAC3E,UAAM,WAAY,WAA6D;AAC/E,UAAM,QAAkB,CAAC;AACzB,UAAMC,UAAyB,CAAC;AAChC,eAAW,UAAU,UAAU;AAC7B,YAAM,EAAE,KAAK,QAAQ,EAAE,IAAI,WAAW,QAAQ,OAAO;AACrD,UAAI,KAAK;AACP,cAAM,KAAK,GAAG;AACd,QAAAA,QAAO,KAAK,GAAG,CAAC;AAAA,MAClB;AAAA,IACF;AACA,QAAI,MAAM,WAAW,EAAG,QAAO,EAAE,KAAK,IAAI,QAAQ,CAAC,EAAE;AACrD,QAAI,MAAM,WAAW,EAAG,QAAO,EAAE,KAAK,MAAM,CAAC,GAAI,QAAAA,QAAO;AACxD,WAAO,EAAE,KAAK,IAAI,MAAM,KAAK,MAAM,CAAC,KAAK,QAAAA,QAAO;AAAA,EAClD;AAGA,MAAI,SAAS,cAAc,MAAM,QAAS,WAAgC,GAAG,GAAG;AAC9E,UAAM,WAAY,WAA8D;AAChF,UAAM,QAAkB,CAAC;AACzB,UAAMA,UAAyB,CAAC;AAChC,eAAW,UAAU,UAAU;AAC7B,YAAM,EAAE,KAAK,QAAQ,EAAE,IAAI,WAAW,QAAQ,OAAO;AACrD,UAAI,KAAK;AACP,cAAM,KAAK,GAAG;AACd,QAAAA,QAAO,KAAK,GAAG,CAAC;AAAA,MAClB;AAAA,IACF;AACA,QAAI,MAAM,WAAW,EAAG,QAAO,EAAE,KAAK,IAAI,QAAQ,CAAC,EAAE;AACrD,QAAI,MAAM,WAAW,EAAG,QAAO,EAAE,KAAK,MAAM,CAAC,GAAI,QAAAA,QAAO;AACxD,WAAO,EAAE,KAAK,IAAI,MAAM,KAAK,OAAO,CAAC,KAAK,QAAAA,QAAO;AAAA,EACnD;AAGA,QAAM,UAAU,OAAO,QAAQ,UAAU,EAAE,OAAO,CAAC,CAAC,EAAE,CAAC,MAAM,MAAM,MAAS;AAC5E,MAAI,QAAQ,WAAW,EAAG,QAAO,EAAE,KAAK,IAAI,QAAQ,CAAC,EAAE;AAEvD,QAAM,WAAqB,CAAC;AAC5B,QAAM,SAAyB,CAAC;AAEhC,aAAW,CAAC,KAAK,KAAK,KAAK,SAAS;AAClC,UAAM,EAAE,KAAK,QAAQ,EAAE,IAAI,oBAAoB,KAAK,OAAO,OAAO;AAClE,aAAS,KAAK,GAAG;AACjB,WAAO,KAAK,GAAG,CAAC;AAAA,EAClB;AAEA,SAAO,EAAE,KAAK,SAAS,KAAK,OAAO,GAAG,OAAO;AAC/C;AAUO,SAAS,YACd,WACA,MACA,YAAY,MAC6B;AACzC,QAAM,UAAU,cAAc,IAAI;AAClC,QAAM,OAAS,QAAQ,IAAI,CAAC,CAAC,GAAG,MAAM,IAAI,GAAG,GAAG,EAAE,KAAK,IAAI;AAC3D,QAAM,eAAe,QAAQ,IAAI,MAAM,GAAG,EAAE,KAAK,IAAI;AACrD,QAAM,SAAS,QAAQ,IAAI,CAAC,CAAC,EAAE,GAAG,MAAM,GAAG;AAC3C,QAAM,mBAAmB,YAAY,iBAAiB;AACtD,QAAM,MAAM,gBAAgB,SAAS,MAAM,IAAI,aAAa,YAAY,IAAI,gBAAgB;AAC5F,SAAO,EAAE,KAAK,OAAO;AACvB;AAUO,SAAS,gBACd,WACA,MACA,YAAY,MAC6B;AACzC,MAAI,KAAK,WAAW,GAAG;AACrB,UAAM,IAAI,MAAM,0CAA0C;AAAA,EAC5D;AAEA,QAAM,UAAU,OAAO,KAAK,KAAK,CAAC,CAAE;AACpC,QAAM,aAAa,QAAQ,IAAI,CAAC,MAAM,IAAI,CAAC,GAAG,EAAE,KAAK,IAAI;AACzD,QAAM,SAAyB,CAAC;AAChC,QAAM,eAAyB,CAAC;AAEhC,aAAW,OAAO,MAAM;AACtB,UAAM,eAAyB,CAAC;AAChC,eAAW,OAAO,SAAS;AACzB,YAAM,MAAM,IAAI,GAAG;AACnB,UAAI,QAAQ,QAAW;AACrB,cAAM,IAAI,MAAM,uBAAuB,GAAG,4EAAuE;AAAA,MACnH;AACA,aAAO,KAAK,GAAG;AACf,mBAAa,KAAK,GAAG;AAAA,IACvB;AACA,iBAAa,KAAK,IAAI,aAAa,KAAK,IAAI,CAAC,GAAG;AAAA,EAClD;AAEA,QAAM,mBAAmB,YAAY,iBAAiB;AACtD,QAAM,MAAM,gBAAgB,SAAS,MAAM,UAAU,YAAY,aAAa,KAAK,IAAI,CAAC,GAAG,gBAAgB;AAC3G,SAAO,EAAE,KAAK,OAAO;AACvB;AASO,SAAS,sBACd,WACA,KACA,OACA,OACA,UAAyB,UACgB;AACzC,QAAM,aAA2B,iBAAiB,OAAO,MAAM,YAAY,IAAI;AAC/E,QAAM,EAAE,KAAK,UAAU,QAAQ,YAAY,IAAI,WAAW,OAAO,OAAO;AACxE,QAAM,SAAS,IAAI,GAAG;AACtB,QAAM,MAAM,WACR,WAAW,SAAS,SAAS,MAAM,UAAU,QAAQ,KACrD,WAAW,SAAS,SAAS,MAAM;AACvC,SAAO,EAAE,KAAK,QAAQ,CAAC,YAAY,GAAG,WAAW,EAAE;AACrD;AAOO,SAAS,YACd,WACA,OACA,IACA,SACyC;AACzC,QAAM,UAAU,cAAc,KAAK;AACnC,QAAM,OAAS,QAAQ,IAAI,CAAC,CAAC,GAAG,MAAM,IAAI,GAAG,OAAO,EAAE,KAAK,IAAI;AAC/D,QAAM,SAAyB,CAAC,GAAG,QAAQ,IAAI,CAAC,CAAC,EAAE,GAAG,MAAM,GAAG,GAAG,OAAO;AACzE,QAAM,MAAM,WAAW,SAAS,SAAS,IAAI,WAAW,EAAE;AAC1D,SAAO,EAAE,KAAK,OAAO;AACvB;AAMO,SAAS,YACd,WACA,IACA,SACyC;AACzC,QAAM,MAAM,gBAAgB,SAAS,YAAY,EAAE;AACnD,SAAO,EAAE,KAAK,QAAQ,CAAC,OAAO,EAAE;AAClC;AAOO,SAAS,eACd,OACA,KACG;AACH,QAAM,SAAkC,CAAC;AACzC,aAAW,CAAC,KAAK,GAAG,KAAK,OAAO,QAAQ,MAAM,MAAM,GAAG;AACrD,UAAM,IAAI;AACV,UAAM,MAAM,IAAI,GAAG;AACnB,QAAI,EAAE,IAAI,SAAS,eAAe,QAAQ,QAAQ,QAAQ,QAAW;AACnE,aAAO,GAAG,IAAI,IAAI,KAAK,GAAa;AAAA,IACtC,OAAO;AACL,aAAO,GAAG,IAAI;AAAA,IAChB;AAAA,EACF;AACA,SAAO;AACT;AAqBO,SAAS,2BAA2B,SAAiC;AAC1E,QAAM,OAAiB,CAAC;AAGxB,MAAI,SAAS,WAAW,QAAQ,QAAQ,SAAS,GAAG;AAClD,SAAK,KAAK,GAAG,QAAQ,QAAQ,IAAI,CAAC,MAAM,IAAI,CAAC,GAAG,CAAC;AAAA,EACnD,WAAW,CAAC,SAAS,cAAc,QAAQ,WAAW,WAAW,GAAG;AAElE,SAAK,KAAK,GAAG;AAAA,EACf,WAAW,SAAS,WAAW,QAAQ,QAAQ,SAAS,GAAG;AAEzD,SAAK,KAAK,GAAG,QAAQ,QAAQ,IAAI,CAAC,MAAM,IAAI,CAAC,GAAG,CAAC;AAAA,EACnD,OAAO;AAAA,EAEP;AAGA,MAAI,SAAS,cAAc,QAAQ,WAAW,SAAS,GAAG;AACxD,eAAW,OAAO,QAAQ,YAAY;AACpC,YAAM,UAAU,IAAI,MAAM,IAAI,IAAI,GAAG,MAAM;AAC3C,WAAK,KAAK,GAAG,IAAI,EAAE,IAAI,OAAO,SAAS,IAAI,KAAK,GAAG;AAAA,IACrD;AAAA,EACF;AAEA,SAAO,KAAK,SAAS,IAAI,KAAK,KAAK,IAAI,IAAI;AAC7C;AAGA,SAAS,yBACP,OACA,SACM;AACN,MAAI,SAAS,WAAW,QAAQ,QAAQ,SAAS,GAAG;AAClD,UAAM,SAAS,QAAQ,QACpB,IAAI,CAAC,EAAE,KAAK,IAAI,MAAM,IAAI,GAAG,KAAK,GAAG,EAAE,EACvC,KAAK,IAAI;AACZ,UAAM,KAAK,YAAY,MAAM,EAAE;AAAA,EACjC;AAOA,MAAI,SAAS,UAAU,UAAa,SAAS,WAAW,QAAW;AACjE,UAAM,WAAW,SAAS,UAAU,SAChC,KAAK,MAAM,KAAK,IAAI,GAAG,QAAQ,KAAK,CAAC,IACrC;AACJ,UAAM,KAAK,SAAS,QAAQ,EAAE;AAE9B,QAAI,SAAS,WAAW,QAAW;AACjC,YAAM,KAAK,UAAU,KAAK,MAAM,KAAK,IAAI,GAAG,QAAQ,MAAM,CAAC,CAAC,EAAE;AAAA,IAChE;AAAA,EACF;AACF;AAQO,SAAS,WACd,OACA,MACA,UAA8E,CAAC,GACtC;AACzC,MAAI,MAAM,SAAS,GAAG;AACpB,UAAM,IAAI,MAAM,uCAAuC;AAAA,EACzD;AACA,QAAM,OAAS,MAAM,IAAI,CAAC,MAAM,EAAE,GAAG;AACrC,QAAM,SAAS,MAAM,QAAQ,CAAC,MAAM,EAAE,MAAM;AAC5C,MAAI,MAAM,KAAK,KAAK,IAAI,IAAI,GAAG;AAC/B,MAAI,QAAQ,SAAS;AACnB,WAAO,cAAc,QAAQ,QAAQ,GAAG,KAAK,QAAQ,QAAQ,OAAO,KAAK;AAAA,EAC3E;AACA,MAAI,QAAQ,UAAU,QAAW;AAC/B,WAAO,UAAU,KAAK,MAAM,KAAK,IAAI,GAAG,QAAQ,KAAK,CAAC,CAAC;AAAA,EACzD;AACA,SAAO,EAAE,KAAK,OAAO;AACvB;AAMO,SAAS,YACd,WACA,YACA,SACA,UAAsB,UACmB;AACzC,QAAM,aAAa,2BAA2B,OAAO;AACrD,QAAM,EAAE,KAAK,UAAU,OAAO,IAAI,WAAW,YAAY,OAAO;AAChE,QAAM,gBAAgB,SAAS,WAAW,oBAAoB;AAE9D,QAAM,QAAkB;AAAA,IACtB,WACI,GAAG,aAAa,IAAI,UAAU,UAAU,SAAS,WAAW,QAAQ,KACpE,GAAG,aAAa,IAAI,UAAU,UAAU,SAAS;AAAA,EACvD;AAGA,MAAI,SAAS,WAAW,QAAQ,QAAQ,SAAS,GAAG;AAClD,UAAM,KAAK,YAAY,QAAQ,QAAQ,IAAI,CAAC,MAAM,IAAI,CAAC,GAAG,EAAE,KAAK,IAAI,CAAC,EAAE;AAAA,EAC1E;AAGA,MAAI,SAAS,QAAQ;AACnB,UAAM,EAAE,KAAK,WAAW,QAAQ,aAAa,IAAI,WAAW,QAAQ,QAAQ,OAAO;AACnF,QAAI,WAAW;AACb,YAAM,KAAK,UAAU,SAAS,EAAE;AAChC,aAAO,KAAK,GAAG,YAAY;AAAA,IAC7B;AAAA,EACF;AAEA,2BAAyB,OAAO,OAAO;AAEvC,SAAO,EAAE,KAAK,MAAM,KAAK,GAAG,GAAG,OAAO;AACxC;AAaA,SAAS,eAAe,KAAqB;AAC3C,MAAI,QAAQ,IAAK,QAAO;AACxB,QAAM,SAAS,IAAI,QAAQ,GAAG;AAC9B,MAAI,WAAW,IAAI;AACjB,UAAM,QAAS,IAAI,MAAM,GAAG,MAAM;AAClC,UAAMC,UAAS,IAAI,MAAM,SAAS,CAAC;AACnC,QAAIA,YAAW,IAAK,QAAO,IAAI,KAAK;AACpC,WAAO,IAAI,KAAK,MAAMA,OAAM;AAAA,EAC9B;AACA,SAAO,IAAI,GAAG;AAChB;AAEO,SAAS,gBACd,WACA,SACA,OACA,OACA,QACA,SACyC;AACzC,QAAM,OAAO,QAAQ,SAAS,IAC1B,QAAQ,IAAI,cAAc,EAAE,KAAK,IAAI,IACrC;AACJ,QAAM,QAAkB,CAAC,UAAU,IAAI,UAAU,SAAS,GAAG;AAE7D,aAAW,KAAK,OAAO;AACrB,UAAM,WAAW,yBAAyB,EAAE,EAAE;AAC9C,UAAM,KAAK,GAAG,EAAE,IAAI,UAAU,EAAE,KAAK,QAAQ,QAAQ,EAAE;AAAA,EACzD;AAEA,MAAI,MAAO,OAAM,KAAK,SAAS,KAAK,EAAE;AAGtC,QAAM,YAAY,CAAC,GAAG,MAAM;AAE5B,2BAAyB,OAAO,OAAO;AAEvC,SAAO,EAAE,KAAK,MAAM,KAAK,IAAI,GAAG,QAAQ,UAAU;AACpD;AA5lBA,IAqDM;AArDN;AAAA;AAAA;AAGA;AAkDA,IAAM,oBAAoB;AAAA;AAAA;;;ACrD1B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAwZA,SAAS,cACP,GACA,GACe;AACf,QAAM,WAAW,EAAE,QAAQ,MAAM,EAAE,SAAS;AAC5C,QAAM,WAAW,EAAE,QAAQ,MAAM,EAAE,SAAS;AAC5C,MAAI,YAAY,UAAU;AACxB,WAAO,EAAE,GAAI,GAAc,GAAI,EAAa;AAAA,EAC9C;AACA,SAAO,EAAE,KAAK,CAAC,GAAG,CAAC,EAAE;AACvB;AAlaA,IA6Ca,QAcA,aA2WA,eA2uBA,yBAyFA,mBA+CA,cA4EA,eAiIA;AAt+Cb;AAAA;AAAA;AAGA;AACA;AACA;AAwCO,IAAM,SAAN,MAAa;AAAA,MAClB,YACmB,SACA,OACjB;AAFiB;AACA;AAAA,MAChB;AAAA,MAFgB;AAAA,MACA;AAAA;AAAA,MAInB,QAAQ,KAAc,OAA2B,UAAkC;AACjF,eAAO,IAAI,YAAY,KAAK,SAAS,KAAK,OAAO,KAAK,OAAO,QAAQ;AAAA,MACvE;AAAA,IACF;AAIO,IAAM,cAAN,MAAM,aAAY;AAAA,MAKvB,YACE,SACiB,OACA,KAEA,OAIjB,UACiB,UAAsB,UACvC;AATiB;AACA;AAEA;AAKA;AAEjB,YAAI,UAAU;AACZ,gBAAM,MAAM;AACZ,eAAK,UAAU;AAAA,YACb,OAAO,OAAU,KAAa,SAAyB,CAAC,MAAM;AAC5D,oBAAM,KAAK,YAAY,IAAI;AAC3B,oBAAM,OAAO,MAAM,QAAQ,MAAS,KAAK,MAAM;AAC/C,oBAAM,aAAa,YAAY,IAAI,IAAI;AACvC,mBAAK;AACL,kBAAI;AACJ,kBAAI,WAAW;AACf,kBAAI,IAAI,WAAY,KAAI,QAAQ,KAAK,EAAE,KAAK,QAAQ,YAAY,MAAM,QAAQ,CAAC;AAC/E,qBAAO;AAAA,YACT;AAAA,YACA,SAAS,OAAO,KAAa,SAAyB,CAAC,MAAM;AAC3D,oBAAM,KAAK,YAAY,IAAI;AAC3B,oBAAM,SAAS,MAAM,QAAQ,QAAQ,KAAK,MAAM;AAChD,oBAAM,aAAa,YAAY,IAAI,IAAI;AACvC,mBAAK;AACL,kBAAI;AACJ,kBAAI,WAAW;AACf,kBAAI,IAAI,WAAY,KAAI,QAAQ,KAAK,EAAE,KAAK,QAAQ,YAAY,MAAM,UAAU,CAAC;AACjF,qBAAO;AAAA,YACT;AAAA,YACA,aAAa,CAAC,OAAO,QAAQ,YAAY,EAAE;AAAA,YAC3C,OAAO,MAAM,QAAQ,MAAM;AAAA,YAC3B,SAAS,QAAQ;AAAA,UACnB;AAAA,QACF,OAAO;AACL,eAAK,UAAU;AAAA,QACjB;AAAA,MACF;AAAA,MAxCmB;AAAA,MACA;AAAA,MAEA;AAAA,MAKA;AAAA;AAAA,MAbnB,cAAc;AAAA,MACG;AAAA;AAAA,MA+CjB,KACE,OACiC;AACjC,eAAO,IAAI,cAAgC,KAAK,SAAS,KAAK,OAAO,KAAK,KAAK,KAAK,OAAO,OAA0C,CAAC,CAAC;AAAA,MACzI;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,MAcA,KAAK,WAAgC;AACnC,eAAO,IAAI,YAAY,KAAK,SAAS,WAAW,CAAC,GAAG,CAAC,GAAG,IAAI,CAAC,CAAC;AAAA,MAChE;AAAA,MAEA,KAA6B,OAA4C;AACvE,eAAO,IAAI,cAAoB,KAAK,SAAS,KAAK,OAAO,KAAK,KAAK,KAAK,OAAO,OAAO,KAAK,OAAO;AAAA,MACpG;AAAA;AAAA,MAkCA,MAAM,aAMJ,SACA,mBACA,eACA,YACgC;AAEhC,YAAI,eAAe,QAAW;AAC5B,iBAAO,KAAK;AAAA,YACV;AAAA,YACA;AAAA,YACA;AAAA,YACA;AAAA,UACF;AAAA,QACF;AAGA,cAAM,aAAa;AACnB,cAAM,aAAa;AACnB,cAAM,SAAS,oBAAI,IAA4B;AAC/C,YAAI,QAAQ,WAAW,EAAG,QAAO;AAEjC,cAAM,MAAM,CAAC,GAAG,IAAI,IAAI,QAAQ,IAAI,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC,CAAC;AAC1D,cAAM,WAAW,MAAM,KAAK,KAAK,UAAU,EACxC,MAAM,EAAE,CAAC,UAAU,GAAG,EAAE,IAAI,MAAM,OAAO,IAAI,EAAE,CAAuB,EACtE,OAAO;AAEV,mBAAW,SAAS,UAAU;AAC5B,gBAAM,MAAM,MAAM,UAAU;AAC5B,gBAAM,QAAQ,OAAO,IAAI,GAAG;AAC5B,cAAI,OAAO;AACT,kBAAM,KAAK,KAAK;AAAA,UAClB,OAAO;AACL,mBAAO,IAAI,KAAK,CAAC,KAAK,CAAC;AAAA,UACzB;AAAA,QACF;AACA,eAAO;AAAA,MACT;AAAA;AAAA,MAiCA,MAAM,gBAMJ,SACA,mBACA,eACA,YACgC;AAEhC,YAAI,eAAe,QAAW;AAC5B,iBAAO,KAAK;AAAA,YACV;AAAA,YACA;AAAA,YACA;AAAA,YACA;AAAA,UACF;AAAA,QACF;AAGA,cAAM,aAAa;AACnB,cAAM,aAAa;AACnB,cAAM,SAAS,oBAAI,IAA0B;AAC7C,YAAI,QAAQ,WAAW,EAAG,QAAO;AAEjC,cAAM,MAAM,CAAC,GAAG,IAAI,IAAI,QAAQ,IAAI,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC,CAAC;AAC1D,cAAM,WAAW,MAAM,KAAK,KAAK,UAAU,EACxC,MAAM,EAAE,CAAC,UAAU,GAAG,EAAE,IAAI,MAAM,OAAO,IAAI,EAAE,CAAuB,EACtE,OAAO;AAEV,mBAAW,SAAS,UAAU;AAC5B,iBAAO,IAAI,MAAM,UAAU,GAA8B,KAAK;AAAA,QAChE;AACA,eAAO;AAAA,MACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,MAOA,MAAc,oBACZ,SACA,cACA,aACA,MACgC;AAChC,cAAM,MAAM,YAAY,UAAU,YAAY;AAE9C,YAAI,QAAQ,QAAW;AACrB,gBAAM,YAAY,OAAO,KAAK,YAAY,SAAS,EAAE,KAAK,IAAI,KAAK;AACnE,gBAAM,IAAI;AAAA,YACR,aAAa,YAAY,8BAA8B,YAAY,IAAI,2BAC/C,SAAS;AAAA,UACnC;AAAA,QACF;AAEA,YAAI,IAAI,SAAS,cAAc;AAC7B,gBAAM,IAAI;AAAA,YACR,+FACmC,YAAY,eAAe,YAAY,IAAI;AAAA,UAChF;AAAA,QACF;AAEA,YAAI,SAAS,SAAS,IAAI,SAAS,WAAW;AAC5C,gBAAM,IAAI;AAAA,YACR,yDAAyD,YAAY,eAAe,YAAY,IAAI;AAAA,UAEtG;AAAA,QACF;AAEA,cAAM,eAAe,IAAI,SAAS;AAClC,cAAM,KAAK,aAAa;AAExB,YAAI,IAAI,SAAS,aAAa;AAK5B,gBAAM,KAAK;AACX,gBAAM,KAAK,IAAI;AACf,cAAI,SAAS,OAAO;AAClB,mBAAO,KAAK,gBAAgB,SAAS,IAAI,IAAI,EAAE;AAAA,UACjD;AACA,iBAAO,KAAK,aAAa,SAAS,IAAI,IAAI,EAAE;AAAA,QAC9C;AAIA,cAAM,WAAW,YAAY;AAC7B,cAAM,SAAS,oBAAI,IAAwB;AAC3C,YAAI,QAAQ,WAAW,EAAG,QAAO;AAEjC,cAAM,MAAM,CAAC,GAAG,IAAI,IAAI,QAAQ,IAAI,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC,CAAC;AACxD,cAAM,WAAW,MAAM,KAAK,KAAK,YAAY,EAC1C,MAAM,EAAE,CAAC,IAAI,UAAU,GAAG,EAAE,IAAI,MAAM,OAAO,IAAI,EAAE,CAAoC,EACvF,OAAO;AAEV,mBAAW,SAAS,UAAuC;AACzD,gBAAM,MAAM,MAAM,IAAI,UAAU;AAChC,gBAAM,QAAQ,OAAO,IAAI,GAAG;AAC5B,cAAI,OAAO;AACT,kBAAM,KAAK,KAAK;AAAA,UAClB,OAAO;AACL,mBAAO,IAAI,KAAK,CAAC,KAAK,CAAC;AAAA,UACzB;AAAA,QACF;AACA,eAAO;AAAA,MACT;AAAA,MAEA,MAAM,YAAe,IAAoE;AAOvF,cAAM,UAAU,IAAI,kBAAkB;AAEtC,cAAM,SAAS,MAAM,KAAK,QAAQ,YAAY,OAAO,cAAc;AACjE,gBAAM,UAAU,IAAI,aAAY,WAAW,KAAK,OAAO,KAAK,KAAK,OAAO;AACxE,iBAAO,GAAG,OAAO;AAAA,QACnB,CAAC;AAED,eAAO,EAAE,QAAQ,QAAQ,QAAQ,MAAM,EAAE;AAAA,MAC3C;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,MAiBA,MAAM,IACJ,KACA,SAA0B,CAAC,GAC3B,QACc;AACd,cAAM,OAAO,MAAM,KAAK,QAAQ,MAA+B,KAAK,MAAM;AAC1E,YAAI,CAAC,OAAQ,QAAO;AACpB,eAAO,KAAK,IAAI,CAAC,QAAQ;AACvB,cAAI;AACF,mBAAO,OAAO,MAAM,GAAG;AAAA,UACzB,SAAS,KAAK;AAEZ,kBAAM,IAAI,gBAAgB,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG,CAAC;AAAA,UAC5E;AAAA,QACF,CAAC;AAAA,MACH;AAAA,IACF;AAoBO,IAAM,gBAAN,MAAM,eAAsF;AAAA,MACjG,YACmB,SACA,OACA,KACA,OAEA,OACA,YACA,WAA0B,CAAC,GAE3B,YAAuD,CAAC,GACxD,WAAuB,UACvB,iBAA2B,CAAC,GAE5B,kBAA2B,OAC5C;AAdiB;AACA;AACA;AACA;AAEA;AACA;AACA;AAEA;AACA;AACA;AAEA;AAAA,MAChB;AAAA,MAdgB;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MAEA;AAAA,MACA;AAAA,MACA;AAAA,MAEA;AAAA,MACA;AAAA,MACA;AAAA,MAEA;AAAA,MAGX,WACN,YACA,UACiC;AACjC,eAAO,IAAI;AAAA,UACT,KAAK;AAAA,UACL,KAAK;AAAA,UACL,KAAK;AAAA,UACL,KAAK;AAAA,UACL,KAAK;AAAA,UACL;AAAA,UACA,KAAK;AAAA,UACL,YAAY,KAAK;AAAA,UACjB,KAAK;AAAA,UACL,KAAK;AAAA,UACL,KAAK;AAAA,QACP;AAAA,MACF;AAAA,MAEQ,OAAO,OAAgE;AAC7E,eAAO,IAAI;AAAA,UACT,KAAK;AAAA,UACL,KAAK;AAAA,UACL,KAAK;AAAA,UACL,KAAK;AAAA,UACL,KAAK;AAAA,UACL,KAAK;AAAA,UACL,EAAE,GAAG,KAAK,UAAU,GAAG,MAAM;AAAA,UAC7B,KAAK;AAAA,UACL,KAAK;AAAA,UACL,KAAK;AAAA,UACL,KAAK;AAAA,QACP;AAAA,MACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,MAWA,KACE,WACiF;AACjF,cAAM,OAAO,OAAO,KAAK,SAAS;AAClC,eAAO,IAAI;AAAA,UACT,KAAK;AAAA,UACL,KAAK;AAAA,UACL,KAAK;AAAA,UACL,KAAK;AAAA;AAAA,UAEL,KAAK;AAAA,UACL,KAAK;AAAA,UACL,KAAK;AAAA,UACL,KAAK;AAAA,UACL,KAAK;AAAA,UACL,CAAC,GAAG,KAAK,gBAAgB,GAAG,IAAI;AAAA,UAChC,KAAK;AAAA,QACP;AAAA,MACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,MAYA,cAA+C;AAC7C,eAAO,IAAI;AAAA,UACT,KAAK;AAAA,UACL,KAAK;AAAA,UACL,KAAK;AAAA,UACL,KAAK;AAAA,UACL,KAAK;AAAA,UACL,KAAK;AAAA,UACL,KAAK;AAAA,UACL,KAAK;AAAA,UACL,KAAK;AAAA,UACL,KAAK;AAAA,UACL;AAAA,QACF;AAAA,MACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,MAWA,MAAM,YAA4D;AAChE,cAAM,SAAS,cAAc,KAAK,YAAY,UAAU;AACxD,eAAO,KAAK,WAAW,MAAM;AAAA,MAC/B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,MAUA,SAAS,KAAa,QAAyD;AAC7E,eAAO,KAAK,WAAW,KAAK,YAAY,CAAC,GAAG,KAAK,WAAW,EAAE,KAAK,OAAO,CAAC,CAAC;AAAA,MAC9E;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,MAUA,WAA4C;AAC1C,eAAO,KAAK,OAAO,EAAE,UAAU,KAAK,CAAC;AAAA,MACvC;AAAA;AAAA,MAGA,MAAM,GAA4C;AAChD,eAAO,KAAK,OAAO,EAAE,OAAO,EAAE,CAAC;AAAA,MACjC;AAAA;AAAA,MAGA,OAAO,GAA4C;AACjD,eAAO,KAAK,OAAO,EAAE,QAAQ,EAAE,CAAC;AAAA,MAClC;AAAA;AAAA,MAGA,QAAQ,KAAuB,MAAsB,OAAwC;AAC3F,cAAM,WAAW,KAAK,SAAS,WAAW,CAAC;AAC3C,eAAO,KAAK,OAAO,EAAE,SAAS,CAAC,GAAG,UAAU,EAAE,KAAK,IAAI,CAAC,EAAE,CAAC;AAAA,MAC7D;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,MAOA,KAAK,MAAc,MAA+C;AAChE,eAAO,KAAK,OAAO,EAAE,OAAO,MAAM,SAAS,OAAO,KAAK,KAAK,CAAC;AAAA,MAC/D;AAAA,MAaA,WAAuC,MAAuG;AAC5I,cAAM,SAAS,KAAK,OAAO,EAAE,SAAS,KAAK,CAAC;AAC5C,YAAI,KAAK,WAAW,GAAG;AACrB,iBAAO,IAAI,wBAAgD,QAAQ,KAAK,CAAC,CAAE;AAAA,QAC7E;AACA,eAAO;AAAA,MACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,MAOA,cAA2B;AAAE,eAAO,KAAK;AAAA,MAAQ;AAAA;AAAA,MAEjD,cAA0B;AAAE,eAAO,KAAK;AAAA,MAAS;AAAA;AAAA;AAAA;AAAA;AAAA,MAMzC,uBAAsC;AAC5C,cAAM,MAAM,KAAK,MAAM;AACvB,YAAI,QAAQ,QAAQ,KAAK,gBAAiB,QAAO,KAAK;AACtD,cAAM,aAAa,EAAE,CAAC,GAAG,GAAG,EAAE,IAAI,UAAU,EAAE;AAC9C,eAAO,cAAc,KAAK,YAAY,UAAU;AAAA,MAClD;AAAA,MAEA,kBAA2D;AACzD,cAAM,aAAa,KAAK,qBAAqB;AAC7C,YAAI,KAAK,UAAU,WAAW,GAAG;AAC/B,iBAAO;AAAA,YACL,KAAK,MAAM;AAAA,YACX;AAAA,YACA,KAAK;AAAA,YACL,KAAK;AAAA,UACP;AAAA,QACF;AAEA,cAAM,EAAE,KAAK,UAAU,QAAQ,YAAY,IAAI;AAAA,UAC7C;AAAA,UACA,KAAK;AAAA,QACP;AACA,cAAM,gBAA0B,CAAC;AACjC,cAAM,YAA4B,CAAC,GAAG,WAAW;AACjD,YAAI,SAAU,eAAc,KAAK,QAAQ;AACzC,mBAAW,OAAO,KAAK,WAAW;AAChC,wBAAc,KAAK,IAAI,GAAG;AAC1B,oBAAU,KAAK,GAAG,IAAI,MAAM;AAAA,QAC9B;AACA,cAAM,gBAAgB,cAAc,KAAK,OAAO;AAChD,cAAM,aAAa,2BAA2B,KAAK,QAAQ;AAC3D,cAAM,gBAAgB,KAAK,SAAS,WAAW,oBAAoB;AACnE,cAAM,QAAkB;AAAA,UACtB,gBACI,GAAG,aAAa,IAAI,UAAU,UAAU,KAAK,MAAM,IAAI,WAAW,aAAa,KAC/E,GAAG,aAAa,IAAI,UAAU,UAAU,KAAK,MAAM,IAAI;AAAA,QAC7D;AACA,YAAI,KAAK,SAAS,WAAW,KAAK,SAAS,QAAQ,SAAS,GAAG;AAC7D,gBAAM,SAAS,KAAK,SAAS,QAAQ,IAAI,CAAC,EAAE,KAAK,IAAI,MAAM,IAAI,GAAG,KAAK,GAAG,EAAE,EAAE,KAAK,IAAI;AACvF,gBAAM,KAAK,YAAY,MAAM,EAAE;AAAA,QACjC;AACA,YAAI,KAAK,SAAS,UAAU,UAAa,KAAK,SAAS,WAAW,QAAW;AAC3E,gBAAM,WAAW,KAAK,SAAS,UAAU,SACrC,KAAK,MAAM,KAAK,IAAI,GAAG,KAAK,SAAS,KAAK,CAAC,IAC3C;AACJ,gBAAM,KAAK,SAAS,QAAQ,EAAE;AAC9B,cAAI,KAAK,SAAS,WAAW,QAAW;AACtC,kBAAM,KAAK,UAAU,KAAK,MAAM,KAAK,IAAI,GAAG,KAAK,SAAS,MAAM,CAAC,CAAC,EAAE;AAAA,UACtE;AAAA,QACF;AACA,eAAO,EAAE,KAAK,MAAM,KAAK,GAAG,GAAG,QAAQ,UAAU;AAAA,MACnD;AAAA;AAAA;AAAA;AAAA;AAAA,MAMA,WAAW,MAA6D;AACtE,eAAO,KAAK,OAAO,EAAE,SAAS,KAAiB,CAAC;AAAA,MAClD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,MASA,OAAO,YAAkF;AACvF,eAAO,KAAK,OAAO,EAAE,QAAQ,WAAW,CAAC;AAAA,MAC3C;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,MAYA,MAAM,UACJ,YACgC;AAChC,cAAM,aAAgC,OAAO,QAAQ,UAAU,EAAE,IAAI,CAAC,CAAC,OAAO,GAAG,OAAO;AAAA,UACtF;AAAA,UACA,IAAM,IAAoD;AAAA,UAC1D,KAAM,IAAoD;AAAA,QAC5D,EAAE;AAGF,cAAM,EAAE,KAAK,OAAO,IAAI;AAAA,UACtB,KAAK,MAAM;AAAA,UACX,KAAK,qBAAqB;AAAA,UAC1B,EAAE,GAAG,KAAK,UAAU,YAAY,WAAW;AAAA,UAC3C,KAAK;AAAA,QACP;AAEA,cAAM,OAAO,MAAM,KAAK,QAAQ,MAA+B,KAAK,MAAM;AAC1E,eAAO;AAAA,MACT;AAAA;AAAA;AAAA;AAAA,MAMA,MAAM,MAAM,KAAyC;AACnD,eAAO,KAAK,iBAAiB,SAAS,GAAG;AAAA,MAC3C;AAAA;AAAA,MAGA,MAAM,IAAI,KAAwC;AAChD,eAAO,KAAK,iBAAiB,OAAO,GAAG;AAAA,MACzC;AAAA;AAAA,MAGA,MAAM,IAAI,KAAwC;AAChD,eAAO,KAAK,iBAAiB,OAAO,GAAG;AAAA,MACzC;AAAA;AAAA,MAGA,MAAM,IAAI,KAAwD;AAChE,eAAO,KAAK,oBAAoB,OAAO,GAAG;AAAA,MAC5C;AAAA;AAAA,MAGA,MAAM,IAAI,KAAwD;AAChE,eAAO,KAAK,oBAAoB,OAAO,GAAG;AAAA,MAC5C;AAAA,MAEA,MAAc,iBAAiB,IAA2B,KAAyC;AACjG,cAAM,MAAM,MAAM,KAAK,oBAAoB,IAAI,GAAG;AAClD,YAAI,QAAQ,QAAQ,QAAQ,OAAW,QAAO;AAC9C,eAAO,OAAO,GAAG;AAAA,MACnB;AAAA,MAEA,MAAc,oBAAoB,IAA2B,KAAyD;AACpH,cAAM,QAAQ;AACd,cAAM,UAAU,MAAM,IAAI,GAAa,MAAM;AAC7C,cAAM,EAAE,KAAK,UAAU,OAAO,IAAI;AAAA,UAChC,KAAK,qBAAqB;AAAA,UAC1B,KAAK;AAAA,QACP;AAEA,YAAI;AACJ,YAAI;AAEJ,YAAI,KAAK,UAAU,SAAS,GAAG;AAC7B,gBAAM,gBAA0B,CAAC;AACjC,gBAAM,YAA4B,CAAC,GAAG,MAAM;AAC5C,cAAI,SAAU,eAAc,KAAK,QAAQ;AACzC,qBAAW,OAAO,KAAK,WAAW;AAChC,0BAAc,KAAK,IAAI,GAAG;AAC1B,sBAAU,KAAK,GAAG,IAAI,MAAM;AAAA,UAC9B;AACA,gBAAM,WAAW,cAAc,KAAK,OAAO;AAC3C,mBAAS,WACL,UAAU,EAAE,IAAI,OAAO,SAAS,KAAK,WAAW,KAAK,MAAM,IAAI,WAAW,QAAQ,KAClF,UAAU,EAAE,IAAI,OAAO,SAAS,KAAK,WAAW,KAAK,MAAM,IAAI;AACnE,wBAAc;AAAA,QAChB,OAAO;AACL,mBAAS,WACL,UAAU,EAAE,IAAI,OAAO,SAAS,KAAK,WAAW,KAAK,MAAM,IAAI,WAAW,QAAQ,KAClF,UAAU,EAAE,IAAI,OAAO,SAAS,KAAK,WAAW,KAAK,MAAM,IAAI;AACnE,wBAAc;AAAA,QAChB;AAEA,cAAM,MAAM,MAAM,KAAK,QAAQ,MAA+B,QAAQ,WAAW;AACjF,eAAQ,IAAI,CAAC,IAAI,KAAK,KAAK;AAAA,MAC7B;AAAA,MAEA,MAAM,SAAuB;AAC3B,YAAI;AACJ,YAAI;AAEJ,cAAM,sBAAsB,KAAK,qBAAqB;AACtD,YAAI,KAAK,UAAU,WAAW,GAAG;AAE/B,gBAAM,EAAE,KAAK,OAAO,IAAI;AAAA,YACtB,KAAK,MAAM;AAAA,YACX;AAAA,YACA,KAAK;AAAA,YACL,KAAK;AAAA,UACP;AACA,qBAAW;AACX,wBAAc;AAAA,QAChB,OAAO;AAEL,gBAAM,EAAE,KAAK,UAAU,QAAQ,YAAY,IAAI;AAAA,YAC7C;AAAA,YACA,KAAK;AAAA,UACP;AACA,gBAAM,gBAA0B,CAAC;AACjC,gBAAM,YAA4B,CAAC,GAAG,WAAW;AACjD,cAAI,SAAU,eAAc,KAAK,QAAQ;AACzC,qBAAW,OAAO,KAAK,WAAW;AAChC,0BAAc,KAAK,IAAI,GAAG;AAC1B,sBAAU,KAAK,GAAG,IAAI,MAAM;AAAA,UAC9B;AACA,gBAAM,gBAAgB,cAAc,KAAK,OAAO;AAKhD,gBAAM,aAAa,2BAA2B,KAAK,QAAQ;AAC3D,gBAAM,QAAkB;AAAA,YACtB,gBACI,UAAU,UAAU,UAAU,KAAK,MAAM,IAAI,WAAW,aAAa,KACrE,UAAU,UAAU,UAAU,KAAK,MAAM,IAAI;AAAA,UACnD;AACA,cAAI,KAAK,SAAS,WAAW,KAAK,SAAS,QAAQ,SAAS,GAAG;AAC7D,kBAAM,KAAK,YAAY,KAAK,SAAS,QAAQ,IAAI,CAAC,MAAM,IAAI,CAAC,GAAG,EAAE,KAAK,IAAI,CAAC,EAAE;AAAA,UAChF;AACA,cAAI,KAAK,SAAS,QAAQ;AACxB,kBAAM,EAAE,KAAK,QAAQ,QAAQ,UAAU,IAAI,WAAW,KAAK,SAAS,QAAQ,KAAK,QAAQ;AACzF,gBAAI,QAAQ;AACV,oBAAM,KAAK,UAAU,MAAM,EAAE;AAC7B,wBAAU,KAAK,GAAG,SAAS;AAAA,YAC7B;AAAA,UACF;AACA,cAAI,KAAK,SAAS,WAAW,KAAK,SAAS,QAAQ,SAAS,GAAG;AAC7D,kBAAM,SAAS,KAAK,SAAS,QAC1B,IAAI,CAAC,EAAE,KAAK,IAAI,MAAM,IAAI,GAAG,KAAK,GAAG,EAAE,EACvC,KAAK,IAAI;AACZ,kBAAM,KAAK,YAAY,MAAM,EAAE;AAAA,UACjC;AACA,cAAI,KAAK,SAAS,UAAU,UAAa,KAAK,SAAS,WAAW,QAAW;AAC3E,kBAAM,WAAW,KAAK,SAAS,UAAU,SACrC,KAAK,MAAM,KAAK,IAAI,GAAG,KAAK,SAAS,KAAK,CAAC,IAC3C;AACJ,kBAAM,KAAK,SAAS,QAAQ,EAAE;AAC9B,gBAAI,KAAK,SAAS,WAAW,QAAW;AACtC,oBAAM,KAAK,UAAU,KAAK,MAAM,KAAK,IAAI,GAAG,KAAK,SAAS,MAAM,CAAC,CAAC,EAAE;AAAA,YACtE;AAAA,UACF;AACA,qBAAW,MAAM,KAAK,GAAG;AACzB,wBAAc;AAAA,QAChB;AAEA,cAAM,UAAU,MAAM,KAAK,QAAQ,MAA+B,UAAU,WAAW;AAEvF,YAAI;AACJ,YAAI,KAAK,SAAS,WAAW,KAAK,SAAS,QAAQ,SAAS,GAAG;AAC7D,iBAAO;AAAA,QACT,OAAO;AACL,iBAAO,QAAQ,IAAI,CAAC,QAAQ,eAAe,KAAK,OAAO,GAAG,CAAC;AAAA,QAC7D;AAEA,YAAI,KAAK,eAAe,WAAW,EAAG,QAAO;AAC7C,eAAO,KAAK,aAAa,IAAI;AAAA,MAC/B;AAAA,MAEA,MAAM,QAA2B;AAC/B,cAAM,OAAO,MAAM,KAAK,OAAO;AAC/B,eAAO,KAAK,CAAC,KAAK;AAAA,MACpB;AAAA;AAAA,MAIA,MAAc,aAAa,MAAyB;AAClD,YAAI,KAAK,WAAW,EAAG,QAAO;AAE9B,cAAM,cAAc,KAAK,IAAI,CAAC,OAAO,EAAE,GAAI,EAA8B,EAAE;AAE3E,mBAAW,gBAAgB,KAAK,gBAAgB;AAC9C,gBAAM,OAAO,KAAK,MAAM,UAAU,YAAY;AAC9C,cAAI,CAAC,KAAM;AAEX,cAAI,KAAK,SAAS,cAAc;AAC9B,kBAAM,IAAI;AAAA,cACR,0FAC2C,YAAY;AAAA,YACzD;AAAA,UACF;AAEA,cAAI,KAAK,SAAS,aAAa;AAC7B,kBAAM,KAAK,iBAAiB,aAA0C,cAAc,IAAI;AAAA,UAC1F,WAAW,KAAK,SAAS,WAAW;AAClC,kBAAM,KAAK,eAAe,aAA0C,cAAc,IAAI;AAAA,UACxF;AAAA,QACF;AAEA,eAAO;AAAA,MACT;AAAA,MAEA,MAAc,iBACZ,MACA,cACA,MACe;AACf,cAAM,eAAe,KAAK,SAAS;AACnC,cAAM,WAAW,KACd,IAAI,CAAC,MAAM,EAAE,KAAK,UAAU,CAAC,EAC7B,OAAO,CAAC,MAAyB,MAAM,QAAQ,MAAM,MAAS;AAEjE,YAAI,SAAS,WAAW,GAAG;AACzB,qBAAW,KAAK,KAAM,GAAE,YAAY,IAAI;AACxC;AAAA,QACF;AAEA,cAAM,iBAAiB,CAAC,GAAG,IAAI,IAAI,QAAQ,CAAC;AAC5C,cAAM,KAAK,aAAa;AACxB,cAAM,iBAA0C,EAAE,CAAC,EAAE,GAAG,EAAE,IAAI,MAAM,OAAO,eAAe,EAAE;AAC5F,YAAI,aAAa,qBAAqB,MAAM;AAC1C,yBAAe,aAAa,gBAA0B,IAAI,EAAE,IAAI,UAAU;AAAA,QAC5E;AACA,cAAM,EAAE,KAAK,OAAO,IAAI;AAAA,UACtB,aAAa;AAAA,UACb;AAAA,UACA,CAAC;AAAA,UACD,KAAK;AAAA,QACP;AACA,cAAM,UAAU,MAAM,KAAK,QAAQ,MAA+B,KAAK,MAAM;AAC7E,cAAM,aAAa,oBAAI,IAAsB;AAC7C,mBAAW,KAAK,SAAS;AACvB,qBAAW,IAAI,EAAE,EAAE,GAAG,eAAe,cAAc,CAAC,CAAC;AAAA,QACvD;AAEA,mBAAW,KAAK,MAAM;AACpB,YAAE,YAAY,IAAI,WAAW,IAAI,EAAE,KAAK,UAAU,CAAC,KAAK;AAAA,QAC1D;AAAA,MACF;AAAA,MAEA,MAAc,eACZ,MACA,cACA,MACe;AACf,cAAM,eAAe,KAAK,SAAS;AACnC,cAAM,KAAK,KAAK,MAAM;AACtB,cAAM,WAAW,KAAK,IAAI,CAAC,MAAM,EAAE,EAAE,CAAC,EAAE,OAAO,CAAC,MAAyB,MAAM,QAAQ,MAAM,MAAS;AAEtG,YAAI,SAAS,WAAW,GAAG;AACzB,qBAAW,KAAK,KAAM,GAAE,YAAY,IAAI,CAAC;AACzC;AAAA,QACF;AAEA,cAAM,oBAA6C,EAAE,CAAC,KAAK,UAAU,GAAG,EAAE,IAAI,MAAM,OAAO,SAAS,EAAE;AACtG,YAAI,aAAa,qBAAqB,MAAM;AAC1C,4BAAkB,aAAa,gBAA0B,IAAI,EAAE,IAAI,UAAU;AAAA,QAC/E;AACA,cAAM,EAAE,KAAK,OAAO,IAAI;AAAA,UACtB,aAAa;AAAA,UACb;AAAA,UACA,CAAC;AAAA,UACD,KAAK;AAAA,QACP;AACA,cAAM,UAAU,MAAM,KAAK,QAAQ,MAA+B,KAAK,MAAM;AAE7E,cAAM,UAAU,oBAAI,IAAwB;AAC5C,mBAAW,SAAS,SAAU,SAAQ,IAAI,OAAO,CAAC,CAAC;AAEnD,mBAAW,KAAK,SAAS;AACvB,gBAAM,QAAQ,EAAE,KAAK,UAAU;AAC/B,gBAAM,eAAe,eAAe,cAAc,CAAC;AACnD,gBAAM,QAAQ,QAAQ,IAAI,KAAK;AAC/B,cAAI,OAAO;AACT,kBAAM,KAAK,YAAY;AAAA,UACzB,OAAO;AACL,oBAAQ,IAAI,OAAO,CAAC,YAAY,CAAC;AAAA,UACnC;AAAA,QACF;AAEA,mBAAW,KAAK,MAAM;AACpB,YAAE,YAAY,IAAI,QAAQ,IAAI,EAAE,EAAE,CAAC,KAAK,CAAC;AAAA,QAC3C;AAAA,MACF;AAAA,MAEA,MAAM,OAAO,OAA+B;AAC1C,cAAM,gBAAgB,EACpB,OAAO,KAAK,KAAK,UAAU,EAAE,WAAW,KAAK,KAAK,UAAU,WAAW;AAEzE,YAAI,CAAC,eAAe;AAClB,gBAAM,IAAI,MAAM,uCAAuC;AAAA,QACzD;AAGA,cAAM,UAAU,MAAM,KAAK,MAAM;AACjC,YAAI,YAAY,MAAM;AACpB,gBAAM,IAAI,MAAM,6BAA6B;AAAA,QAC/C;AAGA,cAAM,aAAa,MAAM,KAAK,MAAM,gBAAgB,KAAK,OAAO,KAAK,KAAK,SAAS,KAAK;AAGxF,cAAM,KAAK,KAAK,MAAM;AACtB,cAAM,UAAW,QAAoC,EAAY;AACjE,cAAM,EAAE,KAAK,OAAO,IAAI;AAAA,UACtB,KAAK,MAAM;AAAA,UACX;AAAA,UACA;AAAA,UACA;AAAA,QACF;AACA,cAAM,KAAK,QAAQ,QAAQ,KAAK,MAAM;AAKtC,cAAM,aAAsC;AAAA,UAC1C,GAAI;AAAA,UACJ,GAAI;AAAA,QACN;AACA,cAAM,SAAS,eAAe,KAAK,OAAO,UAAU;AAGpD,cAAM,KAAK,MAAM,eAAe,KAAK,OAAO,KAAK,KAAK,QAAQ,SAAS,KAAK,KAAK;AAEjF,eAAO;AAAA,MACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,MAaA,MAAM,WAAW,MAAsC;AACrD,YAAI,KAAK,WAAW,EAAG,QAAO,CAAC;AAE/B,cAAM,KAAK,KAAK,MAAM;AAEtB,cAAM,UAAe,MAAM,KAAK,QAAQ,YAAY,OAAO,cAAc;AAEvE,gBAAM,UAAU,IAAI,kBAAkB;AACtC,gBAAM,QAAa,CAAC;AAEpB,qBAAW,OAAO,MAAM;AACtB,kBAAM,UAAW,IAAgC,EAAY;AAC7D,gBAAI,YAAY,UAAa,YAAY,MAAM;AAC7C,oBAAM,IAAI;AAAA,gBACR,2CAA2C,EAAY;AAAA,cACzD;AAAA,YACF;AAGA,kBAAM,YAAY,kBAAkB,KAAK,MAAM,IAAI,YAAY,EAAY;AAC3E,kBAAM,cAAc,MAAM,UAAU,MAA+B,WAAW,CAAC,OAAuB,CAAC;AACvG,gBAAI,YAAY,WAAW,GAAG;AAC5B,oBAAM,IAAI,MAAM,2BAA2B,EAAY,IAAI,OAAO,OAAO,CAAC,YAAY;AAAA,YACxF;AACA,kBAAM,UAAU,eAAe,KAAK,OAAO,YAAY,CAAC,CAAE;AAG1D,kBAAM,EAAE,CAAC,EAAY,GAAG,KAAK,GAAG,eAAe,IAAI;AACnD,kBAAM,QAAQ;AAGd,kBAAM,aAAa,MAAM,KAAK,MAAM,gBAAgB,KAAK,OAAO,KAAK,KAAK,SAAS,KAAK;AAGxF,kBAAM,EAAE,KAAK,OAAO,IAAI;AAAA,cACtB,KAAK,MAAM;AAAA,cACX;AAAA,cACA;AAAA,cACA;AAAA,YACF;AACA,kBAAM,UAAU,QAAQ,KAAK,MAAM;AAGnC,kBAAM,aAAsC;AAAA,cAC1C,GAAI;AAAA,cACJ,GAAI;AAAA,YACN;AACA,kBAAM,SAAS,eAAe,KAAK,OAAO,UAAU;AAGpD,kBAAM,KAAK,MAAM,eAAe,KAAK,OAAO,KAAK,KAAK,QAAQ,SAAS,OAAO;AAE9E,kBAAM,KAAK,MAAM;AAAA,UACnB;AAEA,iBAAO;AAAA,QACT,CAAC;AAED,eAAO;AAAA,MACT;AAAA,MAEA,MAAM,SAAqB;AACzB,cAAM,gBAAgB,EACpB,OAAO,KAAK,KAAK,UAAU,EAAE,WAAW,KAAK,KAAK,UAAU,WAAW;AAEzE,YAAI,CAAC,eAAe;AAClB,gBAAM,IAAI,MAAM,uCAAuC;AAAA,QACzD;AAGA,cAAM,UAAU,MAAM,KAAK,MAAM;AACjC,YAAI,YAAY,MAAM;AACpB,gBAAM,IAAI,MAAM,6BAA6B;AAAA,QAC/C;AAGA,cAAM,KAAK,MAAM,gBAAgB,KAAK,OAAO,KAAK,KAAK,OAAO;AAG9D,cAAM,KAAK,KAAK,MAAM;AACtB,cAAM,UAAW,QAAoC,EAAY;AACjE,cAAM,EAAE,KAAK,OAAO,IAAI,YAAY,KAAK,MAAM,MAAM,IAAI,OAAO;AAChE,cAAM,KAAK,QAAQ,QAAQ,KAAK,MAAM;AAGtC,cAAM,KAAK,MAAM,eAAe,KAAK,OAAO,KAAK,KAAK,SAAS,KAAK,KAAK;AAEzE,eAAO;AAAA,MACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,MAYA,aAAsC;AACpC,eAAO,IAAI,kBAAwB,KAAK,SAAS,KAAK,OAAO,oBAAI,KAAK,GAAG,KAAK,QAAQ;AAAA,MACxF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,MASA,UAAmC;AACjC,eAAO,IAAI,kBAAwB,KAAK,SAAS,KAAK,OAAO,MAAM,KAAK,QAAQ;AAAA,MAClF;AAAA,IACF;AAOO,IAAM,0BAAN,MAAM,yBAAwG;AAAA;AAAA;AAAA,MAGnH,YACmB,UACA,MACjB;AAFiB;AACA;AAAA,MAChB;AAAA,MAFgB;AAAA,MACA;AAAA,MAGnB,MAAM,YAAoG;AACxG,eAAO,IAAI;AAAA,UACT,KAAK,SAAS,MAAM,UAAU;AAAA,UAC9B,KAAK;AAAA,QACP;AAAA,MACF;AAAA,MAEA,MAAM,GAA8D;AAClE,eAAO,IAAI;AAAA,UACT,KAAK,SAAS,MAAM,CAAC;AAAA,UACrB,KAAK;AAAA,QACP;AAAA,MACF;AAAA,MAEA,QAAQ,KAAU,MAAsB,OAA0D;AAChG,eAAO,IAAI;AAAA;AAAA;AAAA,UAGT,KAAK,SAAS,QAAQ,KAAc,GAAG;AAAA,UACvC,KAAK;AAAA,QACP;AAAA,MACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,MAcA,WAAsC;AACpC,cAAM,EAAE,KAAK,OAAO,IAAI,KAAK,SAAS,gBAAgB;AACtD,eAAO,cAAyB,KAAK,QAAQ,KAAK,IAAI;AAAA,MACxD;AAAA;AAAA,MAGA,eAAwD;AACtD,eAAO,KAAK,SAAS,gBAAgB;AAAA,MACvC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,MAWA,MAAM,OAA2F;AAC/F,eAAO,IAAI;AAAA,UACT,CAAC,KAAK,aAAa,GAAG,MAAM,aAAa,CAAC;AAAA,UAC1C;AAAA,UACA,KAAK,SAAS,YAAY;AAAA,UAC1B,KAAK,SAAS,YAAY;AAAA,QAC5B;AAAA,MACF;AAAA;AAAA;AAAA;AAAA,MAKA,SAAS,OAA2F;AAClG,eAAO,IAAI;AAAA,UACT,CAAC,KAAK,aAAa,GAAG,MAAM,aAAa,CAAC;AAAA,UAC1C;AAAA,UACA,KAAK,SAAS,YAAY;AAAA,UAC1B,KAAK,SAAS,YAAY;AAAA,QAC5B;AAAA,MACF;AAAA,IACF;AAOO,IAAM,oBAAN,MAAgD;AAAA,MAGrD,YACmB,SACA,OACA,QACA,WAAwB,UACzC;AAJiB;AACA;AACA;AACA;AAAA,MAChB;AAAA,MAJgB;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MANX,cAA6B,CAAC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,MActC,MAAM,YAAiC;AACrC,aAAK,cAAc,cAAc,KAAK,aAAa,UAAU;AAC7D,eAAO;AAAA,MACT;AAAA;AAAA;AAAA;AAAA;AAAA,MAMA,MAAM,UAAyB;AAC7B,cAAM,MAAM,KAAK,MAAM;AACvB,YAAI,QAAQ,MAAM;AAChB,gBAAM,IAAI;AAAA,YACR,iCAAiC,KAAK,MAAM,IAAI;AAAA,UAElD;AAAA,QACF;AACA,cAAM,EAAE,KAAK,OAAO,IAAI;AAAA,UACtB,KAAK,MAAM;AAAA,UACX;AAAA,UACA,KAAK;AAAA,UACL,KAAK;AAAA,UACL,KAAK;AAAA,QACP;AACA,cAAM,KAAK,QAAQ,QAAQ,KAAK,MAAM;AAAA,MACxC;AAAA,IACF;AAMO,IAAM,eAAN,MAAM,cAAgB;AAAA,MAI3B,YACmB,QACA,OACA,UACA,UACjB;AAJiB;AACA;AACA;AACA;AAAA,MAChB;AAAA,MAJgB;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MAPX;AAAA,MACA;AAAA;AAAA,MAUR,MAAM,OAAqF;AACzF,eAAO,IAAI;AAAA,UACT,CAAC,GAAG,KAAK,QAAQ,MAAM,aAAa,CAAC;AAAA,UACrC;AAAA,UACA,KAAK;AAAA,UACL,KAAK;AAAA,QACP;AAAA,MACF;AAAA;AAAA,MAGA,SAAS,OAAqF;AAC5F,eAAO,IAAI;AAAA,UACT,CAAC,GAAG,KAAK,QAAQ,MAAM,aAAa,CAAC;AAAA,UACrC;AAAA,UACA,KAAK;AAAA,UACL,KAAK;AAAA,QACP;AAAA,MACF;AAAA;AAAA,MAGA,QAAQ,KAAa,MAAsB,OAAwB;AACjE,cAAM,OAAO,IAAI,cAAgB,KAAK,QAAQ,KAAK,OAAO,KAAK,UAAU,KAAK,QAAQ;AACtF,aAAK,WAAW,EAAE,KAAK,IAAI;AAC3B,aAAK,SAAW,KAAK;AACrB,eAAO;AAAA,MACT;AAAA;AAAA,MAGA,MAAM,GAA4B;AAChC,cAAM,OAAO,IAAI,cAAgB,KAAK,QAAQ,KAAK,OAAO,KAAK,UAAU,KAAK,QAAQ;AACtF,aAAK,WAAW,KAAK;AACrB,aAAK,SAAW;AAChB,eAAO;AAAA,MACT;AAAA;AAAA,MAGA,MAAM,SAAuC;AAC3C,cAAM,EAAE,KAAK,OAAO,IAAI,WAAW,KAAK,QAAQ,KAAK,OAAO;AAAA,UAC1D,SAAS,KAAK;AAAA,UACd,OAAS,KAAK;AAAA,QAChB,CAAC;AACD,eAAO,KAAK,SAAS,MAAyB,KAAK,MAAM;AAAA,MAC3D;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,MAWA,WAAsC;AACpC,cAAM,EAAE,KAAK,OAAO,IAAI,WAAW,KAAK,QAAQ,KAAK,OAAO;AAAA,UAC1D,SAAS,KAAK;AAAA,UACd,OAAS,KAAK;AAAA,QAChB,CAAC;AACD,eAAO,cAAyB,KAAK,QAAQ,EAAE;AAAA,MACjD;AAAA,IACF;AAIO,IAAM,gBAAN,MAA4C;AAAA,MACjD,YACmB,SACA,OACA,KACA,OACA,OACA,UAAsB,UACvC;AANiB;AACA;AACA;AACA;AACA;AACA;AAAA,MAChB;AAAA,MANgB;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MAGnB,MAAM,OAAO,MAAkC;AAC7C,cAAM,gBAAgB,EAAE,GAAG,KAAK;AAChC,YAAI,UAAU,EAAE,GAAG,KAAK;AAGxB,kBAAU,MAAM,KAAK,MAAM,gBAAgB,KAAK,OAAO,KAAK,KAAK,OAAO;AAGxE,mBAAW,CAAC,OAAO,GAAG,KAAK,OAAO,QAAQ,KAAK,MAAM,MAAM,GAAG;AAE5D,cAAI,IAAI,IAAI,cAAc,IAAI,IAAI,cAAe;AAEjD,cAAK,QAAoC,KAAK,MAAM,QAAW;AAC7D,gBAAI,IAAI,IAAI,cAAc,QAAW;AACnC;AAAC,cAAC,QAAoC,KAAK,IAAI,IAAI,IAAI,UAAU;AAAA,YACnE,WAAW,IAAI,IAAI,iBAAiB,QAAW;AAC7C;AAAC,cAAC,QAAoC,KAAK,IAAI,IAAI,IAAI;AAAA,YACzD;AAAA,UACF;AAAA,QACF;AAGA,cAAM,aAAa,KAAK,oBAAoB,OAAkC;AAK9E,cAAM,EAAE,KAAK,OAAO,IAAI,YAAY,KAAK,MAAM,MAAM,YAAY,IAAI;AACrE,cAAM,OAAO,MAAM,KAAK,QAAQ,MAA+B,KAAK,MAAM;AAC1E,cAAM,SAAS,eAAe,KAAK,OAAO,KAAK,CAAC,CAAE;AAGlD,cAAM,KAAK,MAAM,eAAe,KAAK,OAAO,KAAK,KAAK,QAAQ,eAAe,KAAK,KAAK;AAEvF,eAAO;AAAA,MACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,MAeA,MAAM,WAAW,MAAsC;AACrD,YAAI,KAAK,WAAW,EAAG,QAAO,CAAC;AAE/B,YAAI,KAAK,YAAY,SAAS;AAC5B,gBAAM,IAAI;AAAA,YACR;AAAA,UAEF;AAAA,QACF;AAGA,cAAM,iBAAiD,CAAC;AAExD,mBAAW,OAAO,MAAM;AAEtB,cAAI,YAAwB,MAAM,KAAK,MAAM;AAAA,YAC3C,KAAK;AAAA,YACL,KAAK;AAAA,YACL,EAAE,GAAG,IAAI;AAAA,UACX;AAGA,qBAAW,CAAC,OAAO,GAAG,KAAK,OAAO,QAAQ,KAAK,MAAM,MAAM,GAAG;AAC5D,gBAAI,IAAI,IAAI,cAAc,IAAI,IAAI,cAAe;AACjD,gBAAK,UAAsC,KAAK,MAAM,QAAW;AAC/D,kBAAI,IAAI,IAAI,cAAc,QAAW;AACnC;AAAC,gBAAC,UAAsC,KAAK,IAAI,IAAI,IAAI,UAAU;AAAA,cACrE,WAAW,IAAI,IAAI,iBAAiB,QAAW;AAC7C;AAAC,gBAAC,UAAsC,KAAK,IAAI,IAAI,IAAI;AAAA,cAC3D;AAAA,YACF;AAAA,UACF;AAGA,gBAAM,aAAa,KAAK,oBAAoB,SAAoC;AAChF,yBAAe,KAAK,UAA0C;AAAA,QAChE;AAGA,cAAM,EAAE,KAAK,OAAO,IAAI,gBAAgB,KAAK,MAAM,MAAM,gBAAgB,IAAI;AAC7E,cAAM,UAAU,MAAM,KAAK,QAAQ,MAA+B,KAAK,MAAM;AAG7E,cAAM,UAAe,CAAC;AACtB,mBAAW,UAAU,SAAS;AAC5B,gBAAM,eAAe,eAAe,KAAK,OAAO,MAAM;AACtD,gBAAM,KAAK,MAAM,eAAe,KAAK,OAAO,KAAK,KAAK,cAAc,CAAC,GAAG,KAAK,KAAK;AAClF,kBAAQ,KAAK,YAAY;AAAA,QAC3B;AAEA,eAAO;AAAA,MACT;AAAA;AAAA,MAGQ,oBAAoB,MAAwD;AAClF,cAAM,SAAkC,CAAC;AACzC,mBAAW,CAAC,KAAK,GAAG,KAAK,OAAO,QAAQ,IAAI,GAAG;AAC7C,cAAI,QAAQ,OAAW;AACvB,iBAAO,GAAG,IAAI,eAAe,OAAO,IAAI,YAAY,IAAI;AAAA,QAC1D;AACA,eAAO;AAAA,MACT;AAAA,IACF;AAOO,IAAM,cAAN,MAAM,aAAY;AAAA,MACvB,YACmB,SACA,WACA,UACA,QACA,QACA,SACA,WAA0B,CAAC,GAC5C;AAPiB;AACA;AACA;AACA;AACA;AACA;AACA;AAAA,MAChB;AAAA,MAPgB;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MAGX,WAAW,OAA4C;AAC7D,eAAO,IAAI;AAAA,UACT,KAAK;AAAA,UACL,KAAK;AAAA,UACL,KAAK;AAAA,UACL,KAAK;AAAA,UACL,KAAK;AAAA,UACL,KAAK;AAAA,UACL,EAAE,GAAG,KAAK,UAAU,GAAG,MAAM;AAAA,QAC/B;AAAA,MACF;AAAA;AAAA,MAGA,QAAQ,MAA6B;AACnC,eAAO,IAAI,aAAY,KAAK,SAAS,KAAK,WAAW,MAAM,KAAK,QAAQ,KAAK,QAAQ,KAAK,SAAS,KAAK,QAAQ;AAAA,MAClH;AAAA;AAAA,MAGA,KAAK,OAAe,IAAyB;AAC3C,eAAO,KAAK,SAAS,SAAS,OAAO,EAAE;AAAA,MACzC;AAAA;AAAA,MAGA,SAAS,OAAe,IAAyB;AAC/C,eAAO,KAAK,SAAS,QAAQ,OAAO,EAAE;AAAA,MACxC;AAAA;AAAA,MAGA,UAAU,OAAe,IAAyB;AAChD,eAAO,KAAK,SAAS,SAAS,OAAO,EAAE;AAAA,MACzC;AAAA;AAAA,MAGA,SAAS,OAAe,IAAyB;AAC/C,eAAO,KAAK,SAAS,QAAQ,OAAO,EAAE;AAAA,MACxC;AAAA,MAkBA,MAAM,iBAAwD,QAAsC;AAClG,YAAI,OAAO,oBAAoB,UAAU;AACvC,iBAAO,IAAI,aAAY,KAAK,SAAS,KAAK,WAAW,KAAK,UAAU,KAAK,QAAQ,iBAAiB,UAAU,CAAC,GAAG,KAAK,QAAQ;AAAA,QAC/H;AACA,cAAM,EAAE,KAAK,QAAQ,YAAY,IAAI,WAAW,eAAe;AAC/D,eAAO,IAAI,aAAY,KAAK,SAAS,KAAK,WAAW,KAAK,UAAU,KAAK,QAAQ,KAAK,aAAa,KAAK,QAAQ;AAAA,MAClH;AAAA;AAAA,MAGA,MAAM,GAAwB;AAC5B,eAAO,KAAK,WAAW,EAAE,OAAO,EAAE,CAAC;AAAA,MACrC;AAAA;AAAA,MAGA,OAAO,GAAwB;AAC7B,eAAO,KAAK,WAAW,EAAE,QAAQ,EAAE,CAAC;AAAA,MACtC;AAAA;AAAA;AAAA;AAAA;AAAA,MAMA,QAAQ,KAAa,MAAsB,OAAoB;AAC7D,cAAM,WAAW,KAAK,SAAS,WAAW,CAAC;AAC3C,eAAO,KAAK,WAAW,EAAE,SAAS,CAAC,GAAG,UAAU,EAAE,KAAK,IAAI,CAAC,EAAE,CAAC;AAAA,MACjE;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,MAOA,KAAK,MAAc,MAA2B;AAC5C,eAAO,KAAK,WAAW,EAAE,OAAO,MAAM,SAAS,OAAO,KAAK,KAAK,CAAC;AAAA,MACnE;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,MASA,MAAM,SAAoD;AACxD,cAAM,EAAE,KAAK,OAAO,IAAI;AAAA,UACtB,KAAK;AAAA,UACL,KAAK;AAAA,UACL,KAAK;AAAA,UACL,KAAK;AAAA,UACL,KAAK;AAAA,UACL,KAAK;AAAA,QACP;AACA,eAAO,KAAK,QAAQ,MAAS,KAAK,MAAM;AAAA,MAC1C;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,MAQA,MAAM,QAAwD;AAC5D,cAAM,OAAO,MAAM,KAAK,OAAU;AAClC,eAAO,KAAK,CAAC,KAAK;AAAA,MACpB;AAAA,MAEQ,SAAS,MAA0B,OAAe,IAAyB;AACjF,eAAO,IAAI;AAAA,UACT,KAAK;AAAA,UACL,KAAK;AAAA,UACL,KAAK;AAAA,UACL,CAAC,GAAG,KAAK,QAAQ,EAAE,MAAM,OAAO,GAAG,CAAC;AAAA,UACpC,KAAK;AAAA,UACL,KAAK;AAAA,UACL,KAAK;AAAA,QACP;AAAA,MACF;AAAA,IACF;AAAA;AAAA;;;ACjnDA;AAEA;AAEA;;;ACCO,SAAS,cAAc,OAAsC;AAClE,SACE,OAAO,UAAU,YACjB,UAAU,QACV,OAAQ,MAAsB,UAAY,cAC1C,OAAQ,MAAsB,YAAY;AAE9C;AAEO,SAAS,eAAe,QAAkD;AAC/E,MAAI,cAAc,MAAM,EAAG,QAAO;AAElC,QAAM,MAAM;AAEZ,MAAI,IAAI,YAAY,UAAU;AAE5B,UAAM,EAAE,eAAAC,eAAc,IAAI;AAC1B,WAAO,IAAIA,eAAc,IAAI,OAAO,EAAE,MAAM,IAAI,KAAK,IAAI,EAAE,MAAM,cAAc,CAAC;AAAA,EAClF;AAEA,MAAI,IAAI,YAAY,YAAY;AAE9B,UAAM,EAAE,iBAAAC,iBAAgB,IAAI;AAC5B,WAAO,IAAIA,iBAAgB,EAAE,KAAK,IAAI,kBAAkB,KAAK,IAAI,eAAe,CAAC;AAAA,EACnF;AAEA,MAAI,IAAI,YAAY,SAAS;AAE3B,UAAM,EAAE,cAAAC,cAAa,IAAI;AACzB,WAAO,IAAIA,cAAa,EAAE,KAAK,IAAI,kBAAkB,KAAK,IAAI,eAAe,CAAC;AAAA,EAChF;AAEA,QAAM,IAAI,MAAM,kDAAmD,IAA4C,OAAO,GAAG;AAC3H;;;ACpBO,IAAM,SAAN,MAAM,QAAU;AAAA,EAIrB,YAAqB,KAA0B;AAA1B;AAAA,EAA2B;AAAA,EAA3B;AAAA,EAErB,WAA6B;AAC3B,WAAO,IAAI,QAAiB,EAAE,GAAG,KAAK,KAAK,UAAU,KAAK,CAAC;AAAA,EAC7D;AAAA,EAEA,aAAwB;AACtB,WAAO,IAAI,QAAU,EAAE,GAAG,KAAK,KAAK,YAAY,MAAM,eAAe,KAAK,CAAC;AAAA,EAC7E;AAAA,EAEA,SAAoB;AAClB,WAAO,IAAI,QAAU,EAAE,GAAG,KAAK,KAAK,QAAQ,KAAK,CAAC;AAAA,EACpD;AAAA,EAEA,QAAQ,OAAkC;AACxC,WAAO,IAAI,QAAU,EAAE,GAAG,KAAK,KAAK,cAAc,MAAM,CAAC;AAAA,EAC3D;AAAA,EAEA,UAAU,IAAqC;AAC7C,WAAO,IAAI,QAAU,EAAE,GAAG,KAAK,KAAK,WAAW,GAAoB,CAAC;AAAA,EACtE;AACF;AAEA,IAAM,OAAO,CAAC,UAA8B;AAAA,EAC1C;AAAA,EACA,UAAU;AAAA,EACV,YAAY;AAAA,EACZ,eAAe;AAAA,EACf,QAAQ;AACV;AAEO,IAAM,SAAS;AAAA,EACpB,SAAW,MAA0B,IAAI,OAAe,EAAE,GAAG,KAAK,SAAS,EAAE,CAAC;AAAA,EAC9E,MAAW,MAA0B,IAAI,OAAe,EAAE,GAAG,KAAK,MAAM,EAAE,CAAC;AAAA,EAC3E,MAAW,MAA0B,IAAI,OAAe,EAAE,GAAG,KAAK,MAAM,EAAE,CAAC;AAAA,EAC3E,SAAW,MAA0B,IAAI,OAAgB,EAAE,GAAG,KAAK,SAAS,EAAE,CAAC;AAAA,EAC/E,WAAW,MAA0B,IAAI,OAAa,EAAE,GAAG,KAAK,WAAW,EAAE,CAAC;AAAA,EAC9E,MAAW,MAA0B,IAAI,OAAe,EAAE,GAAG,KAAK,MAAM,EAAE,CAAC;AAAA,EAC3E,MAAW,MAA0B,IAAI,OAAmB,EAAE,GAAG,KAAK,MAAM,EAAE,CAAC;AAAA,EAC/E,MAAW,MAA8B,IAAI,OAAU,EAAE,GAAG,KAAK,MAAM,EAAE,CAAC;AAC5E;;;ACwHO,IAAM,eAAN,MAAM,cAKX;AAAA,EAMA,YACmB,OACA,SACjB;AAFiB;AACA;AAAA,EAChB;AAAA,EAFgB;AAAA,EACA;AAAA,EAPF,SAAiC,CAAC;AAAA,EAC3C,UAAyB,CAAC;AAAA,EACjB,aAA2B,CAAC;AAAA,EACrC,oBAA+C;AAAA;AAAA,EAQvD,KAAK,UAAsC;AACzC,SAAK,OAAO,KAAK,QAAQ;AACzB,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAeA,eAA6C,KAAgB;AAC3D,SAAK,oBAAoB;AACzB,WAAO;AAAA,EACT;AAAA,EAEA,MAA+B,KAA2C;AACxE,UAAM,OAAO,IAAI,cAAkC,KAAK,OAAO,KAAK,OAAO;AAE3E,eAAW,KAAK,KAAK,OAAQ,CAAC,KAAuC,OAAO,KAAK,CAAC;AACjF,IAAC,KAAsD,UAAU;AAClE,eAAW,CAAC,GAAG,CAAC,KAAK,OAAO,QAAQ,KAAK,UAAU,GAAG;AACpD;AAAC,MAAC,KAAuC,WAAW,CAAC,IAAI;AAAA,IAC3D;AACA;AAAC,IAAC,KAAuC,oBAAoB,KAAK;AAClE,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAWA,UACE,MAEA,UACA,YACkF;AAClF,QAAI,QAAQ,KAAK,YAAY;AAC3B,YAAM,IAAI,MAAM,aAAa,IAAI,kCAAkC,KAAK,KAAK,GAAG;AAAA,IAClF;AACA,UAAM,MAAmC,EAAE,MAAM,aAAa,MAAM,UAAU,WAAW;AACzF,SAAK,WAAW,IAAI,IAAI;AACxB,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAWA,QACE,MAEA,UAEA,YACgF;AAChF,QAAI,QAAQ,KAAK,YAAY;AAC3B,YAAM,IAAI,MAAM,aAAa,IAAI,kCAAkC,KAAK,KAAK,GAAG;AAAA,IAClF;AACA,UAAM,MAAiC,EAAE,MAAM,WAAW,MAAM,UAAU,WAAW;AACrF,SAAK,WAAW,IAAI,IAAI;AACxB,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUA,WACE,MAEA,UAEA,YAEA,UAEA,YACmE;AACnE,QAAI,QAAQ,KAAK,YAAY;AAC3B,YAAM,IAAI,MAAM,aAAa,IAAI,kCAAkC,KAAK,KAAK,GAAG;AAAA,IAClF;AACA,SAAK,WAAW,IAAI,IAAI;AAAA,MACtB,MAAM;AAAA,MACN;AAAA,MACA;AAAA,MACA;AAAA,MACA,OAAO,EAAE,OAAO,YAAY,UAAU,WAAW;AAAA,IACnD;AACA,WAAO;AAAA,EACT;AAAA,EAEA,QAA6C;AAC3C,QAAI,KAAK,sBAAsB,QAAQ,EAAE,KAAK,qBAAqB,KAAK,UAAU;AAChF,YAAM,IAAI;AAAA,QACR,2BAA2B,KAAK,iBAA2B,8BAA8B,KAAK,KAAK;AAAA,MAErG;AAAA,IACF;AACA,WAAO;AAAA,MACL,MAAM,KAAK;AAAA,MACX,QAAQ,KAAK;AAAA,MACb,YAAY,KAAK,gBAAgB;AAAA,MACjC,OAAO,CAAC,GAAG,KAAK,MAAM;AAAA;AAAA,MACtB,QAAQ,EAAE,GAAG,KAAK,QAAQ;AAAA;AAAA;AAAA;AAAA;AAAA,MAK1B,WAAW,CAAC;AAAA,MACZ,WAAW,EAAE,GAAG,KAAK,WAAW;AAAA,MAChC,kBAAkB,KAAK;AAAA,IACzB;AAAA,EACF;AAAA,EAEQ,kBAA0B;AAChC,eAAW,CAAC,KAAK,GAAG,KAAK,OAAO,QAAQ,KAAK,OAAO,GAAG;AACrD,UAAK,IAAoB,IAAI,WAAY,QAAO;AAAA,IAClD;AACA,WAAO;AAAA,EACT;AACF;AAEO,SAAS,YACd,MACA,QAC8B;AAC9B,SAAO,IAAI,aAA6B,MAAM,MAAM;AACtD;AAGO,SAAS,iBAAoB,OAA4B;AAC9D,QAAM,OAAO,OAAO,QAAQ,MAAM,MAAM,EAAE,IAAI,CAAC,CAAC,MAAM,GAAG,MAAM;AAC7D,UAAM,IAAI;AACV,QAAI,MAAM,IAAI,IAAI;AAElB,YAAQ,EAAE,IAAI,MAAM;AAAA,MAClB,KAAK;AAAa,eAAO;AAAW;AAAA,MACpC,KAAK;AAAA,MACL,KAAK;AAAa,eAAO;AAAQ;AAAA,MACjC,KAAK;AAAa,eAAO;AAAQ;AAAA,MACjC,KAAK;AAAa,eAAO;AAAW;AAAA;AAAA,MACpC,KAAK;AAAa,eAAO;AAAQ;AAAA;AAAA,MACjC,KAAK;AAAa,eAAO;AAAQ;AAAA,MACjC,KAAK;AAAa,eAAO;AAAQ;AAAA,IACnC;AAEA,QAAI,EAAE,IAAI,WAAe,QAAO;AAChC,QAAI,EAAE,IAAI,iBAAiB,EAAE,IAAI,SAAS,UAAW,QAAO;AAC5D,QAAI,CAAC,EAAE,IAAI,YAAY,CAAC,EAAE,IAAI,WAAY,QAAO;AACjD,QAAI,EAAE,IAAI,OAAe,QAAO;AAEhC,WAAO;AAAA,EACT,CAAC;AAED,SAAO,+BAA+B,MAAM,IAAI,MAAM,KAAK,KAAK,IAAI,CAAC;AACvE;;;ACpXA,IAAM,mBAAmB;AAAA,EACvB,IAAW,OAAO,QAAQ,EAAE,WAAW;AAAA,EACvC,WAAW,OAAO,KAAK;AAAA,EACvB,WAAW,OAAO,KAAK;AAAA;AAAA,EACvB,OAAW,OAAO,KAAK,EAAE,SAAS;AAAA,EAClC,QAAW,OAAO,KAAK,EAAE,SAAS;AAAA;AAAA,EAClC,OAAW,OAAO,KAAK,EAAE,SAAS;AAAA;AAAA,EAClC,WAAW,OAAO,UAAU,EAAE,UAAU,MAAM,oBAAI,KAAK,CAAC;AAC1D;AAWO,SAAS,iBACd,MACA,aACkE;AAClE,QAAM,SAAS,EAAE,GAAG,kBAAkB,GAAI,eAAe,CAAC,EAAG;AAC7D,SAAO,YAAY,MAAM,MAAM;AACjC;AA4BO,SAAS,YACd,KACA,QACG;AACH,MAAI,OAAO,WAAW,EAAG,QAAO;AAChC,QAAM,OAAO,EAAE,GAAG,IAAI;AACtB,aAAW,KAAK,QAAQ;AACtB,QAAI,KAAK,KAAM,MAAK,CAAC,IAAI;AAAA,EAC3B;AACA,SAAO;AACT;;;ACrDO,IAAM,eAAN,MAAmB;AAAA;AAAA,EAEP,WAAW,oBAAI,IAA4C;AAAA;AAAA;AAAA,EAIpE;AAAA;AAAA,EAGR,cAAc;AAAA,EAAC;AAAA,EAEf,WAAW,SAA4B;AACrC,SAAK,WAAW;AAAA,EAClB;AAAA,EAEA,aAAsC;AACpC,WAAO,KAAK;AAAA,EACd;AAAA;AAAA,EAGA,mBACE,WACA,UACM;AACN,QAAI,CAAC,KAAK,SAAS,IAAI,SAAS,EAAG,MAAK,SAAS,IAAI,WAAW,CAAC,CAAC;AAClE,SAAK,SAAS,IAAI,SAAS,EAAG,KAAK,QAAQ;AAAA,EAC7C;AAAA;AAAA,EAIA,MAAM,gBACJ,OACA,KACA,MACqB;AACrB,QAAI,UAAU,EAAE,GAAG,KAAK;AAGxB,eAAW,KAAK,MAAM,OAAO;AAC3B,UAAI,CAAC,EAAE,aAAc;AACrB,YAAM,SAAS,MAAM,EAAE,aAAa,OAAO;AAC3C,UAAI,UAAU,KAAM,WAAU;AAAA,IAChC;AAGA,eAAW,KAAK,KAAK,gBAAgB,MAAM,IAAI,GAAG;AAChD,UAAI,CAAC,EAAE,aAAc;AACrB,YAAM,SAAS,MAAM,EAAE,aAAa,KAAK,OAAO;AAChD,UAAI,UAAU,KAAM,WAAU;AAAA,IAChC;AAEA,WAAO;AAAA,EACT;AAAA,EAEA,MAAM,gBACJ,OACA,KACA,SACA,OACqB;AACrB,QAAI,eAAe,EAAE,GAAG,MAAM;AAE9B,eAAW,KAAK,MAAM,OAAO;AAC3B,UAAI,CAAC,EAAE,aAAc;AACrB,YAAM,SAAS,MAAM,EAAE,aAAa,SAAS,YAAY;AACzD,UAAI,UAAU,KAAM,gBAAe;AAAA,IACrC;AAEA,eAAW,KAAK,KAAK,gBAAgB,MAAM,IAAI,GAAG;AAChD,UAAI,CAAC,EAAE,aAAc;AACrB,YAAM,SAAS,MAAM,EAAE,aAAa,KAAK,SAAS,YAAY;AAC9D,UAAI,UAAU,KAAM,gBAAe;AAAA,IACrC;AAEA,WAAO;AAAA,EACT;AAAA,EAEA,MAAM,gBAAmB,OAAoB,KAAc,SAA2B;AACpF,eAAW,KAAK,MAAM,OAAO;AAC3B,UAAI,EAAE,aAAc,OAAM,EAAE,aAAa,OAAO;AAAA,IAClD;AACA,eAAW,KAAK,KAAK,gBAAgB,MAAM,IAAI,GAAG;AAChD,UAAI,EAAE,aAAc,OAAM,EAAE,aAAa,KAAK,OAAO;AAAA,IACvD;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAMA,MAAM,eACJ,OACA,KACA,QACA,OACA,OACe;AACf,eAAW,KAAK,MAAM,OAAO;AAC3B,UAAI,EAAE,YAAa,OAAM,EAAE,YAAY,QAAQ,KAAK;AAAA,IACtD;AACA,eAAW,KAAK,KAAK,gBAAgB,MAAM,IAAI,GAAG;AAChD,UAAI,EAAE,YAAa,OAAM,EAAE,YAAY,KAAK,QAAQ,KAAK;AAAA,IAC3D;AAEA,QAAI,MAAM,OAAO,aAAa;AAC5B,aAAO,QAAQ,MAAM,OAAO,aAAa,MAAM;AAAA,IACjD;AAAA,EACF;AAAA,EAEA,MAAM,eACJ,OACA,KACA,QACA,QACA,OACe;AACf,eAAW,KAAK,MAAM,OAAO;AAC3B,UAAI,EAAE,YAAa,OAAM,EAAE,YAAY,QAAQ,MAAM;AAAA,IACvD;AACA,eAAW,KAAK,KAAK,gBAAgB,MAAM,IAAI,GAAG;AAChD,UAAI,EAAE,YAAa,OAAM,EAAE,YAAY,KAAK,QAAQ,MAAM;AAAA,IAC5D;AAEA,QAAI,MAAM,OAAO,aAAa;AAC5B,aAAO,QAAQ,MAAM,OAAO,aAAa,EAAE,QAAQ,OAAO,OAAO,CAAC;AAAA,IACpE;AAAA,EACF;AAAA,EAEA,MAAM,eACJ,OACA,KACA,SACA,OACe;AACf,eAAW,KAAK,MAAM,OAAO;AAC3B,UAAI,EAAE,YAAa,OAAM,EAAE,YAAY,OAAO;AAAA,IAChD;AACA,eAAW,KAAK,KAAK,gBAAgB,MAAM,IAAI,GAAG;AAChD,UAAI,EAAE,YAAa,OAAM,EAAE,YAAY,KAAK,OAAO;AAAA,IACrD;AAEA,QAAI,MAAM,OAAO,aAAa;AAC5B,aAAO,QAAQ,MAAM,OAAO,aAAa,OAAO;AAAA,IAClD;AAAA,EACF;AAAA,EAEQ,gBAAgB,WAAmD;AACzE,WAAO,KAAK,SAAS,IAAI,SAAS,KAAK,CAAC;AAAA,EAC1C;AACF;;;ACtKA,SAAS,SAAS,gBAAgB;AAClC,SAAS,YAAY;;;ACErB,IAAM,wBAAwB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAQ9B,eAAsB,YAAY,SAAsB,WAAkC;AACxF,QAAM,MAAM,sBAAsB,QAAQ,sBAAsB,IAAI,SAAS,GAAG;AAChF,QAAM,QAAQ,QAAQ,GAAG;AAC3B;AAEA,eAAsB,WAAW,SAAsB,WAA+C;AACpG,QAAM,OAAO,MAAM,QAAQ;AAAA,IACzB,2CAA2C,SAAS;AAAA,EACtD;AACA,SAAO,KAAK,IAAI,QAAM;AAAA,IACpB,IAAW,EAAE;AAAA,IACb,MAAW,EAAE;AAAA,IACb,WAAW,IAAI,KAAK,EAAE,UAAU;AAAA,EAClC,EAAE;AACJ;AAEA,eAAsB,YAAY,SAAsB,WAAmB,MAA6B;AACtG,QAAM,QAAQ;AAAA,IACZ,gBAAgB,SAAS;AAAA,IACzB,CAAC,OAAM,oBAAI,KAAK,GAAE,YAAY,CAAC;AAAA,EACjC;AACF;AAEA,eAAsB,eAAe,SAAsB,WAAmB,MAA6B;AACzG,QAAM,QAAQ;AAAA,IACZ,gBAAgB,SAAS;AAAA,IACzB,CAAC,IAAI;AAAA,EACP;AACF;;;AD5BA,eAAe,mBAAmB,KAAuC;AACvE,MAAI;AACJ,MAAI;AACF,cAAU,MAAM,QAAQ,GAAG;AAAA,EAC7B,QAAQ;AACN,WAAO,CAAC;AAAA,EACV;AAEA,QAAM,WAAW,QACd,OAAO,OAAK,EAAE,SAAS,MAAM,CAAC,EAC9B,KAAK;AAER,QAAM,QAAyB,CAAC;AAChC,aAAW,YAAY,UAAU;AAC/B,UAAM,MAAM,MAAM,SAAS,KAAK,KAAK,QAAQ,GAAG,MAAM;AACtD,UAAM,KAAK,EAAE,MAAM,UAAU,IAAI,CAAC;AAAA,EACpC;AACA,SAAO;AACT;AAEO,SAAS,mBAAmB,KAAuB;AACxD,QAAM,aAAuB,CAAC;AAC9B,MAAI,UAAU;AACd,MAAI,WAAW;AACf,MAAI,aAAa;AACjB,MAAI,IAAI;AAER,SAAO,IAAI,IAAI,QAAQ;AACrB,UAAM,KAAK,IAAI,CAAC;AAGhB,QAAI,CAAC,YAAY,OAAO,OAAO,IAAI,IAAI,CAAC,MAAM,KAAK;AACjD,YAAM,UAAU,IAAI,QAAQ,MAAM,CAAC;AACnC,UAAI,YAAY,IAAI;AAClB,mBAAW,IAAI,MAAM,CAAC;AACtB,YAAI,IAAI;AAAA,MACV,OAAO;AACL,mBAAW,IAAI,MAAM,GAAG,UAAU,CAAC;AACnC,YAAI,UAAU;AAAA,MAChB;AACA;AAAA,IACF;AAGA,QAAI,CAAC,YAAY,OAAO,OAAO,IAAI,IAAI,CAAC,MAAM,KAAK;AACjD,YAAM,MAAM,IAAI,QAAQ,MAAM,IAAI,CAAC;AACnC,UAAI,QAAQ,IAAI;AACd,mBAAW,IAAI,MAAM,CAAC;AACtB,YAAI,IAAI;AAAA,MACV,OAAO;AACL,mBAAW,IAAI,MAAM,GAAG,MAAM,CAAC;AAC/B,YAAI,MAAM;AAAA,MACZ;AACA;AAAA,IACF;AAGA,QAAI,CAAC,aAAa,OAAO,OAAO,OAAO,MAAM;AAC3C,iBAAW;AACX,mBAAa;AACb,iBAAW;AACX;AACA;AAAA,IACF;AAEA,QAAI,UAAU;AACZ,UAAI,OAAO,YAAY;AAErB,YAAI,IAAI,IAAI,CAAC,MAAM,YAAY;AAC7B,qBAAW,KAAK;AAChB,eAAK;AACL;AAAA,QACF;AACA,mBAAW;AACX,qBAAa;AAAA,MACf;AACA,iBAAW;AACX;AACA;AAAA,IACF;AAEA,QAAI,OAAO,KAAK;AACd,YAAMC,WAAU,QAAQ,KAAK;AAC7B,UAAIA,SAAS,YAAW,KAAKA,QAAO;AACpC,gBAAU;AACV;AACA;AAAA,IACF;AAEA,eAAW;AACX;AAAA,EACF;AAEA,QAAM,UAAU,QAAQ,KAAK;AAC7B,MAAI,QAAS,YAAW,KAAK,OAAO;AAEpC,SAAO;AACT;AAEA,eAAsB,IAAI,SAAsB,MAAmD;AACjG,QAAM,YAAY,KAAK,aAAa;AAEpC,QAAM,YAAY,SAAS,SAAS;AAEpC,QAAM,QAAU,MAAM,mBAAmB,KAAK,aAAa;AAC3D,QAAM,UAAU,MAAM,WAAW,SAAS,SAAS;AACnD,QAAM,eAAe,IAAI,IAAI,QAAQ,IAAI,OAAK,EAAE,IAAI,CAAC;AAErD,QAAM,UAAU,MAAM,OAAO,OAAK,CAAC,aAAa,IAAI,EAAE,IAAI,CAAC;AAE3D,QAAM,UAA6B,CAAC;AACpC,aAAW,aAAa,SAAS;AAC/B,UAAM,KAAK,YAAY,IAAI;AAC3B,QAAI;AACF,YAAM,KAAK,kBAAkB,EAAE,MAAM,UAAU,MAAM,KAAK,UAAU,IAAI,CAAC;AACzE,YAAM,aAAa,mBAAmB,UAAU,GAAG;AACnD,iBAAW,QAAQ,YAAY;AAC7B,YAAI,KAAK,KAAK,EAAG,OAAM,QAAQ,QAAQ,MAAM,CAAC,CAAC;AAAA,MACjD;AACA,YAAM,YAAY,SAAS,WAAW,UAAU,IAAI;AACpD,YAAM,aAAa,YAAY,IAAI,IAAI;AACvC,YAAM,KAAK,iBAAiB,EAAE,MAAM,UAAU,MAAM,KAAK,UAAU,KAAK,WAAW,CAAC;AACpF,cAAQ,KAAK,EAAE,MAAM,UAAU,MAAM,SAAS,MAAM,UAAU,KAAK,MAAM,UAAU,EAAE,CAAC;AAAA,IACxF,SAAS,KAAK;AACZ,YAAM,QAAQ,eAAe,QAAQ,MAAM,IAAI,MAAM,OAAO,GAAG,CAAC;AAChE,YAAM,KAAK,UAAU,EAAE,MAAM,UAAU,MAAM,MAAM,CAAC;AACpD,cAAQ,KAAK,EAAE,MAAM,UAAU,MAAM,SAAS,OAAO,UAAU,KAAK,MAAM,YAAY,IAAI,IAAI,EAAE,GAAG,MAAM,CAAC;AAC1G;AAAA,IACF;AAAA,EACF;AACA,SAAO;AACT;AAEA,eAAsB,OAAO,SAAsB,MAAmD;AACpG,QAAM,YAAY,KAAK,aAAa;AAEpC,QAAM,YAAY,SAAS,SAAS;AAEpC,QAAM,QAAU,MAAM,mBAAmB,KAAK,aAAa;AAC3D,QAAM,UAAU,MAAM,WAAW,SAAS,SAAS;AACnD,QAAM,aAAa,IAAI,IAAI,QAAQ,IAAI,OAAK,CAAC,EAAE,MAAM,CAAC,CAAC,CAAC;AAExD,SAAO,MAAM,IAAI,OAAK;AACpB,UAAM,SAAS,WAAW,IAAI,EAAE,IAAI;AACpC,QAAI,QAAQ;AACV,aAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,WAAoB,WAAW,OAAO,UAAU;AAAA,IACjF;AACA,WAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,UAAmB;AAAA,EACpD,CAAC;AACH;AAEA,eAAsB,SAAS,SAAsB,MAAsC;AACzF,QAAM,YAAY,KAAK,aAAa;AAEpC,QAAM,YAAY,SAAS,SAAS;AAEpC,QAAM,UAAU,MAAM,WAAW,SAAS,SAAS;AACnD,MAAI,QAAQ,WAAW,EAAG;AAE1B,QAAM,OAAO,QAAQ,QAAQ,SAAS,CAAC;AACvC,QAAM,eAAe,SAAS,WAAW,KAAK,IAAI;AACpD;;;AEhKO,SAAS,eAAe,iBAA8C,SAAoC;AAC/G,QAAM,UAAU,eAAe,eAAe;AAC9C,SAAO;AAAA,IACL,KAAU,MAAM,IAAI,SAAS,OAAO;AAAA,IACpC,QAAU,MAAM,OAAO,SAAS,OAAO;AAAA,IACvC,UAAU,MAAM,SAAS,SAAS,OAAO;AAAA,EAC3C;AACF;;;ACnBA,SAAS,WAAAC,UAAS,iBAAiB;AACnC,SAAS,QAAAC,aAAY;;;ACGrB,IAAM,iBAAiB,oBAAI,IAAI;AAAA,EAC7B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,CAAC;AAsDD,eAAe,iBAAiB,SAAuD;AACrF,QAAM,SAAS,MAAM,QAAQ;AAAA,IAC3B;AAAA,EACF;AAEA,QAAM,SAAS,oBAAI,IAAuB;AAE1C,aAAW,EAAE,KAAK,KAAK,QAAQ;AAC7B,QAAI,eAAe,IAAI,IAAI,EAAG;AAE9B,UAAM,UAAU,MAAM,QAAQ,MAAuB,sBAAsB,IAAI,IAAI;AACnF,UAAM,YAAY,MAAM,QAAQ,MAAuB,sBAAsB,IAAI,IAAI;AAErF,UAAM,aAA0B,QAAQ,IAAI,UAAQ;AAAA,MAClD,MAAY,IAAI;AAAA,MAChB,MAAY,IAAI,KAAK,YAAY;AAAA,MACjC,UAAY,IAAI,YAAY,KAAK,IAAI,OAAO;AAAA,MAC5C,SAAY,IAAI,cAAc;AAAA,MAC9B,YAAY,IAAI,KAAK;AAAA,MACrB,QAAY;AAAA;AAAA,IACd,EAAE;AAEF,UAAM,UAAsB,CAAC;AAC7B,eAAW,OAAO,WAAW;AAE3B,UAAI,IAAI,WAAW,KAAM;AAEzB,YAAM,UAAU,MAAM,QAAQ,MAAuB,sBAAsB,IAAI,IAAI,IAAI;AACvF,YAAM,UAAU,QAAQ,KAAK,CAAC,GAAG,MAAM,EAAE,QAAQ,EAAE,KAAK,EAAE,IAAI,OAAK,EAAE,IAAI;AAGzE,UAAI,IAAI,UAAU,QAAQ,WAAW,GAAG;AACtC,cAAM,MAAM,WAAW,KAAK,OAAK,EAAE,SAAS,QAAQ,CAAC,CAAC;AACtD,YAAI,IAAK,KAAI,SAAS;AAAA,MACxB;AAEA,cAAQ,KAAK;AAAA,QACX,MAAS,IAAI;AAAA,QACb,SAAS;AAAA,QACT,QAAS,IAAI,WAAW;AAAA,MAC1B,CAAC;AAAA,IACH;AAEA,WAAO,IAAI,MAAM,EAAE,MAAM,SAAS,YAAY,QAAQ,CAAC;AAAA,EACzD;AAEA,SAAO;AACT;AAEA,eAAe,mBAAmB,SAAsB,WAAqD;AAC3G,QAAM,cAAc,YAAY,uBAAuB,SAAS,MAAM;AAEtE,QAAM,UAAU,MAAM,QAAQ,MAA+B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,QAYvD,WAAW;AAAA;AAAA,GAEhB;AAED,QAAM,cAAc,MAAM,QAAQ,MAA4D;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,GAW7F;AAED,QAAM,QAAW,oBAAI,IAAyB;AAC9C,QAAM,YAAY,oBAAI,IAAyB;AAC/C,aAAW,KAAK,aAAa;AAC3B,UAAM,MAAM,EAAE;AACd,QAAI,EAAE,oBAAoB,eAAe;AACvC,UAAI,CAAC,MAAM,IAAI,GAAG,EAAG,OAAM,IAAI,KAAK,oBAAI,IAAI,CAAC;AAC7C,YAAM,IAAI,GAAG,EAAG,IAAI,EAAE,WAAW;AAAA,IACnC,WAAW,EAAE,oBAAoB,UAAU;AACzC,UAAI,CAAC,UAAU,IAAI,GAAG,EAAG,WAAU,IAAI,KAAK,oBAAI,IAAI,CAAC;AACrD,gBAAU,IAAI,GAAG,EAAG,IAAI,EAAE,WAAW;AAAA,IACvC;AAAA,EACF;AAEA,QAAM,WAAW,oBAAI,IAAuB;AAC5C,aAAW,OAAO,SAAS;AAGzB;AAAA,EACF;AAGA,QAAM,cAAc,MAAM,QAAQ,MAAwD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,QAapF,WAAW;AAAA;AAAA,GAEhB;AAED,aAAW,OAAO,aAAa;AAC7B,UAAM,MAAM,IAAI;AAChB,QAAI,eAAe,IAAI,GAAG,EAAG;AAE7B,QAAI,CAAC,SAAS,IAAI,GAAG,EAAG,UAAS,IAAI,KAAK,EAAE,MAAM,KAAK,SAAS,CAAC,GAAG,SAAS,CAAC,EAAE,CAAC;AAEjF,UAAM,YAAY,SAAS,IAAI,GAAG;AAClC,cAAU,QAAQ,KAAK;AAAA,MACrB,MAAY,IAAI;AAAA,MAChB,MAAY,IAAI,UAAU,YAAY;AAAA,MACtC,UAAY,IAAI,gBAAgB;AAAA,MAChC,SAAY,IAAI,kBAAkB;AAAA,MAClC,YAAY,MAAM,IAAI,GAAG,GAAG,IAAI,IAAI,WAAW,KAAK;AAAA,MACpD,QAAY,UAAU,IAAI,GAAG,GAAG,IAAI,IAAI,WAAW,KAAK;AAAA,IAC1D,CAAC;AAAA,EACH;AAEA,SAAO;AACT;AAEA,eAAe,gBAAgB,SAAuD;AACpF,QAAM,QAAQ,MAAM,QAAQ,MAA4B,mCAAmC;AAC3F,QAAM,SAAS,MAAM,CAAC,GAAG,YAAY;AAErC,QAAM,UAAU,MAAM,QAAQ,MAA4C;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,4BAUhD,MAAM;AAAA;AAAA,GAE/B;AAED,QAAM,UAAU,MAAM,QAAQ,MAA2C;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,4BAO/C,MAAM;AAAA;AAAA,GAE/B;AAED,QAAM,WAAW,oBAAI,IAAuB;AAE5C,aAAW,OAAO,SAAS;AACzB,UAAM,MAAM,IAAI;AAChB,QAAI,eAAe,IAAI,GAAG,EAAG;AAE7B,QAAI,CAAC,SAAS,IAAI,GAAG,EAAG,UAAS,IAAI,KAAK,EAAE,MAAM,KAAK,SAAS,CAAC,GAAG,SAAS,CAAC,EAAE,CAAC;AAEjF,aAAS,IAAI,GAAG,EAAG,QAAQ,KAAK;AAAA,MAC9B,MAAY,IAAI;AAAA,MAChB,MAAY,IAAI,UAAU,YAAY;AAAA,MACtC,UAAY,IAAI,gBAAgB;AAAA,MAChC,SAAY,IAAI,kBAAkB;AAAA,MAClC,YAAY,IAAI,eAAe;AAAA,MAC/B,QAAY,IAAI,eAAe;AAAA,IACjC,CAAC;AAAA,EACH;AAGA,QAAM,cAAc,oBAAI,IAAqF;AAC7G,aAAW,OAAO,SAAS;AACzB,UAAM,MAAM,GAAG,IAAI,UAAU,IAAI,IAAI,UAAU;AAC/C,QAAI,CAAC,YAAY,IAAI,GAAG,GAAG;AACzB,kBAAY,IAAI,KAAK;AAAA,QACnB,WAAW,IAAI;AAAA,QACf,MAAW,IAAI;AAAA,QACf,SAAW,CAAC;AAAA,QACZ,QAAW,IAAI,eAAe;AAAA,MAChC,CAAC;AAAA,IACH;AACA,gBAAY,IAAI,GAAG,EAAG,QAAQ,KAAK,IAAI,WAAW;AAAA,EACpD;AAEA,aAAW,SAAS,YAAY,OAAO,GAAG;AACxC,UAAM,MAAM,SAAS,IAAI,MAAM,SAAS;AACxC,QAAI,CAAC,IAAK;AACV,QAAI,MAAM,SAAS,UAAW;AAC9B,QAAI,QAAQ,KAAK,EAAE,MAAM,MAAM,MAAM,SAAS,MAAM,SAAS,QAAQ,MAAM,OAAO,CAAC;AAAA,EACrF;AAEA,SAAO;AACT;AAMA,eAAsB,iBAAiB,SAAuD;AAE5F,MAAI;AACF,UAAM,QAAQ,MAAM,qCAAqC;AACzD,WAAO,iBAAiB,OAAO;AAAA,EACjC,QAAQ;AAAA,EAER;AAEA,MAAI;AACF,UAAM,QAAQ,MAAM,2BAA2B;AAC/C,WAAO,mBAAmB,OAAO;AAAA,EACnC,QAAQ;AAAA,EAER;AAEA,SAAO,gBAAgB,OAAO;AAChC;;;AC3RA,SAAS,qBAAqB,QAAgC;AAC5D,SAAO,OAAO,QAAQ,MAAM,EAAE,IAAI,CAAC,CAAC,MAAM,GAAG,MAAM;AACjD,UAAM,IAAI;AAGV,QAAI;AACJ,YAAQ,EAAE,IAAI,MAAM;AAAA,MAClB,KAAK;AAAa,eAAO;AAAa;AAAA,MACtC,KAAK;AAAA,MACL,KAAK;AAAa,eAAO;AAAa;AAAA,MACtC,KAAK;AAAa,eAAO;AAAa;AAAA,MACtC,KAAK;AAAa,eAAO;AAAa;AAAA;AAAA,MACtC,KAAK;AAAa,eAAO;AAAa;AAAA;AAAA,MACtC,KAAK;AAAa,eAAO;AAAa;AAAA,MACtC,KAAK;AAAa,eAAO;AAAa;AAAA,MACtC;AAAkB,eAAO;AAAa;AAAA,IACxC;AAEA,WAAO;AAAA,MACL;AAAA,MACA;AAAA,MACA,UAAY,EAAE,IAAI;AAAA,MAClB,SAAY,EAAE,IAAI,iBAAiB,SAAY,OAAO,EAAE,IAAI,YAAY,IAAI;AAAA,MAC5E,YAAY,EAAE,IAAI;AAAA,MAClB,QAAY,EAAE,IAAI;AAAA,IACpB;AAAA,EACF,CAAC;AACH;AAEA,SAAS,aAAa,GAAc,GAAuB;AACzD,SACE,EAAE,SAAc,EAAE,QAClB,EAAE,aAAc,EAAE,YAClB,EAAE,eAAe,EAAE,cACnB,EAAE,WAAc,EAAE,WACjB,EAAE,WAAW,WAAW,EAAE,WAAW;AAE1C;AAEO,SAAS,eACd,SAEA,QACY;AACZ,QAAM,cAAuC,CAAC;AAC9C,QAAM,gBAAuC,CAAC;AAC9C,QAAM,iBAAuC,CAAC;AAE9C,QAAM,cAAc,IAAI,IAAI,OAAO,IAAI,OAAK,EAAE,IAAI,CAAC;AAGnD,aAAW,CAAC,IAAI,KAAK,SAAS;AAC5B,QAAI,CAAC,YAAY,IAAI,IAAI,GAAG;AAC1B,oBAAc,KAAK,IAAI;AAAA,IACzB;AAAA,EACF;AAEA,aAAW,SAAS,QAAQ;AAC1B,UAAM,eAAe,QAAQ,IAAI,MAAM,IAAI;AAC3C,UAAM,gBAAgB,qBAAqB,MAAM,MAAM;AAEvD,QAAI,CAAC,cAAc;AAEjB,kBAAY,KAAK;AAAA,QACf,MAAS,MAAM;AAAA,QACf,SAAS;AAAA,QACT,SAAS,CAAC;AAAA;AAAA,MACZ,CAAC;AACD;AAAA,IACF;AAGA,UAAM,gBAAgB,IAAI,IAAI,aAAa,QAAQ,IAAI,OAAK,CAAC,EAAE,MAAM,CAAC,CAAC,CAAC;AACxE,UAAM,eAAgB,IAAI,IAAI,cAAc,IAAI,OAAK,CAAC,EAAE,MAAM,CAAC,CAAC,CAAC;AAEjE,UAAM,eAAwC,CAAC;AAC/C,UAAM,iBAAwC,CAAC;AAC/C,UAAM,kBAAwC,CAAC;AAC/C,UAAM,eAAwC,CAAC;AAC/C,UAAM,iBAAwC,CAAC;AAE/C,eAAW,CAAC,MAAM,GAAG,KAAK,cAAc;AACtC,YAAM,WAAW,cAAc,IAAI,IAAI;AACvC,UAAI,CAAC,UAAU;AACb,qBAAa,KAAK,GAAG;AAAA,MACvB,WAAW,CAAC,aAAa,UAAU,GAAG,GAAG;AACvC,wBAAgB,KAAK,EAAE,MAAM,QAAQ,UAAU,OAAO,IAAI,CAAC;AAAA,MAC7D;AAAA,IACF;AAEA,eAAW,CAAC,IAAI,KAAK,eAAe;AAClC,UAAI,CAAC,aAAa,IAAI,IAAI,GAAG;AAC3B,uBAAe,KAAK,IAAI;AAAA,MAC1B;AAAA,IACF;AAEA,UAAM,aACJ,aAAa,SAAY,KACzB,eAAe,SAAU,KACzB,gBAAgB,SAAS,KACzB,aAAa,SAAY,KACzB,eAAe,SAAU;AAE3B,QAAI,YAAY;AACd,qBAAe,KAAK;AAAA,QAClB,MAAM,MAAM;AAAA,QACZ;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,MACF,CAAC;AAAA,IACH;AAAA,EACF;AAEA,SAAO,EAAE,aAAa,eAAe,eAAe;AACtD;;;AF/FA,eAAe,oBAAoB,KAA8B;AAC/D,MAAI;AACJ,MAAI;AACF,cAAU,MAAMC,SAAQ,GAAG;AAAA,EAC7B,QAAQ;AACN,WAAO;AAAA,EACT;AAEA,QAAM,OAAO,QACV,OAAO,OAAK,EAAE,SAAS,MAAM,CAAC,EAC9B,IAAI,OAAK;AACR,UAAM,QAAQ,SAAS,KAAK,CAAC;AAC7B,WAAO,QAAQ,SAAS,MAAM,CAAC,GAAG,EAAE,IAAI;AAAA,EAC1C,CAAC;AAEH,SAAO,KAAK,WAAW,IAAI,IAAI,KAAK,IAAI,GAAG,IAAI,IAAI;AACrD;AAEA,SAAS,aAAa,GAAmB;AACvC,SAAO,OAAO,CAAC,EAAE,SAAS,GAAG,GAAG;AAClC;AAEA,SAAS,YAAY,KAAwB;AAC3C,MAAI,MAAM,IAAI,IAAI,IAAI,KAAK,IAAI,IAAI;AACnC,MAAI,IAAI,WAAkB,QAAO;AACjC,MAAI,CAAC,IAAI,YAAY,CAAC,IAAI,WAAY,QAAO;AAC7C,MAAI,IAAI,OAAkB,QAAO;AACjC,MAAI,IAAI,YAAY,OAAW,QAAO,YAAY,IAAI,OAAO;AAC7D,SAAO;AACT;AAEA,SAAS,YAAY,MAAkB,mBAAmB,OAAe;AACvE,QAAM,QAAkB,CAAC;AAGzB,aAAW,SAAS,KAAK,aAAa;AACpC,UAAM,OAAO,MAAM,QAAQ,IAAI,WAAW;AAC1C,UAAM,KAAK,+BAA+B,MAAM,IAAI,KAAK;AACzD,UAAM,KAAK,KAAK,IAAI,CAAC,GAAG,MAAM,KAAK,CAAC,GAAG,IAAI,KAAK,SAAS,IAAI,MAAM,EAAE,EAAE,EAAE,KAAK,IAAI,CAAC;AACnF,UAAM,KAAK,IAAI;AACf,UAAM,KAAK,EAAE;AAEb,eAAW,OAAO,MAAM,SAAS;AAC/B,YAAM,SAAS,IAAI,SAAS,YAAY;AACxC,YAAMC,QAAS,IAAI,QAAQ,IAAI,OAAK,IAAI,CAAC,GAAG,EAAE,KAAK,IAAI;AACvD,YAAM,KAAK,UAAU,MAAM,wBAAwB,IAAI,IAAI,SAAS,MAAM,IAAI,MAAMA,KAAI,IAAI;AAC5F,YAAM,KAAK,EAAE;AAAA,IACf;AAAA,EACF;AAGA,aAAW,QAAQ,KAAK,eAAe;AACrC,QAAI,kBAAkB;AACpB,YAAM,KAAK,yBAAyB,IAAI,IAAI;AAAA,IAC9C,OAAO;AACL,YAAM,KAAK,2BAA2B,IAAI,yBAAyB;AAAA,IACrE;AACA,UAAM,KAAK,EAAE;AAAA,EACf;AAGA,aAAW,OAAO,KAAK,gBAAgB;AACrC,eAAW,OAAO,IAAI,cAAc;AAClC,YAAM,SAAS,YAAY,GAAG;AAC9B,YAAM,KAAK,gBAAgB,IAAI,IAAI,gBAAgB,MAAM,GAAG;AAC5D,YAAM,KAAK,EAAE;AAAA,IACf;AAEA,eAAW,QAAQ,IAAI,gBAAgB;AACrC,UAAI,kBAAkB;AACpB,cAAM,KAAK,gBAAgB,IAAI,IAAI,kBAAkB,IAAI,IAAI;AAAA,MAC/D,OAAO;AACL,cAAM,KAAK,4BAA4B,IAAI,IAAI,kBAAkB,IAAI,yBAAyB;AAAA,MAChG;AACA,YAAM,KAAK,EAAE;AAAA,IACf;AAEA,eAAW,UAAU,IAAI,iBAAiB;AACxC,UAAI,kBAAkB;AACpB,cAAM,KAAK,gBAAgB,IAAI,IAAI,mBAAmB,OAAO,IAAI,UAAU,OAAO,MAAM,IAAI,GAAG;AAAA,MACjG,OAAO;AACL,cAAM,KAAK,uCAAuC,IAAI,IAAI,MAAM,OAAO,IAAI,6BAA6B;AACxG,cAAM,KAAK,gBAAgB,OAAO,OAAO,IAAI,EAAE;AAC/C,cAAM,KAAK,gBAAgB,OAAO,MAAM,IAAI,EAAE;AAAA,MAChD;AACA,YAAM,KAAK,EAAE;AAAA,IACf;AAEA,eAAW,OAAO,IAAI,cAAc;AAClC,YAAM,SAAS,IAAI,SAAS,YAAY;AACxC,YAAM,OAAS,IAAI,QAAQ,IAAI,OAAK,IAAI,CAAC,GAAG,EAAE,KAAK,IAAI;AACvD,YAAM,KAAK,UAAU,MAAM,wBAAwB,IAAI,IAAI,SAAS,IAAI,IAAI,MAAM,IAAI,IAAI;AAC1F,YAAM,KAAK,EAAE;AAAA,IACf;AAEA,eAAW,QAAQ,IAAI,gBAAgB;AACrC,YAAM,KAAK,yBAAyB,IAAI,IAAI;AAC5C,YAAM,KAAK,EAAE;AAAA,IACf;AAAA,EACF;AAEA,SAAO,MAAM,KAAK,IAAI,EAAE,QAAQ;AAClC;AAEA,eAAsB,kBAAkB,SAAmD;AACzF,QAAM,UAAU,MAAM,iBAAiB,QAAQ,OAAO;AACtD,QAAM,OAAU,eAAe,SAAS,QAAQ,MAAM;AAEtD,QAAM,UACJ,KAAK,YAAY,WAAc,KAC/B,KAAK,cAAc,WAAY,KAC/B,KAAK,eAAe,WAAW;AAEjC,QAAM,MAAM,UAAU,KAAK,YAAY,MAAM,QAAQ,oBAAoB,KAAK;AAE9E,QAAM,MAAW,MAAM,oBAAoB,QAAQ,aAAa;AAChE,QAAM,SAAW,QAAQ,SAAQ,oBAAI,KAAK,GAAE,YAAY,EAAE,QAAQ,YAAY,EAAE,EAAE,MAAM,GAAG,EAAE;AAC7F,QAAM,WAAW,GAAG,aAAa,GAAG,CAAC,IAAI,MAAM;AAE/C,MAAI,CAAC,SAAS;AACZ,UAAM,UAAUC,MAAK,QAAQ,eAAe,QAAQ,GAAG,MAAM,MAAM,MAAM;AAAA,EAC3E;AAEA,SAAO,EAAE,UAAU,KAAK,QAAQ;AAClC;;;ATrHA;AAKA;AAKA;;;AY/CA;AAmCO,IAAM,sBAAN,MAAM,qBAGX;AAAA,EAKA,YAA6B,QAAgB;AAAhB;AAAA,EAAiB;AAAA,EAAjB;AAAA,EAJrB,WAA2B,CAAC;AAAA,EAC5B,cAAmE,oBAAI,IAAI;AAAA,EAC3E,YAA6C,CAAC;AAAA,EAItD,QAAQ,MAAyB;AAC/B,SAAK,WAAW;AAChB,WAAO;AAAA,EACT;AAAA,EAEA,IACE,SAC6D;AAC7D,UAAM,OAAO,IAAI,qBAA4D,KAAK,MAAM;AACxF,SAAK,WAAc,KAAK;AACxB,SAAK,cAAc,KAAK;AACxB,SAAK,YAAc,CAAC,GAAG,KAAK,WAAW,OAAsC;AAC7E,WAAO;AAAA,EACT;AAAA,EAEA,GACE,OACA,SAIM;AACN,SAAK,YAAY,IAAI,OAAO,OAAiD;AAC7E,WAAO;AAAA,EACT;AAAA,EAMA,MAAM,UAAqD;AACzD,UAAM,SAAW,oBAAoB,SAAS,KAAK,OAAO,IAAI,IAAI,KAAK,SAAS,GAAG;AACnF,UAAM,WAAW,KAAK;AAEtB,QAAI,aAAa,QAAW;AAC1B,YAAM,MAAM,oBAAI,IAA2B;AAC3C,iBAAW,CAAC,KAAK,EAAE,KAAK,OAAO,QAAQ,QAAQ,GAAG;AAChD,YAAI,GAAI,KAAI,IAAI,KAAK,EAAmB;AAAA,MAC1C;AACA,aAAO;AAAA,QACL,WAAc;AAAA,QACd,cAAc,oBAAI,IAAI;AAAA,QACtB,SAAc;AAAA,QACd,WAAc,CAAC;AAAA,MACjB;AAAA,IACF;AAIA,UAAM,UAAc,oBAAI,IAA2B;AACnD,UAAM,cAAc,oBAAI,IAAwB;AAChD,eAAW,CAAC,OAAO,OAAO,KAAK,KAAK,aAAa;AAC/C,cAAQ;AAAA,QAAI;AAAA,QAAO,CAAC,YAClB,QAAQ,SAAS,EAAE,OAAO,CAAiD;AAAA,MAC7E;AACA,kBAAY,IAAI,OAAO,OAAqB;AAAA,IAC9C;AACA,WAAO;AAAA,MACL,WAAc;AAAA,MACd,cAAc;AAAA,MACd,SAAc;AAAA,MACd,WAAc;AAAA,IAChB;AAAA,EACF;AACF;AAoBO,SAAS,mBACd,iBACA,eAC+C;AAE/C,MAAI,kBAAkB,QAAW;AAC/B,WAAO,IAAI,oBAAoB,eAAyB,EAAE,MAAM,aAAa;AAAA,EAC/E;AAGA,MAAI,eAAe,iBAAiB;AAClC,WAAO,IAAI,oBAAoB,eAAyB;AAAA,EAC1D;AAGA,QAAM,MAAM;AACZ,QAAM,MAAM,oBAAI,IAA2B;AAC3C,aAAW,CAAC,KAAK,EAAE,KAAK,OAAO,QAAQ,GAAG,GAAG;AAC3C,QAAI,GAAI,KAAI,IAAI,KAAK,EAAE;AAAA,EACzB;AACA,SAAO,EAAE,WAAW,KAAK,cAAc,oBAAI,IAAI,GAAG,SAAS,oBAAoB,OAAO,GAAG,WAAW,CAAC,EAAE;AACzG;;;ACtJA;AAeO,IAAM,eAAN,MAAiD;AAAA,EAGtD,YACmB,OACA,QACjB;AAFiB;AACA;AAAA,EAChB;AAAA,EAFgB;AAAA,EACA;AAAA,EAJX,QAAqB,CAAC;AAAA,EAO9B,QAAQ,MAAyB;AAC/B,SAAK,QAAQ;AACb,WAAO;AAAA,EACT;AAAA,EAEA,OACE,SACuB;AACvB,UAAM,OAAO,KAAK;AAClB,UAAM,OAAO,KAAK;AAClB,WAAO;AAAA,MACL,YAAY;AAAA,MACZ,UAAU,CAAC,OAAyC;AAClD,cAAM,SAAS,oBAAoB,SAAS,IAAI,IAAI,KAAK,GAAG;AAC5D,eAAO,EAAE,GAAG,QAAQ,IAAI,EAAE,OAAO,CAAC,GAAG,GAAG;AAAA,MAC1C;AAAA,IACF;AAAA,EACF;AACF;AA+BO,SAAS,YAKd,MACA,OACA,SACqD;AACrD,MAAI,YAAY,QAAW;AAEzB,WAAO,IAAI,aAA4B,MAAM,KAAK,EAAE,OAAO,OAAO;AAAA,EACpE;AACA,SAAO,IAAI,aAA4B,MAAM,KAAK;AACpD;;;ACtFA;AA8BO,IAAM,iBAAN,MAAM,gBAA2E;AAAA,EAC9E,YACW,MACA,OACA,OACjB;AAHiB;AACA;AACA;AAAA,EAChB;AAAA,EAHgB;AAAA,EACA;AAAA,EACA;AAAA,EAGnB,OAAO,OAA4B,KAAuD;AACxF,WAAO,IAAI,gBAA2C,KAAK,CAAC,GAAG,CAAC,CAAC;AAAA,EACnE;AAAA,EAEA,IACE,KACmE;AACnE,WAAO,IAAI;AAAA,MACT,KAAK;AAAA,MACL,CAAC,GAAG,KAAK,OAAO,GAA2B;AAAA,MAC3C,KAAK;AAAA,IACP;AAAA,EACF;AAAA,EAEA,QAAQ,MAAgD;AACtD,WAAO,IAAI;AAAA,MACT,KAAK;AAAA,MACL,KAAK;AAAA,MACL;AAAA,IACF;AAAA,EACF;AAAA,EAEA,OACE,SACwB;AACxB,WAAO;AAAA,MACL,aAAa,KAAK;AAAA,MAClB,OAAa,KAAK;AAAA,MAClB,UAAa,KAAK;AAAA,MAClB,UAAa;AAAA,IACf;AAAA,EACF;AACF;AAEO,SAAS,cACd,KAC4C;AAC5C,SAAO,eAAe,OAAO,GAAG;AAClC;AAMA,SAAS,WAAW,KAA6D;AAC/E,SAAO,gBAAgB;AACzB;AAGA,SAAS,aAAa,KAA+D;AACnF,SAAO,iBAAiB;AAC1B;AAIO,SAAS,eAAe,UAA4D;AAGzF,QAAM,QAAQ,oBAAI,IAAyC;AAE3D,WAAS,WAAW,KAAwC;AAC1D,QAAI,MAAM,IAAI,IAAI,WAAW,EAAG;AAChC,UAAM,IAAI,IAAI,aAAa,GAAG;AAC9B,eAAW,OAAO,IAAI,OAAO;AAC3B,UAAI,aAAa,GAAG,GAAG;AACrB,mBAAW,GAAG;AAAA,MAChB;AAAA,IACF;AAAA,EACF;AAEA,aAAW,OAAO,UAAU;AAC1B,eAAW,GAAG;AAAA,EAChB;AAGA,QAAM,QAAQ,oBAAI,IAAuB;AAEzC,WAAS,MAAM,KAAa,OAAuB;AACjD,UAAM,IAAI,MAAM,IAAI,GAAG,KAAK;AAC5B,QAAI,MAAM,EAAG;AACb,QAAI,MAAM,GAAG;AACX,YAAM,QAAQ,CAAC,GAAG,OAAO,GAAG,EAAE,KAAK,UAAK;AACxC,YAAM,IAAI,MAAM,wCAAwC,KAAK,EAAE;AAAA,IACjE;AACA,UAAM,IAAI,KAAK,CAAC;AAChB,UAAM,MAAM,MAAM,IAAI,GAAG;AACzB,QAAI,KAAK;AACP,iBAAW,OAAO,IAAI,OAAO;AAC3B,YAAI,aAAa,GAAG,GAAG;AACrB,gBAAM,IAAI,aAAa,CAAC,GAAG,OAAO,GAAG,CAAC;AAAA,QACxC;AAAA,MACF;AAAA,IACF;AACA,UAAM,IAAI,KAAK,CAAC;AAAA,EAClB;AAEA,aAAW,OAAO,MAAM,OAAO,GAAG;AAChC,UAAM,IAAI,aAAa,CAAC,CAAC;AAAA,EAC3B;AACF;AAKO,SAAS,oBACd,UACA,IACyB;AAEzB,QAAM,QAAQ,oBAAI,IAAqB;AAEvC,WAAS,eAAe,KAA2B,UAA2B;AAC5E,QAAI,WAAW,GAAG,GAAG;AACnB,YAAM,MAAM,IAAI;AAChB,UAAI,MAAM,IAAI,GAAG,EAAG,QAAO,MAAM,IAAI,GAAG;AACxC,YAAM,OAAO,IAAI,SAAS,EAAE;AAC5B,YAAM,IAAI,KAAK,IAAI;AACnB,aAAO;AAAA,IACT;AACA,QAAI,aAAa,GAAG,GAAG;AACrB,YAAM,MAAM,IAAI;AAChB,UAAI,MAAM,IAAI,GAAG,EAAG,QAAO,MAAM,IAAI,GAAG;AACxC,YAAM,eAAwC,CAAC;AAE/C,YAAM,SAAS,oBAAoB,WAAW,GAAG,IAAI,IAAI,UAAU,GAAG;AACtE,mBAAa,QAAQ,IAAI;AACzB,iBAAW,KAAK,IAAI,OAAO;AACzB,cAAM,SAAS,WAAW,CAAC,IAAI,EAAE,aAAa,EAAE;AAChD,qBAAa,MAAM,IAAI,eAAe,GAAG,GAAG;AAAA,MAC9C;AACA,YAAM,OAAO,IAAI,SAAS,YAAY;AACtC,YAAM,IAAI,KAAK,IAAI;AACnB,aAAO;AAAA,IACT;AACA,UAAM,IAAI,MAAM,8CAA8C,QAAQ,GAAG;AAAA,EAC3E;AAEA,QAAM,SAAkC,CAAC;AACzC,aAAW,OAAO,UAAU;AAC1B,WAAO,IAAI,WAAW,IAAI,eAAe,KAAK,IAAI,WAAW;AAAA,EAC/D;AACA,SAAO;AACT;;;ACrLA;AAaO,IAAM,oBAAN,MAAwB;AAAA,EAK7B,YAA6B,OAAe;AAAf;AAAA,EAAgB;AAAA,EAAhB;AAAA,EAJrB,WAA6B,CAAC;AAAA,EAC9B;AAAA,EACA;AAAA,EAIR,QAAQ,MAAyB;AAC/B,SAAK,WAAW;AAChB,WAAO;AAAA,EACT;AAAA,EAEA,UAAU,IAAuB;AAC/B,SAAK,eAAe;AACpB,WAAO;AAAA,EACT;AAAA,EAEA,WAAW,IAAwB;AACjC,SAAK,gBAAgB;AACrB,WAAO;AAAA,EACT;AAAA,EAEA,QAAuB;AACrB,UAAM,SAAS,oBAAoB,cAAc,KAAK,KAAK,IAAI,KAAK,SAAS,GAAG;AAChF,WAAO;AAAA,MACL,OAAa,KAAK;AAAA,MAClB,YAAa,KAAK;AAAA,MAClB,aAAa,KAAK;AAAA,MAClB,SAAa;AAAA,IACf;AAAA,EACF;AACF;AAIO,SAAS,iBAAiB,MAAiC;AAChE,SAAO,IAAI,kBAAkB,IAAI;AACnC;;;ACjDA;;;ACsBA,SAAS,eAAe,QAAwC;AAC9D,SAAQ,OAA+C;AACzD;AAEO,SAAS,gBAAgB,QAAgC;AAC9D,QAAM,MAAO,OAAO;AACpB,QAAM,WAAW,IAAI,MAAM;AAE3B,MAAI,aAAa,UAAU;AACzB,WAAO,gBAAgB,QAAQ,kBAAkB,GAAG,CAAC;AAAA,EACvD;AACA,MAAI,aAAa,UAAU;AACzB,WAAO,gBAAgB,QAAQ,kBAAkB,GAAG,CAAC;AAAA,EACvD;AACA,MAAI,aAAa,WAAW;AAC1B,WAAO,gBAAgB,QAAQ,EAAE,MAAM,UAAU,CAAC;AAAA,EACpD;AACA,MAAI,aAAa,QAAQ;AACvB,UAAM,UAAU,IAAI,SAAS;AAC7B,UAAM,SAAS,UAAU,OAAO,OAAO,OAAO,IAAI,CAAC;AACnD,WAAO,gBAAgB,QAAQ,EAAE,MAAM,UAAU,MAAM,OAAO,CAAC;AAAA,EACjE;AACA,MAAI,aAAa,UAAU;AACzB,WAAO,gBAAgB,QAAQ,kBAAkB,GAAG,CAAC;AAAA,EACvD;AACA,MAAI,aAAa,SAAS;AACxB,UAAM,UAAU,IAAI,SAAS;AAC7B,UAAM,SAAqB,EAAE,MAAM,QAAQ;AAC3C,QAAI,QAAS,QAAO,OAAO,IAAI,gBAAgB,OAAO;AACtD,WAAO,gBAAgB,QAAQ,MAAM;AAAA,EACvC;AACA,MAAI,aAAa,YAAY;AAC3B,UAAM,QAAQ,IAAI,WAAW;AAE7B,UAAM,OAAO,eAAe,MAAM;AAClC,UAAM,cAAc,gBAAgB,KAAK;AACzC,WAAO,OAAO,EAAE,GAAG,aAAa,aAAa,KAAK,IAAI;AAAA,EACxD;AACA,MAAI,aAAa,YAAY;AAC3B,UAAM,QAAQ,IAAI,WAAW;AAC7B,UAAM,OAAO,eAAe,MAAM;AAClC,UAAM,cAAc,gBAAgB,KAAK;AACzC,UAAM,YAAY,YAAY,MAAM;AACpC,UAAM,SAAqB,OAAO,cAAc,WAC5C,EAAE,GAAG,aAAa,MAAM,CAAC,WAAW,MAAM,EAAE,IAC5C;AACJ,WAAO,OAAO,EAAE,GAAG,QAAQ,aAAa,KAAK,IAAI;AAAA,EACnD;AACA,MAAI,aAAa,WAAW;AAC1B,UAAM,QAAQ,IAAI,WAAW;AAC7B,UAAM,eAAe,IAAI,cAAc;AACvC,UAAM,cAAc,gBAAgB,KAAK;AACzC,UAAM,OAAO,eAAe,MAAM;AAClC,UAAM,SAAqB,iBAAiB,SACxC,EAAE,GAAG,aAAa,SAAS,aAAa,IACxC;AACJ,WAAO,OAAO,EAAE,GAAG,QAAQ,aAAa,KAAK,IAAI;AAAA,EACnD;AAEA,SAAO,CAAC;AACV;AAEA,SAAS,gBAAgB,QAAoB,QAAgC;AAC3E,QAAM,OAAO,eAAe,MAAM;AAClC,SAAO,OAAO,EAAE,GAAG,QAAQ,aAAa,KAAK,IAAI;AACnD;AAEA,SAAS,kBAAkB,KAA0C;AACnE,QAAM,SAAqB,EAAE,MAAM,SAAS;AAC5C,QAAM,SAAS,IAAI,QAAQ;AAC3B,MAAI,CAAC,OAAQ,QAAO;AACpB,aAAW,SAAS,QAAQ;AAC1B,UAAM,WAAoC,MAAM,MAAM,OAAO,MAAM;AACnE,QAAI,CAAC,SAAU;AACf,UAAM,OAAO,SAAS;AACtB,QAAI,SAAS,iBAAiB;AAC5B,YAAM,MAAM,SAAS;AACrB,UAAI,QAAQ,QAAY,QAAO,QAAQ,IAAI;AAC3C,UAAI,QAAQ,OAAY,QAAO,QAAQ,IAAI;AAC3C,UAAI,QAAQ,MAAY,QAAO,QAAQ,IAAI;AAC3C,UAAI,QAAQ,WAAY,QAAO,QAAQ,IAAI;AAC3C,UAAI,QAAQ,OAAY,QAAO,QAAQ,IAAI;AAC3C,UAAI,QAAQ,OAAY,QAAO,QAAQ,IAAI;AAAA,IAC7C;AACA,QAAI,SAAS,gBAAgB,SAAS,YAAY,QAAW;AAC3D,aAAO,WAAW,IAAI,SAAS;AAAA,IACjC;AACA,QAAI,SAAS,gBAAgB,SAAS,YAAY,QAAW;AAC3D,aAAO,WAAW,IAAI,SAAS;AAAA,IACjC;AAAA,EACF;AACA,SAAO;AACT;AAEA,SAAS,kBAAkB,KAA0C;AACnE,QAAM,SAAqB,EAAE,MAAM,SAAS;AAC5C,QAAM,SAAS,IAAI,QAAQ;AAC3B,MAAI,CAAC,OAAQ,QAAO;AACpB,aAAW,SAAS,QAAQ;AAC1B,UAAM,WAAoC,MAAM,MAAM,OAAO,MAAM;AACnE,QAAI,CAAC,SAAU;AACf,UAAM,OAAO,SAAS;AACtB,QAAI,SAAS,kBAAkB,SAAS,UAAU,QAAW;AAC3D,UAAI,SAAS,WAAW;AACtB,eAAO,SAAS,IAAI,SAAS;AAAA,MAC/B,OAAO;AACL,eAAO,kBAAkB,IAAI,SAAS;AAAA,MACxC;AAAA,IACF;AACA,QAAI,SAAS,eAAe,SAAS,UAAU,QAAW;AACxD,UAAI,SAAS,WAAW;AACtB,eAAO,SAAS,IAAI,SAAS;AAAA,MAC/B,OAAO;AACL,eAAO,kBAAkB,IAAI,SAAS;AAAA,MACxC;AAAA,IACF;AACA,QAAI,SAAS,iBAAiB,SAAS,UAAU,QAAW;AAC1D,aAAO,YAAY,IAAI,SAAS;AAAA,IAClC;AAAA,EACF;AACA,SAAO;AACT;AAEA,SAAS,kBAAkB,KAA0C;AACnE,QAAM,QAAQ,IAAI,OAAO;AACzB,QAAM,gBAA4C,SAAS,CAAC;AAE5D,QAAM,aAAyC,CAAC;AAChD,QAAM,WAAqB,CAAC;AAE5B,aAAW,CAAC,KAAK,WAAW,KAAK,OAAO,QAAQ,aAAa,GAAG;AAC9D,UAAM,WAAY,YAAY;AAC9B,UAAM,aAAa,SAAS,MAAM,MAAM;AACxC,eAAW,GAAG,IAAI,gBAAgB,WAAW;AAC7C,QAAI,CAAC,YAAY;AACf,eAAS,KAAK,GAAG;AAAA,IACnB;AAAA,EACF;AAEA,QAAM,SAAqB,EAAE,MAAM,UAAU,WAAW;AACxD,MAAI,SAAS,SAAS,GAAG;AACvB,WAAO,UAAU,IAAI;AAAA,EACvB;AACA,SAAO;AACT;;;AC9GA,SAAS,cAAc,MAAsB;AAC3C,SAAO,KAAK,QAAQ,8BAA8B,MAAM;AAC1D;AAEA,SAAS,kBAAkB,MAAwB;AACjD,QAAM,UAAU,KAAK,MAAM,4BAA4B;AACvD,SAAO,UAAU,QAAQ,IAAI,OAAK,EAAE,MAAM,CAAC,CAAC,IAAI,CAAC;AACnD;AAEA,SAAS,WAAW,GAAmB;AACrC,SAAO,EAAE,OAAO,CAAC,EAAE,YAAY,IAAI,EAAE,MAAM,CAAC;AAC9C;AAGA,SAAS,cAAc,KAAqB;AAC1C,SAAO,IAAI,MAAM,GAAG,EAAE,IAAI,UAAU,EAAE,KAAK,GAAG;AAChD;AAaA,SAAS,aAAa,QAAgB,MAAsB;AAC1D,QAAM,WAAW,KAAK,MAAM,GAAG,EAAE,OAAO,OAAO;AAC/C,MAAI,SAAS,WAAW,EAAG,QAAO,OAAO,YAAY;AAErD,QAAM,UAAU,CAAC,MAAuB,EAAE,WAAW,GAAG;AACxD,QAAM,WAAW,SAAS,KAAK,OAAK,CAAC,QAAQ,CAAC,CAAC,KAAK;AACpD,QAAM,UAAW,SAAS,SAAS,SAAS,CAAC,KAAK;AAClD,QAAM,mBAAmB,QAAQ,OAAO;AACxC,QAAM,gBAAmB,CAAC,QAAQ,OAAO,KAAK,YAAY;AAE1D,MAAI,cAAe,QAAO,GAAG,WAAW,OAAO,CAAC,IAAI,QAAQ;AAE5D,QAAM,IAAI,OAAO,YAAY;AAC7B,MAAI,MAAM,OAAO;AACf,QAAI,iBAAkB,QAAO,OAAO,QAAQ,OAAO,QAAQ,MAAM,CAAC,CAAC;AACnE,WAAO,QAAQ,QAAQ;AAAA,EACzB;AACA,MAAI,MAAM,OAAU,QAAO,UAAU,QAAQ;AAC7C,MAAI,MAAM,QAAU,QAAO,UAAU,QAAQ;AAC7C,MAAI,MAAM,MAAU,QAAO,UAAU,QAAQ;AAC7C,MAAI,MAAM,SAAU,QAAO,UAAU,QAAQ;AAC7C,SAAO,GAAG,EAAE,YAAY,CAAC,IAAI,QAAQ;AACvC;AAYA,SAAS,iBAAiB,QAAgB,MAAsB;AAC9D,QAAM,WAAW,KAAK,MAAM,GAAG,EAAE,OAAO,OAAO;AAC/C,MAAI,SAAS,WAAW,EAAG,QAAO,OAAO,YAAY;AAErD,QAAM,UAAU,CAAC,MAAuB,EAAE,WAAW,GAAG;AACxD,QAAM,WAAW,SAAS,KAAK,OAAK,CAAC,QAAQ,CAAC,CAAC,KAAK;AACpD,QAAM,UAAW,SAAS,SAAS,SAAS,CAAC,KAAK;AAClD,QAAM,mBAAmB,QAAQ,OAAO;AACxC,QAAM,gBAAmB,CAAC,QAAQ,OAAO,KAAK,YAAY;AAE1D,MAAI,cAAe,QAAO,GAAG,OAAO,GAAG,WAAW,QAAQ,CAAC;AAE3D,QAAM,IAAI,OAAO,YAAY;AAC7B,MAAI,MAAM,OAAO;AACf,QAAI,iBAAkB,QAAO,MAAM,WAAW,QAAQ,CAAC,KAAK,WAAW,QAAQ,MAAM,CAAC,CAAC,CAAC;AACxF,WAAO,OAAO,WAAW,QAAQ,CAAC;AAAA,EACpC;AACA,MAAI,MAAM,OAAU,QAAO,SAAS,WAAW,QAAQ,CAAC;AACxD,MAAI,MAAM,QAAU,QAAO,SAAS,WAAW,QAAQ,CAAC;AACxD,MAAI,MAAM,MAAU,QAAO,SAAS,WAAW,QAAQ,CAAC;AACxD,MAAI,MAAM,SAAU,QAAO,SAAS,WAAW,QAAQ,CAAC;AACxD,SAAO,GAAG,EAAE,YAAY,CAAC,GAAG,WAAW,QAAQ,CAAC;AAClD;AAIO,SAAS,oBACd,QACA,SACa;AACb,QAAM,QAAU,SAAS,SAAW;AACpC,QAAM,UAAU,SAAS,WAAW;AAEpC,QAAM,OAA4B,EAAE,OAAO,QAAQ;AACnD,MAAI,SAAS,YAAa,MAAK,cAAc,QAAQ;AAErD,QAAM,QAA0D,CAAC;AACjE,MAAI,oBAAoB;AAExB,aAAW,SAAS,QAAQ;AAE1B,UAAM,mBAAmB,MAAM,SAAS,cAAc;AACtD,UAAM,kBAAmB,MAAM,cAAc;AAC7C,QAAI,oBAAoB,SAAU;AAElC,UAAM,cAAc,cAAc,MAAM,IAAI;AAC5C,QAAI,CAAC,MAAM,WAAW,EAAG,OAAM,WAAW,IAAI,CAAC;AAE/C,UAAM,SAAS,MAAM,OAAO,YAAY;AACxC,UAAM,SAAS,MAAM;AAGrB,UAAM,aAAiC,CAAC;AAExC,eAAW,aAAa,kBAAkB,MAAM,IAAI,GAAG;AACrD,UAAI,cAA0B,EAAE,MAAM,SAAS;AAC/C,UAAI,QAAQ,QAAQ;AAClB,cAAM,YAAa,OAAO,OAAO;AACjC,cAAM,QAAQ,UAAU,OAAO;AAC/B,cAAM,gBAA4C,SAAS,CAAC;AAC5D,YAAI,cAAc,SAAS,GAAG;AAC5B,wBAAc,gBAAgB,cAAc,SAAS,CAAe;AAAA,QACtE;AAAA,MACF;AACA,iBAAW,KAAK,EAAE,MAAM,WAAW,IAAI,QAAQ,UAAU,MAAM,QAAQ,YAAY,CAAC;AAAA,IACtF;AAEA,QAAI,QAAQ,OAAO;AACjB,YAAM,WAAY,OAAO,MAAM;AAC/B,YAAM,QAAQ,SAAS,OAAO;AAC9B,YAAM,gBAA4C,SAAS,CAAC;AAC5D,iBAAW,CAAC,KAAK,WAAW,KAAK,OAAO,QAAQ,aAAa,GAAG;AAC9D,cAAM,WAAY,YAAY;AAC9B,cAAM,aAAa,SAAS,MAAM,MAAM;AACxC,mBAAW,KAAK;AAAA,UACd,MAAM;AAAA,UACN,IAAI;AAAA,UACJ,UAAU,CAAC;AAAA,UACX,QAAQ,gBAAgB,WAAW;AAAA,QACrC,CAAC;AAAA,MACH;AAAA,IACF;AAGA,QAAI;AACJ,QAAI,QAAQ,MAAM;AAChB,oBAAc;AAAA,QACZ,UAAU;AAAA,QACV,SAAS,EAAE,oBAAoB,EAAE,QAAQ,gBAAgB,OAAO,IAAI,EAAE,EAAE;AAAA,MAC1E;AAAA,IACF;AAGA,UAAM,YAA6C,CAAC;AACpD,QAAI,QAAQ,UAAU;AACpB,gBAAU,KAAK,IAAI;AAAA,QACjB,aAAa;AAAA,QACb,SAAS,EAAE,oBAAoB,EAAE,QAAQ,gBAAgB,OAAO,QAAQ,EAAE,EAAE;AAAA,MAC9E;AAAA,IACF,OAAO;AACL,gBAAU,KAAK,IAAI,EAAE,aAAa,UAAU;AAAA,IAC9C;AAEA,QAAI,MAAM,MAAM,WAAW;AACzB,iBAAW,CAAC,MAAM,GAAG,KAAK,OAAO,QAAQ,MAAM,KAAK,SAAS,GAAG;AAC9D,kBAAU,IAAI,IAAI,EAAE,aAAa,IAAI,YAAY;AAAA,MACnD;AAAA,IACF;AAGA,UAAM,mBAAuB,MAAM,MAAM,WAAe,MAAM,WAAe,aAAa,MAAM,QAAQ,MAAM,IAAI;AAClH,UAAM,uBAAuB,MAAM,MAAM,eAAe,MAAM,eAAe;AAC7E,UAAM,uBAAuB,MAAM,MAAM,eAAe,iBAAiB,MAAM,QAAQ,MAAM,IAAI;AAGjG,UAAM,YAAa,MAAM,SAAS,MAAM;AACxC,UAAM,aAAa,MAAM,KAAK,MAAM,GAAG,EAAE,OAAO,OAAO,EAAE,CAAC,KAAK;AAC/D,UAAM,MAAa,cAAc,aAAa,UAAU;AAGxD,UAAM,gBAAgB,MAAM,SAAS,WAAW,CAAC;AACjD,UAAM,SAAS,cAAc,KAAK,OAAK,EAAE,SAAS,KAAK;AACvD,QAAI,OAAQ,qBAAoB;AAEhC,UAAM,YAA8B,EAAE,UAAU;AAChD,cAAU,cAAc;AACxB,cAAU,UAAc;AACxB,QAAI,qBAAsB,WAAU,cAAc;AAClD,cAAU,OAAc,CAAC,GAAG;AAC5B,QAAI,OAAsB,WAAU,WAAc,CAAC,EAAE,YAAY,CAAC,EAAE,CAAC;AACrE,QAAI,WAAW,SAAS,EAAG,WAAU,aAAa;AAClD,QAAI,YAAuB,WAAU,cAAc;AAEnD,UAAM,WAAW,EAAG,MAAM,IAAI;AAAA,EAChC;AAEA,QAAM,OAAoB,EAAE,SAAS,SAAS,MAAM,MAAM;AAC1D,MAAI,mBAAmB;AACrB,SAAK,aAAa;AAAA,MAChB,iBAAiB;AAAA,QACf,YAAY,EAAE,MAAM,QAAQ,QAAQ,UAAU,cAAc,MAAM;AAAA,MACpE;AAAA,IACF;AAAA,EACF;AACA,SAAO;AACT;;;AFpQA;AACA;;;AGJA;AAcA,IAAM,iBAAyC;AAAA,EAC7C,WAAa;AAAA,EACb,WAAa;AAAA,EACb,UAAa;AAAA,EACb,aAAa;AAAA,EACb,WAAa;AAAA,EACb,YAAa;AAAA,EACb,WAAa;AAAA,EACb,aAAa;AACf;AAEO,SAAS,kBAAkB,MAAsB;AACtD,SAAO,eAAe,IAAI,KAAK;AACjC;AAuBO,IAAM,sBAAN,MAAqD;AAAA,EAC1D,MAAM,QAAQ,UAAkB,QAAkC;AAChE,WAAO;AAAA,EACT;AAAA,EACA,MAAM,QAAQ,UAAiC;AAAA,EAE/C;AACF;AA2DA,SAAS,eAAe,KAAyC;AAE/D,SAAO,OAAO,EAAE,QAAQ,KAAK;AAC/B;AAIA,SAAS,YACP,MACA,YACA,UACA,YACA,OACA,QACA,MACA,SACA,UACA,QACA,SACoB;AACpB,QAAM,MAA0B;AAAA,IAC9B,OAAa;AAAA,IACb,aAAa,kBAAkB,UAAU;AAAA,IACzC,WAAa;AAAA,IACb,aAAa;AAAA,IACb,QAAa;AAAA,IACb,SAAa;AAAA,IACb,OAAa;AAAA,IACb,UAAa;AAAA,IACb,WAAa;AAAA,IACb,SAAa;AAAA,IACb,UAAa;AAAA,IAEb,IACE,SACyC;AACzC,aAAO;AAAA,QACL;AAAA,QAAM;AAAA,QAAY;AAAA,QAAU;AAAA,QAAY;AAAA,QAAO;AAAA,QAAQ;AAAA,QACvD;AAAA,QACA,CAAC,GAAG,UAAU,OAAsC;AAAA,QACpD;AAAA,QACA;AAAA,MACF;AAAA,IACF;AAAA,EACF;AACA,SAAO;AACT;AAEA,SAAS,gBACP,MACA,YACA,MACA,UACwB;AACxB,SAAO;AAAA,IACL,QAAQ,SAAmD;AACzD,aAAO,gBAA2B,MAAM,YAAY,EAAE,GAAG,MAAM,GAAG,QAAQ,GAAG,QAAQ;AAAA,IACvF;AAAA,IAEA,IACE,SAC6C;AAC7C,aAAO;AAAA,QACL;AAAA,QAAM;AAAA,QAAY;AAAA,QAClB,CAAC,GAAG,UAAU,OAAsC;AAAA,MACtD;AAAA,IACF;AAAA,IAEA,QAAQ,IAA4F;AAClG,YAAM,SAAS,oBAAoB,QAAQ,IAAI,IAAI,eAAe,KAAK,GAAG,CAAC;AAC3E,aAAO;AAAA,QACL;AAAA,QAAM;AAAA,QAAY,KAAK;AAAA,QAAU,KAAK,cAAc;AAAA,QACpD,KAAK;AAAA,QAAO;AAAA,QAAQ;AAAA,QAAW;AAAA,QAAI;AAAA,QAAU;AAAA,QAAW,KAAK;AAAA,MAC/D;AAAA,IACF;AAAA,IAEA,GAAG,QAAoC;AACrC,YAAM,SAAS,oBAAoB,QAAQ,IAAI,IAAI,eAAe,KAAK,GAAG,CAAC;AAC3E,aAAO;AAAA,QACL;AAAA,QAAM;AAAA,QAAY,KAAK;AAAA,QAAU,KAAK,cAAc;AAAA,QACpD,KAAK;AAAA,QAAO;AAAA,QAAQ;AAAA,QAAM;AAAA,QAAW;AAAA,QAAU;AAAA,QAAQ,KAAK;AAAA,MAC9D;AAAA,IACF;AAAA,EACF;AACF;AAiBO,SAAS,WACd,MACA,YACA,MACmC;AACnC,SAAO,gBAAsC,MAAM,YAAY,QAAQ,CAAC,GAAG,CAAC,CAAC;AAC/E;;;AC9MA,IAAM,aAAa;AAGnB,IAAM,iBAA4B;AAAA,EAChC,KAAU,MAAM;AAAA,EAChB,KAAU,MAAM;AAAA,EAAC;AAAA,EACjB,QAAU,MAAM;AAAA,EAAC;AAAA,EACjB,UAAU,MAAM,CAAC;AACnB;AAEO,SAAS,gBACd,OACkB;AAClB,QAAMC,QAAgB;AAAA,IACpB,KAAQ,IAAI,QAAQ,UAAU;AAAA,IAC9B,QAAQ,CAAC;AAAA,IACT,OAAQ,CAAC;AAAA,IACT,MAAQ,CAAC,MAAMC,UAAS,QACtB,IAAI,SAAS,KAAK,UAAU,IAAI,GAAG;AAAA,MACjC,QAAAA;AAAA,MACA,SAAS,EAAE,gBAAgB,mBAAmB;AAAA,IAChD,CAAC;AAAA,IACH,MAAQ,CAAC,MAAMA,UAAS,QACtB,IAAI,SAAS,MAAM,EAAE,QAAAA,QAAO,CAAC;AAAA,IAC/B,MAAQ,CAAC,MAAMA,UAAS,QACtB,IAAI,SAAS,MAAM;AAAA,MACjB,QAAAA;AAAA,MACA,SAAS,EAAE,gBAAgB,YAAY;AAAA,IACzC,CAAC;AAAA,IACH,QAAQ;AAAA,IACR,MAAQ,MAAM;AAAA,IAAC;AAAA,IACf,QAAQ,MAAM;AAAE,YAAM,IAAI,MAAM,+CAA+C;AAAA,IAAE;AAAA,IACjF,KAAQ,MAAM;AAAE,YAAM,IAAI,MAAM,4CAA4C;AAAA,IAAE;AAAA,EAChF;AAEA,SAAO,EAAE,GAAGD,OAAM,GAAI,SAAS,CAAC,EAAG;AACrC;;;AJ1CA;AAGA;;;AKbO,SAAS,UAAU,SAAiB,UAAsC;AAE/E,QAAM,cAAe,QAAQ,SAAU,IAAI,QAAQ,QAAQ,OAAO,EAAE,IAAK;AACzE,QAAM,eAAe,SAAS,SAAS,IAAI,SAAS,QAAQ,OAAO,EAAE,IAAI;AAGzE,MAAI,YAAY,SAAS,IAAI,GAAG;AAC9B,UAAM,SAAS,YAAY,MAAM,GAAG,EAAE;AACtC,QAAI,aAAa,WAAW,SAAS,GAAG,GAAG;AACzC,YAAM,OAAO,aAAa,MAAM,OAAO,SAAS,CAAC;AACjD,aAAO,EAAE,QAAQ,EAAE,KAAK,KAAK,EAAE;AAAA,IACjC;AACA,WAAO;AAAA,EACT;AAEA,QAAM,kBAAmB,YAAY,MAAM,GAAG;AAC9C,QAAM,eAAmB,aAAa,MAAM,GAAG;AAE/C,QAAM,SAA6C,CAAC;AAEpD,MAAI,KAAK;AACT,WAAS,IAAI,GAAG,IAAI,gBAAgB,QAAQ,KAAK;AAC/C,UAAM,OAAO,gBAAgB,CAAC;AAE9B,QAAI,KAAK,WAAW,GAAG,KAAK,KAAK,SAAS,GAAG,GAAG;AAE9C,YAAM,YAAY,KAAK,MAAM,GAAG,EAAE;AAClC,UAAI,KAAK,aAAa,QAAQ;AAC5B,eAAO,SAAS,IAAI,aAAa,EAAE;AACnC;AAAA,MACF,OAAO;AACL,eAAO,SAAS,IAAI;AAAA,MACtB;AAAA,IACF,WAAW,KAAK,WAAW,GAAG,GAAG;AAE/B,UAAI,MAAM,aAAa,OAAQ,QAAO;AACtC,aAAO,KAAK,MAAM,CAAC,CAAC,IAAI,aAAa,EAAE;AACvC;AAAA,IACF,OAAO;AAEL,UAAI,MAAM,aAAa,UAAU,aAAa,EAAE,MAAM,KAAM,QAAO;AACnE;AAAA,IACF;AAAA,EACF;AAGA,MAAI,OAAO,aAAa,OAAQ,QAAO;AAEvC,SAAO,EAAE,OAAO;AAClB;AAEO,SAAS,WAAW,QAAmD;AAE5E,QAAM,MAAM,OAAO,WAAW,GAAG,IAAI,OAAO,MAAM,CAAC,IAAI;AACvD,MAAI,CAAC,IAAK,QAAO,CAAC;AAElB,QAAM,SAA4C,CAAC;AACnD,QAAM,SAAS,IAAI,gBAAgB,GAAG;AAEtC,aAAW,OAAO,OAAO,KAAK,GAAG;AAC/B,UAAM,SAAS,OAAO,OAAO,GAAG;AAChC,WAAO,GAAG,IAAI,OAAO,WAAW,IAAI,OAAO,CAAC,IAAK;AAAA,EACnD;AAEA,SAAO;AACT;;;ACjEA;AAiBO,SAAS,gBACd,MACA,SACgC;AAChC,QAAM,EAAE,OAAO,OAAO,IAAI;AAC1B,QAAM,eAAgB,OAAO,UAAU,CAAC;AACxC,QAAM,aAAe,OAAO;AAC5B,QAAM,UAAe,OAAO,YAAY,CAAC,QAAiB,QAAQ,MAAM,yBAAyB,GAAG;AAKpG,QAAM,YAAY,oBAAI,QAAyC;AAE/D,iBAAe,WACb,WACA,OACA,QACA,OACe;AACf,UAAM,MAA+B;AAAA,MACnC,WAAW,MAAM;AAAA,MACjB;AAAA,MACA;AAAA,MACA,QAAW,WAAW,OAAO,KAAK,UAAU,MAAM,IAAI;AAAA,MACtD,OAAW,UAAW,OAAO,KAAK,UAAU,KAAK,IAAK;AAAA,MACtD,YAAW,oBAAI,KAAK,GAAE,YAAY;AAAA,IACpC;AACA,UAAM,EAAE,KAAK,OAAO,IAAI,YAAY,WAAW,MAAM,GAAG;AACxD,UAAM,QAAQ,QAAQ,KAAK,MAAM;AAAA,EACnC;AAEA,SAAO;AAAA,IACL,aAAa,OAAO,KAAK,WAAW;AAClC,UAAI;AACF,cAAM,QAAS,aAAa,SAAS,YAAY,QAAmC,YAAY,IAAI;AACpG,cAAM,QAAS,OAAO,MAAM,GAAW,KAAK;AAC5C,cAAM,WAAW,UAAU,OAAO,MAAM,KAAK;AAAA,MAC/C,SAAS,KAAK;AACZ,gBAAQ,GAAG;AAAA,MACb;AAAA,IACF;AAAA,IAEA,cAAc,OAAO,MAAM,UAAU,UAAU;AAG7C,UAAI,UAAU,QAAQ,OAAO,UAAU,UAAU;AAC/C,kBAAU,IAAI,OAAO,QAAmC;AAAA,MAC1D;AAAA,IACF;AAAA,IAEA,aAAa,OAAO,KAAK,QAAQ,WAAW;AAC1C,UAAI;AACF,cAAM,aAAa,aAAa,SAAS,YAAY,QAAmC,YAAY,IAAI;AACxG,cAAM,YAAa,aAAa,SAAS,YAAY,QAAmC,YAAY,IAAI;AACxG,cAAM,QAAa,OAAO,MAAM,GAAW,KAAK;AAChD,cAAM,WAAW,UAAU,OAAO,YAAY,SAAS;AAAA,MACzD,SAAS,KAAK;AACZ,gBAAQ,GAAG;AAAA,MACb;AAAA,IACF;AAAA,IAEA,aAAa,OAAO,KAAK,YAAY;AACnC,UAAI;AACF,cAAM,SAAS,aAAa,SAAS,YAAY,SAAoC,YAAY,IAAI;AACrG,cAAM,QAAS,OAAO,MAAM,GAAW,KAAK;AAC5C,cAAM,WAAW,UAAU,OAAO,QAAQ,IAAI;AAAA,MAChD,SAAS,KAAK;AACZ,gBAAQ,GAAG;AAAA,MACb;AAAA,IACF;AAAA,EACF;AACF;;;AC5EO,SAAS,gBAAgB,KAAyB;AACvD,QAAM,UAAoB,CAAC;AAE3B,WAAS,eAAuC;AAC9C,UAAM,SAAS,IAAI,QAAQ,IAAI,QAAQ,KAAK;AAC5C,UAAM,SAAiC,CAAC;AACxC,eAAW,QAAQ,OAAO,MAAM,GAAG,GAAG;AACpC,YAAM,UAAU,KAAK,KAAK;AAC1B,YAAM,KAAK,QAAQ,QAAQ,GAAG;AAC9B,UAAI,OAAO,GAAI;AACf,YAAM,OAAQ,QAAQ,MAAM,GAAG,EAAE,EAAE,KAAK;AACxC,YAAM,QAAQ,QAAQ,MAAM,KAAK,CAAC,EAAE,KAAK;AACzC,UAAI,KAAM,QAAO,IAAI,IAAI;AAAA,IAC3B;AACA,WAAO;AAAA,EACT;AAGA,MAAI;AAEJ,SAAO;AAAA,IACL,IAAI,MAAkC;AACpC,UAAI,CAAC,OAAQ,UAAS,aAAa;AACnC,aAAO,OAAO,IAAI;AAAA,IACpB;AAAA,IAEA,IAAI,MAAc,OAAe,UAAyB,CAAC,GAAS;AAClE,YAAM,QAAkB,CAAC,GAAG,mBAAmB,IAAI,CAAC,IAAI,mBAAmB,KAAK,CAAC,EAAE;AACnF,YAAM,KAAK,QAAQ,QAAQ,QAAQ,GAAG,EAAE;AACxC,UAAI,QAAQ,WAAW,OAAW,OAAM,KAAK,WAAW,QAAQ,MAAM,EAAE;AACxE,UAAI,QAAQ,OAAQ,OAAM,KAAK,UAAU,QAAQ,MAAM,EAAE;AACzD,YAAM,gBAAgB,QAAQ,YAAY;AAC1C,YAAM,KAAK,YAAY,aAAa,EAAE;AACtC,UAAI,QAAQ,UAAU,KAAM,OAAM,KAAK,QAAQ;AAC/C,UAAI,QAAQ,YAAY,KAAM,OAAM,KAAK,UAAU;AACnD,cAAQ,KAAK,MAAM,KAAK,IAAI,CAAC;AAAA,IAC/B;AAAA,IAEA,OAAO,MAAoB;AACzB,YAAM,QAAQ;AAAA,QACZ,GAAG,mBAAmB,IAAI,CAAC;AAAA,QAC3B;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,MACF;AACA,cAAQ,KAAK,MAAM,KAAK,IAAI,CAAC;AAAA,IAC/B;AAAA,IAEA,WAAqB;AACnB,aAAO,CAAC,GAAG,OAAO;AAAA,IACpB;AAAA,EACF;AACF;;;AP5CA;AAOA,SAAS,mBACP,QACA,UAAyB,CAAC,GAChB;AACV,QAAM,MAAM,IAAI,YAAY;AAC5B,QAAM,EAAE,UAAU,SAAS,IAAI,IAAI,gBAAwC;AAC3E,QAAM,IAAI,SAAS,UAAU;AAE7B,QAAM,aAA+B;AAAA,IACnC,KAAK,OAA4B;AAC/B,YAAM,QAAQ,OAAO,UAAU,WAAW,IAAI,OAAO,KAAK,IAAI;AAC9D,WAAK,EAAE,MAAM,KAAK;AAAA,IACpB;AAAA,IACA,QAAQ;AACN,WAAK,EAAE,MAAM;AAAA,IACf;AAAA,EACF;AAIA,UAAQ,QAAQ,OAAO,UAAU,CAAC,EAAE,MAAM,MAAM;AAAE,SAAK,EAAE,MAAM;AAAA,EAAE,CAAC;AAElE,QAAM,UAAU,IAAI,QAAQ,QAAQ,OAAO;AAC3C,UAAQ,IAAI,gBAAgB,QAAQ,eAAe,YAAY;AAE/D,SAAO,IAAI,SAAS,UAAU;AAAA,IAC5B,QAAS,QAAQ,UAAU;AAAA,IAC3B;AAAA,EACF,CAAC;AACH;AAaA,SAAS,gBACP,QACU;AACV,QAAM,MAAM,IAAI,YAAY;AAC5B,QAAM,EAAE,UAAU,SAAS,IAAI,IAAI,gBAAwC;AAC3E,QAAM,IAAI,SAAS,UAAU;AAE7B,WAAS,KAAK,OAA8B;AAC1C,WAAO,EAAE,MAAM,IAAI,OAAO,KAAK,CAAC;AAAA,EAClC;AAEA,QAAM,aAA4B;AAAA,IAChC,MAAM,MAAM,MAAc,MAA8B;AACtD,YAAM,KAAK,UAAU,IAAI;AAAA,QAAW,KAAK,UAAU,IAAI,CAAC;AAAA;AAAA,CAAM;AAAA,IAChE;AAAA,IACA,MAAM,KAAK,MAA8B;AACvC,YAAM,KAAK,SAAS,KAAK,UAAU,IAAI,CAAC;AAAA;AAAA,CAAM;AAAA,IAChD;AAAA,IACA,MAAM,QAAQ,OAAO,IAAmB;AACtC,YAAM,KAAK,KAAK,IAAI;AAAA;AAAA,CAAM;AAAA,IAC5B;AAAA,IACA,MAAM,GAAG,SAAgC;AACvC,YAAM,KAAK,OAAO,OAAO;AAAA,CAAI;AAAA,IAC/B;AAAA,IACA,MAAM,MAAM,IAA2B;AACrC,YAAM,KAAK,UAAU,EAAE;AAAA,CAAI;AAAA,IAC7B;AAAA,EACF;AAKA,UAAQ,QAAQ,OAAO,UAAU,CAAC,EAAE,QAAQ,MAAM;AAAE,MAAE,MAAM,EAAE,MAAM,MAAM;AAAA,IAAC,CAAC;AAAA,EAAE,CAAC;AAE/E,SAAO,IAAI,SAAS,UAAU;AAAA,IAC5B,QAAQ;AAAA,IACR,SAAS;AAAA,MACP,gBAAiB;AAAA,MACjB,iBAAiB;AAAA,MACjB,cAAiB;AAAA,IACnB;AAAA,EACF,CAAC;AACH;AAWA,SAAS,iBACP,SAC+F;AAC/F,MAAI,OAAO,YAAY,YAAY;AACjC,WAAO,EAAE,SAAS,EAAE,QAAwB,GAAG,QAAQ,QAAW,MAAM,OAAU;AAAA,EACpF;AAEA,MAAI,YAAY,WAAW,WAAW,WAAW,UAAU,WAAW,cAAc,WAAW,UAAU,SAAS;AAChH,UAAM,IAAI;AACV,WAAO;AAAA,MACL,SAAS,EAAE,SAAS,EAAE,QAAe;AAAA,MACrC,QAAQ;AAAA,QACN,QAAU,EAAE;AAAA,QACZ,OAAU,EAAE;AAAA,QACZ,MAAU,EAAE;AAAA,QACZ,UAAU,EAAE;AAAA,MACd;AAAA,MACA,MAAM,EAAE;AAAA,IACV;AAAA,EACF;AAEA,SAAO,EAAE,SAAwC,QAAQ,QAAW,MAAM,OAAU;AACtF;AAEO,IAAM,OAAN,MAAoH;AAAA,EAIhH,SAAuB,CAAC;AAAA,EAChB,UAA8B,CAAC;AAAA,EAC/B,eAA6B,CAAC;AAAA;AAAA,EAE9B,kBAAwC,CAAC;AAAA,EACzC,uBAAkD,CAAC;AAAA,EACnD,mBAA0C,CAAC;AAAA,EACpD;AAAA,EACS;AAAA;AAAA,EAER;AAAA,EACD,mBAAmB;AAAA;AAAA,EAEV,yBAAyB,oBAAI,IAAY;AAAA;AAAA,EAEzC,4BAAkF,CAAC;AAAA,EAE5F,QAIJ,EAAE,kBAAkB,OAAO,cAAc,MAAM;AAAA;AAAA,EAElC,6BAAoE,CAAC;AAAA;AAAA,EAE9E,0BAA0B;AAAA;AAAA;AAAA;AAAA,EAI1B,cAAc,oBAAI,IAA0F;AAAA,EACnG,mBAAmB;AAAA;AAAA,EAEnB,YAAgD,CAAC;AAAA;AAAA,EAEjD,YAAgD,oBAAI,IAAI;AAAA;AAAA,EAExD;AAAA,EACA;AAAA;AAAA,EAET,aAAmC;AAAA;AAAA,EAEnC,eAAmC;AAAA,EAE3C,YAAY,OAQR,CAAC,GAAG;AACN,SAAK,mBAAmB,KAAK,oBAAoB,CAAC,KAAK,QAAQ,QAAQ,MAAM,KAAK,GAAG;AACrF,SAAK,WAAW,KAAK,YAAY,IAAI,iBAAiB;AACtD,SAAK,YAAY,KAAK,YAAY,IAAI,oBAAoB;AAC1D,SAAK,QAAQ,IAAI,aAAa;AAC9B,SAAK,eAAe,KAAK,QAAQ;AACjC,QAAI,KAAK,YAAY,iBAAiB,QAAW;AAC/C,WAAK,QAAQ,EAAE,GAAG,KAAK,OAAO,cAAc,KAAK,WAAW,aAAa;AAAA,IAC3E;AACA,QAAI,KAAK,OAAO,QAAW;AACzB,WAAK,QAAQ,EAAE,GAAG,KAAK,OAAO,IAAI,KAAK,GAAG;AAAA,IAC5C;AACA,SAAK,qBAAqB,KAAK,KAAK,QAAQ,MAAM;AAAA,EACpD;AAAA;AAAA;AAAA;AAAA,EAKQ,qBAAqB,MAAoB;AAC/C,UAAM,aAAa,KAAK;AACxB,UAAM,iBAAiB,MAAM,KAAK;AAClC,SAAK,OAAO,KAAK;AAAA,MACf,QAAY;AAAA,MACZ;AAAA,MACA,YAAY;AAAA,MACZ,QAAY,CAAC;AAAA,MACb,SAAS;AAAA,QACP,SAAS,CAAC,QAAiB;AACzB,gBAAM,OAAS,IAA2C,MAAM,KAAK;AACrE,gBAAM,MAAiB,CAAC;AACxB,qBAAW,UAAU,YAAY;AAC/B,gBAAI,CAAC,OAAO,OAAO,OAAO,IAAI,WAAW,EAAG;AAG5C,gBAAI,OAAO,eAAe,OAAO,YAAY,SAAS,GAAG;AACvD,kBAAI,QAAQ,KAAM;AAClB,oBAAM,UAAU,eAAe;AAC/B,oBAAM,SAAS,UACX,OAAO,YAAY,KAAK,CAAC,SAAS,QAAQ,cAAc,MAAM,IAAI,CAAC,IACnE;AACJ,kBAAI,CAAC,OAAQ;AAAA,YACf;AACA,gBAAI,KAAK,GAAG,OAAO,GAAG;AAAA,UACxB;AAEA,cAAI,KAAK,CAAC,GAAG,MAAM;AACjB,kBAAM,aAAa,EAAE,SAAS,MAAM,EAAE,SAAS;AAC/C,mBAAO,cAAc,IAAI,YAAY,EAAE,MAAM,cAAc,EAAE,KAAK;AAAA,UACpE,CAAC;AACD,iBAAO,IAAI,KAAK,EAAE,IAAI,CAAC;AAAA,QACzB;AAAA,MACF;AAAA,IACF,CAAC;AAAA,EACH;AAAA,EAEQ,UACN,QACA,MACA,SACA,QACM;AACN,UAAM,EAAE,SAAS,YAAY,QAAQ,KAAK,IAAI,iBAAiB,OAAO;AACtE,SAAK,OAAO,KAAK;AAAA,MACf;AAAA,MACA;AAAA,MACA,SAAS;AAAA,MACT,QAAQ,CAAC;AAAA,MACT;AAAA,MACA;AAAA,MACA,SAAS;AAAA,IACX,CAAC;AACD,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA,EAMQ,gBACN,QACA,MACA,iBACA,SACiC;AACjC,WAAO,UACH,KAAK,UAAU,QAAQ,MAAM,EAAE,GAAG,iBAAgC,QAAQ,CAA8C,IACxH,KAAK,UAAU,QAAQ,MAAM,eAAmC;AAAA,EACtE;AAAA,EAcA,IAAI,MAAc,iBAA2H,SAAyF;AACpO,WAAO,KAAK,gBAAgB,OAAO,MAAM,iBAAiB,OAAO;AAAA,EACnE;AAAA,EAcA,KAAK,MAAc,iBAA2H,SAAyF;AACrO,WAAO,KAAK,gBAAgB,QAAQ,MAAM,iBAAiB,OAAO;AAAA,EACpE;AAAA,EAcA,IAAI,MAAc,iBAA2H,SAAyF;AACpO,WAAO,KAAK,gBAAgB,OAAO,MAAM,iBAAiB,OAAO;AAAA,EACnE;AAAA,EAcA,MAAM,MAAc,iBAA2H,SAAyF;AACtO,WAAO,KAAK,gBAAgB,SAAS,MAAM,iBAAiB,OAAO;AAAA,EACrE;AAAA,EAcA,OAAO,MAAc,iBAA2H,SAAyF;AACvO,WAAO,KAAK,gBAAgB,UAAU,MAAM,iBAAiB,OAAO;AAAA,EACtE;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,kBAAkB,SAA8B;AAC9C,SAAK,aAAa;AAClB,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUA,GAAG,MAAc,OAA2B;AAC1C,QAAI,CAAC,KAAK,YAAY;AACpB,YAAM,IAAI;AAAA,QACR,WAAW,IAAI;AAAA,QACf;AAAA,QAAK;AAAA,MACP;AAAA,IACF;AACA,SAAK,WAAW,cAAc,MAAM,EAAE,GAAG,OAAO,MAAM,SAAS,KAAK,CAAC;AACrE,WAAO;AAAA,EACT;AAAA,EAGA,OAA4B,GAA8D;AAGxF,QAAI,EAAE,YAAY,EAAE,SAAS,SAAS,GAAG;AACvC,YAAM,aAAa,IAAI,IAAI,KAAK,QAAQ,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC;AAC1D,iBAAW,OAAO,EAAE,UAAU;AAC5B,YAAI,CAAC,WAAW,IAAI,GAAG,GAAG;AACxB,gBAAM,IAAI;AAAA,YACR,WAAW,EAAE,IAAI,sBAAsB,GAAG,6CACvB,GAAG,kCAAkC,EAAE,IAAI;AAAA,YAC9D;AAAA,YACA;AAAA,UACF;AAAA,QACF;AAAA,MACF;AAAA,IACF;AACA,SAAK,QAAQ,KAAK,CAAC;AACnB,QAAI,EAAE,SAAS;AACb,iBAAW,OAAO,EAAE,SAAS;AAC3B,aAAK,SAAS,GAAG;AAGjB,YAAI,EAAE,eAAe,EAAE,YAAY,SAAS,GAAG;AAC7C,qBAAW,SAAS,KAAK,QAAQ;AAC/B,gBAAI,MAAM,YAAY,OAAO,MAAM,gBAAgB,QAAW;AAC5D,oBAAM,cAAc,EAAE;AAAA,YACxB;AAAA,UACF;AAAA,QACF;AAAA,MACF;AAAA,IACF;AACA,WAAO;AAAA,EACT;AAAA,EASA,IACE,qBAC4D;AAC5D,QAAI,iBAAiB,qBAAqB;AACxC,WAAK,2BAA2B,KAAK,EAAE,SAAS,oBAAmD,CAAC;AACpG,aAAO;AAAA,IACT;AAEA,UAAM,IAAI;AACV,QAAI,EAAE,WAAa,MAAK,gBAAgB,KAAK,gBAAgB,EAAE,UAAU,CAAC;AAC1E,QAAI,EAAE,YAAa,MAAK,iBAAiB,KAAK,iBAAiB,EAAE,WAAW,CAAC;AAC7E,WAAO;AAAA,EACT;AAAA,EAMA,SAAS,QAAwE;AAE/E,eAAW,QAAQ,OAAO,kBAAkB;AAC1C,WAAK,MAAM,mBAAmB,KAAK,MAAM,MAAM,KAAK,QAAQ;AAAA,IAC9D;AAGA,eAAW,QAAQ,OAAO,mBAAmB;AAC3C,WAAK,0BAA0B,KAAK,IAAI;AAAA,IAC1C;AAGA,eAAW,SAAS,OAAO,QAAQ;AACjC,WAAK,OAAO,KAAK;AAAA,QACf,GAAG;AAAA,QACH,MAAM,OAAO,SAAS,MAAM;AAAA,QAC5B,SAAS;AAAA,MACX,CAAC;AAAA,IACH;AAGA,QAAI,KAAK,cAAc,OAAO,SAAS,SAAS,GAAG;AACjD,iBAAW,WAAW,OAAO,UAAU;AACrC,cAAM,WAAW,OAAO,SAAS,QAAQ;AACzC,aAAK,WAAW,cAAc,UAAU,EAAE,GAAG,SAAS,MAAM,UAAU,SAAS,OAAO,CAAC;AAAA,MACzF;AAAA,IACF;AAGA,eAAW,OAAO,OAAO,kBAAkB;AACzC,WAAK,OAAO,GAAG;AAAA,IACjB;AAIA,eAAW,WAAW,OAAO,UAAU;AAErC,YAAM,eAAe,IAAI,IAAI,QAAQ,UAAU,IAAI,CAAC,MAAM,EAAE,WAAW,CAAC;AACxE,YAAM,SAAS;AAAA,QACb,GAAG,QAAQ;AAAA,QACX,GAAG,OAAO,oBACP,IAAI,CAAC,MAAM,EAAE,OAAO,EACpB,OAAO,CAAC,MAAM,CAAC,aAAa,IAAI,EAAE,WAAW,CAAC;AAAA,MACnD;AACA,YAAM,YAA8C;AAAA,QAClD,GAAG;AAAA,QACH,WAAW;AAAA,QACX,KAAK,QAAQ,IAAI,KAAK,OAAO;AAAA,MAC/B;AACA,WAAK,UAAU,KAAK,SAAS;AAAA,IAC/B;AAGA,SAAK,YAAY,MAAM;AAEvB,WAAO;AAAA,EACT;AAAA;AAAA,EAGQ,iBAAiB,KAA4E;AACnG,QAAI,QAAQ,KAAM,QAAO,KAAK;AAE9B,UAAM,OAAO,oBAAI,IAAY;AAC7B,UAAM,SAAgD,CAAC;AACvD,eAAW,KAAK,CAAC,GAAG,IAAI,qBAAqB,GAAG,KAAK,0BAA0B,GAAG;AAChF,UAAI,CAAC,KAAK,IAAI,EAAE,QAAQ,WAAW,GAAG;AACpC,aAAK,IAAI,EAAE,QAAQ,WAAW;AAC9B,eAAO,KAAK,CAAC;AAAA,MACf;AAAA,IACF;AACA,WAAO;AAAA,EACT;AAAA,EASA,GAAG,OAAe,SAA6B;AAC7C,SAAK,SAAS,GAAG,OAAO,CAAC,YAAY,QAAQ,SAAS,MAAS,CAAC;AAChE,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,QAIE,OACA,OACA,SACM;AACN,SAAK,SAAS,GAAG,OAAiB,CAAC,YAAa,QAAyB,SAAS,MAAS,CAAC;AAC5F,WAAO;AAAA,EACT;AAAA,EAEA,OAAO,KAA4B;AACjC,UAAM,SAAW,IAAI;AACrB,UAAM,cAAc,IAAI,UAAU,SAAS;AAE3C,QAAI,aAAa;AAEf,iBAAW,CAAC,OAAO,UAAU,KAAK,IAAI,cAAc;AAClD,aAAK,SAAS,GAAG,OAAO,OAAO,YAAY;AACzC,cAAI;AACF,kBAAM,UAAU,KAAK,MAAM,WAAW;AACtC,kBAAM,MAA+B,EAAE,OAAO;AAC9C,gBAAI,SAAS;AACX,oBAAM,SAAS,gBAAgB,EAAE,MAAM,QAAQ,CAAC;AAChD,oBAAM,SAAS,IAAI,OAAO,SAAS,KAAK,KAAK;AAC7C,oBAAM,UAAU,OAAO,QAAQ,MAAM;AACrC,oBAAM,WAAW,oBAAoB,IAAI,WAAW,OAAO;AAC3D,qBAAO,OAAO,KAAK,QAAQ;AAAA,YAC7B;AACA,kBAAM,WAAW,SAAS,GAAG;AAAA,UAC/B,SAAS,KAAK;AACZ,mBAAO,MAAM,iBAAiB,EAAE,OAAO,IAAI,CAAC;AAAA,UAC9C;AAAA,QACF,CAAC;AAAA,MACH;AAAA,IACF,OAAO;AAEL,iBAAW,CAAC,OAAO,QAAQ,KAAK,IAAI,WAAW;AAC7C,aAAK,SAAS,GAAG,OAAO,OAAO,YAAY;AACzC,cAAI;AACF,kBAAM,SAAS,OAAO;AAAA,UACxB,SAAS,KAAK;AACZ,mBAAO,MAAM,iBAAiB,EAAE,OAAO,IAAI,CAAC;AAAA,UAC9C;AAAA,QACF,CAAC;AAAA,MACH;AAAA,IACF;AACA,WAAO;AAAA,EACT;AAAA,EAEA,KAAgD,KAA+B;AAC7E,SAAK,UAAU,KAAK,GAAuC;AAC3D,WAAO;AAAA,EACT;AAAA,EAEA,QAAQ,SAAmC;AACzC,SAAK,gBAAgB;AACrB,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA,EAMA,UAAU,MAAiC;AACzC,SAAK,gBAAgB,KAAK,IAA0B;AACpD,WAAO;AAAA,EACT;AAAA,EAEA,eAAe,MAAsC;AACnD,SAAK,qBAAqB,KAAK,IAA+B;AAC9D,WAAO;AAAA,EACT;AAAA,EAEA,WAAW,MAAkC;AAC3C,SAAK,iBAAiB,KAAK,IAA2B;AACtD,WAAO;AAAA,EACT;AAAA,EAEA,MAAM,MAAM,KAAc,QAA2D;AAkBnF,QAAI,CAAC,KAAK,kBAAkB;AAC1B,WAAK,mBAAmB;AACxB,iBAAW,UAAU,KAAK,SAAS;AACjC,YAAI,OAAO,SAAS;AAClB,gBAAM,OAAO,QAAQ,KAAK,KAAK;AAAA,QACjC;AAAA,MACF;AAIA,UAAI,KAAK,0BAA0B,SAAS,GAAG;AAC7C,cAAM,UAAU,KAAK,MAAM,WAAW;AACtC,YAAI,CAAC,SAAS;AACZ,gBAAM,IAAI;AAAA,YACR;AAAA,UAEF;AAAA,QACF;AACA,mBAAW,QAAQ,KAAK,2BAA2B;AACjD,gBAAM,WAAW,gBAAgB,MAAM,OAAO;AAC9C,eAAK,MAAM,mBAAmB,KAAK,MAAM,MAAM,QAAQ;AAAA,QACzD;AACA,aAAK,0BAA0B,SAAS;AAAA,MAC1C;AAAA,IACF;AAGA,UAAM,MAAM,IAAI,IAAI,IAAI,GAAG;AAC3B,UAAM,WAAW,IAAI;AACrB,UAAM,SAAS,IAAI,OAAO,YAAY;AAKtC,UAAM,eAAe,IAAI,kBAAkB;AAI3C,UAAM,WAAW,KAAK,MAAM,IAAI;AAChC,UAAM,WAAuD,UAAU,UACnE;AAAA,MACE,SAAY;AAAA,MACZ,SAAY;AAAA,MACZ,SAAY,CAAC;AAAA,MACb,WAAY,SAAS,eAAe;AAAA,MACpC,YAAY,SAAS,cAAc;AAAA,IACrC,IACA;AAKJ,UAAM,UAAmB;AAAA,MACvB;AAAA,MACA,QAAQ,CAAC;AAAA,MACT,OAAO,WAAW,IAAI,MAAM;AAAA,MAC5B,MAAM,CAAI,MAASE,UAAS,QAAQ,SAAS,KAAK,MAAM,EAAE,QAAAA,QAAO,CAAC;AAAA,MAClE,MAAM,CAAC,MAAcA,UAAS,QAAQ,IAAI,SAAS,MAAM,EAAE,QAAAA,SAAQ,SAAS,EAAE,gBAAgB,aAAa,EAAE,CAAC;AAAA,MAC9G,MAAM,CAAC,MAAcA,UAAS,QAAQ,IAAI,SAAS,MAAM,EAAE,QAAAA,SAAQ,SAAS,EAAE,gBAAgB,YAAY,EAAE,CAAC;AAAA,MAC7G,QAAQ;AAAA,MACR,KAAQ;AAAA,MACR,QAAQ,gBAAgB,GAAG;AAAA,MAC3B,MAAM,CAAC,OAAO,YAAY;AAAE,qBAAa,QAAQ,OAAiB,OAAO;AAAA,MAAE;AAAA,MAC3E,eAAe;AAAA,MACf,WAAW;AAAA,IACb;AAOA,QAAI,KAAK,cAAc;AACrB,UAAI,eAAkD;AACtD,UAAI;AACF,uBAAe,MAAM,KAAK,aAAa,QAAQ,OAAO;AAAA,MACxD,QAAQ;AACN,uBAAe;AAAA,MACjB;AACA,aAAO,OAAO,SAAS,EAAE,MAAM,aAAa,CAAC;AAAA,IAC/C,OAAO;AACL,aAAO,OAAO,SAAS,EAAE,MAAM,KAAK,CAAC;AAAA,IACvC;AAKA,eAAW,QAAQ,KAAK,iBAAiB;AACvC,UAAI;AACJ,UAAI;AACF,mBAAW,MAAM,KAAK,IAAI,OAAO;AAAA,MACnC,QAAQ;AACN,mBAAW;AAAA,MACb;AACA,UAAI,oBAAoB,UAAU;AAChC,eAAO,KAAK,eAAe,SAAS,UAAU,IAAI;AAAA,MACpD;AAAA,IACF;AAKA,QAAI,UAAU,KAAK,cAAc,IAAI,QAAQ,IAAI,SAAS,GAAG,YAAY,MAAM,aAAa;AAC1F,YAAM,eAAe,EAAE,OAAO,KAAK,iBAAiB;AACpD,YAAM,kBAAkB,MAAM,KAAK,WAAW;AAAA,QAC5C;AAAA,QACA;AAAA,QACA;AAAA,QACA,KAAK;AAAA,QACL;AAAA,QACA,KAAK;AAAA,MACP;AACA,WAAK,mBAAmB,aAAa;AACrC,UAAI,oBAAoB,KAAM,QAAO;AACrC,aAAO;AAAA,IACT;AAIA,QAAI,eAAkC;AACtC,QAAI,gBAAoD,CAAC;AACzD,UAAM,iBAAiB,oBAAI,IAAY;AAEvC,UAAM,WAAW,GAAG,MAAM,IAAI,QAAQ;AACtC,UAAM,SAAS,KAAK,YAAY,IAAI,QAAQ;AAC5C,QAAI,WAAW,QAAW;AAExB,UAAI,WAAW,MAAM;AACnB,uBAAe,OAAO;AACtB,wBAAgB,OAAO;AACvB,uBAAe,IAAI,OAAO,MAAM,MAAM;AAAA,MACxC;AAAA,IACF,OAAO;AAEL,iBAAW,SAAS,KAAK,QAAQ;AAC/B,cAAM,SAAS,UAAU,MAAM,MAAM,QAAQ;AAC7C,YAAI,WAAW,KAAM;AACrB,uBAAe,IAAI,MAAM,MAAM;AAC/B,YAAI,MAAM,WAAW,QAAQ;AAC3B,yBAAe;AACf,0BAAgB,OAAO;AACvB;AAAA,QACF;AAAA,MACF;AAEA,UAAI,KAAK,YAAY,QAAQ,KAAK,kBAAkB;AAClD,aAAK,YAAY,OAAO,KAAK,YAAY,KAAK,EAAE,KAAK,EAAE,KAAM;AAAA,MAC/D;AACA,WAAK,YAAY,IAAI,UAAU,eAAe,EAAE,OAAO,cAAc,QAAQ,cAAc,IAAI,IAAI;AAAA,IACrG;AAEA,QAAI,iBAAiB,MAAM;AACzB,UAAI,eAAe,OAAO,GAAG;AAE3B,cAAM,QAAQ,CAAC,GAAG,cAAc,EAAE,KAAK,IAAI;AAC3C,eAAO,KAAK;AAAA,UACV;AAAA,UACA,IAAI,SAAS,sBAAsB,EAAE,QAAQ,KAAK,SAAS,EAAE,OAAO,MAAM,EAAE,CAAC;AAAA,UAC7E;AAAA,QACF;AAAA,MACF;AACA,aAAO,KAAK,eAAe,SAAS,IAAI,SAAS,aAAa,EAAE,QAAQ,IAAI,CAAC,GAAG,IAAI;AAAA,IACtF;AAGA,UAAM,gBAAwC,CAAC;AAC/C,eAAW,CAAC,GAAG,CAAC,KAAK,OAAO,QAAQ,aAAa,GAAG;AAClD,UAAI,MAAM,OAAW,eAAc,CAAC,IAAI;AAAA,IAC1C;AAEA,WAAO,KAAK,UAAU,SAAS,cAAc,eAAe,YAAY;AAAA,EAC1E;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAYA,MAAc,UACZ,SACA,cACA,QACA,cACmB;AACnB,YAAQ,SAAS;AAEjB,UAAM,MAAM,aAAa,WAAW;AAGpC,UAAM,aAAa,MAAM,KAAK,mBAAmB,SAAS,cAAc,GAAG;AAC3E,QAAI,WAAY,QAAO;AAGvB,UAAM,kBAAkB,MAAM,KAAK,oBAAoB,SAAS,cAAc,GAAG;AACjF,QAAI,gBAAiB,QAAO;AAG5B,UAAM,MAAM,MAAM,KAAK,YAAY,SAAS,cAAc,GAAG;AAC7D,QAAI,eAAe,SAAU,QAAO;AAGpC,UAAM,mBAAmB,MAAM,KAAK,eAAe,KAAK,cAAc,GAAG;AACzE,QAAI,iBAAkB,QAAO;AAG7B,UAAM,KAAK,aAAa,KAAK,GAAG;AAGhC,UAAM,cAAc,MAAM,KAAK,WAAW,KAAK,cAAc,GAAG;AAChE,QAAI,YAAa,QAAO;AAGxB,UAAM,qBAAqB,MAAM,KAAK,iBAAiB,KAAK,cAAc,GAAG;AAC7E,QAAI,mBAAoB,QAAO;AAG/B,WAAO,KAAK,YAAY,SAAS,KAAK,cAAc,KAAK,YAAY;AAAA,EACvE;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,MAAc,mBACZ,SACA,cACA,KAC0B;AAC1B,QAAI,aAAa,gBAAgB,OAAW,QAAO;AAEnD,UAAM,WAAW,aAAa;AAC9B,UAAM,aAAa,KAAK,QAAQ,KAAK,CAAC,MAAM,EAAE,SAAS,QAAQ;AAC/D,QAAI,CAAC,YAAY,eAAe,WAAW,YAAY,WAAW,EAAG,QAAO;AAG5E,UAAM,OAAQ,QAA+C,MAAM;AACnE,QAAI,QAAQ,MAAM;AAChB,aAAO,KAAK;AAAA,QACV;AAAA,QACA,MAAM,KAAK,aAAa,IAAI,kBAAkB,yBAAyB,GAAG,SAAS,YAAY;AAAA,QAC/F;AAAA,MACF;AAAA,IACF;AACA,UAAM,UAAU,KAAK;AACrB,UAAM,SAAS,UACX,WAAW,YAAY,KAAK,CAAC,SAAS,QAAQ,cAAc,MAAM,IAAI,CAAC,IACvE;AACJ,QAAI,CAAC,QAAQ;AACX,aAAO,KAAK;AAAA,QACV;AAAA,QACA,MAAM,KAAK,aAAa,IAAI,eAAe,0BAA0B,GAAG,SAAS,YAAY;AAAA,QAC7F;AAAA,MACF;AAAA,IACF;AACA,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA,EAKA,MAAc,oBACZ,SACA,cACA,KAC0B;AAC1B,QAAI,CAAC,IAAK,QAAO;AACjB,eAAW,QAAQ,IAAI,gBAAgB;AACrC,UAAI;AACJ,UAAI;AACF,mBAAW,MAAM,KAAK,IAAI,OAAO;AAAA,MACnC,QAAQ;AACN,mBAAW;AAAA,MACb;AACA,UAAI,oBAAoB,UAAU;AAChC,eAAO,KAAK,eAAe,SAAS,UAAU,GAAG;AAAA,MACnD;AAAA,IACF;AACA,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA,EAKA,MAAc,YACZ,SACA,cACA,KAC6B;AAC7B,QAAI,MAAe;AACnB,QAAI;AAKF,iBAAW,UAAU,KAAK,SAAS;AACjC,eAAO,OAAO,KAAK,MAAM,OAAO,QAAQ,GAAG,CAAC;AAAA,MAC9C;AAEA,UAAI,KAAK;AACP,mBAAW,UAAU,IAAI,SAAS;AAehC,cAAI,OAAO,WAAW,CAAC,KAAK,uBAAuB,IAAI,OAAO,IAAI,GAAG;AACnE,iBAAK,uBAAuB,IAAI,OAAO,IAAI;AAC3C,kBAAM,OAAO,QAAQ,KAAK,KAAK;AAAA,UACjC;AACA,iBAAO,OAAO,KAAK,MAAM,OAAO,QAAQ,GAAG,CAAC;AAAA,QAC9C;AAGA,YAAI,IAAI,SAAS,OAAO,CAAC,IAAI,QAAQ;AACnC,gBAAM,MAAM,IAAI,OAAO,MAAM,GAAG,EAAE,OAAO,OAAO,EAAE,IAAI,KAAK;AAC3D,cAAI,SAAS,oBAAoB,UAAU,GAAG,IAAI,IAAI,QAAQ,GAAG;AAAA,QACnE;AAAA,MACF;AAAA,IACF,SAAS,KAAK;AACZ,YAAM,SAAS,MAAM,KAAK,aAAa,KAAK,KAAK,YAAY;AAC7D,aAAO,KAAK,eAAe,KAAK,QAAQ,GAAG;AAAA,IAC7C;AACA,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA,EAKA,MAAc,eACZ,KACA,cACA,KAC0B;AAC1B,QAAI,CAAC,aAAa,OAAQ,QAAO;AACjC,UAAM,SAAS,aAAa;AAE5B,QAAI,OAAO,QAAQ;AACjB,YAAM,SAAS,OAAO,OAAO,UAAU,IAAI,MAAM;AACjD,UAAI,CAAC,OAAO,SAAS;AACnB,cAAM,SAAS,MAAM,KAAK,aAAa,IAAI,gBAAgB,OAAO,KAAK,GAAG,KAAK,YAAY;AAC3F,eAAO,KAAK,eAAe,KAAK,QAAQ,GAAG;AAAA,MAC7C;AACA,UAAI,SAAS,OAAO;AAAA,IACtB;AAEA,QAAI,OAAO,OAAO;AAChB,YAAM,SAAS,OAAO,MAAM,UAAU,IAAI,KAAK;AAC/C,UAAI,CAAC,OAAO,SAAS;AACnB,cAAM,SAAS,MAAM,KAAK,aAAa,IAAI,gBAAgB,OAAO,KAAK,GAAG,KAAK,YAAY;AAC3F,eAAO,KAAK,eAAe,KAAK,QAAQ,GAAG;AAAA,MAC7C;AACA,UAAI,QAAQ,OAAO;AAAA,IACrB;AAEA,QAAI,OAAO,MAAM;AACf,UAAI,MAAe;AACnB,UAAI;AACF,cAAM,MAAM,IAAI,IAAI,KAAK;AAAA,MAC3B,QAAQ;AAAA,MAER;AACA,YAAM,SAAS,OAAO,KAAK,UAAU,GAAG;AACxC,UAAI,CAAC,OAAO,SAAS;AACnB,cAAM,SAAS,MAAM,KAAK,aAAa,IAAI,gBAAgB,OAAO,KAAK,GAAG,KAAK,YAAY;AAC3F,eAAO,KAAK,eAAe,KAAK,QAAQ,GAAG;AAAA,MAC7C;AACA,UAAI,OAAO,OAAO;AAAA,IACpB;AAEA,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA,EAKA,MAAc,aACZ,KACA,KACe;AACf,UAAM,eAAe,KAAK,iBAAiB,GAAG;AAC9C,QAAI,aAAa,WAAW,EAAG;AAG/B,QAAI,CAAC,KAAK,yBAAyB;AACjC,WAAK,0BAA0B;AAC/B,qBAAe,aAAa,IAAI,CAAC,MAAM,EAAE,OAAO,CAAC;AAAA,IACnD;AAEA,QAAI,CAAC,IAAI,IAAI;AACX,YAAM,IAAI;AAAA,QACR;AAAA,MAEF;AAAA,IACF;AACA,UAAM,mBAAmB;AAAA,MACvB,aAAa,IAAI,CAAC,MAAM,EAAE,OAAO;AAAA,MACjC,IAAI;AAAA,IACN;AACA,eAAW,CAAC,KAAK,IAAI,KAAK,OAAO,QAAQ,gBAAgB,GAAG;AAC1D,MAAC,IAA2C,GAAG,IAAI;AAAA,IACrD;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,MAAc,WACZ,KACA,cACA,KAC0B;AAE1B,eAAW,SAAS,KAAK,cAAc;AACrC,UAAI;AACJ,UAAI;AACF,sBAAc,MAAM,MAAM,GAAG;AAAA,MAC/B,SAAS,KAAK;AACZ,cAAM,SAAS,MAAM,KAAK,aAAa,KAAK,KAAK,YAAY;AAC7D,eAAO,KAAK,eAAe,KAAK,QAAQ,GAAG;AAAA,MAC7C;AACA,UAAI,gBAAgB,MAAM;AACxB,eAAO,KAAK,eAAe,KAAK,aAAa,GAAG;AAAA,MAClD;AAAA,IACF;AAGA,QAAI,OAAO,CAAC,aAAa,mBAAmB;AAC1C,iBAAW,SAAS,IAAI,QAAQ;AAC9B,YAAI;AACJ,YAAI;AACF,wBAAc,MAAM,MAAM,GAAG;AAAA,QAC/B,SAAS,KAAK;AACZ,gBAAM,SAAS,MAAM,KAAK,aAAa,KAAK,KAAK,YAAY;AAC7D,iBAAO,KAAK,eAAe,KAAK,QAAQ,GAAG;AAAA,QAC7C;AACA,YAAI,gBAAgB,MAAM;AACxB,iBAAO,KAAK,eAAe,KAAK,aAAa,GAAG;AAAA,QAClD;AAAA,MACF;AAAA,IACF;AAGA,eAAW,SAAS,aAAa,QAAQ;AACvC,UAAI;AACJ,UAAI;AACF,sBAAc,MAAM,MAAM,GAAG;AAAA,MAC/B,SAAS,KAAK;AACZ,cAAM,SAAS,MAAM,KAAK,aAAa,KAAK,KAAK,YAAY;AAC7D,eAAO,KAAK,eAAe,KAAK,QAAQ,GAAG;AAAA,MAC7C;AACA,UAAI,gBAAgB,MAAM;AACxB,eAAO,KAAK,eAAe,KAAK,aAAa,GAAG;AAAA,MAClD;AAAA,IACF;AAEA,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA,EAKA,MAAc,iBACZ,KACA,cACA,KAC0B;AAE1B,eAAW,QAAQ,KAAK,sBAAsB;AAC5C,UAAI;AACJ,UAAI;AACF,mBAAW,MAAM,KAAK,IAAI,GAAG;AAAA,MAC/B,SAAS,KAAK;AACZ,cAAM,SAAS,MAAM,KAAK,aAAa,KAAK,KAAK,YAAY;AAC7D,eAAO,KAAK,eAAe,KAAK,QAAQ,GAAG;AAAA,MAC7C;AACA,UAAI,oBAAoB,UAAU;AAChC,eAAO,KAAK,eAAe,KAAK,UAAU,GAAG;AAAA,MAC/C;AAAA,IACF;AAGA,QAAI,KAAK;AACP,iBAAW,QAAQ,IAAI,qBAAqB;AAC1C,YAAI;AACJ,YAAI;AACF,qBAAW,MAAM,KAAK,IAAI,GAAG;AAAA,QAC/B,SAAS,KAAK;AACZ,gBAAM,SAAS,MAAM,KAAK,aAAa,KAAK,KAAK,YAAY;AAC7D,iBAAO,KAAK,eAAe,KAAK,QAAQ,GAAG;AAAA,QAC7C;AACA,YAAI,oBAAoB,UAAU;AAChC,iBAAO,KAAK,eAAe,KAAK,UAAU,GAAG;AAAA,QAC/C;AAAA,MACF;AAAA,IACF;AAEA,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA,EAKA,MAAc,YACZ,SACA,KACA,cACA,KACA,cACmB;AAEnB,QAAI;AACJ,QAAI;AACF,iBAAW,MAAM,aAAa,QAAQ,QAAQ,GAAG;AAAA,IACnD,SAAS,KAAK;AACZ,YAAM,SAAS,MAAM,KAAK,aAAa,KAAK,KAAK,YAAY;AAE7D,aAAO,KAAK,eAAe,SAAS,QAAQ,KAAK,MAAS;AAAA,IAC5D;AAKA,UAAM,iBAAiB,KAAK,MAAM,oBAC7B,aAAa,QAAQ,YAAY,QACjC,SAAS,QAAQ,IAAI,cAAc,GAAG,SAAS,kBAAkB,MAAM,QACvE,SAAS,WAAW,OACpB,SAAS,SAAS;AACvB,QAAI,gBAAgB;AAClB,UAAI;AACF,cAAM,OAAgB,MAAM,SAAS,MAAM,EAAE,KAAK;AAClD,cAAM,SAAS,aAAa,OAAQ,SAAU,UAAU,IAAI;AAC5D,YAAI,CAAC,OAAO,SAAS;AACnB,eAAK,iBAAiB,sCAAsC,OAAO,MAAM,MAAM;AAC/E,gBAAM,SAAS,IAAI,SAAS,yBAAyB,EAAE,QAAQ,IAAI,CAAC;AACpE,iBAAO,KAAK,eAAe,SAAS,QAAQ,KAAK,MAAS;AAAA,QAC5D;AAAA,MACF,QAAQ;AAAA,MAER;AAAA,IACF;AAGA,WAAO,KAAK,eAAe,SAAS,UAAU,KAAK,YAAY;AAAA,EACjE;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,MAAc,eAAe,KAAc,UAAoB,QAA4B,YAAmD;AAC5I,QAAI,UAAU;AAGd,eAAW,QAAQ,KAAK,kBAAkB;AACxC,UAAI,SAA0B;AAC9B,UAAI;AACF,iBAAS,MAAM,KAAK,IAAI,KAAK,OAAO;AAAA,MACtC,QAAQ;AAAA,MAER;AACA,UAAI,kBAAkB,UAAU;AAC9B,kBAAU;AAAA,MACZ;AAAA,IACF;AAGA,QAAI,QAAQ;AACV,iBAAW,QAAQ,OAAO,iBAAiB;AACzC,YAAI,SAA0B;AAC9B,YAAI;AACF,mBAAS,MAAM,KAAK,IAAI,KAAK,OAAO;AAAA,QACtC,QAAQ;AAAA,QAER;AACA,YAAI,kBAAkB,UAAU;AAC9B,oBAAU;AAAA,QACZ;AAAA,MACF;AAAA,IACF;AAIA,UAAM,WAAW,IAAI;AACrB,QAAI,YAAY,SAAS,UAAU,SAAS,WAAW;AACrD,YAAM,MAAS,IAAI,IAAI,IAAI,IAAI,GAAG;AAClC,YAAM,SAAS,IAAI,IAAI,OAAO,YAAY;AAC1C,cAAQ;AAAA,QACN,YAAY,SAAS,OAAO,eAAe,MAAM,IAAI,IAAI,QAAQ,sBAAiB,SAAS,SAAS;AAAA,MACtG;AACA,UAAI,SAAS,YAAY;AACvB,mBAAW,SAAS,SAAS,SAAS;AACpC,kBAAQ,KAAK,KAAK,MAAM,GAAG,KAAK,MAAM,WAAW,QAAQ,CAAC,CAAC,KAAK;AAAA,QAClE;AAAA,MACF;AAAA,IACF;AAIA,QAAI,YAAY;AACd,YAAM,WAAW,MAAM,KAAK,KAAK,QAAQ;AAAA,IAC3C;AAGA,UAAM,iBAAiB,IAAI,OAAO,SAAS;AAC3C,QAAI,eAAe,SAAS,GAAG;AAC7B,YAAM,UAAU,IAAI,QAAQ,QAAQ,OAAO;AAC3C,iBAAW,KAAK,gBAAgB;AAC9B,gBAAQ,OAAO,cAAc,CAAC;AAAA,MAChC;AACA,gBAAU,IAAI,SAAS,QAAQ,MAAM;AAAA,QACnC,QAAQ,QAAQ;AAAA,QAChB,YAAY,QAAQ;AAAA,QACpB;AAAA,MACF,CAAC;AAAA,IACH;AAEA,WAAO;AAAA,EACT;AAAA,EAEQ,aAAa,KAAc,KAAU,OAAiD;AAE5F,QAAI,MAAM,SAAS;AACjB,UAAI;AACF,eAAO,MAAM,QAAQ,KAAK,GAAG;AAAA,MAC/B,QAAQ;AAAA,MAER;AAAA,IACF;AAEA,QAAI,MAAM,SAAS,SAAS;AAC1B,UAAI;AACF,eAAO,MAAM,QAAQ,QAAQ,KAAK,GAAG;AAAA,MACvC,QAAQ;AAAA,MAER;AAAA,IACF;AAEA,QAAI,KAAK,eAAe;AACtB,UAAI;AACF,eAAO,KAAK,cAAc,KAAK,GAAG;AAAA,MACpC,QAAQ;AAAA,MAER;AAAA,IACF;AAMA,QAAI,eAAe,iBAAiB;AAClC,YAAM,SAAS,KAAK,MAAM,eACtB,IAAI,SACJ,IAAI,OAAO,IAAI,CAAC,WAAW,EAAE,MAAM,MAAM,MAAM,SAAS,gBAAgB,EAAE;AAC9E,aAAO,SAAS;AAAA,QACd,EAAE,OAAO,oBAAoB,MAAM,IAAI,MAAM,SAAS,IAAI,SAAS,OAAO;AAAA,QAC1E,EAAE,QAAQ,IAAI;AAAA,MAChB;AAAA,IACF;AAEA,QAAI,eAAe,WAAW;AAC5B,aAAO,SAAS;AAAA,QACd,EAAE,OAAO,IAAI,MAAM,MAAM,IAAI,MAAM,SAAS,IAAI,QAAQ;AAAA,QACxD,EAAE,QAAQ,IAAI,OAAO;AAAA,MACvB;AAAA,IACF;AAGA,QACE,eAAe,SACf,OAAQ,IAAY,WAAW,YAC/B,OAAQ,IAAY,SAAS,UAC7B;AACA,YAAM,IAAI;AACV,aAAO,SAAS;AAAA,QACd,EAAE,OAAO,EAAE,MAAM,MAAM,EAAE,MAAM,SAAS,EAAE,QAAQ;AAAA,QAClD,EAAE,QAAQ,EAAE,OAAO;AAAA,MACrB;AAAA,IACF;AAEA,WAAO,SAAS;AAAA,MACd,EAAE,OAAO,yBAAyB,MAAM,kBAAkB,SAAS,+BAA+B;AAAA,MAClG,EAAE,QAAQ,IAAI;AAAA,IAChB;AAAA,EACF;AAAA,EAEA,QAAQ,MAA4C;AAClD,QAAI,KAAK,qBAAqB,QAAW;AACvC,WAAK,QAAQ,EAAE,GAAG,KAAK,OAAO,kBAAkB,KAAK,iBAAiB;AAAA,IACxE;AACA,WAAO;AAAA,EACT;AAAA,EAEA,MAAM,QAAuB;AAE3B,eAAW,OAAO,KAAK,UAAU,OAAO,GAAG;AACzC,UAAI,KAAK;AAAA,IACX;AACA,SAAK,UAAU,MAAM;AAGrB,UAAM,WAAW,CAAC,GAAG,KAAK,OAAO,EAAE,QAAQ;AAC3C,eAAW,UAAU,UAAU;AAC7B,UAAI,OAAO,UAAU;AACnB,YAAI;AACF,gBAAM,OAAO,SAAS;AAAA,QACxB,SAAS,KAAK;AAEZ,eAAK,iBAAiB,sCAAsC,OAAO,IAAI,MAAM,GAAG;AAAA,QAClF;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAAA,EAEA,eAAe,SAA6D;AAC1E,WAAO,oBAAoB,KAAK,QAAQ,OAAO;AAAA,EACjD;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,YAA0F;AACxF,WAAO,KAAK,OACT,OAAO,WAAS,MAAM,eAAe,QAAQ,EAC7C,IAAI,WAAS;AACZ,YAAM,MAAM,MAAM;AAClB,YAAM,aAAa,MACd,IAAI,MAAM,OAAO,IAAI,OAAO,QAAQ,OAAO,EAAE,EAAE,MAAM,GAAG,EAAE,CAAC,IAC5D;AACJ,aAAO;AAAA,QACL,QAAW,MAAM;AAAA,QACjB,MAAW,MAAM;AAAA,QACjB,QAAW,cAAc;AAAA,QACzB,WAAW,MAAM,OAAO,SAAS;AAAA,MACnC;AAAA,IACF,CAAC;AAAA,EACL;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,YAAY,SAAsD;AAChE,UAAM,QAAU,SAAS,SAAW;AACpC,UAAM,UAAU,SAAS,UAAU,IAAI,QAAQ,OAAO,KAAK;AAC3D,YAAQ,IAAI;AAAA,IAAO,KAAK,GAAG,OAAO;AAAA,CAAI;AACtC,eAAW,SAAS,KAAK,QAAQ;AAC/B,YAAM,QAAQ,MAAM,OAAO,SAAS,IAAI,gBAAS;AACjD,cAAQ,IAAI,KAAK,MAAM,OAAO,OAAO,CAAC,CAAC,IAAI,MAAM,IAAI,GAAG,KAAK,EAAE;AAAA,IACjE;AACA,YAAQ,IAAI;AAAA,EACd;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAcQ,kBAA2C;AAEjD,UAAM,SAAS,oBAAI,IAA8B;AACjD,eAAW,SAAS,KAAK,QAAQ;AAG/B,UAAI,MAAM,KAAK,SAAS,GAAG,EAAG;AAC9B,YAAM,WAAW,OAAO,IAAI,MAAM,IAAI;AACtC,UAAI,UAAU;AACZ,iBAAS,KAAK,KAAK;AAAA,MACrB,OAAO;AACL,eAAO,IAAI,MAAM,MAAM,CAAC,KAAK,CAAC;AAAA,MAChC;AAAA,IACF;AAEA,UAAM,YAAqC,CAAC;AAC5C,eAAW,CAAC,MAAM,MAAM,KAAK,QAAQ;AACnC,YAAM,UAAsG,CAAC;AAC7G,iBAAW,SAAS,QAAQ;AAC1B,cAAM,WAAW;AACjB,gBAAQ,SAAS,MAAM,IAAI,OAAO,KAAiB,QAAuC;AAExF,cAAI,CAAC,KAAK,kBAAkB;AAC1B,iBAAK,mBAAmB;AACxB,uBAAW,UAAU,KAAK,SAAS;AACjC,kBAAI,OAAO,QAAS,OAAM,OAAO,QAAQ,KAAK,KAAK;AAAA,YACrD;AAAA,UACF;AAEA,gBAAM,MAAM,IAAI,IAAI,IAAI,GAAG;AAC3B,gBAAM,eAAe,IAAI,kBAAkB;AAE3C,gBAAM,UAAmB;AAAA,YACvB;AAAA,YACA,QAAQ,CAAC;AAAA,YACT,OAAO,WAAW,IAAI,MAAM;AAAA,YAC5B,MAAM,CAAI,MAASA,UAAS,QAAQ,SAAS,KAAK,MAAM,EAAE,QAAAA,QAAO,CAAC;AAAA,YAClE,MAAM,CAAC,MAAcA,UAAS,QAAQ,IAAI,SAAS,MAAM,EAAE,QAAAA,SAAQ,SAAS,EAAE,gBAAgB,aAAa,EAAE,CAAC;AAAA,YAC9G,MAAM,CAAC,MAAcA,UAAS,QAAQ,IAAI,SAAS,MAAM,EAAE,QAAAA,SAAQ,SAAS,EAAE,gBAAgB,YAAY,EAAE,CAAC;AAAA,YAC7G,QAAQ;AAAA,YACR,KAAQ;AAAA,YACR,QAAQ,gBAAgB,GAAG;AAAA,YAC3B,MAAM,CAAC,OAAO,YAAY;AAAE,2BAAa,QAAQ,OAAiB,OAAO;AAAA,YAAE;AAAA,YAC3E,eAAe;AAAA,UACjB;AAGA,qBAAW,QAAQ,KAAK,iBAAiB;AACvC,gBAAI;AACJ,gBAAI;AACF,yBAAW,MAAM,KAAK,IAAI,OAAO;AAAA,YACnC,QAAQ;AACN,yBAAW;AAAA,YACb;AACA,gBAAI,oBAAoB,UAAU;AAChC,qBAAO,KAAK,eAAe,SAAS,UAAU,IAAI;AAAA,YACpD;AAAA,UACF;AAMA,iBAAO,KAAK,UAAU,SAAS,UAAU,IAAI,QAAQ,YAAY;AAAA,QACnE;AAAA,MACF;AACA,gBAAU,IAAI,IAAI;AAAA,IACpB;AAEA,WAAO;AAAA,EACT;AAAA,EAEA,OACE,MACA,IACA,SAC8B;AAE9B,QAAI,CAAC,KAAK,kBAAkB;AAC1B,WAAK,mBAAmB;AACxB,iBAAW,UAAU,KAAK,SAAS;AACjC,YAAI,OAAO,SAAS;AAClB,gBAAM,SAAS,OAAO,QAAQ,KAAK,KAAK;AAExC,cAAI,UAAU,OAAQ,OAAe,SAAS,YAAY;AACxD,YAAC,OAAyB;AAAA,cAAM,CAAC,QAC/B,KAAK,iBAAiB,gDAAgD,GAAG;AAAA,YAC3E;AAAA,UACF;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAGA,SAAK,eAAe;AAGpB,UAAM,SAAS,IAAI,MAAM;AAAA,MACvB;AAAA,MACA,QAAQ,KAAK,gBAAgB;AAAA,MAC7B,OAAO,CAAC,KAAc,QAAuC,KAAK,MAAM,KAAK,GAAG;AAAA,MAChF,GAAI,KAAK,aAAa,EAAE,WAAW,KAAK,WAAW,mBAAmB,EAAE,IAAI,CAAC;AAAA,IAC/E,CAAQ;AACR,SAAK,IAAI;AAIT,UAAM,aAAa,SAAS,sBAAsB;AAClD,QAAI,YAAY;AACd,UAAI,eAAe;AACnB,YAAM,WAAW,YAAY;AAC3B,YAAI,aAAc;AAClB,uBAAe;AACf,cAAM,KAAK,MAAM;AACjB,gBAAQ,KAAK,CAAC;AAAA,MAChB;AACA,cAAQ,GAAG,WAAW,QAAQ;AAC9B,cAAQ,GAAG,UAAU,QAAQ;AAAA,IAC/B;AAEA,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA,EAMQ,iBAAuB;AAC7B,UAAM,UAAU,KAAK,MAAM,WAAW;AAEtC,UAAM,cAAc,KAAK,UAAU,OAAO,OAAK,EAAE,UAAU,IAAI;AAC/D,QAAI,CAAC,WAAW,YAAY,SAAS,GAAG;AACtC,cAAQ,KAAK,oGAA+F;AAAA,IAC9G;AAEA,eAAW,OAAO,KAAK,WAAW;AAChC,cAAQ,IAAI,UAAU,IAAI,KAAK,wBAAmB,IAAI,WAAW,IAAI,IAAI,cAAc,iBAAiB,EAAE,EAAE;AAE5G,UAAI,IAAI,UAAU,MAAM;AAEtB;AAAC,QAAC,IACC,KAAK,IAAI,SAAU,IAAI,aAAa,IAAI,KAAK;AAChD;AAAA,MACF;AAIA,YAAM,EAAE,KAAK,IAAI,UAAQ,QAAQ;AAEjC,YAAM,aAAa,IAAI;AAEvB,YAAM,SAAS,YAAY;AACzB,cAAM,QAAQ,IAAI,UAAU;AAC5B,cAAM,WAAW,MAAM,KAAK,UAAU,QAAQ,IAAI,OAAO,KAAK;AAC9D,YAAI,CAAC,SAAU;AAEf,cAAM,QAAQ,KAAK,IAAI;AACvB,gBAAQ,IAAI,UAAU,IAAI,KAAK,oBAAe;AAC9C,YAAI;AACF,gBAAM,SAAS,gBAAgB,EAAE,MAAM,OAAO,CAAC;AAC/C,gBAAM,SAAS,UAAU,IAAI,OAAO,SAAS,KAAK,KAAK,IAAI;AAC3D,gBAAM,UAAU,SAAS,OAAO,QAAQ,MAAM,IAAI;AAElD,gBAAM,WAAW,IAAI,UAAU,SAAS,KAAK,UACzC,oBAAoB,IAAI,WAAW,OAAO,IAC1C,CAAC;AAEL,gBAAM,IAAI,SAAU,EAAE,IAAI,SAAS,GAAG,SAAS,GAAG,UAAU;AAC5D,kBAAQ,IAAI,UAAU,IAAI,KAAK,iBAAY,KAAK,IAAI,IAAI,KAAK,KAAK;AAAA,QACpE,SAAS,KAAK;AACZ,cAAI,IAAI,UAAU;AAChB,gBAAI,SAAS,GAAG;AAAA,UAClB,OAAO;AACL,oBAAQ,MAAM,UAAU,IAAI,KAAK,kBAAa,GAAG;AAAA,UACnD;AAAA,QACF,UAAE;AACA,gBAAM,KAAK,UAAU,QAAQ,IAAI,KAAK;AAAA,QACxC;AAAA,MACF;AAEA,YAAM,MAAM,IAAI;AAAA,QACd,IAAI;AAAA,QACJ,EAAE,MAAM,IAAI,OAAO,UAAU,IAAI,UAAU;AAAA,QAC3C;AAAA,MACF;AACA,WAAK,UAAU,IAAI,IAAI,OAAO,GAAG;AAEjC,UAAI,IAAI,aAAa;AACnB,eAAO,EAAE,MAAM,CAAC,QAAQ;AACtB,cAAI,IAAI,UAAU;AAChB,gBAAI,SAAS,GAAG;AAAA,UAClB,OAAO;AACL,oBAAQ,MAAM,UAAU,IAAI,KAAK,sBAAsB,GAAG;AAAA,UAC5D;AAAA,QACF,CAAC;AAAA,MACH;AAAA,IACF;AAAA,EACF;AACF;AAsBO,SAAS,UAAU,OAOtB,CAAC,GAA+C;AAClD,SAAO,IAAI,KAA2C,IAAI;AAC5D;;;AQnoDA;AA6FA,SAASC,kBACP,SAC+F;AAC/F,MAAI,OAAO,YAAY,YAAY;AACjC,WAAO,EAAE,SAAS,EAAE,QAAQ,GAAG,QAAQ,QAAW,MAAM,OAAU;AAAA,EACpE;AACA,MAAI,YAAY,WAAW,WAAW,WAAW,UAAU,WAAW,cAAc,WAAW,UAAU,SAAS;AAChH,UAAM,IAAI;AACV,WAAO;AAAA,MACL,SAAS,EAAE,SAAS,EAAE,QAAuD;AAAA,MAC7E,QAAQ,EAAE,QAAQ,EAAE,QAAQ,OAAO,EAAE,OAAO,MAAM,EAAE,MAAM,UAAU,EAAE,SAAS;AAAA,MAC/E,MAAM,EAAE;AAAA,IACV;AAAA,EACF;AACA,SAAO,EAAE,SAAwC,QAAQ,QAAW,MAAM,OAAU;AACtF;AAEO,IAAM,gBAAN,MAAM,eAAsH;AAAA,EAKzH,YAA+B,QAA4B;AAA5B;AAAA,EAA6B;AAAA,EAA7B;AAAA;AAAA;AAAA;AAAA,EAK7B,MACR,WACuC;AACvC,WAAO,IAAI,eAAsC,EAAE,GAAG,KAAK,QAAQ,GAAG,UAAU,CAAC;AAAA,EACnF;AAAA;AAAA;AAAA,EAIA,IAAI,YAA4B;AAAE,WAAO,KAAK,OAAO;AAAA,EAAS;AAAA,EAE9D,OAAO,OAA+B,QAAwE;AAC5G,WAAO,IAAI,eAAsD;AAAA,MAC/D;AAAA,MACA,SAAqB,CAAC;AAAA,MACtB,kBAAqB,CAAC;AAAA,MACtB,mBAAqB,CAAC;AAAA,MACtB,qBAAqB,CAAC;AAAA,MACtB,QAAqB,CAAC;AAAA,MACtB,UAAqB,CAAC;AAAA,MACtB,QAAqB,CAAC;AAAA,MACtB,gBAAqB,CAAC;AAAA,MACtB,qBAAqB,CAAC;AAAA,MACtB,iBAAqB,CAAC;AAAA,MACtB,SAAqB;AAAA,MACrB,kBAAqB,CAAC;AAAA,MACtB,UAAqB,CAAC;AAAA,MACtB,YAAqB;AAAA,MACrB,MAAqB;AAAA,MACrB,SAAqB;AAAA,IACvB,CAAC;AAAA,EACH;AAAA,EAEA,QAAQ,MAA0D;AAChE,WAAO,KAAK,MAAM,EAAE,SAAS,KAAK,CAAC;AAAA,EACrC;AAAA,EAEA,WAAW,GAA+D;AACxE,WAAO,KAAK,MAAM,EAAE,YAAY,EAAE,CAAC;AAAA,EACrC;AAAA,EAEA,OAA4B,GAAqE;AAC/F,UAAM,OAAO,KAAK,MAAM,EAAE,SAAS,CAAC,GAAG,KAAK,OAAO,SAAS,CAAqB,EAAE,CAAC;AACpF,WAAO;AAAA,EACT;AAAA,EASA,IACE,qBACoG;AACpG,QAAI,iBAAiB,qBAAqB;AACxC,YAAM,OAAuC,EAAE,SAAS,oBAAoB;AAC5E,YAAM,OAAO,KAAK,MAAM;AAAA,QACtB,qBAAqB,CAAC,GAAG,KAAK,OAAO,qBAAqB,IAA2C;AAAA,MACvG,CAAC;AACD,aAAO;AAAA,IACT;AAEA,UAAM,IAAI;AACV,UAAM,YAAyC,CAAC;AAChD,QAAI,EAAE,YAAY;AAChB,gBAAU,iBAAiB,CAAC,GAAG,KAAK,OAAO,gBAAgB,gBAAgB,EAAE,UAAU,CAAC;AAAA,IAC1F;AACA,QAAI,EAAE,aAAa;AACjB,gBAAU,kBAAkB,CAAC,GAAG,KAAK,OAAO,iBAAiB,iBAAiB,EAAE,WAAW,CAAC;AAAA,IAC9F;AACA,WAAO,KAAK,MAAM,SAAS;AAAA,EAC7B;AAAA,EAEA,MAAM,GAAuD;AAC3D,WAAO,KAAK,MAAM,EAAE,QAAQ,CAAC,GAAG,KAAK,OAAO,QAAQ,CAAe,EAAE,CAAC;AAAA,EACxE;AAAA,EAEA,UAAU,MAAkE;AAC1E,WAAO,KAAK,MAAM,EAAE,gBAAgB,CAAC,GAAG,KAAK,OAAO,gBAAgB,IAA0B,EAAE,CAAC;AAAA,EACnG;AAAA,EAEA,eAAe,MAAuE;AACpF,WAAO,KAAK,MAAM,EAAE,qBAAqB,CAAC,GAAG,KAAK,OAAO,qBAAqB,IAA+B,EAAE,CAAC;AAAA,EAClH;AAAA,EAEA,WAAW,MAAmE;AAC5E,WAAO,KAAK,MAAM,EAAE,iBAAiB,CAAC,GAAG,KAAK,OAAO,iBAAiB,IAA2B,EAAE,CAAC;AAAA,EACtG;AAAA,EAEA,KAAQ,OAAyB,UAA8E;AAC7G,WAAO,KAAK,MAAM,EAAE,kBAAkB,CAAC,GAAG,KAAK,OAAO,kBAAkB,EAAE,OAAO,SAAS,CAAC,EAAE,CAAC;AAAA,EAChG;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,MACE,OACA,QACuC;AACvC,UAAM,OAAqC,EAAE,OAAO,OAAO;AAC3D,WAAO,KAAK,MAAM,EAAE,mBAAmB,CAAC,GAAG,KAAK,OAAO,mBAAmB,IAAI,EAAE,CAAC;AAAA,EACnF;AAAA,EAEA,OAAO,SAAiE;AACtE,WAAO,KAAK,MAAM,EAAE,kBAAkB,CAAC,GAAG,KAAK,OAAO,kBAAkB,OAAO,EAAE,CAAC;AAAA,EACpF;AAAA,EAEA,KAAK,KAAqD;AACxD,WAAO,KAAK,MAAM,EAAE,UAAU,CAAC,GAAG,KAAK,OAAO,UAAU,GAAG,EAAE,CAAC;AAAA,EAChE;AAAA,EAEQ,UACN,QACA,MACA,YACuC;AACvC,UAAM,EAAE,SAAS,QAAQ,KAAK,IAAIA,kBAAiB,UAAU;AAC7D,UAAM,WAAW,OAAO,eAAe,YAAY,aAAa,cAAc,EAAE,YAAY,cACvF,WAA+C,QAChD;AACJ,UAAM,QAAoB;AAAA,MACxB;AAAA,MAAQ;AAAA,MAAM;AAAA,MAAS;AAAA,MAAQ;AAAA,MAC/B,QAAmB,YAAY,QAAQ,aAAa,QAAQ,CAAC,QAA0B,IAAI,CAAC;AAAA,MAC5F,mBAAmB,aAAa,QAAQ,OAAO;AAAA,IACjD;AACA,WAAO,KAAK,MAAM,EAAE,QAAQ,CAAC,GAAG,KAAK,OAAO,QAAQ,KAAK,EAAE,CAAC;AAAA,EAC9D;AAAA;AAAA,EA4EA,MAAM,KAmBqC;AAEzC,QAAI,OAAO,IAAI;AACf,QAAI,IAAI,YAAY,QAAW;AAC7B,aAAO,EAAE,GAAG,MAAM,SAAS,MAAM,WAAW,IAAI,QAAQ;AAAA,IAC1D;AAEA,UAAM,OAAW,IAAI,QAAY,IAAI,QAAQ;AAC7C,UAAM,SAAW,IAAI,UAAY,IAAI,QAAQ;AAC7C,UAAM,QAAW,IAAI,SAAY,IAAI,QAAQ;AAC7C,UAAM,WAAW,IAAI,YAAY,IAAI,QAAQ;AAE7C,UAAM,SAAwK;AAAA,MAC5K;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA,SAAS,IAAI;AAAA,IACf;AAIA,UAAM,EAAE,SAAS,IAAI,QAAQ,MAAM,eAAe,IAAIA,kBAAiB,MAAM;AAC7E,UAAM,QAAqB;AAAA,MACzB,QAAa,IAAI;AAAA,MACjB,MAAa,IAAI;AAAA,MACjB,SAAa,IAAI;AAAA,MACjB,aAAa,IAAI;AAAA,MACjB,YAAa,IAAI;AAAA,MACjB,MAAa;AAAA,MACb,SAAa;AAAA,MACb,QAAkB,IAAI,SAAS,QAAQ,IAAI,UAAU,QAAQ,CAAC,IAAI,KAAuB,IAAI,CAAC;AAAA,MAC9F,mBAAmB,IAAI,UAAU,QAAQ,OAAO;AAAA,MAChD;AAAA,IACF;AACA,WAAO,KAAK,MAAM,EAAE,QAAQ,CAAC,GAAG,KAAK,OAAO,QAAQ,KAAK,EAAE,CAAC;AAAA,EAC9D;AAAA,EAEA,KAAK,GAAkF;AACrF,WAAO,KAAK,MAAM,EAAE,MAAM,EAAE,CAAC;AAAA,EAC/B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUQ,gBACN,QACA,MACA,cACwC;AACxC,QAAI,OAAO,iBAAiB,YAAY,aAAa,gBAAgB,OAAO,aAAa,YAAY,cAAc,EAAE,YAAY,eAAe;AAC9I,YAAM,EAAE,SAAS,MAAM,QAAQ,OAAO,UAAU,MAAM,MAAM,IAAI;AAChE,aAAO,KAAK,UAAU,QAAQ,MAAM,EAAE,SAAS,MAAM,QAAQ,OAAO,UAAU,MAAM,MAAM,CAA8C;AAAA,IAC1I;AACA,WAAO,KAAK,UAAU,QAAQ,MAAM,YAAkF;AAAA,EACxH;AAAA,EAkBA,IAAI,MAAc,cAAkG;AAClH,WAAO,KAAK,gBAAgB,OAAO,MAAM,YAAY;AAAA,EACvD;AAAA,EAkBA,KAAK,MAAc,cAAkG;AACnH,WAAO,KAAK,gBAAgB,QAAQ,MAAM,YAAY;AAAA,EACxD;AAAA,EAkBA,IAAI,MAAc,cAAkG;AAClH,WAAO,KAAK,gBAAgB,OAAO,MAAM,YAAY;AAAA,EACvD;AAAA,EAkBA,MAAM,MAAc,cAAkG;AACpH,WAAO,KAAK,gBAAgB,SAAS,MAAM,YAAY;AAAA,EACzD;AAAA,EAkBA,OAAO,MAAc,cAAkG;AACrH,WAAO,KAAK,gBAAgB,UAAU,MAAM,YAAY;AAAA,EAC1D;AAAA,EAEA,QAAQ,SAAoE;AAC1E,WAAO,KAAK,MAAM,EAAE,SAAS,QAA6B,CAAC;AAAA,EAC7D;AAAA,EAEA,QAA+E;AAC7E,UAAM,IAAI,KAAK;AACf,UAAM,MAAkB;AAAA,MACtB,QAAqB,EAAE;AAAA,MACvB,QAAqB,CAAC,GAAG,EAAE,MAAM;AAAA,MACjC,UAAqB,CAAC,GAAG,EAAE,QAAQ;AAAA,MACnC,kBAAqB,CAAC,GAAG,EAAE,gBAAgB;AAAA,MAC3C,mBAAqB,CAAC,GAAG,EAAE,iBAAiB;AAAA,MAC5C,qBAAqB,CAAC,GAAG,EAAE,mBAAmB;AAAA,MAC9C,SAAqB,CAAC,GAAG,EAAE,OAAO;AAAA,MAClC,QAAqB,CAAC,GAAG,EAAE,MAAM;AAAA,MACjC,gBAAqB,CAAC,GAAG,EAAE,cAAc;AAAA,MACzC,qBAAqB,CAAC,GAAG,EAAE,mBAAmB;AAAA,MAC9C,iBAAqB,CAAC,GAAG,EAAE,eAAe;AAAA,MAC1C,SAAqB,EAAE;AAAA,MACvB,kBAAqB,CAAC,GAAG,EAAE,gBAAgB;AAAA,MAC3C,UAAqB,CAAC,GAAG,EAAE,QAAQ;AAAA,MACnC,YAAqB,EAAE;AAAA,MACvB,MAAqB,EAAE;AAAA,MACvB,SAAqB,EAAE;AAAA,IACzB;AAGA,WAAO;AAAA,EACT;AACF;AAgBO,SAAS,aACd,QACoD;AAIpD,SAAO,cAAc,OAAO,MAAM;AACpC;;;AC1iBA;AAoEO,IAAM,gBAAN,MAAyC;AAAA,EAO9C,YAA6B,OAAe;AAAf;AAAA,EAAgB;AAAA,EAAhB;AAAA,EANrB,WAA6B,CAAC;AAAA,EAC9B,YAA6B,CAAC;AAAA,EAC9B,WAA6B,CAAC;AAAA,EAC9B,eAA6B,CAAC;AAAA,EAC9B,OAA6B,CAAC;AAAA,EAItC,QAAQ,MAAyB;AAC/B,SAAK,WAAW;AAChB,WAAO;AAAA,EACT;AAAA,EAEA,SAAS,MAAsB;AAC7B,SAAK,YAAY;AACjB,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAYA,QAAQ,OAA2C;AACjD,QAAI,OAAO,UAAU,YAAY;AAK/B,WAAK,WAAW,MAAM,CAAC,CAAmB;AAAA,IAC5C,OAAO;AACL,WAAK,WAAW;AAAA,IAClB;AACA,WAAO;AAAA,EACT;AAAA,EAEA,WAAW,MAA+B;AACxC,SAAK,eAAe,MAAM,QAAQ,IAAI,IAAI,OAAO,CAAC,IAAI;AACtD,WAAO;AAAA,EACT;AAAA,EAEA,IAAI,OAAkC;AACpC,SAAK,OAAO,MAAM,QAAQ,KAAK,IAAI,QAAQ,CAAC,KAAK;AACjD,WAAO;AAAA,EACT;AAAA;AAAA,EAGA,OACE,IACuB;AACvB,UAAM,SAAc,oBAAoB,UAAU,KAAK,KAAK,IAAI,KAAK,SAAS,GAAG;AACjF,UAAM,OAAc,KAAK;AACzB,UAAM,WAAc,KAAK,UAAU,SAAY,IAAI,KAAK,YAAe;AACvE,UAAM,UAAc,KAAK,SAAS,SAAa,IAAI,KAAK,WAAe;AACvE,UAAM,cAAc,KAAK,aAAa,SAAS,IAAI,KAAK,eAAe;AACvE,UAAM,MAAc,KAAK,KAAK,SAAiB,IAAI,KAAK,OAAe;AACvE,WAAO;AAAA,MACL;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA,SAAU;AAAA,MACV,SAAU,OAAO,QAAQ;AACvB,eAAO,MAAM,WAAW,EAAE,QAAQ,KAAK,CAAC;AACxC,eAAO,EAAE,GAAG,KAAK,GAAG,MAAM,GAAG,GAAG,EAAE;AAAA,MACpC;AAAA,MACA,UAAU;AAAA,IACZ;AAAA,EACF;AAAA;AAAA,EAGA,MAAM,KAIoB;AACxB,UAAM,SAAc,oBAAoB,UAAU,KAAK,KAAK,IAAI,KAAK,SAAS,GAAG;AACjF,UAAM,OAAc,KAAK;AACzB,UAAM,WAAc,KAAK,UAAU,SAAY,IAAI,KAAK,YAAe;AACvE,UAAM,UAAc,KAAK,SAAS,SAAa,IAAI,KAAK,WAAe;AACvE,UAAM,cAAc,KAAK,aAAa,SAAS,IAAI,KAAK,eAAe;AACvE,UAAM,MAAc,KAAK,KAAK,SAAiB,IAAI,KAAK,OAAe;AACvE,WAAO;AAAA,MACL;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA,SAAU,IAAI;AAAA,MACd,SAAU,OAAO,QAAQ;AACvB,eAAO,MAAM,WAAW,EAAE,QAAQ,KAAK,CAAC;AACxC,eAAO,EAAE,GAAG,KAAK,GAAG,MAAM,IAAI,QAAQ,GAAG,EAAE;AAAA,MAC7C;AAAA,MACA,UAAU,IAAI;AAAA,IAChB;AAAA,EACF;AACF;AAcO,SAAS,aACd,MACqB;AACrB,SAAO,IAAI,cAAoB,IAAI;AACrC;AAOO,SAAS,aACd,MACA,YAMyB;AACzB,SAAO,OAAO;AAAA,IACZ;AAAA,IACA,SAAU,WAAW,UAAU,MAAM,WAAW,QAAS,IAAI;AAAA,IAC7D,SAAU,OAAO,SAAS,EAAE,GAAG,KAAK,GAAG,MAAM,WAAW,QAAQ,GAAG,EAAE;AAAA,IACrE,UAAU,WAAW;AAAA,EACvB;AACF;AAIO,SAAS,eAAuE;AACrF,QAAM,SAAiB;AAAA,IACrB,MAAO,CAAC,QAAQ,SAAS,QAAQ,IAAI,WAAW,GAAG,IAAI,GAAG,IAAI;AAAA,IAC9D,MAAO,CAAC,QAAQ,SAAS,QAAQ,KAAK,WAAW,GAAG,IAAI,GAAG,IAAI;AAAA,IAC/D,OAAO,CAAC,QAAQ,SAAS,QAAQ,MAAM,WAAW,GAAG,IAAI,GAAG,IAAI;AAAA,IAChE,OAAO,CAAC,QAAQ,SAAS,QAAQ,IAAI,WAAW,GAAG,IAAI,GAAG,IAAI;AAAA,EAChE;AACA,SAAO;AAAA,IACL,MAAM;AAAA,IACN,SAAS,CAAC,SAAS,EAAE,GAAG,KAAK,OAAO;AAAA,EACtC;AACF;AAWO,SAAS,eAAe,KAAuE;AAEpG,QAAM,cAAwB,OAAO,IAAK,8CAAgE,SAAS;AAEnH,QAAM,SAAgE;AAAA,IACpE,MAAM;AAAA,IACN,KAAK;AAAA,IACL,SAAS,CAAC,SAAS,EAAE,GAAG,KAAK,QAAQ,YAAY;AAAA,EACnD;AACA,SAAO;AACT;AAsBO,SAAS,SACd,QACA,KACmC;AAEnC,QAAM,EAAE,QAAAC,QAAO,IAAI;AACnB,MAAI,SAAmE;AAKvE,MAAI;AACJ,MAAI,KAAK,SAAS;AAChB,UAAM,SAAU,IAAI;AACpB,UAAM,QAAU,IAAI,SAAS;AAC7B,UAAM,SAAU,IAAI;AACpB,oBAAgB,CAAC,UAAU;AACzB,YAAM,SAAS,aAAa,MAAM,IAAI,KAAK,MAAM,WAAW,QAAQ,CAAC,CAAC;AACtE,UAAI,WAAW,UAAa,MAAM,cAAc,QAAQ;AACtD,gBAAQ,KAAK,yBAAyB,MAAM,WAAW,QAAQ,CAAC,CAAC,QAAQ,MAAM,GAAG,EAAE;AAAA,MACtF,OAAO;AACL,YAAI,UAAU,OAAS,SAAQ,IAAI,GAAG,MAAM,IAAI,MAAM,GAAG,EAAE;AAAA,iBAClD,UAAU,OAAQ,SAAQ,KAAK,GAAG,MAAM,IAAI,MAAM,GAAG,EAAE;AAAA,YAC3D,SAAQ,MAAM,GAAG,MAAM,IAAI,MAAM,GAAG,EAAE;AAAA,MAC7C;AACA,eAAS,KAAK;AAAA,IAChB;AAAA,EACF,WAAW,KAAK,SAAS;AAEvB,oBAAgB,IAAI;AAAA,EACtB;AAEA,SAAO;AAAA,IACL,MAAM;AAAA,IACN,SAAS,CAAC,UAAU;AAClB,YAAM,UAAU,eAAqB,MAAM;AAC3C,UAAI,cAAe,SAAQ,UAAU;AACrC,YAAM,WAAW,OAAO;AACxB,eAAS,IAAIA,QAAO,SAAS,KAAK;AAAA,IACpC;AAAA,IACA,SAAS,CAAC,QAAQ;AAChB,UAAI,CAAC,OAAQ,OAAM,IAAI,MAAM,oFAA+E;AAK5G,YAAM,WAAY,IAA2C,WAAW;AAExE,aAAO,EAAE,GAAG,KAAK,IAAI,OAAO,QAAQ,KAAK,IAAI,eAAe,QAAQ,EAAE;AAAA,IACxE;AAAA,EACF;AACF;;;AzBzPA;;;A0B5EA;AAoCA,IAAM,aAAc;AACpB,IAAM,cAAc;AAEpB,SAAS,WAAW,OAA8C;AAChE,MAAI,UAAU,MAAW,QAAO;AAChC,MAAI,UAAU,SAAW,QAAO;AAChC,MAAI,UAAU,aAAa,UAAU,OAAW,QAAO;AACvD,SAAO;AACT;AAEA,IAAM,WAAyF;AAAA,EAC7F,yBAAyB;AAAA,EACzB,qBAAyB;AAAA,EACzB,eAAyB;AAAA,EACzB,gBAAyB;AAAA,EACzB,gBAAyB;AAAA,EACzB,mBAAyB;AAC3B;AAEA,IAAM,eAA6F;AAAA,EACjG,yBAAyB;AAAA,EACzB,qBAAyB;AAAA,EACzB,eAAyB;AAAA,EACzB,gBAAyB;AAAA,EACzB,gBAAyB;AAAA,EACzB,mBAAyB;AAC3B;AAeO,SAAS,oBAAoB,UAAgC,CAAC,GAAmB;AAEtF,QAAM,WAAoC,CAAC;AAG3C,aAAW,OAAO,OAAO,KAAK,QAAQ,GAA0E;AAC9G,UAAM,MAAM,OAAO,UAAU,QAAQ,GAAG,IAAI,SAAS,GAAG;AACxD,QAAI,QAAQ,SAAS,QAAQ,QAAW;AACtC,eAAS,KAAK,CAAC,aAAa,GAAG,GAAG,GAAa,CAAC;AAAA,IAClD;AAAA,EACF;AAGA,QAAM,SAAS,WAAW,QAAQ,qBAAqB;AACvD,MAAI,WAAW,OAAO;AACpB,aAAS,KAAK,CAAC,2BAA2B,MAAM,CAAC;AAAA,EACnD;AAEA,SAAO,iBAAiB,CAAC,MAAM,QAAQ;AACrC,UAAM,UAAU,IAAI,QAAQ,IAAI,OAAO;AACvC,eAAW,CAAC,MAAM,KAAK,KAAK,UAAU;AAGpC,UAAI,CAAC,QAAQ,IAAI,IAAI,GAAG;AACtB,gBAAQ,IAAI,MAAM,KAAK;AAAA,MACzB;AAAA,IACF;AACA,WAAO,IAAI,SAAS,IAAI,MAAM;AAAA,MAC5B,QAAY,IAAI;AAAA,MAChB,YAAY,IAAI;AAAA,MAChB;AAAA,IACF,CAAC;AAAA,EACH,CAAC;AACH;;;AC9GA;AAsBO,IAAM,gBAAN,MAA8C;AAAA,EAClC,OAAO,oBAAI,IAAmB;AAAA;AAAA;AAAA;AAAA,EAK9B;AAAA;AAAA;AAAA;AAAA,EAKA;AAAA,EAEjB,YAAY,aAAa,KAAK,aAAa,KAAS;AAClD,SAAK,cAAc;AACnB,SAAK,cAAc;AAAA,EACrB;AAAA,EAEA,MAAM,UAAU,KAAa,UAA+D;AAC1F,UAAM,MAAM,KAAK,IAAI;AAGrB,QAAI,KAAK,OAAO,IAAI,KAAK,cAAc,GAAG;AACxC,WAAK,OAAO,GAAG;AAAA,IACjB;AAEA,UAAM,WAAW,KAAK,KAAK,IAAI,GAAG;AAElC,QAAI,YAAY,MAAM,SAAS,SAAS;AACtC,eAAS,SAAS;AAClB,aAAO,EAAE,OAAO,SAAS,OAAO,SAAS,SAAS,QAAQ;AAAA,IAC5D;AAGA,QAAI,KAAK,KAAK,QAAQ,KAAK,aAAa;AACtC,WAAK,aAAa,KAAK,IAAI,GAAG,KAAK,MAAM,KAAK,cAAc,GAAG,CAAC,CAAC;AAAA,IACnE;AAEA,UAAM,QAAe,EAAE,OAAO,GAAG,SAAS,MAAM,SAAS;AACzD,SAAK,KAAK,IAAI,KAAK,KAAK;AACxB,WAAO,EAAE,OAAO,GAAG,SAAS,MAAM,QAAQ;AAAA,EAC5C;AAAA,EAEA,MAAM,MAAM,KAA4B;AACtC,SAAK,KAAK,OAAO,GAAG;AAAA,EACtB;AAAA;AAAA;AAAA,EAIA,UAAgB;AACd,SAAK,OAAO,KAAK,IAAI,CAAC;AAAA,EACxB;AAAA,EAEQ,OAAO,KAAmB;AAChC,eAAW,CAAC,KAAK,KAAK,KAAK,KAAK,MAAM;AACpC,UAAI,OAAO,MAAM,QAAS,MAAK,KAAK,OAAO,GAAG;AAAA,IAChD;AAAA,EACF;AAAA;AAAA,EAGQ,aAAa,OAAqB;AACxC,UAAM,SAAS,CAAC,GAAG,KAAK,KAAK,QAAQ,CAAC,EAAE,KAAK,CAAC,GAAG,MAAM,EAAE,CAAC,EAAE,UAAU,EAAE,CAAC,EAAE,OAAO;AAClF,aAAS,IAAI,GAAG,IAAI,SAAS,IAAI,OAAO,QAAQ,KAAK;AACnD,WAAK,KAAK,OAAO,OAAO,CAAC,EAAG,CAAC,CAAC;AAAA,IAChC;AAAA,EACF;AACF;AAsEO,SAAS,gBAAgB,SAA0C;AACxE,QAAM,EAAE,KAAK,UAAU,UAAU,oBAAoB,IAAI;AACzD,QAAM,QAAwB,QAAQ,SAAS,IAAI,cAAc;AAEjE,QAAM,aAAa,QAAQ;AAC3B,QAAM,WAAa,OAAO,eAAe,YAAY,WAAW,WAAW;AAC3E,QAAM,UAAa,eAAe,QAAQ;AAM1C,MAAI,CAAC,QAAQ,eAAe,CAAC,YAAY;AACvC,YAAQ;AAAA,MACN;AAAA,IAIF;AAAA,EACF;AAGA,MAAI,uBAAuB;AAE3B,QAAM,qBAAqB,CAAC,QAAoC;AAC9D,QAAI,SAAS;AACX,YAAM,eAAe,IAAI,IAAI,QAAQ,IAAI,iBAAiB;AAC1D,UAAI,cAAc;AAGhB,cAAM,QAAQ,aAAa,MAAM,GAAG;AACpC,cAAM,SAAS,MAAM,MAAM,SAAS,CAAC,GAAG,KAAK;AAC7C,YAAI,OAAQ,QAAO;AAAA,MACrB;AAGA,UAAI,UAAU;AAEZ,eAAO,IAAI;AAAA,UACT,KAAK,UAAU,EAAE,OAAO,eAAe,MAAM,wBAAwB,SAAS,qCAAqC,CAAC;AAAA,UACpH,EAAE,QAAQ,KAAK,SAAS,EAAE,gBAAgB,mBAAmB,EAAE;AAAA,QACjE;AAAA,MACF;AAGA,UAAI,CAAC,sBAAsB;AACzB,+BAAuB;AACvB,gBAAQ;AAAA,UACN;AAAA,QAGF;AAAA,MACF;AAAA,IACF;AAGA,WAAO,IAAI,IAAI,QAAQ,IAAI,WAAW,KAAK;AAAA,EAC7C;AAEA,QAAM,cAAc,QAAQ,cACxB,CAAC,QAAoC,QAAQ,YAAa,GAAG,IAC7D;AAEJ,SAAO,gBAAgB,OAAO,QAAQ;AACpC,UAAM,gBAAgB,YAAY,GAAG;AAGrC,QAAI,yBAAyB,SAAU,QAAO;AAE9C,UAAM,MAAM;AACZ,UAAM,EAAE,OAAO,QAAQ,IAAI,MAAM,MAAM,UAAU,KAAK,QAAQ;AAE9D,UAAM,YAAY,KAAK,IAAI,GAAG,MAAM,KAAK;AACzC,UAAM,WAAY,KAAK,KAAK,UAAU,GAAI;AAE1C,QAAI,QAAQ,KAAK;AACf,YAAM,aAAa,KAAK,MAAM,UAAU,KAAK,IAAI,KAAK,GAAI;AAC1D,aAAO,IAAI;AAAA,QACT,KAAK,UAAU,EAAE,OAAO,qBAAqB,MAAM,uBAAuB,QAAQ,CAAC;AAAA,QACnF;AAAA,UACE,QAAQ;AAAA,UACR,SAAS;AAAA,YACP,gBAAsB;AAAA,YACtB,eAAsB,OAAO,UAAU;AAAA,YACvC,qBAAsB,OAAO,GAAG;AAAA,YAChC,yBAAyB;AAAA,YACzB,qBAAsB,OAAO,QAAQ;AAAA,UACvC;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAOA,SAAK;AACL,SAAK;AAAA,EACP,CAAC;AACH;;;AClQA;AAKA,IAAM,yBAAyB,oBAAI,IAAI,CAAC,QAAQ,OAAO,SAAS,QAAQ,CAAC;AAUlE,SAAS,gBAAgB,GAAW,GAAoB;AAC7D,MAAI,EAAE,WAAW,EAAE,OAAQ,QAAO;AAClC,MAAI,SAAS;AACb,WAAS,IAAI,GAAG,IAAI,EAAE,QAAQ,KAAK;AACjC,cAAU,EAAE,WAAW,CAAC,IAAI,EAAE,WAAW,CAAC;AAAA,EAC5C;AACA,SAAO,WAAW;AACpB;AAIA,SAAS,gBAAwB;AAE/B,QAAM,QAAQ,IAAI,WAAW,EAAE;AAC/B,SAAO,gBAAgB,KAAK;AAC5B,SAAO,MAAM,KAAK,OAAO,CAAC,MAAM,EAAE,SAAS,EAAE,EAAE,SAAS,GAAG,GAAG,CAAC,EAAE,KAAK,EAAE;AAC1E;AAkDO,SAAS,WAAW,UAAuB,CAAC,GAAe;AAChE,QAAM,aAAa,QAAQ,cAAc;AACzC,QAAM,aAAa,QAAQ,cAAc;AACzC,QAAM,SAAa,QAAQ,UAAc;AACzC,QAAM,SAAa,QAAQ,UAAc;AAEzC,QAAM,YAA2B,gBAAgB,CAAC,QAAiB;AACjE,UAAM,SAAS,IAAI,IAAI,OAAO,YAAY;AAC1C,QAAI,CAAC,uBAAuB,IAAI,MAAM,EAAG;AAEzC,UAAM,cAAe,IAAI,OAAO,IAAI,UAAU;AAC9C,UAAM,cAAe,IAAI,IAAI,QAAQ,IAAI,UAAU;AAEnD,QAAI,CAAC,eAAe,CAAC,eAAe,CAAC,gBAAgB,aAAa,WAAW,GAAG;AAC9E,aAAO,IAAI;AAAA,QACT,KAAK,UAAU,EAAE,OAAO,aAAa,MAAM,gBAAgB,SAAS,sBAAsB,CAAC;AAAA,QAC3F;AAAA,UACE,QAAS;AAAA,UACT,SAAS,EAAE,gBAAgB,mBAAmB;AAAA,QAChD;AAAA,MACF;AAAA,IACF;AAAA,EACF,CAAC;AAED,QAAM,aAA6B,iBAAiB,CAAC,KAAc,QAAkB;AACnF,UAAM,SAAS,IAAI,IAAI,OAAO,YAAY;AAG1C,QAAI,uBAAuB,IAAI,MAAM,EAAG;AAGxC,UAAM,WAAW,IAAI,OAAO,IAAI,UAAU;AAC1C,QAAI,SAAU;AAGd,QAAI,OAAO,IAAI,YAAY,cAAc,GAAG;AAAA,MAC1C,UAAU;AAAA,MACV,UAAU;AAAA,MACV;AAAA,MACA;AAAA,MACA,MAAU;AAAA,IACZ,CAAC;AAID,SAAK;AAAA,EACP,CAAC;AAED,SAAO,EAAE,WAAW,WAAW;AACjC;;;AClGA,SAAS,WAAW,UAAkB,OAAe,OAAe,SAAyB;AAC3F,SAAO;AAAA;AAAA;AAAA;AAAA;AAAA,WAKE,KAAK;AAAA;AAAA;AAAA,uDAGuC,QAAQ;AAAA;AAAA,2CAEpB,KAAK;AAAA;AAAA;AAAA;AAAA;AAKhD;AAkBO,SAAS,aAAa,KAAa,UAAyB,CAAC,GAAe;AACjF,QAAM,YAAc,QAAQ,QAAe;AAC3C,QAAM,QAAc,QAAQ,SAAe;AAC3C,QAAM,UAAc,QAAQ,WAAe;AAC3C,QAAM,cAAc,QAAQ,eAAe;AAC3C,QAAM,QAAc,QAAQ,SAAe;AAC3C,QAAM,WAAc,QAAQ,SAAe;AAC3C,QAAM,WAAc,GAAG,SAAS;AAGhC,MAAI,aAA4D;AAEhE,WAAS,UAAkD;AACzD,QAAI,UAAU;AACZ,UAAI,CAAC,WAAY,cAAa,oBAAoB,IAAI,QAAQ,EAAE,OAAO,SAAS,YAAY,CAAC;AAC7F,aAAO;AAAA,IACT;AACA,WAAO,oBAAoB,IAAI,QAAQ,EAAE,OAAO,SAAS,YAAY,CAAC;AAAA,EACxE;AAEA,QAAM,YAA4B;AAAA,IAChC,QAAS;AAAA,IACT,MAAS;AAAA,IACT,SAAS;AAAA,MACP,SAAS,CAAC,SAAS,SAAS,KAAK,QAAQ,CAAC;AAAA,IAC5C;AAAA,IACA,QAAY,CAAC;AAAA,IACb,YAAY;AAAA,EACd;AAEA,QAAM,UAA0B;AAAA,IAC9B,QAAS;AAAA,IACT,MAAS;AAAA,IACT,SAAS;AAAA,MACP,SAAS,CAAC,QAAQ;AAChB,cAAM,OAAU,QAAQ;AACxB,cAAM,WAAW,KAAK,UAAU,IAAI;AACpC,cAAM,OAAU,WAAW,UAAU,OAAO,OAAO,QAAQ;AAC3D,cAAM,MAAU,IAAI,KAAK,IAAI;AAG7B,YAAI,QAAQ;AAAA,UACV;AAAA,UACA;AAAA,YACE;AAAA,YACA;AAAA,YACA;AAAA,YACA;AAAA;AAAA,YACA;AAAA,YACA;AAAA,YACA;AAAA,UACF,EAAE,KAAK,IAAI;AAAA,QACb;AACA,eAAO;AAAA,MACT;AAAA,IACF;AAAA,IACA,QAAY,CAAC;AAAA,IACb,YAAY;AAAA,EACd;AAEA,QAAM,MAAkB;AAAA,IACtB,QAAqB;AAAA,IACrB,QAAqB,CAAC,WAAW,OAAO;AAAA,IACxC,UAAqB,CAAC;AAAA,IACtB,kBAAqB,CAAC;AAAA,IACtB,mBAAqB,CAAC;AAAA,IACtB,qBAAqB,CAAC;AAAA,IACtB,SAAqB,CAAC;AAAA,IACtB,QAAqB,CAAC;AAAA,IACtB,gBAAqB,CAAC;AAAA,IACtB,qBAAqB,CAAC;AAAA,IACtB,iBAAqB,CAAC;AAAA,IACtB,SAAqB;AAAA,IACrB,kBAAqB,CAAC;AAAA,IACtB,UAAqB,CAAC;AAAA,IACtB,YAAqB;AAAA,IACrB,MAAqB,EAAE,KAAK,UAAU,aAAa,uBAAuB;AAAA,EAC5E;AAEA,SAAO;AACT;;;AClJA;AA6BO,SAAS,oBAAoB,UAAgC,CAAC,GAAkB;AACrF,QAAM,UAAU,QAAQ,WAAW;AACnC,QAAM,UAAU,QAAQ,WAAW;AAEnC,SAAO,gBAAgB,CAAC,QAAQ;AAC9B,UAAM,gBAAgB,IAAI,IAAI,QAAQ,IAAI,gBAAgB;AAC1D,QAAI,kBAAkB,KAAM;AAE5B,UAAM,QAAQ,SAAS,eAAe,EAAE;AACxC,QAAI,MAAM,KAAK,EAAG;AAElB,QAAI,QAAQ,SAAS;AACnB,aAAO,IAAI;AAAA,QACT,KAAK,UAAU,EAAE,OAAO,qBAAqB,MAAM,qBAAqB,QAAQ,CAAC;AAAA,QACjF;AAAA,UACE,QAAQ;AAAA,UACR,SAAS,EAAE,gBAAgB,mBAAmB;AAAA,QAChD;AAAA,MACF;AAAA,IACF;AAAA,EACF,CAAC;AACH;;;AClDA;AAkEA,SAAS,cACP,eACA,eACe;AACf,MAAI,CAAC,cAAe,QAAO;AAE3B,MAAI,kBAAkB,IAAK,QAAO;AAClC,MAAI,OAAO,kBAAkB,UAAU;AACrC,WAAO,kBAAkB,gBAAgB,gBAAgB;AAAA,EAC3D;AACA,MAAI,MAAM,QAAQ,aAAa,GAAG;AAChC,WAAO,cAAc,SAAS,aAAa,IAAI,gBAAgB;AAAA,EACjE;AACA,MAAI,OAAO,kBAAkB,YAAY;AACvC,WAAO,cAAc,aAAa,IAAI,gBAAgB;AAAA,EACxD;AACA,SAAO;AACT;AAeO,SAAS,WAAW,UAAuB,CAAC,GAAe;AAChE,QAAM,gBAAiB,QAAQ,UAAiB;AAGhD,MAAK,kBAAkB,OAAQ,QAAQ,gBAAgB,MAAM;AAC3D,UAAM,IAAI;AAAA,MACR;AAAA,IACF;AAAA,EACF;AACA,QAAM,UAAiB,QAAQ,WAAkB,CAAC,OAAO,QAAQ,OAAO,SAAS,UAAU,SAAS;AACpG,QAAM,eAAiB,QAAQ,gBAAkB,CAAC,gBAAgB,iBAAiB,cAAc;AACjG,QAAM,gBAAiB,QAAQ,iBAAkB,CAAC;AAClD,QAAM,cAAiB,QAAQ,eAAkB;AACjD,QAAM,SAAiB,QAAQ,UAAkB;AAEjD,QAAM,aAAkB,QAAQ,KAAK,IAAI;AACzC,QAAM,kBAAkB,aAAa,KAAK,IAAI;AAC9C,QAAM,mBAAmB,cAAc,KAAK,IAAI;AAChD,QAAM,YAAmB,OAAO,MAAM;AAEtC,WAAS,iBAAiB,eAAuC;AAC/D,UAAM,UAAU,IAAI,QAAQ;AAC5B,UAAM,WAAW,cAAc,eAAe,aAAa;AAC3D,QAAI,UAAU;AACZ,cAAQ,IAAI,+BAA+B,QAAQ;AAEnD,UAAI,aAAa,KAAK;AACpB,gBAAQ,IAAI,QAAQ,QAAQ;AAAA,MAC9B;AAAA,IACF;AACA,QAAI,aAAa;AACf,cAAQ,IAAI,oCAAoC,MAAM;AAAA,IACxD;AACA,QAAI,kBAAkB;AACpB,cAAQ,IAAI,iCAAiC,gBAAgB;AAAA,IAC/D;AACA,WAAO;AAAA,EACT;AAEA,QAAM,YAA2B,gBAAgB,CAAC,QAAQ;AACxD,QAAI,IAAI,IAAI,OAAO,YAAY,MAAM,UAAW;AAEhD,UAAM,gBAAgB,IAAI,IAAI,QAAQ,IAAI,QAAQ;AAClD,UAAM,cAAgB,iBAAiB,aAAa;AAGpD,gBAAY,IAAI,gCAAgC,UAAU;AAC1D,gBAAY,IAAI,gCAAgC,eAAe;AAC/D,gBAAY,IAAI,0BAA0B,SAAS;AAEnD,WAAO,IAAI,SAAS,MAAM,EAAE,QAAQ,KAAK,SAAS,YAAY,CAAC;AAAA,EACjE,CAAC;AAED,QAAM,aAA6B,iBAAiB,CAAC,KAAK,QAAQ;AAChE,UAAM,gBAAgB,IAAI,IAAI,QAAQ,IAAI,QAAQ;AAClD,UAAM,cAAgB,iBAAiB,aAAa;AAGpD,UAAM,SAAS,IAAI,QAAQ,IAAI,OAAO;AACtC,eAAW,CAAC,KAAK,KAAK,KAAK,aAAa;AACtC,aAAO,IAAI,KAAK,KAAK;AAAA,IACvB;AAEA,WAAO,IAAI,SAAS,IAAI,MAAM;AAAA,MAC5B,QAAS,IAAI;AAAA,MACb,SAAS;AAAA,IACX,CAAC;AAAA,EACH,CAAC;AAED,SAAO,EAAE,WAAW,WAAW;AACjC;;;ACxKA;AAgDA,SAAS,mBAA2B;AAClC,QAAM,QAAQ,IAAI,WAAW,EAAE;AAC/B,SAAO,gBAAgB,KAAK;AAC5B,SAAO,MAAM,KAAK,OAAO,CAAC,MAAM,EAAE,SAAS,EAAE,EAAE,SAAS,GAAG,GAAG,CAAC,EAAE,KAAK,EAAE;AAC1E;AAGA,SAAS,SAAS,OAAwB;AACxC,SAAO,MAAM,SAAS,KAAK,MAAM,UAAU,OAAO,YAAY,KAAK,KAAK;AAC1E;AAkBO,SAAS,gBAAgB,UAA4B,CAAC,GAAoB;AAC/E,QAAM,iBAAiB,QAAQ,kBAAkB;AACjD,QAAM,iBAAiB,QAAQ,kBAAkB;AACjD,QAAM,WAAiB,QAAQ,aAAkB;AAEjD,QAAM,YAAmD,gBAA8B,CAAC,QAAQ;AAC9F,UAAM,WAAW,IAAI,IAAI,QAAQ,IAAI,cAAc;AACnD,UAAM,KAAM,YAAY,SAAS,QAAQ,IAAK,WAAW,SAAS;AAClE,QAAI,YAAY;AAAA,EAClB,CAAC;AAED,QAAM,aAAqD,iBAA+B,CAAC,KAAK,QAAQ;AACtG,UAAM,UAAU,IAAI,QAAQ,IAAI,OAAO;AACvC,YAAQ,IAAI,gBAAgB,IAAI,SAAS;AACzC,WAAO,IAAI,SAAS,IAAI,MAAM,EAAE,QAAQ,IAAI,QAAQ,QAAQ,CAAC;AAAA,EAC/D,CAAC;AAED,SAAO,EAAE,WAAW,WAAW;AACjC;;;AC7FA;AAgCA,IAAM,eAAe;AAErB,SAAS,eAAe,aAAqC;AAC3D,MAAI,CAAC,YAAa,QAAO;AACzB,SAAO,aAAa,KAAK,YAAY,MAAM,GAAG,EAAE,CAAC,EAAG,KAAK,CAAC;AAC5D;AAGA,SAAS,kBACP,gBACA,SAC2B;AAC3B,MAAI,CAAC,eAAgB,QAAO;AAC5B,aAAW,OAAO,SAAS;AACzB,QAAI,eAAe,SAAS,GAAG,EAAG,QAAO;AAAA,EAC3C;AACA,SAAO;AACT;AAQA,IAAM,cAAc;AAmBpB,IAAM,mBAAmB,KAAK,OAAO;AAE9B,SAAS,kBAAkB,UAA8B,CAAC,GAAmB;AAClF,QAAM,YAAY,QAAQ,aAAa,CAAC,QAAQ,SAAS;AACzD,QAAM,YAAY,QAAQ,aAAa;AACvC,QAAM,UAAY,QAAQ,WAAa;AAEvC,SAAO,iBAAiB,OAAO,KAAK,QAAQ;AAE1C,QAAI,IAAI,WAAW,OAAO,IAAI,WAAW,IAAK;AAG9C,QAAI,IAAI,QAAQ,IAAI,kBAAkB,EAAG;AAGzC,UAAM,cAAc,IAAI,QAAQ,IAAI,cAAc;AAClD,QAAI,aAAa,SAAS,mBAAmB,EAAG;AAGhD,QAAI,CAAC,eAAe,WAAW,EAAG;AAGlC,UAAM,iBAAiB,IAAI,IAAI,QAAQ,IAAI,iBAAiB;AAC5D,UAAM,WAAW,kBAAkB,gBAAgB,SAAS;AAC5D,QAAI,CAAC,SAAU;AAGf,UAAM,OAAO,MAAM,IAAI,YAAY;AACnC,QAAI,KAAK,aAAa,UAAW;AAGjC,QAAI,KAAK,aAAa,QAAS,QAAO;AAGtC,UAAM,QAAa,IAAI,WAAW,IAAI;AACtC,UAAM,aAAa,aAAa,SAC5B,YAAY,SAAS,KAAK,IAC1B,YAAY,YAAY,KAAK;AAEjC,UAAM,UAAU,IAAI,QAAQ,IAAI,OAAO;AACvC,YAAQ,IAAI,oBAAoB,QAAQ;AACxC,YAAQ,IAAI,kBAAkB,OAAO,WAAW,UAAU,CAAC;AAC3D,YAAQ,IAAI,QAAQ,iBAAiB;AAErC,WAAO,IAAI,SAAS,WAAW,QAAuB,EAAE,QAAQ,IAAI,QAAQ,QAAQ,CAAC;AAAA,EACvF,CAAC;AACH;;;AC1HA;AAuCO,SAAS,aAAa,UAA+B,CAAC,GAAiB;AAC5E,QAAM,aAAa,QAAQ,QAAa;AACxC,QAAM,YAAa,QAAQ,aAAa;AACxC,QAAM,SAAa,QAAQ,UAAa,CAAC;AAEzC,QAAM,YAA2B,gBAAgB,OAAO,QAAQ;AAC9D,UAAM,MAAS,IAAI,IAAI,IAAI,IAAI,GAAG;AAClC,UAAM,OAAS,IAAI;AACnB,UAAM,SAAS,IAAI,IAAI,OAAO,YAAY;AAE1C,QAAI,WAAW,MAAO;AAGtB,QAAI,SAAS,YAAY;AACvB,aAAO,SAAS,KAAK,EAAE,QAAQ,MAAM,QAAQ,QAAQ,OAAO,EAAE,GAAG,EAAE,QAAQ,IAAI,CAAC;AAAA,IAClF;AAGA,QAAI,SAAS,WAAW;AACtB,YAAM,aAAe,OAAO,KAAK,MAAM;AACvC,YAAM,eAAmG,CAAC;AAC1G,UAAI,QAAQ;AAEZ,iBAAW,QAAQ,YAAY;AAC7B,YAAI;AACF,gBAAM,SAAS,MAAM,OAAO,IAAI,EAAG;AACnC,uBAAa,IAAI,IAAI,EAAE,IAAI,OAAO,IAAI,GAAI,OAAO,UAAU,EAAE,SAAS,OAAO,QAAQ,IAAI,CAAC,EAAG;AAC7F,cAAI,CAAC,OAAO,GAAI,SAAQ;AAAA,QAC1B,SAAS,KAAK;AACZ,gBAAM,UAAU,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG;AAC/D,uBAAa,IAAI,IAAI,EAAE,IAAI,OAAO,OAAO,QAAQ;AACjD,kBAAQ;AAAA,QACV;AAAA,MACF;AAEA,UAAI,OAAO;AACT,eAAO,SAAS,KAAK,EAAE,QAAQ,SAAS,QAAQ,aAAa,GAAG,EAAE,QAAQ,IAAI,CAAC;AAAA,MACjF,OAAO;AACL,eAAO,SAAS,KAAK,EAAE,QAAQ,aAAa,QAAQ,aAAa,GAAG,EAAE,QAAQ,IAAI,CAAC;AAAA,MACrF;AAAA,IACF;AAAA,EACF,CAAC;AAED,SAAO,EAAE,UAAU;AACrB;;;AClFO,IAAM,kBAAN,cAA8B,MAAM;AAAA,EACzC,YACWC,SACA,MACT,SACS,QACT;AACA,UAAM,OAAO;AALJ,kBAAAA;AACA;AAEA;AAGT,SAAK,OAAO;AAAA,EACd;AAAA,EAPW;AAAA,EACA;AAAA,EAEA;AAKb;;;ACKO,SAAS,gBAAgB,QAAwB;AAEtD,SAAO,OACJ,QAAQ,OAAO,EAAE,EACjB,MAAM,QAAQ,EACd,OAAO,OAAO,EACd,IAAI,CAAC,MAAM,MAAM,MAAM,IAAI,OAAO,KAAK,OAAO,CAAC,EAAE,YAAY,IAAI,KAAK,MAAM,CAAC,CAAC,EAC9E,KAAK,EAAE;AACZ;AAYA,SAAS,iBAAiB,QAAgB,QAAwB;AAChE,QAAM,IAAI,OAAO,YAAY;AAE7B,QAAM,IAAI,OAAO,QAAQ,OAAO,EAAE;AAGlC,MAAI,MAAM,MAAM,MAAM,KAAK;AACzB,QAAI,MAAM,MAAU,QAAO;AAC3B,QAAI,MAAM,OAAU,QAAO;AAAA,EAC7B;AACA,MAAI,aAAa,KAAK,CAAC,GAAG;AACxB,QAAI,MAAM,MAAU,QAAO;AAC3B,QAAI,MAAM,QAAU,QAAO;AAC3B,QAAI,MAAM,SAAU,QAAO;AAAA,EAC7B;AAGA,QAAM,WAAW,EAAE,MAAM,GAAG,EAAE,OAAO,OAAO,EAAE;AAAA,IAAI,CAAC,QACjD,IAAI,WAAW,GAAG,IAAI,OAAO,IAAI,MAAM,CAAC,EAAE,OAAO,CAAC,EAAE,YAAY,IAAI,IAAI,MAAM,CAAC,IAAI;AAAA,EACrF;AACA,QAAM,OAAO,SACV,IAAI,CAAC,KAAK,MAAM,MAAM,IAAI,MAAM,IAAI,OAAO,CAAC,EAAE,YAAY,IAAI,IAAI,MAAM,CAAC,CAAC,EAC1E,KAAK,EAAE;AACV,SAAO,IAAI,KAAK,OAAO,CAAC,EAAE,YAAY,IAAI,KAAK,MAAM,CAAC;AACxD;AAwKA,SAAS,iBAAiB,QAAyG;AACjI,SAAO,OAAO,IAAI,CAAC,MAAM;AACvB,UAAM,SAAS,EAAE,SAAS,UAAU;AACpC,UAAM,SAAS,EAAE,KAAK,WAAW,MAAM,IAAI,EAAE,KAAK,MAAM,OAAO,MAAM,KAAK,MAAM,EAAE;AAClF,WAAO,EAAE,QAAQ,EAAE,QAAQ,MAAM,EAAE,MAAM,QAAQ,OAAO;AAAA,EAC1D,CAAC;AACH;AAEA,SAAS,qBAAqB,MAAc,MAAwD;AAClG,QAAM,cAAc,KAAK,MAAM,SAAS,KAAK,CAAC,GAAG;AACjD,QAAM,SAAS,KAAK,MAAM,GAAG,UAAU;AACvC,QAAM,YAAY,KAAK,MAAM,UAAU;AACvC,MAAI,IAAI;AACR,QAAM,MAAM,KAAK,QAAQ,WAAW,MAAM,OAAO,OAAO,GAAG,KAAK,EAAE,CAAC;AACnE,SAAO,EAAE,KAAK,UAAU;AAC1B;AAEA,eAAe,oBACb,SACA,YACA,MACA,eACA,SACA,cACgC;AAEhC,QAAM,YAAY,SAAS,KAAK,WAAW,MAAM;AACjD,MAAI;AACJ,MAAI;AAEJ,QAAM,eAAe,WAAW,WAAW,UAAU,WAAW,WAAW,SAAS,WAAW,WAAW;AAE1G,MAAI,cAAc;AAEhB,UAAM,cAAc,WAAW,KAAK,MAAM,SAAS,KAAK,CAAC,GAAG;AAC5D,eAAW,KAAK,MAAM,GAAG,UAAU;AACnC,UAAM,UAAU,KAAK,UAAU;AAC/B,UAAM,UAAU,KAAK,aAAa,CAAC;AACnC,WAAO,EAAE,MAAM,SAAS,SAAS,SAAS,SAAS,OAAO,SAAS,MAAM;AAAA,EAC3E,OAAO;AAEL,UAAM,cAAc,WAAW,KAAK,MAAM,SAAS,KAAK,CAAC,GAAG;AAC5D,eAAW,KAAK,MAAM,GAAG,UAAU;AACnC,WAAO,KAAK,UAAU;AAAA,EACxB;AAEA,QAAM,EAAE,KAAK,YAAY,IAAI,qBAAqB,WAAW,MAAM,QAAQ;AAC3E,MAAI,MAAM,QAAQ,QAAQ,OAAO,EAAE,IAAI;AAEvC,MAAI,MAAM,OAAO;AACf,UAAM,KAAK,IAAI,gBAAgB,KAAK,KAA+B,EAAE,SAAS;AAC9E,QAAI,GAAI,QAAO,MAAM;AAAA,EACvB;AAEA,QAAM,UAAkC,EAAE,GAAG,eAAe,GAAG,MAAM,QAAQ;AAC7E,MAAI;AAEJ,MAAI,MAAM,SAAS,UAAa,cAAc;AAC5C,cAAU,KAAK,UAAU,KAAK,IAAI;AAClC,YAAQ,cAAc,IAAI;AAAA,EAC5B;AAEA,MAAI;AACJ,MAAI;AACF,UAAM,MAAM,QAAQ,IAAI,QAAQ,KAAK,EAAE,QAAQ,WAAW,QAAQ,SAAS,MAAM,QAAQ,CAAC,CAAC;AAAA,EAC7F,SAAS,YAAY;AACnB,UAAM,MAAM,sBAAsB,QAAQ,WAAW,UAAU;AAC/D,UAAM,MAAM,IAAI,gBAAgB,GAAG,iBAAiB,GAAG;AACvD,QAAI,aAAc,OAAM;AACxB,WAAO,EAAE,IAAI,OAAO,OAAO,KAAK,QAAQ,GAAG,MAAM,iBAAiB,SAAS,IAAI;AAAA,EACjF;AAEA,MAAI,CAAC,IAAI,IAAI;AACX,QAAI,OAAO,QAAQ,IAAI,MAAM;AAC7B,QAAI,UAAU,QAAQ,IAAI,MAAM;AAChC,QAAI;AACF,YAAM,OAAO,MAAM,IAAI,KAAK;AAC5B,UAAI,KAAK,KAAS,QAAU,KAAK;AACjC,UAAI,KAAK,QAAS,WAAU,KAAK;AAAA,eACxB,KAAK,MAAO,WAAU,KAAK;AAAA,IACtC,QAAQ;AAAA,IAA2B;AAEnC,UAAM,MAAM,IAAI,gBAAgB,IAAI,QAAQ,MAAM,OAAO;AACzD,QAAI,aAAc,OAAM;AACxB,WAAO,EAAE,IAAI,OAAO,OAAO,KAAK,QAAQ,IAAI,QAAQ,MAAM,QAAQ;AAAA,EACpE;AAEA,MAAI;AACJ,MAAI;AACF,WAAO,MAAM,IAAI,KAAK;AAAA,EACxB,QAAQ;AACN,WAAO;AAAA,EACT;AAEA,SAAO,EAAE,IAAI,MAAM,MAAM,QAAQ,IAAI,OAAO;AAC9C;AAIO,SAAS,kBACd,KACA,SACA,SACwB;AACxB,QAAM,UAAU,SAAS,UAAU,CAAC,QAAiB,WAAW,MAAM,GAAG;AACzE,QAAM,gBAAgB,SAAS,WAAW,CAAC;AAC3C,QAAM,eAAe,SAAS,UAAU;AAExC,QAAM,cAAc,iBAAiB,IAAI,MAAM;AAG/C,QAAM,QAAQ,oBAAI,IAA+B;AACjD,aAAW,KAAK,aAAa;AAC3B,UAAM,MAAM,gBAAgB,EAAE,MAAM,KAAK;AACzC,QAAI,CAAC,MAAM,IAAI,GAAG,EAAG,OAAM,IAAI,KAAK,CAAC,CAAC;AACtC,UAAM,IAAI,GAAG,EAAG,KAAK,CAAC;AAAA,EACxB;AAGA,QAAM,QAAgG,CAAC;AAEvG,aAAW,CAAC,KAAK,KAAK,KAAK,OAAO;AAChC,UAAM,UAAkF,CAAC;AACzF,eAAW,QAAQ,OAAO;AACxB,YAAM,aAAa,iBAAiB,KAAK,QAAQ,KAAK,MAAM;AAC5D,cAAQ,UAAU,IAAI,IAAI,SACxB,oBAAoB,SAAS,MAAM,MAAM,eAAe,SAAS,YAAY;AAAA,IACjF;AACA,UAAM,GAAG,IAAI;AAAA,EACf;AAEA,SAAO;AACT;AAIO,SAAS,mBACd,QACA,SACA,SACwE;AACxE,QAAM,UAAU,SAAS,UAAU,CAAC,QAAiB,WAAW,MAAM,GAAG;AACzE,QAAM,gBAAgB,SAAS,WAAW,CAAC;AAC3C,QAAM,eAAe,SAAS,UAAU;AAGxC,QAAM,iBAAiB,OAAO,OAAO,IAAI,CAAC,OAAO;AAAA,IAC/C,GAAG;AAAA,IACH,MAAM,OAAO,SAAS,EAAE;AAAA,IACxB,SAAS,EAAE,QAAQ,OAAO,OAAO;AAAA,EACnC,EAAE;AAEF,QAAM,cAAc,iBAAiB,cAAc;AACnD,QAAM,UAAkF,CAAC;AAEzF,aAAW,QAAQ,aAAa;AAC9B,UAAM,aAAa,iBAAiB,KAAK,QAAQ,KAAK,MAAM;AAC5D,YAAQ,UAAU,IAAI,IAAI,SACxB,oBAAoB,SAAS,MAAM,MAAM,eAAe,SAAS,YAAY;AAAA,EACjF;AAEA,SAAO;AACT;;;ACjXO,SAAS,iBAMd,KACA,SACwB;AACxB,QAAM,EAAE,UAAU,oBAAoB,GAAG,KAAK,IAAI,WAAW,CAAC;AAC9D,SAAO,kBAAkB,KAAK,SAAS;AAAA,IACrC,GAAG;AAAA,IACH,OAAO,CAAC,QAAiB,IAAI,MAAM,GAAG;AAAA,EACxC,CAAC;AACH;;;AC4BA,SAAS,eAAe,MAAc,QAA0C;AAC9E,MAAI,CAAC,OAAQ,QAAO;AACpB,SAAO,KAAK,QAAQ,aAAa,CAAC,GAAG,QAAQ,OAAO,OAAO,GAAa,KAAK,IAAI,GAAG,EAAE,CAAC;AACzF;AAKO,SAAS,aACd,SACA,SAC+F;AAC/F,QAAM,UAAmB,SAAS,UAAU,CAAC,QAAQ,WAAW,MAAM,GAAG;AAEzE,iBAAe,QAAQ,QAAgB,MAAc,MAAoD;AAGvG,UAAM,cAAc,eAAe,MAAM,MAAM,MAA6C;AAE5F,QAAI,MAAM,QAAQ,QAAQ,OAAO,EAAE,IAAI;AAGvC,QAAI,MAAM,UAAU,WAAW,SAAS,WAAW,WAAW;AAC5D,YAAM,KAAK,IAAI,gBAAgB,KAAK,KAA+B,EAAE,SAAS;AAC9E,UAAI,GAAI,QAAO,MAAM;AAAA,IACvB;AAEA,UAAM,UAAkC,EAAE,GAAG,MAAM,QAAQ;AAC3D,QAAI;AAEJ,QAAI,MAAM,SAAS,WAAc,WAAW,UAAU,WAAW,SAAS,WAAW,UAAU;AAC7F,aAAO,KAAK,UAAU,KAAK,IAAI;AAC/B,cAAQ,cAAc,IAAI;AAAA,IAC5B;AAEA,UAAM,MAAM,MAAM,QAAQ,IAAI,QAAQ,KAAK,EAAE,QAAQ,SAAS,KAAK,CAAC,CAAC;AAErE,QAAI,CAAC,IAAI,IAAI;AACX,UAAI,IAAI,WAAW,KAAK;AACtB,YAAI;AACJ,YAAI;AACF,gBAAM,OAAO,MAAM,IAAI,KAAK;AAC5B,mBAAS,KAAK;AAAA,QAChB,QAAQ;AAAA,QAER;AACA,cAAM,IAAI,gBAAgB,IAAI,QAAQ,oBAAoB,qBAAqB,MAAM;AAAA,MACvF;AACA,YAAM,IAAI,gBAAgB,IAAI,QAAQ,QAAQ,IAAI,MAAM,IAAI,QAAQ,IAAI,MAAM,EAAE;AAAA,IAClF;AAGA,QAAI;AACF,aAAO,MAAM,IAAI,KAAK;AAAA,IACxB,QAAQ;AACN,aAAO;AAAA,IACT;AAAA,EACF;AAEA,SAAO;AAAA,IACL,KAAQ,CAAC,MAAM,SAAS,QAAQ,OAAU,MAAgB,IAAiC;AAAA,IAC3F,MAAQ,CAAC,MAAM,SAAS,QAAQ,QAAU,MAAgB,IAAiC;AAAA,IAC3F,KAAQ,CAAC,MAAM,SAAS,QAAQ,OAAU,MAAgB,IAAiC;AAAA,IAC3F,OAAQ,CAAC,MAAM,SAAS,QAAQ,SAAU,MAAgB,IAAiC;AAAA,IAC3F,QAAQ,CAAC,MAAM,SAAS,QAAQ,UAAU,MAAgB,IAAiC;AAAA,EAC7F;AACF;;;AClIA,SAAS,SAAS;AAOlB,SAAS,YAAY,KAAkC;AACrD,MAAIC;AAEJ,UAAQ,IAAI,IAAI,MAAM;AAAA,IACpB,KAAK;AAAa,MAAAA,QAAO,EAAE,OAAO,EAAE,IAAI;AAAG;AAAA,IAC3C,KAAK;AAAa,MAAAA,QAAO,EAAE,OAAO;AAAG;AAAA,IACrC,KAAK;AAAa,MAAAA,QAAO,EAAE,OAAO;AAAG;AAAA,IACrC,KAAK;AAAa,MAAAA,QAAO,EAAE,OAAO,EAAE,KAAK;AAAG;AAAA,IAC5C,KAAK;AAAa,MAAAA,QAAO,EAAE,QAAQ;AAAG;AAAA,IACtC,KAAK;AAAa,MAAAA,QAAO,EAAE,OAAO,KAAK;AAAG;AAAA,IAC1C,KAAK;AAAa,MAAAA,QAAO,EAAE,QAAQ;AAAG;AAAA,IACtC,KAAK;AAAa,MAAAA,QAAO,EAAE,WAAW,UAAU;AAAG;AAAA,IACnD;AAAkB,MAAAA,QAAO,EAAE,QAAQ;AAAA,EACrC;AAEA,MAAI,IAAI,IAAI,UAAU;AACpB,IAAAA,QAAOA,MAAK,SAAS;AAAA,EACvB;AAEA,SAAOA;AACT;AAUO,SAAS,iBACd,OACyC;AACzC,QAAM,QAAoC,CAAC;AAE3C,aAAW,CAAC,MAAM,GAAG,KAAK,OAAO,QAAQ,MAAM,MAAM,GAAG;AACtD,UAAM,IAAI;AAGV,QAAI,EAAE,IAAI,cAAc,EAAE,IAAI,cAAe;AAE7C,QAAI,QAAQ,YAAY,CAAC;AAGzB,QAAI,EAAE,IAAI,iBAAiB,UAAa,EAAE,IAAI,cAAc,QAAW;AACrE,cAAQ,MAAM,SAAS;AAAA,IACzB;AAEA,UAAM,IAAI,IAAI;AAAA,EAChB;AAEA,SAAO,EAAE,OAAO,KAAK;AACvB;AAIO,SAAS,cACd,OACyC;AACzC,QAAM,QAAoC,CAAC;AAE3C,aAAW,CAAC,MAAM,GAAG,KAAK,OAAO,QAAQ,MAAM,MAAM,GAAG;AACtD,UAAM,IAAI,IAAI,YAAY,GAAsB;AAAA,EAClD;AAEA,SAAO,EAAE,OAAO,KAAK;AACvB;;;ACvEA;;;AC8EA,SAAS,mBACP,OACA,WACA;AAIA,QAAM,YAAY,GAAG,MAAM,IAAI;AAE/B,SAAO,YAAY,WAAW,OAAO,CAAC,OAAO;AAC3C,UAAM,KAAK,MAAM;AAEjB,UAAM,QAAQ,UAAU,QACpB,UAAU,MAAM,EAAE,IAClB,MAAM,GAAG,KAAK,KAAK,EAAE,OAAO;AAEhC,UAAM,OAAO,UAAU,OACnB,UAAU,KAAK,EAAE,IACjB,OAAO,OAA8B;AACnC,YAAM,MAAM,MAAO,GAAG,KAAK,KAAK,EAAE,MAAM,EAAE,CAAC,EAAE,GAAG,GAAG,CAAkB,EAAE,MAAM;AAC7E,UAAI,CAAC,IAAK,OAAM,IAAI,cAAc,GAAG,MAAM,IAAI,YAAY,EAAE,YAAY;AACzE,aAAO;AAAA,IACT;AAEJ,UAAM,QAAQ,UAAU,QACpB,UAAU,MAAM,EAAE,IAClB,CAAC,SAAmB,GAAG,KAAK,KAAK,EAA4C,OAAO,IAAI;AAE5F,UAAM,SAAS,UAAU,SACrB,UAAU,OAAO,EAAE,IACnB,OAAO,IAAY,SAA0C;AAC3D,YAAM,KAAK,EAAE;AACb,YAAM,GAAG,KAAK,KAAK,EAAE,MAAM,EAAE,CAAC,EAAE,GAAG,GAAG,CAAkB,EAAE,OAAO,IAAqB;AACtF,aAAO,KAAK,EAAE;AAAA,IAChB;AAEJ,UAAM,UAAU,UAAU,UACtB,UAAU,QAAQ,EAAE,IACpB,OAAO,OAA8B;AACnC,YAAM,KAAK,EAAE;AACb,YAAM,GAAG,KAAK,KAAK,EAAE,MAAM,EAAE,CAAC,EAAE,GAAG,GAAG,CAAkB,EAAE,OAAO;AAAA,IACnE;AAGJ,UAAM,UAAmC,EAAE,OAAO,MAAM,OAAO,QAAQ,QAAQ;AAG/E,eAAW,CAAC,KAAK,OAAO,KAAK,OAAO,QAAQ,SAAS,GAAG;AACtD,UAAI,CAAC,CAAC,SAAS,QAAQ,SAAS,UAAU,SAAS,EAAE,SAAS,GAAG,KAAK,SAAS;AAC7E,gBAAQ,GAAG,IAAI,QAAQ,EAAE;AAAA,MAC3B;AAAA,IACF;AAEA,WAAO;AAAA,EACT,CAAC;AACH;AAMA,SAAS,qBACP,OACA,UACA,kBACoH;AAIpH,QAAM,aAAa,GAAG,MAAM,IAAI;AAChC,QAAM,YAAa,SAAS;AAE5B,SAAO,cAAc,UAAU,EAC5B,IAAI,QAAQ,EACZ,OAAO,CAAC,SAAS;AAChB,UAAM,QAAS,KAAkC,SAAS;AAE1D,UAAM,QAAU,iBAAiB,QAAU,iBAAiB,MAAM,EAAE,MAAM,CAAC,IAAM,MAAM,MAAM,MAAM;AACnG,UAAM,OAAU,iBAAiB,OAAU,iBAAiB,KAAK,EAAE,MAAM,CAAC,IAAO,CAAC,OAAe,MAAM,KAAK,EAAE;AAC9G,UAAM,QAAU,iBAAiB,QAAU,iBAAiB,MAAM,EAAE,MAAM,CAAC,IAAM,CAAC,SAAkB,MAAM,MAAM,IAAI;AACpH,UAAM,SAAU,iBAAiB,SAAU,iBAAiB,OAAO,EAAE,MAAM,CAAC,IAAK,CAAC,IAAY,SAA2B,MAAM,OAAO,IAAI,IAAI;AAC9I,UAAM,UAAU,iBAAiB,UAAU,iBAAiB,QAAQ,EAAE,MAAM,CAAC,IAAI,CAAC,OAAe,MAAM,QAAQ,EAAE;AAEjH,WAAO,EAAE,OAAO,MAAM,OAAO,QAAQ,QAAQ;AAAA,EAC/C,CAAC;AACL;AAIA,SAAS,oBACP,QACA,OACA,YACA,cACwB;AACxB,QAAM,aAAa,WAAW;AAC9B,QAAM,SAAa,gBAAgB,CAAC;AAEpC,QAAM,eAAe,iBAAiB,KAAK;AAC3C,QAAM,YAAe,cAAc,KAAK;AAKxC,MAAI,UAAU,aAAa,MAAM,EAAE,IAAI,UAAU;AAEjD,WAAS,OAAO,KAAe;AAC7B,WAAQ,IAAgC,UAAU;AAAA,EACpD;AAGA,MAAI,OAAO,UAAU,OAAO;AAC1B,UAAM,MAAM,OAAO,SAAS,CAAC;AAC7B,QAAI,IAAI;AACR,QAAI,OAAO,IAAI,MAAO,KAAI,EAAE,MAAM,IAAI,KAAmB;AACzD,QAAI,EAAE,MAAM;AAAA,MACV,QAAS;AAAA,MACT,MAAS;AAAA,MACT,SAAU,OAAO,IAAI,UAAW,IAAI,UAAU,QAAQ,MAAM,IAAI;AAAA,MAChE,SAAS,OAAO,QAAQ,IAAI,KAAK,MAAM,OAAO,GAAG,EAAE,MAAM,CAAC;AAAA,IAC5D,CAAC;AACD,cAAU;AAAA,EACZ;AAGA,MAAI,OAAO,SAAS,OAAO;AACzB,UAAM,MAAM,OAAO,QAAQ,CAAC;AAC5B,QAAI,IAAI;AACR,QAAI,OAAO,IAAI,MAAO,KAAI,EAAE,MAAM,IAAI,KAAmB;AACzD,QAAI,EAAE,MAAM;AAAA,MACV,QAAS;AAAA,MACT,MAAS;AAAA,MACT,SAAU,OAAO,IAAI,UAAW,IAAI,UAAU,OAAO,MAAM,IAAI;AAAA,MAC/D,SAAS,OAAO,QAAQ,IAAI,KAAK,MAAM,OAAO,GAAG,EAAE,KAAK,OAAO,IAAI,OAAO,IAAI,CAAC,CAAC,CAAC;AAAA,IACnF,CAAC;AACD,cAAU;AAAA,EACZ;AAGA,MAAI,OAAO,UAAU,OAAO;AAC1B,UAAM,MAAM,OAAO,SAAS,CAAC;AAC7B,QAAI,IAAI;AACR,QAAI,OAAO,IAAI,MAAO,KAAI,EAAE,MAAM,IAAI,KAAmB;AACzD,QAAI,EAAE,MAAM;AAAA,MACV,QAAS;AAAA,MACT,MAAS;AAAA,MACT,SAAU,OAAO,IAAI,UAAW,IAAI,UAAU,UAAU,MAAM,IAAI;AAAA,MAClE,QAAS,EAAE,MAAM,cAAc,UAAU,UAAU;AAAA,MACnD,SAAS,OAAO,QAAQ,IAAI,KAAK,MAAM,OAAO,GAAG,EAAE,MAAO,IAAoD,IAAI,GAAG,GAAG;AAAA,IAC1H,CAAC;AACD,cAAU;AAAA,EACZ;AAGA,MAAI,OAAO,WAAW,OAAO;AAC3B,UAAM,MAAM,OAAO,UAAU,CAAC;AAC9B,QAAI,IAAI;AACR,QAAI,OAAO,IAAI,MAAO,KAAI,EAAE,MAAM,IAAI,KAAmB;AACzD,QAAI,EAAE,MAAM;AAAA,MACV,QAAS;AAAA,MACT,MAAS;AAAA,MACT,SAAU,OAAO,IAAI,UAAW,IAAI,UAAU,UAAU,MAAM,IAAI;AAAA,MAClE,QAAS,EAAE,MAAM,aAAa,QAAQ,EAAE;AAAA,MACxC,SAAS,OAAO,QAAQ;AACtB,cAAM,MAAM,MAAM,OAAO,GAAG,EAAE;AAAA,UAC5B,OAAO,IAAI,OAAO,IAAI,CAAC;AAAA,UACtB,IAA6D;AAAA,QAChE;AACA,eAAO,IAAI,KAAK,GAAG;AAAA,MACrB;AAAA,IACF,CAAC;AACD,cAAU;AAAA,EACZ;AAGA,MAAI,OAAO,YAAY,OAAO;AAC5B,UAAM,MAAM,OAAO,WAAW,CAAC;AAC/B,QAAI,IAAI;AACR,QAAI,OAAO,IAAI,MAAO,KAAI,EAAE,MAAM,IAAI,KAAmB;AACzD,QAAI,EAAE,MAAM;AAAA,MACV,QAAS;AAAA,MACT,MAAS;AAAA,MACT,SAAU,OAAO,IAAI,UAAW,IAAI,UAAU,UAAU,MAAM,IAAI;AAAA,MAClE,SAAS,OAAO,QAAQ;AACtB,cAAM,OAAO,GAAG,EAAE,QAAQ,OAAO,IAAI,OAAO,IAAI,CAAC,CAAC;AAClD,eAAO,IAAI,KAAK,EAAE,IAAI,KAAK,CAAC;AAAA,MAC9B;AAAA,IACF,CAAC;AACD,cAAU;AAAA,EACZ;AAEA,SAAO;AACT;AAYO,IAAM,kBAAN,MAAM,iBAA8D;AAAA,EACjE,YACW,QACA,UACA,aACjB;AAHiB;AACA;AACA;AAAA,EAChB;AAAA,EAHgB;AAAA,EACA;AAAA,EACA;AAAA,EAGnB,OAAO,OACL,OACA,SACgC;AAChC,WAAO,IAAI,iBAA+B,OAAO,SAAS,CAAC,CAAC;AAAA,EAC9D;AAAA;AAAA,EAIA,QAAQ,MAAgD;AACtD,WAAO,IAAI;AAAA,MACT,KAAK;AAAA,MACL,KAAK;AAAA,MACL,CAAC,GAAG,KAAK,aAAa,CAAC,MAAM,EAAE,QAAQ,IAAI,CAAC;AAAA,IAC9C;AAAA,EACF;AAAA,EAEA,OAA4B,GAA2D;AACrF,WAAO,IAAI;AAAA,MACT,KAAK;AAAA,MACL,KAAK;AAAA,MACL,CAAC,GAAG,KAAK,aAAa,CAAC,MAAO,EAA6B,OAAO,CAAqC,CAAsC;AAAA,IAC/I;AAAA,EACF;AAAA,EAEA,MAAM,GAA6C;AACjD,WAAO,IAAI;AAAA,MACT,KAAK;AAAA,MACL,KAAK;AAAA,MACL,CAAC,GAAG,KAAK,aAAa,CAAC,MAAM,EAAE,MAAM,CAAmB,CAAC;AAAA,IAC3D;AAAA,EACF;AAAA,EAEA,KAAK,OAAuB,UAAoE;AAC9F,WAAO,IAAI;AAAA,MACT,KAAK;AAAA,MACL,KAAK;AAAA,MACL,CAAC,GAAG,KAAK,aAAa,CAAC,MAAM,EAAE,KAAK,OAAO,QAA0C,CAAC;AAAA,IACxF;AAAA,EACF;AAAA,EAEA,MACE,YACA,QAC6B;AAC7B,WAAO,IAAI;AAAA,MACT,KAAK;AAAA,MACL,KAAK;AAAA,MACL,CAAC,GAAG,KAAK,aAAa,CAAC,MAAM,EAAE,MAAM,YAAY,MAAsC,CAAC;AAAA,IAC1F;AAAA,EACF;AAAA,EAEA,IACE,SACkD;AAClD,WAAO,IAAI;AAAA,MACT,KAAK;AAAA,MACL,KAAK;AAAA,MACL,CAAC,GAAG,KAAK,aAAa,CAAC,MAAM,EAAE,IAAI,OAAO,CAA2B;AAAA,IACvE;AAAA,EACF;AAAA,EAEA,UAAU,MAAwD;AAChE,WAAO,IAAI;AAAA,MACT,KAAK;AAAA,MACL,KAAK;AAAA,MACL,CAAC,GAAG,KAAK,aAAa,CAAC,MAAM,EAAE,UAAU,IAA8B,CAAC;AAAA,IAC1E;AAAA,EACF;AAAA,EAEA,eAAe,MAA6D;AAC1E,WAAO,IAAI;AAAA,MACT,KAAK;AAAA,MACL,KAAK;AAAA,MACL,CAAC,GAAG,KAAK,aAAa,CAAC,MAAM,EAAE,eAAe,IAAmC,CAAC;AAAA,IACpF;AAAA,EACF;AAAA,EAEA,WAAW,MAAyD;AAClE,WAAO,IAAI;AAAA,MACT,KAAK;AAAA,MACL,KAAK;AAAA,MACL,CAAC,GAAG,KAAK,aAAa,CAAC,MAAM,EAAE,WAAW,IAA+B,CAAC;AAAA,IAC5E;AAAA,EACF;AAAA,EAEA,QAAQ,SAA0D;AAChE,WAAO,IAAI;AAAA,MACT,KAAK;AAAA,MACL,KAAK;AAAA,MACL,CAAC,GAAG,KAAK,aAAa,CAAC,MAAM,EAAE,QAAQ,OAAgC,CAAC;AAAA,IAC1E;AAAA,EACF;AAAA,EAEA,OAAO,SAAuD;AAC5D,WAAO,IAAI;AAAA,MACT,KAAK;AAAA,MACL,KAAK;AAAA,MACL,CAAC,GAAG,KAAK,aAAa,CAAC,MAAM,EAAE,OAAO,OAAO,CAAC;AAAA,IAChD;AAAA,EACF;AAAA;AAAA,EAIA,QAA8B;AAC5B,UAAM,SAAS,KAAK,SAAS,UAAU,IAAI,KAAK,OAAO,IAAI;AAC3D,UAAM,QAAU,mBAAmB,KAAK,QAAQ,KAAK,SAAS,SAAS,CAAC,CAAC;AACzE,UAAM,UAAU,qBAAqB,KAAK,QAAQ,OAAQ,KAAK,SAAS,WAAW,CAAC,CAAuF;AAC3K,QAAI,gBAAgB,oBAAoB,QAAQ,KAAK,QAAQ,SAAS,KAAK,SAAS,MAAM;AAC1F,eAAW,MAAM,KAAK,aAAa;AACjC,sBAAgB,GAAG,aAAa;AAAA,IAClC;AACA,UAAM,SAAS,cAAc,MAAM;AACnC,WAAO,EAAE,OAAO,SAAS,OAAO;AAAA,EAClC;AACF;AAcO,SAAS,eACd,OACA,UAA2F,CAAC,GAC5D;AAEhC,QAAM,OACJ,OAAO,YAAY,WAAW,EAAE,QAAQ,QAAQ,IAAI;AACtD,SAAO,gBAAgB,OAAO,OAAO,IAAI;AAC3C;;;ACvZA,IAAM,iBAAN,MAAqB;AAAA,EAInB,YAA6B,OAAe;AAAf;AAAA,EAAgB;AAAA,EAAhB;AAAA,EAHrB,QAAQ;AAAA,EACR,QAAyB,CAAC;AAAA,EAIlC,YAAY,MAAoB;AAC9B,SAAK,QAAQ;AACb,WAAO;AAAA,EACT;AAAA,EAEA,OAAO,MAAc,aAAqB,cAA6B;AACrE,SAAK,MAAM,KAAK,EAAE,MAAM,aAAa,SAAS,aAAa,CAAC;AAC5D,WAAO;AAAA,EACT;AAAA,EAEA,OAAO,IAAwE;AAC7E,WAAO;AAAA,MACL,OAAc,KAAK;AAAA,MACnB,cAAc,KAAK;AAAA,MACnB,UAAc,KAAK;AAAA,MACnB,SAAc;AAAA,IAChB;AAAA,EACF;AACF;AAEO,SAAS,aAAa,QAAgC;AAC3D,SAAO;AACT;AAEO,SAAS,cAAc,MAA8B;AAC1D,SAAO,IAAI,eAAe,IAAI;AAChC;;;A1C4EA;","names":["status","params","column","SQLiteAdapter","PostgresAdapter","MySQLAdapter","trimmed","readdir","join","readdir","cols","join","base","status","status","normalizeHandler","VelnDB","status","base"]}
|
|
1
|
+
{"version":3,"sources":["../src/events/index.ts","../src/errors/index.ts","../src/app/logger.ts","../src/app/types.ts","../src/db/sql.ts","../src/db/index.ts","../src/index.ts","../src/adapter/resolve.ts","../src/schema/column.ts","../src/schema/table.ts","../src/schema/audit.ts","../src/hooks/executor.ts","../src/db/migrations/runner.ts","../src/db/migrations/tracker.ts","../src/db/migrations/migrator.ts","../src/db/migrations/generator.ts","../src/db/migrations/introspect.ts","../src/db/migrations/diff.ts","../src/events/handler.ts","../src/model/index.ts","../src/service/index.ts","../src/app/middleware.ts","../src/app/index.ts","../src/openapi/zod-to-schema.ts","../src/openapi/generator.ts","../src/cron/index.ts","../src/app/system-ctx.ts","../src/app/router.ts","../src/app/audit-wiring.ts","../src/app/cookies.ts","../src/app/module.ts","../src/app/plugin.ts","../src/app/secure-headers.ts","../src/app/rate-limit.ts","../src/app/csrf.ts","../src/app/scalar.ts","../src/app/body-size-limit.ts","../src/app/cors.ts","../src/app/request-id.ts","../src/app/compression.ts","../src/app/health.ts","../src/client/error.ts","../src/client/proxy.ts","../src/client/test-client.ts","../src/client/index.ts","../src/resource/zod-table.ts","../src/resource/errors.ts","../src/resource/index.ts","../src/cli/config/types.ts"],"sourcesContent":["import type { PendingEvent } from '../db/index'\n\nexport type EventHandler = (payload: unknown, ctx: unknown) => Promise<void> | void\n\n// ── RequestEventQueue ────────────────────────────────────────────────────────\n// Per-request buffer. HookExecutor collects events here instead of emitting\n// immediately. fetch() flushes the queue after onResponse — guaranteeing that\n// events never fire on guard block, handler error, or rollback.\n\nexport class RequestEventQueue {\n private readonly buffer: PendingEvent[] = []\n\n collect(name: string, payload: unknown): void {\n this.buffer.push({ name, payload })\n }\n\n async flush(ctx: unknown, bus: EventBusAdapter | InMemoryEventBus): Promise<void> {\n const events = this.buffer.splice(0)\n for (const e of events) {\n if ('_emit' in bus) {\n (bus as InMemoryEventBus)._emit(e.name, e.payload, ctx)\n } else {\n await bus.emit(e.name, e.payload)\n }\n }\n }\n\n /** Drain — returns collected events and clears the buffer.\n * Used by the TX path to hand events off to TransactionResult. */\n drain(): PendingEvent[] {\n return this.buffer.splice(0)\n }\n\n /** Number of buffered events — useful in tests. */\n get size(): number {\n return this.buffer.length\n }\n}\n\n// VelnEvents — opt-in Declaration Merging escape hatch.\n//\n// STAGING NOTE (Phase 3 → Phase 4):\n// app.on() currently accepts `event: string` because module registration erases\n// the Table's generic types. InferTableEvents<T, M> is already fully defined in\n// schema/table.ts — Phase 4 will wire it into app.on() via a typed overload that\n// accepts Table references directly, making this Declaration Merging unnecessary\n// for Table-derived events. Use VelnEvents only for events without a Table source\n// (e.g. 'app.started', 'request.error').\nexport interface VelnEvents {}\n\nexport type EventBusErrorHandler = (event: string, error: unknown) => void\n\nexport interface EventBusOptions {\n /** Called when an event handler throws. Defaults to console.error. */\n onError?: EventBusErrorHandler\n}\n\n/**\n * EventBusAdapter — minimal interface for event bus implementations.\n *\n * Default: InMemoryEventBus (single-process, zero latency)\n *\n * For multi-worker deployments: BroadcastChannelAdapter (@oakbun/broadcast, roadmap)\n * For multi-server deployments: RedisAdapter (@oakbun/redis, roadmap)\n *\n * NOTE: EventBus is single-process by default. Events fired on instance A\n * will NOT reach instance B without a distributed adapter.\n */\nexport interface EventBusAdapter {\n on(event: string, handler: (payload: unknown) => void): void\n emit(event: string, payload: unknown): Promise<void>\n}\n\nexport class InMemoryEventBus {\n private readonly handlers = new Map<string, EventHandler[]>()\n private readonly _onError: EventBusErrorHandler\n\n constructor(options?: EventBusOptions) {\n this._onError = options?.onError ??\n ((event, err) => console.error(`[EventBus] Error in handler for \"${event}\":`, err))\n }\n\n // Typed overload for events declared via VelnEvents Declaration Merging\n on<K extends keyof VelnEvents>(\n event: K,\n handler: (payload: VelnEvents[K], ctx: unknown) => Promise<void> | void,\n ): this\n // String fallback — Phase 4 will add a Table-reference overload here that uses\n // InferTableEvents<T, M> directly, making Declaration Merging unnecessary for\n // Table-derived events.\n on(event: string, handler: EventHandler): this\n on(event: string, handler: EventHandler): this {\n if (!this.handlers.has(event)) this.handlers.set(event, [])\n this.handlers.get(event)!.push(handler)\n return this\n }\n\n // _emit — internal. fire & forget — errors in handlers are caught by onError, never thrown.\n // Only HookExecutor and flush() call this. Underscore signals \"not for user-code\".\n _emit(event: string, payload: unknown, ctx: unknown): void {\n const handlers = this.handlers.get(event) ?? []\n for (const h of handlers) {\n // Wrap in Promise constructor to catch both sync throws and async rejections\n new Promise<void>((resolve) => resolve(h(payload, ctx) as void)).catch((err) =>\n this._onError(event, err)\n )\n }\n }\n\n // EventBusAdapter.emit — ctx-free emit for external adapter compatibility.\n // Calls _emit with undefined ctx — handlers that need ctx are registered via on() directly.\n async emit(event: string, payload: unknown): Promise<void> {\n this._emit(event, payload, undefined)\n }\n\n // flush pending events after transaction commit\n async flush(events: PendingEvent[], ctx: unknown): Promise<void> {\n for (const e of events) {\n this._emit(e.name, e.payload, ctx)\n }\n }\n}\n\n/** @deprecated Use InMemoryEventBus instead. EventBus will be removed in a future version. */\nexport const EventBus = InMemoryEventBus\nexport type EventBus = InMemoryEventBus\n","export class VelnError extends Error {\n constructor(\n message: string,\n readonly status: number,\n readonly code: string,\n ) {\n super(message)\n this.name = 'VelnError'\n }\n}\n\nexport class BadRequestError extends VelnError {\n constructor(message = 'Bad Request', code = 'BAD_REQUEST') {\n super(message, 400, code)\n this.name = 'BadRequestError'\n }\n}\n\nexport class UnauthorizedError extends VelnError {\n constructor(message = 'Unauthorized', code = 'UNAUTHORIZED') {\n super(message, 401, code)\n this.name = 'UnauthorizedError'\n }\n}\n\nexport class ForbiddenError extends VelnError {\n constructor(message = 'Forbidden', code = 'FORBIDDEN') {\n super(message, 403, code)\n this.name = 'ForbiddenError'\n }\n}\n\nexport class NotFoundError extends VelnError {\n constructor(message = 'Not Found', code = 'NOT_FOUND') {\n super(message, 404, code)\n this.name = 'NotFoundError'\n }\n}\n\nexport class ConflictError extends VelnError {\n constructor(message = 'Conflict', code = 'CONFLICT') {\n super(message, 409, code)\n this.name = 'ConflictError'\n }\n}\n\nexport class UnprocessableError extends VelnError {\n constructor(message = 'Unprocessable Entity', code = 'UNPROCESSABLE') {\n super(message, 422, code)\n this.name = 'UnprocessableError'\n }\n}\n\nexport class TooManyRequestsError extends VelnError {\n constructor(message = 'Too Many Requests', code = 'TOO_MANY_REQUESTS') {\n super(message, 429, code)\n this.name = 'TooManyRequestsError'\n }\n}\n\nexport class InternalError extends VelnError {\n constructor(message = 'Internal Server Error', code = 'INTERNAL_ERROR') {\n super(message, 500, code)\n this.name = 'InternalError'\n }\n}\n","import type { Logger, LogOptions } from './types'\n\n// ── LogLevel ──────────────────────────────────────────────────────────────────\n\nexport type LogLevel = 'debug' | 'info' | 'warn' | 'error'\n\nconst LEVEL_ORDER: Record<LogLevel, number> = {\n debug: 0,\n info: 1,\n warn: 2,\n error: 3,\n}\n\n// ── ANSI ──────────────────────────────────────────────────────────────────────\n\nconst RESET = '\\x1b[0m'\nconst DIM = '\\x1b[2m'\n\nconst SCOPE_COLORS: Record<string, string> = {\n service: '\\x1b[34m', // Blue\n model: '\\x1b[36m', // Cyan\n plugin: '\\x1b[35m', // Magenta\n cron: '\\x1b[33m', // Yellow\n guard: '\\x1b[31m', // Red\n middleware: '\\x1b[32m', // Green\n event: '\\x1b[38;5;208m', // Orange\n module: '\\x1b[34m', // Blue\n resource: '\\x1b[36m', // Cyan\n}\n\nconst LEVEL_COLORS: Record<LogLevel, string> = {\n debug: '\\x1b[2m', // Dim\n info: '', // No extra color — scope is enough\n warn: '\\x1b[33m', // Yellow\n error: '\\x1b[31m', // Red\n}\n\n// TTY detection — no ANSI in pipes/files\nconst isTTY: boolean = process.stdout.isTTY ?? false\n\nfunction colorScope(scope: string): string {\n if (!isTTY) return `[${scope}]`\n const prefix = scope.split(':')[0]\n const color = SCOPE_COLORS[prefix] ?? ''\n return `${color}[${scope}]${RESET}`\n}\n\nfunction formatData(\n data: Record<string, unknown>,\n maskKeys: Set<string>,\n): string {\n const entries = Object.entries(data)\n if (entries.length === 0) return ''\n\n const masked: Array<[string, unknown]> = entries.map(([k, v]) => [\n k,\n maskKeys.has(k.toLowerCase()) ? '***' : v,\n ])\n\n if (masked.length <= 3) {\n const inline = masked\n .map(([k, v]) => (isTTY ? `${DIM}${k}${RESET}=${JSON.stringify(v)}` : `${k}=${JSON.stringify(v)}`))\n .join(' ')\n return ` ${inline}`\n }\n\n const lines = masked\n .map(([k, v]) => (isTTY ? ` ${DIM}${k}${RESET}=${JSON.stringify(v)}` : ` ${k}=${JSON.stringify(v)}`))\n .join('\\n')\n return `\\n${lines}`\n}\n\n// ── createMinimalLogger ───────────────────────────────────────────────────────\n// Pure console-based logger — no @veln/logger dependency.\n// Used by defineService (.options({ log })), defineModel (.options({ log })),\n// and defineCron (.options({ log })) when no external logger plugin is registered.\n\nexport function createMinimalLogger(scope: string, opts?: LogOptions): Logger {\n if (opts?.silent) return noopLogger()\n\n const minLevel = LEVEL_ORDER[opts?.level ?? 'info']\n const maskKeys = new Set((opts?.mask ?? []).map((k) => k.toLowerCase()))\n const scopeLabel = colorScope(scope)\n\n function log(method: LogLevel, msg: string, args: unknown[]): void {\n if (LEVEL_ORDER[method] < minLevel) return\n\n // Extract first object arg as structured data\n const [first, ...rest] = args\n const isDataObj =\n first !== null &&\n first !== undefined &&\n typeof first === 'object' &&\n !Array.isArray(first)\n\n const dataStr = isDataObj\n ? formatData(first as Record<string, unknown>, maskKeys)\n : ''\n\n const levelColor = isTTY ? LEVEL_COLORS[method] : ''\n const msgPart = levelColor ? `${levelColor}${msg}${RESET}` : msg\n const line = `${scopeLabel} ${msgPart}${dataStr}`\n\n // Remaining args (beyond the first data object) appended as-is\n const extra = isDataObj ? rest : args\n\n if (method === 'error') {\n console.error(line, ...extra)\n } else if (method === 'warn') {\n console.warn(line, ...extra)\n } else {\n console.log(line, ...extra)\n }\n }\n\n return {\n info(msg: string, ...args: unknown[]) { log('info', msg, args) },\n warn(msg: string, ...args: unknown[]) { log('warn', msg, args) },\n error(msg: string, ...args: unknown[]) { log('error', msg, args) },\n debug(msg: string, ...args: unknown[]) { log('debug', msg, args) },\n }\n}\n\nfunction noopLogger(): Logger {\n return {\n debug: () => {},\n info: () => {},\n warn: () => {},\n error: () => {},\n }\n}\n","import type { EventBus, VelnEvents } from '../events/index'\nimport type { BoundVelnDB } from '../db/index'\nimport type { ZodTypeAny, ZodIssue } from 'zod'\nimport { VelnError } from '../errors/index'\nimport { createMinimalLogger } from './logger'\n\n// ── VelnWsAdapter — extension point for @veln/ws ─────────────────────────────\n// Core holds only this minimal interface. @veln/ws provides the full implementation.\n// Registered via app.registerWsAdapter(adapter).\nexport interface VelnWsAdapter {\n /** Called in fetch() when an HTTP Upgrade: websocket request arrives. */\n handleUpgrade(\n req: Request,\n server: import('bun').Server<unknown>,\n baseCtx: BaseCtx,\n plugins: ReadonlyArray<import('./plugin').Plugin<any, any>>,\n installedPlugins: { value: boolean },\n installedModulePlugins: Set<string>,\n ): Promise<Response | null>\n /** Returns the Bun websocket handler config. Passed to Bun.serve(). */\n getWebsocketConfig(): import('bun').WebSocketHandler<Record<string, unknown>>\n /** Registers a WS route. Called from app.ws() and app.register(). */\n registerRoute(path: string, route: WsRouteShape): void\n /** Reads all registered WS routes — used by module registration. */\n getRoute(path: string): WsRouteShape | undefined\n}\n\n/** Minimal WS route shape that Core knows about. Full type lives in @veln/ws. */\nexport interface WsRouteShape {\n path: string\n _module: unknown | null\n [key: string]: unknown\n}\n\n\n// ── Auth Payload ──────────────────────────────────────────────────────────────\n// Minimal JWT/session payload shape used by WsCtx and plugins.\n// @veln/jwt re-exports this as JwtPayload for backward compatibility.\nexport interface AuthPayload {\n sub?: string\n iat?: number\n exp?: number\n nbf?: number\n aud?: string | string[]\n iss?: string\n jti?: string\n [key: string]: unknown\n}\n\n// Key-Format: 'GET /users/:id'\nexport type RouteKey = `${'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE'} /${string}`\n\nexport interface RouteEntry {\n params?: ZodTypeAny\n query?: ZodTypeAny\n body?: ZodTypeAny\n response?: ZodTypeAny\n // Phantom field — carries the module prefix so InferProxyClient can group routes.\n // Never set at runtime. Only present when registered via defineModule().\n readonly _prefix?: string\n}\n\nexport type RouteMap = Record<RouteKey, RouteEntry>\n\n// ValidationError — thrown by validation middleware, caught by error cascade\nexport class ValidationError extends VelnError {\n readonly issues: ZodIssue[]\n\n constructor(zodError: import('zod').ZodError) {\n super('Validation failed', 422, 'VALIDATION_ERROR')\n this.name = 'ValidationError'\n this.issues = zodError.issues\n }\n}\n\n// Route Schema — all fields optional\nexport interface RouteSchema {\n params?: ZodTypeAny\n query?: ZodTypeAny\n body?: ZodTypeAny\n response?: ZodTypeAny // runtime no-op in Phase 4a — used by Phase 4b RPC Client\n}\n\n/** Additional response code definition for OpenAPI docs (e.g. 401, 404). */\nexport interface RouteResponseDoc {\n description: string\n}\n\n// RouteDocs — optional OpenAPI documentation override per route\nexport interface RouteDocs {\n /** Human-readable route summary shown in Scalar / Swagger UI. Auto-generated if absent. */\n summary?: string\n /** Longer description rendered below the summary. Markdown supported. */\n description?: string\n /** Unique operationId. Auto-generated if absent (e.g. \"listUsers\", \"getUserById\"). */\n operationId?: string\n /**\n * Additional HTTP response codes to document in the OpenAPI spec.\n * The 200 success response is always generated automatically.\n * Use this to document error responses like 401, 403, 404, 422, etc.\n *\n * @example\n * docs: {\n * responses: {\n * 401: { description: 'Unauthorized' },\n * 404: { description: 'Not found' },\n * }\n * }\n */\n responses?: Record<number, RouteResponseDoc>\n}\n\n// Typed ctx when schemas are defined\nexport type InferCtx<TCtx, S extends RouteSchema> = Omit<TCtx, 'params' | 'query'> & {\n params: S['params'] extends ZodTypeAny ? import('zod').infer<S['params']> : Record<string, string>\n query: S['query'] extends ZodTypeAny ? import('zod').infer<S['query']> : Record<string, string | string[]>\n body: S['body'] extends ZodTypeAny ? import('zod').infer<S['body']> : unknown\n}\n\n// Extended RouteHandler — supports optional schema\nexport interface RouteHandlerWithSchema<TCtx, S extends RouteSchema> {\n params?: S['params']\n query?: S['query']\n body?: S['body']\n response?: S['response']\n /** Optional OpenAPI documentation override for this route. */\n docs?: RouteDocs\n /** Optional route-level guard — runs before the handler. Use `false` to opt out of a module-level guard. */\n guard?: Guard<TCtx> | false\n handler: (ctx: InferCtx<TCtx, S>) => Response | Promise<Response>\n}\n\n// ─── Streaming Support ────────────────────────────────────────────────────────\n\n/** Controls a streaming response. Passed to the ctx.stream() writer callback. */\nexport interface StreamController {\n /** Push a string or binary chunk to the stream. */\n send(chunk: string | Uint8Array): void\n /** Close the stream. Must be called to end the response. */\n close(): void\n}\n\n/** Options for ctx.stream(). */\nexport interface StreamOptions {\n /**\n * Content-Type header for the streaming response.\n * Defaults to `'text/plain'`.\n * Use `'text/event-stream'` for SSE, `'application/x-ndjson'` for NDJSON.\n */\n contentType?: string\n /** Additional headers to include in the response. */\n headers?: Record<string, string>\n /** HTTP status code. Defaults to 200. */\n status?: number\n}\n\n// ─── SSE Support ──────────────────────────────────────────────────────────────\n\n/**\n * Controls a Server-Sent Events stream.\n * Passed to the ctx.sse() writer callback.\n *\n * SSE wire format:\n * event: <name>\\ndata: <json>\\n\\n — named event\n * data: <json>\\n\\n — unnamed event\n * : <text>\\n\\n — comment / keepalive\n * id: <value>\\n — event ID for reconnect\n * retry: <ms>\\n — reconnect interval\n */\nexport interface SseController {\n /** Send a named event with a JSON-serializable payload. */\n event(name: string, data: unknown): Promise<void>\n /** Send an unnamed data event. */\n data(data: unknown): Promise<void>\n /** Send an SSE comment (e.g. keepalive ping). */\n comment(text?: string): Promise<void>\n /** Set the last event ID (used by the browser for reconnect). */\n id(id: string): Promise<void>\n /** Tell the browser how long to wait before reconnecting (milliseconds). */\n retry(ms: number): Promise<void>\n}\n\n// Logger interface — no external dependency\nexport interface Logger {\n info(msg: string, ...args: unknown[]): void\n warn(msg: string, ...args: unknown[]): void\n error(msg: string, ...args: unknown[]): void\n debug(msg: string, ...args: unknown[]): void\n}\n\n// LogOptions — controls the minimal logger behaviour across all define* builders\nexport interface LogOptions {\n /** Minimum level to emit. Defaults to 'info'. */\n level?: 'debug' | 'info' | 'warn' | 'error'\n /** Keys whose values are replaced with '***' in structured data. Case-insensitive. */\n mask?: string[]\n /** Suppress all output — useful in tests. */\n silent?: boolean\n}\n\n// BaseOptions — base for all define* builder .options() calls\nexport interface BaseOptions {\n log?: LogOptions\n}\n\n// ── AuthAdapter — minimal auth interface ──────────────────────────────────────\n// Core only knows this interface. The concrete implementation lives in @oakbun/auth.\n// Passed to createApp({ auth }) — if omitted the app works without auth.\n\nexport interface AuthUser {\n id: string\n permissions: string[]\n}\n\nexport interface AuthAdapter {\n getUser(ctx: BaseCtx): Promise<AuthUser | null>\n hasPermission(user: AuthUser, permission: string): boolean\n}\n\n// ── BaseCtx — available in every request handler ──────────────────────────────\n// ctx.events is optional — only present when eventBusPlugin() is registered\n// ctx.db is optional — only present when dbPlugin() is registered\n// ctx.logger is optional — only present when loggerPlugin() is registered\nexport interface BaseCtx {\n req: Request\n params: Record<string, string>\n query: Record<string, string | string[]>\n body?: unknown // populated by validation middleware when body schema is defined\n json: <T>(data: T, status?: number) => Response\n text: (data: string, status?: number) => Response\n html: (data: string, status?: number) => Response\n /**\n * Returns a streaming Response backed by a ReadableStream.\n *\n * The callback receives a StreamController — call `send(chunk)` to push data\n * and `close()` to end the stream. Errors thrown inside are caught automatically.\n *\n * Set `contentType` for SSE (`'text/event-stream'`) or NDJSON (`'application/x-ndjson'`).\n * Compression is automatically skipped for streaming responses.\n *\n * @example\n * return ctx.stream((stream) => {\n * stream.send('data: hello\\n\\n')\n * stream.send('data: world\\n\\n')\n * stream.close()\n * }, { contentType: 'text/event-stream' })\n */\n stream: (\n writer: (controller: StreamController) => void | Promise<void>,\n options?: StreamOptions,\n ) => Response\n /**\n * Returns a Server-Sent Events Response.\n *\n * The callback receives an SseController — call `event()`, `data()`,\n * `comment()`, `id()`, or `retry()` to push SSE frames, then let the\n * callback return (or the async iterator complete) to close the stream.\n *\n * @example\n * return ctx.sse(async (sse) => {\n * await sse.event('connected', { userId: '42' })\n * for await (const update of source()) {\n * await sse.event('update', update)\n * await sse.comment('keepalive')\n * }\n * })\n */\n sse: (writer: (controller: SseController) => void | Promise<void>) => Response\n events?: EventBus\n logger?: Logger\n db?: BoundVelnDB\n cookie: import('./cookies').CookieJar\n // Typed event emission into the per-request RequestEventQueue.\n // Fire & forget — buffered until after onResponse, then flushed to EventBus.\n emit: <K extends keyof VelnEvents>(event: K, payload: VelnEvents[K]) => void\n // _requestQueue: framework-internal. Set by fetch() before plugins run.\n // dbPlugin reads it to bind the queue to BoundVelnDB.\n // Never exposed to user-land handlers — prefixed _ to signal framework-only.\n _requestQueue?: import('../events/index').RequestEventQueue\n // _queryLog: framework-internal. Set by fetch() when N+1 detection is enabled.\n // dbPlugin reads it and passes it to BoundVelnDB to count queries per request.\n // Never exposed to user-land handlers — prefixed _ to signal framework-only.\n _queryLog?: import('../db/index').QueryLog\n // _startTime: optional timing field, set by timing middleware.\n _startTime?: number\n}\n\n// Guard — pure predicate, never extends ctx\nexport type Guard<TCtx> = (ctx: TCtx) => Response | null | Promise<Response | null>\n\n// createGuard — typing helper. TAdd is the ctx extension the guard needs.\n// BaseCtx is always present — user only declares what they add on top.\n// @deprecated Use defineGuard() for the fluent builder API.\nexport function createGuard<TAdd extends object = object>(\n fn: (ctx: BaseCtx & TAdd) => Response | null | Promise<Response | null>,\n): Guard<BaseCtx & TAdd> {\n return fn\n}\n\n// ── defineGuard — fluent builder ──────────────────────────────────────────────\n\n/**\n * defineGuard — creates a named guard that protects routes or modules.\n *\n * Call `.check(fn)` to seal into a `Guard`. Throw any error or return a `Response`\n * inside `fn` to block the request; return normally to allow it through.\n *\n * @param name Used in log output for tracing which guard triggered.\n *\n * @example\n * const authGuard = defineGuard('auth')\n * .check<{ user: AuthUser }>((ctx) => {\n * if (!ctx.user) throw new UnauthorizedError()\n * })\n */\nclass GuardBuilder {\n private _options: BaseOptions = {}\n\n constructor(private readonly _name: string) {}\n\n options(opts: BaseOptions): this {\n this._options = opts\n return this\n }\n\n check<TAdd extends object = object>(\n fn: (ctx: BaseCtx & TAdd) => void | Promise<void>,\n ): Guard<BaseCtx & TAdd> {\n const logger = createMinimalLogger(`guard:${this._name}`, this._options.log)\n const name = this._name\n return async (ctx: BaseCtx & TAdd): Promise<Response | null> => {\n logger.debug('check', { guard: name })\n try {\n await fn(ctx)\n return null\n } catch (err) {\n logger.warn('blocked', { guard: name })\n throw err\n }\n }\n }\n}\n\n/** @see GuardBuilder */\nexport function defineGuard(name: string): GuardBuilder {\n return new GuardBuilder(name)\n}\n\n// ErrorHandler\nexport type ErrorHandler<TCtx = BaseCtx> = (err: unknown, ctx: TCtx) => Response | Promise<Response>\n\n// Route handler — object style so Phase 4 can add body/params/query schemas non-breakingly\nexport interface RouteHandler<TCtx> {\n handler: (ctx: TCtx) => Response | Promise<Response>\n}\n\n// ─── Lifecycle Hook Types ──────────────────────────────────────────────────────\n//\n// Three distinct phases — framework always runs them in this order regardless\n// of registration order:\n// 1. onRequest — fires before plugins; always runs (even on guard block / plugin error)\n// 2. onBeforeHandle — fires after guards pass; skipped when a guard blocks\n// 3. onResponse — fires after handler (or after error); always runs\n//\n// TCtx for onRequest is BaseCtx (plugins not yet applied).\n// TCtx for onBeforeHandle / onResponse is the full ctx including plugin extensions.\n\n// onRequest: receives raw BaseCtx — plugins have NOT run yet.\n// Return a Response to short-circuit (replaces 404 / guard / handler entirely).\n// Return void to continue.\nexport type OnRequestFn<TCtx extends BaseCtx = BaseCtx> = (\n ctx: TCtx,\n) => Response | void | Promise<Response | void>\n\n// onBeforeHandle: runs after guards pass, before handler.\n// Return a Response to short-circuit the handler.\n// Return void to continue.\nexport type OnBeforeHandleFn<TCtx extends BaseCtx = BaseCtx> = (\n ctx: TCtx,\n) => Response | void | Promise<Response | void>\n\n// onResponse: always runs; receives the final response (or undefined on plugin/guard error\n// before a response was produced — framework provides a 500 fallback in that case).\n// Return a new Response to replace it, or void to keep the current response.\nexport type OnResponseFn<TCtx extends BaseCtx = BaseCtx> = (\n ctx: TCtx,\n response: Response,\n) => Response | void | Promise<Response | void>\n\n// Tagged wrappers — distinguishable from plain functions at runtime\nexport interface OnRequestHook<TCtx extends BaseCtx = BaseCtx> {\n readonly _phase: 'onRequest'\n readonly _fn: OnRequestFn<TCtx>\n}\n\nexport interface OnBeforeHandleHook<TCtx extends BaseCtx = BaseCtx> {\n readonly _phase: 'onBeforeHandle'\n readonly _fn: OnBeforeHandleFn<TCtx>\n}\n\nexport interface OnResponseHook<TCtx extends BaseCtx = BaseCtx> {\n readonly _phase: 'onResponse'\n readonly _fn: OnResponseFn<TCtx>\n}\n\n// ─── createX helpers ──────────────────────────────────────────────────────────\n// TAdd is the ctx extension needed; user doesn't write BaseCtx & TAdd\n\nexport function createOnRequest<TAdd extends object = object>(\n fn: OnRequestFn<BaseCtx & TAdd>,\n): OnRequestHook<BaseCtx & TAdd> {\n return { _phase: 'onRequest', _fn: fn }\n}\n\nexport function createOnBeforeHandle<TAdd extends object = object>(\n fn: OnBeforeHandleFn<BaseCtx & TAdd>,\n): OnBeforeHandleHook<BaseCtx & TAdd> {\n return { _phase: 'onBeforeHandle', _fn: fn }\n}\n\nexport function createOnResponse<TAdd extends object = object>(\n fn: OnResponseFn<BaseCtx & TAdd>,\n): OnResponseHook<BaseCtx & TAdd> {\n return { _phase: 'onResponse', _fn: fn }\n}\n\n// Internal route record\nexport interface Route<TCtx = BaseCtx> {\n method: 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE'\n path: string // e.g. '/users/:id'\n summary?: string\n description?: string\n /** OpenAPI documentation override set via the `docs` option on route registration. */\n docs?: RouteDocs\n handler: RouteHandler<TCtx>\n guards: Guard<TCtx>[]\n onError?: ErrorHandler<TCtx>\n schema?: RouteSchema\n visibility?: 'public' | 'hidden'\n // Set when the route definition has guard: false — skips module-level guards for this route.\n moduleGuardOptOut?: true\n // Reference to the module this route belongs to (set during registration)\n _module?: import('./module').VelnModule\n // Plugin that contributed this route via .modules() — set by app.plugin() so the\n // permission check in _runRoute can look up the right plugin without a separate Map.\n _pluginName?: string\n}\n","import type { BindingValue } from '../adapter/types'\nimport type { TableDef, SchemaMap } from '../schema/table'\nimport type { Column } from '../schema/column'\nimport { VelnError } from '../errors/index'\n\n// ── SubqueryResult ────────────────────────────────────────────────────────────\n\n/**\n * Phantom-typed wrapper for a subquery SQL fragment.\n * Col and T are used only at compile time — _phantom is never read at runtime.\n *\n * Produced by SelectBuilder.columns(col).subquery().\n * Accepted by WhereOp IN / NOT IN in place of an array.\n */\nexport interface SubqueryResult<Col extends string, T> {\n readonly _sql: string\n readonly _params: BindingValue[]\n readonly _phantom: { col: Col; type: T }\n}\n\n/**\n * Build a SubqueryResult from a complete SELECT SQL string + params.\n * Wraps the SQL in parentheses (required by SQL syntax).\n *\n * The T generic is a phantom — it is never instantiated at runtime.\n * The only permitted cast in this file is `undefined as unknown as T`.\n */\nexport function buildSubquery<Col extends string, T>(\n sql: string,\n params: BindingValue[],\n col: Col,\n): SubqueryResult<Col, T> {\n if (!sql) throw new Error('buildSubquery: sql must not be empty')\n return {\n _sql: `(${sql})`,\n _params: params,\n _phantom: { col, type: undefined as unknown as T },\n }\n}\n\n// ── JOIN types ────────────────────────────────────────────────────────────────\n\nexport interface JoinClause {\n type: 'INNER' | 'LEFT' | 'RIGHT' | 'FULL'\n table: string\n on: string\n}\n\n// ── validateAndQuoteOnClause ──────────────────────────────────────────────────\n// Validates and quotes a JOIN ON clause to prevent SQL injection.\n// Only allows the format: word.word = word.word (table.column = table.column)\n// Throws VelnError(500, INVALID_JOIN_ON) for anything that doesn't match.\n\nconst ON_CLAUSE_PATTERN = /^([\\w]+)\\.([\\w]+)\\s*=\\s*([\\w]+)\\.([\\w]+)$/\n\nexport function validateAndQuoteOnClause(on: string): string {\n const trimmed = on.trim()\n const match = ON_CLAUSE_PATTERN.exec(trimmed)\n if (!match) {\n throw new VelnError(\n `Invalid JOIN ON clause: \"${on}\". Must be in format \"table.column = table.column\"`,\n 500,\n 'INVALID_JOIN_ON',\n )\n }\n const [, t1, c1, t2, c2] = match\n return `\"${t1}\".\"${c1}\" = \"${t2}\".\"${c2}\"`\n}\n\n// ── WHERE operator types ──────────────────────────────────────────────────────\n\n/** SQL dialect — used for ILIKE fallback on non-Postgres adapters. */\nexport type SqlDialect = 'sqlite' | 'postgres' | 'mysql'\n\n/** Accepted value for IN / NOT IN — either a plain array or a typed subquery. */\nexport type InValue<T> = T[] | SubqueryResult<string, T>\n\n/** Explicit operator condition for a single column. */\nexport type WhereOp<T> =\n | { op: '='; value: T }\n | { op: '!='; value: T }\n | { op: '>'; value: T }\n | { op: '>='; value: T }\n | { op: '<'; value: T }\n | { op: '<='; value: T }\n | { op: 'IN'; value: InValue<T> }\n | { op: 'NOT IN'; value: InValue<T> }\n | { op: 'LIKE'; value: string }\n | { op: 'ILIKE'; value: string }\n | { op: 'IS NULL' }\n | { op: 'IS NOT NULL' }\n\n/** Per-field condition — shorthand (plain value = equality) or explicit operator. */\nexport type FieldCondition<T> = T | WhereOp<T>\n\n/** Map of column conditions — each field is optional. */\nexport type WhereConditions<TRow> = {\n [K in keyof TRow]?: FieldCondition<TRow[K]>\n}\n\n/**\n * Full WHERE input — either a flat conditions map, OR-group, or AND-group.\n * OR/AND values are recursively WhereInput allowing nesting.\n */\nexport type WhereInput<TRow> =\n | WhereConditions<TRow>\n | { OR: WhereInput<TRow>[] }\n | { AND: WhereInput<TRow>[] }\n\n// ── Helpers ────────────────────────────────────────────────────────────────\n\n/**\n * Filter out undefined values from a record.\n * null is a valid BindingValue and is kept.\n */\nfunction filterDefined(data: Record<string, unknown>): [string, BindingValue][] {\n return Object.entries(data).filter(\n (entry): entry is [string, BindingValue] => entry[1] !== undefined,\n )\n}\n\n/** Type guard: is the value a WhereOp object (has an `op` string key)? */\nfunction isWhereOp(val: unknown): val is WhereOp<unknown> {\n return typeof val === 'object' && val !== null && 'op' in val && typeof (val as Record<string, unknown>)['op'] === 'string'\n}\n\n/** Type guard: is the value a SubqueryResult (has _sql + _params fields)? */\nfunction isSubqueryResult(val: unknown): val is SubqueryResult<string, unknown> {\n return (\n typeof val === 'object' &&\n val !== null &&\n '_sql' in val &&\n '_params' in val\n )\n}\n\n/**\n * Compile a single column + condition into SQL fragment + params.\n * Handles all WhereOp variants and the shorthand equality case.\n */\nfunction buildFieldCondition(\n key: string,\n condition: unknown,\n dialect: SqlDialect,\n): { sql: string; params: BindingValue[] } {\n if (!isWhereOp(condition)) {\n // Shorthand: plain value → equality\n return { sql: `\"${key}\" = ?`, params: [condition as BindingValue] }\n }\n\n const op = condition as WhereOp<unknown>\n\n switch (op.op) {\n case '=':\n return { sql: `\"${key}\" = ?`, params: [op.value as BindingValue] }\n case '!=':\n return { sql: `\"${key}\" != ?`, params: [op.value as BindingValue] }\n case '>':\n return { sql: `\"${key}\" > ?`, params: [op.value as BindingValue] }\n case '>=':\n return { sql: `\"${key}\" >= ?`, params: [op.value as BindingValue] }\n case '<':\n return { sql: `\"${key}\" < ?`, params: [op.value as BindingValue] }\n case '<=':\n return { sql: `\"${key}\" <= ?`, params: [op.value as BindingValue] }\n case 'IN': {\n const inVal = op.value as InValue<unknown>\n if (isSubqueryResult(inVal)) {\n return { sql: `\"${key}\" IN ${inVal._sql}`, params: inVal._params }\n }\n const vals = inVal as unknown[]\n if (vals.length === 0) {\n // IN () is invalid SQL — use a false literal so no rows match\n return { sql: '1 = 0', params: [] }\n }\n const placeholders = vals.map(() => '?').join(', ')\n return { sql: `\"${key}\" IN (${placeholders})`, params: vals as BindingValue[] }\n }\n case 'NOT IN': {\n const inVal = op.value as InValue<unknown>\n if (isSubqueryResult(inVal)) {\n return { sql: `\"${key}\" NOT IN ${inVal._sql}`, params: inVal._params }\n }\n const vals = inVal as unknown[]\n if (vals.length === 0) {\n // NOT IN () matches everything — use a true literal\n return { sql: '1 = 1', params: [] }\n }\n const placeholders = vals.map(() => '?').join(', ')\n return { sql: `\"${key}\" NOT IN (${placeholders})`, params: vals as BindingValue[] }\n }\n case 'LIKE':\n return { sql: `\"${key}\" LIKE ?`, params: [op.value as BindingValue] }\n case 'ILIKE':\n if (dialect === 'postgres') {\n return { sql: `\"${key}\" ILIKE ?`, params: [op.value as BindingValue] }\n }\n // SQLite / MySQL fallback: LOWER(col) LIKE LOWER(?)\n return { sql: `LOWER(\"${key}\") LIKE LOWER(?)`, params: [op.value as BindingValue] }\n case 'IS NULL':\n return { sql: `\"${key}\" IS NULL`, params: [] }\n case 'IS NOT NULL':\n return { sql: `\"${key}\" IS NOT NULL`, params: [] }\n }\n}\n\n// ── Pure SQL generation functions (SQLite dialect — ? as placeholder) ──────\n\n/**\n * Build a WHERE clause from a WhereInput.\n *\n * Supports:\n * - Shorthand equality: { name: 'Alice' } → \"name\" = ?\n * - Explicit operator: { age: { op: '>=', value: 18 } }\n * - IN / NOT IN: { id: { op: 'IN', value: [1,2,3] } }\n * - IS NULL / IS NOT NULL\n * - LIKE / ILIKE (ILIKE falls back to LOWER() on SQLite/MySQL)\n * - OR groups: { OR: [{ role: 'admin' }, { role: 'mod' }] }\n * - AND groups: { AND: [...] }\n * - Nested OR/AND\n *\n * Returns { sql: '', params: [] } for empty / all-undefined conditions.\n */\nexport function buildWhere(\n conditions: WhereInput<Record<string, unknown>>,\n dialect: SqlDialect = 'sqlite',\n): { sql: string; params: BindingValue[] } {\n // OR group\n if ('OR' in conditions && Array.isArray((conditions as { OR: unknown }).OR)) {\n const branches = (conditions as { OR: WhereInput<Record<string, unknown>>[] }).OR\n const parts: string[] = []\n const params: BindingValue[] = []\n for (const branch of branches) {\n const { sql, params: p } = buildWhere(branch, dialect)\n if (sql) {\n parts.push(sql)\n params.push(...p)\n }\n }\n if (parts.length === 0) return { sql: '', params: [] }\n if (parts.length === 1) return { sql: parts[0]!, params }\n return { sql: `(${parts.join(' OR ')})`, params }\n }\n\n // AND group\n if ('AND' in conditions && Array.isArray((conditions as { AND: unknown }).AND)) {\n const branches = (conditions as { AND: WhereInput<Record<string, unknown>>[] }).AND\n const parts: string[] = []\n const params: BindingValue[] = []\n for (const branch of branches) {\n const { sql, params: p } = buildWhere(branch, dialect)\n if (sql) {\n parts.push(sql)\n params.push(...p)\n }\n }\n if (parts.length === 0) return { sql: '', params: [] }\n if (parts.length === 1) return { sql: parts[0]!, params }\n return { sql: `(${parts.join(' AND ')})`, params }\n }\n\n // Flat conditions map\n const entries = Object.entries(conditions).filter(([, v]) => v !== undefined)\n if (entries.length === 0) return { sql: '', params: [] }\n\n const sqlParts: string[] = []\n const params: BindingValue[] = []\n\n for (const [key, value] of entries) {\n const { sql, params: p } = buildFieldCondition(key, value, dialect)\n sqlParts.push(sql)\n params.push(...p)\n }\n\n return { sql: sqlParts.join(' AND '), params }\n}\n\n/**\n * Build an INSERT statement.\n * INSERT INTO \"table\" (\"col1\", \"col2\") VALUES (?, ?) RETURNING *\n *\n * RETURNING * (SQLite ≥ 3.35, PostgreSQL) returns the inserted row, avoiding\n * a second SELECT round-trip. Pass returning: false for databases that do not\n * support RETURNING (MySQL).\n */\nexport function buildInsert(\n tableName: string,\n data: Record<string, unknown>,\n returning = true,\n): { sql: string; params: BindingValue[] } {\n const entries = filterDefined(data)\n const cols = entries.map(([key]) => `\"${key}\"`).join(', ')\n const placeholders = entries.map(() => '?').join(', ')\n const params = entries.map(([, val]) => val)\n const returning_clause = returning ? ' RETURNING *' : ''\n const sql = `INSERT INTO \"${tableName}\" (${cols}) VALUES (${placeholders})${returning_clause}`\n return { sql, params }\n}\n\n/**\n * Build a multi-row INSERT statement.\n * INSERT INTO \"table\" (\"col1\", \"col2\") VALUES (?, ?), (?, ?) RETURNING *\n *\n * Column order is derived from rows[0] — all subsequent rows must have the same keys.\n * Pass returning: false for databases that do not support RETURNING (MySQL).\n * Throws if rows is empty or any row contains undefined values.\n */\nexport function buildInsertMany(\n tableName: string,\n rows: Record<string, BindingValue>[],\n returning = true,\n): { sql: string; params: BindingValue[] } {\n if (rows.length === 0) {\n throw new Error('insertMany: rows array must not be empty')\n }\n\n const columns = Object.keys(rows[0]!)\n const quotedCols = columns.map((c) => `\"${c}\"`).join(', ')\n const params: BindingValue[] = []\n const valueClauses: string[] = []\n\n for (const row of rows) {\n const placeholders: string[] = []\n for (const col of columns) {\n const val = row[col]\n if (val === undefined) {\n throw new Error(`insertMany: column \"${col}\" has undefined value — apply defaults before calling buildInsertMany`)\n }\n params.push(val)\n placeholders.push('?')\n }\n valueClauses.push(`(${placeholders.join(', ')})`)\n }\n\n const returning_clause = returning ? ' RETURNING *' : ''\n const sql = `INSERT INTO \"${tableName}\" (${quotedCols}) VALUES ${valueClauses.join(', ')}${returning_clause}`\n return { sql, params }\n}\n\n/**\n * Build a soft-delete or restore UPDATE statement.\n * UPDATE \"table\" SET \"col\" = ? [WHERE ...]\n *\n * value is the new column value: Date (serialized to ISO string) for soft delete,\n * null for restore.\n */\nexport function buildSoftDeleteUpdate(\n tableName: string,\n col: string,\n value: Date | null,\n where: WhereInput<Record<string, unknown>>,\n dialect: SqlDialect = 'sqlite',\n): { sql: string; params: BindingValue[] } {\n const serialized: BindingValue = value instanceof Date ? value.toISOString() : null\n const { sql: whereSql, params: whereParams } = buildWhere(where, dialect)\n const setSql = `\"${col}\" = ?`\n const sql = whereSql\n ? `UPDATE \"${tableName}\" SET ${setSql} WHERE ${whereSql}`\n : `UPDATE \"${tableName}\" SET ${setSql}`\n return { sql, params: [serialized, ...whereParams] }\n}\n\n/**\n * Build an UPDATE statement.\n * UPDATE \"table\" SET \"col1\" = ?, \"col2\" = ? WHERE \"pk\" = ?\n * The pk param is always last in params.\n */\nexport function buildUpdate(\n tableName: string,\n patch: Record<string, unknown>,\n pk: string,\n pkValue: BindingValue,\n): { sql: string; params: BindingValue[] } {\n const entries = filterDefined(patch)\n const sets = entries.map(([key]) => `\"${key}\" = ?`).join(', ')\n const params: BindingValue[] = [...entries.map(([, val]) => val), pkValue]\n const sql = `UPDATE \"${tableName}\" SET ${sets} WHERE \"${pk}\" = ?`\n return { sql, params }\n}\n\n/**\n * Build a DELETE statement.\n * DELETE FROM \"table\" WHERE \"pk\" = ?\n */\nexport function buildDelete(\n tableName: string,\n pk: string,\n pkValue: BindingValue,\n): { sql: string; params: BindingValue[] } {\n const sql = `DELETE FROM \"${tableName}\" WHERE \"${pk}\" = ?`\n return { sql, params: [pkValue] }\n}\n\n/**\n * Deserialize a raw DB row into the typed T shape.\n * Consolidated here to avoid duplication between SelectBuilder and InsertBuilder.\n * Handles TIMESTAMP columns: SQLite stores them as ISO strings, we convert back to Date.\n */\nexport function deserializeRow<T, S extends SchemaMap>(\n table: TableDef<T, S>,\n row: Record<string, unknown>,\n): T {\n const result: Record<string, unknown> = {}\n for (const [key, col] of Object.entries(table.schema)) {\n const c = col as Column<unknown>\n const raw = row[key]\n if (c.def.type === 'TIMESTAMP' && raw !== null && raw !== undefined) {\n result[key] = new Date(raw as string)\n } else {\n result[key] = raw\n }\n }\n return result as T\n}\n\n/** A single aggregate expression: FN(\"col\") AS alias. */\nexport interface AggregateClause {\n alias: string\n fn: 'COUNT' | 'SUM' | 'AVG' | 'MIN' | 'MAX'\n col?: string // undefined → COUNT(*)\n}\n\nexport interface SelectOptions {\n limit?: number\n offset?: number\n orderBy?: { col: string; dir: 'ASC' | 'DESC' }[]\n columns?: string[] // explicit column list — overrides SELECT *\n groupBy?: string[] // GROUP BY columns\n aggregates?: AggregateClause[] // aggregate expressions added to SELECT\n having?: WhereInput<Record<string, unknown>> // HAVING clause\n distinct?: boolean // SELECT DISTINCT when true\n}\n\n/** Build the SELECT column list from options. Exported for use in SelectBuilder's raw-where path. */\nexport function buildSelectListFromOptions(options?: SelectOptions): string {\n const cols: string[] = []\n\n // Explicit column selection\n if (options?.columns && options.columns.length > 0) {\n cols.push(...options.columns.map((c) => `\"${c}\"`))\n } else if (!options?.aggregates || options.aggregates.length === 0) {\n // No columns + no aggregates → SELECT *\n cols.push('*')\n } else if (options?.groupBy && options.groupBy.length > 0) {\n // Aggregates + GROUP BY → include the group-by columns so they appear in results\n cols.push(...options.groupBy.map((c) => `\"${c}\"`))\n } else {\n // Aggregates only (no groupBy columns) → e.g. SELECT COUNT(*)\n }\n\n // Aggregate expressions appended after regular columns\n if (options?.aggregates && options.aggregates.length > 0) {\n for (const agg of options.aggregates) {\n const colExpr = agg.col ? `\"${agg.col}\"` : '*'\n cols.push(`${agg.fn}(${colExpr}) AS \"${agg.alias}\"`)\n }\n }\n\n return cols.length > 0 ? cols.join(', ') : '*'\n}\n\n/** Append ORDER BY / LIMIT / OFFSET to parts[]. Shared between buildSelect paths. */\nfunction appendPaginationAndOrder(\n parts: string[],\n options?: SelectOptions,\n): void {\n if (options?.orderBy && options.orderBy.length > 0) {\n const clause = options.orderBy\n .map(({ col, dir }) => `\"${col}\" ${dir}`)\n .join(', ')\n parts.push(`ORDER BY ${clause}`)\n }\n\n // LIMIT and OFFSET are always non-negative integers supplied by framework code,\n // never from raw user input — safe to inline as literals.\n // SQLite does not support ? placeholders in LIMIT/OFFSET positions.\n // SQLite also requires LIMIT to precede OFFSET — if only offset is set,\n // use LIMIT -1 (SQLite's \"unlimited\" sentinel).\n if (options?.limit !== undefined || options?.offset !== undefined) {\n const limitVal = options?.limit !== undefined\n ? Math.trunc(Math.max(0, options.limit))\n : -1 // -1 = unlimited in SQLite/PostgreSQL/MySQL\n parts.push(`LIMIT ${limitVal}`)\n\n if (options?.offset !== undefined) {\n parts.push(`OFFSET ${Math.trunc(Math.max(0, options.offset))}`)\n }\n }\n}\n\n/**\n * Build a UNION or UNION ALL query from two or more SELECT SQL fragments.\n * Optionally appends ORDER BY + LIMIT to the combined query.\n *\n * Throws if fewer than 2 parts are provided.\n */\nexport function buildUnion(\n parts: Array<{ sql: string; params: BindingValue[] }>,\n kind: 'UNION' | 'UNION ALL',\n options: { orderBy?: { col: string; dir: 'ASC' | 'DESC' }; limit?: number } = {},\n): { sql: string; params: BindingValue[] } {\n if (parts.length < 2) {\n throw new Error('buildUnion: at least 2 parts required')\n }\n const sqls = parts.map((p) => p.sql)\n const params = parts.flatMap((p) => p.params)\n let sql = sqls.join(` ${kind} `)\n if (options.orderBy) {\n sql += ` ORDER BY \"${options.orderBy.col}\" ${options.orderBy.dir ?? 'ASC'}`\n }\n if (options.limit !== undefined) {\n sql += ` LIMIT ${Math.trunc(Math.max(0, options.limit))}`\n }\n return { sql, params }\n}\n\n/**\n * Build a SELECT statement.\n * SELECT [cols] FROM \"table\" [WHERE ...] [GROUP BY ...] [HAVING ...] [ORDER BY ...] [LIMIT n] [OFFSET n]\n */\nexport function buildSelect(\n tableName: string,\n conditions: WhereInput<Record<string, unknown>>,\n options?: SelectOptions,\n dialect: SqlDialect = 'sqlite',\n): { sql: string; params: BindingValue[] } {\n const selectList = buildSelectListFromOptions(options)\n const { sql: whereSql, params } = buildWhere(conditions, dialect)\n const selectKeyword = options?.distinct ? 'SELECT DISTINCT' : 'SELECT'\n\n const parts: string[] = [\n whereSql\n ? `${selectKeyword} ${selectList} FROM \"${tableName}\" WHERE ${whereSql}`\n : `${selectKeyword} ${selectList} FROM \"${tableName}\"`,\n ]\n\n // GROUP BY\n if (options?.groupBy && options.groupBy.length > 0) {\n parts.push(`GROUP BY ${options.groupBy.map((c) => `\"${c}\"`).join(', ')}`)\n }\n\n // HAVING — uses same buildWhere system as WHERE\n if (options?.having) {\n const { sql: havingSql, params: havingParams } = buildWhere(options.having, dialect)\n if (havingSql) {\n parts.push(`HAVING ${havingSql}`)\n params.push(...havingParams)\n }\n }\n\n appendPaginationAndOrder(parts, options)\n\n return { sql: parts.join(' '), params }\n}\n\n/**\n * Build a SELECT statement with JOIN clauses and a raw WHERE condition.\n *\n * columns — explicit column list (e.g. ['orders.id', 'users.name']); defaults to *\n * joins — ordered list of JOIN clauses\n * where — optional raw SQL fragment (e.g. 'orders.status = ?')\n * params — bind values for the where clause\n */\n// ── quoteColumnRef ────────────────────────────────────────────────────────────\n// Quotes a column reference: \"table\".\"column\", \"*\", or \"column\".\n\nfunction quoteColumnRef(col: string): string {\n if (col === '*') return '*'\n const dotIdx = col.indexOf('.')\n if (dotIdx !== -1) {\n const table = col.slice(0, dotIdx)\n const column = col.slice(dotIdx + 1)\n if (column === '*') return `\"${table}\".*`\n return `\"${table}\".\"${column}\"`\n }\n return `\"${col}\"`\n}\n\nexport function buildJoinSelect(\n tableName: string,\n columns: string[],\n joins: JoinClause[],\n where: string,\n params: BindingValue[],\n options?: SelectOptions,\n): { sql: string; params: BindingValue[] } {\n const cols = columns.length > 0\n ? columns.map(quoteColumnRef).join(', ')\n : '*'\n const parts: string[] = [`SELECT ${cols} FROM \"${tableName}\"`]\n\n for (const j of joins) {\n const quotedOn = validateAndQuoteOnClause(j.on)\n parts.push(`${j.type} JOIN \"${j.table}\" ON ${quotedOn}`)\n }\n\n if (where) parts.push(`WHERE ${where}`)\n\n // Mutable copy — no additional params needed (pagination uses literals)\n const allParams = [...params]\n\n appendPaginationAndOrder(parts, options)\n\n return { sql: parts.join('\\n'), params: allParams }\n}\n","import type { VelnAdapter, BindingValue, QueryLogEntry } from '../adapter/types'\nimport type { SchemaMap, TableDef, InferInsert, InferUpdate, RelationMeta, RelationsMap, WithRelations } from '../schema/table'\nimport type { HookExecutor } from '../hooks/executor'\nimport { RequestEventQueue } from '../events/index'\nimport { ValidationError } from '../app/types'\nimport { buildInsert, buildInsertMany, buildUpdate, buildDelete, buildSelect, buildJoinSelect, buildWhere, buildSelectListFromOptions, deserializeRow, buildSubquery, buildSoftDeleteUpdate, buildUnion } from './sql'\nimport type { JoinClause, SelectOptions, WhereInput, SqlDialect, AggregateClause, SubqueryResult } from './sql'\n\n// ── QueryLog — per-request query accumulator ──────────────────────────────\n\nexport interface QueryLog {\n /** Total number of queries executed during this request. */\n queries: number\n /** Cumulative wall-clock duration of all queries in ms. */\n totalMs: number\n /** Individual query entries — populated only when logQueries is true. */\n entries: QueryLogEntry[]\n /** Warning threshold — exceeded → N+1 warning. */\n threshold: number\n /** Whether individual query entries should be captured (for logQueries). */\n logQueries: boolean\n}\n\n// ── Event Buffering Stub — Phase 3 fills the flush mechanism ──────────────\n\nexport interface PendingEvent {\n name: string\n payload: unknown\n}\n\nexport interface TransactionResult<T> {\n result: T\n events: PendingEvent[] // always [] in Phase 2; Phase 3 wires EventBus here\n}\n\n// ── EventBus interface — optional on ctx, Phase 3 provides the implementation\n\nexport interface EventBus {\n _emit(event: string, payload: unknown, ctx: unknown): void\n on(event: string, handler: (payload: unknown, ctx: unknown) => Promise<void> | void): this\n flush(events: PendingEvent[], ctx: unknown): Promise<void>\n}\n\n// ── VelnDB ─────────────────────────────────────────────────────────────────\n\nexport class VelnDB {\n constructor(\n private readonly adapter: VelnAdapter,\n private readonly hooks: HookExecutor,\n ) {}\n\n /** Return a new BoundVelnDB scoped to the given context. Never mutates this. */\n withCtx(ctx: unknown, queue?: RequestEventQueue, queryLog?: QueryLog): BoundVelnDB {\n return new BoundVelnDB(this.adapter, this.hooks, ctx, queue, queryLog)\n }\n}\n\n// ── BoundVelnDB ────────────────────────────────────────────────────────────\n\nexport class BoundVelnDB {\n /** Per-request query counter — incremented for every query() and execute() call on this instance. */\n _queryCount = 0\n private readonly adapter: VelnAdapter\n\n constructor(\n adapter: VelnAdapter,\n private readonly hooks: HookExecutor,\n private readonly ctx: unknown,\n // queue is undefined when used outside HTTP context (CLI, tests, background jobs)\n private readonly queue?: RequestEventQueue,\n // Optional per-request QueryLog. When provided, every query() and execute() call\n // increments the log's counters. Never mutates adapter.onQuery — avoids shared-state\n // races when multiple requests run concurrently on the same adapter instance.\n queryLog?: QueryLog,\n private readonly dialect: SqlDialect = 'sqlite',\n ) {\n if (queryLog) {\n const log = queryLog\n this.adapter = {\n query: async <T>(sql: string, params: BindingValue[] = []) => {\n const t0 = performance.now()\n const rows = await adapter.query<T>(sql, params)\n const durationMs = performance.now() - t0\n this._queryCount++\n log.queries++\n log.totalMs += durationMs\n if (log.logQueries) log.entries.push({ sql, params, durationMs, type: 'query' })\n return rows\n },\n execute: async (sql: string, params: BindingValue[] = []) => {\n const t0 = performance.now()\n const result = await adapter.execute(sql, params)\n const durationMs = performance.now() - t0\n this._queryCount++\n log.queries++\n log.totalMs += durationMs\n if (log.logQueries) log.entries.push({ sql, params, durationMs, type: 'execute' })\n return result\n },\n transaction: (fn) => adapter.transaction(fn),\n close: () => adapter.close(),\n onQuery: adapter.onQuery,\n }\n } else {\n this.adapter = adapter\n }\n }\n\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n from<T, S extends SchemaMap, TRelations extends RelationsMap>(\n table: TableDef<T, S, any, TRelations>,\n ): SelectBuilder<T, S, TRelations> {\n return new SelectBuilder<T, S, TRelations>(this.adapter, this.hooks, this.ctx, this.queue, table as TableDef<T, S, any, TRelations>, {})\n }\n\n /**\n * Start a JOIN query from the given table name.\n * Returns a JoinBuilder — call .join()/.leftJoin() etc. to add clauses,\n * then .select() to execute and get Record<string, unknown>[] results.\n *\n * @example\n * const rows = await db.join('orders')\n * .columns(['orders.id', 'users.name'])\n * .join('users', 'orders.user_id = users.id')\n * .where('orders.status = ?', ['pending'])\n * .select()\n */\n join(tableName: string): JoinBuilder {\n return new JoinBuilder(this.adapter, tableName, [], [], '', [])\n }\n\n into<T, S extends SchemaMap>(table: TableDef<T, S>): InsertBuilder<T, S> {\n return new InsertBuilder<T, S>(this.adapter, this.hooks, this.ctx, this.queue, table, this.dialect)\n }\n\n /**\n * DataLoader-pattern relation fetch — single IN-query, no N+1.\n * Returns a Map keyed by the foreign-key value; each entry is an array of\n * matching child rows (for one-to-many relations).\n *\n * Two call forms:\n *\n * @example — explicit (original)\n * const authorMap = await db.loadRelation(posts, 'authorId', usersTable, 'id')\n *\n * @example — name-based (reads relation metadata declared on the table)\n * const authorMap = await db.loadRelation(posts, 'author', postsTable)\n */\n // Overload 1 — explicit, original signature (unchanged)\n loadRelation<\n TParent extends Record<string, unknown>,\n TChild,\n TFk extends keyof TParent & string,\n TPk extends keyof TChild & string,\n >(\n parents: TParent[],\n foreignKey: TFk,\n childTable: TableDef<TChild>,\n primaryKey: TPk,\n ): Promise<Map<TParent[TFk], TChild[]>>\n // Overload 2 — name-based, reads from sourceTable.relations\n loadRelation<TParent extends Record<string, unknown>>(\n parents: TParent[],\n relationName: string,\n sourceTable: TableDef<any>,\n ): Promise<Map<unknown, unknown>>\n // Implementation\n async loadRelation<\n TParent extends Record<string, unknown>,\n TChild,\n TFk extends keyof TParent & string,\n TPk extends keyof TChild & string,\n >(\n parents: TParent[],\n keyOrRelationName: TFk | string,\n tableOrSource: TableDef<TChild> | TableDef<unknown>,\n primaryKey?: TPk,\n ): Promise<Map<unknown, unknown>> {\n // Name-based path: no primaryKey arg\n if (primaryKey === undefined) {\n return this._loadRelationByName(\n parents,\n keyOrRelationName,\n tableOrSource as TableDef<unknown>,\n 'many',\n )\n }\n\n // Explicit path — original behaviour\n const foreignKey = keyOrRelationName as TFk\n const childTable = tableOrSource as TableDef<TChild>\n const result = new Map<TParent[TFk], TChild[]>()\n if (parents.length === 0) return result\n\n const ids = [...new Set(parents.map((p) => p[foreignKey]))]\n const children = await this.from(childTable)\n .where({ [primaryKey]: { op: 'IN', value: ids } } as WhereInput<TChild>)\n .select()\n\n for (const child of children) {\n const key = child[primaryKey] as unknown as TParent[TFk]\n const group = result.get(key)\n if (group) {\n group.push(child)\n } else {\n result.set(key, [child])\n }\n }\n return result\n }\n\n /**\n * Convenience variant of loadRelation for belongs-to (many-to-one) relations.\n * Returns Map<fkValue, TChild> — single child per key instead of an array.\n *\n * Two call forms:\n *\n * @example — explicit (original)\n * const authorMap = await db.loadRelationOne(posts, 'authorId', usersTable, 'id')\n *\n * @example — name-based\n * const authorMap = await db.loadRelationOne(posts, 'author', postsTable)\n */\n // Overload 1 — explicit\n loadRelationOne<\n TParent extends Record<string, unknown>,\n TChild,\n TFk extends keyof TParent & string,\n TPk extends keyof TChild & string,\n >(\n parents: TParent[],\n foreignKey: TFk,\n childTable: TableDef<TChild>,\n primaryKey: TPk,\n ): Promise<Map<TParent[TFk], TChild>>\n // Overload 2 — name-based\n loadRelationOne<TParent extends Record<string, unknown>>(\n parents: TParent[],\n relationName: string,\n sourceTable: TableDef<any>,\n ): Promise<Map<unknown, unknown>>\n // Implementation\n async loadRelationOne<\n TParent extends Record<string, unknown>,\n TChild,\n TFk extends keyof TParent & string,\n TPk extends keyof TChild & string,\n >(\n parents: TParent[],\n keyOrRelationName: TFk | string,\n tableOrSource: TableDef<TChild> | TableDef<unknown>,\n primaryKey?: TPk,\n ): Promise<Map<unknown, unknown>> {\n // Name-based path\n if (primaryKey === undefined) {\n return this._loadRelationByName(\n parents,\n keyOrRelationName,\n tableOrSource as TableDef<unknown>,\n 'one',\n )\n }\n\n // Explicit path — original behaviour\n const foreignKey = keyOrRelationName as TFk\n const childTable = tableOrSource as TableDef<TChild>\n const result = new Map<TParent[TFk], TChild>()\n if (parents.length === 0) return result\n\n const ids = [...new Set(parents.map((p) => p[foreignKey]))]\n const children = await this.from(childTable)\n .where({ [primaryKey]: { op: 'IN', value: ids } } as WhereInput<TChild>)\n .select()\n\n for (const child of children) {\n result.set(child[primaryKey] as unknown as TParent[TFk], child)\n }\n return result\n }\n\n /**\n * Shared implementation for name-based loadRelation / loadRelationOne.\n * Reads RelationMeta from sourceTable.relations, validates the kind,\n * and delegates to the explicit overload.\n */\n private async _loadRelationByName(\n parents: Record<string, unknown>[],\n relationName: string,\n sourceTable: TableDef<unknown>,\n mode: 'many' | 'one',\n ): Promise<Map<unknown, unknown>> {\n const rel = sourceTable.relations[relationName] as RelationMeta | undefined\n\n if (rel === undefined) {\n const available = Object.keys(sourceTable.relations).join(', ') || '(none)'\n throw new Error(\n `Relation '${relationName}' is not defined on table '${sourceTable.name}'. ` +\n `Available relations: ${available}`,\n )\n }\n\n if (rel.kind === 'manyToMany') {\n throw new Error(\n `manyToMany relations are not yet supported in loadRelation. ` +\n `Use a manual JOIN for relation '${relationName}' on table '${sourceTable.name}'.`,\n )\n }\n\n if (mode === 'one' && rel.kind === 'hasMany') {\n throw new Error(\n `loadRelationOne cannot be used with hasMany relation '${relationName}' on table '${sourceTable.name}'. ` +\n `Use loadRelation to get an array of results.`,\n )\n }\n\n const foreignTable = rel.getTable()\n const pk = foreignTable.primaryKey as string\n\n if (rel.kind === 'belongsTo') {\n // FK is on the parent (source) table; PK is on the foreign table.\n // We cast to the explicit overload signature — runtime is correct,\n // TypeScript can't narrow keyof unknown here.\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const ft = foreignTable as TableDef<any>\n const fk = rel.foreignKey as keyof typeof parents[0] & string\n if (mode === 'one') {\n return this.loadRelationOne(parents, fk, ft, pk)\n }\n return this.loadRelation(parents, fk, ft, pk)\n }\n\n // hasMany: FK is on the foreign table; we group by FK value\n // parents is keyed by their PK, foreign rows have rel.foreignKey pointing back\n const parentPk = sourceTable.primaryKey as string\n const result = new Map<unknown, unknown[]>()\n if (parents.length === 0) return result\n\n const ids = [...new Set(parents.map((p) => p[parentPk]))]\n const children = await this.from(foreignTable)\n .where({ [rel.foreignKey]: { op: 'IN', value: ids } } as WhereInput<typeof foreignTable>)\n .select()\n\n for (const child of children as Record<string, unknown>[]) {\n const key = child[rel.foreignKey]\n const group = result.get(key)\n if (group) {\n group.push(child)\n } else {\n result.set(key, [child])\n }\n }\n return result\n }\n\n async transaction<T>(fn: (db: BoundVelnDB) => Promise<T>): Promise<TransactionResult<T>> {\n // TX path: events collected inside the TX go into a dedicated txQueue.\n // If the TX commits successfully, txQueue.drain() returns the buffered events.\n // These are handed back via TransactionResult.events so the caller can flush\n // them at the right moment (after TX commit, not during).\n // This is intentionally separate from the per-request queue so that TX events\n // are never prematurely flushed if the request queue drains first.\n const txQueue = new RequestEventQueue()\n\n const result = await this.adapter.transaction(async (txAdapter) => {\n const txBound = new BoundVelnDB(txAdapter, this.hooks, this.ctx, txQueue)\n return fn(txBound)\n })\n // TX committed — drain buffered events into TransactionResult\n return { result, events: txQueue.drain() }\n }\n\n /**\n * Execute raw SQL and return typed rows.\n *\n * Without a schema the return type is `Record<string, unknown>[]`.\n * With a schema (e.g. a Zod object) every row is validated at runtime\n * and the return type is inferred from the schema.\n *\n * @example\n * // Untyped\n * const rows = await ctx.db.raw('SELECT * FROM orders WHERE amount > ?', [100])\n *\n * // Typed + validated\n * const schema = z.object({ id: z.number(), amount: z.number() })\n * const rows = await ctx.db.raw('SELECT id, amount FROM orders WHERE amount > ?', [100], schema)\n */\n async raw<T = Record<string, unknown>>(\n sql: string,\n params: BindingValue[] = [],\n schema?: { parse: (row: unknown) => T },\n ): Promise<T[]> {\n const rows = await this.adapter.query<Record<string, unknown>>(sql, params)\n if (!schema) return rows as T[]\n return rows.map((row) => {\n try {\n return schema.parse(row)\n } catch (err) {\n // @ts-ignore — ValidationError constructor expects ZodError; caller's schema.parse throws ZodError at runtime\n throw new ValidationError(err instanceof Error ? err.message : String(err))\n }\n })\n }\n}\n\n// ── mergeWhereInput — AND-merge two WhereInput values ─────────────────────────\n// When both are plain objects (no OR/AND key), spread them.\n// Otherwise wrap both in an AND group.\n\nfunction mergeWhereAnd<T>(\n a: WhereInput<T>,\n b: WhereInput<T>,\n): WhereInput<T> {\n const aIsPlain = !('OR' in a) && !('AND' in a)\n const bIsPlain = !('OR' in b) && !('AND' in b)\n if (aIsPlain && bIsPlain) {\n return { ...(a as object), ...(b as object) } as WhereInput<T>\n }\n return { AND: [a, b] }\n}\n\n// ── SelectBuilder ──────────────────────────────────────────────────────────\n\nexport class SelectBuilder<T, S extends SchemaMap, TRelations extends RelationsMap = RelationsMap> {\n constructor(\n private readonly adapter: VelnAdapter,\n private readonly hooks: HookExecutor,\n private readonly ctx: unknown,\n private readonly queue: RequestEventQueue | undefined,\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n private readonly table: TableDef<T, S, any, TRelations>,\n private readonly conditions: WhereInput<T>,\n private readonly _options: SelectOptions = {},\n // Raw SQL fragments appended with AND. Each entry is { sql, params }.\n private readonly _rawWhere: { sql: string; params: BindingValue[] }[] = [],\n private readonly _dialect: SqlDialect = 'sqlite',\n private readonly _withRelations: string[] = [],\n // When true, the soft-delete IS NULL filter is skipped.\n private readonly _includeDeleted: boolean = false,\n ) {}\n\n private _cloneWith(\n conditions: WhereInput<T>,\n rawWhere?: { sql: string; params: BindingValue[] }[],\n ): SelectBuilder<T, S, TRelations> {\n return new SelectBuilder<T, S, TRelations>(\n this.adapter,\n this.hooks,\n this.ctx,\n this.queue,\n this.table,\n conditions,\n this._options,\n rawWhere ?? this._rawWhere,\n this._dialect,\n this._withRelations,\n this._includeDeleted,\n )\n }\n\n private _clone(patch: Partial<SelectOptions>): SelectBuilder<T, S, TRelations> {\n return new SelectBuilder<T, S, TRelations>(\n this.adapter,\n this.hooks,\n this.ctx,\n this.queue,\n this.table,\n this.conditions,\n { ...this._options, ...patch },\n this._rawWhere,\n this._dialect,\n this._withRelations,\n this._includeDeleted,\n )\n }\n\n /**\n * Eager-load relations alongside the main query.\n * One additional IN-query per relation — never N+1 regardless of row count.\n *\n * @example\n * const posts = await db.from(postsTable).with({ author: true }).select()\n * posts[0].author // → User | null (fully typed)\n * posts[0].title // → string (original fields preserved)\n */\n with<Keys extends keyof TRelations & string>(\n relations: { [K in Keys]: true },\n ): SelectBuilder<WithRelations<T, { relations: TRelations }, Keys>, S, TRelations> {\n const keys = Object.keys(relations) as Keys[]\n return new SelectBuilder<WithRelations<T, { relations: TRelations }, Keys>, S, TRelations>(\n this.adapter,\n this.hooks,\n this.ctx,\n this.queue,\n // table type cast: the schema/relations are unchanged; only T changes in the generic\n this.table as unknown as TableDef<WithRelations<T, { relations: TRelations }, Keys>, S, any, TRelations>,\n this.conditions as unknown as WhereInput<WithRelations<T, { relations: TRelations }, Keys>>,\n this._options,\n this._rawWhere,\n this._dialect,\n [...this._withRelations, ...keys],\n this._includeDeleted,\n )\n }\n\n /**\n * Include soft-deleted rows in the query result.\n * By default, tables with `.withSoftDelete()` automatically exclude rows\n * where the soft-delete column is not null.\n *\n * Has no effect on tables without soft delete configured.\n *\n * @example\n * const allUsers = await db.from(usersTable).withDeleted().select()\n */\n withDeleted(): SelectBuilder<T, S, TRelations> {\n return new SelectBuilder<T, S, TRelations>(\n this.adapter,\n this.hooks,\n this.ctx,\n this.queue,\n this.table,\n this.conditions,\n this._options,\n this._rawWhere,\n this._dialect,\n this._withRelations,\n true,\n )\n }\n\n /**\n * Add WHERE conditions. Accepts:\n * - Plain equality map: `.where({ role: 'admin' })`\n * - Operator condition: `.where({ age: { op: '>=', value: 18 } })`\n * - OR group: `.where({ OR: [{ role: 'admin' }, { role: 'mod' }] })`\n * - AND group: `.where({ AND: [...] })`\n *\n * Multiple `.where()` calls are combined with AND.\n */\n where(conditions: WhereInput<T>): SelectBuilder<T, S, TRelations> {\n const merged = mergeWhereAnd(this.conditions, conditions)\n return this._cloneWith(merged)\n }\n\n /**\n * Append a raw SQL WHERE fragment, combined with AND.\n * Use for conditions the builder cannot express.\n *\n * @example\n * .whereRaw('\"score\" > \"threshold\"', [])\n * .whereRaw('\"created_at\" > ?', ['2024-01-01'])\n */\n whereRaw(sql: string, params: BindingValue[]): SelectBuilder<T, S, TRelations> {\n return this._cloneWith(this.conditions, [...this._rawWhere, { sql, params }])\n }\n\n /**\n * Apply SELECT DISTINCT — deduplicate rows in the result set.\n * Combine with `.columns()` to deduplicate on specific columns.\n *\n * @example\n * await db.from(usersTable).columns('name').distinct().select()\n * // → SELECT DISTINCT \"name\" FROM \"users\"\n */\n distinct(): SelectBuilder<T, S, TRelations> {\n return this._clone({ distinct: true })\n }\n\n /** Limit the number of rows returned. Bound as a parameter — never interpolated. */\n limit(n: number): SelectBuilder<T, S, TRelations> {\n return this._clone({ limit: n })\n }\n\n /** Skip the first n rows. Bound as a parameter — never interpolated. */\n offset(n: number): SelectBuilder<T, S, TRelations> {\n return this._clone({ offset: n })\n }\n\n /** Add an ORDER BY clause. Multiple calls accumulate in order. */\n orderBy(col: keyof T & string, dir: 'ASC' | 'DESC' = 'ASC'): SelectBuilder<T, S, TRelations> {\n const existing = this._options.orderBy ?? []\n return this._clone({ orderBy: [...existing, { col, dir }] })\n }\n\n /**\n * Convenience helper for cursor-based pagination.\n * page(1, 10) → LIMIT 10 OFFSET 0\n * page(2, 10) → LIMIT 10 OFFSET 10\n */\n page(page: number, size: number): SelectBuilder<T, S, TRelations> {\n return this._clone({ limit: size, offset: (page - 1) * size })\n }\n\n /**\n * Restrict which columns are returned.\n *\n * Single-column form returns a ColumnRestrictedBuilder, enabling .subquery():\n * db.from(usersTable).columns('id').subquery() // → SubqueryResult<'id', number>\n *\n * Multi-column form returns a narrowed SelectBuilder:\n * db.from(usersTable).columns('id', 'name') // → SelectBuilder<Pick<User, 'id'|'name'>, ...>\n */\n columns<K extends keyof T & string>(col: K): ColumnRestrictedBuilder<K, T[K], S, TRelations>\n columns<K extends keyof T & string>(...cols: K[]): SelectBuilder<Pick<T, K>, S, TRelations>\n columns<K extends keyof T & string>(...cols: K[]): SelectBuilder<Pick<T, K>, S, TRelations> | ColumnRestrictedBuilder<K, T[K], S, TRelations> {\n const cloned = this._clone({ columns: cols }) as unknown as SelectBuilder<unknown, S, TRelations>\n if (cols.length === 1) {\n return new ColumnRestrictedBuilder<K, T[K], S, TRelations>(cloned, cols[0]!)\n }\n return cloned as unknown as SelectBuilder<Pick<T, K>, S, TRelations>\n }\n\n /**\n * Build SELECT SQL + params without executing the query.\n * Used internally by ColumnRestrictedBuilder.subquery().\n */\n /** Internal accessor for ColumnRestrictedBuilder / UnionBuilder — returns the adapter. */\n _getAdapter(): VelnAdapter { return this.adapter }\n /** Internal accessor for ColumnRestrictedBuilder / UnionBuilder — returns the SQL dialect. */\n _getDialect(): SqlDialect { return this._dialect }\n\n /**\n * Returns the effective WHERE conditions, injecting the soft-delete IS NULL\n * filter when the table has a soft-delete column and .withDeleted() was not called.\n */\n private _effectiveConditions(): WhereInput<T> {\n const col = this.table.softDeleteColumn\n if (col === null || this._includeDeleted) return this.conditions\n const softFilter = { [col]: { op: 'IS NULL' } } as WhereInput<T>\n return mergeWhereAnd(this.conditions, softFilter)\n }\n\n _buildSelectSQL(): { sql: string; params: BindingValue[] } {\n const conditions = this._effectiveConditions()\n if (this._rawWhere.length === 0) {\n return buildSelect(\n this.table.name,\n conditions as WhereInput<Record<string, unknown>>,\n this._options,\n this._dialect,\n )\n }\n // Raw WHERE path — mirrors select() logic but without executing\n const { sql: whereSql, params: whereParams } = buildWhere(\n conditions as WhereInput<Record<string, unknown>>,\n this._dialect,\n )\n const allWhereParts: string[] = []\n const allParams: BindingValue[] = [...whereParams]\n if (whereSql) allWhereParts.push(whereSql)\n for (const raw of this._rawWhere) {\n allWhereParts.push(raw.sql)\n allParams.push(...raw.params)\n }\n const combinedWhere = allWhereParts.join(' AND ')\n const selectList = buildSelectListFromOptions(this._options)\n const selectKeyword = this._options.distinct ? 'SELECT DISTINCT' : 'SELECT'\n const parts: string[] = [\n combinedWhere\n ? `${selectKeyword} ${selectList} FROM \"${this.table.name}\" WHERE ${combinedWhere}`\n : `${selectKeyword} ${selectList} FROM \"${this.table.name}\"`,\n ]\n if (this._options.orderBy && this._options.orderBy.length > 0) {\n const clause = this._options.orderBy.map(({ col, dir }) => `\"${col}\" ${dir}`).join(', ')\n parts.push(`ORDER BY ${clause}`)\n }\n if (this._options.limit !== undefined || this._options.offset !== undefined) {\n const limitVal = this._options.limit !== undefined\n ? Math.trunc(Math.max(0, this._options.limit))\n : -1\n parts.push(`LIMIT ${limitVal}`)\n if (this._options.offset !== undefined) {\n parts.push(`OFFSET ${Math.trunc(Math.max(0, this._options.offset))}`)\n }\n }\n return { sql: parts.join(' '), params: allParams }\n }\n\n /**\n * Add a GROUP BY clause. Multiple columns are comma-separated.\n * Combine with .aggregate() to get grouped aggregate results.\n */\n groupBy(...cols: (keyof T & string)[]): SelectBuilder<T, S, TRelations> {\n return this._clone({ groupBy: cols as string[] })\n }\n\n /**\n * Add a HAVING clause — filters aggregate groups.\n * Uses the same WhereInput system as .where() (supports operators, OR/AND).\n *\n * @example\n * .groupBy('role').aggregate({ cnt: { fn: 'COUNT' } }).having({ cnt: { op: '>', value: 1 } })\n */\n having(conditions: WhereInput<Record<string, unknown>>): SelectBuilder<T, S, TRelations> {\n return this._clone({ having: conditions })\n }\n\n /**\n * Execute a GROUP BY + aggregate query.\n * Returns typed rows with group-by columns + aggregate aliases.\n *\n * @example\n * const rows = await db.from(orders)\n * .groupBy('status')\n * .aggregate({ total: { fn: 'SUM', col: 'amount' }, cnt: { fn: 'COUNT' } })\n * // rows: { status: string; total: number; cnt: number }[]\n */\n async aggregate<TAgg extends Record<string, number | string | null>>(\n aggregates: { [K in keyof TAgg]: { fn: 'COUNT' | 'SUM' | 'AVG' | 'MIN' | 'MAX'; col?: keyof T & string } },\n ): Promise<(Partial<T> & TAgg)[]> {\n const aggClauses: AggregateClause[] = Object.entries(aggregates).map(([alias, def]) => ({\n alias,\n fn: (def as { fn: AggregateClause['fn']; col?: string }).fn,\n col: (def as { fn: AggregateClause['fn']; col?: string }).col,\n }))\n\n // Merge aggregate clauses into current options and execute via select()\n const { sql, params } = buildSelect(\n this.table.name,\n this._effectiveConditions() as WhereInput<Record<string, unknown>>,\n { ...this._options, aggregates: aggClauses },\n this._dialect,\n )\n\n const rows = await this.adapter.query<Record<string, unknown>>(sql, params)\n return rows as (Partial<T> & TAgg)[]\n }\n\n // ── Scalar aggregate terminals ─────────────────────────────────────────────\n // These execute immediately and return a single value.\n\n /** COUNT(*) or COUNT(\"col\") — returns the count as a number. */\n async count(col?: keyof T & string): Promise<number> {\n return this._scalarAggregate('COUNT', col)\n }\n\n /** SUM(\"col\") — returns the sum as a number (0 if no rows). */\n async sum(col: keyof T & string): Promise<number> {\n return this._scalarAggregate('SUM', col)\n }\n\n /** AVG(\"col\") — returns the average as a number (0 if no rows). */\n async avg(col: keyof T & string): Promise<number> {\n return this._scalarAggregate('AVG', col)\n }\n\n /** MIN(\"col\") — returns the minimum value. */\n async min(col: keyof T & string): Promise<number | string | null> {\n return this._scalarAggregateRaw('MIN', col)\n }\n\n /** MAX(\"col\") — returns the maximum value. */\n async max(col: keyof T & string): Promise<number | string | null> {\n return this._scalarAggregateRaw('MAX', col)\n }\n\n private async _scalarAggregate(fn: AggregateClause['fn'], col?: keyof T & string): Promise<number> {\n const val = await this._scalarAggregateRaw(fn, col)\n if (val === null || val === undefined) return 0\n return Number(val)\n }\n\n private async _scalarAggregateRaw(fn: AggregateClause['fn'], col?: keyof T & string): Promise<number | string | null> {\n const alias = '_agg'\n const colExpr = col ? `\"${col as string}\"` : '*'\n const { sql: whereSql, params } = buildWhere(\n this._effectiveConditions() as WhereInput<Record<string, unknown>>,\n this._dialect,\n )\n\n let sqlStr: string\n let finalParams: BindingValue[]\n\n if (this._rawWhere.length > 0) {\n const allWhereParts: string[] = []\n const allParams: BindingValue[] = [...params]\n if (whereSql) allWhereParts.push(whereSql)\n for (const raw of this._rawWhere) {\n allWhereParts.push(raw.sql)\n allParams.push(...raw.params)\n }\n const combined = allWhereParts.join(' AND ')\n sqlStr = combined\n ? `SELECT ${fn}(${colExpr}) AS \"${alias}\" FROM \"${this.table.name}\" WHERE ${combined}`\n : `SELECT ${fn}(${colExpr}) AS \"${alias}\" FROM \"${this.table.name}\"`\n finalParams = allParams\n } else {\n sqlStr = whereSql\n ? `SELECT ${fn}(${colExpr}) AS \"${alias}\" FROM \"${this.table.name}\" WHERE ${whereSql}`\n : `SELECT ${fn}(${colExpr}) AS \"${alias}\" FROM \"${this.table.name}\"`\n finalParams = params\n }\n\n const row = await this.adapter.query<Record<string, unknown>>(sqlStr, finalParams)\n return (row[0]?.[alias] ?? null) as number | string | null\n }\n\n async select(): Promise<T[]> {\n let finalSql: string\n let finalParams: BindingValue[]\n\n const effectiveConditions = this._effectiveConditions()\n if (this._rawWhere.length === 0) {\n // Fast path: no raw fragments — buildSelect handles everything\n const { sql, params } = buildSelect(\n this.table.name,\n effectiveConditions as WhereInput<Record<string, unknown>>,\n this._options,\n this._dialect,\n )\n finalSql = sql\n finalParams = params\n } else {\n // Merge structured WHERE + raw fragments via AND, then bolt on options\n const { sql: whereSql, params: whereParams } = buildWhere(\n effectiveConditions as WhereInput<Record<string, unknown>>,\n this._dialect,\n )\n const allWhereParts: string[] = []\n const allParams: BindingValue[] = [...whereParams]\n if (whereSql) allWhereParts.push(whereSql)\n for (const raw of this._rawWhere) {\n allWhereParts.push(raw.sql)\n allParams.push(...raw.params)\n }\n const combinedWhere = allWhereParts.join(' AND ')\n\n // Delegate to buildSelect with a synthetic empty-conditions call so\n // GROUP BY / HAVING / ORDER BY / LIMIT are handled consistently,\n // but inject our merged WHERE manually.\n const selectList = buildSelectListFromOptions(this._options)\n const parts: string[] = [\n combinedWhere\n ? `SELECT ${selectList} FROM \"${this.table.name}\" WHERE ${combinedWhere}`\n : `SELECT ${selectList} FROM \"${this.table.name}\"`,\n ]\n if (this._options.groupBy && this._options.groupBy.length > 0) {\n parts.push(`GROUP BY ${this._options.groupBy.map((c) => `\"${c}\"`).join(', ')}`)\n }\n if (this._options.having) {\n const { sql: havSql, params: havParams } = buildWhere(this._options.having, this._dialect)\n if (havSql) {\n parts.push(`HAVING ${havSql}`)\n allParams.push(...havParams)\n }\n }\n if (this._options.orderBy && this._options.orderBy.length > 0) {\n const clause = this._options.orderBy\n .map(({ col, dir }) => `\"${col}\" ${dir}`)\n .join(', ')\n parts.push(`ORDER BY ${clause}`)\n }\n if (this._options.limit !== undefined || this._options.offset !== undefined) {\n const limitVal = this._options.limit !== undefined\n ? Math.trunc(Math.max(0, this._options.limit))\n : -1\n parts.push(`LIMIT ${limitVal}`)\n if (this._options.offset !== undefined) {\n parts.push(`OFFSET ${Math.trunc(Math.max(0, this._options.offset))}`)\n }\n }\n finalSql = parts.join(' ')\n finalParams = allParams\n }\n\n const rawRows = await this.adapter.query<Record<string, unknown>>(finalSql, finalParams)\n // When columns are restricted, only deserialize the selected columns\n let rows: T[]\n if (this._options.columns && this._options.columns.length > 0) {\n rows = rawRows as unknown as T[]\n } else {\n rows = rawRows.map((row) => deserializeRow(this.table, row))\n }\n\n if (this._withRelations.length === 0) return rows\n return this._executeWith(rows)\n }\n\n async first(): Promise<T | null> {\n const rows = await this.select()\n return rows[0] ?? null\n }\n\n // ── Eager loading — _executeWith ────────────────────────────────────────\n\n private async _executeWith(rows: T[]): Promise<T[]> {\n if (rows.length === 0) return rows\n\n const mutableRows = rows.map((r) => ({ ...(r as Record<string, unknown>) })) as T[]\n\n for (const relationName of this._withRelations) {\n const meta = this.table.relations[relationName] as RelationMeta | undefined\n if (!meta) continue\n\n if (meta.kind === 'manyToMany') {\n throw new Error(\n `manyToMany eager loading is not yet supported. ` +\n `Use loadRelation manually for relation '${relationName}'.`,\n )\n }\n\n if (meta.kind === 'belongsTo') {\n await this._attachBelongsTo(mutableRows as Record<string, unknown>[], relationName, meta)\n } else if (meta.kind === 'hasMany') {\n await this._attachHasMany(mutableRows as Record<string, unknown>[], relationName, meta)\n }\n }\n\n return mutableRows\n }\n\n private async _attachBelongsTo(\n rows: Record<string, unknown>[],\n relationName: string,\n meta: RelationMeta,\n ): Promise<void> {\n const foreignTable = meta.getTable()\n const fkValues = rows\n .map((r) => r[meta.foreignKey])\n .filter((v): v is BindingValue => v !== null && v !== undefined)\n\n if (fkValues.length === 0) {\n for (const r of rows) r[relationName] = null\n return\n }\n\n const uniqueFkValues = [...new Set(fkValues)]\n const pk = foreignTable.primaryKey as string\n const baseConditions: Record<string, unknown> = { [pk]: { op: 'IN', value: uniqueFkValues } }\n if (foreignTable.softDeleteColumn !== null) {\n baseConditions[foreignTable.softDeleteColumn as string] = { op: 'IS NULL' }\n }\n const { sql, params } = buildSelect(\n foreignTable.name,\n baseConditions as WhereInput<Record<string, unknown>>,\n {},\n this._dialect,\n )\n const related = await this.adapter.query<Record<string, unknown>>(sql, params)\n const relatedMap = new Map<unknown, unknown>()\n for (const r of related) {\n relatedMap.set(r[pk], deserializeRow(foreignTable, r))\n }\n\n for (const r of rows) {\n r[relationName] = relatedMap.get(r[meta.foreignKey]) ?? null\n }\n }\n\n private async _attachHasMany(\n rows: Record<string, unknown>[],\n relationName: string,\n meta: RelationMeta,\n ): Promise<void> {\n const foreignTable = meta.getTable()\n const pk = this.table.primaryKey as string\n const pkValues = rows.map((r) => r[pk]).filter((v): v is BindingValue => v !== null && v !== undefined)\n\n if (pkValues.length === 0) {\n for (const r of rows) r[relationName] = []\n return\n }\n\n const hasManyConditions: Record<string, unknown> = { [meta.foreignKey]: { op: 'IN', value: pkValues } }\n if (foreignTable.softDeleteColumn !== null) {\n hasManyConditions[foreignTable.softDeleteColumn as string] = { op: 'IS NULL' }\n }\n const { sql, params } = buildSelect(\n foreignTable.name,\n hasManyConditions as WhereInput<Record<string, unknown>>,\n {},\n this._dialect,\n )\n const related = await this.adapter.query<Record<string, unknown>>(sql, params)\n\n const grouped = new Map<unknown, unknown[]>()\n for (const pkVal of pkValues) grouped.set(pkVal, [])\n\n for (const r of related) {\n const fkVal = r[meta.foreignKey]\n const deserialized = deserializeRow(foreignTable, r)\n const group = grouped.get(fkVal)\n if (group) {\n group.push(deserialized)\n } else {\n grouped.set(fkVal, [deserialized])\n }\n }\n\n for (const r of rows) {\n r[relationName] = grouped.get(r[pk]) ?? []\n }\n }\n\n async update(patch: Partial<T>): Promise<T> {\n const hasConditions = !(\n Object.keys(this.conditions).length === 0 && this._rawWhere.length === 0\n )\n if (!hasConditions) {\n throw new Error('update() requires .where() conditions')\n }\n\n // Load current row\n const current = await this.first()\n if (current === null) {\n throw new Error('Record not found for update')\n }\n\n // Run beforeUpdate hooks (may transform patch)\n const finalPatch = await this.hooks.runBeforeUpdate(this.table, this.ctx, current, patch)\n\n // Execute UPDATE\n const pk = this.table.primaryKey\n const pkValue = (current as Record<string, unknown>)[pk as string] as BindingValue\n const { sql, params } = buildUpdate(\n this.table.name,\n finalPatch as Record<string, unknown>,\n pk,\n pkValue,\n )\n await this.adapter.execute(sql, params)\n\n // Construct updated result from known data — avoids a second SELECT round-trip.\n // We know exactly what was in the row before (current) and what was patched (finalPatch),\n // so the result is the merge of both. deserializeRow handles Date deserialization.\n const updatedRow: Record<string, unknown> = {\n ...(current as Record<string, unknown>),\n ...(finalPatch as Record<string, unknown>),\n }\n const result = deserializeRow(this.table, updatedRow)\n\n // Run afterUpdate hooks — events collected into queue, not emitted immediately\n await this.hooks.runAfterUpdate(this.table, this.ctx, result, current, this.queue)\n\n return result\n }\n\n /**\n * Update multiple rows atomically inside a single transaction.\n * Each row must include the primary key. beforeUpdate and afterUpdate hooks\n * run per row. If any row fails, the entire transaction rolls back.\n *\n * @example\n * const updated = await db.from(usersTable).updateMany([\n * { id: 1, name: 'Alice Updated' },\n * { id: 2, role: 'admin' },\n * ])\n */\n async updateMany(rows: InferUpdate<S>[]): Promise<T[]> {\n if (rows.length === 0) return []\n\n const pk = this.table.primaryKey\n\n const results: T[] = await this.adapter.transaction(async (txAdapter) => {\n // Build a transaction-scoped SelectBuilder that uses the tx adapter\n const txQueue = new RequestEventQueue()\n const inner: T[] = []\n\n for (const row of rows) {\n const pkValue = (row as Record<string, unknown>)[pk as string]\n if (pkValue === undefined || pkValue === null) {\n throw new Error(\n `updateMany: row is missing primary key \"${pk as string}\" — every row must include the PK`,\n )\n }\n\n // Load current row via the tx adapter (so read is within the same TX)\n const selectSql = `SELECT * FROM \"${this.table.name}\" WHERE \"${pk as string}\" = ?`\n const currentRows = await txAdapter.query<Record<string, unknown>>(selectSql, [pkValue as BindingValue])\n if (currentRows.length === 0) {\n throw new Error(`updateMany: record with ${pk as string}=${String(pkValue)} not found`)\n }\n const current = deserializeRow(this.table, currentRows[0]!)\n\n // Extract patch — everything except the PK\n const { [pk as string]: _pk, ...patchWithoutPk } = row as Record<string, unknown>\n const patch = patchWithoutPk as Partial<T>\n\n // Run beforeUpdate hooks (may transform patch)\n const finalPatch = await this.hooks.runBeforeUpdate(this.table, this.ctx, current, patch)\n\n // Execute UPDATE\n const { sql, params } = buildUpdate(\n this.table.name,\n finalPatch as Record<string, unknown>,\n pk,\n pkValue as BindingValue,\n )\n await txAdapter.execute(sql, params)\n\n // Construct updated result\n const updatedRow: Record<string, unknown> = {\n ...(current as Record<string, unknown>),\n ...(finalPatch as Record<string, unknown>),\n }\n const result = deserializeRow(this.table, updatedRow)\n\n // Run afterUpdate hooks — collect into txQueue\n await this.hooks.runAfterUpdate(this.table, this.ctx, result, current, txQueue)\n\n inner.push(result)\n }\n\n return inner\n })\n\n return results\n }\n\n async delete(): Promise<T> {\n const hasConditions = !(\n Object.keys(this.conditions).length === 0 && this._rawWhere.length === 0\n )\n if (!hasConditions) {\n throw new Error('delete() requires .where() conditions')\n }\n\n // Load current row\n const current = await this.first()\n if (current === null) {\n throw new Error('Record not found for delete')\n }\n\n // Run beforeDelete hooks (can throw to cancel)\n await this.hooks.runBeforeDelete(this.table, this.ctx, current)\n\n // Execute DELETE\n const pk = this.table.primaryKey\n const pkValue = (current as Record<string, unknown>)[pk as string] as BindingValue\n const { sql, params } = buildDelete(this.table.name, pk, pkValue)\n await this.adapter.execute(sql, params)\n\n // Run afterDelete hooks — events collected into queue, not emitted immediately\n await this.hooks.runAfterDelete(this.table, this.ctx, current, this.queue)\n\n return current\n }\n\n /**\n * Soft-delete rows by setting the soft-delete column to the current timestamp.\n * The table must have `.withSoftDelete()` configured — throws otherwise (at execute() time).\n *\n * Does NOT call beforeUpdate/afterUpdate hooks.\n * Without .where(), all rows in the table are soft-deleted.\n *\n * @example\n * await db.from(usersTable).softDelete().where({ id: 1 }).execute()\n */\n softDelete(): SoftDeleteBuilder<T, S> {\n return new SoftDeleteBuilder<T, S>(this.adapter, this.table, new Date(), this._dialect)\n }\n\n /**\n * Restore soft-deleted rows by setting the soft-delete column back to null.\n * The table must have `.withSoftDelete()` configured — throws otherwise (at execute() time).\n *\n * @example\n * await db.from(usersTable).restore().where({ id: 1 }).execute()\n */\n restore(): SoftDeleteBuilder<T, S> {\n return new SoftDeleteBuilder<T, S>(this.adapter, this.table, null, this._dialect)\n }\n}\n\n// ── ColumnRestrictedBuilder ────────────────────────────────────────────────\n// Returned by SelectBuilder.columns(singleCol). Exposes only the ops needed\n// to build a subquery: .where(), .limit(), .orderBy(), and .subquery().\n// .select(), .with(), .update(), .delete() are intentionally absent.\n\nexport class ColumnRestrictedBuilder<Col extends string, TCol, S extends SchemaMap, TRelations extends RelationsMap> {\n // _builder is typed as SelectBuilder<unknown, ...> to avoid variance issues\n // when constructing from SelectBuilder<Pick<T,K>, ...> — the runtime shape is identical.\n constructor(\n private readonly _builder: SelectBuilder<unknown, S, TRelations>,\n private readonly _col: Col,\n ) {}\n\n where(conditions: WhereInput<Record<string, unknown>>): ColumnRestrictedBuilder<Col, TCol, S, TRelations> {\n return new ColumnRestrictedBuilder<Col, TCol, S, TRelations>(\n this._builder.where(conditions),\n this._col,\n )\n }\n\n limit(n: number): ColumnRestrictedBuilder<Col, TCol, S, TRelations> {\n return new ColumnRestrictedBuilder<Col, TCol, S, TRelations>(\n this._builder.limit(n),\n this._col,\n )\n }\n\n orderBy(col: Col, dir: 'ASC' | 'DESC' = 'ASC'): ColumnRestrictedBuilder<Col, TCol, S, TRelations> {\n return new ColumnRestrictedBuilder<Col, TCol, S, TRelations>(\n // _builder is SelectBuilder<unknown,...> so keyof unknown = never;\n // col is a valid schema key at runtime — cast is safe.\n this._builder.orderBy(col as never, dir),\n this._col,\n )\n }\n\n /**\n * Build the SQL for this query as a subquery fragment.\n * The result can be used directly in WHERE IN / NOT IN conditions.\n *\n * @example\n * const activeIds = db.from(usersTable).columns('id').where({ active: true }).subquery()\n * // → SubqueryResult<'id', number>\n *\n * const posts = await db.from(postsTable)\n * .where({ authorId: { op: 'IN', value: activeIds } })\n * .select()\n */\n subquery(): SubqueryResult<Col, TCol> {\n const { sql, params } = this._builder._buildSelectSQL()\n return buildSubquery<Col, TCol>(sql, params, this._col)\n }\n\n /** Build raw SELECT SQL + params without parentheses (for UNION). */\n _buildRawSQL(): { sql: string; params: BindingValue[] } {\n return this._builder._buildSelectSQL()\n }\n\n /**\n * Combine this query with another same-type column query via UNION (deduplicates).\n * Both sides must produce the same column type — enforced at compile time.\n *\n * @example\n * db.from(usersTable).columns('id')\n * .union(db.from(adminsTable).columns('id'))\n * .select()\n */\n union(other: ColumnRestrictedBuilder<string, TCol, SchemaMap, RelationsMap>): UnionBuilder<TCol> {\n return new UnionBuilder<TCol>(\n [this._buildRawSQL(), other._buildRawSQL()],\n 'UNION',\n this._builder._getAdapter(),\n this._builder._getDialect(),\n )\n }\n\n /**\n * Combine via UNION ALL — keeps duplicate rows.\n */\n unionAll(other: ColumnRestrictedBuilder<string, TCol, SchemaMap, RelationsMap>): UnionBuilder<TCol> {\n return new UnionBuilder<TCol>(\n [this._buildRawSQL(), other._buildRawSQL()],\n 'UNION ALL',\n this._builder._getAdapter(),\n this._builder._getDialect(),\n )\n }\n}\n\n// ── SoftDeleteBuilder ─────────────────────────────────────────────────────\n// Returned by SelectBuilder.softDelete() and SelectBuilder.restore().\n// Accepts .where() for scoping, then .execute() to run the UPDATE.\n// Does NOT call beforeUpdate/afterUpdate hooks — soft delete is a system operation.\n\nexport class SoftDeleteBuilder<T, S extends SchemaMap> {\n private _conditions: WhereInput<T> = {} as WhereInput<T>\n\n constructor(\n private readonly adapter: VelnAdapter,\n private readonly table: TableDef<T, S>,\n private readonly _value: Date | null,\n private readonly _dialect: SqlDialect = 'sqlite',\n ) {}\n\n /**\n * Add WHERE conditions to scope which rows are soft-deleted / restored.\n * Multiple calls accumulate with AND.\n * Without .where(), all rows in the table are affected.\n */\n where(conditions: WhereInput<T>): this {\n this._conditions = mergeWhereAnd(this._conditions, conditions)\n return this\n }\n\n /**\n * Execute the soft-delete or restore UPDATE.\n * Throws if the table has no softDeleteColumn configured.\n */\n async execute(): Promise<void> {\n const col = this.table.softDeleteColumn\n if (col === null) {\n throw new Error(\n `softDelete() called on table '${this.table.name}' which has no soft delete column. ` +\n `Add .withSoftDelete('deletedAt') to the table definition.`,\n )\n }\n const { sql, params } = buildSoftDeleteUpdate(\n this.table.name,\n col as string,\n this._value,\n this._conditions as WhereInput<Record<string, unknown>>,\n this._dialect,\n )\n await this.adapter.execute(sql, params)\n }\n}\n\n// ── UnionBuilder ──────────────────────────────────────────────────────────\n// Returned by ColumnRestrictedBuilder.union() / .unionAll().\n// Chains UNION / UNION ALL queries and executes them as a single query.\n\nexport class UnionBuilder<T> {\n private _orderBy?: { col: string; dir: 'ASC' | 'DESC' }\n private _limit?: number\n\n constructor(\n private readonly _parts: Array<{ sql: string; params: BindingValue[] }>,\n private readonly _kind: 'UNION' | 'UNION ALL',\n private readonly _adapter: VelnAdapter,\n private readonly _dialect: SqlDialect,\n ) {}\n\n /** Append another UNION (deduplicating) leg. */\n union(other: ColumnRestrictedBuilder<string, T, SchemaMap, RelationsMap>): UnionBuilder<T> {\n return new UnionBuilder<T>(\n [...this._parts, other._buildRawSQL()],\n 'UNION',\n this._adapter,\n this._dialect,\n )\n }\n\n /** Append another UNION ALL (keep duplicates) leg. */\n unionAll(other: ColumnRestrictedBuilder<string, T, SchemaMap, RelationsMap>): UnionBuilder<T> {\n return new UnionBuilder<T>(\n [...this._parts, other._buildRawSQL()],\n 'UNION ALL',\n this._adapter,\n this._dialect,\n )\n }\n\n /** Add ORDER BY to the entire UNION result. */\n orderBy(col: string, dir: 'ASC' | 'DESC' = 'ASC'): UnionBuilder<T> {\n const next = new UnionBuilder<T>(this._parts, this._kind, this._adapter, this._dialect)\n next._orderBy = { col, dir }\n next._limit = this._limit\n return next\n }\n\n /** Add LIMIT to the entire UNION result. */\n limit(n: number): UnionBuilder<T> {\n const next = new UnionBuilder<T>(this._parts, this._kind, this._adapter, this._dialect)\n next._orderBy = this._orderBy\n next._limit = n\n return next\n }\n\n /** Execute the UNION query and return typed rows. */\n async select(): Promise<Record<string, T>[]> {\n const { sql, params } = buildUnion(this._parts, this._kind, {\n orderBy: this._orderBy,\n limit: this._limit,\n })\n return this._adapter.query<Record<string, T>>(sql, params)\n }\n\n /**\n * Build the UNION as a subquery — wrapped in parentheses.\n * Usable in WHERE IN / NOT IN conditions.\n *\n * @example\n * const adminOrModIds = db.from(usersTable).columns('id').where({ role: 'admin' })\n * .union(db.from(usersTable).columns('id').where({ role: 'mod' }))\n * .subquery()\n */\n subquery(): SubqueryResult<string, T> {\n const { sql, params } = buildUnion(this._parts, this._kind, {\n orderBy: this._orderBy,\n limit: this._limit,\n })\n return buildSubquery<string, T>(sql, params, '')\n }\n}\n\n// ── InsertBuilder ──────────────────────────────────────────────────────────\n\nexport class InsertBuilder<T, S extends SchemaMap> {\n constructor(\n private readonly adapter: VelnAdapter,\n private readonly hooks: HookExecutor,\n private readonly ctx: unknown,\n private readonly queue: RequestEventQueue | undefined,\n private readonly table: TableDef<T, S>,\n private readonly dialect: SqlDialect = 'sqlite',\n ) {}\n\n async insert(data: InferInsert<S>): Promise<T> {\n const originalInput = { ...data } as Partial<T>\n let current = { ...data } as Partial<T>\n\n // 1. Run beforeInsert hooks (may transform data)\n current = await this.hooks.runBeforeInsert(this.table, this.ctx, current)\n\n // 2. Apply defaultFns and defaultValues for unset fields\n for (const [field, col] of Object.entries(this.table.schema)) {\n // Skip autoIncrement primary keys — DB assigns the value\n if (col.def.primaryKey && col.def.autoIncrement) continue\n\n if ((current as Record<string, unknown>)[field] === undefined) {\n if (col.def.defaultFn !== undefined) {\n ;(current as Record<string, unknown>)[field] = col.def.defaultFn()\n } else if (col.def.defaultValue !== undefined) {\n ;(current as Record<string, unknown>)[field] = col.def.defaultValue\n }\n }\n }\n\n // 3. Serialize values for SQLite (Date → ISO string)\n const serialized = this._serializeForInsert(current as Record<string, unknown>)\n\n // 4. Execute INSERT RETURNING * — single round-trip, no follow-up SELECT needed.\n // SQLite ≥ 3.35 and PostgreSQL both support RETURNING *.\n // We use adapter.query() (not execute()) because RETURNING * yields rows.\n const { sql, params } = buildInsert(this.table.name, serialized, true)\n const rows = await this.adapter.query<Record<string, unknown>>(sql, params)\n const result = deserializeRow(this.table, rows[0]!)\n\n // 6. Run afterInsert hooks — events collected into queue, not emitted immediately\n await this.hooks.runAfterInsert(this.table, this.ctx, result, originalInput, this.queue)\n\n return result\n }\n\n /**\n * Insert multiple rows in a single SQL statement.\n * beforeInsert and afterInsert hooks run per row.\n * Defaults (defaultFn / defaultValue) are applied per row.\n *\n * MySQL is not yet supported (no RETURNING *) — throws an informative error.\n *\n * @example\n * const users = await db.into(usersTable).insertMany([\n * { name: 'Alice', email: 'alice@example.com' },\n * { name: 'Bob', email: 'bob@example.com' },\n * ])\n */\n async insertMany(data: InferInsert<S>[]): Promise<T[]> {\n if (data.length === 0) return []\n\n if (this.dialect === 'mysql') {\n throw new Error(\n 'insertMany is not yet supported for MySQL — MySQL does not support RETURNING *. ' +\n 'Use individual insert() calls inside a transaction() instead.',\n )\n }\n\n // Phase 1: run hooks + apply defaults + serialize — all before touching the adapter\n const serializedRows: Record<string, BindingValue>[] = []\n\n for (const row of data) {\n // a. beforeInsert hooks (may transform data)\n let processed: Partial<T> = await this.hooks.runBeforeInsert(\n this.table,\n this.ctx,\n { ...row } as Partial<T>,\n )\n\n // b. Apply defaultFns and defaultValues for unset fields\n for (const [field, col] of Object.entries(this.table.schema)) {\n if (col.def.primaryKey && col.def.autoIncrement) continue\n if ((processed as Record<string, unknown>)[field] === undefined) {\n if (col.def.defaultFn !== undefined) {\n ;(processed as Record<string, unknown>)[field] = col.def.defaultFn()\n } else if (col.def.defaultValue !== undefined) {\n ;(processed as Record<string, unknown>)[field] = col.def.defaultValue\n }\n }\n }\n\n // c. Serialize (Date → ISO string), cast to BindingValue[] — undefined already removed\n const serialized = this._serializeForInsert(processed as Record<string, unknown>)\n serializedRows.push(serialized as Record<string, BindingValue>)\n }\n\n // Phase 2: single INSERT … VALUES (…), (…) RETURNING *\n const { sql, params } = buildInsertMany(this.table.name, serializedRows, true)\n const rawRows = await this.adapter.query<Record<string, unknown>>(sql, params)\n\n // Phase 3: deserialize results + run afterInsert hooks per row\n const results: T[] = []\n for (const rawRow of rawRows) {\n const deserialized = deserializeRow(this.table, rawRow)\n await this.hooks.runAfterInsert(this.table, this.ctx, deserialized, {}, this.queue)\n results.push(deserialized)\n }\n\n return results\n }\n\n /** Serialize values for storage. Date → ISO string. Drops undefined values. */\n private _serializeForInsert(data: Record<string, unknown>): Record<string, unknown> {\n const result: Record<string, unknown> = {}\n for (const [key, val] of Object.entries(data)) {\n if (val === undefined) continue\n result[key] = val instanceof Date ? val.toISOString() : val\n }\n return result\n }\n}\n\n// ── JoinBuilder ───────────────────────────────────────────────────────────────\n// Immutable fluent builder for SELECT queries with JOIN clauses.\n// Returns Record<string, unknown>[] — results span multiple tables so no single\n// TypeDef can describe the shape.\n\nexport class JoinBuilder {\n constructor(\n private readonly adapter: VelnAdapter,\n private readonly tableName: string,\n private readonly _columns: string[],\n private readonly _joins: JoinClause[],\n private readonly _where: string,\n private readonly _params: BindingValue[],\n private readonly _options: SelectOptions = {},\n ) {}\n\n private _cloneOpts(patch: Partial<SelectOptions>): JoinBuilder {\n return new JoinBuilder(\n this.adapter,\n this.tableName,\n this._columns,\n this._joins,\n this._where,\n this._params,\n { ...this._options, ...patch },\n )\n }\n\n /** Restrict the selected columns (e.g. ['orders.id', 'users.name']). */\n columns(cols: string[]): JoinBuilder {\n return new JoinBuilder(this.adapter, this.tableName, cols, this._joins, this._where, this._params, this._options)\n }\n\n /** Add an INNER JOIN clause. */\n join(table: string, on: string): JoinBuilder {\n return this._addJoin('INNER', table, on)\n }\n\n /** Add a LEFT JOIN clause. */\n leftJoin(table: string, on: string): JoinBuilder {\n return this._addJoin('LEFT', table, on)\n }\n\n /** Add a RIGHT JOIN clause. */\n rightJoin(table: string, on: string): JoinBuilder {\n return this._addJoin('RIGHT', table, on)\n }\n\n /** Add a FULL JOIN clause. */\n fullJoin(table: string, on: string): JoinBuilder {\n return this._addJoin('FULL', table, on)\n }\n\n /**\n * Set a typed WHERE clause from a conditions object.\n * Each key becomes \"key\" = ? — values are bound safely.\n *\n * @example\n * .where({ status: 'pending', userId })\n */\n where(conditions: Record<string, BindingValue>): JoinBuilder\n /**\n * Set a raw WHERE clause.\n * Use ? as placeholder; pass bind values as the second argument.\n *\n * @example\n * .where('orders.status = ? AND orders.user_id = ?', ['pending', userId])\n */\n where(sql: string, params: BindingValue[]): JoinBuilder\n where(conditionsOrSql: Record<string, BindingValue> | string, params?: BindingValue[]): JoinBuilder {\n if (typeof conditionsOrSql === 'string') {\n return new JoinBuilder(this.adapter, this.tableName, this._columns, this._joins, conditionsOrSql, params ?? [], this._options)\n }\n const { sql, params: builtParams } = buildWhere(conditionsOrSql)\n return new JoinBuilder(this.adapter, this.tableName, this._columns, this._joins, sql, builtParams, this._options)\n }\n\n /** Limit the number of rows returned. Bound as a parameter — never interpolated. */\n limit(n: number): JoinBuilder {\n return this._cloneOpts({ limit: n })\n }\n\n /** Skip the first n rows. Bound as a parameter — never interpolated. */\n offset(n: number): JoinBuilder {\n return this._cloneOpts({ offset: n })\n }\n\n /**\n * Add an ORDER BY clause. Multiple calls accumulate in order.\n * @param col Column reference, e.g. 'orders.created_at' or 'name'.\n */\n orderBy(col: string, dir: 'ASC' | 'DESC' = 'ASC'): JoinBuilder {\n const existing = this._options.orderBy ?? []\n return this._cloneOpts({ orderBy: [...existing, { col, dir }] })\n }\n\n /**\n * Convenience helper for cursor-based pagination.\n * page(1, 10) → LIMIT 10 OFFSET 0\n * page(2, 10) → LIMIT 10 OFFSET 10\n */\n page(page: number, size: number): JoinBuilder {\n return this._cloneOpts({ limit: size, offset: (page - 1) * size })\n }\n\n /**\n * Execute the query and return raw rows (no deserialization).\n *\n * @remarks\n * Type parameter T is a manual cast — not validated at runtime.\n * For runtime validation, use db.raw() with a Zod schema instead.\n */\n async select<T = Record<string, unknown>>(): Promise<T[]> {\n const { sql, params } = buildJoinSelect(\n this.tableName,\n this._columns,\n this._joins,\n this._where,\n this._params,\n this._options,\n )\n return this.adapter.query<T>(sql, params)\n }\n\n /**\n * Execute the query and return the first row, or null.\n *\n * @remarks\n * Type parameter T is a manual cast — not validated at runtime.\n */\n async first<T = Record<string, unknown>>(): Promise<T | null> {\n const rows = await this.select<T>()\n return rows[0] ?? null\n }\n\n private _addJoin(type: JoinClause['type'], table: string, on: string): JoinBuilder {\n return new JoinBuilder(\n this.adapter,\n this.tableName,\n this._columns,\n [...this._joins, { type, table, on }],\n this._where,\n this._params,\n this._options,\n )\n }\n}\n","// Adapter\nexport type { VelnAdapter, BindingValue, ExecuteResult, QueryLogEntry } from './adapter/types'\nexport { SQLiteAdapter } from './adapter/sqlite'\nexport type { SQLiteConfig } from './adapter/sqlite'\nexport { PostgresAdapter } from './adapter/postgres'\nexport type { PostgresConfig } from './adapter/postgres'\nexport { MySQLAdapter } from './adapter/mysql'\nexport type { MySQLConfig } from './adapter/mysql'\nexport { resolveAdapter } from './adapter/resolve'\nexport type { AdapterConfig } from './adapter/resolve'\n\n// Schema\nexport { column } from './schema/column'\nexport type { Column, ColumnDef, SqlType } from './schema/column'\nexport { defineTable, toCreateTableSql } from './schema/table'\nexport type {\n SchemaMap, InferRow, InferInsert, InferUpdate, InferTable,\n TableDef, TableHookHandlers,\n TableEventMap, InferTableEvents,\n RelationMeta, RelationKind, RelationsMap,\n BelongsToRelation, HasManyRelation,\n InferRelationResult, WithRelations,\n} from './schema/table'\nexport { defineAuditTable } from './schema/audit'\nexport type { AuditTableDef, AuditLog, AuditConfig } from './schema/audit'\n\n// Hooks\nexport { HookExecutor } from './hooks/executor'\nexport type { ModuleHookHandlers, HookOperation } from './hooks/types'\n\n// Migrations\nexport { createMigrator, generateMigration, compareSchemas, introspectSchema, splitSqlStatements } from './db/migrations/index'\nexport type {\n Migrator, MigratorOptions, MigrationResult, MigrationStatus, MigrationRecord,\n SchemaDiff, TableDiff, TableModification, ColumnDef as MigrationColumnDef,\n IndexDef, ColumnModification,\n GenerateOptions, GenerateResult,\n} from './db/migrations/index'\n\n// DB\nexport { VelnDB, BoundVelnDB, SelectBuilder, InsertBuilder, JoinBuilder, SoftDeleteBuilder, UnionBuilder } from './db/index'\nexport type {\n PendingEvent, TransactionResult, QueryLog,\n} from './db/index'\nexport type { JoinClause, SelectOptions, AggregateClause, WhereInput, WhereOp, WhereConditions, FieldCondition, SqlDialect, InValue, SubqueryResult } from './db/sql'\nexport { buildSubquery, buildUnion } from './db/sql'\n// EventBus interface (structural type from db layer — the class below satisfies it)\nexport type { EventBus as EventBusInterface } from './db/index'\n\n// Events\nexport { InMemoryEventBus, EventBus, RequestEventQueue } from './events/index'\nexport type { EventBusAdapter, EventBusOptions, EventBusErrorHandler } from './events/index'\nexport type { EventHandler, VelnEvents } from './events/index'\nexport { defineEventHandler, EventHandlerBuilder } from './events/handler'\nexport type { EventHandlerDef, EventCallback, EventHandlerFn } from './events/handler'\n\n// Model\nexport { defineModel, ModelBuilder } from './model/index'\nexport type { ModelDef, ModelInstance } from './model/index'\n\n// Service\nexport { defineService } from './service/index'\nexport type { ServiceDef } from './service/index'\n\n// Middleware\nexport { defineMiddleware, MiddlewareBuilder } from './app/middleware'\nexport type { MiddlewareDef } from './app/middleware'\n\n// App\nexport { createApp, Veln } from './app/index'\nexport { createSystemCtx } from './app/system-ctx'\nexport { defineModule, ModuleBuilder } from './app/module'\nexport type { VelnModule, HookDeclaration, AuditDeclaration, ServiceDeclaration } from './app/module'\nexport { loggerPlugin, dbPlugin, eventBusPlugin, createPlugin, definePlugin, PluginBuilder } from './app/plugin'\nexport type { DbPluginConfig, DbLogOptions, NavItem } from './app/plugin'\nexport type { Plugin } from './app/plugin'\nexport type { BaseCtx, Guard, ErrorHandler, RouteHandler, Logger, AuthPayload, LogOptions, BaseOptions, AuthUser, AuthAdapter } from './app/types'\nexport { ValidationError, createGuard, defineGuard, createOnRequest, createOnBeforeHandle, createOnResponse } from './app/types'\nexport { secureHeadersPlugin } from './app/secure-headers'\nexport type { SecureHeadersOptions, CspPreset } from './app/secure-headers'\nexport { rateLimitPlugin, InMemoryStore } from './app/rate-limit'\nexport type { RateLimitOptions, RateLimitStore } from './app/rate-limit'\nexport { csrfPlugin } from './app/csrf'\nexport type { CsrfOptions, CsrfPlugin } from './app/csrf'\nexport { scalarPlugin } from './app/scalar'\nexport type { ScalarOptions } from './app/scalar'\nexport { bodySizeLimitPlugin } from './app/body-size-limit'\nexport type { BodySizeLimitOptions } from './app/body-size-limit'\nexport { corsPlugin } from './app/cors'\nexport type { CorsOptions, CorsPlugin } from './app/cors'\nexport { requestIdPlugin } from './app/request-id'\nexport type { RequestIdOptions, RequestIdCtx, RequestIdPlugin } from './app/request-id'\nexport { compressionPlugin } from './app/compression'\nexport type { CompressionOptions } from './app/compression'\nexport { healthPlugin } from './app/health'\nexport type { HealthPluginOptions, HealthCheck, HealthPlugin } from './app/health'\nexport type { VelnWsAdapter, WsRouteShape } from './app/types'\nexport type { RouteSchema, RouteHandlerWithSchema, InferCtx } from './app/types'\nexport type { RouteMap, RouteEntry, RouteKey } from './app/types'\nexport type { StreamController, StreamOptions, SseController } from './app/types'\nexport type { OnRequestHook, OnBeforeHandleHook, OnResponseHook, OnRequestFn, OnBeforeHandleFn, OnResponseFn } from './app/types'\n\n// Client\nexport { createClient } from './client/index'\nexport { createProxyClient, createModuleClient, pathToClientKey } from './client/index'\nexport type { ClientResult, InferProxyClient, ProxyClientOptions } from './client/index'\nexport { createTestClient } from './client/test-client'\nexport type { TestClientOptions } from './client/test-client'\nexport { VelnClientError } from './client/error'\n\n// OpenAPI\nexport { generateOpenApiSpec } from './openapi/generator'\nexport type { OpenApiSpec } from './openapi/generator'\nexport { zodToJsonSchema } from './openapi/zod-to-schema'\nexport type { JsonSchema } from './openapi/zod-to-schema'\n\n// Resource\nexport { defineResource, ResourceBuilder, NotFoundError, ConflictError, tableToZodInsert, tableToZodRow } from './resource/index'\nexport type { ResourceResult, DefaultModelMethods, ResourceOptions, ModelOverrides, ServiceOverrides, RouteConfig } from './resource/index'\n\n// Cron\nexport { defineCron, resolveExpression, NoOpCronLockAdapter } from './cron/index'\nexport type { CronDef, CronBuilder, CronCtx, CronBuildOptions, LogLevel, CronLockAdapter } from './cron/index'\n\n// CLI config helpers\nexport { defineConfig, defineCommand } from './cli/index'\nexport type { VelnConfig, CommandDef, CommandOption } from './cli/index'\n\n// Errors\nexport {\n VelnError,\n BadRequestError,\n UnauthorizedError,\n ForbiddenError,\n UnprocessableError,\n TooManyRequestsError,\n InternalError,\n} from './errors/index'\n","import type { VelnAdapter } from './types'\n\nexport type AdapterConfig =\n | { adapter: 'sqlite'; path?: string }\n | { adapter: 'postgres'; connectionString: string; maxConnections?: number }\n | { adapter: 'mysql'; connectionString: string; maxConnections?: number }\n\nexport function isVelnAdapter(value: unknown): value is VelnAdapter {\n return (\n typeof value === 'object' &&\n value !== null &&\n typeof (value as VelnAdapter).query === 'function' &&\n typeof (value as VelnAdapter).execute === 'function'\n )\n}\n\nexport function resolveAdapter(config: AdapterConfig | VelnAdapter): VelnAdapter {\n if (isVelnAdapter(config)) return config\n\n const cfg = config as AdapterConfig\n\n if (cfg.adapter === 'sqlite') {\n // eslint-disable-next-line @typescript-eslint/no-require-imports\n const { SQLiteAdapter } = require('./sqlite') as typeof import('./sqlite')\n return new SQLiteAdapter(cfg.path ? { path: cfg.path } : { path: './db.sqlite' })\n }\n\n if (cfg.adapter === 'postgres') {\n // eslint-disable-next-line @typescript-eslint/no-require-imports\n const { PostgresAdapter } = require('./postgres') as typeof import('./postgres')\n return new PostgresAdapter({ url: cfg.connectionString, max: cfg.maxConnections })\n }\n\n if (cfg.adapter === 'mysql') {\n // eslint-disable-next-line @typescript-eslint/no-require-imports\n const { MySQLAdapter } = require('./mysql') as typeof import('./mysql')\n return new MySQLAdapter({ url: cfg.connectionString, max: cfg.maxConnections })\n }\n\n throw new Error(`[oakbun] resolveAdapter: unknown adapter type \"${(cfg as AdapterConfig & { adapter: string }).adapter}\"`)\n}\n","export type SqlType =\n | 'INTEGER'\n | 'TEXT'\n | 'REAL'\n | 'BOOLEAN'\n | 'TIMESTAMP'\n | 'JSON'\n | 'UUID'\n | 'BLOB'\n\nexport interface ColumnDef {\n type: SqlType\n nullable: boolean\n primaryKey: boolean\n autoIncrement: boolean\n unique: boolean\n defaultValue?: unknown\n defaultFn?: () => unknown\n}\n\nexport class Column<T> {\n // Phantom type — exists only at compile time, never assigned at runtime\n declare readonly _: T\n\n constructor(readonly def: Readonly<ColumnDef>) {}\n\n nullable(): Column<T | null> {\n return new Column<T | null>({ ...this.def, nullable: true })\n }\n\n primaryKey(): Column<T> {\n return new Column<T>({ ...this.def, primaryKey: true, autoIncrement: true })\n }\n\n unique(): Column<T> {\n return new Column<T>({ ...this.def, unique: true })\n }\n\n default(value: NonNullable<T>): Column<T> {\n return new Column<T>({ ...this.def, defaultValue: value })\n }\n\n defaultFn(fn: () => NonNullable<T>): Column<T> {\n return new Column<T>({ ...this.def, defaultFn: fn as () => unknown })\n }\n}\n\nconst base = (type: SqlType): ColumnDef => ({\n type,\n nullable: false,\n primaryKey: false,\n autoIncrement: false,\n unique: false,\n})\n\nexport const column = {\n integer: (): Column<number> => new Column<number>({ ...base('INTEGER') }),\n text: (): Column<string> => new Column<string>({ ...base('TEXT') }),\n real: (): Column<number> => new Column<number>({ ...base('REAL') }),\n boolean: (): Column<boolean> => new Column<boolean>({ ...base('BOOLEAN') }),\n timestamp: (): Column<Date> => new Column<Date>({ ...base('TIMESTAMP') }),\n uuid: (): Column<string> => new Column<string>({ ...base('UUID') }),\n blob: (): Column<Uint8Array> => new Column<Uint8Array>({ ...base('BLOB') }),\n json: <T = unknown>(): Column<T> => new Column<T>({ ...base('JSON') }),\n}\n","import type { Column } from './column'\n\nexport type SchemaMap = Record<string, Column<any>>\n\n// Full row type — what you get back from SELECT.\n// Accepts either a SchemaMap directly or a TableDef (extracts its row type T).\nexport type InferRow<T> =\n T extends TableDef<infer R, any, any> ? R :\n T extends SchemaMap ? { [K in keyof T]: T[K] extends Column<infer C> ? C : never } :\n never\n\n// Insert type — PK + defaulted columns are optional, rest required\ntype IsOptionalOnInsert<C extends Column<any>> =\n C['def']['primaryKey'] extends true ? true :\n C['def']['defaultValue'] extends undefined ?\n C['def']['defaultFn'] extends undefined ?\n C['def']['nullable'] extends true ? true : false\n : true\n : true\n\ntype InferInsertFromSchema<S extends SchemaMap> =\n {\n [K in keyof S as IsOptionalOnInsert<S[K]> extends true ? never : K]:\n S[K] extends Column<infer T> ? NonNullable<T> : never\n } & {\n [K in keyof S as IsOptionalOnInsert<S[K]> extends true ? K : never]?:\n S[K] extends Column<infer T> ? T : never\n }\n\n// Accepts either a SchemaMap or a TableDef directly.\nexport type InferInsert<T> =\n T extends TableDef<any, infer S, any> ? InferInsertFromSchema<S> :\n T extends SchemaMap ? InferInsertFromSchema<T> :\n never\n\n// Update type — all fields Partial, primary key fields required.\n// Accepts either a SchemaMap or a TableDef directly.\nexport type InferUpdate<T> =\n T extends TableDef<infer R, infer S, any>\n ? Partial<R> & { [K in keyof S as S[K] extends Column<any> ? S[K]['def']['primaryKey'] extends true ? K : never : never]: R[K & keyof R] }\n : T extends SchemaMap\n ? Partial<{ [K in keyof T]: T[K] extends Column<infer C> ? C : never }>\n : never\n\n// Convenience wrapper — one import gives all three shapes.\nexport type InferTable<T extends TableDef<any, any, any>> = {\n row: InferRow<T>\n insert: InferInsert<T>\n update: InferUpdate<T>\n}\n\n// Table-level hook handlers — no ctx, always fire\nexport interface TableHookHandlers<T> {\n beforeInsert?: (data: Partial<T>) => Partial<T> | void | Promise<Partial<T> | void>\n afterInsert?: (result: T, input: Partial<T>) => void | Promise<void>\n beforeUpdate?: (current: T, patch: Partial<T>) => Partial<T> | void | Promise<Partial<T> | void>\n afterUpdate?: (result: T, before: T) => void | Promise<void>\n beforeDelete?: (current: T) => void | Promise<void>\n afterDelete?: (deleted: T) => void | Promise<void>\n}\n\n// Event map — declared on the Table, enforced by the framework\nexport interface TableEventMap {\n afterInsert?: string // event name to fire after insert\n afterUpdate?: string // event name to fire after update\n afterDelete?: string // event name to fire after delete\n}\n\n// Infer event payload types from a Table + EventMap.\n//\n// STAGING NOTE (Phase 3 → Phase 4):\n// This type is fully computed here at the Table level. However, app.on() currently\n// accepts `event: string` because TypeScript cannot recover these generic types after\n// they pass through VelnModule (which erases them). In Phase 4, the RPC client and\n// a dedicated app.onEvent<T>() overload will use InferTableEvents directly at the\n// call site, without needing Declaration Merging. Until then, Declaration Merging\n// via `interface VelnEvents {}` is the opt-in escape hatch for typed subscribers.\n//\n// Implementation note: three separate mapped types are intersected instead of using\n// a conditional `K extends 'afterUpdate'` inside a single mapped type. The conditional\n// form is deferred by TypeScript when K is generic, causing TMap[K] to resolve as a\n// union of all value types at the call site. The intersection approach produces a\n// concrete object type that TypeScript evaluates eagerly.\nexport type InferTableEvents<T, M extends TableEventMap> =\n (M['afterInsert'] extends string ? { [_ in M['afterInsert']]: T } : Record<never, never>) &\n (M['afterUpdate'] extends string ? { [_ in M['afterUpdate']]: { before: T; after: T } } : Record<never, never>) &\n (M['afterDelete'] extends string ? { [_ in M['afterDelete']]: T } : Record<never, never>)\n\n// ── Relation Metadata ─────────────────────────────────────────────────────\n\nexport type RelationKind = 'belongsTo' | 'hasMany' | 'manyToMany'\n\n/**\n * Metadata for a single declared relation.\n * TForeign captures the foreign table's row type so that WithRelations can\n * produce concrete types (User, Post[]) rather than unknown.\n *\n * `getTable` is a lazy getter to allow circular references between tables.\n */\nexport interface RelationMeta<TForeign = unknown> {\n kind: RelationKind\n name: string\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n getTable: () => TableDef<TForeign, any, any>\n /** FK column name — on this table for belongsTo, on foreign table for hasMany */\n foreignKey: string\n /** manyToMany only */\n pivot?: {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n table: TableDef<any, any, any>\n localKey: string\n foreignKey: string\n }\n}\n\n/** All declared relations on a table, keyed by relation name. */\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport type RelationsMap = Record<string, RelationMeta<any>>\n\n// ── Eager-loading types ────────────────────────────────────────────────────\n\n// Typed relation interfaces — one per kind.\n// WithRelations indexes into these to get a concrete type per relation name.\n// This avoids deferred conditional types (R['kind'] extends 'belongsTo') which\n// TypeScript cannot evaluate when R is still a generic parameter.\n\nexport interface BelongsToRelation<TForeign> extends RelationMeta<TForeign> {\n kind: 'belongsTo'\n}\n\nexport interface HasManyRelation<TForeign> extends RelationMeta<TForeign> {\n kind: 'hasMany'\n}\n\n/**\n * Derives the result type of a single loaded relation.\n * - belongsTo → TForeign | null\n * - hasMany → TForeign[]\n * - manyToMany → never (not supported in Spec B)\n */\nexport type InferRelationResult<R> =\n R extends BelongsToRelation<infer TForeign>\n ? TForeign | null\n : R extends HasManyRelation<infer TForeign>\n ? TForeign[]\n : never\n\n/**\n * Merges a row type T with the requested relations.\n * Keys must be keys of the table's relations map.\n *\n * @example\n * type PostWithAuthor = WithRelations<Post, typeof postsTable, 'author'>\n * // → Post & { author: User | null }\n */\nexport type WithRelations<\n T,\n TTable extends { relations: RelationsMap },\n Keys extends keyof TTable['relations'] & string,\n> = T & {\n [K in Keys]: InferRelationResult<TTable['relations'][K]>\n}\n\nexport interface TableDef<\n T,\n S extends SchemaMap = SchemaMap,\n TEvents extends TableEventMap = TableEventMap,\n TRelations extends RelationsMap = RelationsMap,\n> {\n readonly name: string\n readonly schema: S\n readonly primaryKey: keyof T & string\n readonly hooks: TableHookHandlers<T>[]\n readonly events: TEvents // typed — not just TableEventMap\n // eventMap is the precomputed InferTableEvents<T, TEvents> shape.\n // Storing it as a concrete generic parameter (TMap) lets onEvent() index it\n // directly as TMap[K] without TypeScript deferring the conditional InferTableEvents.\n readonly _eventMap: InferTableEvents<T, TEvents>\n /** Declared relations — concrete typed map so WithRelations can infer foreign types. */\n readonly relations: TRelations\n /** The column used for soft delete, or null if not configured. */\n readonly softDeleteColumn: (keyof T & string) | null\n}\n\nexport class TableBuilder<\n T,\n S extends SchemaMap,\n TEvents extends TableEventMap = Record<string, never>,\n TRelations extends RelationsMap = Record<string, never>,\n> {\n private readonly _hooks: TableHookHandlers<T>[] = []\n private _events: TableEventMap = {}\n private readonly _relations: RelationsMap = {}\n private _softDeleteColumn: (keyof T & string) | null = null\n\n constructor(\n private readonly _name: string,\n private readonly _schema: S,\n ) {}\n\n // Register table-level hook (no ctx)\n hook(handlers: TableHookHandlers<T>): this {\n this._hooks.push(handlers)\n return this\n }\n\n /**\n * Designate a column as the soft-delete timestamp.\n * Once set, all SELECTs automatically add `WHERE \"col\" IS NULL`.\n * Use `.withDeleted()` on the query to opt out.\n *\n * The column must exist in the schema (validated in `build()`).\n *\n * @example\n * const usersTable = defineTable('users', {\n * id: column.integer().primaryKey(),\n * deletedAt: column.timestamp().nullable(),\n * }).withSoftDelete('deletedAt').build()\n */\n withSoftDelete<Col extends keyof T & string>(col: Col): this {\n this._softDeleteColumn = col\n return this\n }\n\n emits<M extends TableEventMap>(map: M): TableBuilder<T, S, M, TRelations> {\n const next = new TableBuilder<T, S, M, TRelations>(this._name, this._schema)\n // copy existing hooks, relations, and softDeleteColumn\n for (const h of this._hooks) (next as unknown as TableBuilder<T, S>)._hooks.push(h)\n ;(next as unknown as TableBuilder<T, S, M, TRelations>)._events = map\n for (const [k, v] of Object.entries(this._relations)) {\n ;(next as unknown as TableBuilder<T, S>)._relations[k] = v\n }\n ;(next as unknown as TableBuilder<T, S>)._softDeleteColumn = this._softDeleteColumn\n return next\n }\n\n /**\n * Declare a belongs-to relation — FK lives on this table.\n * Returns a new builder with the relation type added to TRelations.\n *\n * @example\n * const postsTable = defineTable('posts', { authorId: column.integer() })\n * .belongsTo('author', () => usersTable, 'authorId')\n * .build()\n */\n belongsTo<K extends string, TForeign>(\n name: K,\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n getTable: () => TableDef<TForeign, any, any, any>,\n foreignKey: keyof T & string,\n ): TableBuilder<T, S, TEvents, TRelations & Record<K, BelongsToRelation<TForeign>>> {\n if (name in this._relations) {\n throw new Error(`Relation '${name}' is already defined on table '${this._name}'`)\n }\n const rel: BelongsToRelation<TForeign> = { kind: 'belongsTo', name, getTable, foreignKey }\n this._relations[name] = rel\n return this as unknown as TableBuilder<T, S, TEvents, TRelations & Record<K, BelongsToRelation<TForeign>>>\n }\n\n /**\n * Declare a has-many relation — FK lives on the foreign table.\n * Returns a new builder with the relation type added to TRelations.\n *\n * @example\n * const usersTable = defineTable('users', { id: column.integer().primaryKey() })\n * .hasMany('posts', () => postsTable, 'authorId')\n * .build()\n */\n hasMany<K extends string, TForeign>(\n name: K,\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n getTable: () => TableDef<TForeign, any, any, any>,\n /** The FK column on the *foreign* table that points back to this table's PK. */\n foreignKey: string,\n ): TableBuilder<T, S, TEvents, TRelations & Record<K, HasManyRelation<TForeign>>> {\n if (name in this._relations) {\n throw new Error(`Relation '${name}' is already defined on table '${this._name}'`)\n }\n const rel: HasManyRelation<TForeign> = { kind: 'hasMany', name, getTable, foreignKey }\n this._relations[name] = rel\n return this as unknown as TableBuilder<T, S, TEvents, TRelations & Record<K, HasManyRelation<TForeign>>>\n }\n\n /**\n * Declare a many-to-many relation via a pivot table.\n *\n * @example\n * const postsTable = defineTable('posts', { ... })\n * .manyToMany('tags', () => tagsTable, postTagsTable, 'postId', 'tagId')\n * .build()\n */\n manyToMany<K extends string>(\n name: K,\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n getTable: () => TableDef<any, any, any, any>,\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n pivotTable: TableDef<any, any, any, any>,\n /** FK on pivot pointing to this table's PK */\n localKey: string,\n /** FK on pivot pointing to the foreign table's PK */\n foreignKey: string,\n ): TableBuilder<T, S, TEvents, TRelations & Record<K, RelationMeta>> {\n if (name in this._relations) {\n throw new Error(`Relation '${name}' is already defined on table '${this._name}'`)\n }\n this._relations[name] = {\n kind: 'manyToMany',\n name,\n getTable,\n foreignKey,\n pivot: { table: pivotTable, localKey, foreignKey },\n }\n return this as unknown as TableBuilder<T, S, TEvents, TRelations & Record<K, RelationMeta>>\n }\n\n build(): TableDef<T, S, TEvents, TRelations> {\n if (this._softDeleteColumn !== null && !(this._softDeleteColumn in this._schema)) {\n throw new Error(\n `withSoftDelete: column '${this._softDeleteColumn as string}' is not defined in table '${this._name}'. ` +\n `Add it to the schema: column.timestamp().nullable()`,\n )\n }\n return {\n name: this._name,\n schema: this._schema,\n primaryKey: this._findPrimaryKey() as keyof T & string,\n hooks: [...this._hooks], // copy — immutable after build\n events: { ...this._events } as unknown as TEvents,\n // _eventMap is typed as InferTableEvents<T, TEvents> — the concrete shape.\n // At runtime it's an empty object (events hold only the string names, not payloads).\n // The field exists solely so TypeScript can infer TMap in onEvent() without\n // recomputing the conditional InferTableEvents each time.\n _eventMap: {} as InferTableEvents<T, TEvents>,\n relations: { ...this._relations } as TRelations,\n softDeleteColumn: this._softDeleteColumn,\n }\n }\n\n private _findPrimaryKey(): string {\n for (const [key, col] of Object.entries(this._schema)) {\n if ((col as Column<any>).def.primaryKey) return key\n }\n return 'id' // convention fallback\n }\n}\n\nexport function defineTable<S extends SchemaMap>(\n name: string,\n schema: S,\n): TableBuilder<InferRow<S>, S> {\n return new TableBuilder<InferRow<S>, S>(name, schema)\n}\n\n// Helper: generate CREATE TABLE SQL from a TableDef (SQLite dialect)\nexport function toCreateTableSql<T>(table: TableDef<T>): string {\n const cols = Object.entries(table.schema).map(([name, col]) => {\n const c = col as Column<any>\n let def = `\"${name}\" `\n\n switch (c.def.type) {\n case 'INTEGER': def += 'INTEGER'; break\n case 'TEXT':\n case 'UUID': def += 'TEXT'; break\n case 'REAL': def += 'REAL'; break\n case 'BOOLEAN': def += 'INTEGER'; break // SQLite has no BOOLEAN\n case 'TIMESTAMP': def += 'TEXT'; break // ISO string in SQLite\n case 'JSON': def += 'TEXT'; break\n case 'BLOB': def += 'BLOB'; break\n }\n\n if (c.def.primaryKey) def += ' PRIMARY KEY'\n if (c.def.autoIncrement && c.def.type === 'INTEGER') def += ' AUTOINCREMENT'\n if (!c.def.nullable && !c.def.primaryKey) def += ' NOT NULL'\n if (c.def.unique) def += ' UNIQUE'\n\n return def\n })\n\n return `CREATE TABLE IF NOT EXISTS \"${table.name}\" (${cols.join(', ')})`\n}\n","import { column } from './column'\nimport { defineTable } from './table'\nimport type { SchemaMap, TableDef, InferRow, TableBuilder } from './table'\n\n// ── Base audit fields — internal, never exported ────────────────────────────\n// Users must not depend on this shape directly; they extend via defineAuditTable().\n\nconst _baseAuditFields = {\n id: column.integer().primaryKey(),\n tableName: column.text(),\n operation: column.text(), // 'insert' | 'update' | 'delete'\n actor: column.text().nullable(),\n before: column.text().nullable(), // JSON string | null (null on insert)\n after: column.text().nullable(), // JSON string | null (null on delete)\n changedAt: column.timestamp().defaultFn(() => new Date()),\n} as const\n\ntype BaseAuditSchema = typeof _baseAuditFields\n\n// ── Public API ───────────────────────────────────────────────────────────────\n// defineAuditTable() = defineTable() with base audit fields pre-merged.\n// Users can add custom fields:\n// export const auditLogs = defineAuditTable('audit_logs', {\n// requestId: column.text().nullable(),\n// }).build()\n\nexport function defineAuditTable<S extends SchemaMap = Record<never, never>>(\n name: string,\n extraSchema?: S,\n): TableBuilder<InferRow<BaseAuditSchema & S>, BaseAuditSchema & S> {\n const merged = { ..._baseAuditFields, ...(extraSchema ?? {}) } as BaseAuditSchema & S\n return defineTable(name, merged)\n}\n\n// AuditTableDef — base shape (no extra fields). Useful as a parameter type\n// when a function accepts any audit table regardless of custom fields.\nexport type AuditTableDef<S extends SchemaMap = BaseAuditSchema> =\n TableDef<InferRow<BaseAuditSchema & S>, BaseAuditSchema & S>\n\n// AuditLog — base row type (no extra fields). Extend via InferRow<typeof myAuditTable>\n// for tables with custom fields.\nexport type AuditLog = InferRow<BaseAuditSchema>\n\n// ── AuditConfig — passed to .audit() on ModuleBuilder ───────────────────────\n\nexport interface AuditConfig<TCtx, TRow, S extends SchemaMap = BaseAuditSchema> {\n /** The audit table to write into. */\n storeIn: AuditTableDef<S>\n /** Extract actor identifier from request context. Return null for anonymous. */\n actor: (ctx: TCtx) => string | null | undefined\n /** Field names to replace with '[REDACTED]' in before/after snapshots. */\n redact?: (keyof TRow & string)[]\n /** Called when an audit write fails. Defaults to console.error. */\n onError?: (err: unknown) => void\n}\n\n// ── applyRedact — internal helper ───────────────────────────────────────────\n// Replaces specified fields with '[REDACTED]' in a shallow clone.\n// Never removes fields — '[REDACTED]' is distinguishable from absent/null.\n\nexport function applyRedact<T extends Record<string, unknown>>(\n row: T,\n fields: string[],\n): T {\n if (fields.length === 0) return row\n const copy = { ...row } as Record<string, unknown>\n for (const f of fields) {\n if (f in copy) copy[f] = '[REDACTED]'\n }\n return copy as T\n}\n","import type { VelnAdapter } from '../adapter/types'\nimport type { TableDef } from '../schema/table'\nimport type { ModuleHookHandlers } from './types'\nimport type { RequestEventQueue } from '../events/index'\n\n// ── BEFORE (executor.ts ~line 93-95):\n// Automatic event firing — immediate, fire & forget:\n// if (table.events.afterInsert) {\n// this.eventBus?._emit(table.events.afterInsert, result, ctx)\n// }\n//\n// ── AFTER (executor.ts ~line 93-95):\n// Collect into per-request queue — flushed by fetch() after onResponse:\n// if (table.events.afterInsert) {\n// queue?.collect(table.events.afterInsert, result)\n// }\n\nexport class HookExecutor {\n // tableName → ordered array of module-level handlers\n private readonly registry = new Map<string, ModuleHookHandlers<any, any>[]>()\n\n // Set by dbPlugin at install() — used by app.register() to build audit closures.\n // undefined until dbPlugin installs (no-DB apps never set this).\n private _adapter?: VelnAdapter\n\n // No EventBus held globally — queue is passed per runAfterX call\n constructor() {}\n\n setAdapter(adapter: VelnAdapter): void {\n this._adapter = adapter\n }\n\n getAdapter(): VelnAdapter | undefined {\n return this._adapter\n }\n\n // Called by defineModule when a .hook() is registered\n registerModuleHook<T, TCtx>(\n tableName: string,\n handlers: ModuleHookHandlers<T, TCtx>,\n ): void {\n if (!this.registry.has(tableName)) this.registry.set(tableName, [])\n this.registry.get(tableName)!.push(handlers)\n }\n\n // ── Before operations — can transform data, can throw to cancel ──\n\n async runBeforeInsert<T>(\n table: TableDef<T>,\n ctx: unknown,\n data: Partial<T>,\n ): Promise<Partial<T>> {\n let current = { ...data }\n\n // 1. Table-level (no ctx)\n for (const h of table.hooks) {\n if (!h.beforeInsert) continue\n const result = await h.beforeInsert(current)\n if (result != null) current = result as Partial<T>\n }\n\n // 2. Module-level (ctx-aware)\n for (const h of this._moduleHandlers(table.name)) {\n if (!h.beforeInsert) continue\n const result = await h.beforeInsert(ctx, current)\n if (result != null) current = result as Partial<T>\n }\n\n return current\n }\n\n async runBeforeUpdate<T>(\n table: TableDef<T>,\n ctx: unknown,\n current: T,\n patch: Partial<T>,\n ): Promise<Partial<T>> {\n let currentPatch = { ...patch }\n\n for (const h of table.hooks) {\n if (!h.beforeUpdate) continue\n const result = await h.beforeUpdate(current, currentPatch)\n if (result != null) currentPatch = result as Partial<T>\n }\n\n for (const h of this._moduleHandlers(table.name)) {\n if (!h.beforeUpdate) continue\n const result = await h.beforeUpdate(ctx, current, currentPatch)\n if (result != null) currentPatch = result as Partial<T>\n }\n\n return currentPatch\n }\n\n async runBeforeDelete<T>(table: TableDef<T>, ctx: unknown, current: T): Promise<void> {\n for (const h of table.hooks) {\n if (h.beforeDelete) await h.beforeDelete(current)\n }\n for (const h of this._moduleHandlers(table.name)) {\n if (h.beforeDelete) await h.beforeDelete(ctx, current)\n }\n }\n\n // ── After operations — side effects only, cannot cancel ──\n // queue: per-request RequestEventQueue, or undefined when called outside HTTP context.\n // When undefined (e.g. background jobs, tests, Phase 2 direct usage), events are dropped.\n\n async runAfterInsert<T>(\n table: TableDef<T>,\n ctx: unknown,\n result: T,\n input: Partial<T>,\n queue?: RequestEventQueue,\n ): Promise<void> {\n for (const h of table.hooks) {\n if (h.afterInsert) await h.afterInsert(result, input)\n }\n for (const h of this._moduleHandlers(table.name)) {\n if (h.afterInsert) await h.afterInsert(ctx, result, input)\n }\n // Collect event into request queue — flushed after onResponse, never immediately\n if (table.events.afterInsert) {\n queue?.collect(table.events.afterInsert, result)\n }\n }\n\n async runAfterUpdate<T>(\n table: TableDef<T>,\n ctx: unknown,\n result: T,\n before: T,\n queue?: RequestEventQueue,\n ): Promise<void> {\n for (const h of table.hooks) {\n if (h.afterUpdate) await h.afterUpdate(result, before)\n }\n for (const h of this._moduleHandlers(table.name)) {\n if (h.afterUpdate) await h.afterUpdate(ctx, result, before)\n }\n // Collect event into request queue — flushed after onResponse, never immediately\n if (table.events.afterUpdate) {\n queue?.collect(table.events.afterUpdate, { before, after: result })\n }\n }\n\n async runAfterDelete<T>(\n table: TableDef<T>,\n ctx: unknown,\n deleted: T,\n queue?: RequestEventQueue,\n ): Promise<void> {\n for (const h of table.hooks) {\n if (h.afterDelete) await h.afterDelete(deleted)\n }\n for (const h of this._moduleHandlers(table.name)) {\n if (h.afterDelete) await h.afterDelete(ctx, deleted)\n }\n // Collect event into request queue — flushed after onResponse, never immediately\n if (table.events.afterDelete) {\n queue?.collect(table.events.afterDelete, deleted)\n }\n }\n\n private _moduleHandlers(tableName: string): ModuleHookHandlers<any, any>[] {\n return this.registry.get(tableName) ?? []\n }\n}\n","import { readdir, readFile } from 'node:fs/promises'\nimport { join } from 'node:path'\nimport type { VelnAdapter } from '../../adapter/types'\nimport type { MigrationResult, MigrationStatus, MigratorOptions } from './types'\nimport { ensureTable, getApplied, markApplied, markRolledBack } from './tracker'\n\ninterface MigrationFile {\n name: string\n sql: string\n}\n\nasync function readMigrationFiles(dir: string): Promise<MigrationFile[]> {\n let entries: string[]\n try {\n entries = await readdir(dir)\n } catch {\n return []\n }\n\n const sqlFiles = entries\n .filter(f => f.endsWith('.sql'))\n .sort() // alphabetical — relies on numeric prefix convention\n\n const files: MigrationFile[] = []\n for (const filename of sqlFiles) {\n const sql = await readFile(join(dir, filename), 'utf8')\n files.push({ name: filename, sql })\n }\n return files\n}\n\nexport function splitSqlStatements(sql: string): string[] {\n const statements: string[] = []\n let current = ''\n let inString = false\n let stringChar = ''\n let i = 0\n\n while (i < sql.length) {\n const ch = sql[i]\n\n // Handle single-line comments\n if (!inString && ch === '-' && sql[i + 1] === '-') {\n const newline = sql.indexOf('\\n', i)\n if (newline === -1) {\n current += sql.slice(i)\n i = sql.length\n } else {\n current += sql.slice(i, newline + 1)\n i = newline + 1\n }\n continue\n }\n\n // Handle block comments\n if (!inString && ch === '/' && sql[i + 1] === '*') {\n const end = sql.indexOf('*/', i + 2)\n if (end === -1) {\n current += sql.slice(i)\n i = sql.length\n } else {\n current += sql.slice(i, end + 2)\n i = end + 2\n }\n continue\n }\n\n // Handle string literals\n if (!inString && (ch === \"'\" || ch === '\"')) {\n inString = true\n stringChar = ch\n current += ch\n i++\n continue\n }\n\n if (inString) {\n if (ch === stringChar) {\n // Check for escaped quote (doubled)\n if (sql[i + 1] === stringChar) {\n current += ch + ch\n i += 2\n continue\n }\n inString = false\n stringChar = ''\n }\n current += ch\n i++\n continue\n }\n\n if (ch === ';') {\n const trimmed = current.trim()\n if (trimmed) statements.push(trimmed)\n current = ''\n i++\n continue\n }\n\n current += ch\n i++\n }\n\n const trimmed = current.trim()\n if (trimmed) statements.push(trimmed)\n\n return statements\n}\n\nexport async function run(adapter: VelnAdapter, opts: MigratorOptions): Promise<MigrationResult[]> {\n const tableName = opts.tableName ?? '_veln_migrations'\n\n await ensureTable(adapter, tableName)\n\n const files = await readMigrationFiles(opts.migrationsDir)\n const applied = await getApplied(adapter, tableName)\n const appliedNames = new Set(applied.map(r => r.name))\n\n const pending = files.filter(f => !appliedNames.has(f.name))\n\n const results: MigrationResult[] = []\n for (const migration of pending) {\n const t0 = performance.now()\n try {\n await opts.onBeforeMigrate?.({ name: migration.name, sql: migration.sql })\n const statements = splitSqlStatements(migration.sql)\n for (const stmt of statements) {\n if (stmt.trim()) await adapter.execute(stmt, [])\n }\n await markApplied(adapter, tableName, migration.name)\n const durationMs = performance.now() - t0\n await opts.onAfterMigrate?.({ name: migration.name, sql: migration.sql, durationMs })\n results.push({ name: migration.name, success: true, duration: Math.round(durationMs) })\n } catch (err) {\n const error = err instanceof Error ? err : new Error(String(err))\n await opts.onError?.({ name: migration.name, error })\n results.push({ name: migration.name, success: false, duration: Math.round(performance.now() - t0), error })\n break\n }\n }\n return results\n}\n\nexport async function status(adapter: VelnAdapter, opts: MigratorOptions): Promise<MigrationStatus[]> {\n const tableName = opts.tableName ?? '_veln_migrations'\n\n await ensureTable(adapter, tableName)\n\n const files = await readMigrationFiles(opts.migrationsDir)\n const applied = await getApplied(adapter, tableName)\n const appliedMap = new Map(applied.map(r => [r.name, r]))\n\n return files.map(f => {\n const record = appliedMap.get(f.name)\n if (record) {\n return { name: f.name, status: 'applied' as const, appliedAt: record.appliedAt }\n }\n return { name: f.name, status: 'pending' as const }\n })\n}\n\nexport async function rollback(adapter: VelnAdapter, opts: MigratorOptions): Promise<void> {\n const tableName = opts.tableName ?? '_veln_migrations'\n\n await ensureTable(adapter, tableName)\n\n const applied = await getApplied(adapter, tableName)\n if (applied.length === 0) return\n\n const last = applied[applied.length - 1]\n await markRolledBack(adapter, tableName, last.name)\n}\n","import type { VelnAdapter } from '../../adapter/types'\nimport type { MigrationRecord } from './types'\n\nconst CREATE_TRACKING_TABLE = `\n CREATE TABLE IF NOT EXISTS \"_veln_migrations\" (\n \"id\" INTEGER PRIMARY KEY AUTOINCREMENT,\n \"name\" TEXT NOT NULL UNIQUE,\n \"applied_at\" TEXT NOT NULL\n )\n`\n\nexport async function ensureTable(adapter: VelnAdapter, tableName: string): Promise<void> {\n const sql = CREATE_TRACKING_TABLE.replace('\"_veln_migrations\"', `\"${tableName}\"`)\n await adapter.execute(sql)\n}\n\nexport async function getApplied(adapter: VelnAdapter, tableName: string): Promise<MigrationRecord[]> {\n const rows = await adapter.query<{ id: number; name: string; applied_at: string }>(\n `SELECT \"id\", \"name\", \"applied_at\" FROM \"${tableName}\" ORDER BY \"id\" ASC`,\n )\n return rows.map(r => ({\n id: r.id,\n name: r.name,\n appliedAt: new Date(r.applied_at),\n }))\n}\n\nexport async function markApplied(adapter: VelnAdapter, tableName: string, name: string): Promise<void> {\n await adapter.execute(\n `INSERT INTO \"${tableName}\" (\"name\", \"applied_at\") VALUES (?, ?)`,\n [name, new Date().toISOString()],\n )\n}\n\nexport async function markRolledBack(adapter: VelnAdapter, tableName: string, name: string): Promise<void> {\n await adapter.execute(\n `DELETE FROM \"${tableName}\" WHERE \"name\" = ?`,\n [name],\n )\n}\n","import type { VelnAdapter } from '../../adapter/types'\nimport type { AdapterConfig } from '../../adapter/resolve'\nimport { resolveAdapter } from '../../adapter/resolve'\nimport type { MigrationResult, MigrationStatus, MigratorOptions } from './types'\nimport { run, status, rollback } from './runner'\n\nexport interface Migrator {\n run(): Promise<MigrationResult[]>\n status(): Promise<MigrationStatus[]>\n rollback(): Promise<void>\n}\n\nexport function createMigrator(adapterOrConfig: AdapterConfig | VelnAdapter, options: MigratorOptions): Migrator {\n const adapter = resolveAdapter(adapterOrConfig)\n return {\n run: () => run(adapter, options),\n status: () => status(adapter, options),\n rollback: () => rollback(adapter, options),\n }\n}\n","import { readdir, writeFile } from 'node:fs/promises'\nimport { join } from 'node:path'\nimport type { VelnAdapter } from '../../adapter/types'\nimport type { TableDef } from '../../schema/table'\nimport type { SchemaMap } from '../../schema/table'\nimport type { SchemaDiff, ColumnDef } from './types'\nimport { introspectSchema } from './introspect'\nimport { compareSchemas } from './diff'\n\nexport interface GenerateOptions {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n tables: TableDef<any, SchemaMap>[]\n adapter: VelnAdapter\n migrationsDir: string\n name?: string\n /**\n * When true, generates executable SQL for column drops and type changes\n * instead of commented-out warnings.\n *\n * @remarks\n * ⚠️ DESTRUCTIVE: Generates SQL that permanently drops columns or changes types.\n * Always review generated migrations before applying in production.\n * Back up your database before running destructive migrations.\n */\n allowDestructive?: boolean\n}\n\nexport interface GenerateResult {\n filename: string\n sql: string\n isEmpty: boolean\n}\n\nasync function nextMigrationNumber(dir: string): Promise<number> {\n let entries: string[]\n try {\n entries = await readdir(dir)\n } catch {\n return 1\n }\n\n const nums = entries\n .filter(f => f.endsWith('.sql'))\n .map(f => {\n const match = /^(\\d+)/.exec(f)\n return match ? parseInt(match[1], 10) : 0\n })\n\n return nums.length === 0 ? 1 : Math.max(...nums) + 1\n}\n\nfunction formatNumber(n: number): string {\n return String(n).padStart(4, '0')\n}\n\nfunction columnToSql(col: ColumnDef): string {\n let def = `\"${col.name}\" ${col.type}`\n if (col.primaryKey) def += ' PRIMARY KEY'\n if (!col.nullable && !col.primaryKey) def += ' NOT NULL'\n if (col.unique) def += ' UNIQUE'\n if (col.default !== undefined) def += ` DEFAULT ${col.default}`\n return def\n}\n\nfunction generateSql(diff: SchemaDiff, allowDestructive = false): string {\n const lines: string[] = []\n\n // Added tables → CREATE TABLE IF NOT EXISTS\n for (const table of diff.addedTables) {\n const cols = table.columns.map(columnToSql)\n lines.push(`CREATE TABLE IF NOT EXISTS \"${table.name}\" (`)\n lines.push(cols.map((c, i) => ` ${c}${i < cols.length - 1 ? ',' : ''}`).join('\\n'))\n lines.push(');')\n lines.push('')\n\n for (const idx of table.indexes) {\n const unique = idx.unique ? 'UNIQUE ' : ''\n const cols = idx.columns.map(c => `\"${c}\"`).join(', ')\n lines.push(`CREATE ${unique}INDEX IF NOT EXISTS \"${idx.name}\" ON \"${table.name}\" (${cols});`)\n lines.push('')\n }\n }\n\n // Dropped tables\n for (const name of diff.droppedTables) {\n if (allowDestructive) {\n lines.push(`DROP TABLE IF EXISTS \"${name}\";`)\n } else {\n lines.push(`-- WARNING: DROP TABLE \"${name}\" -- uncomment to apply`)\n }\n lines.push('')\n }\n\n // Modified tables\n for (const mod of diff.modifiedTables) {\n for (const col of mod.addedColumns) {\n const colSql = columnToSql(col)\n lines.push(`ALTER TABLE \"${mod.name}\" ADD COLUMN ${colSql};`)\n lines.push('')\n }\n\n for (const name of mod.droppedColumns) {\n if (allowDestructive) {\n lines.push(`ALTER TABLE \"${mod.name}\" DROP COLUMN \"${name}\";`)\n } else {\n lines.push(`-- WARNING: ALTER TABLE \"${mod.name}\" DROP COLUMN \"${name}\" -- uncomment to apply`)\n }\n lines.push('')\n }\n\n for (const change of mod.modifiedColumns) {\n if (allowDestructive) {\n lines.push(`ALTER TABLE \"${mod.name}\" ALTER COLUMN \"${change.name}\" TYPE ${change.after.type};`)\n } else {\n lines.push(`-- WARNING: column type change for \"${mod.name}\".\"${change.name}\" requires manual migration`)\n lines.push(`-- before: ${change.before.type}`)\n lines.push(`-- after: ${change.after.type}`)\n }\n lines.push('')\n }\n\n for (const idx of mod.addedIndexes) {\n const unique = idx.unique ? 'UNIQUE ' : ''\n const cols = idx.columns.map(c => `\"${c}\"`).join(', ')\n lines.push(`CREATE ${unique}INDEX IF NOT EXISTS \"${idx.name}\" ON \"${mod.name}\" (${cols});`)\n lines.push('')\n }\n\n for (const name of mod.droppedIndexes) {\n lines.push(`DROP INDEX IF EXISTS \"${name}\";`)\n lines.push('')\n }\n }\n\n return lines.join('\\n').trimEnd()\n}\n\nexport async function generateMigration(options: GenerateOptions): Promise<GenerateResult> {\n const current = await introspectSchema(options.adapter)\n const diff = compareSchemas(current, options.tables)\n\n const isEmpty =\n diff.addedTables.length === 0 &&\n diff.droppedTables.length === 0 &&\n diff.modifiedTables.length === 0\n\n const sql = isEmpty ? '' : generateSql(diff, options.allowDestructive ?? false)\n\n const num = await nextMigrationNumber(options.migrationsDir)\n const suffix = options.name ?? new Date().toISOString().replace(/[-T:.Z]/g, '').slice(0, 15)\n const filename = `${formatNumber(num)}_${suffix}.sql`\n\n if (!isEmpty) {\n await writeFile(join(options.migrationsDir, filename), sql + '\\n', 'utf8')\n }\n\n return { filename, sql, isEmpty }\n}\n","import type { VelnAdapter } from '../../adapter/types'\nimport type { TableDiff, ColumnDef, IndexDef } from './types'\n\n// Internal table names to ignore during introspection\nconst IGNORED_TABLES = new Set([\n '_veln_migrations',\n 'sqlite_sequence',\n 'sqlite_stat1',\n 'sqlite_master',\n])\n\ninterface PragmaTableInfo {\n cid: number\n name: string\n type: string\n notnull: number\n dflt_value: string | null\n pk: number\n}\n\ninterface PragmaIndexList {\n seq: number\n name: string\n unique: number\n origin: string\n partial: number\n}\n\ninterface PragmaIndexInfo {\n seqno: number\n cid: number\n name: string\n}\n\ninterface InformationSchemaColumn {\n column_name: string\n data_type: string\n is_nullable: string\n column_default: string | null\n ordinal_position: number\n}\n\ninterface InformationSchemaConstraint {\n column_name: string\n constraint_type: string\n constraint_name: string\n}\n\ninterface MySQLColumn {\n COLUMN_NAME: string\n DATA_TYPE: string\n IS_NULLABLE: string\n COLUMN_DEFAULT: string | null\n COLUMN_KEY: string\n EXTRA: string\n}\n\ninterface MySQLIndex {\n INDEX_NAME: string\n COLUMN_NAME: string\n NON_UNIQUE: number\n}\n\nasync function introspectSQLite(adapter: VelnAdapter): Promise<Map<string, TableDiff>> {\n const tables = await adapter.query<{ name: string }>(\n `SELECT name FROM sqlite_master WHERE type='table' ORDER BY name`,\n )\n\n const result = new Map<string, TableDiff>()\n\n for (const { name } of tables) {\n if (IGNORED_TABLES.has(name)) continue\n\n const columns = await adapter.query<PragmaTableInfo>(`PRAGMA table_info(\"${name}\")`)\n const indexList = await adapter.query<PragmaIndexList>(`PRAGMA index_list(\"${name}\")`)\n\n const columnDefs: ColumnDef[] = columns.map(col => ({\n name: col.name,\n type: col.type.toUpperCase(),\n nullable: col.notnull === 0 && col.pk === 0,\n default: col.dflt_value ?? undefined,\n primaryKey: col.pk > 0,\n unique: false, // determined from indexes\n }))\n\n const indexes: IndexDef[] = []\n for (const idx of indexList) {\n // Skip auto-created indexes for PRIMARY KEY and UNIQUE constraints on columns\n if (idx.origin === 'pk') continue\n\n const idxInfo = await adapter.query<PragmaIndexInfo>(`PRAGMA index_info(\"${idx.name}\")`)\n const idxCols = idxInfo.sort((a, b) => a.seqno - b.seqno).map(i => i.name)\n\n // Mark column as unique if single-column unique index\n if (idx.unique && idxCols.length === 1) {\n const col = columnDefs.find(c => c.name === idxCols[0])\n if (col) col.unique = true\n }\n\n indexes.push({\n name: idx.name,\n columns: idxCols,\n unique: idx.unique === 1,\n })\n }\n\n result.set(name, { name, columns: columnDefs, indexes })\n }\n\n return result\n}\n\nasync function introspectPostgres(adapter: VelnAdapter, tableName?: string): Promise<Map<string, TableDiff>> {\n const tableFilter = tableName ? `AND t.table_name = '${tableName}'` : ''\n\n const columns = await adapter.query<InformationSchemaColumn>(`\n SELECT\n c.column_name,\n c.data_type,\n c.is_nullable,\n c.column_default,\n c.ordinal_position\n FROM information_schema.columns c\n JOIN information_schema.tables t\n ON t.table_name = c.table_name AND t.table_schema = c.table_schema\n WHERE t.table_schema = 'public'\n AND t.table_type = 'BASE TABLE'\n ${tableFilter}\n ORDER BY c.table_name, c.ordinal_position\n `)\n\n const constraints = await adapter.query<InformationSchemaConstraint & { table_name: string }>(`\n SELECT\n kcu.column_name,\n tc.constraint_type,\n tc.constraint_name,\n kcu.table_name\n FROM information_schema.table_constraints tc\n JOIN information_schema.key_column_usage kcu\n ON tc.constraint_name = kcu.constraint_name AND tc.table_schema = kcu.table_schema\n WHERE tc.table_schema = 'public'\n AND tc.constraint_type IN ('PRIMARY KEY', 'UNIQUE')\n `)\n\n const pkMap = new Map<string, Set<string>>()\n const uniqueMap = new Map<string, Set<string>>()\n for (const c of constraints) {\n const tbl = c.table_name\n if (c.constraint_type === 'PRIMARY KEY') {\n if (!pkMap.has(tbl)) pkMap.set(tbl, new Set())\n pkMap.get(tbl)!.add(c.column_name)\n } else if (c.constraint_type === 'UNIQUE') {\n if (!uniqueMap.has(tbl)) uniqueMap.set(tbl, new Set())\n uniqueMap.get(tbl)!.add(c.column_name)\n }\n }\n\n const tableMap = new Map<string, TableDiff>()\n for (const col of columns) {\n // Extract table name from the query — we need to join differently\n // We'll re-query with table_name included\n break\n }\n\n // Re-query with table_name\n const fullColumns = await adapter.query<InformationSchemaColumn & { table_name: string }>(`\n SELECT\n c.table_name,\n c.column_name,\n c.data_type,\n c.is_nullable,\n c.column_default,\n c.ordinal_position\n FROM information_schema.columns c\n JOIN information_schema.tables t\n ON t.table_name = c.table_name AND t.table_schema = c.table_schema\n WHERE t.table_schema = 'public'\n AND t.table_type = 'BASE TABLE'\n ${tableFilter}\n ORDER BY c.table_name, c.ordinal_position\n `)\n\n for (const col of fullColumns) {\n const tbl = col.table_name\n if (IGNORED_TABLES.has(tbl)) continue\n\n if (!tableMap.has(tbl)) tableMap.set(tbl, { name: tbl, columns: [], indexes: [] })\n\n const tableDiff = tableMap.get(tbl)!\n tableDiff.columns.push({\n name: col.column_name,\n type: col.data_type.toUpperCase(),\n nullable: col.is_nullable === 'YES',\n default: col.column_default ?? undefined,\n primaryKey: pkMap.get(tbl)?.has(col.column_name) ?? false,\n unique: uniqueMap.get(tbl)?.has(col.column_name) ?? false,\n })\n }\n\n return tableMap\n}\n\nasync function introspectMySQL(adapter: VelnAdapter): Promise<Map<string, TableDiff>> {\n const dbRow = await adapter.query<{ database: string }>(`SELECT DATABASE() AS \\`database\\``)\n const dbName = dbRow[0]?.database ?? ''\n\n const columns = await adapter.query<MySQLColumn & { TABLE_NAME: string }>(`\n SELECT\n TABLE_NAME,\n COLUMN_NAME,\n DATA_TYPE,\n IS_NULLABLE,\n COLUMN_DEFAULT,\n COLUMN_KEY,\n EXTRA\n FROM information_schema.COLUMNS\n WHERE TABLE_SCHEMA = '${dbName}'\n ORDER BY TABLE_NAME, ORDINAL_POSITION\n `)\n\n const indexes = await adapter.query<MySQLIndex & { TABLE_NAME: string }>(`\n SELECT\n TABLE_NAME,\n INDEX_NAME,\n COLUMN_NAME,\n NON_UNIQUE\n FROM information_schema.STATISTICS\n WHERE TABLE_SCHEMA = '${dbName}'\n ORDER BY TABLE_NAME, INDEX_NAME, SEQ_IN_INDEX\n `)\n\n const tableMap = new Map<string, TableDiff>()\n\n for (const col of columns) {\n const tbl = col.TABLE_NAME\n if (IGNORED_TABLES.has(tbl)) continue\n\n if (!tableMap.has(tbl)) tableMap.set(tbl, { name: tbl, columns: [], indexes: [] })\n\n tableMap.get(tbl)!.columns.push({\n name: col.COLUMN_NAME,\n type: col.DATA_TYPE.toUpperCase(),\n nullable: col.IS_NULLABLE === 'YES',\n default: col.COLUMN_DEFAULT ?? undefined,\n primaryKey: col.COLUMN_KEY === 'PRI',\n unique: col.COLUMN_KEY === 'UNI',\n })\n }\n\n // Group index rows into IndexDef entries\n const indexBuffer = new Map<string, { tableName: string; name: string; columns: string[]; unique: boolean }>()\n for (const idx of indexes) {\n const key = `${idx.TABLE_NAME}.${idx.INDEX_NAME}`\n if (!indexBuffer.has(key)) {\n indexBuffer.set(key, {\n tableName: idx.TABLE_NAME,\n name: idx.INDEX_NAME,\n columns: [],\n unique: idx.NON_UNIQUE === 0,\n })\n }\n indexBuffer.get(key)!.columns.push(idx.COLUMN_NAME)\n }\n\n for (const entry of indexBuffer.values()) {\n const tbl = tableMap.get(entry.tableName)\n if (!tbl) continue\n if (entry.name === 'PRIMARY') continue // already captured via primaryKey flag\n tbl.indexes.push({ name: entry.name, columns: entry.columns, unique: entry.unique })\n }\n\n return tableMap\n}\n\n/**\n * Detect adapter type and introspect the current DB schema.\n * Returns a map of table name → TableDiff.\n */\nexport async function introspectSchema(adapter: VelnAdapter): Promise<Map<string, TableDiff>> {\n // Probe: if sqlite_master exists → SQLite\n try {\n await adapter.query(`SELECT 1 FROM sqlite_master LIMIT 1`)\n return introspectSQLite(adapter)\n } catch {\n // Not SQLite — try Postgres\n }\n\n try {\n await adapter.query(`SELECT current_database()`)\n return introspectPostgres(adapter)\n } catch {\n // Not Postgres — try MySQL\n }\n\n return introspectMySQL(adapter)\n}\n","import type { TableDef as TableDefSchema } from '../../schema/table'\nimport type { Column } from '../../schema/column'\nimport type { SchemaMap } from '../../schema/table'\nimport type {\n SchemaDiff,\n TableDiff,\n TableModification,\n ColumnDef,\n IndexDef,\n ColumnModification,\n} from './types'\n\nfunction tableDefToColumnDefs(schema: SchemaMap): ColumnDef[] {\n return Object.entries(schema).map(([name, col]) => {\n const c = col as Column<unknown>\n\n // Map SqlType → generic SQL type string\n let type: string\n switch (c.def.type) {\n case 'INTEGER': type = 'INTEGER'; break\n case 'TEXT':\n case 'UUID': type = 'TEXT'; break\n case 'REAL': type = 'REAL'; break\n case 'BOOLEAN': type = 'INTEGER'; break // SQLite stores as INTEGER\n case 'TIMESTAMP': type = 'TEXT'; break // ISO string\n case 'JSON': type = 'TEXT'; break\n case 'BLOB': type = 'BLOB'; break\n default: type = 'TEXT'; break\n }\n\n return {\n name,\n type,\n nullable: c.def.nullable,\n default: c.def.defaultValue !== undefined ? String(c.def.defaultValue) : undefined,\n primaryKey: c.def.primaryKey,\n unique: c.def.unique,\n }\n })\n}\n\nfunction columnsEqual(a: ColumnDef, b: ColumnDef): boolean {\n return (\n a.type === b.type &&\n a.nullable === b.nullable &&\n a.primaryKey === b.primaryKey &&\n a.unique === b.unique &&\n (a.default ?? null) === (b.default ?? null)\n )\n}\n\nexport function compareSchemas(\n current: Map<string, TableDiff>,\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n target: TableDefSchema<any, SchemaMap>[],\n): SchemaDiff {\n const addedTables: TableDiff[] = []\n const droppedTables: string[] = []\n const modifiedTables: TableModification[] = []\n\n const targetNames = new Set(target.map(t => t.name))\n\n // Dropped tables: in current but not in target\n for (const [name] of current) {\n if (!targetNames.has(name)) {\n droppedTables.push(name)\n }\n }\n\n for (const table of target) {\n const currentTable = current.get(table.name)\n const targetColumns = tableDefToColumnDefs(table.schema)\n\n if (!currentTable) {\n // New table\n addedTables.push({\n name: table.name,\n columns: targetColumns,\n indexes: [], // TODO: index extraction from schema when supported\n })\n continue\n }\n\n // Compare columns\n const currentColMap = new Map(currentTable.columns.map(c => [c.name, c]))\n const targetColMap = new Map(targetColumns.map(c => [c.name, c]))\n\n const addedColumns: ColumnDef[] = []\n const droppedColumns: string[] = []\n const modifiedColumns: ColumnModification[] = []\n const addedIndexes: IndexDef[] = []\n const droppedIndexes: string[] = []\n\n for (const [name, col] of targetColMap) {\n const existing = currentColMap.get(name)\n if (!existing) {\n addedColumns.push(col)\n } else if (!columnsEqual(existing, col)) {\n modifiedColumns.push({ name, before: existing, after: col })\n }\n }\n\n for (const [name] of currentColMap) {\n if (!targetColMap.has(name)) {\n droppedColumns.push(name)\n }\n }\n\n const hasChanges =\n addedColumns.length > 0 ||\n droppedColumns.length > 0 ||\n modifiedColumns.length > 0 ||\n addedIndexes.length > 0 ||\n droppedIndexes.length > 0\n\n if (hasChanges) {\n modifiedTables.push({\n name: table.name,\n addedColumns,\n droppedColumns,\n modifiedColumns,\n addedIndexes,\n droppedIndexes,\n })\n }\n }\n\n return { addedTables, droppedTables, modifiedTables }\n}\n","import type { VelnEvents } from './index'\nimport type { Logger, BaseOptions } from '../app/types'\nimport type { ServiceDef } from '../service/index'\nimport { createMinimalLogger } from '../app/logger'\n\nexport type EventCallback = (payload: unknown) => void | Promise<void>\nexport type EventHandlerFn<TPayload, TServices extends Record<string, unknown> = Record<never, never>> = (\n payload: TPayload,\n ctx: { logger: Logger } & TServices,\n) => void | Promise<void>\n\n// RawHandler — (payload, ctx) called by app.events() when services are present.\n// ctx is assembled by the caller (logger + instantiated services).\nexport type RawHandler = (payload: unknown, ctx: Record<string, unknown>) => void | Promise<void>\n\nexport interface EventHandlerDef {\n readonly _handlers: Map<string, EventCallback>\n readonly _rawHandlers: Map<string, RawHandler>\n readonly _logger: Logger\n readonly _services: ReadonlyArray<ServiceDef<string, unknown>>\n}\n\n// Structural constraint — matches any TableDef regardless of its generic params\ntype TableLike = { name: string; _eventMap: Record<string, unknown> }\n\n// Infer handler map type from a table's _eventMap\ntype EventHandlerMap<TTable extends TableLike> = Partial<{\n [K in keyof TTable['_eventMap']]: (payload: TTable['_eventMap'][K]) => void | Promise<void>\n}>\n\n// Internal type for stored handlers (payload + ctx)\ntype StoredHandler<TServices extends Record<string, unknown>> = (\n payload: unknown,\n ctx: { logger: Logger } & TServices,\n) => void | Promise<void>\n\n// ── EventHandlerBuilder ───────────────────────────────────────────────────────\n\nexport class EventHandlerBuilder<\n TTable extends TableLike,\n TServices extends Record<string, unknown> = Record<never, never>,\n> {\n private _options: BaseOptions = {}\n private _handlerMap: Map<string, StoredHandler<Record<string, unknown>>> = new Map()\n private _services: ServiceDef<string, unknown>[] = []\n\n constructor(private readonly _table: TTable) {}\n\n options(opts: BaseOptions): this {\n this._options = opts\n return this\n }\n\n use<TKey extends string, TDef>(\n service: ServiceDef<TKey, TDef>,\n ): EventHandlerBuilder<TTable, TServices & Record<TKey, TDef>> {\n const next = new EventHandlerBuilder<TTable, TServices & Record<TKey, TDef>>(this._table)\n next._options = this._options\n next._handlerMap = this._handlerMap\n next._services = [...this._services, service as ServiceDef<string, unknown>]\n return next\n }\n\n on<TEvent extends string & keyof TTable['_eventMap']>(\n event: TEvent,\n handler: (\n payload: TTable['_eventMap'][TEvent],\n ctx: { logger: Logger } & TServices,\n ) => void | Promise<void>,\n ): this {\n this._handlerMap.set(event, handler as StoredHandler<Record<string, unknown>>)\n return this\n }\n\n // Fluent path — wraps all .on() handlers with logger + service injection\n build(): EventHandlerDef\n // Legacy path — builds EventHandlerDef from a plain handler map (no logger injection)\n build(handlers: EventHandlerMap<TTable>): EventHandlerDef\n build(handlers?: EventHandlerMap<TTable>): EventHandlerDef {\n const logger = createMinimalLogger(`event:${this._table.name}`, this._options.log)\n const services = this._services\n\n if (handlers !== undefined) {\n const map = new Map<string, EventCallback>()\n for (const [key, fn] of Object.entries(handlers)) {\n if (fn) map.set(key, fn as EventCallback)\n }\n return {\n _handlers: map,\n _rawHandlers: new Map(),\n _logger: logger,\n _services: [],\n }\n }\n\n // Logger-only fallback in _handlers (used when no services declared).\n // Raw handlers in _rawHandlers (used by app.events() when services are present).\n const wrapped = new Map<string, EventCallback>()\n const rawHandlers = new Map<string, RawHandler>()\n for (const [event, handler] of this._handlerMap) {\n wrapped.set(event, (payload) =>\n handler(payload, { logger } as { logger: Logger } & Record<string, unknown>),\n )\n rawHandlers.set(event, handler as RawHandler)\n }\n return {\n _handlers: wrapped,\n _rawHandlers: rawHandlers,\n _logger: logger,\n _services: services,\n }\n }\n}\n\n// ── defineEventHandler ────────────────────────────────────────────────────────\n\n// Overload 1 — legacy table-bound (two args) → EventHandlerDef directly\nexport function defineEventHandler<TTable extends TableLike>(\n table: TTable,\n handlers: EventHandlerMap<TTable>,\n): EventHandlerDef\n\n// Overload 2 — fluent builder (one table arg) → EventHandlerBuilder\nexport function defineEventHandler<TTable extends TableLike>(\n table: TTable,\n): EventHandlerBuilder<TTable>\n\n// Overload 3 — free (plain string keys, VelnEvents) → EventHandlerDef\nexport function defineEventHandler(\n handlers: Partial<{ [K in keyof VelnEvents]: (payload: VelnEvents[K]) => void | Promise<void> }>,\n): EventHandlerDef\n\nexport function defineEventHandler<TTable extends TableLike>(\n tableOrHandlers: TTable | Partial<Record<string, EventCallback>>,\n maybeHandlers?: EventHandlerMap<TTable>,\n): EventHandlerBuilder<TTable> | EventHandlerDef {\n // Two args → legacy table-bound overload\n if (maybeHandlers !== undefined) {\n return new EventHandlerBuilder(tableOrHandlers as TTable).build(maybeHandlers)\n }\n\n // One arg with `_eventMap` → TableLike → fluent builder\n if ('_eventMap' in tableOrHandlers) {\n return new EventHandlerBuilder(tableOrHandlers as TTable)\n }\n\n // One arg without `_eventMap` → plain handler map → free overload\n const raw = tableOrHandlers as Partial<Record<string, EventCallback>>\n const map = new Map<string, EventCallback>()\n for (const [key, fn] of Object.entries(raw)) {\n if (fn) map.set(key, fn)\n }\n return { _handlers: map, _rawHandlers: new Map(), _logger: createMinimalLogger('event'), _services: [] }\n}\n","import type { BoundVelnDB } from '../db/index'\nimport type { TableDef, SchemaMap } from '../schema/table'\nimport type { Logger, BaseOptions } from '../app/types'\nimport { createMinimalLogger } from '../app/logger'\n\n// ModelInstance — the user's factory result merged with { db: BoundVelnDB }.\n// .db gives direct raw access: UserModel.db.into(usersTable).insert(...)\nexport type ModelInstance<TDef> = TDef & { readonly db: BoundVelnDB }\n\n// ModelDef — carries the name (= dep key) + factory.\n// Never holds a db reference — instantiated per-request via .use().\nexport interface ModelDef<TName extends string, TDef> {\n readonly _modelName: TName\n readonly _factory: (db: BoundVelnDB) => ModelInstance<TDef>\n}\n\n// ── ModelBuilder ──────────────────────────────────────────────────────────────\n\nexport class ModelBuilder<TName extends string, TTable> {\n private _opts: BaseOptions = {}\n\n constructor(\n private readonly _name: TName,\n private readonly _table: TTable,\n ) {}\n\n options(opts: BaseOptions): this {\n this._opts = opts\n return this\n }\n\n define<TDef extends object>(\n factory: (db: BoundVelnDB, ctx: { logger: Logger }) => TDef,\n ): ModelDef<TName, TDef> {\n const name = this._name\n const opts = this._opts\n return {\n _modelName: name,\n _factory: (db: BoundVelnDB): ModelInstance<TDef> => {\n const logger = createMinimalLogger(`model:${name}`, opts.log)\n return { ...factory(db, { logger }), db }\n },\n }\n }\n}\n\n// ── defineModel — entry point ─────────────────────────────────────────────────\n//\n// Two call forms:\n// Builder (new): defineModel(name, table)\n// .options({ log: { level: 'debug' } })\n// .define((db, { logger }) => ({ ... }))\n//\n// Direct (compat): defineModel(name, table, (db) => ({ ... }))\n// The 3-arg form is kept for existing code. Extra { logger } arg\n// is injected but callers that ignore it continue to work.\n\nexport function defineModel<\n TName extends string,\n TTable,\n>(\n name: TName,\n table: TTable,\n): ModelBuilder<TName, TTable>\n\nexport function defineModel<\n TName extends string,\n TTable,\n TDef extends object,\n>(\n name: TName,\n table: TTable,\n factory: (db: BoundVelnDB, ctx: { logger: Logger }) => TDef,\n): ModelDef<TName, TDef>\n\nexport function defineModel<\n TName extends string,\n TTable,\n TDef extends object,\n>(\n name: TName,\n table: TTable,\n factory?: (db: BoundVelnDB, ctx: { logger: Logger }) => TDef,\n): ModelBuilder<TName, TTable> | ModelDef<TName, TDef> {\n if (factory !== undefined) {\n // Direct (compat) form — wrap in builder immediately\n return new ModelBuilder<TName, TTable>(name, table).define(factory)\n }\n return new ModelBuilder<TName, TTable>(name, table)\n}\n","import type { BoundVelnDB } from '../db/index'\nimport type { ModelDef, ModelInstance } from '../model/index'\nimport type { BaseOptions } from '../app/types'\nimport { createMinimalLogger } from '../app/logger'\n\n// ── Dep union — accepted by ServiceBuilder.use() ──────────────────────────\n\n// A dependency is a ModelDef or ServiceDef.\nexport type Dep<TKey extends string, TDef> =\n | ModelDef<TKey, TDef>\n | ServiceDef<TKey, TDef>\n\n// Helper — extract the key from any Dep kind\ntype DepKey<D> = D extends ModelDef<infer K, unknown> ? K\n : D extends ServiceDef<infer K, unknown> ? K\n : never\n\n// Helper — extract the instance type from any Dep kind\ntype DepInst<D> = D extends ModelDef<string, infer T> ? ModelInstance<T>\n : D extends ServiceDef<string, infer T> ? T\n : never\n\n// ── ServiceDef ─────────────────────────────────────────────────────────────\n\nexport interface ServiceDef<TKey extends string, TDef> {\n readonly _serviceKey: TKey\n readonly _deps: ReadonlyArray<Dep<string, unknown>>\n readonly _options: BaseOptions\n readonly _factory: (deps: Record<string, unknown>) => TDef\n}\n\n// ── ServiceBuilder ─────────────────────────────────────────────────────────\n\nexport class ServiceBuilder<TKey extends string, TDeps extends Record<string, unknown>> {\n private constructor(\n private readonly _key: TKey,\n private readonly _deps: ReadonlyArray<Dep<string, unknown>>,\n private readonly _opts: BaseOptions,\n ) {}\n\n static create<TKey extends string>(key: TKey): ServiceBuilder<TKey, Record<never, never>> {\n return new ServiceBuilder<TKey, Record<never, never>>(key, [], {})\n }\n\n use<TDep extends Dep<string, unknown>>(\n dep: TDep,\n ): ServiceBuilder<TKey, TDeps & Record<DepKey<TDep>, DepInst<TDep>>> {\n return new ServiceBuilder<TKey, TDeps & Record<DepKey<TDep>, DepInst<TDep>>>(\n this._key,\n [...this._deps, dep as Dep<string, unknown>],\n this._opts,\n )\n }\n\n options(opts: BaseOptions): ServiceBuilder<TKey, TDeps> {\n return new ServiceBuilder<TKey, TDeps>(\n this._key,\n this._deps,\n opts,\n )\n }\n\n define<TDef>(\n factory: (deps: TDeps & Record<'logger', import('../app/types').Logger>) => TDef,\n ): ServiceDef<TKey, TDef> {\n return {\n _serviceKey: this._key,\n _deps: this._deps,\n _options: this._opts,\n _factory: factory as (deps: Record<string, unknown>) => TDef,\n }\n }\n}\n\nexport function defineService<TKey extends string>(\n key: TKey,\n): ServiceBuilder<TKey, Record<never, never>> {\n return ServiceBuilder.create(key)\n}\n\n// ── Per-request instantiation helpers ────────────────────────────────────\n// Used by the framework in fetch() — not exported from core public API.\n\n// isModelDef — runtime discriminator\nfunction isModelDef(dep: Dep<string, unknown>): dep is ModelDef<string, unknown> {\n return '_modelName' in dep\n}\n\n// isServiceDef — runtime discriminator\nfunction isServiceDef(dep: Dep<string, unknown>): dep is ServiceDef<string, unknown> {\n return '_serviceKey' in dep\n}\n\n// detectCircular — throws if any cycle exists in the dep graph.\n// Called once at startup (first fetch). O(V+E).\nexport function detectCircular(services: ReadonlyArray<ServiceDef<string, unknown>>): void {\n // Build a name → ServiceDef map transitively — includes nested service deps,\n // not just the top-level services passed in.\n const byKey = new Map<string, ServiceDef<string, unknown>>()\n\n function collectAll(svc: ServiceDef<string, unknown>): void {\n if (byKey.has(svc._serviceKey)) return\n byKey.set(svc._serviceKey, svc)\n for (const dep of svc._deps) {\n if (isServiceDef(dep)) {\n collectAll(dep)\n }\n }\n }\n\n for (const svc of services) {\n collectAll(svc)\n }\n\n // DFS with three-color marking: 0=unvisited, 1=in-stack, 2=done\n const state = new Map<string, 0 | 1 | 2>()\n\n function visit(key: string, stack: string[]): void {\n const s = state.get(key) ?? 0\n if (s === 2) return\n if (s === 1) {\n const cycle = [...stack, key].join(' → ')\n throw new Error(`[veln] Circular dependency detected: ${cycle}`)\n }\n state.set(key, 1)\n const svc = byKey.get(key)\n if (svc) {\n for (const dep of svc._deps) {\n if (isServiceDef(dep)) {\n visit(dep._serviceKey, [...stack, key])\n }\n }\n }\n state.set(key, 2)\n }\n\n for (const svc of byKey.values()) {\n visit(svc._serviceKey, [])\n }\n}\n\n// instantiateServices — per-request.\n// Builds all declared services (and their transitive model/service deps) with the given db.\n// Returns a Record<key, instance> to be merged into ctx.\nexport function instantiateServices(\n services: ReadonlyArray<ServiceDef<string, unknown>>,\n db: BoundVelnDB,\n): Record<string, unknown> {\n // Cache within this request — each dep key instantiated at most once\n const cache = new Map<string, unknown>()\n\n function instantiateDep(dep: Dep<string, unknown>, ownerKey: string): unknown {\n if (isModelDef(dep)) {\n const key = dep._modelName\n if (cache.has(key)) return cache.get(key)\n const inst = dep._factory(db)\n cache.set(key, inst)\n return inst\n }\n if (isServiceDef(dep)) {\n const key = dep._serviceKey\n if (cache.has(key)) return cache.get(key)\n const resolvedDeps: Record<string, unknown> = {}\n // Always inject logger for the service being instantiated\n const logger = createMinimalLogger(`service:${key}`, dep._options?.log)\n resolvedDeps['logger'] = logger\n for (const d of dep._deps) {\n const depKey = isModelDef(d) ? d._modelName : d._serviceKey\n resolvedDeps[depKey] = instantiateDep(d, key)\n }\n const inst = dep._factory(resolvedDeps)\n cache.set(key, inst)\n return inst\n }\n throw new Error(`[veln] Unknown dependency type in service '${ownerKey}'`)\n }\n\n const result: Record<string, unknown> = {}\n for (const svc of services) {\n result[svc._serviceKey] = instantiateDep(svc, svc._serviceKey)\n }\n return result\n}\n","import type { Logger, BaseOptions, OnRequestFn, OnResponseFn } from './types'\nimport { createMinimalLogger } from './logger'\n\n// ── MiddlewareDef — sealed result of MiddlewareBuilder.build() ────────────────\n\nexport interface MiddlewareDef {\n readonly _name: string\n readonly _onRequest?: OnRequestFn\n readonly _onResponse?: OnResponseFn\n readonly _logger: Logger\n}\n\n// ── MiddlewareBuilder ─────────────────────────────────────────────────────────\n\nexport class MiddlewareBuilder {\n private _options: BaseOptions = {}\n private _onRequestFn?: OnRequestFn\n private _onResponseFn?: OnResponseFn\n\n constructor(private readonly _name: string) {}\n\n options(opts: BaseOptions): this {\n this._options = opts\n return this\n }\n\n onRequest(fn: OnRequestFn): this {\n this._onRequestFn = fn\n return this\n }\n\n onResponse(fn: OnResponseFn): this {\n this._onResponseFn = fn\n return this\n }\n\n build(): MiddlewareDef {\n const logger = createMinimalLogger(`middleware:${this._name}`, this._options.log)\n return {\n _name: this._name,\n _onRequest: this._onRequestFn,\n _onResponse: this._onResponseFn,\n _logger: logger,\n }\n }\n}\n\n// ── defineMiddleware — entry point ────────────────────────────────────────────\n\nexport function defineMiddleware(name: string): MiddlewareBuilder {\n return new MiddlewareBuilder(name)\n}\n","import type { BaseCtx, Guard, ErrorHandler, RouteHandler, Route, RouteSchema, RouteHandlerWithSchema, InferCtx, RouteMap, OnRequestHook, OnBeforeHandleHook, OnResponseHook, RouteDocs, StreamController, StreamOptions, SseController, VelnWsAdapter, WsRouteShape, AuthAdapter } from './types'\nimport type { NavItem } from './plugin'\nimport { createMinimalLogger } from './logger'\nimport { generateOpenApiSpec } from '../openapi/generator'\nimport type { OpenApiSpec } from '../openapi/generator'\nimport type { ZodTypeAny } from 'zod'\nimport { ValidationError } from './types'\nimport { VelnError, UnauthorizedError, ForbiddenError } from '../errors/index'\nimport type { Plugin } from './plugin'\nimport type { VelnEvents, EventHandler } from '../events/index'\nimport type { EventHandlerDef } from '../events/handler'\nimport type { CronDef, CronLockAdapter } from '../cron/index'\nimport { NoOpCronLockAdapter } from '../cron/index'\nimport { createSystemCtx } from './system-ctx'\nimport { VelnDB } from '../db/index'\nimport type { VelnModule, ServiceDeclaration } from './module'\nimport type { InferTableEvents, TableEventMap, TableDef, SchemaMap } from '../schema/table'\nimport { InMemoryEventBus, RequestEventQueue } from '../events/index'\nimport type { EventBusAdapter } from '../events/index'\nimport { HookExecutor } from '../hooks/executor'\nimport { matchPath, parseQuery } from './router'\nimport { buildAuditHooks } from './audit-wiring'\nimport { createCookieJar } from './cookies'\nimport type { ServiceDef } from '../service/index'\nimport { detectCircular, instantiateServices } from '../service/index'\nimport type { MiddlewareDef } from './middleware'\nimport { createOnRequest, createOnResponse } from './types'\n\ntype HttpMethod = 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE'\n\n// ── ctx.stream() implementation ──────────────────────────────────────────────\n// Creates a ReadableStream from a writer callback.\n// The writer receives a StreamController and can push chunks then close.\nfunction makeStreamResponse(\n writer: (controller: StreamController) => void | Promise<void>,\n options: StreamOptions = {},\n): Response {\n const enc = new TextEncoder()\n const { readable, writable } = new TransformStream<Uint8Array, Uint8Array>()\n const w = writable.getWriter()\n\n const controller: StreamController = {\n send(chunk: string | Uint8Array) {\n const bytes = typeof chunk === 'string' ? enc.encode(chunk) : chunk\n void w.write(bytes)\n },\n close() {\n void w.close()\n },\n }\n\n // Run the writer async — errors close the stream; success path relies on\n // the caller invoking controller.close() explicitly.\n Promise.resolve(writer(controller)).catch(() => { void w.close() })\n\n const headers = new Headers(options.headers)\n headers.set('Content-Type', options.contentType ?? 'text/plain')\n\n return new Response(readable, {\n status: options.status ?? 200,\n headers,\n })\n}\n\n// ── ctx.sse() implementation ──────────────────────────────────────────────────\n// Thin wrapper over makeStreamResponse — enforces SSE headers and wire format.\n//\n// SSE wire format per https://html.spec.whatwg.org/multipage/server-sent-events.html:\n// event: <name>\\n\n// data: <json>\\n\\n\n//\n// data: <json>\\n\\n (unnamed)\n// : <comment>\\n\\n (keepalive)\n// id: <value>\\n\n// retry: <ms>\\n\nfunction makeSSEResponse(\n writer: (controller: SseController) => void | Promise<void>,\n): Response {\n const enc = new TextEncoder()\n const { readable, writable } = new TransformStream<Uint8Array, Uint8Array>()\n const w = writable.getWriter()\n\n function push(frame: string): Promise<void> {\n return w.write(enc.encode(frame))\n }\n\n const controller: SseController = {\n async event(name: string, data: unknown): Promise<void> {\n await push(`event: ${name}\\ndata: ${JSON.stringify(data)}\\n\\n`)\n },\n async data(data: unknown): Promise<void> {\n await push(`data: ${JSON.stringify(data)}\\n\\n`)\n },\n async comment(text = ''): Promise<void> {\n await push(`: ${text}\\n\\n`)\n },\n async id(eventId: string): Promise<void> {\n await push(`id: ${eventId}\\n`)\n },\n async retry(ms: number): Promise<void> {\n await push(`retry: ${ms}\\n`)\n },\n }\n\n // Run the writer — always close the stream when done (success or error).\n // The try/catch on close() guards against Bun throwing when the writer\n // is already in a closing state (e.g. backpressure abort during error path).\n Promise.resolve(writer(controller)).finally(() => { w.close().catch(() => {}) })\n\n return new Response(readable, {\n status: 200,\n headers: {\n 'Content-Type': 'text/event-stream',\n 'Cache-Control': 'no-cache',\n 'Connection': 'keep-alive',\n },\n })\n}\n\n// Bun's BunRequest type — extends Request with .params (populated by native SIMD router)\ntype BunRequest = import('bun').BunRequest<string>\n\n// Type union — function shorthand OR schema object\ntype HandlerArg<TCtx> =\n | ((ctx: TCtx) => Response | Promise<Response>)\n | RouteHandler<TCtx>\n | RouteHandlerWithSchema<TCtx, any>\n\nfunction normalizeHandler<TCtx>(\n handler: HandlerArg<TCtx>,\n): { handler: RouteHandler<TCtx>; schema: RouteSchema | undefined; docs: RouteDocs | undefined } {\n if (typeof handler === 'function') {\n return { handler: { handler: handler as any }, schema: undefined, docs: undefined }\n }\n // RouteHandlerWithSchema has params/query/body/response fields alongside handler\n if ('params' in handler || 'query' in handler || 'body' in handler || 'response' in handler || 'docs' in handler) {\n const h = handler as RouteHandlerWithSchema<TCtx, any>\n return {\n handler: { handler: h.handler as any },\n schema: {\n params: h.params,\n query: h.query,\n body: h.body,\n response: h.response,\n },\n docs: h.docs,\n }\n }\n // Plain RouteHandler { handler: fn }\n return { handler: handler as RouteHandler<TCtx>, schema: undefined, docs: undefined }\n}\n\nexport class Veln<TCtx extends BaseCtx, TRoutes extends RouteMap = Record<never, never>, TPrefixes extends string = never> {\n // Used for type-extraction only — never set or read at runtime\n declare readonly _routes: TRoutes\n declare readonly _prefixes: TPrefixes\n readonly routes: Route<any>[] = []\n private readonly plugins: Plugin<any, any>[] = []\n private readonly globalGuards: Guard<any>[] = []\n // ─── Lifecycle hook registries (strict phase order enforced in fetch()) ───\n private readonly _onRequestHooks: OnRequestHook<any>[] = []\n private readonly _onBeforeHandleHooks: OnBeforeHandleHook<any>[] = []\n private readonly _onResponseHooks: OnResponseHook<any>[] = []\n private globalOnError?: ErrorHandler<any>\n private readonly eventBus: EventBusAdapter\n // Exposed so users can pass it to dbPlugin — app.register() populates this executor\n readonly hooks: HookExecutor\n private installedPlugins = false\n // Tracks which module plugin names have already been installed\n private readonly installedModulePlugins = new Set<string>()\n // Audit declarations collected from register() — wired after plugins install\n private readonly _pendingAuditDeclarations: import('./module').AuditDeclaration<any, any, any>[] = []\n\n private _opts: {\n validateResponse: boolean\n exposeIssues: boolean\n db?: { log?: { enabled?: boolean; n1Threshold?: number; logQueries?: boolean } }\n } = { validateResponse: false, exposeIssues: false }\n // Global service declarations — registered via app.use()\n private readonly _globalServiceDeclarations: ServiceDeclaration<string, unknown>[] = []\n // Circular dep check happens once on first fetch\n private _serviceCircularChecked = false\n // Route-matching cache — keyed by \"METHOD:pathname\", stores match result or null (no match).\n // Only the fetch() fallback path populates this (Bun native routes bypass fetch() entirely).\n // FIFO eviction at _ROUTE_CACHE_MAX entries.\n private _routeCache = new Map<string, { route: Route<unknown>; params: Record<string, string | undefined> } | null>()\n private readonly _ROUTE_CACHE_MAX = 500\n // Cron job definitions — scheduled at listen()\n private readonly _cronDefs: CronDef<Record<string, unknown>>[] = []\n // Registry of running croner instances — populated by _scheduleCrons(), drained by close()\n private readonly _cronJobs: Map<string, import('croner').Cron> = new Map()\n // Lock adapter — prevents duplicate execution across multiple instances\n private readonly _cronLock: CronLockAdapter\n private readonly _onInternalError: (msg: string, err: unknown) => void\n // Optional WS adapter — registered via app.registerWsAdapter(). Null when @oakbun/ws is not used.\n private _wsAdapter: VelnWsAdapter | null = null\n // Optional auth adapter — set via createApp({ auth }). Null when auth is not configured.\n private _authAdapter: AuthAdapter | null = null\n\n constructor(opts: {\n auth?: AuthAdapter\n nav?: { path?: string }\n validation?: { exposeIssues?: boolean }\n eventBus?: EventBusAdapter\n cronLock?: CronLockAdapter\n db?: { log?: { enabled?: boolean; n1Threshold?: number; logQueries?: boolean } }\n onInternalError?: (msg: string, err: unknown) => void\n } = {}) {\n this._onInternalError = opts.onInternalError ?? ((msg, err) => console.error(msg, err))\n this.eventBus = opts.eventBus ?? new InMemoryEventBus()\n this._cronLock = opts.cronLock ?? new NoOpCronLockAdapter()\n this.hooks = new HookExecutor()\n this._authAdapter = opts.auth ?? null\n if (opts.validation?.exposeIssues !== undefined) {\n this._opts = { ...this._opts, exposeIssues: opts.validation.exposeIssues }\n }\n if (opts.db !== undefined) {\n this._opts = { ...this._opts, db: opts.db }\n }\n this._registerNavEndpoint(opts.nav?.path ?? '/nav')\n }\n\n // Register the built-in GET /nav endpoint.\n // Returns all plugin nav items filtered by the current user's permissions.\n // Always public — no user → empty array, no error.\n private _registerNavEndpoint(path: string): void {\n const pluginsRef = this.plugins\n const authAdapterRef = () => this._authAdapter\n this.routes.push({\n method: 'GET',\n path,\n visibility: 'hidden',\n guards: [],\n handler: {\n handler: (ctx: BaseCtx) => {\n const user = ((ctx as unknown as Record<string, unknown>)['user'] ?? null) as import('./types').AuthUser | null\n const nav: NavItem[] = []\n for (const plugin of pluginsRef) {\n if (!plugin.nav || plugin.nav.length === 0) continue\n // If the plugin has permissions, check whether the user has at least one.\n // Uses _authAdapter.hasPermission() — never reads user.permissions directly.\n if (plugin.permissions && plugin.permissions.length > 0) {\n if (user == null) continue // no user → skip permissioned plugin\n const adapter = authAdapterRef()\n const hasAny = adapter\n ? plugin.permissions.some((perm) => adapter.hasPermission(user, perm))\n : false\n if (!hasAny) continue\n }\n nav.push(...plugin.nav)\n }\n // Sort by order (ascending, default 0), then alphabetically by label\n nav.sort((a, b) => {\n const orderDiff = (a.order ?? 0) - (b.order ?? 0)\n return orderDiff !== 0 ? orderDiff : a.label.localeCompare(b.label)\n })\n return ctx.json({ nav })\n },\n },\n })\n }\n\n private _addRoute(\n method: HttpMethod,\n path: string,\n handler: HandlerArg<TCtx>,\n module?: VelnModule,\n ): this {\n const { handler: normalized, schema, docs } = normalizeHandler(handler)\n this.routes.push({\n method,\n path,\n handler: normalized,\n guards: [],\n schema,\n docs,\n _module: module,\n })\n return this\n }\n\n // HTTP method registration.\n // 3-arg overload with schema: accumulates into TRoutes for RPC client type extraction.\n // 2-arg overload: function shorthand, no schema inference needed, TRoutes unchanged.\n\n private _registerMethod(\n method: HttpMethod,\n path: string,\n schemaOrHandler: { body?: ZodTypeAny; params?: ZodTypeAny; query?: ZodTypeAny; response?: ZodTypeAny } | HandlerArg<TCtx>,\n handler?: (ctx: never) => Response | Promise<Response>,\n ): Veln<TCtx, RouteMap, TPrefixes> {\n return handler\n ? this._addRoute(method, path, { ...schemaOrHandler as RouteSchema, handler } as RouteHandlerWithSchema<TCtx, RouteSchema>)\n : this._addRoute(method, path, schemaOrHandler as HandlerArg<TCtx>)\n }\n\n get<\n TBody extends ZodTypeAny,\n TParams extends ZodTypeAny,\n TQuery extends ZodTypeAny,\n TResponse extends ZodTypeAny,\n TPath extends string\n >(\n path: TPath,\n schema: { body?: TBody; params?: TParams; query?: TQuery; response?: TResponse },\n handler: (ctx: TCtx & { body: import('zod').infer<TBody>; params: import('zod').infer<TParams>; query: import('zod').infer<TQuery> }) => Response | Promise<Response>,\n ): Veln<TCtx, TRoutes & Record<`GET ${TPath}`, { body: TBody; params: TParams; query: TQuery; response: TResponse }>>\n get(path: string, handler: HandlerArg<TCtx>): this\n get(path: string, schemaOrHandler: { body?: ZodTypeAny; params?: ZodTypeAny; query?: ZodTypeAny; response?: ZodTypeAny } | HandlerArg<TCtx>, handler?: (ctx: never) => Response | Promise<Response>): Veln<TCtx, RouteMap, TPrefixes> {\n return this._registerMethod('GET', path, schemaOrHandler, handler)\n }\n\n post<\n TBody extends ZodTypeAny,\n TParams extends ZodTypeAny,\n TQuery extends ZodTypeAny,\n TResponse extends ZodTypeAny,\n TPath extends string\n >(\n path: TPath,\n schema: { body?: TBody; params?: TParams; query?: TQuery; response?: TResponse },\n handler: (ctx: TCtx & { body: import('zod').infer<TBody>; params: import('zod').infer<TParams>; query: import('zod').infer<TQuery> }) => Response | Promise<Response>,\n ): Veln<TCtx, TRoutes & Record<`POST ${TPath}`, { body: TBody; params: TParams; query: TQuery; response: TResponse }>>\n post(path: string, handler: HandlerArg<TCtx>): this\n post(path: string, schemaOrHandler: { body?: ZodTypeAny; params?: ZodTypeAny; query?: ZodTypeAny; response?: ZodTypeAny } | HandlerArg<TCtx>, handler?: (ctx: never) => Response | Promise<Response>): Veln<TCtx, RouteMap, TPrefixes> {\n return this._registerMethod('POST', path, schemaOrHandler, handler)\n }\n\n put<\n TBody extends ZodTypeAny,\n TParams extends ZodTypeAny,\n TQuery extends ZodTypeAny,\n TResponse extends ZodTypeAny,\n TPath extends string\n >(\n path: TPath,\n schema: { body?: TBody; params?: TParams; query?: TQuery; response?: TResponse },\n handler: (ctx: TCtx & { body: import('zod').infer<TBody>; params: import('zod').infer<TParams>; query: import('zod').infer<TQuery> }) => Response | Promise<Response>,\n ): Veln<TCtx, TRoutes & Record<`PUT ${TPath}`, { body: TBody; params: TParams; query: TQuery; response: TResponse }>>\n put(path: string, handler: HandlerArg<TCtx>): this\n put(path: string, schemaOrHandler: { body?: ZodTypeAny; params?: ZodTypeAny; query?: ZodTypeAny; response?: ZodTypeAny } | HandlerArg<TCtx>, handler?: (ctx: never) => Response | Promise<Response>): Veln<TCtx, RouteMap, TPrefixes> {\n return this._registerMethod('PUT', path, schemaOrHandler, handler)\n }\n\n patch<\n TBody extends ZodTypeAny,\n TParams extends ZodTypeAny,\n TQuery extends ZodTypeAny,\n TResponse extends ZodTypeAny,\n TPath extends string\n >(\n path: TPath,\n schema: { body?: TBody; params?: TParams; query?: TQuery; response?: TResponse },\n handler: (ctx: TCtx & { body: import('zod').infer<TBody>; params: import('zod').infer<TParams>; query: import('zod').infer<TQuery> }) => Response | Promise<Response>,\n ): Veln<TCtx, TRoutes & Record<`PATCH ${TPath}`, { body: TBody; params: TParams; query: TQuery; response: TResponse }>>\n patch(path: string, handler: HandlerArg<TCtx>): this\n patch(path: string, schemaOrHandler: { body?: ZodTypeAny; params?: ZodTypeAny; query?: ZodTypeAny; response?: ZodTypeAny } | HandlerArg<TCtx>, handler?: (ctx: never) => Response | Promise<Response>): Veln<TCtx, RouteMap, TPrefixes> {\n return this._registerMethod('PATCH', path, schemaOrHandler, handler)\n }\n\n delete<\n TBody extends ZodTypeAny,\n TParams extends ZodTypeAny,\n TQuery extends ZodTypeAny,\n TResponse extends ZodTypeAny,\n TPath extends string\n >(\n path: TPath,\n schema: { body?: TBody; params?: TParams; query?: TQuery; response?: TResponse },\n handler: (ctx: TCtx & { body: import('zod').infer<TBody>; params: import('zod').infer<TParams>; query: import('zod').infer<TQuery> }) => Response | Promise<Response>,\n ): Veln<TCtx, TRoutes & Record<`DELETE ${TPath}`, { body: TBody; params: TParams; query: TQuery; response: TResponse }>>\n delete(path: string, handler: HandlerArg<TCtx>): this\n delete(path: string, schemaOrHandler: { body?: ZodTypeAny; params?: ZodTypeAny; query?: ZodTypeAny; response?: ZodTypeAny } | HandlerArg<TCtx>, handler?: (ctx: never) => Response | Promise<Response>): Veln<TCtx, RouteMap, TPrefixes> {\n return this._registerMethod('DELETE', path, schemaOrHandler, handler)\n }\n\n /**\n * registerWsAdapter() — connect @oakbun/ws to this app.\n *\n * Call this before registering WS routes:\n * import { createWsAdapter } from '@oakbun/ws'\n * app.registerWsAdapter(createWsAdapter())\n */\n registerWsAdapter(adapter: VelnWsAdapter): this {\n this._wsAdapter = adapter\n return this\n }\n\n /**\n * ws() — register a WebSocket route.\n * Requires app.registerWsAdapter(createWsAdapter()) first.\n *\n * Full typing (WsCtx, Zod schema support) is provided when @oakbun/ws is imported.\n * Full type safety (WsCtx, Zod schema support, typed ctx.data) is provided by @oakbun/ws.\n * This base accepts a loose WsRouteShape so Core stays free of @oakbun/ws types.\n */\n ws(path: string, route: WsRouteShape): this {\n if (!this._wsAdapter) {\n throw new VelnError(\n `app.ws('${path}') called but no WS adapter is registered. Call app.registerWsAdapter(createWsAdapter()) first.`,\n 500, 'NO_WS_ADAPTER',\n )\n }\n this._wsAdapter.registerRoute(path, { ...route, path, _module: null })\n return this\n }\n\n\n plugin<TAdd extends object>(p: Plugin<TCtx, TAdd>): Veln<TCtx & TAdd, TRoutes, TPrefixes> {\n // Validate declared dependencies — fail fast with a clear error rather than a\n // mysterious runtime crash when a required plugin's ctx additions are missing.\n if (p.requires && p.requires.length > 0) {\n const registered = new Set(this.plugins.map((r) => r.name))\n for (const dep of p.requires) {\n if (!registered.has(dep)) {\n throw new VelnError(\n `Plugin \"${p.name}\" requires plugin \"${dep}\" to be registered first. ` +\n `Call app.plugin(${dep}Plugin(...)) before app.plugin(${p.name}Plugin(...)).`,\n 500,\n 'PLUGIN_MISSING_DEP',\n )\n }\n }\n }\n this.plugins.push(p)\n if (p.modules) {\n for (const mod of p.modules) {\n this.register(mod)\n // Tag every route that belongs to this plugin so _runRoute can look up\n // its permissions without a separate Map.\n if (p.permissions && p.permissions.length > 0) {\n for (const route of this.routes) {\n if (route._module === mod && route._pluginName === undefined) {\n route._pluginName = p.name\n }\n }\n }\n }\n }\n return this as unknown as Veln<TCtx & TAdd, TRoutes, TPrefixes>\n }\n\n // ── .use() — global service or middleware registration ────────────────────\n // Service overload: ctx[service._serviceKey] available in every route handler.\n // Middleware overload: registers onRequest/onResponse hooks globally.\n use<TKey extends string, TDef>(\n service: ServiceDef<TKey, TDef>,\n ): Veln<TCtx & Record<TKey, TDef>, TRoutes, TPrefixes>\n use(middleware: MiddlewareDef): this\n use<TKey extends string, TDef>(\n serviceOrMiddleware: ServiceDef<TKey, TDef> | MiddlewareDef,\n ): Veln<TCtx & Record<TKey, TDef>, TRoutes, TPrefixes> | this {\n if ('_serviceKey' in serviceOrMiddleware) {\n this._globalServiceDeclarations.push({ service: serviceOrMiddleware as ServiceDef<string, unknown> })\n return this as unknown as Veln<TCtx & Record<TKey, TDef>, TRoutes, TPrefixes>\n }\n // MiddlewareDef\n const m = serviceOrMiddleware as MiddlewareDef\n if (m._onRequest) this._onRequestHooks.push(createOnRequest(m._onRequest))\n if (m._onResponse) this._onResponseHooks.push(createOnResponse(m._onResponse))\n return this\n }\n\n register<TModuleRoutes extends RouteMap, TModulePrefix extends string>(\n mod: VelnModule & { readonly _routes: TModuleRoutes; readonly _prefix: TModulePrefix },\n ): Veln<TCtx, TRoutes & TModuleRoutes, TPrefixes | TModulePrefix>\n register(module: VelnModule): this\n register(module: VelnModule): Veln<TCtx, TRoutes & RouteMap, TPrefixes | string> {\n // 1. Transfer hook declarations to internal HookExecutor\n for (const decl of module.hookDeclarations) {\n this.hooks.registerModuleHook(decl.table.name, decl.handlers)\n }\n\n // 2. Collect audit declarations — wired after plugins install (first fetch())\n for (const decl of module.auditDeclarations) {\n this._pendingAuditDeclarations.push(decl)\n }\n\n // 3. Mount routes with prefix\n for (const route of module.routes) {\n this.routes.push({\n ...route,\n path: module.prefix + route.path,\n _module: module,\n })\n }\n\n // 3b. Mount WS routes with prefix — delegate to wsAdapter if registered\n if (this._wsAdapter && module.wsRoutes.length > 0) {\n for (const wsRoute of module.wsRoutes) {\n const fullPath = module.prefix + wsRoute.path\n this._wsAdapter.registerRoute(fullPath, { ...wsRoute, path: fullPath, _module: module })\n }\n }\n\n // 4. Register event handler defs on the event bus\n for (const def of module.eventHandlerDefs) {\n this.events(def)\n }\n\n // 5. Collect cron defs — merge module service declarations into each cron's _services\n // so module-level .use(Service) is automatically available in the cron handler\n for (const cronDef of module.cronDefs) {\n // Merge module services that aren't already declared on the CronDef itself\n const existingKeys = new Set(cronDef._services.map((s) => s._serviceKey))\n const merged = [\n ...cronDef._services,\n ...module.serviceDeclarations\n .map((d) => d.service)\n .filter((s) => !existingKeys.has(s._serviceKey)),\n ]\n const mergedDef: CronDef<Record<string, unknown>> = {\n ...cronDef,\n _services: merged,\n use: cronDef.use.bind(cronDef),\n }\n this._cronDefs.push(mergedDef)\n }\n\n // Invalidate route cache — new routes may match previously-cached paths differently\n this._routeCache.clear()\n\n return this as unknown as Veln<TCtx, TRoutes & RouteMap, TPrefixes | string>\n }\n\n // Internal helper: collect all service declarations (global + from a given module)\n private _allServiceDecls(mod: VelnModule | null): ReadonlyArray<ServiceDeclaration<string, unknown>> {\n if (mod === null) return this._globalServiceDeclarations\n // Merge global + module, deduplicate by key (module overrides global)\n const seen = new Set<string>()\n const merged: ServiceDeclaration<string, unknown>[] = []\n for (const d of [...mod.serviceDeclarations, ...this._globalServiceDeclarations]) {\n if (!seen.has(d.service._serviceKey)) {\n seen.add(d.service._serviceKey)\n merged.push(d)\n }\n }\n return merged\n }\n\n // Typed overload for events declared via VelnEvents Declaration Merging\n on<K extends keyof VelnEvents>(\n event: K,\n handler: (payload: VelnEvents[K], ctx: unknown) => Promise<void> | void,\n ): this\n // String fallback\n on(event: string, handler: EventHandler): this\n on(event: string, handler: EventHandler): this {\n this.eventBus.on(event, (payload) => handler(payload, undefined))\n return this\n }\n\n // Typed Table-reference overload — uses InferTableEvents<T, TEvents> directly at the call site.\n // No Declaration Merging needed for Table-derived events.\n // Phase 4b RPC Client uses this signature to build AppType.\n //\n // TMap is inferred from table._eventMap — a concrete precomputed object type stored on\n // TableDef. K is constrained via Pick<TMap, K>[K] which forces TypeScript to infer K\n // as the literal type of the event string rather than the full keyof TMap union.\n onEvent<\n TMap extends Record<string, unknown>,\n K extends string & keyof TMap\n >(\n table: { _eventMap: TMap },\n event: K,\n handler: (payload: Pick<TMap, K>[K], ctx: unknown) => void | Promise<void>,\n ): this {\n this.eventBus.on(event as string, (payload) => (handler as EventHandler)(payload, undefined))\n return this\n }\n\n events(def: EventHandlerDef): this {\n const logger = def._logger\n const hasServices = def._services.length > 0\n\n if (hasServices) {\n // Service path — instantiate services per event fire using a system context\n for (const [event, rawHandler] of def._rawHandlers) {\n this.eventBus.on(event, async (payload) => {\n try {\n const adapter = this.hooks.getAdapter()\n const ctx: Record<string, unknown> = { logger }\n if (adapter) {\n const sysCtx = createSystemCtx({ role: 'event' })\n const velnDb = new VelnDB(adapter, this.hooks)\n const boundDb = velnDb.withCtx(sysCtx)\n const services = instantiateServices(def._services, boundDb)\n Object.assign(ctx, services)\n }\n await rawHandler(payload, ctx)\n } catch (err) {\n logger.error('handler error', { event, err })\n }\n })\n }\n } else {\n // Fast path — logger only, callbacks already wrapped in build()\n for (const [event, callback] of def._handlers) {\n this.eventBus.on(event, async (payload) => {\n try {\n await callback(payload)\n } catch (err) {\n logger.error('handler error', { event, err })\n }\n })\n }\n }\n return this\n }\n\n cron<TServices extends Record<string, unknown>>(def: CronDef<TServices>): this {\n this._cronDefs.push(def as CronDef<Record<string, unknown>>)\n return this\n }\n\n onError(handler: ErrorHandler<TCtx>): this {\n this.globalOnError = handler\n return this\n }\n\n // ─── Lifecycle hook registration ─────────────────────────────────────────\n // Registration order within a phase is preserved (FIFO).\n // Phase order is always: onRequest → plugins → guards → onBeforeHandle → handler → onResponse.\n\n onRequest(hook: OnRequestHook<TCtx>): this {\n this._onRequestHooks.push(hook as OnRequestHook<any>)\n return this\n }\n\n onBeforeHandle(hook: OnBeforeHandleHook<TCtx>): this {\n this._onBeforeHandleHooks.push(hook as OnBeforeHandleHook<any>)\n return this\n }\n\n onResponse(hook: OnResponseHook<TCtx>): this {\n this._onResponseHooks.push(hook as OnResponseHook<any>)\n return this\n }\n\n async fetch(req: Request, server?: import('bun').Server<unknown>): Promise<Response> {\n // ─────────────────────────────────────────────────────────────────────────\n // fetch() Lifecycle — strict phase order regardless of registration order:\n //\n // PHASE 1: onRequest — always runs, even on 404 / guard block / plugin error\n // receives BaseCtx (plugins not yet applied)\n // may return Response to short-circuit everything\n // PHASE 2: plugins — build full ctx (global + module-level)\n // PHASE 3: guards — global → module → route guards\n // block returns guard response (wrapped by onResponse)\n // PHASE 4: onBeforeHandle — runs only when all guards pass\n // may return Response to skip handler\n // PHASE 5: handler — route handler\n // PHASE 6: onResponse — always runs (even on handler/guard/plugin error)\n // receives final Response; may return replacement\n // ─────────────────────────────────────────────────────────────────────────\n\n // PHASE 1: Install plugins once (lazy, on first request)\n if (!this.installedPlugins) {\n this.installedPlugins = true\n for (const plugin of this.plugins) {\n if (plugin.install) {\n await plugin.install(this.hooks)\n }\n }\n\n // Wire pending audit declarations now that plugins are installed.\n // dbPlugin.install() called hooks.setAdapter() above — adapter is available.\n if (this._pendingAuditDeclarations.length > 0) {\n const adapter = this.hooks.getAdapter()\n if (!adapter) {\n throw new Error(\n '[veln] .audit() declarations found but no dbPlugin is registered. ' +\n 'Call app.plugin(dbPlugin(...)) before app.register().'\n )\n }\n for (const decl of this._pendingAuditDeclarations) {\n const handlers = buildAuditHooks(decl, adapter)\n this.hooks.registerModuleHook(decl.table.name, handlers)\n }\n this._pendingAuditDeclarations.length = 0\n }\n }\n\n // Parse URL — pathname + query\n const url = new URL(req.url)\n const pathname = url.pathname\n const method = req.method.toUpperCase() as HttpMethod\n\n // Create per-request event queue — collects all DB-generated events during this request.\n // Flushed after onResponse on success paths only.\n // Guard blocks, handler errors, and plugin errors discard the queue (no flush).\n const requestQueue = new RequestEventQueue()\n\n // Create per-request QueryLog when N+1 detection is enabled.\n // Zero-cost when disabled — no object allocation, no wrapper.\n const dbLogCfg = this._opts.db?.log\n const queryLog: import('../db/index').QueryLog | undefined = dbLogCfg?.enabled\n ? {\n queries: 0,\n totalMs: 0,\n entries: [],\n threshold: dbLogCfg.n1Threshold ?? 10,\n logQueries: dbLogCfg.logQueries ?? false,\n }\n : undefined\n\n // Build minimal base ctx for onRequest (plugins not yet applied)\n // _requestQueue is read by dbPlugin to bind the queue to BoundVelnDB.\n // _queryLog is read by dbPlugin to wire N+1 detection into BoundVelnDB.\n const baseCtx: BaseCtx = {\n req,\n params: {},\n query: parseQuery(url.search),\n json: <T>(data: T, status = 200) => Response.json(data, { status }),\n text: (data: string, status = 200) => new Response(data, { status, headers: { 'Content-Type': 'text/plain' } }),\n html: (data: string, status = 200) => new Response(data, { status, headers: { 'Content-Type': 'text/html' } }),\n stream: makeStreamResponse,\n sse: makeSSEResponse,\n cookie: createCookieJar(req),\n emit: (event, payload) => { requestQueue.collect(event as string, payload) },\n _requestQueue: requestQueue,\n _queryLog: queryLog,\n }\n\n // ── Auth: resolve user before onRequest ──────────────────────────────────\n // getUser() runs once per request — result is available in onRequest hooks,\n // plugins, guards, and handlers as ctx.user (AuthUser | null).\n // Written via Object.assign so BaseCtx doesn't need to declare user — avoids\n // type collision with jwtPlugin/betterAuthPlugin which set their own user shape.\n if (this._authAdapter) {\n let resolvedUser: import('./types').AuthUser | null = null\n try {\n resolvedUser = await this._authAdapter.getUser(baseCtx)\n } catch {\n resolvedUser = null\n }\n Object.assign(baseCtx, { user: resolvedUser })\n } else {\n Object.assign(baseCtx, { user: null })\n }\n\n // ── PHASE 1: onRequest — always runs ─────────────────────────────────────\n // Runs before route matching so ctx.params is empty here.\n // If a hook returns a Response, it is wrapped by onResponse (no module yet).\n for (const hook of this._onRequestHooks) {\n let earlyRes: Response | void\n try {\n earlyRes = await hook._fn(baseCtx)\n } catch {\n earlyRes = undefined\n }\n if (earlyRes instanceof Response) {\n return this._runOnResponse(baseCtx, earlyRes, null)\n }\n }\n\n // ── WS UPGRADE: delegate to @oakbun/ws adapter ─────────────────────────────\n // Only attempted when the upgrade header is present, a server is available,\n // and an adapter has been registered via app.registerWsAdapter().\n if (server && this._wsAdapter && req.headers.get('upgrade')?.toLowerCase() === 'websocket') {\n const installedRef = { value: this.installedPlugins }\n const upgradeResponse = await this._wsAdapter.handleUpgrade(\n req,\n server,\n baseCtx,\n this.plugins,\n installedRef,\n this.installedModulePlugins,\n )\n this.installedPlugins = installedRef.value\n if (upgradeResponse !== null) return upgradeResponse\n return undefined as unknown as Response // Bun: undefined after successful upgrade\n }\n\n // Match route — 405 if path matches but method doesn't, 404 if no path match\n // P3: Cache matchPath() results by \"METHOD:pathname\" — FIFO eviction at _ROUTE_CACHE_MAX.\n let matchedRoute: Route<any> | null = null\n let matchedParams: Record<string, string | undefined> = {}\n const allowedMethods = new Set<string>()\n\n const cacheKey = `${method}:${pathname}`\n const cached = this._routeCache.get(cacheKey)\n if (cached !== undefined) {\n // Cache hit — cached is either { route, params } or null (known 404/405)\n if (cached !== null) {\n matchedRoute = cached.route\n matchedParams = cached.params\n allowedMethods.add(cached.route.method)\n }\n } else {\n // Cache miss — scan all routes\n for (const route of this.routes) {\n const result = matchPath(route.path, pathname)\n if (result === null) continue\n allowedMethods.add(route.method)\n if (route.method === method) {\n matchedRoute = route\n matchedParams = result.params\n break\n }\n }\n // Populate cache — evict oldest entry if at capacity\n if (this._routeCache.size >= this._ROUTE_CACHE_MAX) {\n this._routeCache.delete(this._routeCache.keys().next().value!)\n }\n this._routeCache.set(cacheKey, matchedRoute ? { route: matchedRoute, params: matchedParams } : null)\n }\n\n if (matchedRoute === null) {\n if (allowedMethods.size > 0) {\n // Path exists but method not allowed\n const allow = [...allowedMethods].join(', ')\n return this._runOnResponse(\n baseCtx,\n new Response('Method Not Allowed', { status: 405, headers: { Allow: allow } }),\n null,\n )\n }\n return this._runOnResponse(baseCtx, new Response('Not Found', { status: 404 }), null)\n }\n\n // Filter out undefined optional params — ctx.params is Record<string, string>\n const definedParams: Record<string, string> = {}\n for (const [k, v] of Object.entries(matchedParams)) {\n if (v !== undefined) definedParams[k] = v\n }\n\n return this._runRoute(baseCtx, matchedRoute, definedParams, requestQueue)\n }\n\n /**\n * _runRoute — executes the full Veln pipeline for an already-matched route.\n *\n * Called from two places:\n * 1. fetch() — after matchPath() finds the route (used by createTestClient + fallback)\n * 2. Bun native routes — Bun's SIMD router pre-matched the route; params come from req.params\n *\n * baseCtx must already have req, query, cookie, emit set.\n * params is passed in as Record<string, string> (undefined optionals already filtered out).\n */\n private async _runRoute(\n baseCtx: BaseCtx,\n matchedRoute: Route<unknown>,\n params: Record<string, string>,\n requestQueue: RequestEventQueue,\n ): Promise<Response> {\n baseCtx.params = params\n\n const mod = matchedRoute._module ?? null\n\n // Phase 0 — Plugin permission gate\n const permResult = await this._runPermissionGate(baseCtx, matchedRoute, mod)\n if (permResult) return permResult\n\n // Phase 1 — Module onRequest hooks\n const onRequestResult = await this._runModuleOnRequest(baseCtx, matchedRoute, mod)\n if (onRequestResult) return onRequestResult\n\n // Phase 2a — Plugin context building\n const ctx = await this._runPlugins(baseCtx, matchedRoute, mod)\n if (ctx instanceof Response) return ctx\n\n // Phase 2b — Schema validation\n const validationResult = await this._runValidation(ctx, matchedRoute, mod)\n if (validationResult) return validationResult\n\n // Phase 2c — Service instantiation\n await this._runServices(ctx, mod)\n\n // Phase 3 — Guards (global + module + route)\n const guardResult = await this._runGuards(ctx, matchedRoute, mod)\n if (guardResult) return guardResult\n\n // Phase 4 — onBeforeHandle hooks\n const beforeHandleResult = await this._runBeforeHandle(ctx, matchedRoute, mod)\n if (beforeHandleResult) return beforeHandleResult\n\n // Phase 5 + 5.5 + 6 — Handler, response validation, onResponse\n return this._runHandler(baseCtx, ctx, matchedRoute, mod, requestQueue)\n }\n\n // ── Phase 0: Plugin permission gate ─────────────────────────────────────────\n // Runs immediately after route match — before onRequest hooks, before plugin\n // request() calls, before guards. Ensures no plugin side-effects occur for a\n // request that will be blocked anyway.\n //\n // Only applies to routes tagged with _pluginName (contributed via .modules()).\n // Uses AuthAdapter.hasPermission() — never reads ctx.user.permissions directly.\n private async _runPermissionGate(\n baseCtx: BaseCtx,\n matchedRoute: Route<unknown>,\n mod: VelnModule | null,\n ): Promise<Response | null> {\n if (matchedRoute._pluginName === undefined) return null\n\n const gateName = matchedRoute._pluginName\n const gatePlugin = this.plugins.find((p) => p.name === gateName)\n if (!gatePlugin?.permissions || gatePlugin.permissions.length === 0) return null\n\n // user was written via Object.assign — read it back through the record interface\n const user = (baseCtx as unknown as Record<string, unknown>)['user'] as import('./types').AuthUser | null | undefined\n if (user == null) {\n return this._runOnResponse(\n baseCtx,\n await this._handleError(new UnauthorizedError('Authentication required'), baseCtx, matchedRoute),\n mod,\n )\n }\n const adapter = this._authAdapter\n const hasAny = adapter\n ? gatePlugin.permissions.some((perm) => adapter.hasPermission(user, perm))\n : false\n if (!hasAny) {\n return this._runOnResponse(\n baseCtx,\n await this._handleError(new ForbiddenError('Insufficient permissions'), baseCtx, matchedRoute),\n mod,\n )\n }\n return null\n }\n\n // ── Phase 1: Module onRequest hooks ─────────────────────────────────────────\n // Runs after route match, still before plugins. Returns a Response if any hook\n // short-circuits, null otherwise.\n private async _runModuleOnRequest(\n baseCtx: BaseCtx,\n matchedRoute: Route<unknown>,\n mod: VelnModule | null,\n ): Promise<Response | null> {\n if (!mod) return null\n for (const hook of mod.onRequestHooks) {\n let earlyRes: Response | void\n try {\n earlyRes = await hook._fn(baseCtx)\n } catch {\n earlyRes = undefined\n }\n if (earlyRes instanceof Response) {\n return this._runOnResponse(baseCtx, earlyRes, mod)\n }\n }\n return null\n }\n\n // ── Phase 2a: Plugin context building ───────────────────────────────────────\n // Runs global plugins then module plugins (lazy install with Set guard).\n // Returns the enriched ctx, or a Response if a plugin throws.\n private async _runPlugins(\n baseCtx: BaseCtx,\n matchedRoute: Route<unknown>,\n mod: VelnModule | null,\n ): Promise<BaseCtx | Response> {\n let ctx: BaseCtx = baseCtx\n try {\n // P2 analysis: plugins run sequentially — later plugins may read context added by\n // earlier ones (e.g. authPlugin reads ctx.db set by dbPlugin). Promise.all is NOT\n // safe. Object.assign is applied after each plugin so ctx stays current.\n // Each Object.assign call is O(keys) and negligible — no further batching possible.\n for (const plugin of this.plugins) {\n Object.assign(ctx, await plugin.request(ctx))\n }\n\n if (mod) {\n for (const plugin of mod.plugins) {\n // Install module plugin exactly once — lazy, keyed by plugin name.\n //\n // Race-condition analysis (Spec 07):\n // Bun runs on a single-threaded Event Loop — no true parallelism within\n // one process. Concurrent requests interleave only at `await` points.\n // The check (.has) and the mark (.add) are both synchronous and happen\n // before the first `await plugin.install(this.hooks)`, so no other\n // request can observe the un-marked state after .has() returns false:\n //\n // Request A: .has() → false → .add() ← sync, no yield possible here\n // → await install() ← yield point\n // Request B: .has() → true → skip ← sees the mark, install skipped ✓\n //\n // This is the correct \"optimistic add before await\" pattern.\n if (plugin.install && !this.installedModulePlugins.has(plugin.name)) {\n this.installedModulePlugins.add(plugin.name)\n await plugin.install(this.hooks)\n }\n Object.assign(ctx, await plugin.request(ctx))\n }\n\n // Inject module logger if .options({ log }) was set and ctx.logger not already present\n if (mod.options?.log && !ctx.logger) {\n const seg = mod.prefix.split('/').filter(Boolean).pop() ?? 'root'\n ctx.logger = createMinimalLogger(`module:${seg}`, mod.options.log)\n }\n }\n } catch (err) {\n const errRes = await this._handleError(err, ctx, matchedRoute)\n return this._runOnResponse(ctx, errRes, mod)\n }\n return ctx\n }\n\n // ── Phase 2b: Schema validation ──────────────────────────────────────────────\n // Validates params, query, body against Zod schemas if defined.\n // Returns a Response on validation failure, null on success.\n private async _runValidation(\n ctx: BaseCtx,\n matchedRoute: Route<unknown>,\n mod: VelnModule | null,\n ): Promise<Response | null> {\n if (!matchedRoute.schema) return null\n const schema = matchedRoute.schema\n\n if (schema.params) {\n const result = schema.params.safeParse(ctx.params)\n if (!result.success) {\n const errRes = await this._handleError(new ValidationError(result.error), ctx, matchedRoute)\n return this._runOnResponse(ctx, errRes, mod)\n }\n ctx.params = result.data as Record<string, string>\n }\n\n if (schema.query) {\n const result = schema.query.safeParse(ctx.query)\n if (!result.success) {\n const errRes = await this._handleError(new ValidationError(result.error), ctx, matchedRoute)\n return this._runOnResponse(ctx, errRes, mod)\n }\n ctx.query = result.data as Record<string, string | string[]>\n }\n\n if (schema.body) {\n let raw: unknown = null\n try {\n raw = await ctx.req.json()\n } catch {\n // invalid JSON or no body\n }\n const result = schema.body.safeParse(raw)\n if (!result.success) {\n const errRes = await this._handleError(new ValidationError(result.error), ctx, matchedRoute)\n return this._runOnResponse(ctx, errRes, mod)\n }\n ctx.body = result.data\n }\n\n return null\n }\n\n // ── Phase 2c: Service instantiation ─────────────────────────────────────────\n // Instantiates declared services per-request and merges into ctx.\n // Runs after plugins (ctx.db is available) and before guards.\n private async _runServices(\n ctx: BaseCtx,\n mod: VelnModule | null,\n ): Promise<void> {\n const serviceDecls = this._allServiceDecls(mod)\n if (serviceDecls.length === 0) return\n\n // Circular dep check — once per app lifetime, not per-request\n if (!this._serviceCircularChecked) {\n this._serviceCircularChecked = true\n detectCircular(serviceDecls.map((d) => d.service))\n }\n\n if (!ctx.db) {\n throw new Error(\n '[veln] .use() service declarations found but ctx.db is not available. ' +\n 'Register dbPlugin() before declaring services.',\n )\n }\n const serviceInstances = instantiateServices(\n serviceDecls.map((d) => d.service),\n ctx.db,\n )\n for (const [key, inst] of Object.entries(serviceInstances)) {\n (ctx as unknown as Record<string, unknown>)[key] = inst\n }\n }\n\n // ── Phase 3: Guards (global + module + route) ────────────────────────────────\n // Runs all three guard tiers in order. Returns a Response if any guard blocks,\n // null if all pass.\n private async _runGuards(\n ctx: BaseCtx,\n matchedRoute: Route<unknown>,\n mod: VelnModule | null,\n ): Promise<Response | null> {\n // Global guards\n for (const guard of this.globalGuards) {\n let guardResult: Response | null\n try {\n guardResult = await guard(ctx)\n } catch (err) {\n const errRes = await this._handleError(err, ctx, matchedRoute)\n return this._runOnResponse(ctx, errRes, mod)\n }\n if (guardResult !== null) {\n return this._runOnResponse(ctx, guardResult, mod)\n }\n }\n\n // Module guards — skipped when route has guard: false (moduleGuardOptOut)\n if (mod && !matchedRoute.moduleGuardOptOut) {\n for (const guard of mod.guards) {\n let guardResult: Response | null\n try {\n guardResult = await guard(ctx)\n } catch (err) {\n const errRes = await this._handleError(err, ctx, matchedRoute)\n return this._runOnResponse(ctx, errRes, mod)\n }\n if (guardResult !== null) {\n return this._runOnResponse(ctx, guardResult, mod)\n }\n }\n }\n\n // Route guards\n for (const guard of matchedRoute.guards) {\n let guardResult: Response | null\n try {\n guardResult = await guard(ctx)\n } catch (err) {\n const errRes = await this._handleError(err, ctx, matchedRoute)\n return this._runOnResponse(ctx, errRes, mod)\n }\n if (guardResult !== null) {\n return this._runOnResponse(ctx, guardResult, mod)\n }\n }\n\n return null\n }\n\n // ── Phase 4: onBeforeHandle hooks ───────────────────────────────────────────\n // Runs app-level then module-level onBeforeHandle hooks. Only called after all\n // guards pass. Returns a Response if any hook short-circuits, null otherwise.\n private async _runBeforeHandle(\n ctx: BaseCtx,\n matchedRoute: Route<unknown>,\n mod: VelnModule | null,\n ): Promise<Response | null> {\n // App-level hooks\n for (const hook of this._onBeforeHandleHooks) {\n let earlyRes: Response | void\n try {\n earlyRes = await hook._fn(ctx)\n } catch (err) {\n const errRes = await this._handleError(err, ctx, matchedRoute)\n return this._runOnResponse(ctx, errRes, mod)\n }\n if (earlyRes instanceof Response) {\n return this._runOnResponse(ctx, earlyRes, mod)\n }\n }\n\n // Module-level onBeforeHandle hooks\n if (mod) {\n for (const hook of mod.onBeforeHandleHooks) {\n let earlyRes: Response | void\n try {\n earlyRes = await hook._fn(ctx)\n } catch (err) {\n const errRes = await this._handleError(err, ctx, matchedRoute)\n return this._runOnResponse(ctx, errRes, mod)\n }\n if (earlyRes instanceof Response) {\n return this._runOnResponse(ctx, earlyRes, mod)\n }\n }\n }\n\n return null\n }\n\n // ── Phase 5 + 5.5 + 6: Handler, response validation, onResponse ─────────────\n // Executes the route handler, optionally validates the response, then runs\n // onResponse hooks. On error, discards the request queue (no event flush).\n private async _runHandler(\n baseCtx: BaseCtx,\n ctx: BaseCtx,\n matchedRoute: Route<unknown>,\n mod: VelnModule | null,\n requestQueue: RequestEventQueue,\n ): Promise<Response> {\n // Phase 5 — handler\n let response: Response\n try {\n response = await matchedRoute.handler.handler(ctx)\n } catch (err) {\n const errRes = await this._handleError(err, ctx, matchedRoute)\n // Handler threw — discard the request queue (no event flush on error)\n return this._runOnResponse(baseCtx, errRes, mod, undefined)\n }\n\n // Phase 5.5 — response validation (when enabled)\n // P4: Only clone when the response is actually JSON with a body — avoids cloning\n // SSE streams, HTML responses, and 204 No Content responses unnecessarily.\n const shouldValidate = this._opts.validateResponse\n && matchedRoute.schema?.response != null\n && response.headers.get('content-type')?.includes('application/json') === true\n && response.status !== 204\n && response.body !== null\n if (shouldValidate) {\n try {\n const body: unknown = await response.clone().json()\n const result = matchedRoute.schema!.response!.safeParse(body)\n if (!result.success) {\n this._onInternalError('[veln] Response validation failed:', result.error.issues)\n const errRes = new Response('Internal Server Error', { status: 500 })\n return this._runOnResponse(baseCtx, errRes, mod, undefined)\n }\n } catch {\n // Unparseable JSON — skip validation\n }\n }\n\n // Phase 6 — onResponse (success path — pass requestQueue so events are flushed)\n return this._runOnResponse(baseCtx, response, mod, requestQueue)\n }\n\n // Internal: run all onResponse hooks (app-level + module-level for matched route)\n // Always called — even on error paths — so onResponse truly \"always runs\".\n // flushQueue: only set on the success path (handler ran without error).\n // After all onResponse hooks complete, the queue is flushed to the EventBus.\n private async _runOnResponse(ctx: BaseCtx, response: Response, module?: VelnModule | null, flushQueue?: RequestEventQueue): Promise<Response> {\n let current = response\n\n // App-level onResponse hooks\n for (const hook of this._onResponseHooks) {\n let result: Response | void = undefined\n try {\n result = await hook._fn(ctx, current)\n } catch {\n // onResponse errors are swallowed — never break the response\n }\n if (result instanceof Response) {\n current = result\n }\n }\n\n // Module-level onResponse hooks (if module is known)\n if (module) {\n for (const hook of module.onResponseHooks) {\n let result: Response | void = undefined\n try {\n result = await hook._fn(ctx, current)\n } catch {\n // swallow\n }\n if (result instanceof Response) {\n current = result\n }\n }\n }\n\n // N+1 detection — only when db.log.enabled is true and a QueryLog was created in fetch().\n // Zero-cost when disabled: ctx._queryLog is undefined, so no work is done.\n const queryLog = ctx._queryLog\n if (queryLog && queryLog.queries > queryLog.threshold) {\n const url = new URL(ctx.req.url)\n const method = ctx.req.method.toUpperCase()\n console.warn(\n `[db:n+1] ${queryLog.queries} queries in ${method} ${url.pathname} — threshold: ${queryLog.threshold}`,\n )\n if (queryLog.logQueries) {\n for (const entry of queryLog.entries) {\n console.warn(` ${entry.sql} (${entry.durationMs.toFixed(2)}ms)`)\n }\n }\n }\n\n // Flush request-level event queue — only on success path (flushQueue is undefined on errors).\n // This guarantees: events fire AFTER the response is finalized, never on rollback/error.\n if (flushQueue) {\n await flushQueue.flush(ctx, this.eventBus)\n }\n\n // Apply pending Set-Cookie headers from ctx.cookie\n const pendingCookies = ctx.cookie._pending()\n if (pendingCookies.length > 0) {\n const headers = new Headers(current.headers)\n for (const c of pendingCookies) {\n headers.append('Set-Cookie', c)\n }\n current = new Response(current.body, {\n status: current.status,\n statusText: current.statusText,\n headers,\n })\n }\n\n return current\n }\n\n private _handleError(err: unknown, ctx: any, route: Route<any>): Response | Promise<Response> {\n // Error cascade: route onError → module onError → global onError → built-in fallback\n if (route.onError) {\n try {\n return route.onError(err, ctx)\n } catch {\n // fall through\n }\n }\n\n if (route._module?.onError) {\n try {\n return route._module.onError(err, ctx)\n } catch {\n // fall through\n }\n }\n\n if (this.globalOnError) {\n try {\n return this.globalOnError(err, ctx)\n } catch {\n // fall through\n }\n }\n\n // Built-in fallback — structured error responses with machine-readable codes.\n // ValidationError first (subclass of VelnError) — includes issues array.\n // Issues are masked by default (exposeIssues: false) to prevent schema info leaks.\n // Set createApp({ validation: { exposeIssues: true } }) for full Zod details in development.\n if (err instanceof ValidationError) {\n const issues = this._opts.exposeIssues\n ? err.issues\n : err.issues.map((issue) => ({ path: issue.path, message: 'Invalid value' }))\n return Response.json(\n { error: 'Validation Error', code: err.code, message: err.message, issues },\n { status: 422 },\n )\n }\n\n if (err instanceof VelnError) {\n return Response.json(\n { error: err.name, code: err.code, message: err.message },\n { status: err.status },\n )\n }\n\n // Duck-type fallback: handle errors with status+code (e.g. @oakbun/jwt JwtBaseError)\n if (\n err instanceof Error &&\n typeof (err as any).status === 'number' &&\n typeof (err as any).code === 'string'\n ) {\n const e = err as Error & { status: number; code: string }\n return Response.json(\n { error: e.name, code: e.code, message: e.message },\n { status: e.status },\n )\n }\n\n return Response.json(\n { error: 'Internal Server Error', code: 'INTERNAL_ERROR', message: 'An unexpected error occurred' },\n { status: 500 },\n )\n }\n\n options(opts: { validateResponse?: boolean }): this {\n if (opts.validateResponse !== undefined) {\n this._opts = { ...this._opts, validateResponse: opts.validateResponse }\n }\n return this\n }\n\n async close(): Promise<void> {\n // Stop all cron jobs before tearing down plugins\n for (const job of this._cronJobs.values()) {\n job.stop()\n }\n this._cronJobs.clear()\n\n // Call teardown() in reverse registration order\n const reversed = [...this.plugins].reverse()\n for (const plugin of reversed) {\n if (plugin.teardown) {\n try {\n await plugin.teardown()\n } catch (err) {\n // Log but don't rethrow — other teardowns must still run\n this._onInternalError(`[veln] teardown failed for plugin \"${plugin.name}\":`, err)\n }\n }\n }\n }\n\n getOpenApiSpec(options?: { title?: string; version?: string }): OpenApiSpec {\n return generateOpenApiSpec(this.routes, options)\n }\n\n /**\n * getRoutes — returns all registered HTTP routes as a RouteInfo array.\n * Compatible with @oakbun/logger's printRouteTree().\n */\n getRoutes(): Array<{ method: string; path: string; module?: string; protected: boolean }> {\n return this.routes\n .filter(route => route.visibility !== 'hidden')\n .map(route => {\n const mod = route._module\n const moduleName = mod\n ? (mod.meta?.tag ?? mod.prefix.replace(/^\\//, '').split('/')[0])\n : undefined\n return {\n method: route.method,\n path: route.path,\n module: moduleName ?? undefined,\n protected: route.guards.length > 0,\n }\n })\n }\n\n /**\n * printRoutes — prints a simple route list to stdout.\n * For a pretty tree, use printRouteTree from @oakbun/logger.\n */\n printRoutes(options?: { title?: string; version?: string }): void {\n const title = options?.title ?? 'Veln'\n const version = options?.version ? ` ${options.version}` : ''\n console.log(`\\n ${title}${version}\\n`)\n for (const route of this.routes) {\n const guard = route.guards.length > 0 ? ' 🔒' : ''\n console.log(` ${route.method.padEnd(6)} ${route.path}${guard}`)\n }\n console.log()\n }\n\n /**\n * _buildBunRoutes — converts this.routes into Bun's native route object.\n *\n * Called once at listen() time. Bun's SIMD-accelerated router takes over path matching;\n * params are extracted natively and passed via BunRequest.params.\n *\n * Routes with optional params (:name?) are deliberately excluded — Bun does not support\n * the `?` suffix syntax. They are handled by the fetch() fallback via matchPath().\n *\n * The returned object is typed as Record<string, unknown> because the path keys are\n * dynamic strings, not statically known literals. Bun.serve() receives it via `as any`.\n */\n private _buildBunRoutes(): Record<string, unknown> {\n // Group routes by path — multiple HTTP methods can share the same path\n const byPath = new Map<string, Route<unknown>[]>()\n for (const route of this.routes) {\n // Skip routes with optional params — Bun router doesn't support :param? syntax.\n // These fall through to the fetch() fallback which uses matchPath().\n if (route.path.includes('?')) continue\n const existing = byPath.get(route.path)\n if (existing) {\n existing.push(route)\n } else {\n byPath.set(route.path, [route])\n }\n }\n\n const bunRoutes: Record<string, unknown> = {}\n for (const [path, routes] of byPath) {\n const methods: Record<string, (req: BunRequest, srv: import('bun').Server<unknown>) => Promise<Response>> = {}\n for (const route of routes) {\n const captured = route\n methods[captured.method] = async (req: BunRequest, srv: import('bun').Server<unknown>) => {\n // Lazy plugin install (same guard as fetch())\n if (!this.installedPlugins) {\n this.installedPlugins = true\n for (const plugin of this.plugins) {\n if (plugin.install) await plugin.install(this.hooks)\n }\n }\n\n const url = new URL(req.url)\n const requestQueue = new RequestEventQueue()\n\n const baseCtx: BaseCtx = {\n req,\n params: {},\n query: parseQuery(url.search),\n json: <T>(data: T, status = 200) => Response.json(data, { status }),\n text: (data: string, status = 200) => new Response(data, { status, headers: { 'Content-Type': 'text/plain' } }),\n html: (data: string, status = 200) => new Response(data, { status, headers: { 'Content-Type': 'text/html' } }),\n stream: makeStreamResponse,\n sse: makeSSEResponse,\n cookie: createCookieJar(req),\n emit: (event, payload) => { requestQueue.collect(event as string, payload) },\n _requestQueue: requestQueue,\n }\n\n // Run global onRequest hooks (before pipeline — same as fetch())\n for (const hook of this._onRequestHooks) {\n let earlyRes: Response | void\n try {\n earlyRes = await hook._fn(baseCtx)\n } catch {\n earlyRes = undefined\n }\n if (earlyRes instanceof Response) {\n return this._runOnResponse(baseCtx, earlyRes, null)\n }\n }\n\n // WS upgrade requests are handled by the fetch() fallback — skip here.\n // (Bun routes don't receive WS upgrade requests via the method handler.)\n\n // Params come from Bun's SIMD router — already extracted, always strings\n return this._runRoute(baseCtx, captured, req.params, requestQueue)\n }\n }\n bunRoutes[path] = methods\n }\n\n return bunRoutes\n }\n\n listen(\n port: number,\n cb?: (port: number) => void,\n options?: { autoHandleSignals?: boolean },\n ): ReturnType<typeof Bun.serve> {\n // Install plugins eagerly so cron handlers have access to the DB adapter\n if (!this.installedPlugins) {\n this.installedPlugins = true\n for (const plugin of this.plugins) {\n if (plugin.install) {\n const result = plugin.install(this.hooks)\n // If install returns a Promise, ignore it — sync plugins (dbPlugin) work fine here\n if (result && typeof (result as any).then === 'function') {\n (result as Promise<void>).catch((err) =>\n this._onInternalError('[veln] Plugin install error during listen():', err),\n )\n }\n }\n }\n }\n\n // Schedule all registered cron jobs before starting the server\n this._scheduleCrons()\n\n // Start Bun server — include websocket config from adapter if registered\n const server = Bun.serve({\n port,\n routes: this._buildBunRoutes(),\n fetch: (req: Request, srv: import('bun').Server<unknown>) => this.fetch(req, srv),\n ...(this._wsAdapter ? { websocket: this._wsAdapter.getWebsocketConfig() } : {}),\n } as any) // 'as any' needed because Bun types require websocket when upgrade is used\n cb?.(port)\n\n // Auto-register SIGTERM/SIGINT handlers to call app.close() on shutdown.\n // Default: true. Pass { autoHandleSignals: false } to disable.\n const autoHandle = options?.autoHandleSignals !== false\n if (autoHandle) {\n let shuttingDown = false\n const shutdown = async () => {\n if (shuttingDown) return\n shuttingDown = true\n await this.close()\n process.exit(0)\n }\n process.on('SIGTERM', shutdown)\n process.on('SIGINT', shutdown)\n }\n\n return server\n }\n\n // Internal: schedule all cron defs.\n // - mode:'process' (default) — croner runs handler in-process, has access to ctx.db\n // - mode:'os' — Bun.cron delegates to a separate script file (OS-level scheduling)\n // Called once at listen(). Safe to call multiple times (idempotent — _cronDefs not cleared).\n private _scheduleCrons(): void {\n const adapter = this.hooks.getAdapter()\n\n const processJobs = this._cronDefs.filter(d => d._mode !== 'os')\n if (!adapter && processJobs.length > 0) {\n console.warn('[veln] .cron() jobs registered but no dbPlugin found — ctx.db will be unavailable in handlers')\n }\n\n for (const def of this._cronDefs) {\n console.log(`[Cron] ${def._name} — registriert (${def._expression})${def._runOnStart ? ', runOnStart' : ''}`)\n\n if (def._mode === 'os') {\n // OS-level — Bun.cron(script, expression, name)\n ;(Bun as unknown as { cron: (script: string, expr: string, name: string) => void })\n .cron(def._script!, def._expression, def._name)\n continue\n }\n\n // In-process — croner\n // eslint-disable-next-line @typescript-eslint/no-require-imports\n const { Cron } = require('croner') as typeof import('croner')\n\n const cronLogger = def._logger\n\n const runJob = async () => {\n const ttlMs = def._ttlMs ?? 30_000\n const acquired = await this._cronLock.acquire(def._name, ttlMs)\n if (!acquired) return // another instance has the lock\n\n const start = Date.now()\n console.log(`[Cron] ${def._name} — running...`)\n try {\n const sysCtx = createSystemCtx({ role: 'cron' })\n const velnDb = adapter ? new VelnDB(adapter, this.hooks) : null\n const boundDb = velnDb ? velnDb.withCtx(sysCtx) : null as unknown as import('../db/index').BoundVelnDB\n\n const services = def._services.length > 0 && boundDb\n ? instantiateServices(def._services, boundDb)\n : {}\n\n await def._handler!({ db: boundDb, ...services }, cronLogger)\n console.log(`[Cron] ${def._name} — done (${Date.now() - start}ms)`)\n } catch (err) {\n if (def._onError) {\n def._onError(err)\n } else {\n console.error(`[Cron] ${def._name} — error:`, err)\n }\n } finally {\n await this._cronLock.release(def._name)\n }\n }\n\n const job = new Cron(\n def._expression,\n { name: def._name, timezone: def._timezone },\n runJob,\n )\n this._cronJobs.set(def._name, job)\n\n if (def._runOnStart) {\n runJob().catch((err) => {\n if (def._onError) {\n def._onError(err)\n } else {\n console.error(`[Cron] ${def._name} runOnStart error:`, err)\n }\n })\n }\n }\n }\n}\n\n/**\n * createApp — creates a new Veln application instance.\n *\n * @param opts.auth Authentication adapter (e.g. BetterAuth). Enables `ctx.user` and permission gates.\n * @param opts.validation Validation options. Set `exposeIssues: true` to include raw Zod issues in 422\n * responses (development only — masks issue details by default).\n * @param opts.eventBus Custom event bus adapter. Defaults to `InMemoryEventBus` (single-process).\n * For multi-instance deployments, supply a Redis or BroadcastChannel adapter.\n * @param opts.cronLock Distributed lock adapter for cron jobs. Defaults to `NoOpCronLockAdapter`\n * (always acquires). For multi-instance deployments, supply a Redis-backed adapter.\n * @param opts.nav Navigation endpoint options. `path` sets the `/nav` endpoint URL.\n * @param opts.db Database options. `db.log.enabled` enables query logging and N+1 detection.\n * `db.log.n1Threshold` sets the query count threshold (default: 10).\n * `db.log.logQueries` logs all SQL statements when N+1 is detected.\n *\n * @example\n * const app = createApp()\n * app.get('/ping', (ctx) => ctx.json({ ok: true }))\n * app.listen(3000)\n */\nexport function createApp(opts: {\n auth?: AuthAdapter\n nav?: { path?: string }\n validation?: { exposeIssues?: boolean }\n eventBus?: EventBusAdapter\n cronLock?: CronLockAdapter\n db?: { log?: { enabled?: boolean; n1Threshold?: number; logQueries?: boolean } }\n} = {}): Veln<BaseCtx, Record<never, never>, never> {\n return new Veln<BaseCtx, Record<never, never>, never>(opts)\n}\n","import type { ZodTypeAny } from 'zod'\n\nexport type JsonSchema = Record<string, unknown>\n\n// Zod v4 check internal structure\ninterface ZodCheckDef {\n check: string\n value?: number\n inclusive?: boolean\n minimum?: number\n maximum?: number\n format?: string\n}\n\ninterface ZodCheckInternal {\n def: ZodCheckDef\n}\n\ninterface ZodCheckWithInternal {\n _zod: ZodCheckInternal\n def?: ZodCheckDef\n}\n\n/** Extract description from any Zod schema — stored as `.description` on the instance. */\nfunction getDescription(schema: ZodTypeAny): string | undefined {\n return (schema as unknown as { description?: string }).description\n}\n\nexport function zodToJsonSchema(schema: ZodTypeAny): JsonSchema {\n const def = (schema._def as unknown) as Record<string, unknown>\n const typeName = def['type'] as string | undefined\n\n if (typeName === 'string') {\n return withDescription(schema, zodStringToSchema(def))\n }\n if (typeName === 'number') {\n return withDescription(schema, zodNumberToSchema(def))\n }\n if (typeName === 'boolean') {\n return withDescription(schema, { type: 'boolean' })\n }\n if (typeName === 'enum') {\n const entries = def['entries'] as Record<string, string> | undefined\n const values = entries ? Object.values(entries) : []\n return withDescription(schema, { type: 'string', enum: values })\n }\n if (typeName === 'object') {\n return withDescription(schema, zodObjectToSchema(def))\n }\n if (typeName === 'array') {\n const element = def['element'] as ZodTypeAny | undefined\n const result: JsonSchema = { type: 'array' }\n if (element) result['items'] = zodToJsonSchema(element)\n return withDescription(schema, result)\n }\n if (typeName === 'optional') {\n const inner = def['innerType'] as ZodTypeAny\n // description may be on the optional wrapper itself\n const desc = getDescription(schema)\n const innerSchema = zodToJsonSchema(inner)\n return desc ? { ...innerSchema, description: desc } : innerSchema\n }\n if (typeName === 'nullable') {\n const inner = def['innerType'] as ZodTypeAny\n const desc = getDescription(schema)\n const innerSchema = zodToJsonSchema(inner)\n const innerType = innerSchema['type']\n const result: JsonSchema = typeof innerType === 'string'\n ? { ...innerSchema, type: [innerType, 'null'] }\n : innerSchema\n return desc ? { ...result, description: desc } : result\n }\n if (typeName === 'default') {\n const inner = def['innerType'] as ZodTypeAny\n const defaultValue = def['defaultValue']\n const innerSchema = zodToJsonSchema(inner)\n const desc = getDescription(schema)\n const result: JsonSchema = defaultValue !== undefined\n ? { ...innerSchema, default: defaultValue }\n : innerSchema\n return desc ? { ...result, description: desc } : result\n }\n // Unknown type — return empty schema (no crash)\n return {}\n}\n\nfunction withDescription(schema: ZodTypeAny, result: JsonSchema): JsonSchema {\n const desc = getDescription(schema)\n return desc ? { ...result, description: desc } : result\n}\n\nfunction zodStringToSchema(def: Record<string, unknown>): JsonSchema {\n const schema: JsonSchema = { type: 'string' }\n const checks = def['checks'] as ZodCheckWithInternal[] | undefined\n if (!checks) return schema\n for (const check of checks) {\n const checkDef: ZodCheckDef | undefined = check._zod?.def ?? check.def\n if (!checkDef) continue\n const kind = checkDef.check\n if (kind === 'string_format') {\n const fmt = checkDef.format\n if (fmt === 'email') schema['format'] = 'email'\n if (fmt === 'uuid') schema['format'] = 'uuid'\n if (fmt === 'url') schema['format'] = 'uri'\n if (fmt === 'datetime') schema['format'] = 'date-time'\n if (fmt === 'date') schema['format'] = 'date'\n if (fmt === 'time') schema['format'] = 'time'\n }\n if (kind === 'min_length' && checkDef.minimum !== undefined) {\n schema['minLength'] = checkDef.minimum\n }\n if (kind === 'max_length' && checkDef.maximum !== undefined) {\n schema['maxLength'] = checkDef.maximum\n }\n }\n return schema\n}\n\nfunction zodNumberToSchema(def: Record<string, unknown>): JsonSchema {\n const schema: JsonSchema = { type: 'number' }\n const checks = def['checks'] as ZodCheckWithInternal[] | undefined\n if (!checks) return schema\n for (const check of checks) {\n const checkDef: ZodCheckDef | undefined = check._zod?.def ?? check.def\n if (!checkDef) continue\n const kind = checkDef.check\n if (kind === 'greater_than' && checkDef.value !== undefined) {\n if (checkDef.inclusive) {\n schema['minimum'] = checkDef.value\n } else {\n schema['exclusiveMinimum'] = checkDef.value\n }\n }\n if (kind === 'less_than' && checkDef.value !== undefined) {\n if (checkDef.inclusive) {\n schema['maximum'] = checkDef.value\n } else {\n schema['exclusiveMaximum'] = checkDef.value\n }\n }\n if (kind === 'multiple_of' && checkDef.value !== undefined) {\n schema['multipleOf'] = checkDef.value\n }\n }\n return schema\n}\n\nfunction zodObjectToSchema(def: Record<string, unknown>): JsonSchema {\n const shape = def['shape'] as Record<string, ZodTypeAny> | undefined\n const resolvedShape: Record<string, ZodTypeAny> = shape ?? {}\n\n const properties: Record<string, JsonSchema> = {}\n const required: string[] = []\n\n for (const [key, fieldSchema] of Object.entries(resolvedShape)) {\n const fieldDef = (fieldSchema._def as unknown) as Record<string, unknown>\n const isOptional = fieldDef['type'] === 'optional'\n properties[key] = zodToJsonSchema(fieldSchema)\n if (!isOptional) {\n required.push(key)\n }\n }\n\n const result: JsonSchema = { type: 'object', properties }\n if (required.length > 0) {\n result['required'] = required\n }\n return result\n}\n","import type { Route } from '../app/types'\nimport { zodToJsonSchema } from './zod-to-schema'\nimport type { JsonSchema } from './zod-to-schema'\nimport type { ZodTypeAny } from 'zod'\n\nexport interface OpenApiSpec {\n openapi: '3.1.0'\n info: { title: string; version: string; description?: string }\n paths: Record<string, Record<string, OpenApiOperation>>\n components?: {\n securitySchemes?: Record<string, OpenApiSecurityScheme>\n }\n}\n\ninterface OpenApiSecurityScheme {\n type: 'http'\n scheme: 'bearer'\n bearerFormat?: string\n}\n\ninterface OpenApiOperation {\n operationId?: string\n summary?: string\n description?: string\n tags?: string[]\n security?: Array<Record<string, string[]>>\n parameters?: OpenApiParameter[]\n requestBody?: OpenApiRequestBody\n responses: Record<string, OpenApiResponse>\n}\n\ninterface OpenApiParameter {\n name: string\n in: 'path' | 'query'\n required: boolean\n schema: JsonSchema\n}\n\ninterface OpenApiRequestBody {\n required: true\n content: {\n 'application/json': {\n schema: JsonSchema\n }\n }\n}\n\ninterface OpenApiResponse {\n description: string\n content?: {\n 'application/json': {\n schema: JsonSchema\n }\n }\n}\n\n// ── Pure helpers ──────────────────────────────────────────────────────────────\n\nfunction toOpenApiPath(path: string): string {\n return path.replace(/:([a-zA-Z_][a-zA-Z0-9_]*)/g, '{$1}')\n}\n\nfunction extractPathParams(path: string): string[] {\n const matches = path.match(/:([a-zA-Z_][a-zA-Z0-9_]*)/g)\n return matches ? matches.map(m => m.slice(1)) : []\n}\n\nfunction capitalize(s: string): string {\n return s.charAt(0).toUpperCase() + s.slice(1)\n}\n\n/** \"users\" → \"Users\", \"api-keys\" → \"Api Keys\" */\nfunction capitalizeTag(tag: string): string {\n return tag.split('-').map(capitalize).join(' ')\n}\n\n/**\n * Derives a human-readable summary from an HTTP method and path.\n *\n * GET /users/ → \"List users\"\n * GET /users/:id → \"Get users by id\"\n * GET /users/search → \"Search users\"\n * POST /users/ → \"Create users\"\n * POST /users/export → \"Export users\"\n * PATCH /users/:id → \"Update users\"\n * DELETE /users/:id → \"Delete users\"\n */\nfunction inferSummary(method: string, path: string): string {\n const segments = path.split('/').filter(Boolean)\n if (segments.length === 0) return method.toLowerCase()\n\n const isParam = (s: string): boolean => s.startsWith(':')\n const resource = segments.find(s => !isParam(s)) ?? 'resource'\n const lastSeg = segments[segments.length - 1] ?? ''\n const hasTrailingParam = isParam(lastSeg)\n const isLiteralVerb = !isParam(lastSeg) && lastSeg !== resource\n\n if (isLiteralVerb) return `${capitalize(lastSeg)} ${resource}`\n\n const m = method.toUpperCase()\n if (m === 'GET') {\n if (hasTrailingParam) return `Get ${resource} by ${lastSeg.slice(1)}`\n return `List ${resource}`\n }\n if (m === 'POST') return `Create ${resource}`\n if (m === 'PATCH') return `Update ${resource}`\n if (m === 'PUT') return `Update ${resource}`\n if (m === 'DELETE') return `Delete ${resource}`\n return `${m.toLowerCase()} ${resource}`\n}\n\n/**\n * Derives a camelCase operationId from an HTTP method and path.\n *\n * GET /users/ → \"listUsers\"\n * GET /users/:id → \"getUsersById\"\n * GET /users/search → \"searchUsers\"\n * POST /users/ → \"createUsers\"\n * PATCH /users/:id → \"updateUsers\"\n * DELETE /users/:id → \"deleteUsers\"\n */\nfunction inferOperationId(method: string, path: string): string {\n const segments = path.split('/').filter(Boolean)\n if (segments.length === 0) return method.toLowerCase()\n\n const isParam = (s: string): boolean => s.startsWith(':')\n const resource = segments.find(s => !isParam(s)) ?? 'resource'\n const lastSeg = segments[segments.length - 1] ?? ''\n const hasTrailingParam = isParam(lastSeg)\n const isLiteralVerb = !isParam(lastSeg) && lastSeg !== resource\n\n if (isLiteralVerb) return `${lastSeg}${capitalize(resource)}`\n\n const m = method.toUpperCase()\n if (m === 'GET') {\n if (hasTrailingParam) return `get${capitalize(resource)}By${capitalize(lastSeg.slice(1))}`\n return `list${capitalize(resource)}`\n }\n if (m === 'POST') return `create${capitalize(resource)}`\n if (m === 'PATCH') return `update${capitalize(resource)}`\n if (m === 'PUT') return `update${capitalize(resource)}`\n if (m === 'DELETE') return `delete${capitalize(resource)}`\n return `${m.toLowerCase()}${capitalize(resource)}`\n}\n\n// ── Generator ─────────────────────────────────────────────────────────────────\n\nexport function generateOpenApiSpec(\n routes: readonly Route<unknown>[],\n options?: { title?: string; version?: string; description?: string },\n): OpenApiSpec {\n const title = options?.title ?? 'Veln API'\n const version = options?.version ?? '1.0.0'\n\n const info: OpenApiSpec['info'] = { title, version }\n if (options?.description) info.description = options.description\n\n const paths: Record<string, Record<string, OpenApiOperation>> = {}\n let needsBearerScheme = false\n\n for (const route of routes) {\n // Skip hidden routes and routes belonging to hidden modules\n const moduleVisibility = route._module?.visibility ?? 'public'\n const routeVisibility = route.visibility ?? moduleVisibility\n if (routeVisibility === 'hidden') continue\n\n const openApiPath = toOpenApiPath(route.path)\n if (!paths[openApiPath]) paths[openApiPath] = {}\n\n const method = route.method.toLowerCase()\n const schema = route.schema\n\n // Build parameters from path params + query schema\n const parameters: OpenApiParameter[] = []\n\n for (const paramName of extractPathParams(route.path)) {\n let paramSchema: JsonSchema = { type: 'string' }\n if (schema?.params) {\n const paramsDef = (schema.params._def as unknown) as Record<string, unknown>\n const shape = paramsDef['shape'] as Record<string, ZodTypeAny> | undefined\n const resolvedShape: Record<string, ZodTypeAny> = shape ?? {}\n if (resolvedShape[paramName]) {\n paramSchema = zodToJsonSchema(resolvedShape[paramName] as ZodTypeAny)\n }\n }\n parameters.push({ name: paramName, in: 'path', required: true, schema: paramSchema })\n }\n\n if (schema?.query) {\n const queryDef = (schema.query._def as unknown) as Record<string, unknown>\n const shape = queryDef['shape'] as Record<string, ZodTypeAny> | undefined\n const resolvedShape: Record<string, ZodTypeAny> = shape ?? {}\n for (const [key, fieldSchema] of Object.entries(resolvedShape)) {\n const fieldDef = (fieldSchema._def as unknown) as Record<string, unknown>\n const isOptional = fieldDef['type'] === 'optional'\n parameters.push({\n name: key,\n in: 'query',\n required: !isOptional,\n schema: zodToJsonSchema(fieldSchema),\n })\n }\n }\n\n // Request body\n let requestBody: OpenApiRequestBody | undefined\n if (schema?.body) {\n requestBody = {\n required: true,\n content: { 'application/json': { schema: zodToJsonSchema(schema.body) } },\n }\n }\n\n // Response\n const responses: Record<string, OpenApiResponse> = {}\n if (schema?.response) {\n responses['200'] = {\n description: 'Success',\n content: { 'application/json': { schema: zodToJsonSchema(schema.response) } },\n }\n } else {\n responses['200'] = { description: 'Success' }\n }\n // Additional responses from docs.responses (e.g. 401, 404)\n if (route.docs?.responses) {\n for (const [code, doc] of Object.entries(route.docs.responses)) {\n responses[code] = { description: doc.description }\n }\n }\n\n // ── Summary / description / operationId — docs override > route fields > auto ──\n const effectiveSummary = route.docs?.summary ?? route.summary ?? inferSummary(route.method, route.path)\n const effectiveDescription = route.docs?.description ?? route.description ?? undefined\n const effectiveOperationId = route.docs?.operationId ?? inferOperationId(route.method, route.path)\n\n // ── Tag — module meta tag wins; fall back to first path segment ──\n const moduleTag = route._module?.meta?.tag\n const segmentTag = route.path.split('/').filter(Boolean)[0] ?? 'general'\n const tag = capitalizeTag(moduleTag ?? segmentTag)\n\n // ── Security — jwtPlugin on module ──\n const modulePlugins = route._module?.plugins ?? []\n const hasJwt = modulePlugins.some(p => p.name === 'jwt')\n if (hasJwt) needsBearerScheme = true\n\n const operation: OpenApiOperation = { responses }\n operation.operationId = effectiveOperationId\n operation.summary = effectiveSummary\n if (effectiveDescription) operation.description = effectiveDescription\n operation.tags = [tag]\n if (hasJwt) operation.security = [{ bearerAuth: [] }]\n if (parameters.length > 0) operation.parameters = parameters\n if (requestBody) operation.requestBody = requestBody\n\n paths[openApiPath]![method] = operation\n }\n\n const spec: OpenApiSpec = { openapi: '3.1.0', info, paths }\n if (needsBearerScheme) {\n spec.components = {\n securitySchemes: {\n bearerAuth: { type: 'http', scheme: 'bearer', bearerFormat: 'JWT' },\n },\n }\n }\n return spec\n}\n","import type { BoundVelnDB } from '../db/index'\nimport type { ServiceDef } from '../service/index'\nimport type { Logger, LogOptions } from '../app/types'\nimport { createMinimalLogger } from '../app/logger'\n\n// ── CronCtx ───────────────────────────────────────────────────────────────────\n\nexport interface CronCtx {\n db: BoundVelnDB\n [key: string]: unknown\n}\n\n// Re-export LogLevel for consumers\nexport type { LogLevel } from '../app/logger'\n\n// ── Expression Shortcuts ──────────────────────────────────────────────────────\n\nconst CRON_SHORTCUTS: Record<string, string> = {\n '@minute': '* * * * *',\n '@hourly': '0 * * * *',\n '@daily': '0 0 * * *',\n '@midnight': '0 0 * * *',\n '@weekly': '0 0 * * 0',\n '@monthly': '0 0 1 * *',\n '@yearly': '0 0 1 1 *',\n '@annually': '0 0 1 1 *',\n}\n\nexport function resolveExpression(expr: string): string {\n return CRON_SHORTCUTS[expr] ?? expr\n}\n\n// ── CronLockAdapter ───────────────────────────────────────────────────────────\n\n/**\n * CronLockAdapter — prevents duplicate job execution across multiple instances.\n *\n * Default: NoOpCronLockAdapter (always acquires — suitable for single-instance deployments)\n *\n * For multi-instance deployments, implement this interface with Redis SET NX EX\n * or a similar distributed lock mechanism.\n *\n * WARNING: TTL must exceed the maximum expected job duration.\n * Consider implementing a lock heartbeat for long-running jobs.\n *\n * @example\n * createApp({ cronLock: new RedisCronLockAdapter(redisClient) })\n */\nexport interface CronLockAdapter {\n acquire(jobName: string, ttlMs: number): Promise<boolean>\n release(jobName: string): Promise<void>\n}\n\nexport class NoOpCronLockAdapter implements CronLockAdapter {\n async acquire(_jobName: string, _ttlMs: number): Promise<boolean> {\n return true // always acquire — single-process default\n }\n async release(_jobName: string): Promise<void> {\n // no-op\n }\n}\n\n// ── CronDef — sealed result, produced by CronBuilder ─────────────────────────\n\nexport interface CronDef<TServices extends Record<string, unknown> = Record<never, never>> {\n readonly _name: string\n readonly _expression: string\n readonly _timezone: string | undefined\n readonly _runOnStart: boolean\n readonly _ttlMs: number | undefined\n readonly _logger: Logger\n readonly _mode: 'process' | 'os'\n readonly _handler: ((ctx: CronCtx & TServices, logger: Logger) => Promise<void> | void) | undefined\n readonly _services: ReadonlyArray<ServiceDef<string, unknown>>\n readonly _script: string | undefined\n readonly _onError: ((err: unknown) => void) | undefined\n\n // .use() on a sealed CronDef is kept for backwards-compat and for app.register()\n // service-merging (which spreads + re-binds). It erases the TServices type\n // (returns CronDef without param) because merging happens at runtime, not statically.\n use<TKey extends string, TDef>(\n service: ServiceDef<TKey, TDef>,\n ): CronDef<TServices & Record<TKey, TDef>>\n}\n\n// ── CronBuildOptions — timezone / runOnStart passed to defineCron() ───────────\n\nexport interface CronBuildOptions {\n timezone?: string\n runOnStart?: boolean\n ttlMs?: number\n log?: LogOptions\n onError?: (err: unknown) => void\n}\n\n// ── CronBuilder — fluent builder returned by defineCron() ─────────────────────\n// TServices accumulates via .use(). Call .handler() or .os() to seal into CronDef.\n\nexport interface CronBuilder<TServices extends Record<string, unknown>> {\n // Set timezone / runOnStart / log — returns the same builder for continued chaining\n options(opts: CronBuildOptions): CronBuilder<TServices>\n\n // Accumulate a service — handler will receive ctx[key] typed\n use<TKey extends string, TDef>(\n service: ServiceDef<TKey, TDef>,\n ): CronBuilder<TServices & Record<TKey, TDef>>\n\n // Seal into a process-mode CronDef. ctx has full TServices typing.\n // logger is always available as the 2nd arg — no-op (error level only) when log not set.\n handler(\n fn: (ctx: CronCtx & TServices, logger: Logger) => Promise<void> | void,\n ): CronDef<TServices>\n\n // Seal into an OS-level (Bun.cron) CronDef. No handler.\n os(script: string): CronDef<TServices>\n}\n\n// ── Helpers ───────────────────────────────────────────────────────────────────\n\nfunction resolveLogOpts(log: LogOptions | undefined): LogOptions {\n // No log configured → silent: true (suppress all output by default)\n return log ?? { silent: true }\n}\n\n// ── Internal factory ──────────────────────────────────────────────────────────\n\nfunction makeCronDef<TServices extends Record<string, unknown>>(\n name: string,\n expression: string,\n timezone: string | undefined,\n runOnStart: boolean,\n ttlMs: number | undefined,\n logger: Logger,\n mode: 'process' | 'os',\n handler: ((ctx: CronCtx & TServices, logger: Logger) => Promise<void> | void) | undefined,\n services: ReadonlyArray<ServiceDef<string, unknown>>,\n script: string | undefined,\n onError: ((err: unknown) => void) | undefined,\n): CronDef<TServices> {\n const def: CronDef<TServices> = {\n _name: name,\n _expression: resolveExpression(expression),\n _timezone: timezone,\n _runOnStart: runOnStart,\n _ttlMs: ttlMs,\n _logger: logger,\n _mode: mode,\n _handler: handler,\n _services: services,\n _script: script,\n _onError: onError,\n\n use<TKey extends string, TDef>(\n service: ServiceDef<TKey, TDef>,\n ): CronDef<TServices & Record<TKey, TDef>> {\n return makeCronDef<TServices & Record<TKey, TDef>>(\n name, expression, timezone, runOnStart, ttlMs, logger, mode,\n handler as ((ctx: CronCtx & TServices & Record<TKey, TDef>, logger: Logger) => Promise<void> | void) | undefined,\n [...services, service as ServiceDef<string, unknown>],\n script,\n onError,\n )\n },\n }\n return def\n}\n\nfunction makeCronBuilder<TServices extends Record<string, unknown>>(\n name: string,\n expression: string,\n opts: CronBuildOptions,\n services: ReadonlyArray<ServiceDef<string, unknown>>,\n): CronBuilder<TServices> {\n return {\n options(newOpts: CronBuildOptions): CronBuilder<TServices> {\n return makeCronBuilder<TServices>(name, expression, { ...opts, ...newOpts }, services)\n },\n\n use<TKey extends string, TDef>(\n service: ServiceDef<TKey, TDef>,\n ): CronBuilder<TServices & Record<TKey, TDef>> {\n return makeCronBuilder<TServices & Record<TKey, TDef>>(\n name, expression, opts,\n [...services, service as ServiceDef<string, unknown>],\n )\n },\n\n handler(fn: (ctx: CronCtx & TServices, logger: Logger) => Promise<void> | void): CronDef<TServices> {\n const logger = createMinimalLogger(`cron:${name}`, resolveLogOpts(opts.log))\n return makeCronDef<TServices>(\n name, expression, opts.timezone, opts.runOnStart ?? false,\n opts.ttlMs, logger, 'process', fn, services, undefined, opts.onError,\n )\n },\n\n os(script: string): CronDef<TServices> {\n const logger = createMinimalLogger(`cron:${name}`, resolveLogOpts(opts.log))\n return makeCronDef<TServices>(\n name, expression, opts.timezone, opts.runOnStart ?? false,\n opts.ttlMs, logger, 'os', undefined, services, script, opts.onError,\n )\n },\n }\n}\n\n/**\n * defineCron — defines a scheduled background job.\n *\n * @param name Unique job identifier. Used as lock key and in log output.\n * @param expression Cron expression or shortcut (`@daily`, `@hourly`, `@minute`, etc.).\n * @param opts Optional timezone, runOnStart, ttlMs (lock TTL), and log options.\n *\n * Call `.handler(fn)` to run in-process, or `.os(script)` for OS-level scheduling via Bun.\n * Chain `.use(ServiceDef)` to inject services into the handler context.\n *\n * @example\n * defineCron('cleanup', '@daily')\n * .use(JobService)\n * .handler(async (ctx) => { await ctx.jobService.deleteExpired() })\n */\nexport function defineCron(\n name: string,\n expression: string,\n opts?: CronBuildOptions,\n): CronBuilder<Record<never, never>> {\n return makeCronBuilder<Record<never, never>>(name, expression, opts ?? {}, [])\n}\n","import type { BaseCtx } from './types'\nimport type { CookieJar } from './cookies'\n\n// ── createSystemCtx ───────────────────────────────────────────────────────────\n// Builds a complete BaseCtx for use outside the HTTP request lifecycle:\n// background jobs, CLI scripts, cron workers, seeding, etc.\n//\n// A dummy Request is provided so hooks that read ctx.req (e.g. ctx.req.url)\n// don't crash — they receive a stable sentinel URL instead of throwing.\n//\n// extra is spread into the returned object, extending BaseCtx with whatever\n// fields the caller's hooks expect (e.g. { user: { id: 'system', role: 'admin' } }).\n//\n// Usage:\n// const ctx = createSystemCtx({ user: { id: 'cron', role: 'admin' } })\n// const bound = db.withCtx(ctx)\n// await bound.into(usersTable).insert({ name: 'Cron User' })\n// // Hooks see ctx.user.id === 'cron' ✅\n// // Audit actor: 'cron' ✅\n\nconst SYSTEM_URL = 'http://system.local/background'\n\n// Empty CookieJar for system/background contexts — no request cookies, no Set-Cookie headers.\nconst emptyCookieJar: CookieJar = {\n get: () => undefined,\n set: () => {},\n delete: () => {},\n _pending: () => [],\n}\n\nexport function createSystemCtx<TExtra extends object = Record<never, never>>(\n extra?: TExtra,\n): BaseCtx & TExtra {\n const base: BaseCtx = {\n req: new Request(SYSTEM_URL),\n params: {},\n query: {},\n json: (data, status = 200) =>\n new Response(JSON.stringify(data), {\n status,\n headers: { 'Content-Type': 'application/json' },\n }),\n text: (data, status = 200) =>\n new Response(data, { status }),\n html: (data, status = 200) =>\n new Response(data, {\n status,\n headers: { 'Content-Type': 'text/html' },\n }),\n cookie: emptyCookieJar,\n emit: () => {},\n stream: () => { throw new Error('[veln] stream not available in system context') },\n sse: () => { throw new Error('[veln] sse not available in system context') },\n }\n\n return { ...base, ...(extra ?? {}) } as BaseCtx & TExtra\n}\n","export interface MatchResult {\n params: Record<string, string | undefined>\n}\n\nexport function matchPath(pattern: string, pathname: string): MatchResult | null {\n // Normalize trailing slashes (but keep root '/')\n const normPattern = pattern.length > 1 ? pattern.replace(/\\/$/, '') : pattern\n const normPathname = pathname.length > 1 ? pathname.replace(/\\/$/, '') : pathname\n\n // Wildcard: pattern ends with /*\n if (normPattern.endsWith('/*')) {\n const prefix = normPattern.slice(0, -2) // remove /*\n if (normPathname.startsWith(prefix + '/')) {\n const rest = normPathname.slice(prefix.length + 1) // skip leading /\n return { params: { '*': rest } }\n }\n return null\n }\n\n const patternSegments = normPattern.split('/')\n const pathSegments = normPathname.split('/')\n\n const params: Record<string, string | undefined> = {}\n\n let pi = 0 // path index\n for (let i = 0; i < patternSegments.length; i++) {\n const pSeg = patternSegments[i]!\n\n if (pSeg.startsWith(':') && pSeg.endsWith('?')) {\n // Optional param\n const paramName = pSeg.slice(1, -1)\n if (pi < pathSegments.length) {\n params[paramName] = pathSegments[pi]\n pi++\n } else {\n params[paramName] = undefined\n }\n } else if (pSeg.startsWith(':')) {\n // Required param\n if (pi >= pathSegments.length) return null\n params[pSeg.slice(1)] = pathSegments[pi]!\n pi++\n } else {\n // Literal\n if (pi >= pathSegments.length || pathSegments[pi] !== pSeg) return null\n pi++\n }\n }\n\n // All path segments must be consumed (unless optional params left pattern shorter)\n if (pi !== pathSegments.length) return null\n\n return { params }\n}\n\nexport function parseQuery(search: string): Record<string, string | string[]> {\n // Strip leading '?' if present\n const raw = search.startsWith('?') ? search.slice(1) : search\n if (!raw) return {}\n\n const result: Record<string, string | string[]> = {}\n const params = new URLSearchParams(raw)\n\n for (const key of params.keys()) {\n const values = params.getAll(key)\n result[key] = values.length === 1 ? values[0]! : values\n }\n\n return result\n}\n","import type { VelnAdapter } from '../adapter/types'\nimport type { SchemaMap } from '../schema/table'\nimport type { ModuleHookHandlers } from '../hooks/types'\nimport type { AuditDeclaration } from './module'\nimport { buildInsert } from '../db/sql'\nimport { applyRedact } from '../schema/audit'\n\n// ── buildAuditHooks ───────────────────────────────────────────────────────────\n// Called by app.register() for each AuditDeclaration.\n// Returns ModuleHookHandlers that write directly to adapter — no ctx, no cast.\n//\n// actor: (ctx: TCtx) => string | null | undefined\n// ctx is passed by HookExecutor at hook-call time — fully typed at the call site,\n// safely typed as unknown here (this file doesn't need to know TCtx internals).\n//\n// Atomicity note: audit writes use the base adapter, not a TX adapter.\n// This means audit rows survive even if the calling TX is rolled back.\n// That is intentional: audit logs are an append-only record of attempted operations.\n//\n// Audit errors are caught and console.error'd — never thrown to the caller.\n\nexport function buildAuditHooks<T extends Record<string, unknown>, TCtx, S extends SchemaMap>(\n decl: AuditDeclaration<T, TCtx, S>,\n adapter: VelnAdapter,\n): ModuleHookHandlers<T, unknown> {\n const { table, config } = decl\n const redactFields = (config.redact ?? []) as string[]\n const auditTable = config.storeIn\n const onError = config.onError ?? ((err: unknown) => console.error('[audit] write failed:', err))\n\n // before-snapshot: WeakMap keyed on the patch object.\n // Each .update() call gets a fresh patch object — the WeakMap entry is\n // GC'd when the patch goes out of scope. No global state, no leaks.\n const snapshots = new WeakMap<object, Record<string, unknown>>()\n\n async function writeAudit(\n operation: 'insert' | 'update' | 'delete',\n actor: string | null,\n before: Record<string, unknown> | null,\n after: Record<string, unknown> | null,\n ): Promise<void> {\n const row: Record<string, unknown> = {\n tableName: table.name,\n operation,\n actor,\n before: before !== null ? JSON.stringify(before) : null,\n after: after !== null ? JSON.stringify(after) : null,\n changedAt: new Date().toISOString(),\n }\n const { sql, params } = buildInsert(auditTable.name, row)\n await adapter.execute(sql, params)\n }\n\n return {\n afterInsert: async (ctx, result) => {\n try {\n const after = redactFields.length ? applyRedact(result as Record<string, unknown>, redactFields) : result as Record<string, unknown>\n const actor = config.actor(ctx as TCtx) ?? null\n await writeAudit('insert', actor, null, after)\n } catch (err) {\n onError(err)\n }\n },\n\n beforeUpdate: async (_ctx, _current, patch) => {\n // Capture snapshot before the update.\n // patch is a unique object per .update() call — safe WeakMap key.\n if (patch !== null && typeof patch === 'object') {\n snapshots.set(patch, _current as Record<string, unknown>)\n }\n },\n\n afterUpdate: async (ctx, result, before) => {\n try {\n const beforeSnap = redactFields.length ? applyRedact(before as Record<string, unknown>, redactFields) : before as Record<string, unknown>\n const afterSnap = redactFields.length ? applyRedact(result as Record<string, unknown>, redactFields) : result as Record<string, unknown>\n const actor = config.actor(ctx as TCtx) ?? null\n await writeAudit('update', actor, beforeSnap, afterSnap)\n } catch (err) {\n onError(err)\n }\n },\n\n afterDelete: async (ctx, deleted) => {\n try {\n const before = redactFields.length ? applyRedact(deleted as Record<string, unknown>, redactFields) : deleted as Record<string, unknown>\n const actor = config.actor(ctx as TCtx) ?? null\n await writeAudit('delete', actor, before, null)\n } catch (err) {\n onError(err)\n }\n },\n }\n}\n","export interface CookieOptions {\n httpOnly?: boolean\n secure?: boolean\n sameSite?: 'Strict' | 'Lax' | 'None'\n maxAge?: number\n path?: string\n domain?: string\n}\n\nexport interface CookieJar {\n get(name: string): string | undefined\n set(name: string, value: string, options?: CookieOptions): void\n delete(name: string): void\n /** Framework-internal: returns all pending Set-Cookie header values */\n _pending(): string[]\n}\n\nexport function createCookieJar(req: Request): CookieJar {\n const pending: string[] = []\n\n function parseCookies(): Record<string, string> {\n const header = req.headers.get('Cookie') ?? ''\n const result: Record<string, string> = {}\n for (const part of header.split(';')) {\n const trimmed = part.trim()\n const eq = trimmed.indexOf('=')\n if (eq === -1) continue\n const name = trimmed.slice(0, eq).trim()\n const value = trimmed.slice(eq + 1).trim()\n if (name) result[name] = value\n }\n return result\n }\n\n // Parse once, cache\n let parsed: Record<string, string> | undefined\n\n return {\n get(name: string): string | undefined {\n if (!parsed) parsed = parseCookies()\n return parsed[name]\n },\n\n set(name: string, value: string, options: CookieOptions = {}): void {\n const parts: string[] = [`${encodeURIComponent(name)}=${encodeURIComponent(value)}`]\n parts.push(`Path=${options.path ?? '/'}`)\n if (options.maxAge !== undefined) parts.push(`Max-Age=${options.maxAge}`)\n if (options.domain) parts.push(`Domain=${options.domain}`)\n const sameSiteValue = options.sameSite ?? 'Lax'\n parts.push(`SameSite=${sameSiteValue}`)\n if (options.secure ?? true) parts.push('Secure')\n if (options.httpOnly ?? true) parts.push('HttpOnly')\n pending.push(parts.join('; '))\n },\n\n delete(name: string): void {\n const parts = [\n `${encodeURIComponent(name)}=`,\n 'Path=/',\n 'Max-Age=0',\n 'Secure',\n 'HttpOnly',\n ]\n pending.push(parts.join('; '))\n },\n\n _pending(): string[] {\n return [...pending]\n },\n }\n}\n","import type { Guard, ErrorHandler, RouteHandler, Route, OnRequestHook, OnBeforeHandleHook, OnResponseHook, RouteHandlerWithSchema, RouteSchema, RouteMap, RouteDocs, WsRouteShape, BaseOptions } from './types'\nimport { createOnRequest, createOnResponse } from './types'\nimport type { Plugin } from './plugin'\nimport type { TableDef, SchemaMap } from '../schema/table'\nimport type { ModuleHookHandlers } from '../hooks/types'\nimport type { BaseCtx } from './types'\nimport type { AuditConfig } from '../schema/audit'\nimport type { ServiceDef } from '../service/index'\nimport type { ZodTypeAny } from 'zod'\nimport type { EventHandlerDef } from '../events/handler'\nimport type { CronDef } from '../cron/index'\nimport type { MiddlewareDef } from './middleware'\nimport { z } from 'zod'\n\nexport interface HookDeclaration<T, TCtx> {\n table: TableDef<T, any>\n handlers: ModuleHookHandlers<T, TCtx>\n}\n\n// AuditDeclaration — carries table + config only.\n// No adapter, no handler closures here.\n// app.register() injects the adapter and wires the hooks.\nexport interface AuditDeclaration<T, TCtx, S extends SchemaMap> {\n table: TableDef<T, any>\n config: AuditConfig<TCtx, T, S>\n}\n\n// ServiceDeclaration — carries a ServiceDef only.\n// Framework instantiates per-request in fetch() after plugins run.\nexport interface ServiceDeclaration<TKey extends string, TDef> {\n readonly service: ServiceDef<TKey, TDef>\n}\n\nexport interface VelnModule {\n prefix: string\n routes: Route<any>[]\n wsRoutes: WsRouteShape[]\n hookDeclarations: HookDeclaration<any, any>[]\n auditDeclarations: AuditDeclaration<any, any, any>[]\n serviceDeclarations: ReadonlyArray<ServiceDeclaration<string, unknown>>\n plugins: Plugin<any, any>[]\n guards: Guard<any>[]\n onRequestHooks: OnRequestHook<any>[]\n onBeforeHandleHooks: OnBeforeHandleHook<any>[]\n onResponseHooks: OnResponseHook<any>[]\n onError?: ErrorHandler<any>\n eventHandlerDefs: EventHandlerDef[]\n cronDefs: CronDef<Record<string, unknown>>[]\n visibility: 'public' | 'hidden'\n meta?: { tag?: string; description?: string }\n options?: BaseOptions\n}\n\n// ── ModuleBuilderState ───────────────────────────────────────────────────────\n// All builder state in one object — clone() spreads it with one override.\n// Adding a new field costs: (1) add here, (2) add to create(), (3) add to build().\n// Zero call-site changes needed anywhere else.\n\ninterface ModuleBuilderState {\n prefix: string\n plugins: Plugin<any, any>[]\n hookDeclarations: HookDeclaration<any, any>[]\n auditDeclarations: AuditDeclaration<any, any, any>[]\n serviceDeclarations: ReadonlyArray<ServiceDeclaration<string, unknown>>\n routes: Route<any>[]\n wsRoutes: WsRouteShape[]\n guards: Guard<any>[]\n onRequestHooks: OnRequestHook<any>[]\n onBeforeHandleHooks: OnBeforeHandleHook<any>[]\n onResponseHooks: OnResponseHook<any>[]\n onError: ErrorHandler<any> | undefined\n eventHandlerDefs: EventHandlerDef[]\n cronDefs: CronDef<Record<string, unknown>>[]\n visibility: 'public' | 'hidden'\n meta: { tag?: string; description?: string } | undefined\n options: BaseOptions | undefined\n}\n\n// RouteDefinition — used by .route(). Generics kept for type inference at call site.\n// The interface itself stays non-generic to allow storage; the .route() method\n// carries the generics so z.infer<TBody> resolves immediately.\nexport interface RouteDefinition<TCtx extends BaseCtx> {\n method: 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE'\n path: string\n summary?: string\n description?: string\n docs?: RouteDocs\n visibility?: 'public' | 'hidden'\n schema?: RouteSchema\n handler: (ctx: TCtx) => Response | Promise<Response>\n}\n\nexport type HttpMethod = 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE'\n\nfunction normalizeHandler<TCtx, S extends RouteSchema>(\n handler: RouteHandler<TCtx> | ((ctx: TCtx) => Response | Promise<Response>) | RouteHandlerWithSchema<TCtx, S>,\n): { handler: RouteHandler<TCtx>; schema: RouteSchema | undefined; docs: RouteDocs | undefined } {\n if (typeof handler === 'function') {\n return { handler: { handler }, schema: undefined, docs: undefined }\n }\n if ('params' in handler || 'query' in handler || 'body' in handler || 'response' in handler || 'docs' in handler) {\n const h = handler as RouteHandlerWithSchema<TCtx, RouteSchema>\n return {\n handler: { handler: h.handler as (ctx: TCtx) => Response | Promise<Response> },\n schema: { params: h.params, query: h.query, body: h.body, response: h.response },\n docs: h.docs,\n }\n }\n return { handler: handler as RouteHandler<TCtx>, schema: undefined, docs: undefined }\n}\n\nexport class ModuleBuilder<TCtx extends BaseCtx, TPrefix extends string = string, TRoutes extends RouteMap = Record<never, never>> {\n // Phantom fields — never assigned at runtime, used only for type extraction\n declare readonly _routes: TRoutes\n declare readonly _prefix: TPrefix\n\n private constructor(protected readonly _state: ModuleBuilderState) {}\n\n // clone() — the only place new ModuleBuilder is constructed after create().\n // Every builder method calls clone() with one override — adding a field\n // to ModuleBuilderState never requires touching existing methods.\n protected clone<NCtx extends BaseCtx = TCtx, NPrefix extends string = TPrefix, NRoutes extends RouteMap = TRoutes>(\n overrides: Partial<ModuleBuilderState>,\n ): ModuleBuilder<NCtx, NPrefix, NRoutes> {\n return new ModuleBuilder<NCtx, NPrefix, NRoutes>({ ...this._state, ...overrides })\n }\n\n // Framework-internal accessor — used by @veln/ws module augmentation.\n // Not part of the public API — prefixed with _ to signal framework-only.\n get _wsRoutes(): WsRouteShape[] { return this._state.wsRoutes }\n\n static create<TPrefix extends string>(prefix: TPrefix): ModuleBuilder<BaseCtx, TPrefix, Record<never, never>> {\n return new ModuleBuilder<BaseCtx, TPrefix, Record<never, never>>({\n prefix,\n plugins: [],\n hookDeclarations: [],\n auditDeclarations: [],\n serviceDeclarations: [],\n routes: [],\n wsRoutes: [],\n guards: [],\n onRequestHooks: [],\n onBeforeHandleHooks: [],\n onResponseHooks: [],\n onError: undefined,\n eventHandlerDefs: [],\n cronDefs: [],\n visibility: 'public',\n meta: undefined,\n options: undefined,\n })\n }\n\n options(opts: BaseOptions): ModuleBuilder<TCtx, TPrefix, TRoutes> {\n return this.clone({ options: opts })\n }\n\n visibility(v: 'public' | 'hidden'): ModuleBuilder<TCtx, TPrefix, TRoutes> {\n return this.clone({ visibility: v })\n }\n\n plugin<TAdd extends object>(p: Plugin<TCtx, TAdd>): ModuleBuilder<TCtx & TAdd, TPrefix, TRoutes> {\n const next = this.clone({ plugins: [...this._state.plugins, p as Plugin<any, any>] })\n return next as unknown as ModuleBuilder<TCtx & TAdd, TPrefix, TRoutes>\n }\n\n // ── .use() ───────────────────────────────────────────────────────────────\n // Service overload: declares a service dep for this module.\n // Middleware overload: registers onRequest/onResponse hooks module-scoped.\n use<TKey extends string, TDef>(\n service: ServiceDef<TKey, TDef>,\n ): ModuleBuilder<TCtx & Record<TKey, TDef>, TPrefix, TRoutes>\n use(middleware: MiddlewareDef): ModuleBuilder<TCtx, TPrefix, TRoutes>\n use<TKey extends string, TDef>(\n serviceOrMiddleware: ServiceDef<TKey, TDef> | MiddlewareDef,\n ): ModuleBuilder<TCtx & Record<TKey, TDef>, TPrefix, TRoutes> | ModuleBuilder<TCtx, TPrefix, TRoutes> {\n if ('_serviceKey' in serviceOrMiddleware) {\n const decl: ServiceDeclaration<TKey, TDef> = { service: serviceOrMiddleware }\n const next = this.clone({\n serviceDeclarations: [...this._state.serviceDeclarations, decl as ServiceDeclaration<string, unknown>],\n })\n return next as unknown as ModuleBuilder<TCtx & Record<TKey, TDef>, TPrefix, TRoutes>\n }\n // MiddlewareDef — wire hooks\n const m = serviceOrMiddleware as MiddlewareDef\n const overrides: Partial<ModuleBuilderState> = {}\n if (m._onRequest) {\n overrides.onRequestHooks = [...this._state.onRequestHooks, createOnRequest(m._onRequest)]\n }\n if (m._onResponse) {\n overrides.onResponseHooks = [...this._state.onResponseHooks, createOnResponse(m._onResponse)]\n }\n return this.clone(overrides)\n }\n\n guard(g: Guard<TCtx>): ModuleBuilder<TCtx, TPrefix, TRoutes> {\n return this.clone({ guards: [...this._state.guards, g as Guard<any>] })\n }\n\n onRequest(hook: OnRequestHook<TCtx>): ModuleBuilder<TCtx, TPrefix, TRoutes> {\n return this.clone({ onRequestHooks: [...this._state.onRequestHooks, hook as OnRequestHook<any>] })\n }\n\n onBeforeHandle(hook: OnBeforeHandleHook<TCtx>): ModuleBuilder<TCtx, TPrefix, TRoutes> {\n return this.clone({ onBeforeHandleHooks: [...this._state.onBeforeHandleHooks, hook as OnBeforeHandleHook<any>] })\n }\n\n onResponse(hook: OnResponseHook<TCtx>): ModuleBuilder<TCtx, TPrefix, TRoutes> {\n return this.clone({ onResponseHooks: [...this._state.onResponseHooks, hook as OnResponseHook<any>] })\n }\n\n hook<T>(table: TableDef<T, any>, handlers: ModuleHookHandlers<T, TCtx>): ModuleBuilder<TCtx, TPrefix, TRoutes> {\n return this.clone({ hookDeclarations: [...this._state.hookDeclarations, { table, handlers }] })\n }\n\n // ── .audit() ─────────────────────────────────────────────────────────────\n // Declares that this table should be audited with the given config.\n // No hooks are built here — no adapter, no closures.\n // app.register() receives the AuditDeclaration and wires the adapter there.\n audit<T extends Record<string, unknown>, S extends SchemaMap>(\n table: TableDef<T, any>,\n config: AuditConfig<TCtx, T, S>,\n ): ModuleBuilder<TCtx, TPrefix, TRoutes> {\n const decl: AuditDeclaration<T, TCtx, S> = { table, config }\n return this.clone({ auditDeclarations: [...this._state.auditDeclarations, decl] })\n }\n\n events(handler: EventHandlerDef): ModuleBuilder<TCtx, TPrefix, TRoutes> {\n return this.clone({ eventHandlerDefs: [...this._state.eventHandlerDefs, handler] })\n }\n\n cron(def: CronDef): ModuleBuilder<TCtx, TPrefix, TRoutes> {\n return this.clone({ cronDefs: [...this._state.cronDefs, def] })\n }\n\n private _addRoute<S extends RouteSchema>(\n method: HttpMethod,\n path: string,\n handlerArg: RouteHandler<TCtx> | ((ctx: TCtx) => Response | Promise<Response>) | RouteHandlerWithSchema<TCtx, S>,\n ): ModuleBuilder<TCtx, TPrefix, TRoutes> {\n const { handler, schema, docs } = normalizeHandler(handlerArg)\n const guardDef = typeof handlerArg === 'object' && 'handler' in handlerArg && !('_phase' in handlerArg)\n ? (handlerArg as RouteHandlerWithSchema<TCtx, S>).guard\n : undefined\n const route: Route<any> = {\n method, path, handler, schema, docs,\n guards: guardDef != null && guardDef !== false ? [guardDef as Guard<unknown>] : [],\n moduleGuardOptOut: guardDef === false ? true : undefined,\n }\n return this.clone({ routes: [...this._state.routes, route] })\n }\n\n // ── .route() ─────────────────────────────────────────────────────────────\n //\n // Analysis (Spec 05):\n // 1. Method shortcuts ARE wrappers around _registerMethod() → _addRoute().\n // 2. Body/params/query schemas are stored in route.schema; validation runs at\n // request time in the framework fetch() pipeline.\n // 3. Generics TBody/TParams/etc flow into RouteMap via the typed overload return\n // type: Record<`METHOD ${TPrefix}${TPath}`, { body, params, query, response, _prefix }>.\n // 4. Old .route() built the Route object manually, used a nested `schema:{}` wrapper,\n // and returned ModuleBuilder without updating TRoutes.\n //\n // Implementation: delegate to _registerMethod() so validation logic is shared\n // (no duplication). The typed overload updates TRoutes just like .get()/.post() etc.\n // Backward compat: top-level `summary` and nested `schema:{}` both still work.\n\n // Overload 1 — legacy: nested `schema:{}` wrapper (backward compat, tried first so\n // calls with `schema` don't fall through to the flat overload)\n route<\n TBody extends ZodTypeAny = never,\n TParams extends ZodTypeAny = never,\n TQuery extends ZodTypeAny = never,\n >(def: {\n method: HttpMethod\n path: string\n /** @deprecated Use docs.summary instead */\n summary?: string\n description?: string\n docs?: RouteDocs\n visibility?: 'public' | 'hidden'\n schema?: {\n body?: TBody\n params?: TParams\n query?: TQuery\n response?: ZodTypeAny\n }\n handler: (ctx: TCtx & {\n body: z.infer<TBody>\n params: z.infer<TParams>\n query: z.infer<TQuery>\n }) => Response | Promise<Response>\n }): ModuleBuilder<TCtx, TPrefix, TRoutes>\n // Overload 2 — fully typed: flat body/params/query/response + updates RouteMap.\n // NoInfer<TBody/TParams/TQuery> in the handler parameter prevents TypeScript from\n // trying to infer the generics from the handler (which would cause a circular\n // dependency with the `body:`, `params:`, `query:` fields in the same object literal).\n // TypeScript infers the generics from the schema fields first, then contextually\n // types the handler using NoInfer — the same pattern used by tRPC and similar frameworks.\n route<\n TMethod extends HttpMethod = HttpMethod,\n TBody extends ZodTypeAny = never,\n TParams extends ZodTypeAny = never,\n TQuery extends ZodTypeAny = never,\n TResponse extends ZodTypeAny = never,\n TPath extends string = string,\n >(def: {\n method: TMethod\n path: TPath\n body?: TBody\n params?: TParams\n query?: TQuery\n response?: TResponse\n docs?: RouteDocs\n guard?: Guard<TCtx> | false\n /** @deprecated Use docs.summary instead */\n summary?: string\n description?: string\n visibility?: 'public' | 'hidden'\n handler: (ctx: TCtx & {\n body: z.infer<NoInfer<TBody>>\n params: z.infer<NoInfer<TParams>>\n query: z.infer<NoInfer<TQuery>>\n }) => Response | Promise<Response>\n }): ModuleBuilder<TCtx, TPrefix, TRoutes & Record<`${TMethod} ${TPrefix}${TPath}`, { body: TBody; params: TParams; query: TQuery; response: TResponse; _prefix: TPrefix }>>\n // Implementation — handles both overloads\n route(def: {\n method: HttpMethod\n path: string\n body?: ZodTypeAny\n params?: ZodTypeAny\n query?: ZodTypeAny\n response?: ZodTypeAny\n docs?: RouteDocs\n guard?: Guard<TCtx> | false\n summary?: string\n description?: string\n visibility?: 'public' | 'hidden'\n schema?: {\n body?: ZodTypeAny\n params?: ZodTypeAny\n query?: ZodTypeAny\n response?: ZodTypeAny\n }\n handler: (ctx: TCtx) => Response | Promise<Response>\n }): ModuleBuilder<TCtx, TPrefix, RouteMap> {\n // Normalize docs — merge deprecated top-level summary into docs.summary\n let docs = def.docs\n if (def.summary !== undefined) {\n docs = { ...docs, summary: docs?.summary ?? def.summary }\n }\n // Support both flat (new) and nested schema (legacy) forms\n const body = def.body ?? def.schema?.body\n const params = def.params ?? def.schema?.params\n const query = def.query ?? def.schema?.query\n const response = def.response ?? def.schema?.response\n // Build the defOrHandler object for _registerMethod — identical shape to method shortcuts\n const defObj: { body?: ZodTypeAny; params?: ZodTypeAny; query?: ZodTypeAny; response?: ZodTypeAny; docs?: RouteDocs; handler: (ctx: TCtx) => Response | Promise<Response> } = {\n body,\n params,\n query,\n response,\n docs,\n handler: def.handler,\n }\n // Register via shared _registerMethod — no duplication of validation logic.\n // We pre-build the route so we can patch legacy fields (summary, description,\n // visibility, guard) before cloning — all within the same class so _state is accessible.\n const { handler: rh, schema, docs: normalizedDocs } = normalizeHandler(defObj)\n const route: Route<TCtx> = {\n method: def.method,\n path: def.path,\n summary: def.summary,\n description: def.description,\n visibility: def.visibility,\n docs: normalizedDocs,\n handler: rh,\n guards: def.guard != null && def.guard !== false ? [def.guard as Guard<unknown>] : [],\n moduleGuardOptOut: def.guard === false ? true : undefined,\n schema,\n }\n return this.clone({ routes: [...this._state.routes, route] })\n }\n\n meta(m: { tag?: string; description?: string }): ModuleBuilder<TCtx, TPrefix, TRoutes> {\n return this.clone({ meta: m })\n }\n\n // ── HTTP methods ─────────────────────────────────────────────────────────\n // Two overloads per method:\n // 1. (path, { body?, params?, query?, response?, handler }) — separate generics,\n // z.infer<TBody> resolved immediately — no deferred conditional, no unknown body\n // 2. (path, handler) — plain function, no schema\n //\n // The (path, schema, handler) 3-arg form is intentionally omitted — use overload 1.\n\n private _registerMethod(\n method: 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE',\n path: string,\n defOrHandler: { body?: ZodTypeAny; params?: ZodTypeAny; query?: ZodTypeAny; response?: ZodTypeAny; docs?: RouteDocs; guard?: Guard<TCtx> | false; handler: (ctx: any) => Response | Promise<Response> } | RouteHandler<TCtx> | ((ctx: TCtx) => Response | Promise<Response>),\n ): ModuleBuilder<TCtx, TPrefix, RouteMap> {\n if (typeof defOrHandler === 'object' && 'handler' in defOrHandler && typeof defOrHandler.handler === 'function' && !('_phase' in defOrHandler)) {\n const { handler, body, params, query, response, docs, guard } = defOrHandler as { handler: (ctx: TCtx) => Response | Promise<Response>; body?: ZodTypeAny; params?: ZodTypeAny; query?: ZodTypeAny; response?: ZodTypeAny; docs?: RouteDocs; guard?: Guard<TCtx> | false }\n return this._addRoute(method, path, { handler, body, params, query, response, docs, guard } as RouteHandlerWithSchema<TCtx, RouteSchema>)\n }\n return this._addRoute(method, path, defOrHandler as RouteHandler<TCtx> | ((ctx: TCtx) => Response | Promise<Response>))\n }\n\n get<\n TBody extends ZodTypeAny = never,\n TParams extends ZodTypeAny = never,\n TQuery extends ZodTypeAny = never,\n TResponse extends ZodTypeAny = never,\n TPath extends string = string,\n >(path: TPath, def: {\n body?: TBody\n params?: TParams\n query?: TQuery\n response?: TResponse\n docs?: RouteDocs\n guard?: Guard<TCtx> | false\n handler: (ctx: TCtx & { body: z.infer<TBody>; params: z.infer<TParams>; query: z.infer<TQuery> }) => Response | Promise<Response>\n }): ModuleBuilder<TCtx, TPrefix, TRoutes & Record<`GET ${TPrefix}${TPath}`, { body: TBody; params: TParams; query: TQuery; response: TResponse; _prefix: TPrefix }>>\n get(path: string, handler: RouteHandler<TCtx> | ((ctx: TCtx) => Response | Promise<Response>)): ModuleBuilder<TCtx, TPrefix, TRoutes>\n get(path: string, defOrHandler: Parameters<typeof this._registerMethod>[2]): ModuleBuilder<TCtx, TPrefix, RouteMap> {\n return this._registerMethod('GET', path, defOrHandler)\n }\n\n post<\n TBody extends ZodTypeAny = never,\n TParams extends ZodTypeAny = never,\n TQuery extends ZodTypeAny = never,\n TResponse extends ZodTypeAny = never,\n TPath extends string = string,\n >(path: TPath, def: {\n body?: TBody\n params?: TParams\n query?: TQuery\n response?: TResponse\n docs?: RouteDocs\n guard?: Guard<TCtx> | false\n handler: (ctx: TCtx & { body: z.infer<TBody>; params: z.infer<TParams>; query: z.infer<TQuery> }) => Response | Promise<Response>\n }): ModuleBuilder<TCtx, TPrefix, TRoutes & Record<`POST ${TPrefix}${TPath}`, { body: TBody; params: TParams; query: TQuery; response: TResponse; _prefix: TPrefix }>>\n post(path: string, handler: RouteHandler<TCtx> | ((ctx: TCtx) => Response | Promise<Response>)): ModuleBuilder<TCtx, TPrefix, TRoutes>\n post(path: string, defOrHandler: Parameters<typeof this._registerMethod>[2]): ModuleBuilder<TCtx, TPrefix, RouteMap> {\n return this._registerMethod('POST', path, defOrHandler)\n }\n\n put<\n TBody extends ZodTypeAny = never,\n TParams extends ZodTypeAny = never,\n TQuery extends ZodTypeAny = never,\n TResponse extends ZodTypeAny = never,\n TPath extends string = string,\n >(path: TPath, def: {\n body?: TBody\n params?: TParams\n query?: TQuery\n response?: TResponse\n docs?: RouteDocs\n guard?: Guard<TCtx> | false\n handler: (ctx: TCtx & { body: z.infer<TBody>; params: z.infer<TParams>; query: z.infer<TQuery> }) => Response | Promise<Response>\n }): ModuleBuilder<TCtx, TPrefix, TRoutes & Record<`PUT ${TPrefix}${TPath}`, { body: TBody; params: TParams; query: TQuery; response: TResponse; _prefix: TPrefix }>>\n put(path: string, handler: RouteHandler<TCtx> | ((ctx: TCtx) => Response | Promise<Response>)): ModuleBuilder<TCtx, TPrefix, TRoutes>\n put(path: string, defOrHandler: Parameters<typeof this._registerMethod>[2]): ModuleBuilder<TCtx, TPrefix, RouteMap> {\n return this._registerMethod('PUT', path, defOrHandler)\n }\n\n patch<\n TBody extends ZodTypeAny = never,\n TParams extends ZodTypeAny = never,\n TQuery extends ZodTypeAny = never,\n TResponse extends ZodTypeAny = never,\n TPath extends string = string,\n >(path: TPath, def: {\n body?: TBody\n params?: TParams\n query?: TQuery\n response?: TResponse\n docs?: RouteDocs\n guard?: Guard<TCtx> | false\n handler: (ctx: TCtx & { body: z.infer<TBody>; params: z.infer<TParams>; query: z.infer<TQuery> }) => Response | Promise<Response>\n }): ModuleBuilder<TCtx, TPrefix, TRoutes & Record<`PATCH ${TPrefix}${TPath}`, { body: TBody; params: TParams; query: TQuery; response: TResponse; _prefix: TPrefix }>>\n patch(path: string, handler: RouteHandler<TCtx> | ((ctx: TCtx) => Response | Promise<Response>)): ModuleBuilder<TCtx, TPrefix, TRoutes>\n patch(path: string, defOrHandler: Parameters<typeof this._registerMethod>[2]): ModuleBuilder<TCtx, TPrefix, RouteMap> {\n return this._registerMethod('PATCH', path, defOrHandler)\n }\n\n delete<\n TBody extends ZodTypeAny = never,\n TParams extends ZodTypeAny = never,\n TQuery extends ZodTypeAny = never,\n TResponse extends ZodTypeAny = never,\n TPath extends string = string,\n >(path: TPath, def: {\n body?: TBody\n params?: TParams\n query?: TQuery\n response?: TResponse\n docs?: RouteDocs\n guard?: Guard<TCtx> | false\n handler: (ctx: TCtx & { body: z.infer<TBody>; params: z.infer<TParams>; query: z.infer<TQuery> }) => Response | Promise<Response>\n }): ModuleBuilder<TCtx, TPrefix, TRoutes & Record<`DELETE ${TPrefix}${TPath}`, { body: TBody; params: TParams; query: TQuery; response: TResponse; _prefix: TPrefix }>>\n delete(path: string, handler: RouteHandler<TCtx> | ((ctx: TCtx) => Response | Promise<Response>)): ModuleBuilder<TCtx, TPrefix, TRoutes>\n delete(path: string, defOrHandler: Parameters<typeof this._registerMethod>[2]): ModuleBuilder<TCtx, TPrefix, RouteMap> {\n return this._registerMethod('DELETE', path, defOrHandler)\n }\n\n onError(handler: ErrorHandler<TCtx>): ModuleBuilder<TCtx, TPrefix, TRoutes> {\n return this.clone({ onError: handler as ErrorHandler<any> })\n }\n\n build(): VelnModule & { readonly _routes: TRoutes; readonly _prefix: TPrefix } {\n const s = this._state\n const mod: VelnModule = {\n prefix: s.prefix,\n routes: [...s.routes],\n wsRoutes: [...s.wsRoutes],\n hookDeclarations: [...s.hookDeclarations],\n auditDeclarations: [...s.auditDeclarations],\n serviceDeclarations: [...s.serviceDeclarations],\n plugins: [...s.plugins],\n guards: [...s.guards],\n onRequestHooks: [...s.onRequestHooks],\n onBeforeHandleHooks: [...s.onBeforeHandleHooks],\n onResponseHooks: [...s.onResponseHooks],\n onError: s.onError,\n eventHandlerDefs: [...s.eventHandlerDefs],\n cronDefs: [...s.cronDefs],\n visibility: s.visibility,\n meta: s.meta,\n options: s.options,\n }\n // Phantom cast — _routes and _prefix don't exist at runtime,\n // they only carry type information for createProxyClient / .module()\n return mod as VelnModule & { readonly _routes: TRoutes; readonly _prefix: TPrefix }\n }\n}\n\n/**\n * defineModule — groups routes, guards, services, and cron jobs under a shared prefix.\n *\n * @param prefix URL prefix for all routes in this module (e.g. `'/users'`).\n *\n * Supply a `TCtx` generic to get typed handlers without casts:\n * `defineModule<BaseCtx & { user: AuthUser }>('/admin')`\n *\n * @example\n * const usersModule = defineModule('/users')\n * .get('/', (ctx) => ctx.json([]))\n * .build()\n * app.register(usersModule)\n */\nexport function defineModule<TCtx extends BaseCtx = BaseCtx, TPrefix extends string = string>(\n prefix: TPrefix,\n): ModuleBuilder<TCtx, TPrefix, Record<never, never>> {\n // ModuleBuilder.create() always returns ModuleBuilder<BaseCtx, ...>.\n // We cast to the caller-supplied TCtx here — this is the only cast needed,\n // and it's in the framework internals, not user code.\n return ModuleBuilder.create(prefix) as unknown as ModuleBuilder<TCtx, TPrefix, Record<never, never>>\n}\n","import type { BaseCtx, Logger, BaseOptions } from './types'\nimport type { VelnAdapter } from '../adapter/types'\nimport type { HookExecutor } from '../hooks/executor'\nimport type { EventBus } from '../events/index'\nimport type { BoundVelnDB } from '../db/index'\nimport type { VelnModule } from './module'\nimport { createMinimalLogger } from './logger'\nimport { type AdapterConfig, resolveAdapter as resolveAdapterConfig } from '../adapter/resolve'\n\n/** A single navigation item contributed by a plugin via .nav(). */\nexport interface NavItem {\n label: string\n route: string\n icon?: string\n order?: number\n children?: NavItem[]\n}\n\n// ── ModulesInput — Option A (Spec 04) ────────────────────────────────────────\n//\n// .modules() now accepts either a plain array OR a factory function.\n//\n// Factory form: .modules((ctx: TCtx) => [myModule])\n//\n// Purpose: the factory's argument type gives TypeScript the correct ctx for\n// modules defined inside it — purely a compile-time convenience.\n//\n// IMPORTANT: the factory is called at plugin-build time with a dummy empty\n// object. The factory's argument is NEVER used for actual request handling —\n// it exists only to let TypeScript infer the correct ctx type for the modules\n// returned. The resulting VelnModule[] is extracted once and stored as a plain\n// array, identical to the non-factory case.\nexport type ModulesInput<TCtx> = VelnModule[] | ((ctx: TCtx) => VelnModule[])\n\nexport interface Plugin<TCtx, TAdd extends object> {\n name: string\n /**\n * Optional list of plugin names that must be registered before this plugin.\n * app.plugin() validates this at registration time and throws PLUGIN_MISSING_DEP\n * if a required plugin is not yet registered.\n *\n * Example: eventBusPlugin sets requires: ['db'] to enforce registration order.\n */\n requires?: string[]\n /**\n * Optional list of modules this plugin contributes.\n * app.plugin() calls app.register() on each entry automatically.\n *\n * Can also be set to a factory function for typed ctx inference (Option A, Spec 04).\n * The factory is called once with a dummy ctx to extract the module list —\n * it is NEVER called at request time.\n */\n modules?: VelnModule[]\n /**\n * Optional permission gate for all routes contributed via .modules().\n * app.plugin() checks ctx.user before running plugin.request() for those routes.\n * User must have at least one of the listed permissions — checked via AuthAdapter.hasPermission().\n * No user → 401. User without any matching permission → 403.\n */\n permissions?: string[]\n /**\n * Optional nav items contributed by this plugin.\n * GET /nav returns these filtered by the plugin's permissions for the current user.\n */\n nav?: NavItem[]\n // install receives the app's HookExecutor so plugins can register hooks into it.\n // Most plugins ignore it — only dbPlugin uses it to wire itself into the app.\n install?: (hooks: HookExecutor) => Promise<void> | void\n request: (ctx: TCtx) => Promise<TCtx & TAdd> | (TCtx & TAdd)\n teardown?: () => Promise<void> | void\n}\n\n// ── PluginBuilder — fluent builder for definePlugin() ─────────────────────────\n\nexport class PluginBuilder<TAdd extends object> {\n private _options: BaseOptions = {}\n private _requires: string[] = []\n private _modules: VelnModule[] = []\n private _permissions: string[] = []\n private _nav: NavItem[] = []\n\n constructor(private readonly _name: string) {}\n\n options(opts: BaseOptions): this {\n this._options = opts\n return this\n }\n\n requires(deps: string[]): this {\n this._requires = deps\n return this\n }\n\n // Option A (Spec 04): accepts a plain array OR a factory function.\n //\n // Factory form: .modules((ctx: BaseCtx & TAdd) => [myModule])\n //\n // The factory receives a typed ctx so TypeScript can infer the correct ctx\n // type for handlers defined inside the returned modules. This is a pure\n // compile-time feature — the factory is called ONCE here (at plugin-build\n // time) with a dummy empty object to extract the VelnModule[]. The dummy\n // argument is NEVER used for actual request handling and carries no real data.\n // The result is stored as a plain VelnModule[], identical to the array form.\n modules(input: ModulesInput<BaseCtx & TAdd>): this {\n if (typeof input === 'function') {\n // Call factory with a dummy ctx to extract the module array.\n // IMPORTANT: The factory's argument is never used at request time —\n // its sole purpose is to give TypeScript the correct ctx type.\n // We cast the empty object so the runtime call succeeds without `any`.\n this._modules = input({} as BaseCtx & TAdd)\n } else {\n this._modules = input\n }\n return this\n }\n\n permission(perm: string | string[]): this {\n this._permissions = Array.isArray(perm) ? perm : [perm]\n return this\n }\n\n nav(items: NavItem | NavItem[]): this {\n this._nav = Array.isArray(items) ? items : [items]\n return this\n }\n\n // Shorthand: only need to provide a request() factory. Returns Plugin directly (not a factory fn).\n extend(\n fn: (ctx: BaseCtx) => Promise<TAdd> | TAdd,\n ): Plugin<BaseCtx, TAdd> {\n const logger = createMinimalLogger(`plugin:${this._name}`, this._options.log)\n const name = this._name\n const requires = this._requires.length > 0 ? this._requires : undefined\n const modules = this._modules.length > 0 ? this._modules : undefined\n const permissions = this._permissions.length > 0 ? this._permissions : undefined\n const nav = this._nav.length > 0 ? this._nav : undefined\n return {\n name,\n requires,\n modules,\n permissions,\n nav,\n install: undefined,\n request: async (ctx) => {\n logger.debug('request', { plugin: name })\n return { ...ctx, ...await fn(ctx) }\n },\n teardown: undefined,\n }\n }\n\n // Full control — install + request + teardown.\n build(def: {\n install?: (hooks: HookExecutor) => Promise<void> | void\n request: (ctx: BaseCtx) => Promise<TAdd> | TAdd\n teardown?: () => Promise<void> | void\n }): Plugin<BaseCtx, TAdd> {\n const logger = createMinimalLogger(`plugin:${this._name}`, this._options.log)\n const name = this._name\n const requires = this._requires.length > 0 ? this._requires : undefined\n const modules = this._modules.length > 0 ? this._modules : undefined\n const permissions = this._permissions.length > 0 ? this._permissions : undefined\n const nav = this._nav.length > 0 ? this._nav : undefined\n return {\n name,\n requires,\n modules,\n permissions,\n nav,\n install: def.install,\n request: async (ctx) => {\n logger.debug('request', { plugin: name })\n return { ...ctx, ...await def.request(ctx) }\n },\n teardown: def.teardown,\n }\n }\n}\n\n/**\n * definePlugin — creates a named plugin that extends the request context.\n *\n * @param name Unique plugin name. Used for deduplication — a plugin with the same\n * name is installed at most once per app instance.\n *\n * @example\n * const tenantPlugin = definePlugin<{ tenantId: string }>('tenant')\n * .request((ctx) => ({ tenantId: ctx.req.headers.get('x-tenant-id') ?? 'default' }))\n * .build()\n * app.plugin(tenantPlugin)\n */\nexport function definePlugin<TAdd extends object = object>(\n name: string,\n): PluginBuilder<TAdd> {\n return new PluginBuilder<TAdd>(name)\n}\n\n// createPlugin — factory helper that merges TAdd into ctx internally.\n// The user-supplied request() only needs to return TAdd (not { ...ctx, ...TAdd }).\n// The framework spreads ctx internally so user code stays clean.\n// @deprecated Use definePlugin() for the fluent builder API.\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport function createPlugin<TAdd extends object>(\n name: string,\n definition: {\n install?: () => Promise<void> | void\n request: (ctx: BaseCtx) => Promise<TAdd> | TAdd\n teardown?: () => Promise<void> | void\n },\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\n): () => Plugin<any, TAdd> {\n return () => ({\n name,\n install: definition.install ? () => definition.install!() : undefined,\n request: async (ctx) => ({ ...ctx, ...await definition.request(ctx) }),\n teardown: definition.teardown,\n })\n}\n\n// loggerPlugin — adds ctx.logger\n// Generic over TCtx so it composes correctly in a plugin chain that already has other fields.\nexport function loggerPlugin<TCtx extends BaseCtx>(): Plugin<TCtx, { logger: Logger }> {\n const logger: Logger = {\n info: (msg, ...args) => console.log(`[INFO] ${msg}`, ...args),\n warn: (msg, ...args) => console.warn(`[WARN] ${msg}`, ...args),\n error: (msg, ...args) => console.error(`[ERROR] ${msg}`, ...args),\n debug: (msg, ...args) => console.log(`[DEBUG] ${msg}`, ...args),\n }\n return {\n name: 'logger',\n request: (ctx) => ({ ...ctx, logger }),\n }\n}\n\n// eventBusPlugin — adds ctx.events\n// IMPORTANT: register BEFORE dbPlugin — withCtx(ctx) in dbPlugin snapshots the ctx at\n// request time, so ctx.events must already be present for module hooks to access it.\n//\n// Calling with no argument auto-creates an EventBus. Access it via plugin.bus:\n// const eventsPlugin = eventBusPlugin()\n// app.plugin(eventsPlugin)\n// eventsPlugin.bus.on('user.created', handler)\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport function eventBusPlugin(bus?: EventBus): Plugin<any, { events: EventBus }> & { bus: EventBus } {\n // eslint-disable-next-line @typescript-eslint/no-require-imports\n const resolvedBus: EventBus = bus ?? new (require('../events/index') as typeof import('../events/index')).EventBus()\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const plugin: Plugin<any, { events: EventBus }> & { bus: EventBus } = {\n name: 'eventBus',\n bus: resolvedBus,\n request: (ctx) => ({ ...ctx, events: resolvedBus }),\n }\n return plugin\n}\n\n// ── DbPluginConfig — declarative adapter creation ─────────────────────────────\n\nexport type DbPluginConfig = AdapterConfig | VelnAdapter\n\nexport interface DbLogOptions {\n /** Whether query logging is enabled. Default: false. */\n enabled: boolean\n /** Emit a warning for queries that exceed this threshold in milliseconds. */\n slowQueryMs?: number\n /** Log level used for query logging. Default: 'debug'. */\n level?: 'debug' | 'info' | 'warn'\n /** Custom per-query callback. Receives the full QueryLogEntry for each query. */\n onQuery?: (entry: import('../adapter/types').QueryLogEntry) => void\n}\n\n// dbPlugin — adds ctx.db as a BoundVelnDB scoped to the request ctx.\n// The HookExecutor is NOT created here — it is received from the app via install(hooks).\n// This ensures module hook registrations (app.register()) and DB operations share the same executor.\n// IMPORTANT: register AFTER eventBusPlugin/loggerPlugin — withCtx(ctx) snapshots the full\n// ctx at request time, so ctx.events and ctx.logger must already be on ctx before db binds.\nexport function dbPlugin<TCtx extends BaseCtx>(\n config: DbPluginConfig,\n log?: DbLogOptions,\n): Plugin<TCtx, { db: BoundVelnDB }> {\n // eslint-disable-next-line @typescript-eslint/no-require-imports\n const { VelnDB } = require('../db/index') as typeof import('../db/index')\n let velnDB: InstanceType<typeof import('../db/index').VelnDB> | null = null\n\n // Build a global onQuery handler if logging is enabled.\n // This is set once on the adapter and called for every query across all requests.\n // For per-request handling (slow query logging, query counters), see BoundVelnDB.\n let globalOnQuery: ((entry: import('../adapter/types').QueryLogEntry) => void) | undefined\n if (log?.enabled) {\n const slowMs = log.slowQueryMs\n const level = log.level ?? 'debug'\n const custom = log.onQuery\n globalOnQuery = (entry) => {\n const prefix = `[veln:db] ${entry.type} (${entry.durationMs.toFixed(2)}ms)`\n if (slowMs !== undefined && entry.durationMs >= slowMs) {\n console.warn(`[veln:db] SLOW QUERY (${entry.durationMs.toFixed(2)}ms): ${entry.sql}`)\n } else {\n if (level === 'info') console.log(`${prefix} ${entry.sql}`)\n else if (level === 'warn') console.warn(`${prefix} ${entry.sql}`)\n else console.debug(`${prefix} ${entry.sql}`)\n }\n custom?.(entry)\n }\n } else if (log?.onQuery) {\n // enabled is false but a custom handler was supplied — wire it anyway\n globalOnQuery = log.onQuery\n }\n\n return {\n name: 'db',\n install: (hooks) => {\n const adapter = resolveAdapterConfig(config)\n if (globalOnQuery) adapter.onQuery = globalOnQuery\n hooks.setAdapter(adapter)\n velnDB = new VelnDB(adapter, hooks)\n },\n request: (ctx) => {\n if (!velnDB) throw new Error('[veln] dbPlugin not installed — call app.plugin(dbPlugin(...)) before fetch()')\n // Read the per-request QueryLog injected by fetch() via ctx._queryLog.\n // When N+1 detection is enabled, fetch() creates a QueryLog and attaches it\n // to the base ctx before plugins run. dbPlugin reads it here and passes it\n // to BoundVelnDB so each query increments the log's counters.\n const queryLog = (ctx as unknown as Record<string, unknown>)['_queryLog'] as\n import('../db/index').QueryLog | undefined\n return { ...ctx, db: velnDB.withCtx(ctx, ctx._requestQueue, queryLog) }\n },\n }\n}\n","import type { OnResponseHook } from './types'\nimport { createOnResponse } from './types'\n\n/**\n * CSP preset values for `contentSecurityPolicy`.\n *\n * - `'strict'` — no unsafe-inline; suitable for APIs and security-critical apps.\n * - `'relaxed'` — allows unsafe-inline scripts/styles; suitable for dashboards and SSR (default).\n * - `false` — omits the Content-Security-Policy header entirely.\n * - `string` — passed through as the raw header value.\n */\nexport type CspPreset = 'strict' | 'relaxed' | false | string\n\nexport interface SecureHeadersOptions {\n /** Strict-Transport-Security — default: 'max-age=15552000; includeSubDomains' */\n strictTransportSecurity?: string | false\n /** X-Content-Type-Options — default: 'nosniff' */\n xContentTypeOptions?: string | false\n /** X-Frame-Options — default: 'SAMEORIGIN' */\n xFrameOptions?: string | false\n /** X-XSS-Protection — default: '0' (modern recommendation: rely on CSP instead) */\n xXssProtection?: string | false\n /** Referrer-Policy — default: 'strict-origin-when-cross-origin' */\n referrerPolicy?: string | false\n /** Permissions-Policy — default: 'camera=(), microphone=(), geolocation=()' */\n permissionsPolicy?: string | false\n /**\n * Content-Security-Policy — accepts a preset or a raw header string.\n *\n * - `'relaxed'` (default) — allows unsafe-inline scripts/styles.\n * - `'strict'` — no unsafe-inline; for APIs and security-critical apps.\n * - `false` — omit header entirely.\n * - custom string — used as-is.\n */\n contentSecurityPolicy?: CspPreset\n}\n\nconst CSP_STRICT = \"default-src 'self'; script-src 'self'; style-src 'self'; img-src 'self' data:; font-src 'self'; connect-src 'self'; frame-ancestors 'none'\"\nconst CSP_RELAXED = \"default-src 'self'; script-src 'self' 'unsafe-inline'; style-src 'self' 'unsafe-inline'; img-src 'self' data: https:; font-src 'self' data: https:; connect-src 'self'\"\n\nfunction resolveCsp(value: CspPreset | undefined): string | false {\n if (value === false) return false\n if (value === 'strict') return CSP_STRICT\n if (value === 'relaxed' || value === undefined) return CSP_RELAXED\n return value // custom string\n}\n\nconst DEFAULTS: Record<Exclude<keyof SecureHeadersOptions, 'contentSecurityPolicy'>, string> = {\n strictTransportSecurity: 'max-age=15552000; includeSubDomains',\n xContentTypeOptions: 'nosniff',\n xFrameOptions: 'SAMEORIGIN',\n xXssProtection: '0',\n referrerPolicy: 'strict-origin-when-cross-origin',\n permissionsPolicy: 'camera=(), microphone=(), geolocation=()',\n}\n\nconst HEADER_NAMES: Record<Exclude<keyof SecureHeadersOptions, 'contentSecurityPolicy'>, string> = {\n strictTransportSecurity: 'Strict-Transport-Security',\n xContentTypeOptions: 'X-Content-Type-Options',\n xFrameOptions: 'X-Frame-Options',\n xXssProtection: 'X-XSS-Protection',\n referrerPolicy: 'Referrer-Policy',\n permissionsPolicy: 'Permissions-Policy',\n}\n\n/**\n * secureHeadersPlugin — adds security response headers to every response.\n *\n * Returns an OnResponseHook — pass it to app.onResponse():\n * app.onResponse(secureHeadersPlugin())\n * app.onResponse(secureHeadersPlugin({ xFrameOptions: 'DENY', contentSecurityPolicy: 'strict' }))\n *\n * Each option defaults to a secure value. Pass `false` to omit that header entirely.\n * Pass a custom string to override the default value.\n * `contentSecurityPolicy` also accepts `'strict'` (no unsafe-inline) or `'relaxed'` (default).\n *\n * Header resolution runs once at call time — zero overhead per request.\n */\nexport function secureHeadersPlugin(options: SecureHeadersOptions = {}): OnResponseHook {\n // Resolve final header list at plugin-creation time — not per request\n const resolved: Array<[string, string]> = []\n\n // Non-CSP headers\n for (const key of Object.keys(DEFAULTS) as Array<Exclude<keyof SecureHeadersOptions, 'contentSecurityPolicy'>>) {\n const val = key in options ? options[key] : DEFAULTS[key]\n if (val !== false && val !== undefined) {\n resolved.push([HEADER_NAMES[key], val as string])\n }\n }\n\n // CSP — preset-aware resolution\n const cspVal = resolveCsp(options.contentSecurityPolicy)\n if (cspVal !== false) {\n resolved.push(['Content-Security-Policy', cspVal])\n }\n\n return createOnResponse((_ctx, res) => {\n const headers = new Headers(res.headers)\n for (const [name, value] of resolved) {\n // Don't overwrite headers already set by the route handler —\n // allows per-route CSP overrides (e.g. scalarPlugin loosens CSP for /docs)\n if (!headers.has(name)) {\n headers.set(name, value)\n }\n }\n return new Response(res.body, {\n status: res.status,\n statusText: res.statusText,\n headers,\n })\n })\n}\n","import type { BaseCtx, OnRequestHook } from './types'\nimport { createOnRequest } from './types'\n\n// ── Store Interface ────────────────────────────────────────────────────────────\n\nexport interface RateLimitStore {\n /**\n * Increment the counter for `key` within the given window.\n * Returns the new count and the timestamp (ms) when the window resets.\n * If the key is new or expired, the window starts fresh from now.\n */\n increment(key: string, windowMs: number): Promise<{ count: number; resetAt: number }>\n /** Reset the counter for `key` immediately. */\n reset(key: string): Promise<void>\n}\n\n// ── In-Memory Store ────────────────────────────────────────────────────────────\n\ninterface Entry {\n count: number\n resetAt: number\n}\n\nexport class InMemoryStore implements RateLimitStore {\n private readonly _map = new Map<string, Entry>()\n\n // Probabilistic sweep: 1-in-N chance on every increment() call.\n // Amortizes cleanup cost across all requests — no manual calls, no Interval,\n // no process-keep-alive issues. At 1000 req/s with N=100, ~10 sweeps/s.\n private readonly _sweepEvery: number\n\n // Hard cap on map size — prevents memory exhaustion under unique-IP DoS attacks.\n // When the cap is reached, the oldest 20% of entries are evicted before inserting\n // a new key. Only new-key inserts check the cap; increments on existing keys are free.\n private readonly _maxEntries: number\n\n constructor(sweepEvery = 100, maxEntries = 100_000) {\n this._sweepEvery = sweepEvery\n this._maxEntries = maxEntries\n }\n\n async increment(key: string, windowMs: number): Promise<{ count: number; resetAt: number }> {\n const now = Date.now()\n\n // Probabilistic sweep — runs on ~1/sweepEvery calls\n if (Math.random() * this._sweepEvery < 1) {\n this._sweep(now)\n }\n\n const existing = this._map.get(key)\n\n if (existing && now < existing.resetAt) {\n existing.count += 1\n return { count: existing.count, resetAt: existing.resetAt }\n }\n\n // New window — enforce max-entries cap before inserting\n if (this._map.size >= this._maxEntries) {\n this._evictOldest(Math.max(1, Math.floor(this._maxEntries * 0.2)))\n }\n\n const entry: Entry = { count: 1, resetAt: now + windowMs }\n this._map.set(key, entry)\n return { count: 1, resetAt: entry.resetAt }\n }\n\n async reset(key: string): Promise<void> {\n this._map.delete(key)\n }\n\n /** Evict all expired entries. Called automatically on a probabilistic basis\n * during increment(). Can also be called manually for eager cleanup. */\n cleanup(): void {\n this._sweep(Date.now())\n }\n\n private _sweep(now: number): void {\n for (const [key, entry] of this._map) {\n if (now >= entry.resetAt) this._map.delete(key)\n }\n }\n\n // Evict the `count` entries with the smallest resetAt (oldest windows).\n private _evictOldest(count: number): void {\n const sorted = [...this._map.entries()].sort((a, b) => a[1].resetAt - b[1].resetAt)\n for (let i = 0; i < count && i < sorted.length; i++) {\n this._map.delete(sorted[i]![0])\n }\n }\n}\n\n// ── Options ────────────────────────────────────────────────────────────────────\n\nexport interface RateLimitOptions {\n /** Maximum number of requests allowed per window. */\n max: number\n /** Window duration in milliseconds. */\n windowMs: number\n /** Store implementation. Defaults to InMemoryStore. */\n store?: RateLimitStore\n /**\n * Extracts the rate-limit key from a request context.\n * When not specified, uses the default resolver which respects `trustProxy`.\n */\n keyResolver?: (ctx: BaseCtx) => string\n /** Response message when limit is exceeded. Defaults to 'Too many requests'. */\n message?: string\n /**\n * When true, the default keyResolver trusts the X-Forwarded-For header as the\n * real client IP. Only enable this if you are behind a trusted reverse proxy.\n * Default: false\n *\n * Without trustProxy, the default resolver uses x-real-ip or 'unknown'.\n *\n * trustProxy can also be an object for advanced configuration:\n * { strict: true } — returns 400 when the expected proxy header is missing,\n * instead of falling back to 'unknown'. Use this in security-critical deployments\n * where a missing header indicates a misconfigured proxy or direct client access.\n */\n trustProxy?: boolean | { strict: boolean }\n}\n\n// ── Plugin ─────────────────────────────────────────────────────────────────────\n\n/**\n * rateLimitPlugin — sliding-window rate limiter.\n *\n * Returns an OnRequestHook — pass it to app.onRequest() or module.onRequest():\n * app.onRequest(rateLimitPlugin({ max: 100, windowMs: 60_000 }))\n *\n * When the limit is exceeded, returns a 429 response with:\n * - Retry-After: seconds until the window resets\n * - X-RateLimit-Limit: max\n * - X-RateLimit-Remaining: 0\n * - X-RateLimit-Reset: unix timestamp (seconds)\n *\n * Under the limit, the hook returns void — request continues normally.\n */\n// ── Security analysis: X-Forwarded-For header handling ───────────────────────\n//\n// VULNERABILITY (if using first entry): A client can spoof X-Forwarded-For by\n// sending \"FAKE_IP, real_proxy_ip\". If the rate limiter reads the FIRST entry,\n// the attacker controls their own bucket key and bypasses rate limiting entirely.\n//\n// CORRECT behavior: read the LAST entry — set by the outermost trusted proxy,\n// which the client cannot control. The client can prepend values to the list\n// but cannot forge the final entry added by the proxy.\n//\n// Example: client sends X-Forwarded-For: 10.0.0.1\n// proxy appends X-Forwarded-For: 10.0.0.1, 203.0.113.5\n// → correct client IP = last entry = 203.0.113.5\n//\n// MISSING HEADER behavior (trustProxy: true, no X-Forwarded-For):\n// - Default (option A): falls back to 'unknown' + emits a one-time warning.\n// All requests without the header share the same bucket — DoS vector if\n// the proxy is misconfigured. The warning helps operators detect this.\n// - Strict (option B): returns 400 Bad Request immediately. Use this in\n// security-critical deployments where a missing header means a broken proxy.\n\nexport function rateLimitPlugin(options: RateLimitOptions): OnRequestHook {\n const { max, windowMs, message = 'Too many requests' } = options\n const store: RateLimitStore = options.store ?? new InMemoryStore()\n\n const trustProxy = options.trustProxy\n const isStrict = typeof trustProxy === 'object' && trustProxy.strict === true\n const doTrust = trustProxy === true || isStrict\n\n // Pitfall warning: no keyResolver + no trustProxy → default falls back to\n // x-real-ip and then 'unknown'. Behind a proxy that doesn't set x-real-ip,\n // every request maps to the same key — the entire app shares one rate-limit\n // bucket. This is almost certainly unintentional.\n if (!options.keyResolver && !trustProxy) {\n console.warn(\n '[veln:rateLimit] Warning: no keyResolver or trustProxy provided. ' +\n \"If your app runs behind a reverse proxy, the default key resolver may fall back to 'unknown', \" +\n 'causing all clients to share a single rate-limit bucket. ' +\n 'Set trustProxy: true (if behind a trusted proxy) or provide a custom keyResolver.',\n )\n }\n\n // Track whether the missing-header warning has been emitted — once per plugin instance.\n let _missingHeaderWarned = false\n\n const defaultKeyResolver = (ctx: BaseCtx): string | Response => {\n if (doTrust) {\n const forwardedFor = ctx.req.headers.get('x-forwarded-for')\n if (forwardedFor) {\n // Use the LAST entry — set by the outermost trusted proxy, not forgeable by client.\n // Client can prepend fake IPs but cannot control the final proxy-appended entry.\n const parts = forwardedFor.split(',')\n const lastIp = parts[parts.length - 1]?.trim()\n if (lastIp) return lastIp\n }\n\n // Header missing — proxy may be misconfigured\n if (isStrict) {\n // Strict mode: reject the request — a missing header is a hard error\n return new Response(\n JSON.stringify({ error: 'Bad Request', code: 'MISSING_PROXY_HEADER', message: 'X-Forwarded-For header is required' }),\n { status: 400, headers: { 'Content-Type': 'application/json' } },\n )\n }\n\n // Option A: warn once, fall back to 'unknown'\n if (!_missingHeaderWarned) {\n _missingHeaderWarned = true\n console.warn(\n '[veln:rateLimit] trustProxy is enabled but no X-Forwarded-For header found. ' +\n 'All requests may be bucketed under the same IP. ' +\n 'Ensure your reverse proxy sets X-Forwarded-For correctly.',\n )\n }\n }\n\n // Without trustProxy, use x-real-ip or fall back to 'unknown'\n return ctx.req.headers.get('x-real-ip') ?? 'unknown'\n }\n\n const keyResolver = options.keyResolver\n ? (ctx: BaseCtx): string | Response => options.keyResolver!(ctx)\n : defaultKeyResolver\n\n return createOnRequest(async (ctx) => {\n const keyOrResponse = keyResolver(ctx)\n\n // Strict mode returns a Response directly when the proxy header is missing\n if (keyOrResponse instanceof Response) return keyOrResponse\n\n const key = keyOrResponse\n const { count, resetAt } = await store.increment(key, windowMs)\n\n const remaining = Math.max(0, max - count)\n const resetSec = Math.ceil(resetAt / 1000)\n\n if (count > max) {\n const retryAfter = Math.ceil((resetAt - Date.now()) / 1000)\n return new Response(\n JSON.stringify({ error: 'Too Many Requests', code: 'RATE_LIMIT_EXCEEDED', message }),\n {\n status: 429,\n headers: {\n 'Content-Type': 'application/json',\n 'Retry-After': String(retryAfter),\n 'X-RateLimit-Limit': String(max),\n 'X-RateLimit-Remaining': '0',\n 'X-RateLimit-Reset': String(resetSec),\n },\n },\n )\n }\n\n // Under limit — attach informational headers via response hook is not possible\n // from onRequest. We return void and let the request continue.\n // RateLimit info headers (Limit/Remaining/Reset) are intentionally omitted on\n // the success path to avoid leaking rate-limit state to clients by default.\n // Advanced users can add them via a custom onResponse hook if needed.\n void remaining\n void resetSec\n })\n}\n","import type { BaseCtx, OnRequestHook, OnResponseHook } from './types'\nimport { createOnRequest, createOnResponse } from './types'\n\n// ── Constants ──────────────────────────────────────────────────────────────────\n\n// Methods that mutate state — CSRF validation is enforced for these.\nconst STATE_CHANGING_METHODS = new Set(['POST', 'PUT', 'PATCH', 'DELETE'])\n\n// ── Constant-time string comparison ───────────────────────────────────────────\n\n/**\n * Constant-time string comparison to prevent timing attacks.\n * Returns false immediately on length mismatch (length is not secret).\n * XORs all character codes and accumulates into a single result so the\n * comparison time is proportional to the string length, not the first mismatch.\n */\nexport function timingSafeEqual(a: string, b: string): boolean {\n if (a.length !== b.length) return false\n let result = 0\n for (let i = 0; i < a.length; i++) {\n result |= a.charCodeAt(i) ^ b.charCodeAt(i)\n }\n return result === 0\n}\n\n// ── Token generation ───────────────────────────────────────────────────────────\n\nfunction generateToken(): string {\n // crypto is available globally in Bun, Node 19+, and all modern browsers.\n const bytes = new Uint8Array(32)\n crypto.getRandomValues(bytes)\n return Array.from(bytes, (b) => b.toString(16).padStart(2, '0')).join('')\n}\n\n// ── Options ────────────────────────────────────────────────────────────────────\n\nexport interface CsrfOptions {\n /** Cookie name that holds the CSRF token. Default: 'csrf_token' */\n cookieName?: string\n /** Request header that must carry the token on state-changing requests. Default: 'x-csrf-token' */\n headerName?: string\n /** Cookie Max-Age in seconds. Default: 86400 (24h) */\n maxAge?: number\n /** Restrict cookie to HTTPS. Default: true (set false for local development) */\n secure?: boolean\n}\n\n// ── Plugin return type ─────────────────────────────────────────────────────────\n\nexport interface CsrfPlugin {\n /**\n * Register on app.onRequest() or module.onRequest().\n * Validates the CSRF token on state-changing methods (POST/PUT/PATCH/DELETE).\n * Returns a 403 response on mismatch — short-circuits the request lifecycle.\n */\n onRequest: OnRequestHook\n /**\n * Register on app.onResponse() or module.onResponse().\n * Sets a new CSRF token cookie on responses to safe methods (GET/HEAD/OPTIONS)\n * when no valid token cookie exists yet.\n */\n onResponse: OnResponseHook\n}\n\n/**\n * csrfPlugin — Double-Submit Cookie pattern. Stateless, no store required.\n *\n * Usage:\n * const csrf = csrfPlugin()\n * app.onRequest(csrf.onRequest)\n * app.onResponse(csrf.onResponse)\n *\n * How it works:\n * 1. On GET/HEAD/OPTIONS — onResponse sets a readable cookie (httpOnly: false)\n * so the client-side JS can read the token.\n * 2. On POST/PUT/PATCH/DELETE — onRequest reads the cookie value and compares\n * it to the x-csrf-token request header. Mismatch or missing → 403.\n *\n * The Double-Submit Cookie pattern is stateless: the server never stores tokens.\n * Security relies on the same-origin policy: a cross-origin attacker can read\n * neither the cookie nor the custom header value.\n */\nexport function csrfPlugin(options: CsrfOptions = {}): CsrfPlugin {\n const cookieName = options.cookieName ?? 'csrf_token'\n const headerName = options.headerName ?? 'x-csrf-token'\n const maxAge = options.maxAge ?? 86_400\n const secure = options.secure ?? true\n\n const onRequest: OnRequestHook = createOnRequest((ctx: BaseCtx) => {\n const method = ctx.req.method.toUpperCase()\n if (!STATE_CHANGING_METHODS.has(method)) return\n\n const cookieToken = ctx.cookie.get(cookieName)\n const headerToken = ctx.req.headers.get(headerName)\n\n if (!cookieToken || !headerToken || !timingSafeEqual(cookieToken, headerToken)) {\n return new Response(\n JSON.stringify({ error: 'Forbidden', code: 'CSRF_INVALID', message: 'CSRF token mismatch' }),\n {\n status: 403,\n headers: { 'Content-Type': 'application/json' },\n },\n )\n }\n })\n\n const onResponse: OnResponseHook = createOnResponse((ctx: BaseCtx, res: Response) => {\n const method = ctx.req.method.toUpperCase()\n // Only issue tokens on safe methods — no point issuing a fresh token\n // on a request that was just blocked by onRequest.\n if (STATE_CHANGING_METHODS.has(method)) return\n\n // Don't overwrite a valid existing token — avoids invalidating in-flight requests.\n const existing = ctx.cookie.get(cookieName)\n if (existing) return\n\n // Set a new token — httpOnly: false so client-side JS can read it.\n ctx.cookie.set(cookieName, generateToken(), {\n httpOnly: false,\n sameSite: 'Strict',\n maxAge,\n secure,\n path: '/',\n })\n\n // ctx.cookie._pending() is flushed into the response by the framework\n // after onResponse hooks complete — no manual header manipulation needed.\n void res\n })\n\n return { onRequest, onResponse }\n}\n","import type { VelnModule } from './module'\nimport type { Route, BaseCtx } from './types'\nimport { generateOpenApiSpec } from '../openapi/generator'\n\n// ── Options ────────────────────────────────────────────────────────────────────\n\nexport interface ScalarOptions {\n /** Mount path for the Scalar UI. Default: '/scalar' */\n path?: string\n /** API title shown in the Scalar UI. Default: 'Veln API' */\n title?: string\n /** API version shown in the OpenAPI spec. Default: '1.0.0' */\n version?: string\n /** Optional API description shown in the OpenAPI spec info block. Markdown supported. */\n description?: string\n /** Scalar UI theme. Default: 'purple' */\n theme?: string\n /**\n * Cache the generated OpenAPI spec after the first request.\n * Default: false — spec is regenerated on every request (safe for development).\n * Set to true in production to avoid repeated traversal of app.routes.\n */\n cache?: boolean\n}\n\n// ── App reference — minimal shape needed at runtime ───────────────────────────\n\ninterface AppRef {\n routes: Route<unknown>[]\n}\n\n// ── HTML template ──────────────────────────────────────────────────────────────\n\nfunction renderHtml(specJson: string, title: string, theme: string, jsonUrl: string): string {\n return `<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n <meta charset=\"UTF-8\" />\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\" />\n <title>${title}</title>\n</head>\n<body>\n <script id=\"api-reference\" type=\"application/json\">${specJson}</script>\n <script>\n window.__SCALAR_CONFIG__ = { theme: '${theme}' };\n </script>\n <script src=\"https://cdn.jsdelivr.net/npm/@scalar/api-reference\"></script>\n</body>\n</html>`\n}\n\n// ── Plugin factory ─────────────────────────────────────────────────────────────\n\n/**\n * scalarPlugin — mounts a Scalar API reference UI and an OpenAPI JSON endpoint.\n *\n * Usage:\n * app.register(scalarPlugin(app))\n * app.register(scalarPlugin(app, { path: '/docs', title: 'My API', theme: 'blue' }))\n *\n * Registers two routes (both hidden from the OpenAPI spec itself):\n * GET {path} → Scalar UI (HTML, CDN-loaded)\n * GET {path}/openapi.json → Raw OpenAPI 3.1 JSON\n *\n * The app reference is captured by closure so the spec always reflects\n * the current route list at request time — including late-registered modules.\n */\nexport function scalarPlugin(app: AppRef, options: ScalarOptions = {}): VelnModule {\n const mountPath = options.path ?? '/scalar'\n const title = options.title ?? 'Veln API'\n const version = options.version ?? '1.0.0'\n const description = options.description ?? undefined\n const theme = options.theme ?? 'purple'\n const useCache = options.cache ?? false\n const jsonPath = `${mountPath}/openapi.json`\n\n // Cache slot — null until first request when cache: true\n let cachedSpec: ReturnType<typeof generateOpenApiSpec> | null = null\n\n function getSpec(): ReturnType<typeof generateOpenApiSpec> {\n if (useCache) {\n if (!cachedSpec) cachedSpec = generateOpenApiSpec(app.routes, { title, version, description })\n return cachedSpec\n }\n return generateOpenApiSpec(app.routes, { title, version, description })\n }\n\n const jsonRoute: Route<BaseCtx> = {\n method: 'GET',\n path: jsonPath,\n handler: {\n handler: (_ctx) => Response.json(getSpec()),\n },\n guards: [],\n visibility: 'hidden',\n }\n\n const uiRoute: Route<BaseCtx> = {\n method: 'GET',\n path: mountPath,\n handler: {\n handler: (ctx) => {\n const spec = getSpec()\n const specJson = JSON.stringify(spec)\n const html = renderHtml(specJson, title, theme, jsonPath)\n const res = ctx.html(html)\n // Scalar UI requires inline scripts, cdn.jsdelivr.net, proxy.scalar.com,\n // and Google Fonts — override the strict CSP set by secureHeadersPlugin.\n res.headers.set(\n 'Content-Security-Policy',\n [\n \"default-src 'self'\",\n \"script-src 'unsafe-inline' https://cdn.jsdelivr.net\",\n \"style-src 'unsafe-inline' https://cdn.jsdelivr.net https://fonts.googleapis.com\",\n \"font-src *\", // Scalar bundles / loads fonts from varying CDN origins\n \"connect-src 'self' https://proxy.scalar.com https://cdn.jsdelivr.net\",\n \"img-src 'self' data: blob: https://cdn.jsdelivr.net\",\n \"worker-src blob:\",\n ].join('; '),\n )\n return res\n },\n },\n guards: [],\n visibility: 'hidden',\n }\n\n const mod: VelnModule = {\n prefix: '',\n routes: [jsonRoute, uiRoute],\n wsRoutes: [],\n hookDeclarations: [],\n auditDeclarations: [],\n serviceDeclarations: [],\n plugins: [],\n guards: [],\n onRequestHooks: [],\n onBeforeHandleHooks: [],\n onResponseHooks: [],\n onError: undefined,\n eventHandlerDefs: [],\n cronDefs: [],\n visibility: 'hidden',\n meta: { tag: 'scalar', description: 'Scalar API Reference' },\n }\n\n return mod\n}\n","import type { OnRequestHook } from './types'\nimport { createOnRequest } from './types'\n\nexport interface BodySizeLimitOptions {\n /**\n * Maximum allowed body size in bytes.\n * Default: 1_048_576 (1 MB)\n */\n maxSize?: number\n /** Response message when limit is exceeded. Default: 'Payload too large' */\n message?: string\n}\n\n/**\n * bodySizeLimitPlugin — rejects requests whose Content-Length exceeds maxSize.\n *\n * Returns an OnRequestHook — pass it to app.onRequest():\n * app.onRequest(bodySizeLimitPlugin()) // 1MB default\n * app.onRequest(bodySizeLimitPlugin({ maxSize: 512_000 })) // 512KB\n *\n * Checks the Content-Length header only — does not buffer or read the body.\n * Requests without Content-Length are passed through (streaming / chunked).\n * Returns 413 Payload Too Large on violation.\n *\n * @remarks\n * This plugin enforces limits based on the Content-Length header only.\n * Chunked transfer-encoding bypasses this check entirely.\n * For production deployments, configure body size limits at the reverse proxy level:\n * nginx: `client_max_body_size`, Caddy: `request_body { max_size }`.\n */\nexport function bodySizeLimitPlugin(options: BodySizeLimitOptions = {}): OnRequestHook {\n const maxSize = options.maxSize ?? 1_048_576\n const message = options.message ?? 'Payload too large'\n\n return createOnRequest((ctx) => {\n const contentLength = ctx.req.headers.get('content-length')\n if (contentLength === null) return // no length declared — pass through\n\n const bytes = parseInt(contentLength, 10)\n if (isNaN(bytes)) return // unparseable — pass through, let handler deal with it\n\n if (bytes > maxSize) {\n return new Response(\n JSON.stringify({ error: 'Payload Too Large', code: 'PAYLOAD_TOO_LARGE', message }),\n {\n status: 413,\n headers: { 'Content-Type': 'application/json' },\n },\n )\n }\n })\n}\n","import type { OnRequestHook, OnResponseHook } from './types'\nimport { createOnRequest, createOnResponse } from './types'\n\n// ── Options ─────────────────────────────────────────────────────────────────\n\nexport interface CorsOptions {\n /**\n * Allowed origins. Can be:\n * - `'*'` → any origin (not usable with credentials)\n * - `string` → single allowed origin\n * - `string[]` → list of allowed origins (matched against request Origin header)\n * - `(origin: string) => boolean` → custom predicate\n *\n * Default: `'*'`\n */\n origin?: '*' | string | string[] | ((origin: string) => boolean)\n\n /**\n * HTTP methods allowed in CORS requests.\n * Default: `['GET', 'POST', 'PUT', 'PATCH', 'DELETE', 'OPTIONS']`\n */\n methods?: string[]\n\n /**\n * Request headers the client is allowed to send.\n * Default: `['Content-Type', 'Authorization', 'x-csrf-token']`\n */\n allowHeaders?: string[]\n\n /**\n * Response headers that the browser may expose to the client-side script.\n * Default: `[]` (none exposed beyond the CORS-safelisted headers)\n */\n exposeHeaders?: string[]\n\n /**\n * Whether cross-origin requests may include credentials (cookies, auth headers).\n * When true, `origin` must not be `'*'`.\n * Default: `false`\n */\n credentials?: boolean\n\n /**\n * How long (in seconds) the preflight result may be cached.\n * Default: `86400` (24h)\n */\n maxAge?: number\n}\n\n// ── Plugin return type ───────────────────────────────────────────────────────\n\nexport interface CorsPlugin {\n /**\n * Register on `app.onRequest()`.\n * Handles OPTIONS preflight requests — returns a 204 with CORS headers directly,\n * short-circuiting the pipeline (no route handler runs for OPTIONS).\n */\n onRequest: OnRequestHook\n /**\n * Register on `app.onResponse()`.\n * Appends CORS headers to every response.\n */\n onResponse: OnResponseHook\n}\n\n// ── Helpers ──────────────────────────────────────────────────────────────────\n\nfunction resolveOrigin(\n allowedOrigin: CorsOptions['origin'],\n requestOrigin: string | null,\n): string | null {\n if (!requestOrigin) return null\n\n if (allowedOrigin === '*') return '*'\n if (typeof allowedOrigin === 'string') {\n return allowedOrigin === requestOrigin ? requestOrigin : null\n }\n if (Array.isArray(allowedOrigin)) {\n return allowedOrigin.includes(requestOrigin) ? requestOrigin : null\n }\n if (typeof allowedOrigin === 'function') {\n return allowedOrigin(requestOrigin) ? requestOrigin : null\n }\n return null\n}\n\n// ── Plugin factory ───────────────────────────────────────────────────────────\n\n/**\n * corsPlugin — adds CORS headers to responses and handles preflight OPTIONS requests.\n *\n * Usage:\n * const cors = corsPlugin({ origin: 'https://app.example.com', credentials: true })\n * app.onRequest(cors.onRequest)\n * app.onResponse(cors.onResponse)\n *\n * Preflight (OPTIONS) requests are short-circuited with a 204 — no route handler\n * runs. All other requests receive CORS headers in onResponse.\n */\nexport function corsPlugin(options: CorsOptions = {}): CorsPlugin {\n const allowedOrigin = options.origin ?? '*'\n\n // Validate: wildcard origin cannot be combined with credentials\n if ((allowedOrigin === '*') && options.credentials === true) {\n throw new Error(\n \"CORS: origin: '*' cannot be combined with credentials: true. Use a specific origin instead.\",\n )\n }\n const methods = options.methods ?? ['GET', 'POST', 'PUT', 'PATCH', 'DELETE', 'OPTIONS']\n const allowHeaders = options.allowHeaders ?? ['Content-Type', 'Authorization', 'x-csrf-token']\n const exposeHeaders = options.exposeHeaders ?? []\n const credentials = options.credentials ?? false\n const maxAge = options.maxAge ?? 86_400\n\n const methodsStr = methods.join(', ')\n const allowHeadersStr = allowHeaders.join(', ')\n const exposeHeadersStr = exposeHeaders.join(', ')\n const maxAgeStr = String(maxAge)\n\n function buildCorsHeaders(requestOrigin: string | null): Headers {\n const headers = new Headers()\n const resolved = resolveOrigin(allowedOrigin, requestOrigin)\n if (resolved) {\n headers.set('Access-Control-Allow-Origin', resolved)\n // Vary: Origin when not wildcard — required for correct cache behaviour\n if (resolved !== '*') {\n headers.set('Vary', 'Origin')\n }\n }\n if (credentials) {\n headers.set('Access-Control-Allow-Credentials', 'true')\n }\n if (exposeHeadersStr) {\n headers.set('Access-Control-Expose-Headers', exposeHeadersStr)\n }\n return headers\n }\n\n const onRequest: OnRequestHook = createOnRequest((ctx) => {\n if (ctx.req.method.toUpperCase() !== 'OPTIONS') return\n\n const requestOrigin = ctx.req.headers.get('Origin')\n const corsHeaders = buildCorsHeaders(requestOrigin)\n\n // Add preflight-specific headers\n corsHeaders.set('Access-Control-Allow-Methods', methodsStr)\n corsHeaders.set('Access-Control-Allow-Headers', allowHeadersStr)\n corsHeaders.set('Access-Control-Max-Age', maxAgeStr)\n\n return new Response(null, { status: 204, headers: corsHeaders })\n })\n\n const onResponse: OnResponseHook = createOnResponse((ctx, res) => {\n const requestOrigin = ctx.req.headers.get('Origin')\n const corsHeaders = buildCorsHeaders(requestOrigin)\n\n // Don't mutate the original response — rebuild with merged headers\n const merged = new Headers(res.headers)\n for (const [key, value] of corsHeaders) {\n merged.set(key, value)\n }\n\n return new Response(res.body, {\n status: res.status,\n headers: merged,\n })\n })\n\n return { onRequest, onResponse }\n}\n","import type { BaseCtx, OnRequestHook, OnResponseHook } from './types'\nimport { createOnRequest, createOnResponse } from './types'\n\n// ── Options ─────────────────────────────────────────────────────────────────\n\nexport interface RequestIdOptions {\n /**\n * Name of the incoming request header to read an existing ID from.\n * If present and valid, the existing ID is reused (useful for distributed tracing).\n * Default: `'x-request-id'`\n */\n incomingHeader?: string\n\n /**\n * Name of the response header to echo the request ID back to the client.\n * Default: `'x-request-id'`\n */\n responseHeader?: string\n\n /**\n * Custom ID generator. Must return a non-empty string.\n * Default: 16 random hex bytes (128 bits, UUID-compatible entropy)\n */\n generator?: () => string\n}\n\n// ── Plugin return type ───────────────────────────────────────────────────────\n\n/** Context extension added by requestIdPlugin. Available after onRequest. */\nexport interface RequestIdCtx {\n /** Unique ID for this request. Set before any route handler runs. */\n requestId: string\n}\n\nexport interface RequestIdPlugin {\n /**\n * Register on `app.onRequest()`.\n * Assigns `ctx.requestId` — available in all subsequent lifecycle phases.\n */\n onRequest: OnRequestHook<BaseCtx & RequestIdCtx>\n /**\n * Register on `app.onResponse()`.\n * Echoes the request ID back in the response header.\n */\n onResponse: OnResponseHook<BaseCtx & RequestIdCtx>\n}\n\n// ── Helpers ──────────────────────────────────────────────────────────────────\n\nfunction defaultGenerator(): string {\n const bytes = new Uint8Array(16)\n crypto.getRandomValues(bytes)\n return Array.from(bytes, (b) => b.toString(16).padStart(2, '0')).join('')\n}\n\n/** Returns true if the value is a non-empty string containing only safe characters. */\nfunction isSafeId(value: string): boolean {\n return value.length > 0 && value.length <= 128 && /^[\\w\\-]+$/.test(value)\n}\n\n// ── Plugin factory ───────────────────────────────────────────────────────────\n\n/**\n * requestIdPlugin — assigns a unique ID to every request and echoes it back.\n *\n * Usage:\n * const rid = requestIdPlugin()\n * app.onRequest(rid.onRequest)\n * app.onResponse(rid.onResponse)\n *\n * After registration, `ctx.requestId` is available in all handlers, guards,\n * and lifecycle hooks. The ID is echoed back in the `x-request-id` response header.\n *\n * Reuses an existing `x-request-id` header if it passes a safe-characters check,\n * enabling distributed tracing across services.\n */\nexport function requestIdPlugin(options: RequestIdOptions = {}): RequestIdPlugin {\n const incomingHeader = options.incomingHeader ?? 'x-request-id'\n const responseHeader = options.responseHeader ?? 'x-request-id'\n const generate = options.generator ?? defaultGenerator\n\n const onRequest: OnRequestHook<BaseCtx & RequestIdCtx> = createOnRequest<RequestIdCtx>((ctx) => {\n const incoming = ctx.req.headers.get(incomingHeader)\n const id = (incoming && isSafeId(incoming)) ? incoming : generate()\n ctx.requestId = id\n })\n\n const onResponse: OnResponseHook<BaseCtx & RequestIdCtx> = createOnResponse<RequestIdCtx>((ctx, res) => {\n const headers = new Headers(res.headers)\n headers.set(responseHeader, ctx.requestId)\n return new Response(res.body, { status: res.status, headers })\n })\n\n return { onRequest, onResponse }\n}\n","import type { OnResponseHook } from './types'\nimport { createOnResponse } from './types'\n\n// ── Options ─────────────────────────────────────────────────────────────────\n\nexport interface CompressionOptions {\n /**\n * Compression algorithms to offer, in preference order.\n * Default: `['gzip', 'deflate']`\n *\n * Bun 1.x provides `Bun.gzipSync` and `Bun.deflateSync` natively.\n */\n encodings?: Array<'gzip' | 'deflate'>\n\n /**\n * Minimum response body size in bytes before compression is applied.\n * Responses smaller than this are sent uncompressed.\n * Default: `1024` (1 KB)\n */\n threshold?: number\n\n /**\n * Maximum response body size in bytes to attempt compression.\n * Responses larger than this are passed through uncompressed to avoid\n * excessive memory usage when buffering very large responses.\n * Default: `10485760` (10 MB)\n */\n maxSize?: number\n}\n\n// ── Helpers ──────────────────────────────────────────────────────────────────\n\n/** Content-types that benefit from compression. Binary formats are excluded. */\nconst COMPRESSIBLE = /^(text\\/|application\\/(json|xml|javascript|x-www-form-urlencoded|graphql|ld\\+json|geo\\+json|atom\\+xml|rss\\+xml|manifest\\+json))/i\n\nfunction isCompressible(contentType: string | null): boolean {\n if (!contentType) return false\n return COMPRESSIBLE.test(contentType.split(';')[0]!.trim())\n}\n\n/** Pick the best encoding the client accepts from our offered list. */\nfunction negotiateEncoding(\n acceptEncoding: string | null,\n offered: Array<'gzip' | 'deflate'>,\n): 'gzip' | 'deflate' | null {\n if (!acceptEncoding) return null\n for (const enc of offered) {\n if (acceptEncoding.includes(enc)) return enc\n }\n return null\n}\n\n// Bun-native compression — typed interface to avoid `any`\ninterface BunCompress {\n gzipSync(data: Uint8Array): Uint8Array\n deflateSync(data: Uint8Array): Uint8Array\n}\n\nconst bunCompress = Bun as unknown as BunCompress\n\n// ── Plugin factory ───────────────────────────────────────────────────────────\n\n/**\n * compressionPlugin — compresses responses using Bun's native gzip/deflate.\n *\n * Usage:\n * app.onResponse(compressionPlugin())\n * app.onResponse(compressionPlugin({ encodings: ['gzip'], threshold: 512 }))\n *\n * Compression is skipped when:\n * - The client doesn't send Accept-Encoding with a supported algorithm\n * - The Content-Type is binary (images, audio, video, zip, …)\n * - The response body is below the threshold\n * - The response already has a Content-Encoding header (e.g. pre-compressed assets)\n * - The response is a 204 No Content or 304 Not Modified (no body)\n * - The response is a streaming body (Content-Type: text/event-stream)\n */\nconst DEFAULT_MAX_SIZE = 10 * 1024 * 1024 // 10 MB\n\nexport function compressionPlugin(options: CompressionOptions = {}): OnResponseHook {\n const encodings = options.encodings ?? ['gzip', 'deflate']\n const threshold = options.threshold ?? 1024\n const maxSize = options.maxSize ?? DEFAULT_MAX_SIZE\n\n return createOnResponse(async (ctx, res) => {\n // Skip: no-body statuses\n if (res.status === 204 || res.status === 304) return\n\n // Skip: already encoded\n if (res.headers.get('Content-Encoding')) return\n\n // Skip: SSE (streaming — must not buffer)\n const contentType = res.headers.get('Content-Type')\n if (contentType?.includes('text/event-stream')) return\n\n // Skip: non-compressible content type\n if (!isCompressible(contentType)) return\n\n // Negotiate encoding\n const acceptEncoding = ctx.req.headers.get('Accept-Encoding')\n const encoding = negotiateEncoding(acceptEncoding, encodings)\n if (!encoding) return\n\n // Read body — skip if below threshold or empty\n const body = await res.arrayBuffer()\n if (body.byteLength < threshold) return\n\n // Skip: above max size threshold — avoid excessive memory usage\n if (body.byteLength > maxSize) return res\n\n // Compress via Bun-native sync API\n const input = new Uint8Array(body)\n const compressed = encoding === 'gzip'\n ? bunCompress.gzipSync(input)\n : bunCompress.deflateSync(input)\n\n const headers = new Headers(res.headers)\n headers.set('Content-Encoding', encoding)\n headers.set('Content-Length', String(compressed.byteLength))\n headers.set('Vary', 'Accept-Encoding')\n\n return new Response(compressed.buffer as ArrayBuffer, { status: res.status, headers })\n })\n}\n","import type { OnRequestHook } from './types'\nimport { createOnRequest } from './types'\n\n// ── Types ─────────────────────────────────────────────────────────────────────\n\nexport interface HealthCheck {\n (): Promise<{ ok: boolean; details?: Record<string, unknown> }>\n}\n\nexport interface HealthPluginOptions {\n /** Path for the liveness endpoint. Default: '/health' */\n path?: string\n /** Path for the readiness endpoint. Default: '/ready' */\n readyPath?: string\n /** Named checks to run for the readiness endpoint. */\n checks?: Record<string, HealthCheck>\n}\n\n// ── Plugin ────────────────────────────────────────────────────────────────────\n\n/**\n * healthPlugin — adds /health and /ready endpoints for Kubernetes/load balancers.\n *\n * Usage:\n * const health = healthPlugin({ checks: { db: async () => ({ ok: true }) } })\n * app.onRequest(health.onRequest)\n *\n * GET /health → 200 { status: 'ok', uptime: number }\n * Always returns 200. Use for liveness probes (is the process alive?).\n *\n * GET /ready → 200 { status: 'ready', checks: { db: { ok: true } } }\n * → 503 { status: 'not_ready', checks: { db: { ok: false, error: '...' } } }\n * Runs all checks. Use for readiness probes (is the service ready to serve traffic?).\n *\n * The health endpoints are intercepted in the onRequest phase — before auth plugins run.\n */\nexport interface HealthPlugin {\n onRequest: OnRequestHook\n}\n\nexport function healthPlugin(options: HealthPluginOptions = {}): HealthPlugin {\n const healthPath = options.path ?? '/health'\n const readyPath = options.readyPath ?? '/ready'\n const checks = options.checks ?? {}\n\n const onRequest: OnRequestHook = createOnRequest(async (ctx) => {\n const url = new URL(ctx.req.url)\n const path = url.pathname\n const method = ctx.req.method.toUpperCase()\n\n if (method !== 'GET') return\n\n // GET /health — liveness probe\n if (path === healthPath) {\n return Response.json({ status: 'ok', uptime: process.uptime() }, { status: 200 })\n }\n\n // GET /ready — readiness probe\n if (path === readyPath) {\n const checkNames = Object.keys(checks)\n const checkResults: Record<string, { ok: boolean; details?: Record<string, unknown>; error?: string }> = {}\n let allOk = true\n\n for (const name of checkNames) {\n try {\n const result = await checks[name]!()\n checkResults[name] = { ok: result.ok, ...(result.details ? { details: result.details } : {}) }\n if (!result.ok) allOk = false\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err)\n checkResults[name] = { ok: false, error: message }\n allOk = false\n }\n }\n\n if (allOk) {\n return Response.json({ status: 'ready', checks: checkResults }, { status: 200 })\n } else {\n return Response.json({ status: 'not_ready', checks: checkResults }, { status: 503 })\n }\n }\n })\n\n return { onRequest }\n}\n","import type { ZodIssue } from 'zod'\n\nexport class VelnClientError extends Error {\n constructor(\n readonly status: number,\n readonly code: string,\n message: string,\n readonly issues?: ZodIssue[],\n ) {\n super(message)\n this.name = 'VelnClientError'\n }\n}\n","import type { RouteMap, RouteEntry } from '../app/types'\nimport type { ZodTypeAny } from 'zod'\nimport { VelnClientError } from './error'\n\n// ── Type utilities ─────────────────────────────────────────────────────────────\n\n// Response type — only if `response:` schema is defined, otherwise unknown\ntype RouteResponseType<TEntry extends RouteEntry> =\n TEntry['response'] extends ZodTypeAny ? import('zod').infer<TEntry['response']> : unknown\n\n// ClientResult — discriminated union so callers must check ok before accessing data\nexport type ClientResult<T> =\n | { ok: true; data: T; status: number }\n | { ok: false; error: VelnClientError; status: number; code: string; message: string }\n\n// ── Path → client key conversion ──────────────────────────────────────────────\n\nexport function pathToClientKey(prefix: string): string {\n // '/api/users' → 'apiUsers', '/blog-posts' → 'blogPosts', '/v1/orders' → 'v1Orders'\n return prefix\n .replace(/^\\//, '') // strip leading slash\n .split(/[\\/\\-]/) // split on / and -\n .filter(Boolean)\n .map((part, i) => i === 0 ? part : part.charAt(0).toUpperCase() + part.slice(1))\n .join('')\n}\n\n// ── Path → method name conversion ─────────────────────────────────────────────\n\n// Converts a (HTTP method, path-suffix) pair into a camelCase method name.\n// 'GET', '/' → 'index'\n// 'GET', '/:id' → 'show'\n// 'POST', '/' → 'store'\n// 'PATCH', '/:id' → 'update'\n// 'DELETE', '/:id' → 'destroy'\n// 'GET', '/export' → 'getExport'\n// 'POST', '/:id/publish' → 'postByIdPublish'\nfunction pathToMethodName(method: string, suffix: string): string {\n const m = method.toLowerCase()\n // Normalise suffix — strip leading slash\n const s = suffix.replace(/^\\//, '')\n\n // CRUD shorthands\n if (s === '' || s === '/') {\n if (m === 'get') return 'index'\n if (m === 'post') return 'store'\n }\n if (/^:([^/]+)$/.test(s)) {\n if (m === 'get') return 'show'\n if (m === 'patch') return 'update'\n if (m === 'delete') return 'destroy'\n }\n\n // Custom routes — method + path-segments as camelCase\n const segments = s.split('/').filter(Boolean).map((seg) =>\n seg.startsWith(':') ? 'By' + seg.slice(1).charAt(0).toUpperCase() + seg.slice(2) : seg,\n )\n const body = segments\n .map((seg, i) => i === 0 ? seg : seg.charAt(0).toUpperCase() + seg.slice(1))\n .join('')\n return m + body.charAt(0).toUpperCase() + body.slice(1)\n}\n\n// ── Type-level per-module client ───────────────────────────────────────────────\n//\n// Approach: per-module types keep each resolution step small.\n// Each `ModuleRoutes` is a sub-map of routes that share a prefix —\n// TS only traverses the slice it needs, not all routes at once.\n\n// Extract routes whose keys start with a given prefix\ntype ExtractModuleRoutes<TRoutes extends RouteMap, TPrefix extends string> = {\n [K in Extract<keyof TRoutes, `${string} ${TPrefix}${string}`>]: TRoutes[K]\n}\n\n// Suffix after the prefix — e.g. 'GET /users/:id' with prefix '/users' → '/:id'\ntype SuffixAfterPrefix<K extends string, TPrefix extends string> =\n K extends `${infer _Method} ${TPrefix}${infer Suffix}` ? Suffix : never\n\n// Infer the method name for a given route key\ntype MethodOf<K extends string> =\n K extends `GET ${string}` ? 'get' :\n K extends `POST ${string}` ? 'post' :\n K extends `PATCH ${string}` ? 'patch' :\n K extends `DELETE ${string}` ? 'delete' :\n K extends `PUT ${string}` ? 'put' :\n never\n\n// Build one method entry for a route key\n// Returns args as tuple — params before body, then optional request options\n// Note: use [never] extends [TRoutes[K]['body']] to avoid distributing over union,\n// and exclude `never` (the no-body default) from triggering the body branch.\ntype HasBody<TEntry extends RouteEntry> =\n [TEntry['body']] extends [never] ? false :\n [TEntry['body']] extends [ZodTypeAny] ? true : false\n\ntype MethodEntry<TRoutes extends RouteMap, K extends keyof TRoutes & string, TPrefix extends string> =\n HasBody<TRoutes[K] & RouteEntry> extends true\n ? (\n ...args: [\n body: import('zod').infer<TRoutes[K]['body'] & ZodTypeAny>,\n options?: { headers?: Record<string, string>; query?: Record<string, string> },\n ]\n ) => Promise<ClientResult<RouteResponseType<TRoutes[K] & RouteEntry>>>\n : SuffixAfterPrefix<K, TPrefix> extends `/${':'}${string}` | `${string}/${':'}${string}`\n ? (\n ...args: [\n id: number | string,\n options?: { headers?: Record<string, string>; query?: Record<string, string> },\n ]\n ) => Promise<ClientResult<RouteResponseType<TRoutes[K] & RouteEntry>>>\n : (\n options?: { headers?: Record<string, string>; query?: Record<string, string> },\n ) => Promise<ClientResult<RouteResponseType<TRoutes[K] & RouteEntry>>>\n\n// Type-level pathToMethodName — mirrors the runtime function exactly.\n// CRUD shorthands (suffix after stripping leading slash):\n// ''|'/' GET→index POST→store\n// ':x' GET→show PATCH→update DELETE→destroy\n// Custom routes: method + CamelCase(segments)\n// e.g. GET /search → 'getSearch', POST /:id/ban → 'postByIdBan'\n\n// Capitalize first letter of a string\ntype Capitalize1<S extends string> = S extends `${infer F}${infer R}` ? `${Uppercase<F>}${R}` : S\n\n// Convert a single path segment to its camelCase contribution:\n// ':id' → 'ById', ':userId' → 'ByUserId', 'search' → 'Search', 'export' → 'Export'\ntype SegmentToKey<S extends string> =\n S extends `:${infer Param}` ? `By${Capitalize1<Param>}` : Capitalize1<S>\n\n// Convert a slash-separated suffix string to camelCase body (no leading method prefix):\n// 'search' → 'Search'\n// ':id/ban' → 'ByIdBan'\n// 'by-user/:id' → 'By-userById' (runtime splits on / only, not -)\ntype SuffixToCamel<S extends string> =\n S extends `${infer Head}/${infer Tail}`\n ? `${SegmentToKey<Head>}${SuffixToCamel<Tail>}`\n : SegmentToKey<S>\n\n// Full method name: method + Capitalize1(SuffixToCamel(suffix))\ntype CustomMethodName<TMethod extends string, S extends string> =\n `${Lowercase<TMethod>}${Capitalize1<SuffixToCamel<S>>}`\n\ntype RouteMethodName<TMethod extends string, TSuffix extends string> =\n // Strip leading slash before matching\n TSuffix extends `/${infer S}`\n ? RouteMethodNameInner<TMethod, S>\n : RouteMethodNameInner<TMethod, TSuffix>\n\ntype RouteMethodNameInner<TMethod extends string, S extends string> =\n // CRUD: root (empty or just slash)\n S extends '' | '/'\n ? TMethod extends 'get' ? 'index'\n : TMethod extends 'post' ? 'store'\n : CustomMethodName<TMethod, S>\n // CRUD: single bare param segment ':x' — must not contain a slash (no sub-paths)\n : S extends `:${infer _P}` ? _P extends `${string}/${string}`\n ? CustomMethodName<TMethod, S>\n : TMethod extends 'get' ? 'show'\n : TMethod extends 'patch' ? 'update'\n : TMethod extends 'delete' ? 'destroy'\n : CustomMethodName<TMethod, S>\n // Custom route — compute literal name\n : CustomMethodName<TMethod, S>\n\n// Per-module client type — only routes belonging to this prefix, no cross-module bleed.\ntype ModuleClient<TRoutes extends RouteMap, TPrefix extends string> = {\n [K in ModuleRouteKeys<TRoutes, TPrefix> as\n RouteMethodName<MethodOf<K>, SuffixAfterPrefix<K, TPrefix>>\n ]: MethodEntry<TRoutes, K & keyof TRoutes & string, TPrefix>\n}\n\n// ── InferClient — splits app routes into per-module namespaces ─────────────────\n\n// Exact route key filter for a module — uses the _prefix phantom field set by ModuleBuilder.\n// Each route entry has _prefix: TPrefix — filter on exact equality to prevent cross-module bleed.\ntype ModuleRouteKeys<TRoutes extends RouteMap, TPrefix extends string> = {\n [K in keyof TRoutes & string]: TRoutes[K] extends { _prefix: TPrefix } ? K : never\n}[keyof TRoutes & string]\n\n// Type-level pathToClientKey: '/api/users' → 'apiUsers', '/blog-posts' → 'blogPosts'\n// Splits on '/' and '-', capitalizes segments after the first, joins them.\n// TS can do this with recursive template literal inference.\ntype PathToClientKey<S extends string> =\n // Strip leading slash first\n S extends `/${infer Rest}`\n ? PathToClientKey<Rest>\n : PathSegmentsToKey<S>\n\n// Split remaining string on '/' and '-' separators, join as camelCase\ntype PathSegmentsToKey<S extends string> =\n S extends `${infer Head}/${infer Tail}`\n ? `${Head}${Capitalize<PathSegmentsToKey<Tail>>}`\n : S extends `${infer Head}-${infer Tail}`\n ? `${Head}${Capitalize<PathSegmentsToKey<Tail>>}`\n : S\n\n// Public type for consumers\nexport type InferProxyClient<TApp> =\n TApp extends { readonly _routes: infer R; readonly _prefixes: infer P }\n ? R extends RouteMap\n ? [P] extends [string]\n ? ProxyClientFromRoutes<R, P>\n : Record<string, never>\n : Record<string, never>\n : Record<string, never>\n\n// Build the proxy client — one namespace per module prefix, fully typed.\n// P is the union of all registered module prefixes (from app._prefixes).\n// Key is the camelCase version of each prefix, matching pathToClientKey() at runtime.\ntype ProxyClientFromRoutes<TRoutes extends RouteMap, TPrefixes extends string> = {\n [P in TPrefixes as PathToClientKey<P>]: ModuleClient<TRoutes, P>\n}\n\n// ── Runtime implementation ─────────────────────────────────────────────────────\n\nexport interface ProxyClientOptions {\n fetch?: (input: Request) => Promise<Response>\n headers?: Record<string, string>\n throws?: boolean\n}\n\n// Runtime route descriptor — built from app.routes\ninterface RouteDescriptor {\n method: string\n path: string // full path e.g. '/users/:id'\n prefix: string // module prefix e.g. '/users'\n suffix: string // path after prefix e.g. '/:id'\n}\n\nfunction buildDescriptors(routes: Array<{ method: string; path: string; _module?: { prefix: string } | null }>): RouteDescriptor[] {\n return routes.map((r) => {\n const prefix = r._module?.prefix ?? ''\n const suffix = r.path.startsWith(prefix) ? r.path.slice(prefix.length) || '/' : r.path\n return { method: r.method, path: r.path, prefix, suffix }\n })\n}\n\nfunction substitutePathParams(path: string, args: unknown[]): { url: string; remaining: unknown[] } {\n const paramCount = (path.match(/:[^/]+/g) ?? []).length\n const params = args.slice(0, paramCount) as (string | number)[]\n const remaining = args.slice(paramCount)\n let i = 0\n const url = path.replace(/:[^/]+/g, () => String(params[i++] ?? ''))\n return { url, remaining }\n}\n\nasync function executeProxyRequest(\n baseUrl: string,\n descriptor: RouteDescriptor,\n args: unknown[],\n globalHeaders: Record<string, string>,\n fetchFn: (input: Request) => Promise<Response>,\n throwOnError: boolean,\n): Promise<ClientResult<unknown>> {\n // Separate path params (positional) from options (last arg if object without body for GET)\n const hasSuffix = /:[^/]+/.test(descriptor.suffix)\n let pathArgs: unknown[]\n let opts: { body?: unknown; headers?: Record<string, string>; query?: Record<string, string> } | undefined\n\n const isBodyMethod = descriptor.method === 'POST' || descriptor.method === 'PUT' || descriptor.method === 'PATCH'\n\n if (isBodyMethod) {\n // First positional args are path params, then body, then opts\n const paramCount = (descriptor.path.match(/:[^/]+/g) ?? []).length\n pathArgs = args.slice(0, paramCount)\n const bodyArg = args[paramCount]\n const optsArg = args[paramCount + 1] as typeof opts\n opts = { body: bodyArg, headers: optsArg?.headers, query: optsArg?.query }\n } else {\n // GET/DELETE: path params then optional opts object\n const paramCount = (descriptor.path.match(/:[^/]+/g) ?? []).length\n pathArgs = args.slice(0, paramCount)\n opts = args[paramCount] as typeof opts\n }\n\n const { url: substituted } = substitutePathParams(descriptor.path, pathArgs)\n let url = baseUrl.replace(/\\/$/, '') + substituted\n\n if (opts?.query) {\n const qs = new URLSearchParams(opts.query as Record<string, string>).toString()\n if (qs) url += '?' + qs\n }\n\n const headers: Record<string, string> = { ...globalHeaders, ...opts?.headers }\n let bodyStr: string | undefined\n\n if (opts?.body !== undefined && isBodyMethod) {\n bodyStr = JSON.stringify(opts.body)\n headers['Content-Type'] = 'application/json'\n }\n\n let res: Response\n try {\n res = await fetchFn(new Request(url, { method: descriptor.method, headers, body: bodyStr }))\n } catch (networkErr) {\n const msg = networkErr instanceof Error ? networkErr.message : 'Network error'\n const err = new VelnClientError(0, 'NETWORK_ERROR', msg)\n if (throwOnError) throw err\n return { ok: false, error: err, status: 0, code: 'NETWORK_ERROR', message: msg }\n }\n\n if (!res.ok) {\n let code = `HTTP_${res.status}`\n let message = `HTTP ${res.status}`\n try {\n const body = await res.json() as { code?: string; message?: string; error?: string }\n if (body.code) code = body.code\n if (body.message) message = body.message\n else if (body.error) message = body.error\n } catch { /* ignore parse error */ }\n\n const err = new VelnClientError(res.status, code, message)\n if (throwOnError) throw err\n return { ok: false, error: err, status: res.status, code, message }\n }\n\n let data: unknown\n try {\n data = await res.json()\n } catch {\n data = undefined\n }\n\n return { ok: true, data, status: res.status }\n}\n\n// ── Public factory ─────────────────────────────────────────────────────────────\n\nexport function createProxyClient<TApp extends { routes: Array<{ method: string; path: string; _module?: { prefix: string } | null }> }>(\n app: TApp,\n baseUrl: string,\n options?: ProxyClientOptions,\n): InferProxyClient<TApp> {\n const fetchFn = options?.fetch ?? ((req: Request) => globalThis.fetch(req))\n const globalHeaders = options?.headers ?? {}\n const throwOnError = options?.throws ?? false\n\n const descriptors = buildDescriptors(app.routes)\n\n // Group descriptors by prefix → clientKey\n const byKey = new Map<string, RouteDescriptor[]>()\n for (const d of descriptors) {\n const key = pathToClientKey(d.prefix) || 'root'\n if (!byKey.has(key)) byKey.set(key, [])\n byKey.get(key)!.push(d)\n }\n\n // Build namespace → method-map\n const proxy: Record<string, Record<string, (...args: unknown[]) => Promise<ClientResult<unknown>>>> = {}\n\n for (const [key, descs] of byKey) {\n const methods: Record<string, (...args: unknown[]) => Promise<ClientResult<unknown>>> = {}\n for (const desc of descs) {\n const methodName = pathToMethodName(desc.method, desc.suffix)\n methods[methodName] = (...args: unknown[]) =>\n executeProxyRequest(baseUrl, desc, args, globalHeaders, fetchFn, throwOnError)\n }\n proxy[key] = methods\n }\n\n return proxy as InferProxyClient<TApp>\n}\n\n// ── createModuleClient — single-module entry point ────────────────────────────\n\nexport function createModuleClient<TModule extends { routes: Array<{ method: string; path: string; _module?: { prefix: string } | null }>; prefix: string }>(\n module: TModule,\n baseUrl: string,\n options?: ProxyClientOptions,\n): Record<string, (...args: unknown[]) => Promise<ClientResult<unknown>>> {\n const fetchFn = options?.fetch ?? ((req: Request) => globalThis.fetch(req))\n const globalHeaders = options?.headers ?? {}\n const throwOnError = options?.throws ?? false\n\n // Module routes have unprefixed paths — add the module prefix to each\n const prefixedRoutes = module.routes.map((r) => ({\n ...r,\n path: module.prefix + r.path,\n _module: { prefix: module.prefix },\n }))\n\n const descriptors = buildDescriptors(prefixedRoutes)\n const methods: Record<string, (...args: unknown[]) => Promise<ClientResult<unknown>>> = {}\n\n for (const desc of descriptors) {\n const methodName = pathToMethodName(desc.method, desc.suffix)\n methods[methodName] = (...args: unknown[]) =>\n executeProxyRequest(baseUrl, desc, args, globalHeaders, fetchFn, throwOnError)\n }\n\n return methods\n}\n","import { createProxyClient } from './proxy'\nimport type { InferProxyClient, ProxyClientOptions } from './proxy'\n\nexport interface TestClientOptions extends Omit<ProxyClientOptions, 'fetch'> {\n /** Base URL for constructing request URLs. Defaults to 'http://localhost'. */\n baseUrl?: string\n}\n\n/**\n * createTestClient — type-safe test client that calls app.fetch() directly.\n *\n * Identical API to createProxyClient but requires no running HTTP server.\n * Returns InferProxyClient<TApp> — the same fully-typed client as the production proxy.\n *\n * Usage:\n * const client = createTestClient(app)\n * const result = await client.apiUsers.index()\n * expect(result.ok).toBe(true)\n *\n * app.fetch() needs a valid URL to parse pathname/query from,\n * so requests are constructed as 'http://localhost/path' by default.\n */\nexport function createTestClient<\n TApp extends {\n fetch: (req: Request) => Promise<Response>\n routes: Array<{ method: string; path: string; _module?: { prefix: string } | null }>\n }\n>(\n app: TApp,\n options?: TestClientOptions,\n): InferProxyClient<TApp> {\n const { baseUrl = 'http://localhost', ...rest } = options ?? {}\n return createProxyClient(app, baseUrl, {\n ...rest,\n fetch: (req: Request) => app.fetch(req),\n })\n}\n","export { createProxyClient, createModuleClient, pathToClientKey } from './proxy'\nexport type { ClientResult, InferProxyClient, ProxyClientOptions } from './proxy'\nexport { createTestClient } from './test-client'\nexport type { TestClientOptions } from './test-client'\n\nimport type { RouteMap, RouteEntry } from '../app/types'\nimport type { ZodTypeAny } from 'zod'\nimport { VelnClientError } from './error'\nexport { VelnClientError } from './error'\n\n// Helper types — all eager, no conditional on generic parameter\ntype RouteResponse<TEntry extends RouteEntry> =\n TEntry['response'] extends ZodTypeAny ? import('zod').infer<TEntry['response']> : unknown\n\ntype RouteBody<TEntry extends RouteEntry> =\n TEntry['body'] extends ZodTypeAny ? import('zod').infer<TEntry['body']> : never\n\ntype RouteParams<TEntry extends RouteEntry> =\n TEntry['params'] extends ZodTypeAny ? import('zod').infer<TEntry['params']> : never\n\ntype RouteQuery<TEntry extends RouteEntry> =\n TEntry['query'] extends ZodTypeAny ? import('zod').infer<TEntry['query']> : never\n\ntype ClientOptions<TEntry extends RouteEntry> = {\n params?: RouteParams<TEntry>\n query?: RouteQuery<TEntry>\n body?: RouteBody<TEntry>\n headers?: Record<string, string>\n}\n\n// Strip 'METHOD ' prefix from a route key to get just the path.\n// 'POST /items' → '/items'\ntype StripMethod<M extends string, K extends string> =\n K extends `${M} ${infer P}` ? P : never\n\ntype VelnClient<TRoutes extends RouteMap> = {\n get<P extends StripMethod<'GET', Extract<keyof TRoutes, `GET /${string}`>>>(\n path: P,\n options?: ClientOptions<TRoutes[`GET ${P}`]>,\n ): Promise<RouteResponse<TRoutes[`GET ${P}`]>>\n\n post<P extends StripMethod<'POST', Extract<keyof TRoutes, `POST /${string}`>>>(\n path: P,\n options?: ClientOptions<TRoutes[`POST ${P}`]>,\n ): Promise<RouteResponse<TRoutes[`POST ${P}`]>>\n\n put<P extends StripMethod<'PUT', Extract<keyof TRoutes, `PUT /${string}`>>>(\n path: P,\n options?: ClientOptions<TRoutes[`PUT ${P}`]>,\n ): Promise<RouteResponse<TRoutes[`PUT ${P}`]>>\n\n patch<P extends StripMethod<'PATCH', Extract<keyof TRoutes, `PATCH /${string}`>>>(\n path: P,\n options?: ClientOptions<TRoutes[`PATCH ${P}`]>,\n ): Promise<RouteResponse<TRoutes[`PATCH ${P}`]>>\n\n delete<P extends StripMethod<'DELETE', Extract<keyof TRoutes, `DELETE /${string}`>>>(\n path: P,\n options?: ClientOptions<TRoutes[`DELETE ${P}`]>,\n ): Promise<RouteResponse<TRoutes[`DELETE ${P}`]>>\n}\n\ntype ExtractRoutes<TApp> = TApp extends { readonly _routes: infer R } ? R : never\n\nfunction substitutePath(path: string, params?: Record<string, unknown>): string {\n if (!params) return path\n return path.replace(/:([^/]+)/g, (_, key) => String(params[key as string] ?? `:${key}`))\n}\n\n// FetchFn — accepts either globalThis.fetch or app.fetch (which only takes Request)\ntype FetchFn = (input: Request) => Promise<Response>\n\nexport function createClient<TApp>(\n baseUrl: string,\n options?: { fetch?: FetchFn },\n): VelnClient<ExtractRoutes<TApp> extends RouteMap ? ExtractRoutes<TApp> : Record<never, never>> {\n const fetchFn: FetchFn = options?.fetch ?? ((req) => globalThis.fetch(req))\n\n async function request(method: string, path: string, opts?: ClientOptions<RouteEntry>): Promise<unknown> {\n // Extract HTTP method from path key (e.g. \"GET /users/:id\" → path \"/users/:id\")\n // The path argument here is already just the path portion (e.g. \"/users/:id\")\n const substituted = substitutePath(path, opts?.params as Record<string, unknown> | undefined)\n\n let url = baseUrl.replace(/\\/$/, '') + substituted\n\n // Append query params for GET/DELETE\n if (opts?.query && (method === 'GET' || method === 'DELETE')) {\n const qs = new URLSearchParams(opts.query as Record<string, string>).toString()\n if (qs) url += '?' + qs\n }\n\n const headers: Record<string, string> = { ...opts?.headers }\n let body: string | undefined\n\n if (opts?.body !== undefined && (method === 'POST' || method === 'PUT' || method === 'PATCH')) {\n body = JSON.stringify(opts.body)\n headers['Content-Type'] = 'application/json'\n }\n\n const res = await fetchFn(new Request(url, { method, headers, body }))\n\n if (!res.ok) {\n if (res.status === 422) {\n let issues: import('zod').ZodIssue[] | undefined\n try {\n const data = await res.json() as { issues?: import('zod').ZodIssue[] }\n issues = data.issues\n } catch {\n // ignore parse error\n }\n throw new VelnClientError(res.status, 'VALIDATION_ERROR', 'Validation failed', issues)\n }\n throw new VelnClientError(res.status, `HTTP_${res.status}`, `HTTP ${res.status}`)\n }\n\n // Parse JSON response\n try {\n return await res.json()\n } catch {\n return undefined\n }\n }\n\n return {\n get: (path, opts) => request('GET', path as string, opts as ClientOptions<RouteEntry>),\n post: (path, opts) => request('POST', path as string, opts as ClientOptions<RouteEntry>),\n put: (path, opts) => request('PUT', path as string, opts as ClientOptions<RouteEntry>),\n patch: (path, opts) => request('PATCH', path as string, opts as ClientOptions<RouteEntry>),\n delete: (path, opts) => request('DELETE', path as string, opts as ClientOptions<RouteEntry>),\n } as VelnClient<ExtractRoutes<TApp> extends RouteMap ? ExtractRoutes<TApp> : Record<never, never>>\n}\n","import { z } from 'zod'\nimport type { ZodTypeAny } from 'zod'\nimport type { Column } from '../schema/column'\nimport type { SchemaMap, TableDef } from '../schema/table'\n\n// ── columnToZod — map a single Column to its Zod type ────────────────────\n\nfunction columnToZod(col: Column<unknown>): ZodTypeAny {\n let base: ZodTypeAny\n\n switch (col.def.type) {\n case 'INTEGER': base = z.number().int(); break\n case 'REAL': base = z.number(); break\n case 'TEXT': base = z.string(); break\n case 'UUID': base = z.string().uuid(); break\n case 'BOOLEAN': base = z.boolean(); break\n case 'TIMESTAMP': base = z.coerce.date(); break\n case 'JSON': base = z.unknown(); break\n case 'BLOB': base = z.instanceof(Uint8Array); break\n default: base = z.unknown()\n }\n\n if (col.def.nullable) {\n base = base.nullable()\n }\n\n return base\n}\n\n// ── tableToZodInsert — derive insert Zod schema from TableDef ─────────────\n//\n// Rules (mirror InferInsert):\n// - primaryKey + autoIncrement → excluded entirely\n// - nullable → .nullable() applied\n// - defaultValue or defaultFn present → .optional()\n// - otherwise → required\n\nexport function tableToZodInsert<T, S extends SchemaMap>(\n table: TableDef<T, S>,\n): z.ZodObject<Record<string, ZodTypeAny>> {\n const shape: Record<string, ZodTypeAny> = {}\n\n for (const [name, col] of Object.entries(table.schema)) {\n const c = col as Column<unknown>\n\n // Skip auto-increment primary keys — DB assigns the value\n if (c.def.primaryKey && c.def.autoIncrement) continue\n\n let field = columnToZod(c)\n\n // Fields with defaults are optional on insert\n if (c.def.defaultValue !== undefined || c.def.defaultFn !== undefined) {\n field = field.optional()\n }\n\n shape[name] = field\n }\n\n return z.object(shape)\n}\n\n// ── tableToZodRow — full row schema (all fields required except nullable) ─\n\nexport function tableToZodRow<T, S extends SchemaMap>(\n table: TableDef<T, S>,\n): z.ZodObject<Record<string, ZodTypeAny>> {\n const shape: Record<string, ZodTypeAny> = {}\n\n for (const [name, col] of Object.entries(table.schema)) {\n shape[name] = columnToZod(col as Column<unknown>)\n }\n\n return z.object(shape)\n}\n","// Re-export from the central errors module so resource-level imports still work.\n// NotFoundError and ConflictError are now VelnError subclasses with status + code.\nexport { NotFoundError, ConflictError } from '../errors/index'\n","import type { ZodTypeAny } from 'zod'\nimport type { TableDef, SchemaMap, InferRow, InferInsert } from '../schema/table'\nimport type { BoundVelnDB } from '../db/index'\nimport type { BaseCtx, BaseOptions } from '../app/types'\nimport type { Guard, ErrorHandler, OnRequestHook, OnBeforeHandleHook, OnResponseHook } from '../app/types'\nimport type { Plugin } from '../app/plugin'\nimport type { AuditConfig } from '../schema/audit'\nimport type { ModuleHookHandlers } from '../hooks/types'\nimport type { ServiceDef } from '../service/index'\nimport type { EventHandlerDef } from '../events/handler'\nimport { defineModel } from '../model/index'\nimport { defineService } from '../service/index'\nimport { ModuleBuilder, defineModule } from '../app/module'\nimport type { VelnModule } from '../app/module'\nimport { tableToZodInsert, tableToZodRow } from './zod-table'\nimport { NotFoundError } from './errors'\n\nexport { NotFoundError, ConflictError } from './errors'\nexport { tableToZodInsert, tableToZodRow } from './zod-table'\n\n// ── Types ─────────────────────────────────────────────────────────────────────\n\ntype ResourceServiceKey<TName extends string> = `${TName}Resource`\n\n// ── Default model methods ─────────────────────────────────────────────────────\n// These are the methods the built-in model exposes by default.\n// User can override any via ResourceOptions.model.\n\nexport interface DefaultModelMethods<TRow, TInsert> {\n index(): Promise<TRow[]>\n show(id: number): Promise<TRow>\n store(data: TInsert): Promise<TRow>\n update(id: number, data: Partial<TInsert>): Promise<TRow>\n destroy(id: number): Promise<void>\n}\n\n// ResourceOptions.model — user provides (db, ...args) => result for each method override,\n// plus any new methods they want to add.\n// Each override replaces the default implementation entirely.\nexport interface ModelOverrides<TRow, TInsert> {\n index?: (db: BoundVelnDB) => () => Promise<TRow[]>\n show?: (db: BoundVelnDB) => (id: number) => Promise<TRow>\n store?: (db: BoundVelnDB) => (data: TInsert) => Promise<TRow>\n update?: (db: BoundVelnDB) => (id: number, data: Partial<TInsert>) => Promise<TRow>\n destroy?: (db: BoundVelnDB) => (id: number) => Promise<void>\n // Extra methods — any signature\n [key: string]: ((db: BoundVelnDB) => (...args: never[]) => unknown) | undefined\n}\n\n// ServiceOverrides — user provides ({ model }, ...args) => result for each CRUD method.\n// model includes all default + custom model methods.\nexport type ServiceOverrides<TModel, TRow, TInsert> = {\n index?: (deps: { model: TModel }) => () => Promise<TRow[]>\n show?: (deps: { model: TModel }) => (id: number) => Promise<TRow>\n store?: (deps: { model: TModel }) => (data: TInsert) => Promise<TRow>\n update?: (deps: { model: TModel }) => (id: number, data: Partial<TInsert>) => Promise<TRow>\n destroy?: (deps: { model: TModel }) => (id: number) => Promise<void>\n}\n\n// RouteConfig — per-route options\nexport type RouteConfig = {\n guard?: Guard<BaseCtx>\n summary?: string\n} | false\n\nexport interface ResourceOptions<TRow, TInsert> {\n prefix?: string\n model?: ModelOverrides<TRow, TInsert>\n service?: ServiceOverrides<DefaultModelMethods<TRow, TInsert> & Record<string, unknown>, TRow, TInsert>\n routes?: {\n index?: RouteConfig\n show?: RouteConfig\n store?: RouteConfig\n update?: RouteConfig\n destroy?: RouteConfig\n }\n}\n\n// ── buildResourceModel ────────────────────────────────────────────────────────\n\nfunction buildResourceModel<T, S extends SchemaMap>(\n table: TableDef<T, S>,\n overrides: ModelOverrides<InferRow<TableDef<T, S>>, InferInsert<TableDef<T, S>>>,\n) {\n type TRow = InferRow<TableDef<T, S>>\n type TInsert = InferInsert<TableDef<T, S>>\n\n const modelName = `${table.name}Model` as const\n\n return defineModel(modelName, table, (db) => {\n const pk = table.primaryKey as keyof TRow & string\n\n const index = overrides.index\n ? overrides.index(db)\n : () => db.from(table).select() as Promise<TRow[]>\n\n const show = overrides.show\n ? overrides.show(db)\n : async (id: number): Promise<TRow> => {\n const row = await (db.from(table).where({ [pk]: id } as Partial<TRow>).first() as Promise<TRow | null>)\n if (!row) throw new NotFoundError(`${table.name} with id ${id} not found`)\n return row\n }\n\n const store = overrides.store\n ? overrides.store(db)\n : (data: TInsert) => (db.into(table) as { insert(d: unknown): Promise<TRow> }).insert(data)\n\n const update = overrides.update\n ? overrides.update(db)\n : async (id: number, data: Partial<TInsert>): Promise<TRow> => {\n await show(id) // throws NotFoundError if missing\n await db.from(table).where({ [pk]: id } as Partial<TRow>).update(data as Partial<TRow>)\n return show(id)\n }\n\n const destroy = overrides.destroy\n ? overrides.destroy(db)\n : async (id: number): Promise<void> => {\n await show(id) // throws NotFoundError if missing\n await db.from(table).where({ [pk]: id } as Partial<TRow>).delete()\n }\n\n // Build base methods\n const methods: Record<string, unknown> = { index, show, store, update, destroy }\n\n // Add any extra methods from overrides\n for (const [key, factory] of Object.entries(overrides)) {\n if (!['index', 'show', 'store', 'update', 'destroy'].includes(key) && factory) {\n methods[key] = factory(db)\n }\n }\n\n return methods as DefaultModelMethods<TRow, TInsert> & Record<string, unknown>\n })\n}\n\n// ── buildResourceService ──────────────────────────────────────────────────────\n\ntype AnyModel = DefaultModelMethods<unknown, unknown> & Record<string, unknown>\n\nfunction buildResourceService<T, S extends SchemaMap>(\n table: TableDef<T, S>,\n modelDef: ReturnType<typeof buildResourceModel<T, S>>,\n serviceOverrides: ServiceOverrides<AnyModel, InferRow<TableDef<T, S>>, InferInsert<TableDef<T, S>>>,\n): ServiceDef<ResourceServiceKey<string>, DefaultModelMethods<InferRow<TableDef<T, S>>, InferInsert<TableDef<T, S>>>> {\n type TRow = InferRow<TableDef<T, S>>\n type TInsert = InferInsert<TableDef<T, S>>\n\n const serviceKey = `${table.name}Resource` as ResourceServiceKey<string>\n const modelName = modelDef._modelName\n\n return defineService(serviceKey)\n .use(modelDef)\n .define((deps) => {\n const model = (deps as Record<string, AnyModel>)[modelName]\n\n const index = serviceOverrides.index ? serviceOverrides.index({ model }) : () => model.index() as Promise<TRow[]>\n const show = serviceOverrides.show ? serviceOverrides.show({ model }) : (id: number) => model.show(id) as Promise<TRow>\n const store = serviceOverrides.store ? serviceOverrides.store({ model }) : (data: TInsert) => model.store(data) as Promise<TRow>\n const update = serviceOverrides.update ? serviceOverrides.update({ model }) : (id: number, data: Partial<TInsert>) => model.update(id, data) as Promise<TRow>\n const destroy = serviceOverrides.destroy ? serviceOverrides.destroy({ model }) : (id: number) => model.destroy(id) as Promise<void>\n\n return { index, show, store, update, destroy }\n }) as ServiceDef<ResourceServiceKey<string>, DefaultModelMethods<TRow, TInsert>>\n}\n\n// ── buildResourceModule ───────────────────────────────────────────────────────\n\nfunction buildResourceModule<T, S extends SchemaMap>(\n prefix: string,\n table: TableDef<T, S>,\n serviceDef: ServiceDef<ResourceServiceKey<string>, DefaultModelMethods<InferRow<TableDef<T, S>>, InferInsert<TableDef<T, S>>>>,\n routeOptions: ResourceOptions<InferRow<TableDef<T, S>>, InferInsert<TableDef<T, S>>>['routes'],\n): ModuleBuilder<BaseCtx> {\n const serviceKey = serviceDef._serviceKey\n const routes = routeOptions ?? {}\n\n const insertSchema = tableToZodInsert(table)\n const rowSchema = tableToZodRow(table)\n\n type Svc = DefaultModelMethods<InferRow<TableDef<T, S>>, InferInsert<TableDef<T, S>>>\n type Ctx = BaseCtx & Record<typeof serviceKey, Svc>\n\n let builder = defineModule(prefix).use(serviceDef) as unknown as ModuleBuilder<Ctx>\n\n function getSvc(ctx: Ctx): Svc {\n return (ctx as Record<string, unknown>)[serviceKey] as Svc\n }\n\n // GET / — index\n if (routes.index !== false) {\n const cfg = routes.index ?? {}\n let b = builder\n if (cfg && cfg.guard) b = b.guard(cfg.guard as Guard<Ctx>)\n b = b.route({\n method: 'GET',\n path: '/',\n summary: (cfg && cfg.summary) ? cfg.summary : `List ${table.name}`,\n handler: async (ctx) => ctx.json(await getSvc(ctx).index()),\n })\n builder = b\n }\n\n // GET /:id — show\n if (routes.show !== false) {\n const cfg = routes.show ?? {}\n let b = builder\n if (cfg && cfg.guard) b = b.guard(cfg.guard as Guard<Ctx>)\n b = b.route({\n method: 'GET',\n path: '/:id',\n summary: (cfg && cfg.summary) ? cfg.summary : `Get ${table.name} by id`,\n handler: async (ctx) => ctx.json(await getSvc(ctx).show(Number(ctx.params['id']))),\n })\n builder = b\n }\n\n // POST / — store\n if (routes.store !== false) {\n const cfg = routes.store ?? {}\n let b = builder\n if (cfg && cfg.guard) b = b.guard(cfg.guard as Guard<Ctx>)\n b = b.route({\n method: 'POST',\n path: '/',\n summary: (cfg && cfg.summary) ? cfg.summary : `Create ${table.name}`,\n schema: { body: insertSchema, response: rowSchema },\n handler: async (ctx) => ctx.json(await getSvc(ctx).store((ctx as Ctx & { body: InferInsert<TableDef<T, S>> }).body), 201),\n })\n builder = b\n }\n\n // PATCH /:id — update\n if (routes.update !== false) {\n const cfg = routes.update ?? {}\n let b = builder\n if (cfg && cfg.guard) b = b.guard(cfg.guard as Guard<Ctx>)\n b = b.route({\n method: 'PATCH',\n path: '/:id',\n summary: (cfg && cfg.summary) ? cfg.summary : `Update ${table.name}`,\n schema: { body: insertSchema.partial() },\n handler: async (ctx) => {\n const row = await getSvc(ctx).update(\n Number(ctx.params['id']),\n (ctx as Ctx & { body: Partial<InferInsert<TableDef<T, S>>> }).body,\n )\n return ctx.json(row)\n },\n })\n builder = b\n }\n\n // DELETE /:id — destroy\n if (routes.destroy !== false) {\n const cfg = routes.destroy ?? {}\n let b = builder\n if (cfg && cfg.guard) b = b.guard(cfg.guard as Guard<Ctx>)\n b = b.route({\n method: 'DELETE',\n path: '/:id',\n summary: (cfg && cfg.summary) ? cfg.summary : `Delete ${table.name}`,\n handler: async (ctx) => {\n await getSvc(ctx).destroy(Number(ctx.params['id']))\n return ctx.json({ ok: true })\n },\n })\n builder = b\n }\n\n return builder as unknown as ModuleBuilder<BaseCtx>\n}\n\n// ── ResourceResult ────────────────────────────────────────────────────────────\n\nexport interface ResourceResult<T, S extends SchemaMap> {\n Model: ReturnType<typeof buildResourceModel<T, S>>\n Service: ServiceDef<ResourceServiceKey<string>, DefaultModelMethods<InferRow<TableDef<T, S>>, InferInsert<TableDef<T, S>>>>\n module: VelnModule\n}\n\n// ── ResourceBuilder ───────────────────────────────────────────────────────────\n\nexport class ResourceBuilder<TCtx extends BaseCtx, T, S extends SchemaMap> {\n private constructor(\n private readonly _table: TableDef<T, S>,\n private readonly _options: ResourceOptions<InferRow<TableDef<T, S>>, InferInsert<TableDef<T, S>>>,\n private readonly _builderFns: Array<(b: ModuleBuilder<BaseCtx>) => ModuleBuilder<BaseCtx>>,\n ) {}\n\n static create<T, S extends SchemaMap>(\n table: TableDef<T, S>,\n options: ResourceOptions<InferRow<TableDef<T, S>>, InferInsert<TableDef<T, S>>>,\n ): ResourceBuilder<BaseCtx, T, S> {\n return new ResourceBuilder<BaseCtx, T, S>(table, options, [])\n }\n\n // ── Delegate to ModuleBuilder ─────────────────────────────────────────────\n\n options(opts: BaseOptions): ResourceBuilder<TCtx, T, S> {\n return new ResourceBuilder<TCtx, T, S>(\n this._table,\n this._options,\n [...this._builderFns, (b) => b.options(opts)],\n )\n }\n\n plugin<TAdd extends object>(p: Plugin<TCtx, TAdd>): ResourceBuilder<TCtx & TAdd, T, S> {\n return new ResourceBuilder<TCtx & TAdd, T, S>(\n this._table,\n this._options,\n [...this._builderFns, (b) => (b as ModuleBuilder<BaseCtx>).plugin(p as unknown as Plugin<BaseCtx, TAdd>) as unknown as ModuleBuilder<BaseCtx>],\n )\n }\n\n guard(g: Guard<TCtx>): ResourceBuilder<TCtx, T, S> {\n return new ResourceBuilder<TCtx, T, S>(\n this._table,\n this._options,\n [...this._builderFns, (b) => b.guard(g as Guard<BaseCtx>)],\n )\n }\n\n hook(table: TableDef<T, S>, handlers: ModuleHookHandlers<T, TCtx>): ResourceBuilder<TCtx, T, S> {\n return new ResourceBuilder<TCtx, T, S>(\n this._table,\n this._options,\n [...this._builderFns, (b) => b.hook(table, handlers as ModuleHookHandlers<T, BaseCtx>)],\n )\n }\n\n audit<AT extends Record<string, unknown>, AS extends SchemaMap>(\n auditTable: TableDef<AT, AS>,\n config: AuditConfig<TCtx, AT, AS>,\n ): ResourceBuilder<TCtx, T, S> {\n return new ResourceBuilder<TCtx, T, S>(\n this._table,\n this._options,\n [...this._builderFns, (b) => b.audit(auditTable, config as AuditConfig<BaseCtx, AT, AS>)],\n )\n }\n\n use<TKey extends string, TDef>(\n service: ServiceDef<TKey, TDef>,\n ): ResourceBuilder<TCtx & Record<TKey, TDef>, T, S> {\n return new ResourceBuilder<TCtx & Record<TKey, TDef>, T, S>(\n this._table,\n this._options,\n [...this._builderFns, (b) => b.use(service) as ModuleBuilder<BaseCtx>],\n )\n }\n\n onRequest(hook: OnRequestHook<TCtx>): ResourceBuilder<TCtx, T, S> {\n return new ResourceBuilder<TCtx, T, S>(\n this._table,\n this._options,\n [...this._builderFns, (b) => b.onRequest(hook as OnRequestHook<BaseCtx>)],\n )\n }\n\n onBeforeHandle(hook: OnBeforeHandleHook<TCtx>): ResourceBuilder<TCtx, T, S> {\n return new ResourceBuilder<TCtx, T, S>(\n this._table,\n this._options,\n [...this._builderFns, (b) => b.onBeforeHandle(hook as OnBeforeHandleHook<BaseCtx>)],\n )\n }\n\n onResponse(hook: OnResponseHook<TCtx>): ResourceBuilder<TCtx, T, S> {\n return new ResourceBuilder<TCtx, T, S>(\n this._table,\n this._options,\n [...this._builderFns, (b) => b.onResponse(hook as OnResponseHook<BaseCtx>)],\n )\n }\n\n onError(handler: ErrorHandler<TCtx>): ResourceBuilder<TCtx, T, S> {\n return new ResourceBuilder<TCtx, T, S>(\n this._table,\n this._options,\n [...this._builderFns, (b) => b.onError(handler as ErrorHandler<BaseCtx>)],\n )\n }\n\n events(handler: EventHandlerDef): ResourceBuilder<TCtx, T, S> {\n return new ResourceBuilder<TCtx, T, S>(\n this._table,\n this._options,\n [...this._builderFns, (b) => b.events(handler)],\n )\n }\n\n // ── .build() ─────────────────────────────────────────────────────────────\n\n build(): ResourceResult<T, S> {\n const prefix = this._options.prefix ?? `/${this._table.name}`\n const Model = buildResourceModel(this._table, this._options.model ?? {})\n const Service = buildResourceService(this._table, Model, (this._options.service ?? {}) as ServiceOverrides<AnyModel, InferRow<TableDef<T, S>>, InferInsert<TableDef<T, S>>>)\n let moduleBuilder = buildResourceModule(prefix, this._table, Service, this._options.routes)\n for (const fn of this._builderFns) {\n moduleBuilder = fn(moduleBuilder)\n }\n const module = moduleBuilder.build()\n return { Model, Service, module }\n }\n}\n\n// ── defineResource — entry point ─────────────────────────────────────────────\n\n/**\n * defineResource — generates CRUD routes, a Model, and a Service from a table definition.\n *\n * @param table The table definition produced by `defineTable(...).build()`.\n * @param options Route prefix string or `ResourceOptions` for customization.\n *\n * @example\n * const { module } = defineResource(usersTable, '/users').build()\n * app.register(module)\n */\nexport function defineResource<T, S extends SchemaMap>(\n table: TableDef<T, S>,\n options: ResourceOptions<InferRow<TableDef<T, S>>, InferInsert<TableDef<T, S>>> | string = {},\n): ResourceBuilder<BaseCtx, T, S> {\n // Convenience: if options is a string, treat it as the prefix\n const opts: ResourceOptions<InferRow<TableDef<T, S>>, InferInsert<TableDef<T, S>>> =\n typeof options === 'string' ? { prefix: options } : options\n return ResourceBuilder.create(table, opts)\n}\n","import type { VelnAdapter } from '../../adapter/types'\n\nexport interface VelnConfig {\n adapter?: VelnAdapter\n features?: string // default: './src/features'\n schema?: string // default: './src/schema'\n tables?: string // default: './src/tables'\n migrations?: string // default: './migrations'\n commands?: string // default: './src/commands'\n}\n\nexport interface CommandOption {\n flag: string\n description: string\n default?: string\n}\n\nexport interface CommandDef {\n _name: string\n _description: string\n _options: CommandOption[]\n _action: (args: Record<string, string>) => Promise<void> | void\n}\n\nclass CommandBuilder {\n private _desc = ''\n private _opts: CommandOption[] = []\n\n constructor(private readonly _name: string) {}\n\n description(desc: string): this {\n this._desc = desc\n return this\n }\n\n option(flag: string, description: string, defaultValue?: string): this {\n this._opts.push({ flag, description, default: defaultValue })\n return this\n }\n\n action(fn: (args: Record<string, string>) => Promise<void> | void): CommandDef {\n return {\n _name: this._name,\n _description: this._desc,\n _options: this._opts,\n _action: fn,\n }\n }\n}\n\nexport function defineConfig(config: VelnConfig): VelnConfig {\n return config\n}\n\nexport function defineCommand(name: string): CommandBuilder {\n return new CommandBuilder(name)\n}\n"],"mappings":"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","names":["status","params","column","SQLiteAdapter","PostgresAdapter","MySQLAdapter","trimmed","readdir","join","readdir","cols","join","base","status","status","normalizeHandler","VelnDB","status","base"]}
|