@forinda/kickjs 6.5.0 → 6.5.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{adapter-CEt1MEdF.d.mts → adapter-CbMq-NBf.d.mts} +25 -381
- package/dist/adapter-CbMq-NBf.d.mts.map +1 -0
- package/dist/{app-module-BSpHKlhE.d.mts → app-module-DtoySG6l.d.mts} +6 -5
- package/dist/app-module-DtoySG6l.d.mts.map +1 -0
- package/dist/application-Cl0JlmNY.mjs +12 -0
- package/dist/application-Cl0JlmNY.mjs.map +1 -0
- package/dist/{application-Bzdzl5wP.d.mts → application-zlzYGgKD.d.mts} +6 -6
- package/dist/application-zlzYGgKD.d.mts.map +1 -0
- package/dist/{bootstrap-C1VGQQVF.mjs → bootstrap-DzyWLYpU.mjs} +3 -3
- package/dist/{bootstrap-C1VGQQVF.mjs.map → bootstrap-DzyWLYpU.mjs.map} +1 -1
- package/dist/{bootstrap-DYexY169.d.mts → bootstrap-Nzgi7K2d.d.mts} +2 -3
- package/dist/bootstrap-Nzgi7K2d.d.mts.map +1 -0
- package/dist/{cache-CwZzIH0D.d.mts → cache-C0qL0NSD.d.mts} +2 -1
- package/dist/cache-C0qL0NSD.d.mts.map +1 -0
- package/dist/config/index.d.mts +1 -1
- package/dist/config/index.mjs +2 -2
- package/dist/{config-BeIZJBXA.mjs → config-CwFPFwsN.mjs} +3 -3
- package/dist/{config-BeIZJBXA.mjs.map → config-CwFPFwsN.mjs.map} +1 -1
- package/dist/{container-iED1swkd.d.mts → container-BW_MlgLj.d.mts} +3 -2
- package/dist/container-BW_MlgLj.d.mts.map +1 -0
- package/dist/{container-CBaL5lus.mjs → container-C7kmdVwh.mjs} +3 -3
- package/dist/{container-CBaL5lus.mjs.map → container-C7kmdVwh.mjs.map} +1 -1
- package/dist/{context-BS5o1IuU.mjs → context-DQaUwwQM.mjs} +3 -3
- package/dist/{context-BS5o1IuU.mjs.map → context-DQaUwwQM.mjs.map} +1 -1
- package/dist/{context-errors-CwD27Vbj.mjs → context-errors-97x9siRx.mjs} +2 -2
- package/dist/{context-errors-CwD27Vbj.mjs.map → context-errors-97x9siRx.mjs.map} +1 -1
- package/dist/core/adapter.d.mts +1 -1
- package/dist/core/adapter.mjs +1 -1
- package/dist/core/app-module.d.mts +1 -1
- package/dist/core/app-module.mjs +1 -1
- package/dist/core/cache.d.mts +1 -1
- package/dist/core/cache.mjs +1 -1
- package/dist/core/container.d.mts +1 -1
- package/dist/core/container.mjs +2 -2
- package/dist/core/cron.mjs +2 -2
- package/dist/core/decorators.d.mts +1 -1
- package/dist/core/decorators.mjs +2 -2
- package/dist/core/errors.d.mts +1 -1
- package/dist/core/errors.mjs +1 -1
- package/dist/core/interfaces.d.mts +1 -1
- package/dist/core/interfaces.mjs +1 -1
- package/dist/core/logger.mjs +1 -1
- package/dist/core/path.mjs +1 -1
- package/dist/core/plugin.d.mts +1 -1
- package/dist/core/plugin.mjs +1 -1
- package/dist/core/reactivity.d.mts +1 -1
- package/dist/core/reactivity.mjs +1 -1
- package/dist/core-CLmwVWlw.mjs +12 -0
- package/dist/core-CLmwVWlw.mjs.map +1 -0
- package/dist/{cors-C4aSCD3J.d.mts → cors-BuDU9CpA.d.mts} +1 -2
- package/dist/cors-BuDU9CpA.d.mts.map +1 -0
- package/dist/cron-DOOtTY4q.d.mts.map +1 -1
- package/dist/{csrf-DNh_7aOk.mjs → csrf-BsrsObK-.mjs} +2 -2
- package/dist/{csrf-DNh_7aOk.mjs.map → csrf-BsrsObK-.mjs.map} +1 -1
- package/dist/{csrf-7nUXGTuz.d.mts → csrf-vR23CJas.d.mts} +1 -2
- package/dist/csrf-vR23CJas.d.mts.map +1 -0
- package/dist/{decorators-wEJBqXHg.d.mts → decorators-Bks7cgBJ.d.mts} +12 -7
- package/dist/decorators-Bks7cgBJ.d.mts.map +1 -0
- package/dist/{disposables-mnjJuaVx.mjs → disposables-D46xX96x.mjs} +2 -2
- package/dist/{disposables-mnjJuaVx.mjs.map → disposables-D46xX96x.mjs.map} +1 -1
- package/dist/env-Biq_60jq.mjs +13 -0
- package/dist/{env-Dgtjncd5.mjs.map → env-Biq_60jq.mjs.map} +1 -1
- package/dist/{error-handler-DR01K_rI.d.mts → error-handler-Cr6Yt9as.d.mts} +1 -2
- package/dist/error-handler-Cr6Yt9as.d.mts.map +1 -0
- package/dist/{errors-n0H96eEz.d.mts → errors-By6UueCm.d.mts} +18 -9
- package/dist/errors-By6UueCm.d.mts.map +1 -0
- package/dist/{handler-UvmjQGYc.mjs → handler-Ci1NMv-9.mjs} +3 -3
- package/dist/{handler-UvmjQGYc.mjs.map → handler-Ci1NMv-9.mjs.map} +1 -1
- package/dist/{helmet-CKzZzeNl.d.mts → helmet-CFQUTVig.d.mts} +1 -2
- package/dist/helmet-CFQUTVig.d.mts.map +1 -0
- package/dist/http/application.d.mts +1 -1
- package/dist/http/application.mjs +2 -2
- package/dist/http/bootstrap.d.mts +1 -1
- package/dist/http/bootstrap.mjs +2 -2
- package/dist/http/context.d.mts +2 -2
- package/dist/http/context.mjs +2 -2
- package/dist/http/middleware/cors.d.mts +1 -1
- package/dist/http/middleware/cors.mjs +1 -1
- package/dist/http/middleware/csrf.d.mts +1 -1
- package/dist/http/middleware/csrf.mjs +2 -2
- package/dist/http/middleware/error-handler.d.mts +1 -1
- package/dist/http/middleware/error-handler.mjs +2 -2
- package/dist/http/middleware/helmet.d.mts +1 -1
- package/dist/http/middleware/helmet.mjs +1 -1
- package/dist/http/middleware/rate-limit.d.mts +1 -1
- package/dist/http/middleware/rate-limit.mjs +2 -2
- package/dist/http/middleware/request-id.d.mts +1 -1
- package/dist/http/middleware/request-id.mjs +1 -1
- package/dist/http/middleware/request-logger.d.mts +1 -1
- package/dist/http/middleware/request-logger.mjs +2 -2
- package/dist/http/middleware/session.d.mts +1 -1
- package/dist/http/middleware/session.mjs +2 -2
- package/dist/http/middleware/spa.d.mts +1 -1
- package/dist/http/middleware/spa.mjs +2 -2
- package/dist/http/middleware/spa.mjs.map +1 -1
- package/dist/http/middleware/upload.d.mts +1 -1
- package/dist/http/middleware/upload.mjs +2 -2
- package/dist/http/middleware/upload.mjs.map +1 -1
- package/dist/http/middleware/validate.d.mts +1 -1
- package/dist/http/middleware/validate.mjs +1 -1
- package/dist/http/middleware/views.d.mts +1 -1
- package/dist/http/middleware/views.mjs +2 -3
- package/dist/http/query/index.d.mts +1 -1
- package/dist/http/query/index.mjs +2 -2
- package/dist/http/router-builder.d.mts +1 -1
- package/dist/http/router-builder.mjs +2 -3
- package/dist/http/runtimes/fastify.d.mts +1 -2
- package/dist/http/runtimes/fastify.d.mts.map +1 -1
- package/dist/http/runtimes/fastify.mjs +3 -3
- package/dist/http/runtimes/fastify.mjs.map +1 -1
- package/dist/http/runtimes/h3-web.d.mts +1 -2
- package/dist/http/runtimes/h3-web.d.mts.map +1 -1
- package/dist/http/runtimes/h3-web.mjs +2 -2
- package/dist/http/runtimes/h3.d.mts +1 -2
- package/dist/http/runtimes/h3.d.mts.map +1 -1
- package/dist/http/runtimes/h3.mjs +2 -2
- package/dist/{index-BtWJ9SLP.d.mts → index-BfT5KZ-M.d.mts} +2 -2
- package/dist/index-BfT5KZ-M.d.mts.map +1 -0
- package/dist/{index-D98NLfS5.d.mts → index-M6TF75MS.d.mts} +2 -3
- package/dist/index-M6TF75MS.d.mts.map +1 -0
- package/dist/index.d.mts +26 -26
- package/dist/index.mjs +2 -2
- package/dist/index.mjs.map +1 -1
- package/dist/{interfaces-CayXPOAf.d.mts → interfaces-BTTBdkvG.d.mts} +3 -2
- package/dist/interfaces-BTTBdkvG.d.mts.map +1 -0
- package/dist/{kv-stores-O8HUSwpv.mjs → kv-stores-BLJdf3Fn.mjs} +2 -2
- package/dist/{kv-stores-O8HUSwpv.mjs.map → kv-stores-BLJdf3Fn.mjs.map} +1 -1
- package/dist/{kv-stores-duYHIEr1.d.mts → kv-stores-CHowq8VP.d.mts} +5 -6
- package/dist/kv-stores-CHowq8VP.d.mts.map +1 -0
- package/dist/logger-DA43DvNY.d.mts.map +1 -1
- package/dist/{metadata-CUDfhy4e.mjs → metadata-DUBbuHqY.mjs} +2 -2
- package/dist/{metadata-CUDfhy4e.mjs.map → metadata-DUBbuHqY.mjs.map} +1 -1
- package/dist/{module-registry-Mv5FqVlq.mjs → module-registry-aIt66if2.mjs} +2 -2
- package/dist/{module-registry-Mv5FqVlq.mjs.map → module-registry-aIt66if2.mjs.map} +1 -1
- package/dist/path-BVA9MfN1.d.mts.map +1 -1
- package/dist/query-CXN52dzy.mjs +12 -0
- package/dist/{query-gMAVXzx2.mjs.map → query-CXN52dzy.mjs.map} +1 -1
- package/dist/{rate-limit-oLL5EPUf.d.mts → rate-limit-Dme747JJ.d.mts} +1 -2
- package/dist/rate-limit-Dme747JJ.d.mts.map +1 -0
- package/dist/{reactivity-XL0fFDvG.d.mts → reactivity-BkMNA0kp.d.mts} +2 -2
- package/dist/reactivity-BkMNA0kp.d.mts.map +1 -0
- package/dist/{reply-BMBvs-FB.mjs → reply-C1ljl6xS.mjs} +3 -3
- package/dist/{reply-BMBvs-FB.mjs.map → reply-C1ljl6xS.mjs.map} +1 -1
- package/dist/{request-id-IDobbxU-.d.mts → request-id-CVzJ1uHD.d.mts} +1 -2
- package/dist/request-id-CVzJ1uHD.d.mts.map +1 -0
- package/dist/{request-logger-DZVW6VNI.d.mts → request-logger-BU4ulKLp.d.mts} +1 -2
- package/dist/request-logger-BU4ulKLp.d.mts.map +1 -0
- package/dist/router-builder-BbgVXuy3.mjs +12 -0
- package/dist/router-builder-BbgVXuy3.mjs.map +1 -0
- package/dist/{router-builder-GWgxoOdC.d.mts → router-builder-CMGhEBU2.d.mts} +2 -3
- package/dist/router-builder-CMGhEBU2.d.mts.map +1 -0
- package/dist/{session-DSRA-PUX.d.mts → session-z9iewOXA.d.mts} +1 -2
- package/dist/session-z9iewOXA.d.mts.map +1 -0
- package/dist/{spa-DWzSWAzx.d.mts → spa-DsRUrm69.d.mts} +4 -9
- package/dist/spa-DsRUrm69.d.mts.map +1 -0
- package/dist/{upload-CIZc803m.d.mts → upload-XVTyQcNN.d.mts} +3 -3
- package/dist/upload-XVTyQcNN.d.mts.map +1 -0
- package/dist/{upload-config-CFfHvoHF.mjs → upload-config-Dd_QvlpC.mjs} +2 -2
- package/dist/{upload-config-CFfHvoHF.mjs.map → upload-config-Dd_QvlpC.mjs.map} +1 -1
- package/dist/{validate-DoZDOhCi.d.mts → validate-DMYpUnrf.d.mts} +1 -2
- package/dist/validate-DMYpUnrf.d.mts.map +1 -0
- package/dist/views-Dj6XFaca.mjs +12 -0
- package/dist/views-Dj6XFaca.mjs.map +1 -0
- package/dist/views-DsfBT1fR.d.mts +659 -0
- package/dist/views-DsfBT1fR.d.mts.map +1 -0
- package/dist/web.d.mts +4 -5
- package/dist/web.d.mts.map +1 -1
- package/dist/web.mjs +2 -2
- package/dist/web.mjs.map +1 -1
- package/package.json +10 -10
- package/dist/adapter-CEt1MEdF.d.mts.map +0 -1
- package/dist/app-module-BSpHKlhE.d.mts.map +0 -1
- package/dist/application-Bzdzl5wP.d.mts.map +0 -1
- package/dist/application-C-r79XqD.mjs +0 -12
- package/dist/application-C-r79XqD.mjs.map +0 -1
- package/dist/bootstrap-DYexY169.d.mts.map +0 -1
- package/dist/cache-CwZzIH0D.d.mts.map +0 -1
- package/dist/container-iED1swkd.d.mts.map +0 -1
- package/dist/contributor-runner-Cu13cDQp.mjs +0 -12
- package/dist/contributor-runner-Cu13cDQp.mjs.map +0 -1
- package/dist/core-TDR0XGzO.mjs +0 -12
- package/dist/core-TDR0XGzO.mjs.map +0 -1
- package/dist/cors-C4aSCD3J.d.mts.map +0 -1
- package/dist/csrf-7nUXGTuz.d.mts.map +0 -1
- package/dist/decorators-wEJBqXHg.d.mts.map +0 -1
- package/dist/env-Dgtjncd5.mjs +0 -13
- package/dist/error-handler-DR01K_rI.d.mts.map +0 -1
- package/dist/errors-n0H96eEz.d.mts.map +0 -1
- package/dist/helmet-CKzZzeNl.d.mts.map +0 -1
- package/dist/http/middleware/views.mjs.map +0 -1
- package/dist/http/router-builder.mjs.map +0 -1
- package/dist/index-BtWJ9SLP.d.mts.map +0 -1
- package/dist/index-D98NLfS5.d.mts.map +0 -1
- package/dist/interfaces-CayXPOAf.d.mts.map +0 -1
- package/dist/kv-stores-duYHIEr1.d.mts.map +0 -1
- package/dist/query-gMAVXzx2.mjs +0 -12
- package/dist/rate-limit-oLL5EPUf.d.mts.map +0 -1
- package/dist/reactivity-XL0fFDvG.d.mts.map +0 -1
- package/dist/request-id-IDobbxU-.d.mts.map +0 -1
- package/dist/request-logger-DZVW6VNI.d.mts.map +0 -1
- package/dist/rolldown-runtime-CuwksmWW.mjs +0 -11
- package/dist/router-builder-GWgxoOdC.d.mts.map +0 -1
- package/dist/session-DSRA-PUX.d.mts.map +0 -1
- package/dist/spa-DWzSWAzx.d.mts.map +0 -1
- package/dist/upload-CIZc803m.d.mts.map +0 -1
- package/dist/validate-DoZDOhCi.d.mts.map +0 -1
- package/dist/views-Kp8Z3AO1.d.mts +0 -275
- package/dist/views-Kp8Z3AO1.d.mts.map +0 -1
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"core-TDR0XGzO.mjs","names":["mergeConfig","composeName","mergeConfig","composeName"],"sources":["../src/core/define-module.ts","../src/core/define-modules.ts","../src/core/circuit-breaker.ts","../src/core/context-decorator.ts","../src/core/mount-sort.ts","../src/core/define-plugin.ts","../src/core/define-adapter.ts","../src/core/augmentation.ts","../src/core/asset-keys.ts","../src/core/assets.ts"],"sourcesContent":["import type { AppModule } from './app-module'\nimport type { BuildContext } from './define-plugin'\n\n/**\n * Options passed to {@link defineModule}. Mirrors {@link DefineAdapterOptions}\n * and {@link DefinePluginOptions} so adopters learn one mental model\n * across all three primitives.\n *\n * The optional `TExtra` generic lets a module ship public methods\n * beyond the standard {@link AppModule} contract — they're preserved\n * on the returned module instance so external callers (tests, sibling\n * modules) can invoke them directly.\n */\nexport interface DefineModuleOptions<TConfig, TExtra = unknown> {\n /**\n * Stable identity surfaced in diagnostics, route logs, and\n * `.scoped()` namespacing. Required because boot-time error\n * messages reference modules by name — anonymous modules make\n * cycles + missing-dep errors hard to localize.\n */\n name: string\n /** Optional version string surfaced in diagnostics. */\n version?: string\n /**\n * Optional kickjs version constraint. Enforced by the framework\n * when implemented; today it lives on the definition for\n * documentation and forward compatibility.\n */\n requires?: { kickjs?: string }\n /**\n * Default config merged with overrides at instantiation time\n * (`MyModule({ field: x })`). Call-site overrides win.\n */\n defaults?: Partial<TConfig>\n /**\n * Build the AppModule shape from the resolved config and context.\n * `ctx.name` is the resolved instance name (the bare definition\n * name for the default call, or `${name}:${scope}` for\n * `.scoped()`); `ctx.scoped` discriminates so the build function\n * can branch on namespacing if needed.\n *\n * Return any extension methods alongside the standard\n * {@link AppModule} surface — they're typed via `TExtra` and stay\n * accessible on the resulting instance.\n */\n build(config: TConfig, ctx: BuildContext): AppModule & TExtra\n}\n\n/**\n * Factory returned by {@link defineModule}. Mirrors {@link AdapterFactory}\n * — call (`MyModule({...})`), scope (`MyModule.scoped('public', {...})`),\n * inspect (`MyModule.definition`).\n *\n * `.async()` is intentionally **not** part of the module factory\n * surface. Module config has no async-resolution window: `register()`\n * and `routes()` both run synchronously during bootstrap, before any\n * adapter `beforeStart` hook fires. Adopters that need async-resolved\n * config push it into an adapter (which has `beforeStart`), then\n * inject the resolved value into the module via DI tokens.\n */\nexport interface ModuleFactory<TConfig, TExtra = unknown> {\n (config?: Partial<TConfig>): AppModule & TExtra\n scoped(scopeName: string, config?: Partial<TConfig>): AppModule & TExtra\n readonly definition: Readonly<DefineModuleOptions<TConfig, TExtra>>\n}\n\nconst mergeConfig = <TConfig>(\n defaults: Partial<TConfig> = {},\n overrides: Partial<TConfig> = {},\n): TConfig => ({ ...defaults, ...overrides }) as TConfig\n\nconst composeName = (base: string, scope: string): string => `${base}:${scope}`\n\n/**\n * Build an {@link AppModule} factory from a typed definition. Pairs\n * with {@link defineAdapter}, {@link definePlugin}, and\n * {@link defineContextDecorator} as the fourth `define*` primitive\n * — adopters write modules the same way they write adapters and\n * plugins.\n *\n * The returned factory produces real {@link AppModule} instances\n * that drop into `bootstrap({ modules })` directly. The legacy\n * class form (`class TasksModule implements AppModule { ... }`) keeps\n * working — `bootstrap` accepts either shape.\n *\n * @example\n * ```ts\n * interface TasksConfig {\n * scope: 'public' | 'admin'\n * }\n *\n * const TasksModule = defineModule<TasksConfig>({\n * name: 'TasksModule',\n * defaults: { scope: 'public' },\n * build: (config, { name }) => ({\n * register(container) {\n * container.registerInstance(`tasks:scope:${name}`, config.scope)\n * },\n * routes() {\n * return { path: `/${config.scope}/tasks`, router: buildTasksRouter() }\n * },\n * contributors() {\n * return [LoadTenant.registration]\n * },\n * }),\n * })\n *\n * bootstrap({\n * modules: [\n * TasksModule(), // public scope (defaults)\n * TasksModule.scoped('admin', { scope: 'admin' }),\n * ],\n * })\n * ```\n */\nexport function defineModule<TConfig = Record<string, unknown>, TExtra = unknown>(\n options: DefineModuleOptions<TConfig, TExtra>,\n): ModuleFactory<TConfig, TExtra> {\n if (options === null || typeof options !== 'object') {\n throw new TypeError(\n 'defineModule: options must be an object literal. ' +\n 'See architecture.md §21 for the spec shape.',\n )\n }\n if (typeof options.name !== 'string' || options.name.length === 0) {\n const got = typeof options.name === 'string' ? '\"\"' : typeof options.name\n throw new TypeError(\n `defineModule: options.name must be a non-empty string (got ${got}). ` +\n 'Module names appear in diagnostics and `.scoped()` namespacing — anonymous ' +\n 'modules make cycle / missing-dep errors hard to localize.',\n )\n }\n if (typeof options.build !== 'function') {\n throw new TypeError(\n `defineModule(${options.name}): options.build is required and must be a function ` +\n `(got ${typeof options.build}). The build function returns the AppModule shape — ` +\n 'register() / routes() / contributors() — wired with the resolved config.',\n )\n }\n\n const buildSync = (\n instanceName: string,\n scoped: boolean,\n overrides?: Partial<TConfig>,\n ): AppModule & TExtra => {\n const config = mergeConfig(options.defaults, overrides)\n // Mutate-in-place rather than spread: spread strips prototype methods\n // when build() returns a class instance, and the existing defineAdapter\n // pattern uses the same approach. `TExtra` properties survive because\n // they're own properties on the build result.\n const built = options.build(config, { name: instanceName, scoped })\n // AppModule has no `name` field today, but stamping the resolved\n // instance name onto the result lets diagnostics surface it without\n // adopter wiring. The cast keeps the public AppModule type\n // unchanged while the data is available for any framework code\n // that wants it.\n Object.defineProperty(built, '__moduleName', {\n value: instanceName,\n enumerable: false,\n writable: false,\n configurable: false,\n })\n return built\n }\n\n const factory = ((config?: Partial<TConfig>) =>\n buildSync(options.name, false, config)) as ModuleFactory<TConfig, TExtra>\n\n factory.scoped = (scopeName: string, config?: Partial<TConfig>) =>\n buildSync(composeName(options.name, scopeName), true, config)\n\n Object.defineProperty(factory, 'definition', {\n value: Object.freeze({ ...options }),\n writable: false,\n enumerable: true,\n configurable: false,\n })\n\n return factory\n}\n","import type { AppModuleEntry } from './app-module'\n\n/**\n * Chainable registry returned by {@link defineModules}. Extends\n * `Array<AppModuleEntry>` so it drops into `bootstrap({ modules })`\n * unchanged — the framework loader already iterates the array, so a\n * `ModuleList` IS a valid `modules` value with no special handling.\n *\n * The added affordance is `.mount(module)` returning `this` so\n * adopters can build the list fluently:\n *\n * ```ts\n * const modules = defineModules()\n * .mount(HelloModule())\n * .mount(AdminModule())\n *\n * bootstrap({ modules })\n * ```\n *\n * **Why not just use a plain array?** Two reasons. First, the\n * fluent shape reads more naturally for module-list construction —\n * adopters used to `definePlugin().scoped(...)` / `defineAdapter(...)`\n * see the same call-then-call pattern. Second, the registry is the\n * stable extension point: a future `.use(module)` for non-HTTP\n * modules (queues, cron, workers) lands as a method on `ModuleList`\n * without breaking the `Array<AppModuleEntry>` superclass contract.\n */\nexport class ModuleList extends Array<AppModuleEntry> {\n /**\n * Append a module to the list. Returns `this` for chaining.\n *\n * Accepts both class form (`SomeModule extends AppModule`) and\n * `defineModule` factory output — same as the underlying\n * `bootstrap({ modules })` array. The framework loader\n * discriminates `typeof entry === 'function'` at boot.\n */\n mount(module: AppModuleEntry): this {\n this.push(module)\n return this\n }\n}\n\n/**\n * Build a {@link ModuleList} for the application. Optional vararg\n * lets adopters seed the list inline; subsequent `.mount()` calls\n * append.\n *\n * @example\n * ```ts\n * import { bootstrap, defineModules } from '@forinda/kickjs'\n * import { HelloModule } from './modules/hello/hello.module'\n * import { AdminModule } from './modules/admin/admin.module'\n *\n * // Fluent — most common\n * const modules = defineModules()\n * .mount(HelloModule())\n * .mount(AdminModule())\n *\n * // Or seeded inline + chained\n * const modules2 = defineModules(HelloModule()).mount(AdminModule())\n *\n * await bootstrap({ modules })\n * ```\n *\n * The returned value is an `AppModuleEntry[]` subclass — `bootstrap`\n * accepts it directly without any special-casing. For conditional /\n * dynamic registration at bootstrap time (env flags, runtime config,\n * tenant lists), use the `setup(registry)` callback on `bootstrap`\n * instead — both surfaces compose.\n */\nexport function defineModules(...initial: AppModuleEntry[]): ModuleList {\n const list = new ModuleList()\n for (const entry of initial) list.push(entry)\n return list\n}\n","/**\n * Circuit Breaker pattern for external service calls.\n *\n * Protects your application from cascading failures when downstream\n * services are unhealthy by short-circuiting requests after a\n * configurable failure threshold.\n *\n * @example\n * ```ts\n * const breaker = new CircuitBreaker('payment-api', {\n * failureThreshold: 5,\n * resetTimeout: 30_000,\n * })\n *\n * const result = await breaker.execute(() => fetch('https://payment.example.com/charge'))\n * ```\n */\n\nexport type CircuitBreakerState = 'closed' | 'open' | 'half_open'\n\nexport interface CircuitBreakerOptions {\n /** Number of consecutive failures before the circuit opens. */\n failureThreshold: number\n /** Milliseconds to wait before transitioning from OPEN to HALF_OPEN. */\n resetTimeout: number\n /** Max requests allowed in HALF_OPEN state before deciding (default 1). */\n halfOpenMax?: number\n}\n\nexport interface CircuitBreakerStats {\n failures: number\n successes: number\n state: CircuitBreakerState\n lastFailure?: Date\n}\n\n/**\n * Error thrown when the circuit is open and calls are being rejected.\n */\nexport class CircuitOpenError extends Error {\n constructor(public readonly breakerName: string) {\n super(`Circuit breaker \"${breakerName}\" is open — request rejected`)\n this.name = 'CircuitOpenError'\n }\n}\n\nexport class CircuitBreaker {\n private state: CircuitBreakerState = 'closed'\n private failures = 0\n private successes = 0\n private halfOpenAttempts = 0\n private lastFailure?: Date\n private openedAt?: number\n\n private readonly failureThreshold: number\n private readonly resetTimeout: number\n private readonly halfOpenMax: number\n\n constructor(\n public readonly name: string,\n options: CircuitBreakerOptions,\n ) {\n this.failureThreshold = options.failureThreshold\n this.resetTimeout = options.resetTimeout\n this.halfOpenMax = options.halfOpenMax ?? 1\n }\n\n /**\n * Execute an async function through the circuit breaker.\n * Throws `CircuitOpenError` if the circuit is open.\n */\n async execute<T>(fn: () => Promise<T>): Promise<T> {\n this.maybeTransitionToHalfOpen()\n\n if (this.state === 'open') {\n throw new CircuitOpenError(this.name)\n }\n\n if (this.state === 'half_open' && this.halfOpenAttempts >= this.halfOpenMax) {\n throw new CircuitOpenError(this.name)\n }\n\n if (this.state === 'half_open') {\n this.halfOpenAttempts++\n }\n\n try {\n const result = await fn()\n this.onSuccess()\n return result\n } catch (error) {\n this.onFailure()\n throw error\n }\n }\n\n /** Returns the current circuit state. */\n getState(): CircuitBreakerState {\n this.maybeTransitionToHalfOpen()\n return this.state\n }\n\n /** Returns current statistics. */\n getStats(): CircuitBreakerStats {\n this.maybeTransitionToHalfOpen()\n return {\n failures: this.failures,\n successes: this.successes,\n state: this.state,\n ...(this.lastFailure ? { lastFailure: this.lastFailure } : {}),\n }\n }\n\n /** Manually reset the circuit breaker to CLOSED state. */\n reset(): void {\n this.state = 'closed'\n this.failures = 0\n this.successes = 0\n this.halfOpenAttempts = 0\n this.lastFailure = undefined\n this.openedAt = undefined\n }\n\n private onSuccess(): void {\n if (this.state === 'half_open') {\n // Recovery confirmed — close the circuit\n this.state = 'closed'\n this.failures = 0\n this.halfOpenAttempts = 0\n this.openedAt = undefined\n }\n this.successes++\n }\n\n private onFailure(): void {\n this.failures++\n this.lastFailure = new Date()\n\n if (this.state === 'half_open') {\n // Recovery failed — re-open\n this.state = 'open'\n this.openedAt = Date.now()\n this.halfOpenAttempts = 0\n } else if (this.state === 'closed' && this.failures >= this.failureThreshold) {\n this.state = 'open'\n this.openedAt = Date.now()\n }\n }\n\n private maybeTransitionToHalfOpen(): void {\n if (this.state === 'open' && this.openedAt != null) {\n if (Date.now() - this.openedAt >= this.resetTimeout) {\n this.state = 'half_open'\n this.halfOpenAttempts = 0\n }\n }\n }\n}\n","import 'reflect-metadata'\nimport { METADATA, type Constructor, type MaybePromise } from './interfaces'\nimport { pushClassMeta, pushMethodMeta } from './metadata'\nimport type { InjectionToken } from './token'\nimport type { ContextKeys, ContextMeta, ExecutionContext, MetaValue } from './execution-context'\n\n/**\n * String-literal union of every known context key — the union of the\n * keys declared on {@link ContextKeys} (key-only registry) and\n * {@link ContextMeta} (value-type registry). Resolves to `string` when\n * the project hasn't augmented either yet (so a first-day project keeps\n * compiling), and narrows to the concrete keys once the\n * `declare module '@forinda/kickjs' { interface ContextKeys/ContextMeta { ... } }`\n * blocks land.\n *\n * Used as the element type of `dependsOn`, so a typo like\n * `dependsOn: ['tenent']` becomes a TS error instead of a boot-time\n * `MissingContributorError`.\n *\n * Unioning BOTH registries is deliberate: it means adding a value type\n * via `ContextMeta` automatically makes that key a valid `dependsOn`\n * target, and you can register a dependsOn-able key in `ContextKeys`\n * without being forced to give it a value type. (Before the split,\n * `dependsOn` was keyed off `ContextMeta` alone, so augmenting\n * `ContextMeta` for some keys broke `dependsOn` for every key you\n * hadn't added there.)\n */\ntype KnownContextKey = keyof ContextMeta | keyof ContextKeys\nexport type ContextMetaKey = [KnownContextKey] extends [never] ? string : KnownContextKey & string\n\n/**\n * What a single `deps` entry is allowed to be — the runtime calls\n * `container.resolve(value)`, which accepts an injection token brand\n * or a constructor (decorated class). Anything else (a string literal,\n * an array, a plain object) silently fails at boot when the runner\n * tries to resolve it; constraining at the type level surfaces the\n * mistake in the editor instead.\n */\nexport type DepValue = InjectionToken<unknown> | Constructor<unknown>\n\n/**\n * Maps a `deps` declaration object to its resolved-instance shape.\n *\n * `deps: { db: DB_TOKEN, cache: CacheService }` produces\n * `{ db: Db, cache: CacheService }` — the runner resolves each value\n * against the DI container and hands the result to `resolve()`.\n */\nexport type ResolvedDeps<D extends Record<string, DepValue>> = {\n [K in keyof D]: D[K] extends InjectionToken<infer T>\n ? T\n : D[K] extends Constructor<infer T>\n ? T\n : never\n}\n\n/**\n * Keys of `T` that are declared required (i.e. not `?`-optional).\n */\ntype RequiredParamKeys<T> = {\n // eslint-disable-next-line @typescript-eslint/ban-types\n [K in keyof T]-?: {} extends Pick<T, K> ? never : K\n}[keyof T]\n\n/**\n * Params a call site MUST supply: the required keys of `P` that\n * `paramDefaults` (type `PD`) doesn't already provide.\n *\n * The `string extends keyof P` guard short-circuits the index-signature\n * case — `P` defaults to `Record<string, never>` for the overwhelmingly\n * common zero-params contributor, and a mapped type over `string` would\n * otherwise report \"every key is required\" and break `@Foo` for every\n * existing decorator in the wild.\n */\nexport type MissingParamKeys<P, PD> = string extends keyof P\n ? never\n : Exclude<RequiredParamKeys<P>, keyof PD>\n\n/**\n * The argument type for a call site (`@Foo({...})`, `.with({...})`).\n *\n * `Partial<P>` when every required field has a default, so adopters keep\n * overriding just the fields they care about. Otherwise `Partial<P>`\n * intersected with the undefaulted required fields, making those\n * mandatory at each call site.\n */\nexport type CallSiteParams<P, PD> = [MissingParamKeys<P, PD>] extends [never]\n ? Partial<P>\n : Partial<P> & Pick<P, MissingParamKeys<P, PD> & keyof P>\n\n/**\n * Spec passed to {@link defineContextDecorator}. Describes one entry in\n * the per-request contributor pipeline.\n *\n * @typeParam K - The {@link ContextMeta} key this contributor populates.\n * @typeParam D - DI dependency declaration shape (see {@link ResolvedDeps}).\n * @typeParam Ctx - Concrete execution-context type. Defaults to the abstract\n * {@link ExecutionContext}; HTTP contributors typically\n * default to `RequestContext` at the call site.\n * @typeParam PD - Inferred from `paramDefaults`. Drives which params each\n * call site is required to supply — see {@link CallSiteParams}.\n * Never spell this by hand.\n */\nexport interface ContextDecoratorSpec<\n K extends string = string,\n D extends Record<string, DepValue> = Record<string, never>,\n P extends Record<string, unknown> = Record<string, never>,\n Ctx extends ExecutionContext = ExecutionContext,\n PD extends Partial<P> = Partial<P>,\n> {\n /** ContextMeta key the resolved value is written to. */\n key: K\n /**\n * DI dependencies resolved by the runner before `resolve()` runs.\n * Map entry keys become property names on the resolved-deps argument\n * passed to `resolve()`.\n */\n deps?: D\n /**\n * Other contributor keys that must populate before this one runs.\n * Enforced via topo-sort at startup; missing deps and cycles fail boot.\n *\n * Typed against {@link ContextMetaKey} — the union of `keyof ContextMeta`\n * and `keyof ContextKeys` — once the project augments either, so\n * `dependsOn: ['tenent']` (typo) is a TS error, not a boot-time\n * `MissingContributorError`. Falls back to plain `string[]` when both\n * registries are empty (no augmentation yet) so first-day projects keep\n * compiling. Cast escape hatch: `dependsOn: ['custom-key' as ContextMetaKey]`.\n */\n dependsOn?: readonly ContextMetaKey[]\n /**\n * If `true`, a thrown `resolve` skips the contributor instead of\n * forwarding to the request error handler. The key is left unset\n * and downstream consumers see `ctx.get(key) === undefined`.\n */\n optional?: boolean\n /**\n * Default per-call params merged with the call-site params; call-site\n * wins. When omitted, params default to `{}` and the resolver\n * receives an empty object — back-compat with today's zero-arg\n * decorators.\n *\n * Param shape is intentionally unconstrained: plain data, functions,\n * and closures are all valid. Adopters who want runtime validation\n * should perform it inside `resolve()` — keeps the framework\n * validator-agnostic so projects can plug Zod / Valibot / hand-rolled\n * checks without the framework caring.\n *\n * **Required fields are enforced at the call site.** A required field\n * of `P` that has no entry here must be supplied wherever the\n * decorator is applied — `@Foo({ action: 'audit:read' })`. The bare\n * `@Foo` form and `.registration` stop type-checking for such a\n * decorator, because neither can supply the value.\n *\n * This exists so nobody has to invent a meaningless default just to\n * satisfy the type (`action: 'settings:read'` on a permission\n * contributor every call site overrides anyway). A default that is\n * never correct is worse than no default: forget the argument at one\n * call site and the route silently gates on the placeholder instead\n * of failing to compile.\n *\n * Omit this entirely for the common zero-params case — `P` defaults\n * to `Record<string, never>`, which requires nothing.\n */\n paramDefaults?: PD\n /**\n * Runtime mirror of the compile-time requirement above: param names\n * that must be present after merging call-site params over\n * `paramDefaults`. A missing one throws `TypeError` at the point of\n * use (decoration time for `@Foo`, call time for `@Foo({...})` /\n * `.with({...})`), naming the decorator and the field.\n *\n * The type-level check already covers TypeScript call sites, so this\n * is for the paths types can't reach: plain-JS adopters, `as any`\n * escapes, and params assembled dynamically. Optional — list only\n * fields whose absence is a correctness bug rather than a default.\n */\n requiredParams?: readonly (keyof P & string)[]\n /**\n * Hook invoked when `resolve()` throws and `optional` is `false`.\n * Returning a value writes it to `ctx.set(key, …)`; returning\n * `undefined` / `void` skips. Throwing inside the hook forwards\n * the new error to the request error handler.\n *\n * Async-permitted by design — adopters frequently want to\n * `await auditService.log(err)` or `await cache.fallback(...)`.\n *\n * The third `params` argument carries the resolved per-call params\n * (call-site overrides merged on top of `paramDefaults`).\n */\n onError?: (err: unknown, ctx: Ctx, params: P) => MaybePromise<MetaValue<K> | undefined | void>\n /**\n * Compute and return the value to write into `ctx.set(key, …)`.\n *\n * The third `params` argument carries the resolved per-call params\n * (call-site overrides merged on top of `paramDefaults`). When the\n * decorator is applied zero-arg (`@Foo`), `params` equals\n * `paramDefaults` (or `{}` if defaults are omitted). When applied as\n * a factory (`@Foo({ ... })`), the call-site object is merged on top.\n */\n resolve: (ctx: Ctx, deps: ResolvedDeps<D>, params: P) => MaybePromise<MetaValue<K>>\n}\n\n/**\n * Internal, normalised registration produced by {@link defineContextDecorator}.\n *\n * Frozen and shared by every use site of the decorator (method, class,\n * module, adapter, global). The pipeline builder dedupes by `key` using\n * the precedence rule defined in §20.4 of `architecture.md`.\n */\nexport interface ContributorRegistration<\n K extends string = string,\n D extends Record<string, DepValue> = Record<string, never>,\n Ctx extends ExecutionContext = ExecutionContext,\n> {\n readonly key: K\n readonly deps: D\n readonly dependsOn: readonly ContextMetaKey[]\n readonly optional: boolean\n /**\n * Per-call params from the spec are baked into the closure at\n * decorator-construction time, so the runner-facing `onError`\n * exposes only `(err, ctx)`.\n */\n readonly onError?: (err: unknown, ctx: Ctx) => MaybePromise<MetaValue<K> | undefined | void>\n /**\n * Per-call params from the spec are baked into the closure at\n * decorator-construction time, so the runner-facing `resolve`\n * exposes only `(ctx, deps)`. Adopters who write their own\n * registrations (without `defineContextDecorator`) match this\n * shape directly — params are an implementation detail of the\n * decorator factory, not of the runtime pipeline.\n */\n readonly resolve: (ctx: Ctx, deps: ResolvedDeps<D>) => MaybePromise<MetaValue<K>>\n /**\n * Stack snapshot captured the moment the decorator was defined.\n * Used by the contributor-pipeline builder to point boot-time\n * errors (`MissingContributorError`, `ContributorCycleError`,\n * `DuplicateContributorError`) at the adopter file that declared\n * the broken contributor — instead of forcing them to grep for\n * the key string.\n *\n * Optional because adopters who hand-roll a `ContributorRegistration`\n * (without `defineContextDecorator`) may not have a useful stack to\n * attach. Format is the raw `Error.stack` string; consumers slice\n * the first non-framework frame for display.\n */\n readonly definedAt?: string\n}\n\n/**\n * Type-erased registration shape used in the public collection slots\n * (`AppModule.contributors?()`, `AppAdapter.contributors?()`,\n * `KickPlugin.contributors?()`, `bootstrap({ contributors })`).\n *\n * The narrow `ContributorRegistration` carries a `Ctx` parameter so\n * `resolve(ctx, deps)` is typed at the *definition* site, but `Ctx`\n * sits in a contravariant position on `resolve` — meaning a\n * `ContributorRegistration<…, RequestContext>` is *not* assignable to\n * `ContributorRegistration<…, ExecutionContext>` even though every\n * `RequestContext` is-a `ExecutionContext`. That's TS-sound but\n * useless: the runner only ever calls a contributor with the same\n * concrete ctx the route mounts under, so an HTTP-typed contributor\n * never sees a non-HTTP ctx. Erasing `Ctx` to `any` in the collection\n * type lets adopters store contributors typed against `RequestContext`\n * (or any future transport-specific ctx) in the same array without\n * casting.\n */\nexport type AnyContributorRegistration = ContributorRegistration<\n string,\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n any,\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n any\n>\n\n/** Convenience alias for `AnyContributorRegistration[]` collections. */\nexport type ContributorRegistrations =\n | AnyContributorRegistration[]\n | readonly AnyContributorRegistration[]\n\n/**\n * The decorator function returned by either a zero-arg\n * {@link ContextDecorator} application or a factory call. Overloaded\n * to satisfy both class and method decorator shapes — adopters apply\n * the same decorator to either site without TS rejecting the call.\n */\nexport interface ContextDecoratorTarget {\n /** Class decorator usage. */\n // eslint-disable-next-line @typescript-eslint/no-unsafe-function-type\n (target: Function): void\n /** Method decorator usage. */\n (target: object, propertyKey: string | symbol, descriptor?: PropertyDescriptor): void\n}\n\n/**\n * The value returned by {@link defineContextDecorator}.\n *\n * Resolves to one of two shapes depending on whether every required\n * field of `P` has a `paramDefaults` entry:\n *\n * - {@link ContextDecoratorWithDefaults} — the classic shape. Usable\n * bare (`@Foo`), as a factory (`@Foo({...})`), via `.with(params)`,\n * and via `.registration`.\n * - {@link ContextDecoratorRequiringParams} — when `P` has required\n * fields `paramDefaults` doesn't cover. Only the factory and\n * `.with(params)` forms exist, because the others have no way to\n * supply the missing values. Applying such a decorator bare is a\n * compile error rather than a silent `undefined` at request time.\n *\n * `PD` is inferred from the spec's `paramDefaults`; the default here\n * (`Partial<P>`) keeps hand-written `ContextDecorator<K, D, P>`\n * annotations resolving to the permissive shape as before.\n */\nexport type ContextDecorator<\n K extends string = string,\n D extends Record<string, DepValue> = Record<string, never>,\n P extends Record<string, unknown> = Record<string, never>,\n Ctx extends ExecutionContext = ExecutionContext,\n PD = Partial<P>,\n> = [MissingParamKeys<P, PD>] extends [never]\n ? ContextDecoratorWithDefaults<K, D, P, Ctx>\n : ContextDecoratorRequiringParams<K, D, P, Ctx, PD>\n\n/**\n * Decorator whose params are fully defaulted (or which takes none).\n * Callable as a class or method decorator directly, as a factory, or\n * via `.with(params)` / `.registration` at non-decorator registration\n * sites.\n */\nexport interface ContextDecoratorWithDefaults<\n K extends string = string,\n D extends Record<string, DepValue> = Record<string, never>,\n P extends Record<string, unknown> = Record<string, never>,\n Ctx extends ExecutionContext = ExecutionContext,\n> {\n /**\n * Class decorator usage with `paramDefaults` — `@Foo class C {}`.\n * The class constructor is a `Function`, so this overload only\n * matches actual classes (not plain object literals — which\n * fall through to the factory overload below).\n */\n // eslint-disable-next-line @typescript-eslint/no-unsafe-function-type\n (target: Function): void\n /**\n * Method decorator usage with `paramDefaults` — `@Foo` over a\n * method. The required `propertyKey` distinguishes this from the\n * factory overload's single-object-arg call shape.\n */\n (target: object, propertyKey: string | symbol, descriptor?: PropertyDescriptor): void\n /**\n * Zero-arg factory usage — `@Foo()` returns a decorator with\n * `paramDefaults` applied. Equivalent in behaviour to the bare\n * `@Foo` form, exposed here so adopters who prefer \"always call the\n * factory\" don't need an `as any` cast.\n */\n (): ContextDecoratorTarget\n /**\n * Factory usage — `@Foo({ ... })` returns the actual decorator with\n * call-site params merged onto `paramDefaults`. Matches a single\n * params object; plain objects don't satisfy the `Function` /\n * 2-arg-minimum constraints above, so TS picks this overload.\n *\n * Accepts `Partial<P>` so adopters can override only the fields\n * they care about — anything missing falls back to `paramDefaults`\n * at runtime. Inside `resolve()`, `params` is the fully merged\n * `P`, never a `Partial<P>`.\n *\n * The returned decorator is overloaded for class AND method usage —\n * `@Foo({...}) class C {}` and `@Foo({...}) m() {}` both type-check.\n */\n (params: Partial<P>): ContextDecoratorTarget\n /**\n * Bare registration — uses `paramDefaults` only. Use this at non-\n * decorator registration sites (module / adapter / bootstrap) when\n * the call site doesn't need to override params.\n */\n readonly registration: ContributorRegistration<K, D, Ctx>\n /**\n * Build a registration with call-site params merged onto\n * `paramDefaults`. Use this at non-decorator registration sites\n * when the call site DOES want to override params:\n *\n * ```ts\n * bootstrap({\n * contributors: [LoadTenant.with({ source: 'subdomain' }).registration],\n * })\n * ```\n *\n * `Partial<P>` for the same reason as the factory overload — the\n * runtime merges with `paramDefaults`, so adopters only specify\n * fields they want to override.\n */\n with(params: Partial<P>): { readonly registration: ContributorRegistration<K, D, Ctx> }\n}\n\n/**\n * Decorator with at least one required param that `paramDefaults`\n * doesn't cover. Deliberately narrower than\n * {@link ContextDecoratorWithDefaults}: the bare `@Foo` form, the\n * zero-arg `@Foo()` form, and the `.registration` accessor are all\n * absent, because none of them can supply the missing value.\n *\n * ```ts\n * const OperatorPerm = defineContextDecorator.withParams<{ action: string }>()({\n * key: 'operatorPerm',\n * resolve: (ctx, _deps, { action }) => check(ctx, action),\n * })\n *\n * class Ops {\n * @OperatorPerm // ✗ compile error — `action` missing\n * @Get('/a')\n * a(ctx: RequestContext) {}\n *\n * @OperatorPerm({ action: 'read' }) // ✓\n * @Get('/b')\n * b(ctx: RequestContext) {}\n * }\n * ```\n *\n * If you want the bare form back, give `action` a default in\n * `paramDefaults` — but only when the default is genuinely correct for\n * an undecorated route, which for a permission string it usually isn't.\n */\nexport interface ContextDecoratorRequiringParams<\n K extends string = string,\n D extends Record<string, DepValue> = Record<string, never>,\n P extends Record<string, unknown> = Record<string, never>,\n Ctx extends ExecutionContext = ExecutionContext,\n PD = Partial<P>,\n> {\n /**\n * Factory usage — the only decorator form available here. The\n * argument type carries every required field `paramDefaults` didn't\n * provide, so omitting one is a compile error at this call site.\n */\n (params: CallSiteParams<P, PD>): ContextDecoratorTarget\n /**\n * Build a registration for non-decorator registration sites. Same\n * required-field rule as the factory form.\n */\n with(params: CallSiteParams<P, PD>): {\n readonly registration: ContributorRegistration<K, D, Ctx>\n }\n}\n\n/**\n * Curried params-first helper for {@link defineContextDecorator}.\n *\n * Solves the partial-inference problem: TS generics are positional, so\n * the moment an adopter wants to specify the per-call params shape\n * `P`, they're forced to spell `K` and `D` by hand — losing the\n * automatic `deps` inference that drives the `(ctx, deps, params) =>`\n * resolver signature:\n *\n * ```ts\n * // ❌ Positional generics — must repeat the deps type, and `D` no\n * // longer flows from `spec.deps` into `resolve(ctx, deps, ...)`.\n * defineContextDecorator<'tenant', { repo: typeof TENANT_REPO }, MyParams>({\n * key: 'tenant',\n * deps: { repo: TENANT_REPO },\n * resolve: (ctx, { repo }, params) => ...,\n * })\n *\n * // ✅ Curried form — only `P` is spelled; `K`, `D`, `Ctx` infer.\n * defineContextDecorator.withParams<MyParams>()({\n * key: 'tenant',\n * deps: { repo: TENANT_REPO }, // D inferred\n * resolve: (ctx, { repo }, params) => ..., // deps + params both typed\n * })\n * ```\n *\n * Use this whenever the contributor takes call-site params; use the\n * positional form when there are no params (the common case).\n */\nexport interface DefineContextDecoratorWithParams<P extends Record<string, unknown>> {\n <\n K extends string,\n D extends Record<string, DepValue> = Record<string, never>,\n Ctx extends ExecutionContext = ExecutionContext,\n // Inferred from `spec.paramDefaults`. The `Record<never, never>`\n // default (NOT `Partial<P>`) is what makes an omitted `paramDefaults`\n // mean \"nothing is defaulted\" — so every required field of `P` lands\n // on the call site. `Partial<P>` here would make `keyof PD` cover all\n // of `P` and silently defeat the whole check.\n PD extends Partial<P> = Record<never, never>,\n >(\n spec: ContextDecoratorSpec<K, D, P, Ctx, PD>,\n ): ContextDecorator<K, D, P, Ctx, PD>\n}\n\n/**\n * The public shape of {@link defineContextDecorator}. Combines the\n * original positional-generic call signature with the curried\n * `.withParams<P>()` helper that fixes partial-inference for the\n * parameterised case.\n */\nexport interface DefineContextDecoratorFn {\n <\n K extends string,\n D extends Record<string, DepValue> = Record<string, never>,\n P extends Record<string, unknown> = Record<string, never>,\n Ctx extends ExecutionContext = ExecutionContext,\n PD extends Partial<P> = Record<never, never>,\n >(\n spec: ContextDecoratorSpec<K, D, P, Ctx, PD>,\n ): ContextDecorator<K, D, P, Ctx, PD>\n\n /**\n * Curried entry point. Spell only the per-call params shape `P`;\n * `K`, `D`, and `Ctx` are inferred from the spec passed to the\n * returned function. See {@link DefineContextDecoratorWithParams}\n * for the rationale.\n */\n withParams<P extends Record<string, unknown>>(): DefineContextDecoratorWithParams<P>\n}\n\n/**\n * Define a typed context contributor.\n *\n * The returned function works as a method or class decorator:\n *\n * ```ts\n * const LoadTenant = defineContextDecorator({\n * key: 'tenant',\n * deps: { tenants: TenantsRepo },\n * resolve: (ctx, { tenants }) => tenants.findByHost(ctx.requestId),\n * })\n *\n * @LoadTenant\n * @Get('/me')\n * me(ctx: RequestContext) {\n * ctx.get('tenant') // typed via ContextMeta\n * }\n * ```\n *\n * For non-decorator registration (module/adapter/bootstrap), pass\n * `LoadTenant.registration` into the appropriate contributors list.\n *\n * Boot-time validation: a missing `resolve`, an empty `key`, or a\n * non-array `dependsOn` throws `TypeError` here at definition time\n * (typically module-load) rather than waiting for the first request.\n * See `architecture.md` §20 for the full pipeline plan.\n *\n * **Parameterised contributors:** TS generics are positional, so to\n * specify `P` (the per-call params shape) with this signature you\n * also have to spell `K` and `D` — which loses automatic `deps`\n * inference. Use {@link DefineContextDecoratorFn.withParams} instead:\n * `defineContextDecorator.withParams<MyParams>()(spec)`.\n */\nfunction defineContextDecoratorImpl<\n K extends string,\n D extends Record<string, DepValue> = Record<string, never>,\n P extends Record<string, unknown> = Record<string, never>,\n Ctx extends ExecutionContext = ExecutionContext,\n PD extends Partial<P> = Record<never, never>,\n>(spec: ContextDecoratorSpec<K, D, P, Ctx, PD>): ContextDecorator<K, D, P, Ctx, PD> {\n // ---- Boot-time validation --------------------------------------\n // Surface mistakes the moment `defineContextDecorator` is called\n // (typically module-load time) instead of letting them ride to\n // request time as cryptic ContextMeta misses or container failures.\n // Cheap, ~15 lines, catches a whole class of definition-time bugs.\n if (spec === null || typeof spec !== 'object') {\n throw new TypeError(\n 'defineContextDecorator: spec must be an object literal. ' +\n 'See architecture.md §20.4 for the spec shape.',\n )\n }\n if (typeof spec.key !== 'string' || spec.key.length === 0) {\n const got = typeof spec.key === 'string' ? '\"\"' : typeof spec.key\n throw new TypeError(\n `defineContextDecorator: spec.key must be a non-empty string (got ${got}). ` +\n 'Pick a name that matches a key declared on `ContextMeta` (or one of the framework keys).',\n )\n }\n if (typeof spec.resolve !== 'function') {\n throw new TypeError(\n `defineContextDecorator(${spec.key}): spec.resolve is required and must be a function ` +\n `(got ${typeof spec.resolve}). Each contributor needs a resolver that produces ` +\n `the value to write into ctx.set(${JSON.stringify(spec.key)}, …).`,\n )\n }\n if (spec.onError !== undefined && typeof spec.onError !== 'function') {\n throw new TypeError(\n `defineContextDecorator(${spec.key}): spec.onError must be a function when provided ` +\n `(got ${typeof spec.onError}).`,\n )\n }\n if (spec.dependsOn !== undefined && !Array.isArray(spec.dependsOn)) {\n throw new TypeError(\n `defineContextDecorator(${spec.key}): spec.dependsOn must be an array when provided ` +\n `(got ${typeof spec.dependsOn}).`,\n )\n }\n if (spec.requiredParams !== undefined && !Array.isArray(spec.requiredParams)) {\n throw new TypeError(\n `defineContextDecorator(${spec.key}): spec.requiredParams must be an array when provided ` +\n `(got ${typeof spec.requiredParams}).`,\n )\n }\n if (\n Array.isArray(spec.requiredParams) &&\n spec.requiredParams.some((p) => typeof p !== 'string' || p.length === 0)\n ) {\n throw new TypeError(\n `defineContextDecorator(${spec.key}): spec.requiredParams entries must be non-empty strings.`,\n )\n }\n if (\n Array.isArray(spec.dependsOn) &&\n spec.dependsOn.some((dep) => typeof dep !== 'string' || dep.length === 0)\n ) {\n // TS narrows dependsOn to `readonly ContextMetaKey[]` for typed\n // adopters, but JS callers (and TS callers who erase via `as any`)\n // can still slip through with `[42]` or `['']`. Surface it at\n // definition time as a TypeError instead of riding to first\n // request as a `MissingContributorError` on a phantom key.\n throw new TypeError(\n `defineContextDecorator(${spec.key}): spec.dependsOn entries must be non-empty strings.`,\n )\n }\n\n // Source-location capture. `new Error().stack` here records the\n // adopter's call site so boot-time errors (cycles, missing deps,\n // duplicate keys) can point at the file that declared the broken\n // decorator. Bad boot errors are why frameworks get abandoned —\n // a single stack frame turns \"what's a 'tenent'?\" into \"edit\n // src/contributors/tenant.ts line 42\".\n const definedAt = new Error().stack\n\n // Snapshot + freeze paramDefaults so callers can't mutate the spec\n // object post-definition and shift the merged params under our feet.\n // Same immutability boundary applied to `deps` and `dependsOn`.\n const defaults = Object.freeze({\n ...(spec.paramDefaults ?? ({} as Partial<P>)),\n }) as Readonly<Partial<P>>\n\n // Shared deps + dependsOn — frozen once and reused across every\n // registration produced by this decorator (one per call site).\n // `Object.freeze` is shallow — the values inside (DI tokens,\n // constructors) are intentionally untouched; freezing them would\n // prevent the container from doing legitimate per-instance\n // bookkeeping.\n //\n // The `({} as D)` cast: `spec.deps` is optional (`deps?: D`), so\n // the fallback to `{}` is required. When `D` defaults to\n // `Record<string, never>`, the cast is sound (`{}` matches). When\n // `D` is non-empty AND adopter omitted `deps`, the cast is unsound\n // — but the runner errors loudly the moment it tries to resolve a\n // missing dep, so the mistake surfaces at first request rather\n // than producing wrong-but-silent behaviour. The alternative\n // (forcing `deps` non-optional in the spec) would break ergonomics\n // for the common zero-deps case.\n const sharedDeps = Object.freeze({ ...(spec.deps ?? ({} as D)) }) as D\n const sharedDependsOn = Object.freeze([...(spec.dependsOn ?? [])])\n const sharedOptional = spec.optional ?? false\n\n /**\n * Build a frozen registration that closes over a specific\n * resolved-params object. The runner sees a normal\n * `(ctx, deps) => value` registration — params are baked into the\n * closure, invisible to the pipeline.\n */\n const buildRegistration = (params: P): ContributorRegistration<K, D, Ctx> => {\n // Shallow-freeze the captured params so a misbehaving `resolve()` /\n // `onError()` can't mutate the closure and bleed into later\n // requests through the same registration. Adopters who really need\n // mutable per-request state should write to `ctx.set(...)` from\n // inside the resolver instead of mutating params.\n const frozenParams = Object.freeze({ ...params }) as P\n const onError: ContributorRegistration<K, D, Ctx>['onError'] = spec.onError\n ? (err: unknown, ctx: Ctx) => spec.onError!(err, ctx, frozenParams)\n : undefined\n const resolve: ContributorRegistration<K, D, Ctx>['resolve'] = (\n ctx: Ctx,\n deps: ResolvedDeps<D>,\n ) => spec.resolve(ctx, deps, frozenParams)\n return Object.freeze({\n key: spec.key,\n deps: sharedDeps,\n dependsOn: sharedDependsOn,\n optional: sharedOptional,\n onError,\n resolve,\n definedAt,\n })\n }\n\n // Default-params registration — used for zero-arg decorator\n // applications and for the `.registration` accessor. Cloning\n // `defaults` so the closure can't be mutated through the spec.\n const defaultRegistration = buildRegistration({ ...defaults } as P)\n\n /**\n * Decide whether the decorator was called as a decorator\n * (`@Foo` / `@Foo(target, key)`) or as a factory\n * (`@Foo()` / `@Foo({...})`).\n *\n * - Class decorator: `(target)` where target is a constructor function.\n * - Method decorator: `(target, propertyKey, descriptor?)` where\n * target is a prototype object and propertyKey is a string/symbol.\n * - Factory (defaults): `()` — adopter wrote `@Foo()` (rare; usually\n * they write the bare `@Foo`). Returns a decorator using\n * `paramDefaults`.\n * - Factory (params): `(params)` where params is a plain object.\n *\n * The legacy decorators that ship with KickJS (`@Get('/path')`,\n * `@Cron('* * * *')`, etc.) use the same heuristic, so adopters\n * already know to pass plain object literals as factory args.\n */\n const isDecoratorCall = (args: unknown[]): boolean => {\n // Zero args is a factory call (`@Foo()`), not a direct decorator\n // application — TS never invokes a decorator with zero args.\n if (args.length === 0) return false\n if (args.length >= 2) return true\n const first = args[0]\n // Functions are class constructors at decoration time.\n if (typeof first === 'function') return true\n // Anything else (plain object, undefined, primitive) → factory call.\n return false\n }\n\n const applyAsDecorator = (\n registration: ContributorRegistration<K, D, Ctx>,\n target: object,\n propertyKey?: string | symbol,\n ): void => {\n if (propertyKey === undefined) {\n // Class decorator — `target` is the constructor.\n pushClassMeta(METADATA.CLASS_CONTRIBUTORS, target, registration)\n } else {\n // Method decorator — `target` is the prototype; we write to its\n // constructor so reads can use the controller class as the\n // lookup key, matching the convention used by @Middleware and\n // consumed by router-builder.ts.\n const constructor = (target as { constructor: object }).constructor\n pushMethodMeta(METADATA.METHOD_CONTRIBUTORS, constructor, String(propertyKey), registration)\n }\n }\n\n /**\n * `true` for `{...}` and `Object.create(null)`. Rejects every\n * built-in subclass (Map / Set / Date / Error / RegExp / Promise),\n * adopter classes, and arrays.\n */\n const isPlainObject = (value: object): boolean => {\n const proto = Object.getPrototypeOf(value)\n return proto === Object.prototype || proto === null\n }\n\n /**\n * Merge call-site `Partial<P>` over `paramDefaults`. Strict guard:\n * accepts only **plain object literals** (or `Object.create(null)`).\n * Reject everything else with a descriptive `TypeError`.\n *\n * Why strict? Object spread copies enumerable own properties only.\n * `{ ...new Date() }` and `{ ...new Map([...])}` both produce `{}`\n * — the params silently drop. Catching this at the boundary\n * surfaces the mistake instead of routing the request with empty\n * config. Adopters who genuinely need a class-instance shape can\n * destructure it themselves: `Foo({ ...new MyParams() })`.\n */\n const mergeParams = (override: unknown): P => {\n if (override === undefined) return { ...defaults } as P\n if (\n override === null ||\n typeof override !== 'object' ||\n Array.isArray(override) ||\n !isPlainObject(override)\n ) {\n const got =\n override === null\n ? 'null'\n : Array.isArray(override)\n ? 'array'\n : typeof override === 'object'\n ? `instance of ${(override as object).constructor?.name ?? 'unknown class'}`\n : typeof override\n throw new TypeError(\n `defineContextDecorator(${spec.key}): factory call requires a plain object literal, got ${got}. ` +\n `Class instances and built-ins (Map, Date, etc) silently spread to empty objects — ` +\n `call the decorator with a spread object literal instead, e.g. ` +\n `\\`MyDecorator({ ...someInstance })\\`.`,\n )\n }\n return { ...defaults, ...(override as Partial<P>) } as P\n }\n\n const sharedRequiredParams = Object.freeze([...(spec.requiredParams ?? [])])\n\n /**\n * Runtime half of the required-params guarantee. The type system\n * already stops TS call sites from omitting a required field, so this\n * catches what types can't see: plain-JS adopters, `as any`, and\n * params built dynamically.\n *\n * `usage` names the form that failed so the message points at the fix\n * — a bare `@Foo` on a decorator with required params needs to become\n * `@Foo({ ... })`, which is a different edit from a factory call that\n * merely forgot one field.\n */\n const assertRequiredParams = (params: P, usage: string): void => {\n if (sharedRequiredParams.length === 0) return\n const missing = sharedRequiredParams.filter(\n (name) => (params as Record<string, unknown>)[name] === undefined,\n )\n if (missing.length === 0) return\n throw new TypeError(\n `defineContextDecorator(${spec.key}): ${usage} is missing required param(s) ` +\n `${missing.map((m) => `'${m}'`).join(', ')}. ` +\n `Supply them at the call site — e.g. \\`@${spec.key}({ ${missing[0]}: … })\\` — or ` +\n `add a default in \\`paramDefaults\\` if one is genuinely correct for every route.`,\n )\n }\n\n // Overloaded function signatures so `decoratorOrFactory`'s type\n // matches `ContextDecorator`'s call shapes directly — no\n // `as unknown as` double-cast needed. The implementation signature\n // (`...args: unknown[]`) is hidden from callers; only the four\n // declared overloads are reachable.\n // eslint-disable-next-line @typescript-eslint/no-unsafe-function-type\n function decoratorOrFactory(target: Function): void\n function decoratorOrFactory(\n target: object,\n propertyKey: string | symbol,\n descriptor?: PropertyDescriptor,\n ): void\n function decoratorOrFactory(): ContextDecoratorTarget\n function decoratorOrFactory(params: Partial<P>): ContextDecoratorTarget\n function decoratorOrFactory(...args: unknown[]): unknown {\n if (isDecoratorCall(args)) {\n const [target, propertyKey] = args as [\n object,\n string | symbol | undefined,\n PropertyDescriptor?,\n ]\n // Bare `@Foo` — nothing can supply params here, so a required one\n // that isn't defaulted is a decoration-time (module-load) failure\n // rather than an undefined riding into the resolver.\n assertRequiredParams({ ...defaults } as P, 'bare `@decorator` usage')\n applyAsDecorator(defaultRegistration, target, propertyKey)\n return undefined\n }\n // Factory call — capture merged params and return a decorator.\n const params = mergeParams(args[0])\n assertRequiredParams(params, 'factory call')\n const registration = buildRegistration(params)\n return (target: object, propertyKey?: string | symbol) => {\n applyAsDecorator(registration, target, propertyKey)\n }\n }\n\n // Set a meaningful `.name` so `console.log(LoadTenant)` and stack\n // traces show `[Function: ContextDecorator(tenant)]` instead of\n // `[Function: decoratorOrFactory]`. Function.name is configurable\n // by default, so this works on the existing function reference.\n Object.defineProperty(decoratorOrFactory, 'name', {\n value: `ContextDecorator(${spec.key})`,\n writable: false,\n enumerable: false,\n configurable: true,\n })\n\n // `Object.assign` returns the intersection type, so the decorator\n // gets `.registration` + `.with` properties typed without the\n // previous `as unknown as ContextDecorator<...>` double cast.\n // Properties go on via assign (writable + enumerable defaults),\n // then `Object.freeze` locks the shape so adopters can't mutate\n // `decorator.registration = …` post-construction.\n const decorator = Object.assign(decoratorOrFactory, {\n with: (params: Partial<P>) => {\n const merged = mergeParams(params)\n assertRequiredParams(merged, '`.with()`')\n return { registration: buildRegistration(merged) }\n },\n })\n\n // `.registration` is a getter, not a plain property, so that reading it\n // on a decorator with undefaulted required params throws instead of\n // handing back a registration whose resolver will see `undefined`.\n // (`Object.assign` would have copied the value and lost the check.)\n Object.defineProperty(decorator, 'registration', {\n get() {\n assertRequiredParams({ ...defaults } as P, '`.registration`')\n return defaultRegistration\n },\n enumerable: true,\n configurable: false,\n })\n\n // `ContextDecorator` is a conditional type (permissive vs required-params\n // shape), and TS can't evaluate a conditional whose input generics are\n // still unresolved — so the assignment can't be checked structurally\n // here regardless of how `decorator` is built. The cast is the price of\n // the call-site guarantee; the two branches differ only in which call\n // forms they expose, and every one of them is implemented above.\n return Object.freeze(decorator) as unknown as ContextDecorator<K, D, P, Ctx, PD>\n}\n\n/**\n * Public export — the positional-generic implementation plus the\n * curried `.withParams<P>()` helper attached as a method. Adopters\n * pick whichever form fits the call site:\n *\n * - **Positional** — `defineContextDecorator(spec)` when there are\n * no per-call params (the common case). `K`, `D`, `Ctx` infer.\n * - **Curried** — `defineContextDecorator.withParams<P>()(spec)`\n * when the contributor takes params; spell only `P`, the rest\n * still infer.\n *\n * Frozen so adopters can't reassign `.withParams` at runtime.\n */\nexport const defineContextDecorator: DefineContextDecoratorFn = Object.freeze(\n Object.assign(defineContextDecoratorImpl, {\n withParams: <P extends Record<string, unknown>>(): DefineContextDecoratorWithParams<P> => {\n return <\n K extends string,\n D extends Record<string, DepValue> = Record<string, never>,\n Ctx extends ExecutionContext = ExecutionContext,\n PD extends Partial<P> = Record<never, never>,\n >(\n spec: ContextDecoratorSpec<K, D, P, Ctx, PD>,\n ): ContextDecorator<K, D, P, Ctx, PD> => defineContextDecoratorImpl<K, D, P, Ctx, PD>(spec)\n },\n }),\n) as DefineContextDecoratorFn\n","/**\n * Topological sort for plugins and adapters with `dependsOn` declarations.\n *\n * Mirrors the algorithm used by the Context Contributor pipeline\n * (`contributor-pipeline.ts:topoSort`) but operates on a name-keyed\n * `MountSortItem` shape rather than a `ContributorRegistration`. Kept\n * standalone instead of factored generic so that:\n *\n * 1. The contributor pipeline doesn't need refactoring (risk reduction).\n * 2. The error classes can carry plugin/adapter-specific diagnostic\n * fields (`kind`, `dependent`) without bending the contributor types.\n */\n\n/**\n * A plugin or adapter that participates in dependency-ordered mounting.\n * Both `KickPlugin` and `AppAdapter` satisfy this shape via their `name`\n * and `dependsOn` fields.\n */\nexport interface MountSortItem {\n /** Unique mount name within the plugin/adapter set being sorted. */\n name: string\n /**\n * Other plugin/adapter names that must mount before this one. Cycles\n * and missing names fail at boot — same fail-fast contract as the\n * Context Contributor pipeline (architecture.md §20.4).\n */\n dependsOn?: readonly string[]\n}\n\n/** What kind of mount set the sort is operating on — surfaces in error messages. */\nexport type MountKind = 'plugin' | 'adapter'\n\n/**\n * Two items in the same mount set declared the same `name`. Plugin/adapter\n * names must be unique so `dependsOn` references resolve unambiguously.\n */\nexport class DuplicateMountNameError extends Error {\n readonly kind: MountKind\n readonly mountName: string\n\n constructor(kind: MountKind, mountName: string) {\n super(`Duplicate ${kind} name '${mountName}' — every ${kind} must declare a unique name`)\n this.name = 'DuplicateMountNameError'\n this.kind = kind\n this.mountName = mountName\n }\n}\n\n/**\n * A `dependsOn` entry references a plugin/adapter that isn't in the\n * current set. The dependency might not be installed, might be misspelled,\n * or might live in a different mount set (plugin referencing an adapter,\n * or vice versa — they sort independently).\n */\nexport class MissingMountDepError extends Error {\n readonly kind: MountKind\n readonly missing: string\n readonly dependent: string\n\n constructor(kind: MountKind, missing: string, dependent: string) {\n super(\n `Missing ${kind} dependency '${missing}' required by '${dependent}' — ` +\n `is the ${kind} installed and named correctly?`,\n )\n this.name = 'MissingMountDepError'\n this.kind = kind\n this.missing = missing\n this.dependent = dependent\n }\n}\n\n/**\n * The `dependsOn` declarations form a cycle. Boot fails so the cycle\n * can't poison live traffic. The `cycle` field reports one path through\n * the offending nodes for diagnostics — formatted `A → B → C → A`.\n */\nexport class MountCycleError extends Error {\n readonly kind: MountKind\n readonly cycle: readonly string[]\n\n constructor(kind: MountKind, cycle: readonly string[]) {\n super(`Cycle in ${kind} dependsOn declarations: ${cycle.join(' → ')}`)\n this.name = 'MountCycleError'\n this.kind = kind\n this.cycle = Object.freeze([...cycle])\n }\n}\n\n/**\n * Topologically sort `items` so every item with `dependsOn: ['X']` mounts\n * after `X`. Items without `dependsOn` keep their input order via Kahn's\n * algorithm with a FIFO queue seeded in input order — preserves the\n * historical \"plugins/adapters mount in declaration order\" behaviour for\n * any set that doesn't use `dependsOn`.\n *\n * @param items - mountable items, e.g. plugins or adapters\n * @param kind - 'plugin' | 'adapter', used in error messages\n * @returns a new array in valid mount order\n * @throws {DuplicateMountNameError} two items share a name\n * @throws {MissingMountDepError} a `dependsOn` references an unknown name\n * @throws {MountCycleError} the dep graph contains a cycle\n */\nexport function mountSort<T extends MountSortItem>(items: readonly T[], kind: MountKind): T[] {\n const byName = new Map<string, T>()\n for (const item of items) {\n if (byName.has(item.name)) {\n throw new DuplicateMountNameError(kind, item.name)\n }\n byName.set(item.name, item)\n }\n\n // indegree[name] = number of unresolved deps for that item\n const indegree = new Map<string, number>()\n // dependents[depName] = items that depend on depName\n const dependents = new Map<string, T[]>()\n\n for (const item of items) {\n indegree.set(item.name, item.dependsOn?.length ?? 0)\n }\n for (const item of items) {\n for (const dep of item.dependsOn ?? []) {\n if (!byName.has(dep)) {\n throw new MissingMountDepError(kind, dep, item.name)\n }\n const list = dependents.get(dep) ?? []\n list.push(item)\n dependents.set(dep, list)\n }\n }\n\n // Initial queue: items with zero indegree, preserving input order.\n const queue: T[] = []\n for (const item of items) {\n if (indegree.get(item.name) === 0) queue.push(item)\n }\n\n const sorted: T[] = []\n while (queue.length > 0) {\n const node = queue.shift()!\n sorted.push(node)\n for (const dependent of dependents.get(node.name) ?? []) {\n const next = (indegree.get(dependent.name) ?? 0) - 1\n indegree.set(dependent.name, next)\n if (next === 0) queue.push(dependent)\n }\n }\n\n if (sorted.length !== items.length) {\n const remaining = items.filter((it) => (indegree.get(it.name) ?? 0) > 0)\n throw new MountCycleError(kind, reconstructCycle(remaining, byName))\n }\n\n return sorted\n}\n\n/**\n * Walk the residual graph to find one cycle path for diagnostics.\n * Starts from the first remaining node and follows the first dep that's\n * still in the residual set until we revisit a node. Returns a path\n * starting and ending with the same name so the message reads naturally\n * (`A → B → C → A`).\n */\nfunction reconstructCycle<T extends MountSortItem>(\n residual: readonly T[],\n byName: ReadonlyMap<string, T>,\n): string[] {\n const residualNames = new Set(residual.map((r) => r.name))\n const start = residual[0].name\n const path: string[] = [start]\n const seen = new Set<string>([start])\n let cursor = start\n\n while (true) {\n const item = byName.get(cursor)!\n const nextDep = item.dependsOn?.find((d) => residualNames.has(d))\n if (nextDep === undefined) break\n if (seen.has(nextDep)) {\n const cycleStart = path.indexOf(nextDep)\n return [...path.slice(cycleStart), nextDep]\n }\n path.push(nextDep)\n seen.add(nextDep)\n cursor = nextDep\n }\n\n return path\n}\n","import type { Container } from './container'\nimport type { KickPlugin } from './plugin'\n\n/**\n * Options passed to {@link definePlugin}. Mirrors the spec in\n * `architecture.md` §21.3.1 + §21.2.2 (Phase A \"lite\").\n */\nexport interface DefinePluginOptions<TConfig> {\n /** Stable identity used for logging, `dependsOn` lookups, and `.scoped()` namespacing. */\n name: string\n\n /** Optional plugin version — surfaced to DevTools and `kick add` compatibility checks (Phase B). */\n version?: string\n\n /**\n * Peer-version ranges this plugin needs from the framework or other\n * plugins. Recorded as metadata; runtime enforcement lands in §21.4.4.\n */\n requires?: { kickjs?: string }\n\n /** Default config merged under any caller overrides. */\n defaults?: Partial<TConfig>\n\n /** Builds the underlying {@link KickPlugin} from the resolved config. */\n build(config: TConfig, ctx: BuildContext): Omit<KickPlugin, 'name'>\n}\n\n/**\n * Hook context handed to a plugin/adapter `build` function. `name` is the\n * resolved instance name (the bare definition name for the bare call,\n * or `${defName}:${scope}` for `.scoped()`). `scoped` is the discriminator\n * authors use to namespace DI tokens or resource keys.\n */\nexport interface BuildContext {\n name: string\n scoped: boolean\n}\n\n/**\n * Async-config form of a plugin or adapter — `inject` lists DI tokens to\n * resolve from the container, then `useFactory` produces the config.\n *\n * Plugins resolve this lazily inside `onReady`, so any module/adapter/\n * middleware/contributor a plugin contributes via `build` is **not\n * available** when `.async()` is used. Use the bare/`.scoped()` form for\n * plugins that need to register modules or middleware.\n */\nexport interface PluginAsyncOptions<TConfig> {\n inject?: ReadonlyArray<unknown>\n useFactory(...deps: any[]): TConfig | Promise<TConfig>\n}\n\n/**\n * Factory returned by {@link definePlugin}. Callable form is the singleton\n * (`AuthPlugin(config)`); `.scoped()` and `.async()` are the multi-instance\n * and deferred-config forms.\n */\nexport interface PluginFactory<TConfig> {\n (config?: Partial<TConfig>): KickPlugin\n scoped(scopeName: string, config?: Partial<TConfig>): KickPlugin\n async(opts: PluginAsyncOptions<TConfig>): KickPlugin\n /** Read-only access to the original definition — useful for DevTools introspection. */\n readonly definition: Readonly<DefinePluginOptions<TConfig>>\n}\n\nconst mergeConfig = <TConfig>(\n defaults: Partial<TConfig> = {},\n overrides: Partial<TConfig> = {},\n): TConfig => ({ ...defaults, ...overrides }) as TConfig\n\nconst composeName = (base: string, scope: string): string => `${base}:${scope}`\n\n/**\n * Build a {@link KickPlugin} factory from a typed definition. See\n * `architecture.md` §21.2.2 for the design rationale.\n *\n * @example\n * ```ts\n * const FlagsPlugin = definePlugin<FlagsConfig>({\n * name: 'FlagsPlugin',\n * defaults: { defaultTtl: 60_000 },\n * build(config) {\n * return {\n * register(container) {\n * container.registerInstance(FLAGS, makeProvider(config))\n * },\n * }\n * },\n * })\n *\n * bootstrap({ plugins: [FlagsPlugin({ provider: launchDarkly })] })\n * ```\n */\nexport function definePlugin<TConfig = Record<string, unknown>>(\n options: DefinePluginOptions<TConfig>,\n): PluginFactory<TConfig> {\n const buildSync = (\n instanceName: string,\n scoped: boolean,\n overrides?: Partial<TConfig>,\n ): KickPlugin => {\n const config = mergeConfig(options.defaults, overrides)\n // Mutate `name` on the build result instead of spreading — spread\n // strips prototype methods when `build()` returns a class instance.\n const built = options.build(config, { name: instanceName, scoped }) as KickPlugin\n built.name = instanceName\n return built\n }\n\n const buildAsync = (instanceName: string, opts: PluginAsyncOptions<TConfig>): KickPlugin => {\n let inner: KickPlugin | undefined\n\n const ensureInner = async (container: Container): Promise<KickPlugin> => {\n if (inner) return inner\n const deps = (opts.inject ?? []).map((tok) => container.resolve(tok as never))\n const config = await opts.useFactory(...deps)\n inner = buildSync(instanceName, false, config as Partial<TConfig>)\n return inner\n }\n\n return {\n name: instanceName,\n async onReady(container: Container) {\n const built = await ensureInner(container)\n // Run the inner plugin's register() now that we have the config —\n // late but better than never; `.async()` plugins skip the early\n // module/middleware contribution surface by design.\n built.register?.(container)\n await built.onReady?.(container)\n },\n async shutdown() {\n await inner?.shutdown?.()\n },\n }\n }\n\n const factory = ((config?: Partial<TConfig>) =>\n buildSync(options.name, false, config)) as PluginFactory<TConfig>\n\n factory.scoped = (scopeName: string, config?: Partial<TConfig>) =>\n buildSync(composeName(options.name, scopeName), true, config)\n\n factory.async = (opts: PluginAsyncOptions<TConfig>) => buildAsync(options.name, opts)\n\n Object.defineProperty(factory, 'definition', { value: Object.freeze({ ...options }) })\n\n return factory\n}\n","import type { AppAdapter, AdapterContext } from './adapter'\nimport type { BuildContext } from './define-plugin'\n\n/**\n * Options passed to {@link defineAdapter}. Mirrors {@link DefinePluginOptions}\n * exactly — see `architecture.md` §21.3.4 for the definePlugin/defineAdapter\n * symmetry rationale.\n *\n * The optional `TExtra` generic lets an adapter ship public methods\n * beyond the standard {@link AppAdapter} contract — they're preserved\n * on the returned adapter instance so external callers (tests, peer\n * adapters) can invoke them directly. See `OtelAdapter.applyRedaction`\n * for the canonical use case.\n */\nexport interface DefineAdapterOptions<TConfig, TExtra = unknown> {\n /**\n * Stable identity used for logging, `dependsOn` lookups, and `.scoped()`\n * namespacing. Required for adapters that participate in `dependsOn`\n * sort — error messages reference adapters by name.\n */\n name: string\n version?: string\n requires?: { kickjs?: string }\n defaults?: Partial<TConfig>\n build(config: TConfig, ctx: BuildContext): Omit<AppAdapter, 'name'> & TExtra\n}\n\n/**\n * Async-config form of an adapter. Identical shape to `PluginAsyncOptions`\n * but resolved during `beforeStart` (the earliest async hook in\n * `AppAdapter`) — meaning `middleware()` and `contributors()` from the inner\n * adapter are **not** picked up. Use the bare/`.scoped()` form when you need\n * those.\n */\nexport interface AdapterAsyncOptions<TConfig> {\n inject?: ReadonlyArray<unknown>\n useFactory(...deps: any[]): TConfig | Promise<TConfig>\n}\n\n/**\n * Factory returned by {@link defineAdapter}. Same surface as\n * {@link PluginFactory} (call / `.scoped()` / `.async()`) so adopters learn\n * one mental model for both primitives. Returned instances carry both\n * the standard {@link AppAdapter} contract and any `TExtra` extension\n * methods the `build` function exposed.\n */\nexport interface AdapterFactory<TConfig, TExtra = unknown> {\n (config?: Partial<TConfig>): AppAdapter & TExtra\n scoped(scopeName: string, config?: Partial<TConfig>): AppAdapter & TExtra\n async(opts: AdapterAsyncOptions<TConfig>): AppAdapter\n readonly definition: Readonly<DefineAdapterOptions<TConfig, TExtra>>\n}\n\nconst mergeConfig = <TConfig>(\n defaults: Partial<TConfig> = {},\n overrides: Partial<TConfig> = {},\n): TConfig => ({ ...defaults, ...overrides }) as TConfig\n\nconst composeName = (base: string, scope: string): string => `${base}:${scope}`\n\n/**\n * Build an {@link AppAdapter} factory from a typed definition. See\n * `architecture.md` §21.3.4 for migration guidance — most first-party\n * adapter packages collapse to a single `defineAdapter()` call after this\n * lands.\n *\n * @example\n * ```ts\n * const TenantAdapter = defineAdapter<TenantConfig>({\n * name: 'TenantAdapter',\n * defaults: { strategy: 'header', required: true },\n * build: (config) => ({\n * middleware: () => [tenantResolverMiddleware(config)],\n * beforeStart: ({ container }) => registerTenantFactory(container, config),\n * }),\n * })\n *\n * bootstrap({\n * adapters: [\n * TenantAdapter({ strategy: 'subdomain' }),\n * TenantAdapter.scoped('shard-eu', { headerName: 'x-eu-tenant' }),\n * ],\n * })\n * ```\n */\nexport function defineAdapter<TConfig = Record<string, unknown>, TExtra = unknown>(\n options: DefineAdapterOptions<TConfig, TExtra>,\n): AdapterFactory<TConfig, TExtra> {\n const buildSync = (\n instanceName: string,\n scoped: boolean,\n overrides?: Partial<TConfig>,\n ): AppAdapter & TExtra => {\n const config = mergeConfig(options.defaults, overrides)\n // Mutate `name` on the build result instead of spreading — spread\n // strips prototype methods when `build()` returns a class instance.\n // Extension methods declared by the build function (`TExtra`) survive\n // the mutation since they're own properties on the build result.\n const built = options.build(config, { name: instanceName, scoped }) as AppAdapter & TExtra\n ;(built as AppAdapter).name = instanceName\n return built\n }\n\n const buildAsync = (instanceName: string, opts: AdapterAsyncOptions<TConfig>): AppAdapter => {\n let inner: AppAdapter | undefined\n\n return {\n name: instanceName,\n async beforeStart(ctx: AdapterContext) {\n const deps = (opts.inject ?? []).map((tok) => ctx.container.resolve(tok as never))\n const config = await opts.useFactory(...deps)\n inner = buildSync(instanceName, false, config as Partial<TConfig>)\n await inner.beforeStart?.(ctx)\n },\n async afterStart(ctx: AdapterContext) {\n await inner?.afterStart?.(ctx)\n },\n async shutdown() {\n await inner?.shutdown?.()\n },\n async onHealthCheck() {\n return (await inner?.onHealthCheck?.()) ?? { name: instanceName, status: 'up' }\n },\n }\n }\n\n const factory = ((config?: Partial<TConfig>) =>\n buildSync(options.name, false, config)) as AdapterFactory<TConfig, TExtra>\n\n factory.scoped = (scopeName: string, config?: Partial<TConfig>) =>\n buildSync(composeName(options.name, scopeName), true, config)\n\n factory.async = (opts: AdapterAsyncOptions<TConfig>) => buildAsync(options.name, opts)\n\n Object.defineProperty(factory, 'definition', { value: Object.freeze({ ...options }) })\n\n return factory\n}\n","/**\n * Augmentation registry — runtime no-op + the canonical\n * `KickJsPluginRegistry` interface that `kick typegen` augments.\n *\n * See `architecture.md` §21.2.1 (typegen for `dependsOn`) and §21.3.3\n * (standardized augmentation registry) for the design rationale.\n *\n * @module @forinda/kickjs/core/augmentation\n */\n\n/**\n * Marker interface that lists every plugin/adapter in the project. The\n * keys are the literal `name` field passed to `defineAdapter` /\n * `definePlugin` (or declared on a `class implements AppAdapter`); the\n * values are the kind tag (`'plugin' | 'adapter'`).\n *\n * The framework ships this empty. `kick typegen` augments it from\n * source so `keyof KickJsPluginRegistry` resolves to a string-literal\n * union of every name in scope — and therefore so do `dependsOn`\n * declarations on plugins/adapters.\n */\nexport interface KickJsPluginRegistry {}\n\n/**\n * Resolves to a string-literal union of every registered plugin/adapter\n * name when the project's typegen has populated `KickJsPluginRegistry`,\n * or to `string` when the registry is empty (no typegen pass yet).\n *\n * Falling back to `string` keeps fresh projects compiling — the typegen\n * narrowing is a progressive enhancement, not a hard prerequisite.\n */\nexport type KickJsPluginName = keyof KickJsPluginRegistry extends never\n ? string\n : keyof KickJsPluginRegistry & string\n\n/**\n * Metadata attached to a `defineAugmentation` call. The fields are\n * documentation-only — `kick typegen` surfaces them in the generated\n * `.kickjs/types/augmentations.d.ts` so adopters can browse every\n * augmentable interface from one place.\n *\n * `description` and `example` may both be multi-line — typegen preserves\n * line breaks when rendering them as JSDoc. There is no upper limit on\n * the example size; entire shape definitions or worked snippets are fine.\n */\nexport interface AugmentationMeta {\n /**\n * Free-form description of what the augmentation customises. May be\n * multi-line — newlines are preserved in the generated JSDoc.\n */\n description?: string\n /**\n * TS snippet showing a typical shape. May be multi-line; rendered\n * inside a fenced code block in the generated catalogue. Use this\n * for anything from `'{ foo: string }'` up to a full interface body\n * — typegen no longer flattens newlines.\n */\n example?: string\n}\n\n/**\n * Advertise an augmentable interface so `kick typegen` can list it in\n * `.kickjs/types/augmentations.d.ts` for project-wide discovery.\n *\n * **This function is a runtime AND type-level no-op.** It does NOT\n * augment the interface for TypeScript. The actual augmentation is\n * the `declare module` block — `defineAugmentation` only adds an\n * entry to the typegen catalogue so other contributors / adopters\n * can find the interface and know its expected shape.\n *\n * Both calls are needed:\n *\n * ```ts\n * import { defineAugmentation } from '@forinda/kickjs'\n *\n * // (1) The actual TS augmentation — what `ctx.get('tenant')` reads.\n * declare module '@forinda/kickjs' {\n * interface ContextMeta {\n * tenant: { id: string; name: string }\n * }\n * }\n *\n * // (2) Catalogue entry — what `kick typegen` lists in\n * // `.kickjs/types/augmentations.d.ts` for browseability.\n * defineAugmentation('ContextMeta', {\n * description: 'Tenant resolved from x-tenant-id by TenantAdapter',\n * example: `{\n * tenant: {\n * id: string\n * name: string\n * plan: 'free' | 'pro' | 'enterprise'\n * featureFlags: Record<string, boolean>\n * }\n * }`,\n * })\n * ```\n *\n * Skip `defineAugmentation` if you don't care about the catalogue — the\n * `declare module` block alone is enough for runtime + type behaviour.\n *\n * @deprecated Low value in practice: it does nothing at runtime or at\n * the type level — the `declare module` block alone gives you the\n * augmentation, and the generated `.kickjs/types/kick__augmentations.d.ts`\n * catalogue it feeds is documentation-only. Prefer a plain\n * `declare module '@forinda/kickjs' { ... }` block and (optionally) a\n * JSDoc comment on your own interface. `defineAugmentation` and the\n * `kick/augmentations` typegen plugin will be removed in a future major.\n */\nexport function defineAugmentation(name: string, meta?: AugmentationMeta): void {\n // No-op at runtime — `kick typegen` discovers the call statically and\n // emits the augmentation catalogue. Touch the args so esbuild / tsc\n // don't drop the call as dead code under aggressive minification\n // (the marker has to survive the build for static scanners that look\n // at compiled output, e.g. third-party tools).\n void name\n void meta\n}\n","// Shared asset-key strategy — used by the build pipeline, the\n// runtime dev resolver, and the typegen emitter so all three layers\n// agree on what the manifest looks like.\n//\n// Three strategies:\n//\n// - `'strip'` — drop the final extension. `pages/index.pug` →\n// `pages/index`. Best for namespaces where every basename is\n// unique (mail templates, pdf invoices). Shortest autocomplete.\n//\n// - `'with-extension'` — keep the extension. `pages/index.pug` →\n// `pages/index.pug`. Required when extension siblings coexist.\n//\n// - `'auto'` (default) — strip when safe, keep extensions when not.\n// The grouping pass collects files by stripped basename; groups\n// of one keep the stripped key, groups of more than one keep the\n// full path. Backward compatible for projects with no\n// extension-siblings; lossless for projects that have them.\n//\n// The function returns the path / key pairs in walk order (input\n// order preserved) so callers can iterate without re-sorting. Sort\n// in the caller if a stable manifest order is needed.\n\nexport type AssetKeyStrategy = 'auto' | 'strip' | 'with-extension'\n\nexport interface AssetKeyPair {\n /** Source-relative path the file was discovered at. */\n rel: string\n /** Final logical key for the manifest, including the namespace prefix. */\n key: string\n}\n\nexport interface GroupAssetKeysOptions {\n /**\n * Strategy applied to this namespace. Default `'auto'`.\n *\n * Adopters override per-namespace via `assetMap.<ns>.keys` in\n * kick.config.ts when they want uniform behaviour (e.g. always\n * include the extension regardless of collisions).\n */\n strategy?: AssetKeyStrategy\n}\n\nexport interface GroupAssetKeysResult {\n pairs: AssetKeyPair[]\n /**\n * Number of collision groups resolved by keeping extensions.\n * Surfaces as an informational log (\"auto-resolved N collisions\")\n * so adopters know whether they're relying on auto-mode or not.\n * Always 0 for `'strip'` (overwrites) and `'with-extension'`\n * (extensions always preserved, no collision possible).\n */\n collisionGroupsResolved: number\n}\n\n/**\n * Compute final manifest keys for a namespace's discovered paths,\n * given the chosen strategy. Pure function — no fs / config / globals\n * involved.\n *\n * @param namespace assetMap key — e.g. `'mails'`, `'pages'`.\n * @param paths source-relative file paths (POSIX separators) discovered\n * under the namespace's `src` directory.\n * @param opts grouping options.\n */\nexport function groupAssetKeys(\n namespace: string,\n paths: readonly string[],\n opts: GroupAssetKeysOptions = {},\n): GroupAssetKeysResult {\n const strategy = opts.strategy ?? 'auto'\n\n if (strategy === 'with-extension') {\n return {\n pairs: paths.map((rel) => ({ rel, key: `${namespace}/${rel}` })),\n collisionGroupsResolved: 0,\n }\n }\n\n if (strategy === 'strip') {\n // Strict strip — last-walk-order wins on collision; no\n // collision tracking here because the docs document this as the\n // adopter's choice. The caller (build / runtime / typegen) can\n // still warn if it wants; this function just shapes keys.\n return {\n pairs: paths.map((rel) => ({ rel, key: `${namespace}/${stripExt(rel)}` })),\n collisionGroupsResolved: 0,\n }\n }\n\n // strategy === 'auto' — group by stripped basename, keep\n // extensions only on collision groups.\n const groups = new Map<string, string[]>()\n for (const rel of paths) {\n const strippedKey = `${namespace}/${stripExt(rel)}`\n const arr = groups.get(strippedKey)\n if (arr) {\n arr.push(rel)\n } else {\n groups.set(strippedKey, [rel])\n }\n }\n\n let collisionGroupsResolved = 0\n // Build a per-rel decision table so we preserve input ordering in\n // the output (manifest writers rely on stable ordering).\n const keyByRel = new Map<string, string>()\n for (const [strippedKey, rels] of groups) {\n if (rels.length === 1) {\n keyByRel.set(rels[0], strippedKey)\n } else {\n collisionGroupsResolved += 1\n for (const rel of rels) {\n keyByRel.set(rel, `${namespace}/${rel}`)\n }\n }\n }\n\n return {\n pairs: paths.map((rel) => ({\n rel,\n key: keyByRel.get(rel) ?? `${namespace}/${rel}`,\n })),\n collisionGroupsResolved,\n }\n}\n\n/** Strip the final extension from a path. `'mails/welcome.ejs'` → `'mails/welcome'`. */\nexport function stripExt(path: string): string {\n // Inline the logic instead of importing extname so this module\n // stays usable in pure-browser contexts. Same algorithm: find the\n // last dot AFTER the last separator, slice up to it.\n const lastSlash = path.lastIndexOf('/')\n const filename = lastSlash >= 0 ? path.slice(lastSlash + 1) : path\n const lastDot = filename.lastIndexOf('.')\n if (lastDot <= 0) return path // no ext, or hidden file like `.env`\n const dirPart = lastSlash >= 0 ? path.slice(0, lastSlash + 1) : ''\n return dirPart + filename.slice(0, lastDot)\n}\n","/**\n * Asset manager runtime (assets-plan.md PR 3).\n *\n * Three accessor surfaces over one resolver engine:\n *\n * - `assets.x.y()` — Proxy ambient, autocomplete-friendly default.\n * - `useAssets()` — hook returning the same Proxy; mockable per-call.\n * - `resolveAsset(ns, k)` — string resolver for dynamic dispatch.\n *\n * Resolution path:\n *\n * 1. Load the build-time manifest (`<outDir>/.kickjs-assets.json`)\n * when present. Manifest existence = \"we're running from a built\n * dist\". Fast path; mapped paths returned verbatim.\n * 2. Otherwise (dev / test) walk the assetMap src directories from\n * `kick.config.{json,js,cjs}` and synthesise the same manifest\n * shape in memory. First call pays the walk cost; subsequent\n * calls hit the cache.\n * 3. `KICK_ASSETS_ROOT` env var overrides everything — the resolver\n * treats the path as the manifest directory and skips discovery.\n *\n * @module @forinda/kickjs/core/assets\n */\n\nimport { existsSync, readFileSync, readdirSync } from 'node:fs'\nimport { isAbsolute, join, resolve, sep } from 'node:path'\nimport { createToken, type InjectionToken } from './token'\nimport { groupAssetKeys } from './asset-keys'\n\nexport const ASSET_MANIFEST_VERSION = 1 as const\n\ninterface AssetManifest {\n version: typeof ASSET_MANIFEST_VERSION\n entries: Record<string, string>\n}\n\ninterface ResolvedManifest {\n manifest: AssetManifest\n root: string\n}\n\n/**\n * Augmentable interface — `kick typegen` (assets-plan.md PR 4) emits\n * a `declare global` augmentation listing every namespace + key for\n * the project's `assetMap`. Adopters who haven't run typegen yet\n * still get a runtime-correct Proxy; only typed autocomplete waits\n * on the augmentation.\n */\nexport interface KickAssets {}\n\n/**\n * DI token for the `assets` Proxy. Adopter code that wants to\n * receive assets via constructor injection registers via\n * `container.registerInstance(ASSETS, useAssets())` in `bootstrap()`\n * and injects with `@Inject(ASSETS)`.\n */\nexport const ASSETS: InjectionToken<KickAssets> = createToken<KickAssets>('kick/assets/Map')\n\nexport class UnknownAssetError extends Error {\n readonly namespace: string\n readonly key: string\n constructor(namespace: string, key: string) {\n super(\n `Unknown asset '${namespace}/${key}'. ` +\n `Make sure the namespace exists in kick.config.ts assetMap and that the file is present in the source directory.`,\n )\n this.name = 'UnknownAssetError'\n this.namespace = namespace\n this.key = key\n }\n}\n\nlet manifestCache: ResolvedManifest | null | undefined = undefined\n\n/**\n * Convert a filesystem path to its posix (forward-slash) form. The\n * asset manifest and the public `resolveAsset` / `assets.x.y()` /\n * `useAssets()` contract returns posix paths on every platform so\n * adopters can:\n *\n * - pass the result to `express.static` / `res.sendFile` / `ejs.renderFile`\n * without worrying about Windows vs. posix separators\n * - splice the path into URLs (`href`, `src`, CDN keys) without\n * replacing `\\` with `/` by hand\n * - compare two paths from `resolveAsset` for equality on any host\n *\n * Node's `fs.*` and Express's path-handling APIs accept either\n * separator on Windows, so this normalisation is safe — the only\n * adopter code it could break is something explicitly parsing\n * Windows backslashes back out of the result, which would already be\n * brittle.\n */\nfunction toPosixPath(p: string): string {\n return p.replaceAll('\\\\', '/')\n}\n\nexport function resolveAsset(namespace: string, key: string): string {\n const resolved = loadManifest()\n if (!resolved) {\n throw new UnknownAssetError(namespace, key)\n }\n const entry = resolved.manifest.entries[`${namespace}/${key}`]\n if (!entry) {\n throw new UnknownAssetError(namespace, key)\n }\n const abs = isAbsolute(entry) ? entry : resolve(resolved.root, entry)\n return toPosixPath(abs)\n}\n\n/** Reset the manifest cache. Tests use this; production code shouldn't need it. */\nexport function clearAssetCache(): void {\n manifestCache = undefined\n}\n\nfunction loadManifest(): ResolvedManifest | null {\n // In development we deliberately skip the cache so adding or removing\n // a template file (e.g. dropping `welcome-back.ejs` into\n // `src/templates/mails/`) takes effect without a server restart. The\n // synthesise-dev-manifest path walks ~10 files; the cost is negligible\n // compared to the user-visible surprise of \"I added a file but\n // assets.x.y() throws\". Production keeps the cache because the built\n // manifest under `dist/.kickjs-assets.json` doesn't change at runtime.\n if (process.env.NODE_ENV !== 'production') {\n return discoverManifest()\n }\n if (manifestCache !== undefined) return manifestCache\n manifestCache = discoverManifest()\n return manifestCache\n}\n\nfunction discoverManifest(): ResolvedManifest | null {\n // `KICK_ASSETS_ROOT` is an explicit, deliberate override — it wins in\n // both dev and prod.\n const envRoot = process.env.KICK_ASSETS_ROOT\n if (envRoot) {\n const fromEnv = readBuiltManifest(envRoot)\n if (fromEnv) return fromEnv\n }\n\n const cwd = process.cwd()\n const config = loadConfigSync(cwd)\n\n // In dev, prefer a live walk of the source tree over any built\n // manifest left on disk by an earlier `kick build`. Otherwise a stale\n // `dist/.kickjs-assets.json` shadows the live `src/` tree: a freshly\n // added template file would resolve to the old map (or throw\n // UnknownAssetError) until the next rebuild — exactly the surprise the\n // cache-skip in `loadManifest` exists to avoid. `synthesiseDevManifest`\n // returns null only when there's no `assetMap` config at all, in which\n // case we fall through to the built-manifest probes below.\n if (process.env.NODE_ENV !== 'production') {\n const fresh = synthesiseDevManifest(cwd, config)\n if (fresh) return fresh\n }\n\n // Honour `kick.config.build.outDir` BEFORE the standard probe list\n // so adopters with non-default Vite outputs (e.g. `output/`,\n // `target/`, anything else) don't have to set KICK_ASSETS_ROOT\n // every time. Cached config load — same loader the dev fallback\n // uses. Skip when outDir matches one of the standard candidates;\n // it'd be probed redundantly otherwise.\n const configOutDir = config?.build?.outDir\n if (configOutDir && !(STANDARD_OUT_DIRS as readonly string[]).includes(configOutDir)) {\n const found = readBuiltManifest(resolve(cwd, configOutDir))\n if (found) return found\n }\n\n for (const candidate of STANDARD_OUT_DIRS) {\n const found = readBuiltManifest(join(cwd, candidate))\n if (found) return found\n }\n\n return synthesiseDevManifest(cwd, config)\n}\n\nconst STANDARD_OUT_DIRS = ['dist', 'build', 'out'] as const\n\nfunction readBuiltManifest(dir: string): ResolvedManifest | null {\n const path = join(dir, '.kickjs-assets.json')\n if (!existsSync(path)) return null\n try {\n const raw = readFileSync(path, 'utf-8')\n const parsed = JSON.parse(raw) as Partial<AssetManifest>\n if (parsed.version !== ASSET_MANIFEST_VERSION) return null\n if (!parsed.entries || typeof parsed.entries !== 'object') return null\n return { manifest: parsed as AssetManifest, root: resolve(dir) }\n } catch {\n return null\n }\n}\n\ninterface AssetMapConfigShape {\n assetMap?: Record<\n string,\n {\n src: string\n dest?: string\n glob?: string\n keys?: 'auto' | 'strip' | 'with-extension'\n }\n >\n build?: { outDir?: string }\n}\n\nfunction synthesiseDevManifest(\n cwd: string,\n preloadedConfig?: AssetMapConfigShape | null,\n): ResolvedManifest | null {\n const config = preloadedConfig === undefined ? loadConfigSync(cwd) : preloadedConfig\n if (!config?.assetMap) return null\n\n const entries: Record<string, string> = {}\n // Walk order is filesystem-dependent on Linux/macOS, so we collect\n // every match per-namespace first, then sort + feed `groupAssetKeys`\n // for stable manifest output. Build pipeline does the same — both\n // layers agree on the resulting key set.\n for (const [namespace, entry] of Object.entries(config.assetMap)) {\n if (!entry || typeof entry.src !== 'string') continue\n const srcAbs = resolve(cwd, entry.src)\n if (!existsSync(srcAbs)) continue\n\n const collected: Array<{ rel: string; abs: string }> = []\n walkSync(srcAbs, srcAbs, (relPath, absPath) => {\n if (entry.glob && !matchesGlobLite(relPath, entry.glob, namespace)) return\n collected.push({ rel: relPath, abs: absPath })\n })\n collected.sort((a, b) => a.rel.localeCompare(b.rel))\n\n const { pairs, collisionGroupsResolved } = groupAssetKeys(\n namespace,\n collected.map((c) => c.rel),\n { strategy: entry.keys ?? 'auto' },\n )\n const absByRel = new Map(collected.map((c) => [c.rel, c.abs]))\n for (const { rel, key } of pairs) {\n const abs = absByRel.get(rel)\n if (abs) entries[key] = abs\n }\n if (collisionGroupsResolved > 0 && process.env.NODE_ENV !== 'production') {\n // Dev-only nudge — production runs read the build manifest where\n // the collision was already resolved at build time.\n console.log(\n `[kickjs/assets] '${namespace}': ${collisionGroupsResolved} basename collision(s) auto-resolved by keeping extensions ` +\n `(set assetMap.${namespace}.keys to 'strip' or 'with-extension' to override).`,\n )\n }\n }\n\n return { manifest: { version: ASSET_MANIFEST_VERSION, entries }, root: cwd }\n}\n\nconst warnedGlobs = new Set<string>()\n\n/**\n * Tiny glob matcher used only by dev manifest synthesis. Covers the\n * common assetMap glob patterns (`**\\/*`, `**\\/*.ext`,\n * `**\\/*.{a,b}`). Anything exotic prints a one-time warning + falls\n * through to `**\\/*` semantics rather than silently dropping files.\n *\n * The build pipeline (`packages/cli/src/asset-manager/build.ts`) uses\n * the full `glob` package; adopters who hit the dev-mode warning\n * should run `kick build:assets` to produce a real manifest.\n */\nfunction matchesGlobLite(relPath: string, pattern: string, namespace: string): boolean {\n if (pattern === '**/*' || pattern === '**') return true\n const singleExt = /^\\*\\*\\/\\*\\.(\\w+)$/.exec(pattern)\n if (singleExt) return relPath.endsWith(`.${singleExt[1]}`)\n const braceExt = /^\\*\\*\\/\\*\\.\\{([^}]+)\\}$/.exec(pattern)\n if (braceExt) {\n const exts = braceExt[1].split(',').map((e) => e.trim())\n return exts.some((ext) => relPath.endsWith(`.${ext}`))\n }\n const tag = `${namespace}::${pattern}`\n if (!warnedGlobs.has(tag)) {\n warnedGlobs.add(tag)\n console.warn(\n `[kickjs/assets] Dev-mode glob '${pattern}' on '${namespace}' isn't recognised by the lite matcher. ` +\n `Falling back to '**/*'. Run 'kick build:assets' to use the full glob engine.`,\n )\n }\n return true\n}\n\nfunction walkSync(root: string, dir: string, onFile: (rel: string, abs: string) => void): void {\n let entries\n try {\n entries = readdirSync(dir, { withFileTypes: true })\n } catch {\n return\n }\n for (const entry of entries) {\n if (entry.name === 'node_modules' || entry.name.startsWith('.')) continue\n const full = join(dir, entry.name)\n if (entry.isDirectory()) {\n walkSync(root, full, onFile)\n } else if (entry.isFile()) {\n const rel = full\n .slice(root.length + 1)\n .split(sep)\n .join('/')\n onFile(rel, full)\n }\n }\n}\n\n/**\n * Sync `kick.config.{json,cjs,js}` loader for dev manifest\n * synthesis. Avoids dynamic `import()` (would force every assets\n * lookup to be async). TypeScript configs (`kick.config.ts`) are\n * skipped here — adopters who use them should run `kick build:assets`\n * to produce a real manifest the resolver can read.\n */\nfunction loadConfigSync(cwd: string): AssetMapConfigShape | null {\n const jsonPath = join(cwd, 'kick.config.json')\n if (existsSync(jsonPath)) {\n try {\n return JSON.parse(readFileSync(jsonPath, 'utf-8')) as AssetMapConfigShape\n } catch {\n return null\n }\n }\n for (const filename of ['kick.config.cjs', 'kick.config.js']) {\n const path = join(cwd, filename)\n if (!existsSync(path)) continue\n try {\n // eslint-disable-next-line @typescript-eslint/no-require-imports\n const { createRequire } = require('node:module') as typeof import('node:module')\n const req = createRequire(join(cwd, 'package.json'))\n const mod = req(path) as { default?: AssetMapConfigShape } & AssetMapConfigShape\n return mod.default ?? mod ?? null\n } catch {\n continue\n }\n }\n\n // Fallback: the CLI snapshot of a transpiled `kick.config.ts`. We\n // can't transpile TS synchronously on the asset hot path, so the CLI\n // (`loadKickConfig`) mirrors the JSON-serialisable `assetMap` +\n // `build.outDir` into `.kickjs/kick.config.json` whenever it loads a\n // `.ts`/`.js` config. This is what makes `assets.x.y()` resolve in\n // dev for `.ts`-config projects before the first production build.\n const snapshotPath = join(cwd, '.kickjs', 'kick.config.json')\n if (existsSync(snapshotPath)) {\n try {\n return JSON.parse(readFileSync(snapshotPath, 'utf-8')) as AssetMapConfigShape\n } catch {\n return null\n }\n }\n return null\n}\n\n/**\n * Keys we MUST return `undefined` for: returning anything truthy\n * here causes Promise resolution to treat the Proxy as a thenable\n * and `await` it (resolving to whatever `then.call(...)` produces).\n * Two-element list deliberately — every other coercion-related key\n * goes through {@link PASSTHROUGH_KEYS} below so `String(assets)`,\n * template literals, and `util.inspect` keep working.\n */\nconst PROMISE_DETECTION_KEYS: ReadonlySet<string | symbol> = new Set<string | symbol>(['then'])\n\n/**\n * Keys we let fall through to the proxy target (a function-shaped\n * object). The default `Object.prototype` implementations of\n * `toString` / `valueOf` etc. are correct for these — returning\n * `undefined` here would break `String(assets)` and template\n * literals (`${assets}`) because `Symbol.toPrimitive` falling through\n * to a missing `toString` throws. Adopters that hit `assets.toString`\n * get `'function () {}'` back, which is fine — the contract is\n * \"asset access returns paths\"; everything else is incidental.\n */\nconst PASSTHROUGH_KEYS: ReadonlySet<string | symbol> = new Set<string | symbol>([\n 'toString',\n 'valueOf',\n 'constructor',\n 'prototype',\n 'name',\n 'length',\n 'asymmetricMatch',\n 'nodeType',\n Symbol.toPrimitive,\n Symbol.toStringTag,\n Symbol.iterator,\n Symbol.asyncIterator,\n])\n\nfunction createNamespaceProxy(parts: readonly string[]): unknown {\n const target = function () {} as unknown as Record<string, unknown>\n return new Proxy(target, {\n apply() {\n if (parts.length < 2) {\n throw new UnknownAssetError(parts[0] ?? '', '')\n }\n const [namespace, ...rest] = parts\n return resolveAsset(namespace, rest.join('/'))\n },\n get(t, prop) {\n if (PROMISE_DETECTION_KEYS.has(prop)) return undefined\n if (PASSTHROUGH_KEYS.has(prop)) return Reflect.get(t, prop)\n if (typeof prop === 'symbol') return undefined\n return createNamespaceProxy([...parts, prop])\n },\n })\n}\n\nfunction createAssetProxy(): KickAssets {\n return new Proxy({} as Record<string, unknown>, {\n get(t, prop) {\n if (PROMISE_DETECTION_KEYS.has(prop)) return undefined\n if (PASSTHROUGH_KEYS.has(prop)) return Reflect.get(t, prop)\n if (typeof prop === 'symbol') return undefined\n return createNamespaceProxy([prop])\n },\n }) as unknown as KickAssets\n}\n\n/**\n * Variant A — the ambient Proxy. Default accessor for static call\n * sites where the namespace + key are literals known at compile time.\n *\n * @example\n * ```ts\n * import { assets } from '@forinda/kickjs'\n * const path = assets.mails.welcome()\n * ```\n */\nexport const assets: KickAssets = createAssetProxy()\n\n/**\n * Variant B — the hook accessor. Returns the same Proxy as `assets`;\n * factory shape exists for testability + DI. Mock via\n * `vi.mock('@forinda/kickjs', () => ({ useAssets: () => fakeAssets }))`.\n *\n * @example\n * ```ts\n * import { useAssets } from '@forinda/kickjs'\n * class MailService {\n * private assets = useAssets()\n * send(name: string) {\n * return ejs.renderFile(this.assets.mails[name](), {})\n * }\n * }\n * ```\n */\nexport function useAssets(): KickAssets {\n return assets\n}\n\n// Install this module's resolver into the container's asset slot — the\n// container deliberately avoids importing this file (edge purity; see\n// asset-resolver-slot.ts). Runs at module scope so any node app that loads\n// the asset manager gets full @Asset injection.\nimport { _setAssetResolver } from './asset-resolver-slot'\n_setAssetResolver(resolveAsset)\n"],"mappings":"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"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"cors-C4aSCD3J.d.mts","names":[],"sources":["../src/http/middleware/cors.ts"],"mappings":";;;;UAEiB,WAAA;;EAEf,MAAA,sBAA4B,MAAA,aAAmB,MAAM;EAF3B;EAI1B,OAAA;EAFqD;EAIrD,cAAA;EAJ4B;EAM5B,cAAA;EAJA;EAMA,WAAA;EAFA;EAIA,MAAA;EAAA;EAEA,SAAA;AAAA;AAAS;AAyCX;;;;;;;;;;;;;;;;;;AAWyD;;;;;AApD9C,iBAyCK,IAAA,CAAK,OAAA,GAAS,WAAA,IAAgB,GAAA,EAW/B,OAAA,EAAO,GAAA,EAAO,QAAA,EAAQ,IAAA,EAAQ,YAAA"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"csrf-7nUXGTuz.d.mts","names":[],"sources":["../src/http/middleware/csrf.ts"],"mappings":";;;;UAIiB,WAAA;;EAEf,MAAA;EAF0B;EAI1B,MAAA;EAJ0B;EAM1B,OAAA;EAFA;EAIA,WAAA;EAAA;EAEA,WAAA;EAEA;EAAA,aAAA;IACE,QAAA;IACA,QAAA;IACA,MAAA;IACA,IAAA;EAAA;AAAA;;;;;;;;;;;;;;;;;;;;;;AA6CqD;;;;iBAhBzC,IAAA,CAAK,OAAA,GAAS,WAAA,IAAgB,GAAA,EAgB/B,OAAA,EAAO,GAAA,EAAO,QAAA,EAAQ,IAAA,EAAQ,YAAA,YAAY,QAAA,MAAA,MAAA"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"decorators-wEJBqXHg.d.mts","names":[],"sources":["../src/core/assets.ts","../src/core/decorators.ts"],"mappings":"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"}
|
package/dist/env-Dgtjncd5.mjs
DELETED
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @forinda/kickjs v6.5.0
|
|
3
|
-
*
|
|
4
|
-
* Copyright (c) Felix Orinda
|
|
5
|
-
*
|
|
6
|
-
* This source code is licensed under the MIT license found in the
|
|
7
|
-
* LICENSE file in the root directory of this source tree.
|
|
8
|
-
*
|
|
9
|
-
* @license MIT
|
|
10
|
-
*/
|
|
11
|
-
import{t as __require}from"./rolldown-runtime-CuwksmWW.mjs";import{t as Container}from"./container-CBaL5lus.mjs";import{detectSchema}from"@forinda/kickjs-schema";let _zod;function getZod(){if(_zod)return _zod;try{_zod=__require(`zod`)}catch{throw Error("@forinda/kickjs: the 'zod' peer dependency is required for baseEnvSchema / defineEnv / loadEnv but is not installed. Install it (`pnpm add zod`), or define your env with a non-Zod schema and call loadEnvFromSchema() instead — @forinda/kickjs-schema supports Valibot, Yup, and any Standard Schema validator without zod.")}return _zod}function tryLoadDotenv(){try{__require(`dotenv`).config({override:!1,quiet:!0})}catch{}}tryLoadDotenv();function buildBaseEnvSchema(){let z=getZod();return z.object({PORT:z.coerce.number().default(3e3),NODE_ENV:z.enum([`development`,`production`,`test`]).default(`development`),LOG_LEVEL:z.string().default(`info`)})}let _baseEnvSchema;function getBaseEnvSchema(){return _baseEnvSchema||=buildBaseEnvSchema(),_baseEnvSchema}const baseEnvSchema=new Proxy({},{get(_t,prop){let real=getBaseEnvSchema(),value=real[prop];return typeof value==`function`?value.bind(real):value},has(_t,prop){return prop in getBaseEnvSchema()}});let cachedEnv=null,cachedSchema=null;function defineEnv(extend){let base=getBaseEnvSchema(),userSchema=extend(base);return base.extend(userSchema.shape)}function loadEnv(schema){let s=schema??cachedSchema??getBaseEnvSchema();return cachedEnv&&cachedSchema===s?cachedEnv:(cachedSchema=s,cachedEnv=s.parse(process.env),Container._envResolver=key=>cachedEnv?.[key],cachedEnv)}function getEnv(key,schema){return(schema?loadEnv(schema):loadEnv())[key]}function reloadEnv(){try{__require(`dotenv`).config({override:!0,quiet:!0})}catch{}cachedEnv=null,cachedSchema&&(typeof cachedSchema.parse==`function`?loadEnv(cachedSchema):loadEnvFromSchema(cachedSchema))}function resetEnvCache(){cachedEnv=null,cachedSchema=null}function loadEnvFromSchema(schema){let result=detectSchema(schema).safeParse(process.env);if(!result.success){let details=result.issues.map(i=>` ${i.path.join(`.`)||`(root)`}: ${i.message}`).join(`
|
|
12
|
-
`);throw Error(`Environment validation failed:\n${details}`)}return cachedEnv=result.data,cachedSchema=schema,Container._envResolver=key=>cachedEnv?.[key],result.data}export{loadEnvFromSchema as a,loadEnv as i,defineEnv as n,reloadEnv as o,getEnv as r,resetEnvCache as s,baseEnvSchema as t};
|
|
13
|
-
//# sourceMappingURL=env-Dgtjncd5.mjs.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"error-handler-DR01K_rI.d.mts","names":[],"sources":["../src/http/middleware/error-handler.ts"],"mappings":";;;;;iBAYgB,eAAA,KAAe,IAAA,EACf,OAAA,EAAO,GAAA,EAAO,QAAA,EAAQ,KAAA,EAAS,YAAA;AAD/C;;;;;;;;;;;;;;;AAC2D;AAwB3D;;;AAzBA,iBAyBgB,YAAA,KAAY,GAAA,OAEV,GAAA,EAAO,OAAA,EAAO,GAAA,EAAO,QAAA,EAAQ,KAAA,EAAS,YAAA,KAAY,QAAA,MAAA,MAAA"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"errors-n0H96eEz.d.mts","names":[],"sources":["../src/core/errors.ts"],"mappings":"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"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"helmet-CKzZzeNl.d.mts","names":[],"sources":["../src/http/middleware/helmet.ts"],"mappings":";;;;UAEiB,aAAA;;EAEf,qBAAA,aAAkC,MAAM;EAFZ;EAI5B,OAAA;EAFwC;EAIxC,UAAA;EAJkC;EAMlC,IAAA;IAAiB,MAAA;IAAiB,iBAAA;IAA6B,OAAA;EAAA;EAAA;EAE/D,WAAA;EAEA;EAAA,aAAA;EAIA;EAFA,cAAA;EAES;EAAT,SAAA;AAAA;;;;;;;;;;;;iBAcc,MAAA,CAAO,OAAA,GAAS,aAAA,IAAkB,GAAA,EAYnC,OAAA,EAAO,GAAA,EAAO,QAAA,EAAQ,IAAA,EAAQ,YAAA"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"views.mjs","names":[],"sources":["../../../src/http/middleware/views.ts"],"sourcesContent":["import { resolve } from 'node:path'\nimport { Logger, defineAdapter } from '../../core'\n\nconst log = Logger.for('ViewEngine')\n\nexport interface ViewAdapterOptions {\n /**\n * Template engine — pass the engine module or a render function.\n * Supported engines: ejs, pug, handlebars, nunjucks, or any\n * Express-compatible engine with a __express property.\n *\n * @example\n * ```ts\n * import ejs from 'ejs'\n * ViewAdapter({ engine: ejs, ext: 'ejs' })\n *\n * import pug from 'pug'\n * ViewAdapter({ engine: pug, ext: 'pug' })\n * ```\n */\n engine: any\n\n /** File extension for templates (e.g., 'ejs', 'pug', 'hbs') */\n ext: string\n\n /** Directory containing template files (default: 'src/views') */\n viewsDir?: string\n\n /** Default layout template (optional — depends on engine) */\n layout?: string\n}\n\n/**\n * View/template adapter — pluggable template engine support for KickJS.\n *\n * Registers an Express view engine and sets the views directory.\n * Use `ctx.render()` in controllers to render templates.\n *\n * Migrated to the `defineAdapter()` factory in v4 — call without `new`.\n * The pre-v4 `new ViewAdapter({...})` form is gone; see\n * `docs/guide/migration-v3-to-v4.md` for the rename.\n *\n * @example\n * ```ts\n * import ejs from 'ejs'\n * import { ViewAdapter } from '@forinda/kickjs'\n *\n * bootstrap({\n * modules,\n * adapters: [\n * ViewAdapter({ engine: ejs, ext: 'ejs', viewsDir: 'src/views' }),\n * ],\n * })\n *\n * // In a controller:\n * @Get('/dashboard')\n * async dashboard(ctx: RequestContext) {\n * ctx.render('dashboard', { user: currentUser, title: 'Dashboard' })\n * }\n * ```\n */\nexport const ViewAdapter = defineAdapter<ViewAdapterOptions>({\n name: 'ViewAdapter',\n build: (options) => ({\n beforeMount({ app }) {\n const { engine, ext, viewsDir = 'src/views' } = options\n\n // Register the engine. Three resolution paths cover every\n // mainstream template engine + a fall-through for custom ones.\n if (engine.__express) {\n // EJS, Pug — have __express method\n app.engine(ext, engine.__express)\n } else if (typeof engine.renderFile === 'function') {\n // Engines with renderFile (nunjucks-style)\n app.engine(\n ext,\n (path: string, opts: any, callback: (err: Error | null, html?: string) => void) => {\n engine.renderFile(path, opts, callback)\n },\n )\n } else if (typeof engine === 'function') {\n // Custom render function: (path, options, callback) => void\n app.engine(ext, engine)\n } else {\n log.warn(`Engine for .${ext} does not have __express or renderFile. Trying as-is.`)\n app.engine(ext, engine)\n }\n\n app.set('view engine', ext)\n app.set('views', resolve(viewsDir))\n\n log.debug(`View engine: ${ext} (${resolve(viewsDir)})`)\n },\n }),\n})\n"],"mappings":";;;;;;;;;;iIAGA,MAAM,IAAM,OAAO,IAAI,YAAY,EA0DtB,YAAc,cAAkC,CAC3D,KAAM,cACN,MAAQ,UAAa,CACnB,YAAY,CAAE,KAAO,CACnB,GAAM,CAAE,OAAQ,IAAK,SAAW,aAAgB,QAI5C,OAAO,UAET,IAAI,OAAO,IAAK,OAAO,SAAS,EACvB,OAAO,OAAO,YAAe,WAEtC,IAAI,OACF,KACC,KAAc,KAAW,WAAyD,CACjF,OAAO,WAAW,KAAM,KAAM,QAAQ,CACxC,CACF,GACS,OAAO,QAAW,YAI3B,IAAI,KAAK,eAAe,IAAI,sDAAsD,EAFlF,IAAI,OAAO,IAAK,MAAM,GAMxB,IAAI,IAAI,cAAe,GAAG,EAC1B,IAAI,IAAI,QAAS,QAAQ,QAAQ,CAAC,EAElC,IAAI,MAAM,gBAAgB,IAAI,IAAI,QAAQ,QAAQ,EAAE,EAAE,CACxD,CACF,EACF,CAAC"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"router-builder.mjs","names":[],"sources":["../../src/http/router-builder.ts"],"sourcesContent":["// Concrete-module imports (NOT the `../core` barrel): the barrel re-exports\n// the asset manager, whose eager `node:fs` import would poison the edge-safe\n// `@forinda/kickjs/web` entry graph that flows through this file.\nimport { buildPipeline, type SourcedRegistration } from '../core/contributor-pipeline'\nimport { runContributors } from '../core/contributor-runner'\nimport { Container } from '../core/container'\nimport { METADATA } from '../core/interfaces'\nimport type { ContributorRegistration } from '../core/context-decorator'\nimport type { FileUploadConfig, MiddlewareHandler, RouteDefinition } from '../core/decorators'\nimport { getClassMeta, getMethodMeta, getMethodMetaOrUndefined } from '../core/metadata'\nimport { duplicateRouteError } from '../core/kick-errors'\nimport type { CtxHandler, RouteEntry, RouteMethod } from './runtime'\n\n/**\n * Per-module SourcedRegistration[] threaded through the route-mount loop by\n * Application.setup(). Carries module + adapter + global contributors so\n * buildRouteTable() can merge them with class + method ones into a single pipeline.\n *\n * Module setup is sequential, so this slot is race-free. Cleared in a finally\n * block after each module mounts. Outside of Application setup the slot is\n * empty — direct buildRouteTable()/buildRoutes() callers (mostly tests) see only\n * class + method contributors unless they pass `externalSources` explicitly.\n *\n * Same idiom as `Container._requestStoreProvider`: an internal escape hatch for\n * cross-module wiring without inversion-of-control gymnastics.\n *\n * @internal\n */\nlet _externalContributorSources: readonly SourcedRegistration[] = []\n\n/** @internal — set by Application.setup() before each `mod.routes()` call. */\nexport function _setExternalContributorSources(sources: readonly SourcedRegistration[]): void {\n _externalContributorSources = sources\n}\n\n/**\n * Boot-time duplicate-route guard shared by the node and web mount loops.\n *\n * Registers `METHOD /mounted/path` into `registry` and throws\n * {@link duplicateRouteError} (KICK006) if another handler already claimed\n * it. Param *names* are ignored — `/tasks/:id` and `/tasks/:taskId` are the\n * same route at dispatch time, so they collide here too.\n *\n * @internal\n */\nexport function assertRouteUnique(\n registry: Map<string, string>,\n method: string,\n fullPath: string,\n owner: string,\n): void {\n const key = `${method.toUpperCase()} ${fullPath.replace(/:[^/]+/g, ':*')}`\n const prior = registry.get(key)\n if (prior !== undefined) {\n throw duplicateRouteError(method.toUpperCase(), fullPath, owner, prior)\n }\n registry.set(key, owner)\n}\n\nexport interface BuildRoutesOptions {\n /**\n * Extra contributors to merge into the per-route pipeline at their declared\n * precedence levels. Pass explicitly when calling buildRouteTable/buildRoutes\n * outside the Application route-mount loop (typically in tests). When omitted,\n * falls back to the slot set by Application.setup().\n */\n externalSources?: readonly SourcedRegistration[]\n}\n\n/**\n * Turn a controller class decorated with @Get, @Post, etc. into a plain-data\n * {@link RouteEntry}[] — the engine-neutral route table an {@link HttpRuntime}\n * materializes (see `docs/http/spec-http-runtimes.md`, Avenue B).\n *\n * What used to be per-handler Express `(req, res, next)` closures is now\n * captured as data: `middlewares` keep their `(ctx, next)` shape, the contributor\n * pipeline is pre-built into a `contributorRunner` closure, validation / upload\n * stay as metadata, and the terminal `handler` resolves the controller per-request\n * (to respect DI scoping) and invokes it. The runtime owns how these get wrapped\n * onto its engine.\n *\n * Routes use only the method-level decorator paths (e.g. @Get('/me') → '/me').\n * The @Controller path is NOT baked in — it is metadata for Swagger/introspection.\n * The module's routes().path is the single source of truth for the mount prefix,\n * which avoids path doubling when both the module and controller specify the path.\n *\n * The contributor pipeline is built here, so a cycle or missing `dependsOn`\n * throws at table-build time (boot) rather than on first request.\n */\nexport function buildRouteTable(\n controllerClass: any,\n options: BuildRoutesOptions = {},\n): RouteEntry[] {\n const container = Container.getInstance()\n const externalSources = options.externalSources ?? _externalContributorSources\n const routes: RouteDefinition[] = getClassMeta<RouteDefinition[]>(\n METADATA.ROUTES,\n controllerClass,\n [],\n )\n\n // Class-level middleware\n const classMiddlewares: MiddlewareHandler[] = getClassMeta<MiddlewareHandler[]>(\n METADATA.CLASS_MIDDLEWARES,\n controllerClass,\n [],\n )\n\n // Class-level Context Contributors (#107) — applied to every method on the\n // controller. Method-level contributors are added per-route below.\n const classContributors: ContributorRegistration[] = getClassMeta<ContributorRegistration[]>(\n METADATA.CLASS_CONTRIBUTORS,\n controllerClass,\n [],\n )\n\n const entries: RouteEntry[] = []\n\n for (const route of routes) {\n const method = route.method.toUpperCase() as RouteMethod\n const fullPath = route.path || '/'\n\n // Method-level middleware\n const methodMiddlewares: MiddlewareHandler[] = getMethodMeta<MiddlewareHandler[]>(\n METADATA.METHOD_MIDDLEWARES,\n controllerClass,\n route.handlerName,\n [],\n )\n\n // @FileUpload decorator — runtime supplies the upload backend.\n const fileUploadConfig = getMethodMetaOrUndefined<FileUploadConfig>(\n METADATA.FILE_UPLOAD,\n controllerClass,\n route.handlerName,\n )\n\n // Context Contributor pipeline (#107) — class + method contributors,\n // built once at mount time so cycle/missing-dep failures abort boot.\n const methodContributors: ContributorRegistration[] = getMethodMeta<ContributorRegistration[]>(\n METADATA.METHOD_CONTRIBUTORS,\n controllerClass,\n route.handlerName,\n [],\n )\n\n let contributorRunner: CtxHandler | null = null\n if (\n classContributors.length > 0 ||\n methodContributors.length > 0 ||\n externalSources.length > 0\n ) {\n // Labels are surfaced in DuplicateContributorError messages — include\n // the registration's key + the original index so a same-key collision\n // at one precedence level points at the conflicting decorator slot,\n // not just the host method/class.\n const sources: SourcedRegistration[] = [\n ...methodContributors.map(\n (registration, i): SourcedRegistration => ({\n source: 'method',\n registration,\n label: `${controllerClass.name}.${String(route.handlerName)}#${i}(${registration.key})`,\n }),\n ),\n ...classContributors.map(\n (registration, i): SourcedRegistration => ({\n source: 'class',\n registration,\n label: `${controllerClass.name}.@class#${i}(${registration.key})`,\n }),\n ),\n ...externalSources,\n ]\n const pipeline = buildPipeline(sources, {\n route: `${method} ${fullPath}`,\n })\n contributorRunner = (ctx) => runContributors({ pipeline, ctx, container })\n }\n\n // Terminal handler — resolve controller per-request to respect DI scoping.\n const handler: CtxHandler = (ctx) => container.resolve(controllerClass)[route.handlerName](ctx)\n\n entries.push({\n method,\n path: fullPath,\n middlewares: [...classMiddlewares, ...methodMiddlewares],\n contributorRunner,\n handler,\n meta: {\n controller: controllerClass,\n handlerName: route.handlerName,\n validation: route.validation,\n upload: fileUploadConfig,\n },\n })\n }\n\n return entries\n}\n"],"mappings":";;;;;;;;;;6TA4BA,IAAI,4BAA8D,CAAC,EAGnE,SAAgB,+BAA+B,QAA+C,CAC5F,4BAA8B,OAChC,CAYA,SAAgB,kBACd,SACA,OACA,SACA,MACM,CACN,IAAM,IAAM,GAAG,OAAO,YAAY,EAAE,GAAG,SAAS,QAAQ,UAAW,IAAI,IACjE,MAAQ,SAAS,IAAI,GAAG,EAC9B,GAAI,QAAU,IAAA,GACZ,MAAM,oBAAoB,OAAO,YAAY,EAAG,SAAU,MAAO,KAAK,EAExE,SAAS,IAAI,IAAK,KAAK,CACzB,CAgCA,SAAgB,gBACd,gBACA,QAA8B,CAAC,EACjB,CACd,IAAM,UAAY,UAAU,YAAY,EAClC,gBAAkB,QAAQ,iBAAmB,4BAC7C,OAA4B,aAChC,SAAS,OACT,gBACA,CAAC,CACH,EAGM,iBAAwC,aAC5C,SAAS,kBACT,gBACA,CAAC,CACH,EAIM,kBAA+C,aACnD,SAAS,mBACT,gBACA,CAAC,CACH,EAEM,QAAwB,CAAC,EAE/B,IAAK,IAAM,SAAS,OAAQ,CAC1B,IAAM,OAAS,MAAM,OAAO,YAAY,EAClC,SAAW,MAAM,MAAQ,IAGzB,kBAAyC,cAC7C,SAAS,mBACT,gBACA,MAAM,YACN,CAAC,CACH,EAGM,iBAAmB,yBACvB,SAAS,YACT,gBACA,MAAM,WACR,EAIM,mBAAgD,cACpD,SAAS,oBACT,gBACA,MAAM,YACN,CAAC,CACH,EAEI,kBAAuC,KAC3C,GACE,kBAAkB,OAAS,GAC3B,mBAAmB,OAAS,GAC5B,gBAAgB,OAAS,EACzB,CAsBA,IAAM,SAAW,cAAc,CAhB7B,GAAG,mBAAmB,KACnB,aAAc,KAA4B,CACzC,OAAQ,SACR,aACA,MAAO,GAAG,gBAAgB,KAAK,GAAG,OAAO,MAAM,WAAW,EAAE,GAAG,EAAE,GAAG,aAAa,IAAI,EACvF,EACF,EACA,GAAG,kBAAkB,KAClB,aAAc,KAA4B,CACzC,OAAQ,QACR,aACA,MAAO,GAAG,gBAAgB,KAAK,UAAU,EAAE,GAAG,aAAa,IAAI,EACjE,EACF,EACA,GAAG,eAEgC,EAAG,CACtC,MAAO,GAAG,OAAO,GAAG,UACtB,CAAC,EACD,kBAAqB,KAAQ,gBAAgB,CAAE,SAAU,IAAK,SAAU,CAAC,CAC3E,CAGA,IAAM,QAAuB,KAAQ,UAAU,QAAQ,eAAe,CAAC,CAAC,MAAM,YAAY,CAAC,GAAG,EAE9F,QAAQ,KAAK,CACX,OACA,KAAM,SACN,YAAa,CAAC,GAAG,iBAAkB,GAAG,iBAAiB,EACvD,kBACA,QACA,KAAM,CACJ,WAAY,gBACZ,YAAa,MAAM,YACnB,WAAY,MAAM,WAClB,OAAQ,gBACV,CACF,CAAC,CACH,CAEA,OAAO,OACT"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index-BtWJ9SLP.d.mts","names":[],"sources":["../src/http/query/types.ts","../src/http/query/parse-query.ts"],"mappings":";;;KACY,cAAA;AAAA,cAaC,gBAAA,EAAgB,GAAA;AAAA,UAcZ,UAAA;EACf,KAAA;EACA,QAAA,EAAU,cAAc;EACxB,KAAA;AAAA;AAAA,UAGe,QAAA;EACf,KAAA;EACA,SAAS;AAAA;AAAA,UAGM,gBAAA;EACf,IAAA;EACA,KAAA;EACA,MAAA;AAAA;;;;AAXK;AAGP;UAgBiB,WAAA;EACf,OAAA,EAAS,UAAA;EACT,IAAA,EAAM,QAAA;EACN,UAAA,EAAY,gBAAA;EACZ,MAAA;AAAA;;;;;;;AAZM;AAQR;KAeY,QAAA,iBACM,gBAAA,oEAEd,OAAA,0BAAiC,CAAA,4BACjC,CAAA,kBACE,CAAA,YAEF,OAAA;EAAkB,OAAA;AAAA,IAChB,CAAA,8BACQ,CAAA;;;;;;;;;;;AApBN;AAWR;;;;;;UA8BiB,gBAAA,iBACC,gBAAA,sBACR,WAAA;EACR,OAAA,EAAS,KAAA,CAAM,UAAA;IAAe,KAAA,EAAO,QAAA,CAAS,OAAA;EAAA;EAC9C,IAAA,EAAM,KAAA,CAAM,QAAA;IAAa,KAAA,EAAO,QAAA,CAAS,OAAA;EAAA;AAAA;;;;;;;;;;;KAa/B,gBAAA,GAAmB,sBAAA,GAAyB,sBAAsB;AAAA,UAE7D,sBAAA;EACf,UAAA;EACA,QAAA;EACA,UAAA;AAAA;;;;;UAOe,sBAAA;EACf,OAAA,EAAS,MAAA;EACT,QAAA,GAAW,MAAM;EACjB,aAAA;EAAA,CACC,GAAA;AAAA;;UAIc,iBAAA;EACf,IAAA,EAAM,CAAC;EACP,IAAA;IACE,IAAA;IACA,KAAA;IACA,KAAA;IACA,UAAA;IACA,OAAA;IACA,OAAA;EAAA;AAAA;;;;;;;AAzC8C;AAalD;;;;AAA8E;AAE9E;;;;;;;;AAGY;AAOZ;;UA2CiB,mBAAA;EAzCE;EAAA,SA2CR,IAAA;EA5CA;;;;;EAmDT,KAAA,CAAM,MAAA,EAAQ,WAAA,EAAa,MAAA,EAAQ,OAAA,GAAU,OAAA;AAAA;;;AA/K/C;;;;AAA0B;AAA1B,KCkBY,iBAAA;AAAA,UAEK,cAAA;EACf,IAAA;EACA,KAAA;EACA,MAAA,EAAQ,iBAAiB;AAAA;AAAA,UAGV,iBAAA;;EAEf,QAAA;EDAA;ECEA,YAAA;EDDU;ECGV,eAAA;EDFK;AAAA;AAGP;;;ECKE,QAAA,IAAY,SAAA,EAAW,cAAc;AAAA;AAAA,UAG7B,oBAAA;EACR,QAAA;EACA,YAAA;EACA,eAAA;EACA,WAAA;AAAA;;;ADJM;AAQR;iBCYgB,uBAAA,CACd,OAAA,EAAS,OAAA,CAAQ,IAAA,CAAK,oBAAA;;iBAQR,uBAAA,IAA2B,QAAQ,CAAC,oBAAA;;;;;;;iBAUpC,yBAAA;;iBAOA,YAAA,CACd,WAAA,iCACA,aAAA,aACA,OAAA,GAAU,IAAA,CAAK,iBAAA,gBACd,UAAA;;iBAqCa,SAAA,CACd,SAAA,iCACA,aAAA,aACA,OAAA,GAAU,IAAA,CAAK,iBAAA,gBACd,QAAA;;iBA8Ba,eAAA,CACd,MAAA;EACE,IAAA;EACA,KAAA;AAAA,GAEF,OAAA,GAAU,IAAA,CAAK,iBAAA,iCACd,gBAAA;;iBAqBa,gBAAA,CACd,CAAA,sBACA,OAAA,GAAU,IAAI,CAAC,iBAAA;;;;;;;;;;;;;;;;;;;;;;ADtHF;AAqBf;;;;;;;iBCmKgB,UAAA,iBAA2B,gBAAA,0BACzC,KAAA,EAAO,MAAA,eACP,WAAA,GAAc,OAAA,EACd,OAAA,GAAU,iBAAA,GACT,gBAAA,CAAiB,OAAA;;iBAcJ,gBAAA,CACd,MAAA,EAAQ,OAAA,CAAQ,WAAA,IACf,MAAA"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index-D98NLfS5.d.mts","names":[],"sources":["../src/config/env.ts","../src/config/config-service.ts"],"mappings":";;;;;;;;AAGgD;;;iBA6EvC,kBAAA,IAAkB,CAAA,CAAA,SAAA;;;;;;;;;;KAWf,aAAA,GAAgB,UAAU,QAAQ,kBAAA;;;;;;;;;;;cAsBjC,aAAA,EAAe,aAUT;;;;;;;;;;;;;AAhCnB;;;;AAAgE;AAsBhE;;;;AAUmB;AAoCnB;;;;;;;;iBAAgB,SAAA,WAAoB,CAAA,CAAE,WAAA,EACpC,MAAA,GAAS,IAAA,SAAa,aAAA,KAAkB,CAAA,CAAE,SAAA,CAAU,CAAA,IACnD,CAAA,CAAE,SAAA,QAAiB,aAAA,CAAc,KAAA,GAAQ,CAAA;;;;;;;;;;;;;;;;;;;AAAC;AAgC7C;;;;iBAAgB,OAAA,WAAkB,CAAA,CAAE,SAAA,OAAgB,MAAA,EAAQ,CAAA,GAAI,CAAA,CAAE,KAAA,CAAM,CAAA;AAAA,iBACxD,OAAA,KAAY,MAAA,oBAA0B,GAAA,GAAM,OAAA;;;;;;;;;;;;;AADa;AACzE;;;;;;;;iBAqCgB,MAAA,WAAiB,MAAA,EAAQ,GAAA,EAAK,CAAA,GAAI,OAAA,CAAQ,CAAA;AAAA,iBAC1C,MAAA,WAAiB,CAAA,CAAE,SAAA,gCAAyC,CAAA,CAAE,KAAA,CAAM,CAAA,GAClF,GAAA,EAAK,CAAA,EACL,MAAA,EAAQ,CAAA,GACP,CAAA,CAAE,KAAA,CAAM,CAAA,EAAG,CAAA;;;AAzCqD;AAqCnE;;;;;;;;;;;;iBAyBgB,SAAA;;;;AAzB2C;AAC3D;;iBAuDgB,aAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;AApDD;AAqBf;;;;AAAyB;AA+BzB;iBAsCgB,iBAAA,UACd,MAAA,EAAQ,OAAA,mBACS,OAAA,GAAU,MAAA,oBAA0B,iBAAA,CAAkB,OAAA;;;AAxC5C;AAsC7B;;;;KAyBY,GAAA;EACV,IAAA;EACA,QAAA;EACA,SAAA;AAAA;;;;;;AA9V8C;;;;KCS3C,SAAA,sBAA+B,MAAA,oBAA0B,CAAA,GAAI,CAAA,GAAI,MAAA;;;;;;;KAQjE,WAAA,wBAAmC,CAAA,SAAU,MAAA,GAAS,OAAA,CAAQ,CAAA,IAAK,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;cA2B3D,aAAA;;AD4Cb;;;;AAAgE;AAsBhE;;;;AAUmB;AAoCnB;;cClGc,GAAA;EDkGwB;;;;;;;;;ECrFpC,GAAA,4BAA+B,GAAA,EAAK,SAAA,CAAU,CAAA,IAAK,WAAA,CAAY,CAAA,EAAG,CAAA;EDqFhC;;;;;EC5ElC,MAAA,KAAW,MAAA,oBAA0B,QAAA,CAAS,MAAA,iBAAuB,QAAA,CAAS,OAAA;ED6E1B;ECxEpD,MAAA;EAMA,YAAA;EAIA,aAAA;EAIA,MAAA;AAAA;;;AD2D2C;AAgC7C;UClFiB,kBAAA,cAAgC,MAAA;EAC/C,GAAA,0BAA6B,IAAA,EAAM,GAAA,EAAK,CAAA,GAAI,IAAA,CAAK,CAAA;EACjD,MAAA,IAAU,QAAA,CAAS,IAAA;EACnB,MAAA;EACA,YAAA;EACA,aAAA;EACA,MAAA;AAAA;;;;;;;;;;AD4EuE;AACzE;;;;;;;;;;;;AAAmE;AAqCnE;;;;;iBCnFgB,mBAAA,WAA8B,CAAA,CAAE,SAAA,OAAgB,MAAA,EAAQ,CAAA;EAAA,QAqC5D,kBAAA,CAAkB,CAAA,CAAA,MAAA,CAAA,CAAA;AAAA"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"interfaces-CayXPOAf.d.mts","names":[],"sources":["../src/core/interfaces.ts"],"mappings":";;;aAGY,KAAA;EACV,SAAA;EACA,SAAA;;EAEA,OAAA;AAAA;;KAIU,WAAA,oBAA+B,IAAA,YAAgB,CAAC;;KAGhD,YAAA,aAAyB,CAAA,GAAI,OAAA,CAAQ,CAAA;AAHjD;AAAA,UAMiB,cAAA;EACf,KAAA,GAAQ,KAAK;AAAA;;KAIH,SAAA,oBACE,CAAA,IAAK,CAAA,CAAE,CAAA,UAAW,QAAA,WAAmB,CAAA,MAAO,KAAA,EAAO,CAAA,CAAE,CAAA,MAAO,SAAA,CAAU,CAAA;EAC9E,KAAA,IAAS,CAAA;AAAA;;UAGE,SAAA;EACf,OAAA,IAAW,SAAS,CAAC,CAAA;AAAA;;KAIX,SAAA;;KAWA,mBAAA;;;;;AA7BsC;AAGlD;;;;AACe;AAIf;;;;;;;;cAyCa,QAAA;EAAA,SACX,UAAA;EAAA,SACA,KAAA;EAAA,SACA,UAAA;EAAA,SACA,SAAA;EAAA,SACA,MAAA;EAAA,SACA,cAAA;EAAA,SACA,WAAA;EAAA,SACA,OAAA;EAAA,SACA,YAAA;EAAA,SACA,MAAA;EAAA,SACA,iBAAA;EAAA,SACA,kBAAA;EAAA,SACA,kBAAA;EAAA,SACA,mBAAA;EAAA,SACA,WAAA;EAAA,SACA,KAAA;EAAA,SACA,KAAA;EAAA,SAEA,WAAA;EAAA,SACA,aAAA;EAAA,SACA,WAAA;AAAA"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"kv-stores-duYHIEr1.d.mts","names":[],"sources":["../src/http/reply.ts","../src/http/middleware/rate-limit-guard.ts","../src/http/middleware/kv-stores.ts"],"mappings":";;;;;;;cAeM,WAAA;;;;;AALyC;UAY9B,KAAA;EAAA,UACL,WAAA;EAAA,SACD,MAAA,EAAQ,CAAA;EAAA,SACR,IAAA,EAAM,CAAA;AAAA;;;;;;;;;;;iBAaD,KAAA,sBAA2B,MAAA,EAAQ,CAAA,EAAG,IAAA,EAAM,CAAA,GAAI,KAAA,CAAM,CAAA,EAAG,CAAA;AAAA,kBAAzD,KAAA;EAAA,iBAKE,IAAA,EAAQ,CAAA,KAAI,KAAA,MAAW,CAAA;EAAA,kBAEtB,IAAA,EAAQ,CAAA,KAAI,KAAA,MAAW,CAAA;EAAA,qBAEpB,KAAA;AAAA;AATtB;;;;;;;;;;;;;;AAAA,KAyBY,oBAAA,MAA0B,CAAA,cAAc,IAAA,0BAC/C,OAAA,CAAQ,OAAA,CAAQ,CAAA,kDAEf,WAAA,CAAY,OAAA,CAAQ,OAAA,CAAQ,CAAA;AAAA,KAG7B,WAAA,MAAiB,CAAA,SAAU,KAAA,oBAAyB,CAAA,GAAI,CAAA;AAAA,iBAE7C,OAAA,CAAQ,KAAA,YAAiB,KAAA,IAAS,KAAK;;;;AAjCmB;;;;;;;;iBAoD1D,kBAAA,CAAmB,GAAA,EAAK,cAAc,EAAE,MAAA;;;UCjFvC,qBAAA;;EAEf,GAAA;EDII;ECFJ,QAAA;;EAEA,OAAA;EDA4C;ECE5C,UAAA;EDKoB;;;;;ECCpB,YAAA,IAAgB,GAAA,EAAK,cAAA;EDEL;ECAhB,OAAA;EDHgD;;;;;ECShD,KAAA,GAAQ,cAAA;EDNQ;ECQhB,IAAA,IAAQ,GAAA,EAAK,cAAA;AAAA;;;;;;;;;;;;;;;;iBAkEC,cAAA,CAAe,OAAA,GAAS,qBAAA,GAA6B,iBAAiB;;;;;;;ADzFvC;;;;AAKD;AAO9C;;;;;;;UEDiB,MAAA;EACf,GAAA,CAAI,GAAA,WAAc,OAAA;EAClB,GAAA,CAAI,GAAA,UAAa,KAAA,UAAe,OAAA;IAAY,aAAA;EAAA,IAA2B,OAAA;EACvE,MAAA,CAAO,GAAA,WAAc,OAAA;AAAA;AAAA,UAQN,uBAAA;EFPC;EEShB,QAAA;EFIc;EEFd,MAAM;AAAA;;;;;;;;;;;cAaK,gBAAA,YAA4B,cAAA;EAAA,iBAKpB,EAAA;EAAA,iBAJF,MAAA;EAAA,iBACA,QAAA;EAEjB,WAAA,CACmB,EAAA,EAAI,MAAA,EACrB,OAAA,EAAS,uBAAA;EAML,SAAA,CAAU,GAAA,WAAc,OAAA;IAAU,SAAA;IAAmB,SAAA,EAAW,IAAA;EAAA;EAahE,SAAA,CAAU,GAAA,WAAc,OAAA;EAQxB,KAAA,CAAM,GAAA,WAAc,OAAA;EAAA,QAIZ,IAAA;EAAA,QAUA,KAAA;AAAA;AAAA,UAOC,qBAAA;EF1DyB;EE4DxC,MAAM;AAAA;;;;;;;;;;;cAaK,cAAA,YAA0B,YAAA;EAAA,iBAIlB,EAAA;EAAA,iBAHF,MAAA;EAEjB,WAAA,CACmB,EAAA,EAAI,MAAA,EACrB,OAAA,GAAS,qBAAA;EAKL,GAAA,CAAI,GAAA,WAAc,OAAA,CAAQ,WAAA;EAU1B,GAAA,CAAI,GAAA,UAAa,IAAA,EAAM,WAAA,EAAa,MAAA,WAAiB,OAAA;EAMrD,OAAA,CAAQ,GAAA,WAAc,OAAA;EAItB,KAAA,CAAM,GAAA,UAAa,MAAA,WAAiB,OAAA;AAAA"}
|
package/dist/query-gMAVXzx2.mjs
DELETED
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @forinda/kickjs v6.5.0
|
|
3
|
-
*
|
|
4
|
-
* Copyright (c) Felix Orinda
|
|
5
|
-
*
|
|
6
|
-
* This source code is licensed under the MIT license found in the
|
|
7
|
-
* LICENSE file in the root directory of this source tree.
|
|
8
|
-
*
|
|
9
|
-
* @license MIT
|
|
10
|
-
*/
|
|
11
|
-
const FILTER_OPERATORS=new Set([`eq`,`neq`,`gt`,`gte`,`lt`,`lte`,`between`,`in`,`contains`,`starts`,`ends`]),BUILTIN_DEFAULTS={maxLimit:100,defaultLimit:20,maxSearchLength:200,defaultPage:1},defaults={...BUILTIN_DEFAULTS};function setQueryParsingDefaults(partial){partial.maxLimit!==void 0&&(defaults.maxLimit=partial.maxLimit),partial.defaultLimit!==void 0&&(defaults.defaultLimit=partial.defaultLimit),partial.maxSearchLength!==void 0&&(defaults.maxSearchLength=partial.maxSearchLength)}function getQueryParsingDefaults(){return{...defaults}}function resetQueryParsingDefaults(){Object.assign(defaults,BUILTIN_DEFAULTS)}function parseFilters(filterParam,allowedFields,options){if(!filterParam)return[];let items=Array.isArray(filterParam)?filterParam:[filterParam],results=[],allowed=allowedFields?new Set(allowedFields):null,onReject=options?.onReject;for(let item of items){let firstColon=item.indexOf(`:`);if(firstColon===-1)continue;let secondColon=item.indexOf(`:`,firstColon+1);if(secondColon===-1)continue;let field=item.slice(0,firstColon),operator=item.slice(firstColon+1,secondColon),value=item.slice(secondColon+1);if(!(!field||!value)){if(!FILTER_OPERATORS.has(operator)){onReject?.({kind:`filter`,field,reason:`unknown-operator`});continue}if(allowed&&!allowed.has(field)){onReject?.({kind:`filter`,field,reason:`field-not-allowed`});continue}results.push({field,operator,value})}}return results}function parseSort(sortParam,allowedFields,options){if(!sortParam)return[];let items=Array.isArray(sortParam)?sortParam:[sortParam],results=[],allowed=allowedFields?new Set(allowedFields):null,onReject=options?.onReject;for(let item of items){let lastColon=item.lastIndexOf(`:`);if(lastColon===-1)continue;let field=item.slice(0,lastColon),dir=item.slice(lastColon+1).toLowerCase();if(field&&!(dir!==`asc`&&dir!==`desc`)){if(allowed&&!allowed.has(field)){onReject?.({kind:`sort`,field,reason:`field-not-allowed`});continue}results.push({field,direction:dir})}}return results}function parsePagination(params,options){let defaultLimit=options?.defaultLimit??defaults.defaultLimit,maxLimit=options?.maxLimit??defaults.maxLimit,page=typeof params.page==`string`?Number.parseInt(params.page,10):params.page??defaults.defaultPage,limit=typeof params.limit==`string`?Number.parseInt(params.limit,10):params.limit??defaultLimit;return(Number.isNaN(page)||page<1)&&(page=defaults.defaultPage),(Number.isNaN(limit)||limit<1)&&(limit=defaultLimit),limit>maxLimit&&(limit=maxLimit),{page,limit,offset:(page-1)*limit}}function parseSearchQuery(q,options){if(!q)return``;let maxLen=options?.maxSearchLength??defaults.maxSearchLength,trimmed=q.trim();return trimmed.length>maxLen?(options?.onReject?.({kind:`search`,field:`q`,reason:`truncated`}),trimmed.slice(0,maxLen)):trimmed}function normalizeFieldConfig(config){if(config)return`columns`in config&&config.columns&&typeof config.columns==`object`?{filterable:Object.keys(config.columns),sortable:config.sortable?Object.keys(config.sortable):void 0,searchable:void 0}:config}function parseQuery(query,fieldConfig,options){let normalized=normalizeFieldConfig(fieldConfig),rejectOpts=options?.onReject?{onReject:options.onReject}:void 0;return{filters:parseFilters(query.filter,normalized?.filterable,rejectOpts),sort:parseSort(query.sort,normalized?.sortable,rejectOpts),pagination:parsePagination({page:query.page,limit:query.limit},options),search:parseSearchQuery(query.q,options)}}function buildQueryParams(parsed){let params={};return parsed.filters?.length&&(params.filter=parsed.filters.map(f=>`${f.field}:${f.operator}:${f.value}`)),parsed.sort?.length&&(params.sort=parsed.sort.map(s=>`${s.field}:${s.direction}`)),parsed.pagination&&(params.page=parsed.pagination.page,params.limit=parsed.pagination.limit),parsed.search&&(params.q=parsed.search),params}export{parseQuery as a,resetQueryParsingDefaults as c,parsePagination as i,setQueryParsingDefaults as l,getQueryParsingDefaults as n,parseSearchQuery as o,parseFilters as r,parseSort as s,buildQueryParams as t,FILTER_OPERATORS as u};
|
|
12
|
-
//# sourceMappingURL=query-gMAVXzx2.mjs.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"rate-limit-oLL5EPUf.d.mts","names":[],"sources":["../src/http/middleware/rate-limit.ts"],"mappings":";;;;UAIiB,cAAA;EACf,SAAA,CAAU,GAAA,WAAc,OAAA;IAAU,SAAA;IAAmB,SAAA,EAAW,IAAA;EAAA;EAChE,SAAA,CAAU,GAAA,WAAc,OAAA;EACxB,KAAA,CAAM,GAAA,WAAc,OAAA;AAAA;AAAA,UAGL,gBAAA;EAHY;EAK3B,GAAA;EAPA;EASA,QAAA;EATwB;EAWxB,OAAA;EAXqD;EAarD,UAAA;EAZA;EAcA,YAAA,IAAgB,GAAA,EAAK,OAAA;EAdG;EAgBxB,OAAA;EAfM;EAiBN,KAAA,GAAQ,cAAA;EAjBmB;EAmB3B,IAAA,IAAQ,GAAA,EAAK,OAAA;EAhBE;EAkBf,SAAA;AAAA;;;;;;;;;;;;;;;;;;;;;iBAsFc,SAAA,CAAU,OAAA,GAAS,gBAAA,IAAqB,GAAA,EAWnC,OAAA,EAAO,GAAA,EAAO,QAAA,EAAQ,IAAA,EAAQ,YAAA,KAAY,OAAA,QAAA,QAAA,MAAA,MAAA"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"reactivity-XL0fFDvG.d.mts","names":[],"sources":["../src/core/reactivity.ts"],"mappings":";;;AAgFA;;;;UAAiB,GAAA;EACf,KAAA,EAAO,CAAA;EASG;EAPV,SAAA,CAAU,EAAA,GAAK,QAAA,EAAU,CAAA,EAAG,QAAA,EAAU,CAAA;EAO3B;;;;;;EAAX,MAAA,IAAU,CAAA;AAAA;;;;;;AAAC;AAab;;;;iBAAgB,GAAA,IAAO,YAAA,EAAc,CAAA,GAAI,GAAA,CAAI,CAAA;AAAA,UAuC5B,WAAA;EAAA,SACN,KAAA,EAAO,CAAA;EAxC0B;;;;;EA8C1C,MAAA,IAAU,CAAC;EA9CiC;AAAA;AAuC9C;;;;;;EAgBE,OAAA;AAAA;;;;AAAO;AAeT;;;;;;;;iBAAgB,QAAA,IAAY,MAAA,QAAc,CAAA,GAAI,WAAA,CAAY,CAAA;AAAA,UA4DzC,YAAA;EA5DW;EA8D1B,SAAS;AAAA;AAAA,KAGN,WAAA,MAAiB,GAAA,CAAI,CAAA,IAAK,WAAA,CAAY,CAAA,WAAY,CAAA;AAjEI;AA4D3D;;;;AAEW;AACV;;;;;;;;AA/D0D,iBAiF3C,KAAA,IACd,MAAA,EAAQ,WAAA,CAAY,CAAA,GACpB,QAAA,GAAW,QAAA,EAAU,CAAA,EAAG,QAAA,EAAU,CAAA,WAClC,OAAA,GAAU,YAAA;AAAA,iBAwDI,QAAA,WAAmB,MAAA,eAAqB,MAAA,EAAQ,CAAA,GAAI,CAAA;;iBA8BpD,KAAA,CAAM,KAAA,QAAa,KAAA,IAAS,GAAG;;iBAK/B,KAAA,IAAS,KAAA,EAAO,GAAA,CAAI,CAAA,IAAK,CAAA,GAAI,CAAA;;iBAK7B,MAAA,WAAiB,MAAA,eAAqB,GAAA,EAAK,CAAA,iBAAkB,CAAA,GAAI,GAAA,CAAI,CAAA,CAAE,CAAA"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"request-id-IDobbxU-.d.mts","names":[],"sources":["../src/http/middleware/request-id.ts"],"mappings":";;;;cAEa,iBAAA;;AAAb;;;;AAA8B;AAY9B;;;;iBAAgB,SAAA,KAAS,GAAA,EACV,OAAA,EAAO,GAAA,EAAO,QAAA,EAAQ,IAAA,EAAQ,YAAA"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"request-logger-DZVW6VNI.d.mts","names":[],"sources":["../src/http/middleware/request-logger.ts"],"mappings":";;;;UAGiB,oBAAA;;EAEf,IAAA;EAFmC;EAInC,KAAA;EAJmC;EAMnC,IAAA;AAAA;;;AAAI;AAmBN;;;;;;;;;;;;;iBAAgB,aAAA,CAAc,OAAA,GAAS,oBAAA,IAAyB,GAAA,EAKjD,OAAA,EAAO,GAAA,EAAO,QAAA,EAAQ,IAAA,EAAQ,YAAA"}
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @forinda/kickjs v6.5.0
|
|
3
|
-
*
|
|
4
|
-
* Copyright (c) Felix Orinda
|
|
5
|
-
*
|
|
6
|
-
* This source code is licensed under the MIT license found in the
|
|
7
|
-
* LICENSE file in the root directory of this source tree.
|
|
8
|
-
*
|
|
9
|
-
* @license MIT
|
|
10
|
-
*/
|
|
11
|
-
import{createRequire}from"node:module";var __require=createRequire(import.meta.url);export{__require as t};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"router-builder-GWgxoOdC.d.mts","names":[],"sources":["../src/http/router-builder.ts"],"mappings":";;;;;iBA+BgB,8BAAA,CAA+B,OAAuC,WAArB,mBAAmB;;;;AAAE;AActF;;;;;;iBAAgB,iBAAA,CACd,QAAA,EAAU,GAAG,kBACb,MAAA,UACA,QAAA,UACA,KAAA;AAAA,UAUe,kBAAA;EAVf;;AAAa;AAUf;;;EAOE,eAAA,YAA2B,mBAAmB;AAAA;AAuBhD;;;;;;;;;AAGa;;;;;;;;;;;AAHb,iBAAgB,eAAA,CACd,eAAA,OACA,OAAA,GAAS,kBAAA,GACR,UAAU"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"session-DSRA-PUX.d.mts","names":[],"sources":["../src/http/middleware/session.ts"],"mappings":";;;;UAKiB,WAAA;EAAA,CACd,GAAW;AAAA;AAAA,UAGG,YAAA;EACf,GAAA,CAAI,GAAA,WAAc,OAAA,CAAQ,WAAA;EAC1B,GAAA,CAAI,GAAA,UAAa,IAAA,EAAM,WAAA,EAAa,MAAA,WAAiB,OAAA;EACrD,OAAA,CAAQ,GAAA,WAAc,OAAA;EACtB,KAAA,EAAO,GAAA,UAAa,MAAA,WAAiB,OAAA;AAAA;AAAA,UAGtB,OAAA;EACf,EAAA;EACA,IAAA,EAAM,WAAA;EACN,UAAA,IAAc,OAAA;EACd,OAAA,IAAW,OAAA;EACX,IAAA,IAAQ,OAAA;AAAA;AAAA,UAGO,cAAA;EAX6B;EAa5C,MAAA;EAhBI;EAkBJ,UAAA;EAlB0B;EAoB1B,MAAA;EAnBI;EAqBJ,OAAA;EArBiB;EAuBjB,iBAAA;EAvBqD;EAyBrD,MAAA;IACE,QAAA;IACA,MAAA;IACA,QAAA;IACA,IAAA;IACA,MAAA;EAAA;EA5B0C;EA+B5C,KAAA,GAAQ,YAAY;AAAA;;;;;;;;;;;;;;;;;;;AAvBL;AAGjB;;;;;iBA2JgB,OAAA,CAAQ,OAAA,EAAS,cAAA,IAAc,GAAA,EAoB1B,OAAA,EAAO,GAAA,EAAO,QAAA,EAAQ,IAAA,EAAQ,YAAA,KAAY,OAAA"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"spa-DWzSWAzx.d.mts","names":[],"sources":["../src/http/middleware/spa.ts"],"mappings":";;;;UAMiB,iBAAA;;AAAjB;;;;;;;;;;AAiDmB;AAkCnB;EArEE,SAAA;;;;;;;;;;;EAYA,SAAA;EA0DA;;;;;;;;;EA/CA,OAAA;EAiEA;;;;EA3DA,YAAA;EAoGc;;;;EA9Fd,iBAAA;AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;cAkCW,UAAA,YAAsB,UAAA;EAAA,QASb,OAAA;EARpB,IAAA;EAAA,QACQ,SAAA;EAAA,QACA,WAAA;EAAA,QACA,YAAA;EAAA,QACA,YAAA;EAAA,QACA,iBAAA;EAAA,QACA,SAAA;EAER,WAAA,CAAoB,OAAA,GAAS,iBAAA;EAU7B,WAAA;IAAc;EAAA,GAAO,cAAA;EAyCrB,WAAA;IAAc;EAAA,GAAO,cAAA;AAAA"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"upload-CIZc803m.d.mts","names":[],"sources":["../src/http/middleware/upload-config.ts","../src/http/middleware/upload.ts"],"mappings":";;;;;;;;;;AAuEA;;;;AAAgD;AAchD;iBAdgB,gBAAA,CAAiB,KAAe;;;;;;;;iBAchC,mBAAA,CACd,YAAA,EAAc,iBAAA,kBACd,aAAA,GAAgB,MAAM,oBACpB,QAAA,UAAkB,QAAA;;UAYL,gBAAA;EACf,SAAA;EACA,YAAA;EACA,QAAA;EACA,QAAA;EACA,IAAA;EACA,MAAA,EAAQ,MAAM;AAAA;;UAIC,aAAA;EACf,SAAA;EACA,QAAA;EACA,QAAA;EACA,MAAA,EAAQ,MAAM;AAAA;;;;;;;;iBAYA,iBAAA,CACd,KAAA,EAAO,aAAA,IACP,MAAA,EAAQ,gBAAA;EACL,IAAA,GAAO,gBAAA;EAAkB,KAAA,GAAQ,gBAAA;AAAA;;;;;AA1DtC;;;UCtBiB,aAAA,SAAsB,iBAAiB;EDsBR;ECpB9C,OAAA,GAAU,OAAA;EDkCuB;EChCjC,IAAA;AAAA;;;;;;;;ADmCoC;AAYtC;;;;iBCLS,MAAA,CAAO,SAAA,UAAmB,OAAA,GAAS,aAAA,GAAqB,cAAc;;;;iBAQtE,KAAA,CAAM,SAAA,UAAmB,QAAA,WAAe,OAAA,GAAS,aAAA,GAAqB,cAAc;;;;iBAQpF,IAAA,CAAK,OAAA,GAAS,aAAA,GAAqB,cAAc;ADD1D;;;;;;;;;;AAIgB;AAYhB;;;AAhBA,iBCoBgB,YAAA,KAAY,GAAA,EACb,OAAA,EAAO,GAAA,EAAO,QAAA,EAAQ,IAAA,EAAQ,YAAA;;;;;;iBA+B7B,qBAAA,CAAsB,MAAA,EAAQ,gBAAA,GAAmB,cAAc;;cAmBlE,MAAA"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"validate-DoZDOhCi.d.mts","names":[],"sources":["../src/http/middleware/validate.ts"],"mappings":";;;;UAMiB,gBAAA;EACf,IAAA;EACA,KAAA;EACA,MAAA;AAAA;;;;;;AAAM;AAgDR;;;;;;;iBAAgB,QAAA,CAAS,MAAA,EAAQ,gBAAA,IAAgB,GAAA,EAClC,OAAA,EAAO,IAAA,EAAQ,QAAA,EAAQ,IAAA,EAAQ,YAAA"}
|