@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.
Files changed (208) hide show
  1. package/dist/{adapter-CEt1MEdF.d.mts → adapter-CbMq-NBf.d.mts} +25 -381
  2. package/dist/adapter-CbMq-NBf.d.mts.map +1 -0
  3. package/dist/{app-module-BSpHKlhE.d.mts → app-module-DtoySG6l.d.mts} +6 -5
  4. package/dist/app-module-DtoySG6l.d.mts.map +1 -0
  5. package/dist/application-Cl0JlmNY.mjs +12 -0
  6. package/dist/application-Cl0JlmNY.mjs.map +1 -0
  7. package/dist/{application-Bzdzl5wP.d.mts → application-zlzYGgKD.d.mts} +6 -6
  8. package/dist/application-zlzYGgKD.d.mts.map +1 -0
  9. package/dist/{bootstrap-C1VGQQVF.mjs → bootstrap-DzyWLYpU.mjs} +3 -3
  10. package/dist/{bootstrap-C1VGQQVF.mjs.map → bootstrap-DzyWLYpU.mjs.map} +1 -1
  11. package/dist/{bootstrap-DYexY169.d.mts → bootstrap-Nzgi7K2d.d.mts} +2 -3
  12. package/dist/bootstrap-Nzgi7K2d.d.mts.map +1 -0
  13. package/dist/{cache-CwZzIH0D.d.mts → cache-C0qL0NSD.d.mts} +2 -1
  14. package/dist/cache-C0qL0NSD.d.mts.map +1 -0
  15. package/dist/config/index.d.mts +1 -1
  16. package/dist/config/index.mjs +2 -2
  17. package/dist/{config-BeIZJBXA.mjs → config-CwFPFwsN.mjs} +3 -3
  18. package/dist/{config-BeIZJBXA.mjs.map → config-CwFPFwsN.mjs.map} +1 -1
  19. package/dist/{container-iED1swkd.d.mts → container-BW_MlgLj.d.mts} +3 -2
  20. package/dist/container-BW_MlgLj.d.mts.map +1 -0
  21. package/dist/{container-CBaL5lus.mjs → container-C7kmdVwh.mjs} +3 -3
  22. package/dist/{container-CBaL5lus.mjs.map → container-C7kmdVwh.mjs.map} +1 -1
  23. package/dist/{context-BS5o1IuU.mjs → context-DQaUwwQM.mjs} +3 -3
  24. package/dist/{context-BS5o1IuU.mjs.map → context-DQaUwwQM.mjs.map} +1 -1
  25. package/dist/{context-errors-CwD27Vbj.mjs → context-errors-97x9siRx.mjs} +2 -2
  26. package/dist/{context-errors-CwD27Vbj.mjs.map → context-errors-97x9siRx.mjs.map} +1 -1
  27. package/dist/core/adapter.d.mts +1 -1
  28. package/dist/core/adapter.mjs +1 -1
  29. package/dist/core/app-module.d.mts +1 -1
  30. package/dist/core/app-module.mjs +1 -1
  31. package/dist/core/cache.d.mts +1 -1
  32. package/dist/core/cache.mjs +1 -1
  33. package/dist/core/container.d.mts +1 -1
  34. package/dist/core/container.mjs +2 -2
  35. package/dist/core/cron.mjs +2 -2
  36. package/dist/core/decorators.d.mts +1 -1
  37. package/dist/core/decorators.mjs +2 -2
  38. package/dist/core/errors.d.mts +1 -1
  39. package/dist/core/errors.mjs +1 -1
  40. package/dist/core/interfaces.d.mts +1 -1
  41. package/dist/core/interfaces.mjs +1 -1
  42. package/dist/core/logger.mjs +1 -1
  43. package/dist/core/path.mjs +1 -1
  44. package/dist/core/plugin.d.mts +1 -1
  45. package/dist/core/plugin.mjs +1 -1
  46. package/dist/core/reactivity.d.mts +1 -1
  47. package/dist/core/reactivity.mjs +1 -1
  48. package/dist/core-CLmwVWlw.mjs +12 -0
  49. package/dist/core-CLmwVWlw.mjs.map +1 -0
  50. package/dist/{cors-C4aSCD3J.d.mts → cors-BuDU9CpA.d.mts} +1 -2
  51. package/dist/cors-BuDU9CpA.d.mts.map +1 -0
  52. package/dist/cron-DOOtTY4q.d.mts.map +1 -1
  53. package/dist/{csrf-DNh_7aOk.mjs → csrf-BsrsObK-.mjs} +2 -2
  54. package/dist/{csrf-DNh_7aOk.mjs.map → csrf-BsrsObK-.mjs.map} +1 -1
  55. package/dist/{csrf-7nUXGTuz.d.mts → csrf-vR23CJas.d.mts} +1 -2
  56. package/dist/csrf-vR23CJas.d.mts.map +1 -0
  57. package/dist/{decorators-wEJBqXHg.d.mts → decorators-Bks7cgBJ.d.mts} +12 -7
  58. package/dist/decorators-Bks7cgBJ.d.mts.map +1 -0
  59. package/dist/{disposables-mnjJuaVx.mjs → disposables-D46xX96x.mjs} +2 -2
  60. package/dist/{disposables-mnjJuaVx.mjs.map → disposables-D46xX96x.mjs.map} +1 -1
  61. package/dist/env-Biq_60jq.mjs +13 -0
  62. package/dist/{env-Dgtjncd5.mjs.map → env-Biq_60jq.mjs.map} +1 -1
  63. package/dist/{error-handler-DR01K_rI.d.mts → error-handler-Cr6Yt9as.d.mts} +1 -2
  64. package/dist/error-handler-Cr6Yt9as.d.mts.map +1 -0
  65. package/dist/{errors-n0H96eEz.d.mts → errors-By6UueCm.d.mts} +18 -9
  66. package/dist/errors-By6UueCm.d.mts.map +1 -0
  67. package/dist/{handler-UvmjQGYc.mjs → handler-Ci1NMv-9.mjs} +3 -3
  68. package/dist/{handler-UvmjQGYc.mjs.map → handler-Ci1NMv-9.mjs.map} +1 -1
  69. package/dist/{helmet-CKzZzeNl.d.mts → helmet-CFQUTVig.d.mts} +1 -2
  70. package/dist/helmet-CFQUTVig.d.mts.map +1 -0
  71. package/dist/http/application.d.mts +1 -1
  72. package/dist/http/application.mjs +2 -2
  73. package/dist/http/bootstrap.d.mts +1 -1
  74. package/dist/http/bootstrap.mjs +2 -2
  75. package/dist/http/context.d.mts +2 -2
  76. package/dist/http/context.mjs +2 -2
  77. package/dist/http/middleware/cors.d.mts +1 -1
  78. package/dist/http/middleware/cors.mjs +1 -1
  79. package/dist/http/middleware/csrf.d.mts +1 -1
  80. package/dist/http/middleware/csrf.mjs +2 -2
  81. package/dist/http/middleware/error-handler.d.mts +1 -1
  82. package/dist/http/middleware/error-handler.mjs +2 -2
  83. package/dist/http/middleware/helmet.d.mts +1 -1
  84. package/dist/http/middleware/helmet.mjs +1 -1
  85. package/dist/http/middleware/rate-limit.d.mts +1 -1
  86. package/dist/http/middleware/rate-limit.mjs +2 -2
  87. package/dist/http/middleware/request-id.d.mts +1 -1
  88. package/dist/http/middleware/request-id.mjs +1 -1
  89. package/dist/http/middleware/request-logger.d.mts +1 -1
  90. package/dist/http/middleware/request-logger.mjs +2 -2
  91. package/dist/http/middleware/session.d.mts +1 -1
  92. package/dist/http/middleware/session.mjs +2 -2
  93. package/dist/http/middleware/spa.d.mts +1 -1
  94. package/dist/http/middleware/spa.mjs +2 -2
  95. package/dist/http/middleware/spa.mjs.map +1 -1
  96. package/dist/http/middleware/upload.d.mts +1 -1
  97. package/dist/http/middleware/upload.mjs +2 -2
  98. package/dist/http/middleware/upload.mjs.map +1 -1
  99. package/dist/http/middleware/validate.d.mts +1 -1
  100. package/dist/http/middleware/validate.mjs +1 -1
  101. package/dist/http/middleware/views.d.mts +1 -1
  102. package/dist/http/middleware/views.mjs +2 -3
  103. package/dist/http/query/index.d.mts +1 -1
  104. package/dist/http/query/index.mjs +2 -2
  105. package/dist/http/router-builder.d.mts +1 -1
  106. package/dist/http/router-builder.mjs +2 -3
  107. package/dist/http/runtimes/fastify.d.mts +1 -2
  108. package/dist/http/runtimes/fastify.d.mts.map +1 -1
  109. package/dist/http/runtimes/fastify.mjs +3 -3
  110. package/dist/http/runtimes/fastify.mjs.map +1 -1
  111. package/dist/http/runtimes/h3-web.d.mts +1 -2
  112. package/dist/http/runtimes/h3-web.d.mts.map +1 -1
  113. package/dist/http/runtimes/h3-web.mjs +2 -2
  114. package/dist/http/runtimes/h3.d.mts +1 -2
  115. package/dist/http/runtimes/h3.d.mts.map +1 -1
  116. package/dist/http/runtimes/h3.mjs +2 -2
  117. package/dist/{index-BtWJ9SLP.d.mts → index-BfT5KZ-M.d.mts} +2 -2
  118. package/dist/index-BfT5KZ-M.d.mts.map +1 -0
  119. package/dist/{index-D98NLfS5.d.mts → index-M6TF75MS.d.mts} +2 -3
  120. package/dist/index-M6TF75MS.d.mts.map +1 -0
  121. package/dist/index.d.mts +26 -26
  122. package/dist/index.mjs +2 -2
  123. package/dist/index.mjs.map +1 -1
  124. package/dist/{interfaces-CayXPOAf.d.mts → interfaces-BTTBdkvG.d.mts} +3 -2
  125. package/dist/interfaces-BTTBdkvG.d.mts.map +1 -0
  126. package/dist/{kv-stores-O8HUSwpv.mjs → kv-stores-BLJdf3Fn.mjs} +2 -2
  127. package/dist/{kv-stores-O8HUSwpv.mjs.map → kv-stores-BLJdf3Fn.mjs.map} +1 -1
  128. package/dist/{kv-stores-duYHIEr1.d.mts → kv-stores-CHowq8VP.d.mts} +5 -6
  129. package/dist/kv-stores-CHowq8VP.d.mts.map +1 -0
  130. package/dist/logger-DA43DvNY.d.mts.map +1 -1
  131. package/dist/{metadata-CUDfhy4e.mjs → metadata-DUBbuHqY.mjs} +2 -2
  132. package/dist/{metadata-CUDfhy4e.mjs.map → metadata-DUBbuHqY.mjs.map} +1 -1
  133. package/dist/{module-registry-Mv5FqVlq.mjs → module-registry-aIt66if2.mjs} +2 -2
  134. package/dist/{module-registry-Mv5FqVlq.mjs.map → module-registry-aIt66if2.mjs.map} +1 -1
  135. package/dist/path-BVA9MfN1.d.mts.map +1 -1
  136. package/dist/query-CXN52dzy.mjs +12 -0
  137. package/dist/{query-gMAVXzx2.mjs.map → query-CXN52dzy.mjs.map} +1 -1
  138. package/dist/{rate-limit-oLL5EPUf.d.mts → rate-limit-Dme747JJ.d.mts} +1 -2
  139. package/dist/rate-limit-Dme747JJ.d.mts.map +1 -0
  140. package/dist/{reactivity-XL0fFDvG.d.mts → reactivity-BkMNA0kp.d.mts} +2 -2
  141. package/dist/reactivity-BkMNA0kp.d.mts.map +1 -0
  142. package/dist/{reply-BMBvs-FB.mjs → reply-C1ljl6xS.mjs} +3 -3
  143. package/dist/{reply-BMBvs-FB.mjs.map → reply-C1ljl6xS.mjs.map} +1 -1
  144. package/dist/{request-id-IDobbxU-.d.mts → request-id-CVzJ1uHD.d.mts} +1 -2
  145. package/dist/request-id-CVzJ1uHD.d.mts.map +1 -0
  146. package/dist/{request-logger-DZVW6VNI.d.mts → request-logger-BU4ulKLp.d.mts} +1 -2
  147. package/dist/request-logger-BU4ulKLp.d.mts.map +1 -0
  148. package/dist/router-builder-BbgVXuy3.mjs +12 -0
  149. package/dist/router-builder-BbgVXuy3.mjs.map +1 -0
  150. package/dist/{router-builder-GWgxoOdC.d.mts → router-builder-CMGhEBU2.d.mts} +2 -3
  151. package/dist/router-builder-CMGhEBU2.d.mts.map +1 -0
  152. package/dist/{session-DSRA-PUX.d.mts → session-z9iewOXA.d.mts} +1 -2
  153. package/dist/session-z9iewOXA.d.mts.map +1 -0
  154. package/dist/{spa-DWzSWAzx.d.mts → spa-DsRUrm69.d.mts} +4 -9
  155. package/dist/spa-DsRUrm69.d.mts.map +1 -0
  156. package/dist/{upload-CIZc803m.d.mts → upload-XVTyQcNN.d.mts} +3 -3
  157. package/dist/upload-XVTyQcNN.d.mts.map +1 -0
  158. package/dist/{upload-config-CFfHvoHF.mjs → upload-config-Dd_QvlpC.mjs} +2 -2
  159. package/dist/{upload-config-CFfHvoHF.mjs.map → upload-config-Dd_QvlpC.mjs.map} +1 -1
  160. package/dist/{validate-DoZDOhCi.d.mts → validate-DMYpUnrf.d.mts} +1 -2
  161. package/dist/validate-DMYpUnrf.d.mts.map +1 -0
  162. package/dist/views-Dj6XFaca.mjs +12 -0
  163. package/dist/views-Dj6XFaca.mjs.map +1 -0
  164. package/dist/views-DsfBT1fR.d.mts +659 -0
  165. package/dist/views-DsfBT1fR.d.mts.map +1 -0
  166. package/dist/web.d.mts +4 -5
  167. package/dist/web.d.mts.map +1 -1
  168. package/dist/web.mjs +2 -2
  169. package/dist/web.mjs.map +1 -1
  170. package/package.json +10 -10
  171. package/dist/adapter-CEt1MEdF.d.mts.map +0 -1
  172. package/dist/app-module-BSpHKlhE.d.mts.map +0 -1
  173. package/dist/application-Bzdzl5wP.d.mts.map +0 -1
  174. package/dist/application-C-r79XqD.mjs +0 -12
  175. package/dist/application-C-r79XqD.mjs.map +0 -1
  176. package/dist/bootstrap-DYexY169.d.mts.map +0 -1
  177. package/dist/cache-CwZzIH0D.d.mts.map +0 -1
  178. package/dist/container-iED1swkd.d.mts.map +0 -1
  179. package/dist/contributor-runner-Cu13cDQp.mjs +0 -12
  180. package/dist/contributor-runner-Cu13cDQp.mjs.map +0 -1
  181. package/dist/core-TDR0XGzO.mjs +0 -12
  182. package/dist/core-TDR0XGzO.mjs.map +0 -1
  183. package/dist/cors-C4aSCD3J.d.mts.map +0 -1
  184. package/dist/csrf-7nUXGTuz.d.mts.map +0 -1
  185. package/dist/decorators-wEJBqXHg.d.mts.map +0 -1
  186. package/dist/env-Dgtjncd5.mjs +0 -13
  187. package/dist/error-handler-DR01K_rI.d.mts.map +0 -1
  188. package/dist/errors-n0H96eEz.d.mts.map +0 -1
  189. package/dist/helmet-CKzZzeNl.d.mts.map +0 -1
  190. package/dist/http/middleware/views.mjs.map +0 -1
  191. package/dist/http/router-builder.mjs.map +0 -1
  192. package/dist/index-BtWJ9SLP.d.mts.map +0 -1
  193. package/dist/index-D98NLfS5.d.mts.map +0 -1
  194. package/dist/interfaces-CayXPOAf.d.mts.map +0 -1
  195. package/dist/kv-stores-duYHIEr1.d.mts.map +0 -1
  196. package/dist/query-gMAVXzx2.mjs +0 -12
  197. package/dist/rate-limit-oLL5EPUf.d.mts.map +0 -1
  198. package/dist/reactivity-XL0fFDvG.d.mts.map +0 -1
  199. package/dist/request-id-IDobbxU-.d.mts.map +0 -1
  200. package/dist/request-logger-DZVW6VNI.d.mts.map +0 -1
  201. package/dist/rolldown-runtime-CuwksmWW.mjs +0 -11
  202. package/dist/router-builder-GWgxoOdC.d.mts.map +0 -1
  203. package/dist/session-DSRA-PUX.d.mts.map +0 -1
  204. package/dist/spa-DWzSWAzx.d.mts.map +0 -1
  205. package/dist/upload-CIZc803m.d.mts.map +0 -1
  206. package/dist/validate-DoZDOhCi.d.mts.map +0 -1
  207. package/dist/views-Kp8Z3AO1.d.mts +0 -275
  208. package/dist/views-Kp8Z3AO1.d.mts.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"handler-UvmjQGYc.mjs","names":[],"sources":["../src/http/web/driver.ts","../src/http/web/handler.ts"],"sourcesContent":["// Web-standard driver pair — the request/response bridge between web\n// primitives (WHATWG Request/Response) and the KickJS RequestContext surface.\n//\n// Deliberately imports NOTHING from node: this module is the edge-safe core\n// shared by the h3 v2 runtime (`runtimes/h3-web.ts`, node bootstrap) and the\n// `@forinda/kickjs/web` fetch entry (edge/Bun/Deno). See\n// `web-standards-edge-design.md` §3.1.\n\nimport type { RuntimeResponse } from '../runtime'\n\n/**\n * Presents a web `Request` as the express-shaped `req` object that\n * `RequestContext` (and route validation) reads: plain-object `headers`,\n * assignable `body`/`params`/`query`, and `on/once('close')` bridged from\n * the request's `AbortSignal` — the only EventEmitter surface the context\n * layer uses (`ctx.signal`, SSE close).\n */\nexport class WebRequestShim {\n readonly method: string\n readonly url: string\n /** Lower-cased plain header object (RequestContext indexes it directly). */\n readonly headers: Record<string, string>\n body: unknown\n params: Record<string, string> = {}\n query: Record<string, unknown> = {}\n requestId?: string\n file?: unknown\n files?: unknown;\n // Ad-hoc props middleware may set (session, user, ...) — index signature\n // keeps assignment open like a node req object.\n [key: string]: unknown\n\n private readonly signal: AbortSignal\n\n constructor(request: Request, url: URL) {\n this.method = request.method\n // Express-shaped `req.url` is path + search, not the absolute URL.\n this.url = url.pathname + url.search\n this.signal = request.signal\n const headers: Record<string, string> = {}\n request.headers.forEach((value, key) => {\n headers[key] = value\n })\n this.headers = headers\n const query: Record<string, unknown> = {}\n for (const key of url.searchParams.keys()) {\n const all = url.searchParams.getAll(key)\n query[key] = all.length > 1 ? all : all[0]\n }\n this.query = query\n }\n\n /** `req.once('close')` — abort of the underlying request signal. */\n once(event: string, listener: () => void): this {\n if (event === 'close') this.signal.addEventListener('abort', listener, { once: true })\n return this\n }\n\n /** `req.on('close')` — same bridge; signals only abort once anyway. */\n on(event: string, listener: () => void): this {\n return this.once(event, listener)\n }\n}\n\nconst encoder = new TextEncoder()\n\nfunction toBytes(chunk: unknown): Uint8Array {\n if (chunk instanceof Uint8Array) return chunk\n return encoder.encode(String(chunk))\n}\n\n/**\n * `RuntimeResponse` over a web `Response`.\n *\n * Two modes:\n * - **Buffered** (default): `status/json/send/type/setHeader` record state;\n * the terminal call resolves {@link ready} with a complete `Response`.\n * - **Streaming**: the first `writeHead`/`flushHeaders`/`write` call switches\n * to a `TransformStream` and resolves {@link ready} IMMEDIATELY with a\n * streamed `Response` — SSE works on edge this way; `write` feeds the\n * writer, `end` closes it.\n *\n * A class so the method table lives on a shared prototype (one allocation\n * per request — same rationale as the Fastify/h3 driver classes).\n */\nexport class WebResponseDriver implements RuntimeResponse {\n /** Resolves with the final (or streamed) Response. */\n readonly ready: Promise<Response>\n /** True once a terminal/streaming action produced the Response. */\n settled = false\n\n private _status = 200\n private readonly headers = new Headers()\n private _headersSent = false\n private writer?: WritableStreamDefaultWriter<Uint8Array>\n private resolveReady!: (response: Response) => void\n\n constructor(private readonly signal?: AbortSignal) {\n this.ready = new Promise<Response>((resolve) => {\n this.resolveReady = resolve\n })\n }\n\n status(code: number): this {\n this._status = code\n return this\n }\n\n json(data: unknown): this {\n if (!this.headers.has('content-type'))\n this.headers.set('content-type', 'application/json; charset=utf-8')\n return this.finish(JSON.stringify(data))\n }\n\n send(data: unknown): this {\n if (\n data !== undefined &&\n data !== null &&\n typeof data === 'object' &&\n !(data instanceof Uint8Array)\n ) {\n return this.json(data)\n }\n return this.finish(data as string | Uint8Array | null | undefined)\n }\n\n type(contentType: string): this {\n this.headers.set('content-type', contentType)\n return this\n }\n\n setHeader(name: string, value: unknown): this {\n if (Array.isArray(value)) {\n this.headers.delete(name)\n for (const v of value) this.headers.append(name, String(v))\n } else {\n this.headers.set(name, String(value))\n }\n return this\n }\n\n render(): never {\n throw new Error('ctx.render() is not supported on the web runtime (no view engine).')\n }\n\n writeHead(statusCode: number, headers?: Record<string, string | number | string[]>): this {\n this._status = statusCode\n if (headers) {\n for (const [name, value] of Object.entries(headers)) this.setHeader(name, value)\n }\n this.startStream()\n return this\n }\n\n flushHeaders(): this {\n this.startStream()\n return this\n }\n\n write(chunk: unknown): boolean {\n this.startStream()\n // Fire-and-forget: backpressure is absorbed by the stream's queue. Write\n // failures (client gone) surface via the abort listener, not here.\n void this.writer!.write(toBytes(chunk)).catch(() => {})\n return true\n }\n\n end(data?: unknown): this {\n if (this.writer) {\n if (data !== undefined) this.write(data)\n void this.writer.close().catch(() => {})\n this.writer = undefined\n return this\n }\n return this.finish(data as string | Uint8Array | null | undefined)\n }\n\n once(event: string, listener: (...args: unknown[]) => void): this {\n if (event === 'close' && this.signal)\n this.signal.addEventListener('abort', listener as () => void, { once: true })\n return this\n }\n\n get headersSent(): boolean {\n return this._headersSent\n }\n\n /** Buffered terminal: build the final Response exactly once. */\n private finish(body?: string | Uint8Array | null): this {\n if (this.settled) return this\n this.settled = true\n this._headersSent = true\n // 204/304 must not carry a body per the Response constructor contract.\n const bodyAllowed = this._status !== 204 && this._status !== 304\n this.resolveReady(\n new Response(bodyAllowed ? (body ?? null) : null, {\n status: this._status,\n headers: this.headers,\n }),\n )\n return this\n }\n\n /** Switch to streaming mode and resolve `ready` with the streamed Response. */\n private startStream(): void {\n if (this.writer || this.settled) return\n const { readable, writable } = new TransformStream<Uint8Array, Uint8Array>()\n this.writer = writable.getWriter()\n this.settled = true\n this._headersSent = true\n // Abort from the client tears the stream down so the writer stops queueing.\n this.signal?.addEventListener(\n 'abort',\n () => {\n void this.writer?.abort().catch(() => {})\n this.writer = undefined\n },\n { once: true },\n )\n this.resolveReady(new Response(readable, { status: this._status, headers: this.headers }))\n }\n}\n","// Engine-neutral web pipeline: run one KickJS RouteEntry against a WHATWG\n// Request and produce a WHATWG Response. Shared by the h3 v2 runtime\n// (node bootstrap) and the `@forinda/kickjs/web` fetch entry (edge/Bun/Deno).\n// Edge-safe: no node imports beyond the sanctioned ALS request store.\n\nimport { RequestContext } from '../context'\nimport { applyHandlerResult } from '../reply'\nimport { requestStore } from '../request-store'\nimport { createRequestStore, disposeRequestStore } from '../middleware/request-scope'\nimport { validate } from '../middleware/validate'\nimport { applyUploadConfig, type RawUploadPart } from '../middleware/upload-config'\nimport type { RouteEntry, RuntimeResponse } from '../runtime'\nimport { WebRequestShim, WebResponseDriver } from './driver'\nimport { createLogger, describeError } from '../../core/logger'\n\nconst log = createLogger('WebPipeline')\nconst NOOP_NEXT = (): void => {}\nconst BODY_METHODS = new Set(['POST', 'PUT', 'PATCH', 'DELETE'])\n\nexport interface WebRouteInvocation {\n request: Request\n url: URL\n params: Record<string, string>\n}\n\nexport interface WebRouteHooks {\n /**\n * Error bridge — receives pipeline rejections (validation failures,\n * handler throws) with the shim + driver so an engine can dispatch the\n * framework's connect-style error handler. When absent (or when it\n * doesn't settle the driver), a minimal JSON error is produced from\n * `err.status`/`err.statusCode` (500 default).\n */\n onError?: (err: unknown, req: WebRequestShim, res: WebResponseDriver) => void | Promise<void>\n}\n\n/**\n * Fallback error shape when no engine error handler settles the response.\n *\n * This path used to be completely silent: a bare\n * `{ error: 'Internal Server Error' }` with no log line anywhere, so a\n * failure that reached here left no trace on either side. It is a\n * last-resort branch, which is exactly when diagnostics matter most.\n */\nfunction defaultErrorResponse(err: unknown, driver: WebResponseDriver): void {\n const status =\n typeof (err as { status?: number })?.status === 'number'\n ? (err as { status: number }).status\n : typeof (err as { statusCode?: number })?.statusCode === 'number'\n ? (err as { statusCode: number }).statusCode\n : 500\n\n if (status >= 500) {\n log.error(err, `Unhandled error in web pipeline — ${describeError(err)}`)\n const stack = (err as Error)?.stack\n driver.status(status).json({\n error: 'Internal Server Error',\n ...(isProduction()\n ? {}\n : {\n message: describeError(err),\n ...(typeof stack === 'string' ? { stack: stack.split('\\n') } : {}),\n }),\n })\n return\n }\n\n driver.status(status).json({ error: (err as Error)?.message ?? 'Request failed' })\n}\n\n/**\n * Read per-call, not at module scope: the web entry is imported once and\n * reused across invocations, and edge runtimes may not expose `process`.\n */\nfunction isProduction(): boolean {\n return typeof process !== 'undefined' && process.env?.NODE_ENV === 'production'\n}\n\n/**\n * Compile a RouteEntry into a `(invocation) => Promise<Response>` function.\n * Everything derivable at route-build time (validator, upload config) is\n * hoisted here — per-request work is shim + store + pipeline only.\n */\nexport function compileWebRoute(\n entry: RouteEntry,\n hooks?: WebRouteHooks,\n): (invocation: WebRouteInvocation) => Promise<Response> {\n const validator = entry.meta.validation ? validate(entry.meta.validation) : undefined\n const upload = entry.meta.upload && entry.meta.upload.mode !== 'none' ? entry.meta.upload : null\n\n return async ({ request, url, params }) => {\n const req = new WebRequestShim(request, url)\n req.params = params\n\n // Body: uploads consume the stream as FormData; everything else parses\n // by content-type. A failed parse leaves body undefined (validation\n // rejects it downstream if the route demands a shape).\n if (upload) {\n const form = await request.formData().catch(() => undefined)\n if (form) {\n const rawParts: RawUploadPart[] = []\n const fields: Record<string, unknown> = {}\n for (const [name, value] of form.entries()) {\n if (typeof value === 'string') {\n fields[name] = value\n } else {\n rawParts.push({\n fieldname: name,\n filename: value.name ?? '',\n mimetype: value.type || 'application/octet-stream',\n buffer: new Uint8Array(await value.arrayBuffer()) as unknown as Buffer,\n })\n }\n }\n const { file, files } = applyUploadConfig(rawParts, entry.meta.upload!)\n req.file = file\n req.files = files\n req.body = fields\n }\n } else if (BODY_METHODS.has(request.method)) {\n const contentType = req.headers['content-type'] ?? ''\n if (contentType.includes('application/json')) {\n req.body = await request.json().catch(() => undefined)\n } else if (contentType.includes('application/x-www-form-urlencoded')) {\n const text = await request.text().catch(() => '')\n req.body = Object.fromEntries(new URLSearchParams(text))\n } else if (contentType.startsWith('text/')) {\n req.body = await request.text().catch(() => undefined)\n }\n }\n\n const store = createRequestStore(req.headers['x-request-id'])\n req.requestId = store.requestId\n\n const driver = new WebResponseDriver(request.signal)\n driver.setHeader('x-request-id', store.requestId)\n\n const pipeline = requestStore.run(store, async () => {\n const ctx = new RequestContext(\n req as never,\n driver as never,\n NOOP_NEXT,\n driver as RuntimeResponse,\n )\n\n if (validator) {\n await new Promise<void>((resolve, reject) => {\n validator(req as never, undefined as never, (err?: unknown) =>\n err ? reject(err) : resolve(),\n )\n })\n }\n\n for (const mw of entry.middlewares) {\n let advanced = false\n await new Promise<void>((resolve, reject) => {\n const next = (err?: unknown): void => {\n advanced = true\n if (err) reject(err)\n else resolve()\n }\n Promise.resolve(mw(ctx, next)).catch(reject)\n })\n if (!advanced || driver.settled) return\n }\n\n if (entry.contributorRunner) await entry.contributorRunner(ctx)\n if (driver.settled) return\n const result = await entry.handler(ctx)\n // Return-value handlers (reply.ts): auto-send when nothing was written.\n // `undefined` falls through to the canonical 404 below.\n if (!driver.settled) applyHandlerResult(ctx, result)\n })\n\n try {\n // Streaming responses resolve `ready` mid-pipeline (SSE); buffered ones\n // resolve at the terminal ctx call. Race so both shapes return promptly.\n try {\n await Promise.race([pipeline, driver.ready])\n } catch (err) {\n if (!driver.settled) {\n if (hooks?.onError) await hooks.onError(err, req, driver)\n if (!driver.settled) defaultErrorResponse(err, driver)\n }\n }\n if (!driver.settled) {\n // Pipeline finished without responding — canonical 404 shape.\n driver.status(404).json({ error: 'Not Found' })\n }\n return await driver.ready\n } finally {\n // @PreDestroy teardown. For buffered responses this runs post-response;\n // for streams it runs when the pipeline (not the stream) completes —\n // stream lifetime is governed by the client abort signal.\n void Promise.resolve(pipeline)\n .catch(() => {})\n .then(() => disposeRequestStore(store))\n }\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"handler-Ci1NMv-9.mjs","names":[],"sources":["../src/http/web/driver.ts","../src/http/web/handler.ts"],"sourcesContent":["// Web-standard driver pair — the request/response bridge between web\n// primitives (WHATWG Request/Response) and the KickJS RequestContext surface.\n//\n// Deliberately imports NOTHING from node: this module is the edge-safe core\n// shared by the h3 v2 runtime (`runtimes/h3-web.ts`, node bootstrap) and the\n// `@forinda/kickjs/web` fetch entry (edge/Bun/Deno). See\n// `web-standards-edge-design.md` §3.1.\n\nimport type { RuntimeResponse } from '../runtime'\n\n/**\n * Presents a web `Request` as the express-shaped `req` object that\n * `RequestContext` (and route validation) reads: plain-object `headers`,\n * assignable `body`/`params`/`query`, and `on/once('close')` bridged from\n * the request's `AbortSignal` — the only EventEmitter surface the context\n * layer uses (`ctx.signal`, SSE close).\n */\nexport class WebRequestShim {\n readonly method: string\n readonly url: string\n /** Lower-cased plain header object (RequestContext indexes it directly). */\n readonly headers: Record<string, string>\n body: unknown\n params: Record<string, string> = {}\n query: Record<string, unknown> = {}\n requestId?: string\n file?: unknown\n files?: unknown;\n // Ad-hoc props middleware may set (session, user, ...) — index signature\n // keeps assignment open like a node req object.\n [key: string]: unknown\n\n private readonly signal: AbortSignal\n\n constructor(request: Request, url: URL) {\n this.method = request.method\n // Express-shaped `req.url` is path + search, not the absolute URL.\n this.url = url.pathname + url.search\n this.signal = request.signal\n const headers: Record<string, string> = {}\n request.headers.forEach((value, key) => {\n headers[key] = value\n })\n this.headers = headers\n const query: Record<string, unknown> = {}\n for (const key of url.searchParams.keys()) {\n const all = url.searchParams.getAll(key)\n query[key] = all.length > 1 ? all : all[0]\n }\n this.query = query\n }\n\n /** `req.once('close')` — abort of the underlying request signal. */\n once(event: string, listener: () => void): this {\n if (event === 'close') this.signal.addEventListener('abort', listener, { once: true })\n return this\n }\n\n /** `req.on('close')` — same bridge; signals only abort once anyway. */\n on(event: string, listener: () => void): this {\n return this.once(event, listener)\n }\n}\n\nconst encoder = new TextEncoder()\n\nfunction toBytes(chunk: unknown): Uint8Array {\n if (chunk instanceof Uint8Array) return chunk\n return encoder.encode(String(chunk))\n}\n\n/**\n * `RuntimeResponse` over a web `Response`.\n *\n * Two modes:\n * - **Buffered** (default): `status/json/send/type/setHeader` record state;\n * the terminal call resolves {@link ready} with a complete `Response`.\n * - **Streaming**: the first `writeHead`/`flushHeaders`/`write` call switches\n * to a `TransformStream` and resolves {@link ready} IMMEDIATELY with a\n * streamed `Response` — SSE works on edge this way; `write` feeds the\n * writer, `end` closes it.\n *\n * A class so the method table lives on a shared prototype (one allocation\n * per request — same rationale as the Fastify/h3 driver classes).\n */\nexport class WebResponseDriver implements RuntimeResponse {\n /** Resolves with the final (or streamed) Response. */\n readonly ready: Promise<Response>\n /** True once a terminal/streaming action produced the Response. */\n settled = false\n\n private _status = 200\n private readonly headers = new Headers()\n private _headersSent = false\n private writer?: WritableStreamDefaultWriter<Uint8Array>\n private resolveReady!: (response: Response) => void\n\n constructor(private readonly signal?: AbortSignal) {\n this.ready = new Promise<Response>((resolve) => {\n this.resolveReady = resolve\n })\n }\n\n status(code: number): this {\n this._status = code\n return this\n }\n\n json(data: unknown): this {\n if (!this.headers.has('content-type'))\n this.headers.set('content-type', 'application/json; charset=utf-8')\n return this.finish(JSON.stringify(data))\n }\n\n send(data: unknown): this {\n if (\n data !== undefined &&\n data !== null &&\n typeof data === 'object' &&\n !(data instanceof Uint8Array)\n ) {\n return this.json(data)\n }\n return this.finish(data as string | Uint8Array | null | undefined)\n }\n\n type(contentType: string): this {\n this.headers.set('content-type', contentType)\n return this\n }\n\n setHeader(name: string, value: unknown): this {\n if (Array.isArray(value)) {\n this.headers.delete(name)\n for (const v of value) this.headers.append(name, String(v))\n } else {\n this.headers.set(name, String(value))\n }\n return this\n }\n\n render(): never {\n throw new Error('ctx.render() is not supported on the web runtime (no view engine).')\n }\n\n writeHead(statusCode: number, headers?: Record<string, string | number | string[]>): this {\n this._status = statusCode\n if (headers) {\n for (const [name, value] of Object.entries(headers)) this.setHeader(name, value)\n }\n this.startStream()\n return this\n }\n\n flushHeaders(): this {\n this.startStream()\n return this\n }\n\n write(chunk: unknown): boolean {\n this.startStream()\n // Fire-and-forget: backpressure is absorbed by the stream's queue. Write\n // failures (client gone) surface via the abort listener, not here.\n void this.writer!.write(toBytes(chunk)).catch(() => {})\n return true\n }\n\n end(data?: unknown): this {\n if (this.writer) {\n if (data !== undefined) this.write(data)\n void this.writer.close().catch(() => {})\n this.writer = undefined\n return this\n }\n return this.finish(data as string | Uint8Array | null | undefined)\n }\n\n once(event: string, listener: (...args: unknown[]) => void): this {\n if (event === 'close' && this.signal)\n this.signal.addEventListener('abort', listener as () => void, { once: true })\n return this\n }\n\n get headersSent(): boolean {\n return this._headersSent\n }\n\n /** Buffered terminal: build the final Response exactly once. */\n private finish(body?: string | Uint8Array | null): this {\n if (this.settled) return this\n this.settled = true\n this._headersSent = true\n // 204/304 must not carry a body per the Response constructor contract.\n const bodyAllowed = this._status !== 204 && this._status !== 304\n this.resolveReady(\n new Response(bodyAllowed ? (body ?? null) : null, {\n status: this._status,\n headers: this.headers,\n }),\n )\n return this\n }\n\n /** Switch to streaming mode and resolve `ready` with the streamed Response. */\n private startStream(): void {\n if (this.writer || this.settled) return\n const { readable, writable } = new TransformStream<Uint8Array, Uint8Array>()\n this.writer = writable.getWriter()\n this.settled = true\n this._headersSent = true\n // Abort from the client tears the stream down so the writer stops queueing.\n this.signal?.addEventListener(\n 'abort',\n () => {\n void this.writer?.abort().catch(() => {})\n this.writer = undefined\n },\n { once: true },\n )\n this.resolveReady(new Response(readable, { status: this._status, headers: this.headers }))\n }\n}\n","// Engine-neutral web pipeline: run one KickJS RouteEntry against a WHATWG\n// Request and produce a WHATWG Response. Shared by the h3 v2 runtime\n// (node bootstrap) and the `@forinda/kickjs/web` fetch entry (edge/Bun/Deno).\n// Edge-safe: no node imports beyond the sanctioned ALS request store.\n\nimport { RequestContext } from '../context'\nimport { applyHandlerResult } from '../reply'\nimport { requestStore } from '../request-store'\nimport { createRequestStore, disposeRequestStore } from '../middleware/request-scope'\nimport { validate } from '../middleware/validate'\nimport { applyUploadConfig, type RawUploadPart } from '../middleware/upload-config'\nimport type { RouteEntry, RuntimeResponse } from '../runtime'\nimport { WebRequestShim, WebResponseDriver } from './driver'\nimport { createLogger, describeError } from '../../core/logger'\n\nconst log = createLogger('WebPipeline')\nconst NOOP_NEXT = (): void => {}\nconst BODY_METHODS = new Set(['POST', 'PUT', 'PATCH', 'DELETE'])\n\nexport interface WebRouteInvocation {\n request: Request\n url: URL\n params: Record<string, string>\n}\n\nexport interface WebRouteHooks {\n /**\n * Error bridge — receives pipeline rejections (validation failures,\n * handler throws) with the shim + driver so an engine can dispatch the\n * framework's connect-style error handler. When absent (or when it\n * doesn't settle the driver), a minimal JSON error is produced from\n * `err.status`/`err.statusCode` (500 default).\n */\n onError?: (err: unknown, req: WebRequestShim, res: WebResponseDriver) => void | Promise<void>\n}\n\n/**\n * Fallback error shape when no engine error handler settles the response.\n *\n * This path used to be completely silent: a bare\n * `{ error: 'Internal Server Error' }` with no log line anywhere, so a\n * failure that reached here left no trace on either side. It is a\n * last-resort branch, which is exactly when diagnostics matter most.\n */\nfunction defaultErrorResponse(err: unknown, driver: WebResponseDriver): void {\n const status =\n typeof (err as { status?: number })?.status === 'number'\n ? (err as { status: number }).status\n : typeof (err as { statusCode?: number })?.statusCode === 'number'\n ? (err as { statusCode: number }).statusCode\n : 500\n\n if (status >= 500) {\n log.error(err, `Unhandled error in web pipeline — ${describeError(err)}`)\n const stack = (err as Error)?.stack\n driver.status(status).json({\n error: 'Internal Server Error',\n ...(isProduction()\n ? {}\n : {\n message: describeError(err),\n ...(typeof stack === 'string' ? { stack: stack.split('\\n') } : {}),\n }),\n })\n return\n }\n\n driver.status(status).json({ error: (err as Error)?.message ?? 'Request failed' })\n}\n\n/**\n * Read per-call, not at module scope: the web entry is imported once and\n * reused across invocations, and edge runtimes may not expose `process`.\n */\nfunction isProduction(): boolean {\n return typeof process !== 'undefined' && process.env?.NODE_ENV === 'production'\n}\n\n/**\n * Compile a RouteEntry into a `(invocation) => Promise<Response>` function.\n * Everything derivable at route-build time (validator, upload config) is\n * hoisted here — per-request work is shim + store + pipeline only.\n */\nexport function compileWebRoute(\n entry: RouteEntry,\n hooks?: WebRouteHooks,\n): (invocation: WebRouteInvocation) => Promise<Response> {\n const validator = entry.meta.validation ? validate(entry.meta.validation) : undefined\n const upload = entry.meta.upload && entry.meta.upload.mode !== 'none' ? entry.meta.upload : null\n\n return async ({ request, url, params }) => {\n const req = new WebRequestShim(request, url)\n req.params = params\n\n // Body: uploads consume the stream as FormData; everything else parses\n // by content-type. A failed parse leaves body undefined (validation\n // rejects it downstream if the route demands a shape).\n if (upload) {\n const form = await request.formData().catch(() => undefined)\n if (form) {\n const rawParts: RawUploadPart[] = []\n const fields: Record<string, unknown> = {}\n for (const [name, value] of form.entries()) {\n if (typeof value === 'string') {\n fields[name] = value\n } else {\n rawParts.push({\n fieldname: name,\n filename: value.name ?? '',\n mimetype: value.type || 'application/octet-stream',\n buffer: new Uint8Array(await value.arrayBuffer()) as unknown as Buffer,\n })\n }\n }\n const { file, files } = applyUploadConfig(rawParts, entry.meta.upload!)\n req.file = file\n req.files = files\n req.body = fields\n }\n } else if (BODY_METHODS.has(request.method)) {\n const contentType = req.headers['content-type'] ?? ''\n if (contentType.includes('application/json')) {\n req.body = await request.json().catch(() => undefined)\n } else if (contentType.includes('application/x-www-form-urlencoded')) {\n const text = await request.text().catch(() => '')\n req.body = Object.fromEntries(new URLSearchParams(text))\n } else if (contentType.startsWith('text/')) {\n req.body = await request.text().catch(() => undefined)\n }\n }\n\n const store = createRequestStore(req.headers['x-request-id'])\n req.requestId = store.requestId\n\n const driver = new WebResponseDriver(request.signal)\n driver.setHeader('x-request-id', store.requestId)\n\n const pipeline = requestStore.run(store, async () => {\n const ctx = new RequestContext(\n req as never,\n driver as never,\n NOOP_NEXT,\n driver as RuntimeResponse,\n )\n\n if (validator) {\n await new Promise<void>((resolve, reject) => {\n validator(req as never, undefined as never, (err?: unknown) =>\n err ? reject(err) : resolve(),\n )\n })\n }\n\n for (const mw of entry.middlewares) {\n let advanced = false\n await new Promise<void>((resolve, reject) => {\n const next = (err?: unknown): void => {\n advanced = true\n if (err) reject(err)\n else resolve()\n }\n Promise.resolve(mw(ctx, next)).catch(reject)\n })\n if (!advanced || driver.settled) return\n }\n\n if (entry.contributorRunner) await entry.contributorRunner(ctx)\n if (driver.settled) return\n const result = await entry.handler(ctx)\n // Return-value handlers (reply.ts): auto-send when nothing was written.\n // `undefined` falls through to the canonical 404 below.\n if (!driver.settled) applyHandlerResult(ctx, result)\n })\n\n try {\n // Streaming responses resolve `ready` mid-pipeline (SSE); buffered ones\n // resolve at the terminal ctx call. Race so both shapes return promptly.\n try {\n await Promise.race([pipeline, driver.ready])\n } catch (err) {\n if (!driver.settled) {\n if (hooks?.onError) await hooks.onError(err, req, driver)\n if (!driver.settled) defaultErrorResponse(err, driver)\n }\n }\n if (!driver.settled) {\n // Pipeline finished without responding — canonical 404 shape.\n driver.status(404).json({ error: 'Not Found' })\n }\n return await driver.ready\n } finally {\n // @PreDestroy teardown. For buffered responses this runs post-response;\n // for streams it runs when the pipeline (not the stream) completes —\n // stream lifetime is governed by the client abort signal.\n void Promise.resolve(pipeline)\n .catch(() => {})\n .then(() => disposeRequestStore(store))\n }\n }\n}\n"],"mappings":"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"}
@@ -1,6 +1,5 @@
1
1
 
2
2
  import { NextFunction, Request, Response } from "express";
3
-
4
3
  //#region src/http/middleware/helmet.d.ts
5
4
  interface HelmetOptions {
6
5
  /** Set Content-Security-Policy header (default: self-only policy) */
@@ -38,4 +37,4 @@ interface HelmetOptions {
38
37
  declare function helmet(options?: HelmetOptions): (req: Request, res: Response, next: NextFunction) => void;
39
38
  //#endregion
40
39
  export { helmet as n, HelmetOptions as t };
41
- //# sourceMappingURL=helmet-CKzZzeNl.d.mts.map
40
+ //# sourceMappingURL=helmet-CFQUTVig.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"helmet-CFQUTVig.d.mts","names":[],"sources":["../src/http/middleware/helmet.ts"],"mappings":";;;UAEiB;;EAEf,kCAAkC;;EAElC;;EAEA;;EAEA;IAAiB;IAAiB;IAA6B;;;EAE/D;;EAEA;;EAEA;;EAEA;;;;;;;;;;;;;iBAcc,OAAO,UAAS,iBAAkB,KAYnC,SAAO,KAAO,UAAQ,MAAQ"}
@@ -1,3 +1,3 @@
1
1
 
2
- import { n as ApplicationOptions, r as MiddlewareEntry, t as Application } from "../application-Bzdzl5wP.mjs";
2
+ import { n as ApplicationOptions, r as MiddlewareEntry, t as Application } from "../application-zlzYGgKD.mjs";
3
3
  export { Application, ApplicationOptions, MiddlewareEntry };
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @forinda/kickjs v6.5.0
2
+ * @forinda/kickjs v6.5.1
3
3
  *
4
4
  * Copyright (c) Felix Orinda
5
5
  *
@@ -8,4 +8,4 @@
8
8
  *
9
9
  * @license MIT
10
10
  */
11
- import{t as Application}from"../application-C-r79XqD.mjs";export{Application};
11
+ import{t as Application}from"../application-Cl0JlmNY.mjs";export{Application};
@@ -1,3 +1,3 @@
1
1
 
2
- import { t as bootstrap } from "../bootstrap-DYexY169.mjs";
2
+ import { t as bootstrap } from "../bootstrap-Nzgi7K2d.mjs";
3
3
  export { bootstrap };
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @forinda/kickjs v6.5.0
2
+ * @forinda/kickjs v6.5.1
3
3
  *
4
4
  * Copyright (c) Felix Orinda
5
5
  *
@@ -8,4 +8,4 @@
8
8
  *
9
9
  * @license MIT
10
10
  */
11
- import{t as bootstrap}from"../bootstrap-C1VGQQVF.mjs";export{bootstrap};
11
+ import{t as bootstrap}from"../bootstrap-DzyWLYpU.mjs";export{bootstrap};
@@ -1,4 +1,4 @@
1
1
 
2
- import { g as ContextMeta } from "../app-module-BSpHKlhE.mjs";
3
- import { C as Ctx, D as SseHandler, E as RouteShape, T as RequestContext, w as DeepReadonly } from "../adapter-CEt1MEdF.mjs";
2
+ import { g as ContextMeta } from "../app-module-DtoySG6l.mjs";
3
+ import { C as Ctx, D as SseHandler, E as RouteShape, T as RequestContext, w as DeepReadonly } from "../adapter-CbMq-NBf.mjs";
4
4
  export { type ContextMeta, Ctx, DeepReadonly, RequestContext, RouteShape, SseHandler };
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @forinda/kickjs v6.5.0
2
+ * @forinda/kickjs v6.5.1
3
3
  *
4
4
  * Copyright (c) Felix Orinda
5
5
  *
@@ -8,4 +8,4 @@
8
8
  *
9
9
  * @license MIT
10
10
  */
11
- import{t as RequestContext}from"../context-BS5o1IuU.mjs";export{RequestContext};
11
+ import{t as RequestContext}from"../context-DQaUwwQM.mjs";export{RequestContext};
@@ -1,3 +1,3 @@
1
1
 
2
- import { n as cors, t as CorsOptions } from "../../cors-C4aSCD3J.mjs";
2
+ import { n as cors, t as CorsOptions } from "../../cors-BuDU9CpA.mjs";
3
3
  export { CorsOptions, cors };
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @forinda/kickjs v6.5.0
2
+ * @forinda/kickjs v6.5.1
3
3
  *
4
4
  * Copyright (c) Felix Orinda
5
5
  *
@@ -1,3 +1,3 @@
1
1
 
2
- import { n as csrf, t as CsrfOptions } from "../../csrf-7nUXGTuz.mjs";
2
+ import { n as csrf, t as CsrfOptions } from "../../csrf-vR23CJas.mjs";
3
3
  export { CsrfOptions, csrf };
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @forinda/kickjs v6.5.0
2
+ * @forinda/kickjs v6.5.1
3
3
  *
4
4
  * Copyright (c) Felix Orinda
5
5
  *
@@ -8,4 +8,4 @@
8
8
  *
9
9
  * @license MIT
10
10
  */
11
- import{t as csrf}from"../../csrf-DNh_7aOk.mjs";export{csrf};
11
+ import{t as csrf}from"../../csrf-BsrsObK-.mjs";export{csrf};
@@ -1,3 +1,3 @@
1
1
 
2
- import { n as notFoundHandler, t as errorHandler } from "../../error-handler-DR01K_rI.mjs";
2
+ import { n as notFoundHandler, t as errorHandler } from "../../error-handler-Cr6Yt9as.mjs";
3
3
  export { errorHandler, notFoundHandler };
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @forinda/kickjs v6.5.0
2
+ * @forinda/kickjs v6.5.1
3
3
  *
4
4
  * Copyright (c) Felix Orinda
5
5
  *
@@ -8,6 +8,6 @@
8
8
  *
9
9
  * @license MIT
10
10
  */
11
- import{createLogger,describeError}from"../../core/logger.mjs";import"../../core-TDR0XGzO.mjs";import{HttpException,ProblemException,normalizeProblem}from"../../core/errors.mjs";const log=createLogger(`ErrorHandler`);function notFoundHandler(){return(_req,res,_next)=>{res.status(404).json({message:`Not Found`})}}function errorHandler(){let isProduction=process.env.NODE_ENV===`production`;return(err,req,res,_next)=>{if(res.headersSent){log.warn(`Error after headers sent: ${err?.message||`Unknown`}`);return}if(err instanceof ProblemException){if(err.problem.status>=500&&log.error(err,err.message),err.headers)for(let[k,v]of Object.entries(err.headers))res.setHeader(k,v);let body=normalizeProblem(err.problem);return res.setHeader(`Content-Type`,`application/problem+json`),res.status(body.status).json(body)}if(err?.name===`ZodError`){let firstIssue=err.issues?.[0];return res.status(422).json({message:firstIssue?.message||`Validation failed`,...isProduction?{}:{errors:err.issues}})}if(err instanceof HttpException){if(err.status>=500&&log.error(err,err.message),err.headers)for(let[k,v]of Object.entries(err.headers))res.setHeader(k,v);let exposeDetails=!isProduction&&err.details!==void 0;return res.status(err.status).json({message:err.message,...exposeDetails?{errors:err.details}:{}})}let status=err.status||err.statusCode||500,requestId=req.requestId??req.headers[`x-request-id`];if(log.error(err,`${req.method} ${req.originalUrl} — ${describeError(err)}${requestId?` [${requestId}]`:``}`),status!==500)return res.status(status).json({message:err.message||`Error`,...requestId?{requestId}:{}});res.status(500).json({message:`Internal Server Error`,...requestId?{requestId}:{},...isProduction?{}:{error:describeError(err),...typeof err?.stack==`string`?{stack:err.stack.split(`
11
+ import{createLogger,describeError}from"../../core/logger.mjs";import{HttpException,ProblemException,normalizeProblem}from"../../core/errors.mjs";import"../../core-CLmwVWlw.mjs";const log=createLogger(`ErrorHandler`);function notFoundHandler(){return(_req,res,_next)=>{res.status(404).json({message:`Not Found`})}}function errorHandler(){let isProduction=process.env.NODE_ENV===`production`;return(err,req,res,_next)=>{if(res.headersSent){log.warn(`Error after headers sent: ${err?.message||`Unknown`}`);return}if(err instanceof ProblemException){if(err.problem.status>=500&&log.error(err,err.message),err.headers)for(let[k,v]of Object.entries(err.headers))res.setHeader(k,v);let body=normalizeProblem(err.problem);return res.setHeader(`Content-Type`,`application/problem+json`),res.status(body.status).json(body)}if(err?.name===`ZodError`){let firstIssue=err.issues?.[0];return res.status(422).json({message:firstIssue?.message||`Validation failed`,...isProduction?{}:{errors:err.issues}})}if(err instanceof HttpException){if(err.status>=500&&log.error(err,err.message),err.headers)for(let[k,v]of Object.entries(err.headers))res.setHeader(k,v);let exposeDetails=!isProduction&&err.details!==void 0;return res.status(err.status).json({message:err.message,...exposeDetails?{errors:err.details}:{}})}let status=err.status||err.statusCode||500,requestId=req.requestId??req.headers[`x-request-id`];if(log.error(err,`${req.method} ${req.originalUrl} — ${describeError(err)}${requestId?` [${requestId}]`:``}`),status!==500)return res.status(status).json({message:err.message||`Error`,...requestId?{requestId}:{}});res.status(500).json({message:`Internal Server Error`,...requestId?{requestId}:{},...isProduction?{}:{error:describeError(err),...typeof err?.stack==`string`?{stack:err.stack.split(`
12
12
  `)}:{}}})}}export{errorHandler,notFoundHandler};
13
13
  //# sourceMappingURL=error-handler.mjs.map
@@ -1,3 +1,3 @@
1
1
 
2
- import { n as helmet, t as HelmetOptions } from "../../helmet-CKzZzeNl.mjs";
2
+ import { n as helmet, t as HelmetOptions } from "../../helmet-CFQUTVig.mjs";
3
3
  export { HelmetOptions, helmet };
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @forinda/kickjs v6.5.0
2
+ * @forinda/kickjs v6.5.1
3
3
  *
4
4
  * Copyright (c) Felix Orinda
5
5
  *
@@ -1,3 +1,3 @@
1
1
 
2
- import { n as RateLimitStore, r as rateLimit, t as RateLimitOptions } from "../../rate-limit-oLL5EPUf.mjs";
2
+ import { n as RateLimitStore, r as rateLimit, t as RateLimitOptions } from "../../rate-limit-Dme747JJ.mjs";
3
3
  export { RateLimitOptions, RateLimitStore, rateLimit };
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @forinda/kickjs v6.5.0
2
+ * @forinda/kickjs v6.5.1
3
3
  *
4
4
  * Copyright (c) Felix Orinda
5
5
  *
@@ -8,5 +8,5 @@
8
8
  *
9
9
  * @license MIT
10
10
  */
11
- import{r as registerDisposable}from"../../disposables-mnjJuaVx.mjs";var MemoryStore=class{windowMs;hits=new Map;cleanupTimer;constructor(windowMs){this.windowMs=windowMs,this.cleanupTimer=setInterval(()=>this.cleanup(),windowMs),this.cleanupTimer.unref&&this.cleanupTimer.unref(),registerDisposable(()=>this.dispose())}dispose(){clearInterval(this.cleanupTimer),this.hits.clear()}async increment(key){let now=Date.now(),entry=this.hits.get(key);if(entry&&entry.resetTime.getTime()>now)return entry.totalHits++,{totalHits:entry.totalHits,resetTime:entry.resetTime};let resetTime=new Date(now+this.windowMs),newEntry={totalHits:1,resetTime};return this.hits.set(key,newEntry),{totalHits:1,resetTime}}async decrement(key){let entry=this.hits.get(key);entry&&entry.totalHits>0&&entry.totalHits--}async reset(key){this.hits.delete(key)}cleanup(){let now=Date.now();for(let[key,entry]of this.hits)entry.resetTime.getTime()<=now&&this.hits.delete(key)}};function rateLimit(options={}){let max=options.max??100,windowMs=options.windowMs??6e4,message=options.message??`Too Many Requests`,statusCode=options.statusCode??429,keyGenerator=options.keyGenerator??(req=>req.ip??`127.0.0.1`),sendHeaders=options.headers??!0,store=options.store??new MemoryStore(windowMs),skip=options.skip,skipPaths=new Set(options.skipPaths??[]);return async(req,res,next)=>{if(skipPaths.has(req.path)||skip&&skip(req))return next();let key=keyGenerator(req),{totalHits,resetTime}=await store.increment(key),remaining=Math.max(0,max-totalHits);if(sendHeaders&&(res.setHeader(`RateLimit-Limit`,max),res.setHeader(`RateLimit-Remaining`,remaining),res.setHeader(`RateLimit-Reset`,Math.ceil(resetTime.getTime()/1e3))),totalHits>max)return res.status(statusCode).json({message});next()}}export{rateLimit};
11
+ import{r as registerDisposable}from"../../disposables-D46xX96x.mjs";var MemoryStore=class{windowMs;hits=new Map;cleanupTimer;constructor(windowMs){this.windowMs=windowMs,this.cleanupTimer=setInterval(()=>this.cleanup(),windowMs),this.cleanupTimer.unref&&this.cleanupTimer.unref(),registerDisposable(()=>this.dispose())}dispose(){clearInterval(this.cleanupTimer),this.hits.clear()}async increment(key){let now=Date.now(),entry=this.hits.get(key);if(entry&&entry.resetTime.getTime()>now)return entry.totalHits++,{totalHits:entry.totalHits,resetTime:entry.resetTime};let resetTime=new Date(now+this.windowMs),newEntry={totalHits:1,resetTime};return this.hits.set(key,newEntry),{totalHits:1,resetTime}}async decrement(key){let entry=this.hits.get(key);entry&&entry.totalHits>0&&entry.totalHits--}async reset(key){this.hits.delete(key)}cleanup(){let now=Date.now();for(let[key,entry]of this.hits)entry.resetTime.getTime()<=now&&this.hits.delete(key)}};function rateLimit(options={}){let max=options.max??100,windowMs=options.windowMs??6e4,message=options.message??`Too Many Requests`,statusCode=options.statusCode??429,keyGenerator=options.keyGenerator??(req=>req.ip??`127.0.0.1`),sendHeaders=options.headers??!0,store=options.store??new MemoryStore(windowMs),skip=options.skip,skipPaths=new Set(options.skipPaths??[]);return async(req,res,next)=>{if(skipPaths.has(req.path)||skip&&skip(req))return next();let key=keyGenerator(req),{totalHits,resetTime}=await store.increment(key),remaining=Math.max(0,max-totalHits);if(sendHeaders&&(res.setHeader(`RateLimit-Limit`,max),res.setHeader(`RateLimit-Remaining`,remaining),res.setHeader(`RateLimit-Reset`,Math.ceil(resetTime.getTime()/1e3))),totalHits>max)return res.status(statusCode).json({message});next()}}export{rateLimit};
12
12
  //# sourceMappingURL=rate-limit.mjs.map
@@ -1,3 +1,3 @@
1
1
 
2
- import { n as requestId, t as REQUEST_ID_HEADER } from "../../request-id-IDobbxU-.mjs";
2
+ import { n as requestId, t as REQUEST_ID_HEADER } from "../../request-id-CVzJ1uHD.mjs";
3
3
  export { REQUEST_ID_HEADER, requestId };
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @forinda/kickjs v6.5.0
2
+ * @forinda/kickjs v6.5.1
3
3
  *
4
4
  * Copyright (c) Felix Orinda
5
5
  *
@@ -1,3 +1,3 @@
1
1
 
2
- import { n as requestLogger, t as RequestLoggerOptions } from "../../request-logger-DZVW6VNI.mjs";
2
+ import { n as requestLogger, t as RequestLoggerOptions } from "../../request-logger-BU4ulKLp.mjs";
3
3
  export { RequestLoggerOptions, requestLogger };
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @forinda/kickjs v6.5.0
2
+ * @forinda/kickjs v6.5.1
3
3
  *
4
4
  * Copyright (c) Felix Orinda
5
5
  *
@@ -8,5 +8,5 @@
8
8
  *
9
9
  * @license MIT
10
10
  */
11
- import{createLogger}from"../../core/logger.mjs";import"../../core-TDR0XGzO.mjs";function requestLogger(options={}){let log=createLogger(options.name??`HTTP`),level=options.level??`info`,skip=options.skip??[];return(req,res,next)=>{if(skip.some(prefix=>req.path.startsWith(prefix)))return next();let start=Date.now();res.on(`finish`,()=>{let duration=Date.now()-start,requestId=req.requestId||req.headers[`x-request-id`]||`-`,status=res.statusCode;log[level](`${req.method} ${req.originalUrl} ${status} ${duration}ms ${requestId}`)}),next()}}export{requestLogger};
11
+ import{createLogger}from"../../core/logger.mjs";import"../../core-CLmwVWlw.mjs";function requestLogger(options={}){let log=createLogger(options.name??`HTTP`),level=options.level??`info`,skip=options.skip??[];return(req,res,next)=>{if(skip.some(prefix=>req.path.startsWith(prefix)))return next();let start=Date.now();res.on(`finish`,()=>{let duration=Date.now()-start,requestId=req.requestId||req.headers[`x-request-id`]||`-`,status=res.statusCode;log[level](`${req.method} ${req.originalUrl} ${status} ${duration}ms ${requestId}`)}),next()}}export{requestLogger};
12
12
  //# sourceMappingURL=request-logger.mjs.map
@@ -1,3 +1,3 @@
1
1
 
2
- import { a as session, i as SessionStore, n as SessionData, r as SessionOptions, t as Session } from "../../session-DSRA-PUX.mjs";
2
+ import { a as session, i as SessionStore, n as SessionData, r as SessionOptions, t as Session } from "../../session-z9iewOXA.mjs";
3
3
  export { Session, SessionData, SessionOptions, SessionStore, session };
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @forinda/kickjs v6.5.0
2
+ * @forinda/kickjs v6.5.1
3
3
  *
4
4
  * Copyright (c) Felix Orinda
5
5
  *
@@ -8,5 +8,5 @@
8
8
  *
9
9
  * @license MIT
10
10
  */
11
- import{r as registerDisposable}from"../../disposables-mnjJuaVx.mjs";import{createHmac,randomUUID,timingSafeEqual}from"node:crypto";var MemoryStore=class{sessions=new Map;cleanupInterval;constructor(){this.cleanupInterval=setInterval(()=>this.purge(),6e4),this.cleanupInterval.unref(),registerDisposable(()=>this.dispose())}dispose(){clearInterval(this.cleanupInterval),this.sessions.clear()}async get(sid){let entry=this.sessions.get(sid);return entry?Date.now()>entry.expires?(this.sessions.delete(sid),null):entry.data:null}async set(sid,data,maxAge){this.sessions.set(sid,{data,expires:Date.now()+maxAge})}async destroy(sid){this.sessions.delete(sid)}async touch(sid,maxAge){let entry=this.sessions.get(sid);entry&&(entry.expires=Date.now()+maxAge)}purge(){let now=Date.now();for(let[sid,entry]of this.sessions)now>entry.expires&&this.sessions.delete(sid)}};function parseCookieHeader(header){let out={};for(let pair of header.split(`;`)){let eq=pair.indexOf(`=`);if(eq===-1)continue;let key=pair.slice(0,eq).trim();if(!key)continue;let value=pair.slice(eq+1).trim();value.startsWith(`"`)&&value.endsWith(`"`)&&(value=value.slice(1,-1));try{out[key]=decodeURIComponent(value)}catch{out[key]=value}}return out}function sign(value,secret){return`s:${value}.${createHmac(`sha256`,secret).update(value).digest(`base64url`)}`}function unsign(signed,secret){if(!signed.startsWith(`s:`))return!1;let raw=signed.slice(2),dotIndex=raw.lastIndexOf(`.`);if(dotIndex===-1)return!1;let value=raw.slice(0,dotIndex),providedSig=raw.slice(dotIndex+1),expectedSig=createHmac(`sha256`,secret).update(value).digest(`base64url`),a=Buffer.from(providedSig),b=Buffer.from(expectedSig);return a.length!==b.length||!timingSafeEqual(a,b)?!1:value}function session(options){let{secret,cookieName=`kick.sid`,maxAge=864e5,rolling=!1,saveUninitialized=!0,store=new MemoryStore,cookie:cookieOpts={}}=options,cookieDefaults={httpOnly:cookieOpts.httpOnly??!0,secure:cookieOpts.secure??process.env.NODE_ENV===`production`,sameSite:cookieOpts.sameSite??`lax`,path:cookieOpts.path??`/`,...cookieOpts.domain?{domain:cookieOpts.domain}:{},maxAge};return async(req,res,next)=>{let cookies=req.cookies;if(!cookies){let header=req.headers.cookie;cookies=header?parseCookieHeader(header):{}}let signedCookie=cookies[cookieName],sid=!1,sessionData=null,isNew=!1;signedCookie&&(sid=unsign(signedCookie,secret),sid&&(sessionData=await store.get(sid))),(!sid||!sessionData)&&(sid=randomUUID(),sessionData={},isNew=!0);let currentSid=sid,currentData={...sessionData},destroyed=!1,sessionObj={get id(){return currentSid},data:currentData,async regenerate(){await store.destroy(currentSid),currentSid=randomUUID(),currentData={},sessionObj.data=currentData,await store.set(currentSid,currentData,maxAge),res.cookie(cookieName,sign(currentSid,secret),cookieDefaults)},async destroy(){await store.destroy(currentSid),destroyed=!0,currentData={},sessionObj.data=currentData,res.clearCookie(cookieName,{path:cookieDefaults.path})},async save(){destroyed||await store.set(currentSid,currentData,maxAge)}};req.session=sessionObj,isNew&&res.cookie(cookieName,sign(currentSid,secret),cookieDefaults),res.on(`finish`,async()=>{destroyed||isNew&&!saveUninitialized&&Object.keys(currentData).length===0||(await store.set(currentSid,currentData,maxAge),rolling&&!isNew&&store.touch&&await store.touch(currentSid,maxAge))}),rolling&&!isNew&&res.cookie(cookieName,sign(currentSid,secret),cookieDefaults),next()}}export{session};
11
+ import{r as registerDisposable}from"../../disposables-D46xX96x.mjs";import{createHmac,randomUUID,timingSafeEqual}from"node:crypto";var MemoryStore=class{sessions=new Map;cleanupInterval;constructor(){this.cleanupInterval=setInterval(()=>this.purge(),6e4),this.cleanupInterval.unref(),registerDisposable(()=>this.dispose())}dispose(){clearInterval(this.cleanupInterval),this.sessions.clear()}async get(sid){let entry=this.sessions.get(sid);return entry?Date.now()>entry.expires?(this.sessions.delete(sid),null):entry.data:null}async set(sid,data,maxAge){this.sessions.set(sid,{data,expires:Date.now()+maxAge})}async destroy(sid){this.sessions.delete(sid)}async touch(sid,maxAge){let entry=this.sessions.get(sid);entry&&(entry.expires=Date.now()+maxAge)}purge(){let now=Date.now();for(let[sid,entry]of this.sessions)now>entry.expires&&this.sessions.delete(sid)}};function parseCookieHeader(header){let out={};for(let pair of header.split(`;`)){let eq=pair.indexOf(`=`);if(eq===-1)continue;let key=pair.slice(0,eq).trim();if(!key)continue;let value=pair.slice(eq+1).trim();value.startsWith(`"`)&&value.endsWith(`"`)&&(value=value.slice(1,-1));try{out[key]=decodeURIComponent(value)}catch{out[key]=value}}return out}function sign(value,secret){return`s:${value}.${createHmac(`sha256`,secret).update(value).digest(`base64url`)}`}function unsign(signed,secret){if(!signed.startsWith(`s:`))return!1;let raw=signed.slice(2),dotIndex=raw.lastIndexOf(`.`);if(dotIndex===-1)return!1;let value=raw.slice(0,dotIndex),providedSig=raw.slice(dotIndex+1),expectedSig=createHmac(`sha256`,secret).update(value).digest(`base64url`),a=Buffer.from(providedSig),b=Buffer.from(expectedSig);return a.length!==b.length||!timingSafeEqual(a,b)?!1:value}function session(options){let{secret,cookieName=`kick.sid`,maxAge=864e5,rolling=!1,saveUninitialized=!0,store=new MemoryStore,cookie:cookieOpts={}}=options,cookieDefaults={httpOnly:cookieOpts.httpOnly??!0,secure:cookieOpts.secure??process.env.NODE_ENV===`production`,sameSite:cookieOpts.sameSite??`lax`,path:cookieOpts.path??`/`,...cookieOpts.domain?{domain:cookieOpts.domain}:{},maxAge};return async(req,res,next)=>{let cookies=req.cookies;if(!cookies){let header=req.headers.cookie;cookies=header?parseCookieHeader(header):{}}let signedCookie=cookies[cookieName],sid=!1,sessionData=null,isNew=!1;signedCookie&&(sid=unsign(signedCookie,secret),sid&&(sessionData=await store.get(sid))),(!sid||!sessionData)&&(sid=randomUUID(),sessionData={},isNew=!0);let currentSid=sid,currentData={...sessionData},destroyed=!1,sessionObj={get id(){return currentSid},data:currentData,async regenerate(){await store.destroy(currentSid),currentSid=randomUUID(),currentData={},sessionObj.data=currentData,await store.set(currentSid,currentData,maxAge),res.cookie(cookieName,sign(currentSid,secret),cookieDefaults)},async destroy(){await store.destroy(currentSid),destroyed=!0,currentData={},sessionObj.data=currentData,res.clearCookie(cookieName,{path:cookieDefaults.path})},async save(){destroyed||await store.set(currentSid,currentData,maxAge)}};req.session=sessionObj,isNew&&res.cookie(cookieName,sign(currentSid,secret),cookieDefaults),res.on(`finish`,async()=>{destroyed||isNew&&!saveUninitialized&&Object.keys(currentData).length===0||(await store.set(currentSid,currentData,maxAge),rolling&&!isNew&&store.touch&&await store.touch(currentSid,maxAge))}),rolling&&!isNew&&res.cookie(cookieName,sign(currentSid,secret),cookieDefaults),next()}}export{session};
12
12
  //# sourceMappingURL=session.mjs.map
@@ -1,3 +1,3 @@
1
1
 
2
- import { n as SpaAdapterOptions, t as SpaAdapter } from "../../spa-DWzSWAzx.mjs";
2
+ import { n as SpaAdapterOptions, t as SpaAdapter } from "../../spa-DsRUrm69.mjs";
3
3
  export { SpaAdapter, SpaAdapterOptions };
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @forinda/kickjs v6.5.0
2
+ * @forinda/kickjs v6.5.1
3
3
  *
4
4
  * Copyright (c) Felix Orinda
5
5
  *
@@ -8,5 +8,5 @@
8
8
  *
9
9
  * @license MIT
10
10
  */
11
- import{t as __require}from"../../rolldown-runtime-CuwksmWW.mjs";import{Logger}from"../../core/logger.mjs";import"../../core-TDR0XGzO.mjs";import{existsSync,readFileSync}from"node:fs";import{join,resolve}from"node:path";const log=Logger.for(`SpaAdapter`);var SpaAdapter=class{options;name=`SpaAdapter`;clientDir;apiPrefixes;excludePaths;cacheControl;indexCacheControl;indexHtml=null;constructor(options={}){this.options=options,this.clientDir=resolve(options.clientDir??`dist/client`),this.excludePaths=options.exclude??[],this.cacheControl=options.cacheControl??`public, max-age=31536000, immutable`,this.indexCacheControl=options.indexCacheControl??`no-cache`;let prefix=options.apiPrefix??`/api`;this.apiPrefixes=Array.isArray(prefix)?prefix:[prefix]}beforeMount({app}){if(!existsSync(this.clientDir)){log.warn(`SPA client directory not found: ${this.clientDir}`),log.warn(`Build your frontend first, or set clientDir to the correct path.`);return}let indexPath=join(this.clientDir,`index.html`);if(existsSync(indexPath))this.indexHtml=readFileSync(indexPath,`utf-8`);else{log.warn(`index.html not found in ${this.clientDir}`);return}try{let express=__require(`express`),staticOpts={};this.cacheControl&&(staticOpts.setHeaders=(res,filePath)=>{filePath.endsWith(`.html`)?res.setHeader(`Cache-Control`,this.indexCacheControl):res.setHeader(`Cache-Control`,this.cacheControl)}),app.use(express.static(this.clientDir,staticOpts))}catch{log.error(`express.static not available — SPA static file serving disabled`);return}log.debug(`Serving SPA from ${this.clientDir}`)}beforeStart({app}){this.indexHtml&&app.use((req,res,next)=>{for(let prefix of this.apiPrefixes)if(req.path.startsWith(prefix))return next();for(let path of this.excludePaths)if(req.path.startsWith(path))return next();if(req.path.includes(`.`)||req.method!==`GET`)return next();res.setHeader(`Content-Type`,`text/html`),res.setHeader(`Cache-Control`,this.indexCacheControl),res.send(this.indexHtml)})}};export{SpaAdapter};
11
+ import{c as __require}from"../../env-Biq_60jq.mjs";import{Logger}from"../../core/logger.mjs";import"../../core-CLmwVWlw.mjs";import{existsSync,readFileSync}from"node:fs";import{join,resolve}from"node:path";const log=Logger.for(`SpaAdapter`);var SpaAdapter=class{options;name=`SpaAdapter`;clientDir;apiPrefixes;excludePaths;cacheControl;indexCacheControl;indexHtml=null;constructor(options={}){this.options=options,this.clientDir=resolve(options.clientDir??`dist/client`),this.excludePaths=options.exclude??[],this.cacheControl=options.cacheControl??`public, max-age=31536000, immutable`,this.indexCacheControl=options.indexCacheControl??`no-cache`;let prefix=options.apiPrefix??`/api`;this.apiPrefixes=Array.isArray(prefix)?prefix:[prefix]}beforeMount({app}){if(!existsSync(this.clientDir)){log.warn(`SPA client directory not found: ${this.clientDir}`),log.warn(`Build your frontend first, or set clientDir to the correct path.`);return}let indexPath=join(this.clientDir,`index.html`);if(existsSync(indexPath))this.indexHtml=readFileSync(indexPath,`utf-8`);else{log.warn(`index.html not found in ${this.clientDir}`);return}try{let express=__require(`express`),staticOpts={};this.cacheControl&&(staticOpts.setHeaders=(res,filePath)=>{filePath.endsWith(`.html`)?res.setHeader(`Cache-Control`,this.indexCacheControl):res.setHeader(`Cache-Control`,this.cacheControl)}),app.use(express.static(this.clientDir,staticOpts))}catch{log.error(`express.static not available — SPA static file serving disabled`);return}log.debug(`Serving SPA from ${this.clientDir}`)}beforeStart({app}){this.indexHtml&&app.use((req,res,next)=>{for(let prefix of this.apiPrefixes)if(req.path.startsWith(prefix))return next();for(let path of this.excludePaths)if(req.path.startsWith(path))return next();if(req.path.includes(`.`)||req.method!==`GET`)return next();res.setHeader(`Content-Type`,`text/html`),res.setHeader(`Cache-Control`,this.indexCacheControl),res.send(this.indexHtml)})}};export{SpaAdapter};
12
12
  //# sourceMappingURL=spa.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"spa.mjs","names":[],"sources":["../../../src/http/middleware/spa.ts"],"sourcesContent":["import { existsSync, readFileSync } from 'node:fs'\nimport { resolve, join } from 'node:path'\nimport { Logger, type AppAdapter, type AdapterContext } from '../../core'\n\nconst log = Logger.for('SpaAdapter')\n\nexport interface SpaAdapterOptions {\n /**\n * Directory containing the built SPA files (index.html, assets, etc.)\n * Default: 'dist/client'\n *\n * @example\n * ```ts\n * // Vue: 'dist'\n * // React (Vite): 'dist'\n * // React (CRA): 'build'\n * // Svelte: 'build'\n * // Angular: 'dist/my-app/browser'\n * ```\n */\n clientDir?: string\n\n /**\n * URL prefix for API routes. SPA fallback only applies to\n * non-API routes (routes NOT starting with this prefix).\n * Default: '/api'\n *\n * Set to an array for multiple prefixes:\n * ```ts\n * apiPrefix: ['/api', '/graphql', '/_debug']\n * ```\n */\n apiPrefix?: string | string[]\n\n /**\n * Additional paths to exclude from SPA fallback.\n * These paths will NOT serve index.html.\n *\n * @example\n * ```ts\n * exclude: ['/health', '/metrics', '/ws']\n * ```\n */\n exclude?: string[]\n\n /**\n * Cache-Control header for static assets (default: 'public, max-age=31536000, immutable')\n * Set to false to disable caching headers.\n */\n cacheControl?: string | false\n\n /**\n * Cache-Control for index.html (default: 'no-cache')\n * index.html should not be cached to ensure clients get fresh builds.\n */\n indexCacheControl?: string\n}\n\n/**\n * SPA adapter — serve a Vue, React, Svelte, or Angular build alongside\n * your KickJS API. API routes are handled by controllers; everything else\n * falls back to index.html for client-side routing.\n *\n * @example\n * ```ts\n * import { SpaAdapter } from '@forinda/kickjs/spa'\n *\n * bootstrap({\n * modules,\n * adapters: [\n * new SpaAdapter({\n * clientDir: 'dist/client', // or 'build', 'dist', etc.\n * apiPrefix: '/api',\n * }),\n * ],\n * })\n * ```\n *\n * File structure:\n * ```\n * dist/\n * client/ ← SPA build output\n * index.html\n * assets/\n * app.js\n * style.css\n * server/ ← KickJS server\n * ```\n */\nexport class SpaAdapter implements AppAdapter {\n name = 'SpaAdapter'\n private clientDir: string\n private apiPrefixes: string[]\n private excludePaths: string[]\n private cacheControl: string | false\n private indexCacheControl: string\n private indexHtml: string | null = null\n\n constructor(private options: SpaAdapterOptions = {}) {\n this.clientDir = resolve(options.clientDir ?? 'dist/client')\n this.excludePaths = options.exclude ?? []\n this.cacheControl = options.cacheControl ?? 'public, max-age=31536000, immutable'\n this.indexCacheControl = options.indexCacheControl ?? 'no-cache'\n\n const prefix = options.apiPrefix ?? '/api'\n this.apiPrefixes = Array.isArray(prefix) ? prefix : [prefix]\n }\n\n beforeMount({ app }: AdapterContext): void {\n if (!existsSync(this.clientDir)) {\n log.warn(`SPA client directory not found: ${this.clientDir}`)\n log.warn('Build your frontend first, or set clientDir to the correct path.')\n return\n }\n\n // Read index.html into memory\n const indexPath = join(this.clientDir, 'index.html')\n if (existsSync(indexPath)) {\n this.indexHtml = readFileSync(indexPath, 'utf-8')\n } else {\n log.warn(`index.html not found in ${this.clientDir}`)\n return\n }\n\n // Serve static files with cache headers\n try {\n // Dynamic import to avoid hard dependency on express.static\n const express = require('express')\n const staticOpts: any = {}\n\n if (this.cacheControl) {\n staticOpts.setHeaders = (res: any, filePath: string) => {\n if (filePath.endsWith('.html')) {\n res.setHeader('Cache-Control', this.indexCacheControl)\n } else {\n res.setHeader('Cache-Control', this.cacheControl as string)\n }\n }\n }\n\n app.use(express.static(this.clientDir, staticOpts))\n } catch {\n log.error('express.static not available — SPA static file serving disabled')\n return\n }\n\n log.debug(`Serving SPA from ${this.clientDir}`)\n }\n\n beforeStart({ app }: AdapterContext): void {\n if (!this.indexHtml) return\n\n // SPA fallback: serve index.html for all non-API, non-file routes\n app.use((req: any, res: any, next: any) => {\n // Skip API routes\n for (const prefix of this.apiPrefixes) {\n if (req.path.startsWith(prefix)) return next()\n }\n\n // Skip excluded paths\n for (const path of this.excludePaths) {\n if (req.path.startsWith(path)) return next()\n }\n\n // Skip requests for files (have an extension)\n if (req.path.includes('.')) return next()\n\n // Skip non-GET requests\n if (req.method !== 'GET') return next()\n\n // Serve index.html\n res.setHeader('Content-Type', 'text/html')\n res.setHeader('Cache-Control', this.indexCacheControl)\n res.send(this.indexHtml)\n })\n }\n}\n"],"mappings":";;;;;;;;;;2NAIA,MAAM,IAAM,OAAO,IAAI,YAAY,EAqFnC,IAAa,WAAb,KAA8C,CASxB,QARpB,KAAO,aACP,UACA,YACA,aACA,aACA,kBACA,UAAmC,KAEnC,YAAY,QAAqC,CAAC,EAAG,CAAjC,KAAA,QAAA,QAClB,KAAK,UAAY,QAAQ,QAAQ,WAAa,aAAa,EAC3D,KAAK,aAAe,QAAQ,SAAW,CAAC,EACxC,KAAK,aAAe,QAAQ,cAAgB,sCAC5C,KAAK,kBAAoB,QAAQ,mBAAqB,WAEtD,IAAM,OAAS,QAAQ,WAAa,OACpC,KAAK,YAAc,MAAM,QAAQ,MAAM,EAAI,OAAS,CAAC,MAAM,CAC7D,CAEA,YAAY,CAAE,KAA6B,CACzC,GAAI,CAAC,WAAW,KAAK,SAAS,EAAG,CAC/B,IAAI,KAAK,mCAAmC,KAAK,WAAW,EAC5D,IAAI,KAAK,kEAAkE,EAC3E,MACF,CAGA,IAAM,UAAY,KAAK,KAAK,UAAW,YAAY,EACnD,GAAI,WAAW,SAAS,EACtB,KAAK,UAAY,aAAa,UAAW,OAAO,MAC3C,CACL,IAAI,KAAK,2BAA2B,KAAK,WAAW,EACpD,MACF,CAGA,GAAI,CAEF,IAAM,QAAA,UAAkB,SAAS,EAC3B,WAAkB,CAAC,EAErB,KAAK,eACP,WAAW,YAAc,IAAU,WAAqB,CAClD,SAAS,SAAS,OAAO,EAC3B,IAAI,UAAU,gBAAiB,KAAK,iBAAiB,EAErD,IAAI,UAAU,gBAAiB,KAAK,YAAsB,CAE9D,GAGF,IAAI,IAAI,QAAQ,OAAO,KAAK,UAAW,UAAU,CAAC,CACpD,MAAQ,CACN,IAAI,MAAM,iEAAiE,EAC3E,MACF,CAEA,IAAI,MAAM,oBAAoB,KAAK,WAAW,CAChD,CAEA,YAAY,CAAE,KAA6B,CACpC,KAAK,WAGV,IAAI,KAAK,IAAU,IAAU,OAAc,CAEzC,IAAK,IAAM,UAAU,KAAK,YACxB,GAAI,IAAI,KAAK,WAAW,MAAM,EAAG,OAAO,KAAK,EAI/C,IAAK,IAAM,QAAQ,KAAK,aACtB,GAAI,IAAI,KAAK,WAAW,IAAI,EAAG,OAAO,KAAK,EAO7C,GAHI,IAAI,KAAK,SAAS,GAAG,GAGrB,IAAI,SAAW,MAAO,OAAO,KAAK,EAGtC,IAAI,UAAU,eAAgB,WAAW,EACzC,IAAI,UAAU,gBAAiB,KAAK,iBAAiB,EACrD,IAAI,KAAK,KAAK,SAAS,CACzB,CAAC,CACH,CACF"}
1
+ {"version":3,"file":"spa.mjs","names":[],"sources":["../../../src/http/middleware/spa.ts"],"sourcesContent":["import { existsSync, readFileSync } from 'node:fs'\nimport { resolve, join } from 'node:path'\nimport { Logger, type AppAdapter, type AdapterContext } from '../../core'\n\nconst log = Logger.for('SpaAdapter')\n\nexport interface SpaAdapterOptions {\n /**\n * Directory containing the built SPA files (index.html, assets, etc.)\n * Default: 'dist/client'\n *\n * @example\n * ```ts\n * // Vue: 'dist'\n * // React (Vite): 'dist'\n * // React (CRA): 'build'\n * // Svelte: 'build'\n * // Angular: 'dist/my-app/browser'\n * ```\n */\n clientDir?: string\n\n /**\n * URL prefix for API routes. SPA fallback only applies to\n * non-API routes (routes NOT starting with this prefix).\n * Default: '/api'\n *\n * Set to an array for multiple prefixes:\n * ```ts\n * apiPrefix: ['/api', '/graphql', '/_debug']\n * ```\n */\n apiPrefix?: string | string[]\n\n /**\n * Additional paths to exclude from SPA fallback.\n * These paths will NOT serve index.html.\n *\n * @example\n * ```ts\n * exclude: ['/health', '/metrics', '/ws']\n * ```\n */\n exclude?: string[]\n\n /**\n * Cache-Control header for static assets (default: 'public, max-age=31536000, immutable')\n * Set to false to disable caching headers.\n */\n cacheControl?: string | false\n\n /**\n * Cache-Control for index.html (default: 'no-cache')\n * index.html should not be cached to ensure clients get fresh builds.\n */\n indexCacheControl?: string\n}\n\n/**\n * SPA adapter — serve a Vue, React, Svelte, or Angular build alongside\n * your KickJS API. API routes are handled by controllers; everything else\n * falls back to index.html for client-side routing.\n *\n * @example\n * ```ts\n * import { SpaAdapter } from '@forinda/kickjs/spa'\n *\n * bootstrap({\n * modules,\n * adapters: [\n * new SpaAdapter({\n * clientDir: 'dist/client', // or 'build', 'dist', etc.\n * apiPrefix: '/api',\n * }),\n * ],\n * })\n * ```\n *\n * File structure:\n * ```\n * dist/\n * client/ ← SPA build output\n * index.html\n * assets/\n * app.js\n * style.css\n * server/ ← KickJS server\n * ```\n */\nexport class SpaAdapter implements AppAdapter {\n name = 'SpaAdapter'\n private clientDir: string\n private apiPrefixes: string[]\n private excludePaths: string[]\n private cacheControl: string | false\n private indexCacheControl: string\n private indexHtml: string | null = null\n\n constructor(private options: SpaAdapterOptions = {}) {\n this.clientDir = resolve(options.clientDir ?? 'dist/client')\n this.excludePaths = options.exclude ?? []\n this.cacheControl = options.cacheControl ?? 'public, max-age=31536000, immutable'\n this.indexCacheControl = options.indexCacheControl ?? 'no-cache'\n\n const prefix = options.apiPrefix ?? '/api'\n this.apiPrefixes = Array.isArray(prefix) ? prefix : [prefix]\n }\n\n beforeMount({ app }: AdapterContext): void {\n if (!existsSync(this.clientDir)) {\n log.warn(`SPA client directory not found: ${this.clientDir}`)\n log.warn('Build your frontend first, or set clientDir to the correct path.')\n return\n }\n\n // Read index.html into memory\n const indexPath = join(this.clientDir, 'index.html')\n if (existsSync(indexPath)) {\n this.indexHtml = readFileSync(indexPath, 'utf-8')\n } else {\n log.warn(`index.html not found in ${this.clientDir}`)\n return\n }\n\n // Serve static files with cache headers\n try {\n // Dynamic import to avoid hard dependency on express.static\n const express = require('express')\n const staticOpts: any = {}\n\n if (this.cacheControl) {\n staticOpts.setHeaders = (res: any, filePath: string) => {\n if (filePath.endsWith('.html')) {\n res.setHeader('Cache-Control', this.indexCacheControl)\n } else {\n res.setHeader('Cache-Control', this.cacheControl as string)\n }\n }\n }\n\n app.use(express.static(this.clientDir, staticOpts))\n } catch {\n log.error('express.static not available — SPA static file serving disabled')\n return\n }\n\n log.debug(`Serving SPA from ${this.clientDir}`)\n }\n\n beforeStart({ app }: AdapterContext): void {\n if (!this.indexHtml) return\n\n // SPA fallback: serve index.html for all non-API, non-file routes\n app.use((req: any, res: any, next: any) => {\n // Skip API routes\n for (const prefix of this.apiPrefixes) {\n if (req.path.startsWith(prefix)) return next()\n }\n\n // Skip excluded paths\n for (const path of this.excludePaths) {\n if (req.path.startsWith(path)) return next()\n }\n\n // Skip requests for files (have an extension)\n if (req.path.includes('.')) return next()\n\n // Skip non-GET requests\n if (req.method !== 'GET') return next()\n\n // Serve index.html\n res.setHeader('Content-Type', 'text/html')\n res.setHeader('Cache-Control', this.indexCacheControl)\n res.send(this.indexHtml)\n })\n }\n}\n"],"mappings":";;;;;;;;;;8MAIA,MAAM,IAAM,OAAO,IAAI,YAAY,EAqFnC,IAAa,WAAb,KAA8C,CASxB,QARpB,KAAO,aACP,UACA,YACA,aACA,aACA,kBACA,UAAmC,KAEnC,YAAY,QAAqC,CAAC,EAAG,CAAjC,KAAA,QAAA,QAClB,KAAK,UAAY,QAAQ,QAAQ,WAAa,aAAa,EAC3D,KAAK,aAAe,QAAQ,SAAW,CAAC,EACxC,KAAK,aAAe,QAAQ,cAAgB,sCAC5C,KAAK,kBAAoB,QAAQ,mBAAqB,WAEtD,IAAM,OAAS,QAAQ,WAAa,OACpC,KAAK,YAAc,MAAM,QAAQ,MAAM,EAAI,OAAS,CAAC,MAAM,CAC7D,CAEA,YAAY,CAAE,KAA6B,CACzC,GAAI,CAAC,WAAW,KAAK,SAAS,EAAG,CAC/B,IAAI,KAAK,mCAAmC,KAAK,WAAW,EAC5D,IAAI,KAAK,kEAAkE,EAC3E,MACF,CAGA,IAAM,UAAY,KAAK,KAAK,UAAW,YAAY,EACnD,GAAI,WAAW,SAAS,EACtB,KAAK,UAAY,aAAa,UAAW,OAAO,MAC3C,CACL,IAAI,KAAK,2BAA2B,KAAK,WAAW,EACpD,MACF,CAGA,GAAI,CAEF,IAAM,QAAA,UAAkB,SAAS,EAC3B,WAAkB,CAAC,EAErB,KAAK,eACP,WAAW,YAAc,IAAU,WAAqB,CAClD,SAAS,SAAS,OAAO,EAC3B,IAAI,UAAU,gBAAiB,KAAK,iBAAiB,EAErD,IAAI,UAAU,gBAAiB,KAAK,YAAsB,CAE9D,GAGF,IAAI,IAAI,QAAQ,OAAO,KAAK,UAAW,UAAU,CAAC,CACpD,MAAQ,CACN,IAAI,MAAM,iEAAiE,EAC3E,MACF,CAEA,IAAI,MAAM,oBAAoB,KAAK,WAAW,CAChD,CAEA,YAAY,CAAE,KAA6B,CACpC,KAAK,WAGV,IAAI,KAAK,IAAU,IAAU,OAAc,CAEzC,IAAK,IAAM,UAAU,KAAK,YACxB,GAAI,IAAI,KAAK,WAAW,MAAM,EAAG,OAAO,KAAK,EAI/C,IAAK,IAAM,QAAQ,KAAK,aACtB,GAAI,IAAI,KAAK,WAAW,IAAI,EAAG,OAAO,KAAK,EAO7C,GAHI,IAAI,KAAK,SAAS,GAAG,GAGrB,IAAI,SAAW,MAAO,OAAO,KAAK,EAGtC,IAAI,UAAU,eAAgB,WAAW,EACzC,IAAI,UAAU,gBAAiB,KAAK,iBAAiB,EACrD,IAAI,KAAK,KAAK,SAAS,CACzB,CAAC,CACH,CACF"}
@@ -1,3 +1,3 @@
1
1
 
2
- import { a as RawUploadPart, c as buildFileTypeFilter, i as upload, l as resolveMimeTypes, n as buildUploadMiddleware, o as UploadedFileLike, r as cleanupFiles, s as applyUploadConfig, t as UploadOptions } from "../../upload-CIZc803m.mjs";
2
+ import { a as RawUploadPart, c as buildFileTypeFilter, i as upload, l as resolveMimeTypes, n as buildUploadMiddleware, o as UploadedFileLike, r as cleanupFiles, s as applyUploadConfig, t as UploadOptions } from "../../upload-XVTyQcNN.mjs";
3
3
  export { type RawUploadPart, UploadOptions, type UploadedFileLike, applyUploadConfig, buildFileTypeFilter, buildUploadMiddleware, cleanupFiles, resolveMimeTypes, upload };
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @forinda/kickjs v6.5.0
2
+ * @forinda/kickjs v6.5.1
3
3
  *
4
4
  * Copyright (c) Felix Orinda
5
5
  *
@@ -8,6 +8,6 @@
8
8
  *
9
9
  * @license MIT
10
10
  */
11
- import{n as buildFileTypeFilter,r as resolveMimeTypes,t as applyUploadConfig}from"../../upload-config-CFfHvoHF.mjs";import{createRequire}from"node:module";import{unlink}from"node:fs/promises";const requireFromHere=createRequire(import.meta.url);let _multer;function loadMulter(){if(_multer)return _multer;try{return _multer=requireFromHere(`multer`),_multer}catch{throw Error(`@forinda/kickjs: file uploads require the 'multer' package, which is not installed.
11
+ import{n as buildFileTypeFilter,r as resolveMimeTypes,t as applyUploadConfig}from"../../upload-config-Dd_QvlpC.mjs";import{createRequire}from"node:module";import{unlink}from"node:fs/promises";const requireFromHere=createRequire(import.meta.url);let _multer;function loadMulter(){if(_multer)return _multer;try{return _multer=requireFromHere(`multer`),_multer}catch{throw Error(`@forinda/kickjs: file uploads require the 'multer' package, which is not installed.
12
12
  Install it as a peer dependency: pnpm add multer (or npm i multer / yarn add multer).`)}}function createMulter(options){let limits={fileSize:options.maxSize??5*1024*1024},fileFilter;if(options.allowedTypes){let typeAllowed=buildFileTypeFilter(options.allowedTypes,options.customMimeMap);fileFilter=(_req,file,cb)=>{typeAllowed(file.mimetype,file.originalname)?cb(null,!0):cb(Error(`File type ${file.mimetype} is not allowed`))}}let multerOptions={limits,...fileFilter?{fileFilter}:{},...options.storage?{storage:options.storage}:{},...options.dest?{dest:options.dest}:{}};return loadMulter()(multerOptions)}function single(fieldName,options={}){return createMulter(options).single(fieldName)}function array(fieldName,maxCount=10,options={}){return createMulter(options).array(fieldName,maxCount)}function none(options={}){return createMulter(options).none()}function cleanupFiles(){return(req,res,next)=>{res.on(`finish`,async()=>{let files=[];if(req.file?.path&&files.push(req.file),Array.isArray(req.files))for(let f of req.files)f?.path&&files.push(f);for(let file of files)try{await unlink(file.path)}catch{}}),next()}}function buildUploadMiddleware(config){let options={};config.maxSize&&(options.maxSize=config.maxSize),config.allowedTypes&&(options.allowedTypes=config.allowedTypes),config.customMimeMap&&(options.customMimeMap=config.customMimeMap);let fieldName=config.fieldName??`file`;switch(config.mode){case`single`:return single(fieldName,options);case`array`:return array(fieldName,config.maxCount??10,options);case`none`:return none(options)}}const upload={single,array,none};export{applyUploadConfig,buildFileTypeFilter,buildUploadMiddleware,cleanupFiles,resolveMimeTypes,upload};
13
13
  //# sourceMappingURL=upload.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"upload.mjs","names":[],"sources":["../../../src/http/middleware/upload.ts"],"sourcesContent":["import { unlink } from 'node:fs/promises'\nimport { createRequire } from 'node:module'\nimport type { Request, Response, NextFunction, RequestHandler } from 'express'\nimport type { Options as MulterOptions } from 'multer'\nimport type { BaseUploadOptions, FileUploadConfig } from '../../core'\n\n// `multer` is an optional peer dependency. We load it lazily via\n// `createRequire` so importing this module never touches `multer` —\n// only constructing an upload middleware does. Adopters who never\n// call `upload.single/array/none()` or use `@FileUpload` don't need\n// `multer` installed at all.\n//\n// multer uses CJS `export = multer`, so the module is itself the\n// callable factory — no `.default` indirection on either the type\n// or the runtime side.\nconst requireFromHere = createRequire(import.meta.url)\ntype MulterFactory = typeof import('multer')\nlet _multer: MulterFactory | undefined\n\nfunction loadMulter(): MulterFactory {\n if (_multer) return _multer\n try {\n _multer = requireFromHere('multer') as MulterFactory\n return _multer\n } catch {\n throw new Error(\n \"@forinda/kickjs: file uploads require the 'multer' package, which is not installed.\\n\" +\n 'Install it as a peer dependency: pnpm add multer (or npm i multer / yarn add multer).',\n )\n }\n}\n\n// Pure upload core (MIME map, type filter, applyUploadConfig) moved to\n// `./upload-config` so the edge-safe web entry can use it without this\n// module's node-only surface. Re-exported here for compatibility.\nexport {\n buildFileTypeFilter,\n resolveMimeTypes,\n applyUploadConfig,\n type UploadedFileLike,\n type RawUploadPart,\n} from './upload-config'\nimport { buildFileTypeFilter } from './upload-config'\n\n/**\n * Upload options for the middleware.\n * Extends BaseUploadOptions from core (shared with @FileUpload decorator)\n * and adds Multer-specific storage options.\n */\nexport interface UploadOptions extends BaseUploadOptions {\n /** Multer storage config (default: memory storage) */\n storage?: MulterOptions['storage']\n /** Multer dest for disk storage shorthand */\n dest?: string\n}\n\nfunction createMulter(options: UploadOptions) {\n const limits: MulterOptions['limits'] = {\n fileSize: options.maxSize ?? 5 * 1024 * 1024,\n }\n\n let fileFilter: MulterOptions['fileFilter'] | undefined\n if (options.allowedTypes) {\n const typeAllowed = buildFileTypeFilter(options.allowedTypes, options.customMimeMap)\n fileFilter = (_req, file, cb) => {\n if (typeAllowed(file.mimetype, file.originalname)) {\n cb(null, true)\n } else {\n cb(new Error(`File type ${file.mimetype} is not allowed`))\n }\n }\n }\n\n const multerOptions: MulterOptions = {\n limits,\n ...(fileFilter ? { fileFilter } : {}),\n ...(options.storage ? { storage: options.storage } : {}),\n ...(options.dest ? { dest: options.dest } : {}),\n }\n\n return loadMulter()(multerOptions)\n}\n\n/**\n * Single file upload middleware. Attaches the file to `req.file`.\n *\n * @example\n * ```ts\n * @Post('/avatar')\n * @Middleware(upload.single('avatar', { maxSize: 2 * 1024 * 1024, allowedTypes: ['jpg', 'png'] }))\n * async uploadAvatar(ctx: RequestContext) {\n * ctx.json({ filename: ctx.file.originalname })\n * }\n * ```\n */\nfunction single(fieldName: string, options: UploadOptions = {}): RequestHandler {\n const m = createMulter(options)\n return m.single(fieldName) as RequestHandler\n}\n\n/**\n * Multiple file upload middleware. Attaches files to `req.files`.\n */\nfunction array(fieldName: string, maxCount = 10, options: UploadOptions = {}): RequestHandler {\n const m = createMulter(options)\n return m.array(fieldName, maxCount) as RequestHandler\n}\n\n/**\n * No file upload — just parse multipart form data without file fields.\n */\nfunction none(options: UploadOptions = {}): RequestHandler {\n const m = createMulter(options)\n return m.none() as RequestHandler\n}\n\n/**\n * Removes temporary files from disk after the response is sent.\n * Attach this as Express middleware after the upload middleware.\n * Works with both `req.file` (single) and `req.files` (array).\n *\n * @example\n * ```ts\n * @Post('/process')\n * @Middleware(upload.single('document', { dest: '/tmp/uploads' }), cleanupFiles())\n * async processDocument(ctx: RequestContext) {\n * ctx.json({ ok: true })\n * }\n * ```\n */\nexport function cleanupFiles() {\n return (req: Request, res: Response, next: NextFunction) => {\n res.on('finish', async () => {\n const files: any[] = []\n\n if ((req as any).file?.path) {\n files.push((req as any).file)\n }\n if (Array.isArray((req as any).files)) {\n for (const f of (req as any).files) {\n if (f?.path) files.push(f)\n }\n }\n\n for (const file of files) {\n try {\n await unlink(file.path)\n } catch {\n // File may already be moved/deleted by the handler — ignore\n }\n }\n })\n\n next()\n }\n}\n\n/**\n * Build upload middleware from a @FileUpload decorator config.\n * Used internally by the router builder when it detects FILE_UPLOAD metadata.\n * Accepts the same FileUploadConfig interface used by the @FileUpload decorator.\n */\nexport function buildUploadMiddleware(config: FileUploadConfig): RequestHandler {\n const options: UploadOptions = {}\n if (config.maxSize) options.maxSize = config.maxSize\n if (config.allowedTypes) options.allowedTypes = config.allowedTypes\n if (config.customMimeMap) options.customMimeMap = config.customMimeMap\n\n const fieldName = config.fieldName ?? 'file'\n\n switch (config.mode) {\n case 'single':\n return single(fieldName, options)\n case 'array':\n return array(fieldName, config.maxCount ?? 10, options)\n case 'none':\n return none(options)\n }\n}\n\n/** Upload middleware factory with `.single()`, `.array()`, `.none()` methods */\nexport const upload = { single, array, none }\n"],"mappings":";;;;;;;;;;gMAeA,MAAM,gBAAkB,cAAc,OAAO,KAAK,GAAG,EAErD,IAAI,QAEJ,SAAS,YAA4B,CACnC,GAAI,QAAS,OAAO,QACpB,GAAI,CAEF,MADA,SAAU,gBAAgB,QAAQ,EAC3B,OACT,MAAQ,CACN,MAAU,MACR;sFAEF,CACF,CACF,CA0BA,SAAS,aAAa,QAAwB,CAC5C,IAAM,OAAkC,CACtC,SAAU,QAAQ,SAAW,EAAI,KAAO,IAC1C,EAEI,WACJ,GAAI,QAAQ,aAAc,CACxB,IAAM,YAAc,oBAAoB,QAAQ,aAAc,QAAQ,aAAa,EACnF,YAAc,KAAM,KAAM,KAAO,CAC3B,YAAY,KAAK,SAAU,KAAK,YAAY,EAC9C,GAAG,KAAM,EAAI,EAEb,GAAO,MAAM,aAAa,KAAK,SAAS,gBAAgB,CAAC,CAE7D,CACF,CAEA,IAAM,cAA+B,CACnC,OACA,GAAI,WAAa,CAAE,UAAW,EAAI,CAAC,EACnC,GAAI,QAAQ,QAAU,CAAE,QAAS,QAAQ,OAAQ,EAAI,CAAC,EACtD,GAAI,QAAQ,KAAO,CAAE,KAAM,QAAQ,IAAK,EAAI,CAAC,CAC/C,EAEA,OAAO,WAAW,CAAC,CAAC,aAAa,CACnC,CAcA,SAAS,OAAO,UAAmB,QAAyB,CAAC,EAAmB,CAE9E,OADU,aAAa,OAChB,CAAC,CAAC,OAAO,SAAS,CAC3B,CAKA,SAAS,MAAM,UAAmB,SAAW,GAAI,QAAyB,CAAC,EAAmB,CAE5F,OADU,aAAa,OAChB,CAAC,CAAC,MAAM,UAAW,QAAQ,CACpC,CAKA,SAAS,KAAK,QAAyB,CAAC,EAAmB,CAEzD,OADU,aAAa,OAChB,CAAC,CAAC,KAAK,CAChB,CAgBA,SAAgB,cAAe,CAC7B,OAAQ,IAAc,IAAe,OAAuB,CAC1D,IAAI,GAAG,SAAU,SAAY,CAC3B,IAAM,MAAe,CAAC,EAKtB,GAHK,IAAY,MAAM,MACrB,MAAM,KAAM,IAAY,IAAI,EAE1B,MAAM,QAAS,IAAY,KAAK,MAC7B,IAAM,KAAM,IAAY,MACvB,GAAG,MAAM,MAAM,KAAK,CAAC,EAI7B,IAAK,IAAM,QAAQ,MACjB,GAAI,CACF,MAAM,OAAO,KAAK,IAAI,CACxB,MAAQ,CAER,CAEJ,CAAC,EAED,KAAK,CACP,CACF,CAOA,SAAgB,sBAAsB,OAA0C,CAC9E,IAAM,QAAyB,CAAC,EAC5B,OAAO,UAAS,QAAQ,QAAU,OAAO,SACzC,OAAO,eAAc,QAAQ,aAAe,OAAO,cACnD,OAAO,gBAAe,QAAQ,cAAgB,OAAO,eAEzD,IAAM,UAAY,OAAO,WAAa,OAEtC,OAAQ,OAAO,KAAf,CACE,IAAK,SACH,OAAO,OAAO,UAAW,OAAO,EAClC,IAAK,QACH,OAAO,MAAM,UAAW,OAAO,UAAY,GAAI,OAAO,EACxD,IAAK,OACH,OAAO,KAAK,OAAO,CACvB,CACF,CAGA,MAAa,OAAS,CAAE,OAAQ,MAAO,IAAK"}
1
+ {"version":3,"file":"upload.mjs","names":[],"sources":["../../../src/http/middleware/upload.ts"],"sourcesContent":["import { unlink } from 'node:fs/promises'\nimport { createRequire } from 'node:module'\nimport type { Request, Response, NextFunction, RequestHandler } from 'express'\nimport type { Options as MulterOptions } from 'multer'\nimport type { BaseUploadOptions, FileUploadConfig } from '../../core'\n\n// `multer` is an optional peer dependency. We load it lazily via\n// `createRequire` so importing this module never touches `multer` —\n// only constructing an upload middleware does. Adopters who never\n// call `upload.single/array/none()` or use `@FileUpload` don't need\n// `multer` installed at all.\n//\n// multer uses CJS `export = multer`, so the module is itself the\n// callable factory — no `.default` indirection on either the type\n// or the runtime side.\nconst requireFromHere = createRequire(import.meta.url)\ntype MulterFactory = typeof import('multer')\nlet _multer: MulterFactory | undefined\n\nfunction loadMulter(): MulterFactory {\n if (_multer) return _multer\n try {\n _multer = requireFromHere('multer') as MulterFactory\n return _multer\n } catch {\n throw new Error(\n \"@forinda/kickjs: file uploads require the 'multer' package, which is not installed.\\n\" +\n 'Install it as a peer dependency: pnpm add multer (or npm i multer / yarn add multer).',\n )\n }\n}\n\n// Pure upload core (MIME map, type filter, applyUploadConfig) moved to\n// `./upload-config` so the edge-safe web entry can use it without this\n// module's node-only surface. Re-exported here for compatibility.\nexport {\n buildFileTypeFilter,\n resolveMimeTypes,\n applyUploadConfig,\n type UploadedFileLike,\n type RawUploadPart,\n} from './upload-config'\nimport { buildFileTypeFilter } from './upload-config'\n\n/**\n * Upload options for the middleware.\n * Extends BaseUploadOptions from core (shared with @FileUpload decorator)\n * and adds Multer-specific storage options.\n */\nexport interface UploadOptions extends BaseUploadOptions {\n /** Multer storage config (default: memory storage) */\n storage?: MulterOptions['storage']\n /** Multer dest for disk storage shorthand */\n dest?: string\n}\n\nfunction createMulter(options: UploadOptions) {\n const limits: MulterOptions['limits'] = {\n fileSize: options.maxSize ?? 5 * 1024 * 1024,\n }\n\n let fileFilter: MulterOptions['fileFilter'] | undefined\n if (options.allowedTypes) {\n const typeAllowed = buildFileTypeFilter(options.allowedTypes, options.customMimeMap)\n fileFilter = (_req, file, cb) => {\n if (typeAllowed(file.mimetype, file.originalname)) {\n cb(null, true)\n } else {\n cb(new Error(`File type ${file.mimetype} is not allowed`))\n }\n }\n }\n\n const multerOptions: MulterOptions = {\n limits,\n ...(fileFilter ? { fileFilter } : {}),\n ...(options.storage ? { storage: options.storage } : {}),\n ...(options.dest ? { dest: options.dest } : {}),\n }\n\n return loadMulter()(multerOptions)\n}\n\n/**\n * Single file upload middleware. Attaches the file to `req.file`.\n *\n * @example\n * ```ts\n * @Post('/avatar')\n * @Middleware(upload.single('avatar', { maxSize: 2 * 1024 * 1024, allowedTypes: ['jpg', 'png'] }))\n * async uploadAvatar(ctx: RequestContext) {\n * ctx.json({ filename: ctx.file.originalname })\n * }\n * ```\n */\nfunction single(fieldName: string, options: UploadOptions = {}): RequestHandler {\n const m = createMulter(options)\n return m.single(fieldName) as RequestHandler\n}\n\n/**\n * Multiple file upload middleware. Attaches files to `req.files`.\n */\nfunction array(fieldName: string, maxCount = 10, options: UploadOptions = {}): RequestHandler {\n const m = createMulter(options)\n return m.array(fieldName, maxCount) as RequestHandler\n}\n\n/**\n * No file upload — just parse multipart form data without file fields.\n */\nfunction none(options: UploadOptions = {}): RequestHandler {\n const m = createMulter(options)\n return m.none() as RequestHandler\n}\n\n/**\n * Removes temporary files from disk after the response is sent.\n * Attach this as Express middleware after the upload middleware.\n * Works with both `req.file` (single) and `req.files` (array).\n *\n * @example\n * ```ts\n * @Post('/process')\n * @Middleware(upload.single('document', { dest: '/tmp/uploads' }), cleanupFiles())\n * async processDocument(ctx: RequestContext) {\n * ctx.json({ ok: true })\n * }\n * ```\n */\nexport function cleanupFiles() {\n return (req: Request, res: Response, next: NextFunction) => {\n res.on('finish', async () => {\n const files: any[] = []\n\n if ((req as any).file?.path) {\n files.push((req as any).file)\n }\n if (Array.isArray((req as any).files)) {\n for (const f of (req as any).files) {\n if (f?.path) files.push(f)\n }\n }\n\n for (const file of files) {\n try {\n await unlink(file.path)\n } catch {\n // File may already be moved/deleted by the handler — ignore\n }\n }\n })\n\n next()\n }\n}\n\n/**\n * Build upload middleware from a @FileUpload decorator config.\n * Used internally by the router builder when it detects FILE_UPLOAD metadata.\n * Accepts the same FileUploadConfig interface used by the @FileUpload decorator.\n */\nexport function buildUploadMiddleware(config: FileUploadConfig): RequestHandler {\n const options: UploadOptions = {}\n if (config.maxSize) options.maxSize = config.maxSize\n if (config.allowedTypes) options.allowedTypes = config.allowedTypes\n if (config.customMimeMap) options.customMimeMap = config.customMimeMap\n\n const fieldName = config.fieldName ?? 'file'\n\n switch (config.mode) {\n case 'single':\n return single(fieldName, options)\n case 'array':\n return array(fieldName, config.maxCount ?? 10, options)\n case 'none':\n return none(options)\n }\n}\n\n/** Upload middleware factory with `.single()`, `.array()`, `.none()` methods */\nexport const upload = { single, array, none }\n"],"mappings":";;;;;;;;;;gMAeA,MAAM,gBAAkB,cAAc,OAAO,KAAK,GAAG,EAErD,IAAI,QAEJ,SAAS,YAA4B,CACnC,GAAI,QAAS,OAAO,QACpB,GAAI,CAEF,MADA,SAAU,gBAAgB,QAAQ,EAC3B,OACT,MAAQ,CACN,MAAU,MACR;sFAEF,CACF,CACF,CA0BA,SAAS,aAAa,QAAwB,CAC5C,IAAM,OAAkC,CACtC,SAAU,QAAQ,SAAW,EAAI,KAAO,IAC1C,EAEI,WACJ,GAAI,QAAQ,aAAc,CACxB,IAAM,YAAc,oBAAoB,QAAQ,aAAc,QAAQ,aAAa,EACnF,YAAc,KAAM,KAAM,KAAO,CAC3B,YAAY,KAAK,SAAU,KAAK,YAAY,EAC9C,GAAG,KAAM,EAAI,EAEb,GAAO,MAAM,aAAa,KAAK,SAAS,gBAAgB,CAAC,CAE7D,CACF,CAEA,IAAM,cAA+B,CACnC,OACA,GAAI,WAAa,CAAE,UAAW,EAAI,CAAC,EACnC,GAAI,QAAQ,QAAU,CAAE,QAAS,QAAQ,OAAQ,EAAI,CAAC,EACtD,GAAI,QAAQ,KAAO,CAAE,KAAM,QAAQ,IAAK,EAAI,CAAC,CAC/C,EAEA,OAAO,WAAW,CAAC,CAAC,aAAa,CACnC,CAcA,SAAS,OAAO,UAAmB,QAAyB,CAAC,EAAmB,CAE9E,OADU,aAAa,OAChB,CAAC,CAAC,OAAO,SAAS,CAC3B,CAKA,SAAS,MAAM,UAAmB,SAAW,GAAI,QAAyB,CAAC,EAAmB,CAE5F,OADU,aAAa,OAChB,CAAC,CAAC,MAAM,UAAW,QAAQ,CACpC,CAKA,SAAS,KAAK,QAAyB,CAAC,EAAmB,CAEzD,OADU,aAAa,OAChB,CAAC,CAAC,KAAK,CAChB,CAgBA,SAAgB,cAAe,CAC7B,OAAQ,IAAc,IAAe,OAAuB,CAC1D,IAAI,GAAG,SAAU,SAAY,CAC3B,IAAM,MAAe,CAAC,EAKtB,GAHK,IAAY,MAAM,MACrB,MAAM,KAAM,IAAY,IAAI,EAE1B,MAAM,QAAS,IAAY,KAAK,EAC7B,IAAA,IAAM,KAAM,IAAY,MACvB,GAAG,MAAM,MAAM,KAAK,CAAC,EAI7B,IAAK,IAAM,QAAQ,MACjB,GAAI,CACF,MAAM,OAAO,KAAK,IAAI,CACxB,MAAQ,CAER,CAEJ,CAAC,EAED,KAAK,CACP,CACF,CAOA,SAAgB,sBAAsB,OAA0C,CAC9E,IAAM,QAAyB,CAAC,EAC5B,OAAO,UAAS,QAAQ,QAAU,OAAO,SACzC,OAAO,eAAc,QAAQ,aAAe,OAAO,cACnD,OAAO,gBAAe,QAAQ,cAAgB,OAAO,eAEzD,IAAM,UAAY,OAAO,WAAa,OAEtC,OAAQ,OAAO,KAAf,CACE,IAAK,SACH,OAAO,OAAO,UAAW,OAAO,EAClC,IAAK,QACH,OAAO,MAAM,UAAW,OAAO,UAAY,GAAI,OAAO,EACxD,IAAK,OACH,OAAO,KAAK,OAAO,CACvB,CACF,CAGA,MAAa,OAAS,CAAE,OAAQ,MAAO,IAAK"}
@@ -1,3 +1,3 @@
1
1
 
2
- import { n as validate, t as ValidationSchema } from "../../validate-DoZDOhCi.mjs";
2
+ import { n as validate, t as ValidationSchema } from "../../validate-DMYpUnrf.mjs";
3
3
  export { ValidationSchema, validate };
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @forinda/kickjs v6.5.0
2
+ * @forinda/kickjs v6.5.1
3
3
  *
4
4
  * Copyright (c) Felix Orinda
5
5
  *
@@ -1,3 +1,3 @@
1
1
 
2
- import { n as ViewAdapterOptions, t as ViewAdapter } from "../../views-Kp8Z3AO1.mjs";
2
+ import { n as ViewAdapterOptions, t as ViewAdapter } from "../../views-DsfBT1fR.mjs";
3
3
  export { ViewAdapter, ViewAdapterOptions };
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @forinda/kickjs v6.5.0
2
+ * @forinda/kickjs v6.5.1
3
3
  *
4
4
  * Copyright (c) Felix Orinda
5
5
  *
@@ -8,5 +8,4 @@
8
8
  *
9
9
  * @license MIT
10
10
  */
11
- import{Logger}from"../../core/logger.mjs";import{d as defineAdapter}from"../../core-TDR0XGzO.mjs";import{resolve}from"node:path";const log=Logger.for(`ViewEngine`),ViewAdapter=defineAdapter({name:`ViewAdapter`,build:options=>({beforeMount({app}){let{engine,ext,viewsDir=`src/views`}=options;engine.__express?app.engine(ext,engine.__express):typeof engine.renderFile==`function`?app.engine(ext,(path,opts,callback)=>{engine.renderFile(path,opts,callback)}):(typeof engine==`function`||log.warn(`Engine for .${ext} does not have __express or renderFile. Trying as-is.`),app.engine(ext,engine)),app.set(`view engine`,ext),app.set(`views`,resolve(viewsDir)),log.debug(`View engine: ${ext} (${resolve(viewsDir)})`)}})});export{ViewAdapter};
12
- //# sourceMappingURL=views.mjs.map
11
+ import{t as ViewAdapter}from"../../views-Dj6XFaca.mjs";export{ViewAdapter};
@@ -1,3 +1,3 @@
1
1
 
2
- import { C as SortItem, S as QueryFieldConfig, T as TypedParsedQuery, _ as FilterOperator, a as getQueryParsingDefaults, b as ParsedQuery, c as parseQuery, d as resetQueryParsingDefaults, f as setQueryParsingDefaults, g as FilterItem, h as FieldsOf, i as buildQueryParams, l as parseSearchQuery, m as FILTER_OPERATORS, n as QueryRejectReason, o as parseFilters, p as ColumnQueryFieldConfig, r as QueryRejection, s as parsePagination, t as ParseQueryOptions, u as parseSort, v as PaginatedResponse, w as StringQueryFieldConfig, x as QueryBuilderAdapter, y as PaginationParams } from "../../index-BtWJ9SLP.mjs";
2
+ import { C as SortItem, S as QueryFieldConfig, T as TypedParsedQuery, _ as FilterOperator, a as getQueryParsingDefaults, b as ParsedQuery, c as parseQuery, d as resetQueryParsingDefaults, f as setQueryParsingDefaults, g as FilterItem, h as FieldsOf, i as buildQueryParams, l as parseSearchQuery, m as FILTER_OPERATORS, n as QueryRejectReason, o as parseFilters, p as ColumnQueryFieldConfig, r as QueryRejection, s as parsePagination, t as ParseQueryOptions, u as parseSort, v as PaginatedResponse, w as StringQueryFieldConfig, x as QueryBuilderAdapter, y as PaginationParams } from "../../index-BfT5KZ-M.mjs";
3
3
  export { type ColumnQueryFieldConfig, FILTER_OPERATORS, type FieldsOf, type FilterItem, type FilterOperator, type PaginatedResponse, type PaginationParams, type ParseQueryOptions, type ParsedQuery, type QueryBuilderAdapter, type QueryFieldConfig, type QueryRejectReason, type QueryRejection, type SortItem, type StringQueryFieldConfig, type TypedParsedQuery, buildQueryParams, getQueryParsingDefaults, parseFilters, parsePagination, parseQuery, parseSearchQuery, parseSort, resetQueryParsingDefaults, setQueryParsingDefaults };
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @forinda/kickjs v6.5.0
2
+ * @forinda/kickjs v6.5.1
3
3
  *
4
4
  * Copyright (c) Felix Orinda
5
5
  *
@@ -8,4 +8,4 @@
8
8
  *
9
9
  * @license MIT
10
10
  */
11
- import{a as parseQuery,c as resetQueryParsingDefaults,i as parsePagination,l as setQueryParsingDefaults,n as getQueryParsingDefaults,o as parseSearchQuery,r as parseFilters,s as parseSort,t as buildQueryParams,u as FILTER_OPERATORS}from"../../query-gMAVXzx2.mjs";export{FILTER_OPERATORS,buildQueryParams,getQueryParsingDefaults,parseFilters,parsePagination,parseQuery,parseSearchQuery,parseSort,resetQueryParsingDefaults,setQueryParsingDefaults};
11
+ import{a as parseQuery,c as resetQueryParsingDefaults,i as parsePagination,l as setQueryParsingDefaults,n as getQueryParsingDefaults,o as parseSearchQuery,r as parseFilters,s as parseSort,t as buildQueryParams,u as FILTER_OPERATORS}from"../../query-CXN52dzy.mjs";export{FILTER_OPERATORS,buildQueryParams,getQueryParsingDefaults,parseFilters,parsePagination,parseQuery,parseSearchQuery,parseSort,resetQueryParsingDefaults,setQueryParsingDefaults};
@@ -1,3 +1,3 @@
1
1
 
2
- import { i as buildRouteTable, n as _setExternalContributorSources, r as assertRouteUnique, t as BuildRoutesOptions } from "../router-builder-GWgxoOdC.mjs";
2
+ import { i as buildRouteTable, n as _setExternalContributorSources, r as assertRouteUnique, t as BuildRoutesOptions } from "../router-builder-CMGhEBU2.mjs";
3
3
  export { BuildRoutesOptions, _setExternalContributorSources, assertRouteUnique, buildRouteTable };
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @forinda/kickjs v6.5.0
2
+ * @forinda/kickjs v6.5.1
3
3
  *
4
4
  * Copyright (c) Felix Orinda
5
5
  *
@@ -8,5 +8,4 @@
8
8
  *
9
9
  * @license MIT
10
10
  */
11
- import{METADATA}from"../core/interfaces.mjs";import{o as duplicateRouteError,t as Container}from"../container-CBaL5lus.mjs";import{a as getMethodMeta,o as getMethodMetaOrUndefined,t as getClassMeta}from"../metadata-CUDfhy4e.mjs";import{n as buildPipeline,t as runContributors}from"../contributor-runner-Cu13cDQp.mjs";let _externalContributorSources=[];function _setExternalContributorSources(sources){_externalContributorSources=sources}function assertRouteUnique(registry,method,fullPath,owner){let key=`${method.toUpperCase()} ${fullPath.replace(/:[^/]+/g,`:*`)}`,prior=registry.get(key);if(prior!==void 0)throw duplicateRouteError(method.toUpperCase(),fullPath,owner,prior);registry.set(key,owner)}function buildRouteTable(controllerClass,options={}){let container=Container.getInstance(),externalSources=options.externalSources??_externalContributorSources,routes=getClassMeta(METADATA.ROUTES,controllerClass,[]),classMiddlewares=getClassMeta(METADATA.CLASS_MIDDLEWARES,controllerClass,[]),classContributors=getClassMeta(METADATA.CLASS_CONTRIBUTORS,controllerClass,[]),entries=[];for(let route of routes){let method=route.method.toUpperCase(),fullPath=route.path||`/`,methodMiddlewares=getMethodMeta(METADATA.METHOD_MIDDLEWARES,controllerClass,route.handlerName,[]),fileUploadConfig=getMethodMetaOrUndefined(METADATA.FILE_UPLOAD,controllerClass,route.handlerName),methodContributors=getMethodMeta(METADATA.METHOD_CONTRIBUTORS,controllerClass,route.handlerName,[]),contributorRunner=null;if(classContributors.length>0||methodContributors.length>0||externalSources.length>0){let pipeline=buildPipeline([...methodContributors.map((registration,i)=>({source:`method`,registration,label:`${controllerClass.name}.${String(route.handlerName)}#${i}(${registration.key})`})),...classContributors.map((registration,i)=>({source:`class`,registration,label:`${controllerClass.name}.@class#${i}(${registration.key})`})),...externalSources],{route:`${method} ${fullPath}`});contributorRunner=ctx=>runContributors({pipeline,ctx,container})}let handler=ctx=>container.resolve(controllerClass)[route.handlerName](ctx);entries.push({method,path:fullPath,middlewares:[...classMiddlewares,...methodMiddlewares],contributorRunner,handler,meta:{controller:controllerClass,handlerName:route.handlerName,validation:route.validation,upload:fileUploadConfig}})}return entries}export{_setExternalContributorSources,assertRouteUnique,buildRouteTable};
12
- //# sourceMappingURL=router-builder.mjs.map
11
+ import{n as assertRouteUnique,r as buildRouteTable,t as _setExternalContributorSources}from"../router-builder-BbgVXuy3.mjs";export{_setExternalContributorSources,assertRouteUnique,buildRouteTable};
@@ -1,7 +1,6 @@
1
1
 
2
- import { f as HttpRuntime } from "../../adapter-CEt1MEdF.mjs";
2
+ import { f as HttpRuntime } from "../../adapter-CbMq-NBf.mjs";
3
3
  import { IncomingMessage, ServerResponse } from "node:http";
4
-
5
4
  //#region src/http/runtimes/fastify.d.ts
6
5
  interface FastifyReplyLike {
7
6
  code(statusCode: number): FastifyReplyLike;