@forinda/kickjs 8.4.0 → 8.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (96) hide show
  1. package/dist/{application-Bm3wCm06.mjs → application-BFKE8ac5.mjs} +3 -3
  2. package/dist/{application-Bm3wCm06.mjs.map → application-BFKE8ac5.mjs.map} +1 -1
  3. package/dist/{application-C2WveUZr.d.mts → application-BRvykQ6h.d.mts} +65 -6
  4. package/dist/application-BRvykQ6h.d.mts.map +1 -0
  5. package/dist/{bootstrap-DHftqJ1m.mjs → bootstrap-CPRgpW3i.mjs} +3 -3
  6. package/dist/{bootstrap-DHftqJ1m.mjs.map → bootstrap-CPRgpW3i.mjs.map} +1 -1
  7. package/dist/{client-ip-D9nKcjVJ.mjs → client-ip-CW7HwSOm.mjs} +2 -2
  8. package/dist/{client-ip-D9nKcjVJ.mjs.map → client-ip-CW7HwSOm.mjs.map} +1 -1
  9. package/dist/config/index.mjs +2 -2
  10. package/dist/{config-pot4-2DS.mjs → config-Cajrc3qr.mjs} +3 -3
  11. package/dist/{config-pot4-2DS.mjs.map → config-Cajrc3qr.mjs.map} +1 -1
  12. package/dist/{container-BB_XC2ww.mjs → container-Cj2hqlfm.mjs} +3 -3
  13. package/dist/{container-BB_XC2ww.mjs.map → container-Cj2hqlfm.mjs.map} +1 -1
  14. package/dist/{context-Xd8C4fIo.mjs → context-B7N5oE7S.mjs} +3 -3
  15. package/dist/{context-Xd8C4fIo.mjs.map → context-B7N5oE7S.mjs.map} +1 -1
  16. package/dist/{context-errors-doMQ4bAU.mjs → context-errors-Cj2_aDaj.mjs} +2 -2
  17. package/dist/{context-errors-doMQ4bAU.mjs.map → context-errors-Cj2_aDaj.mjs.map} +1 -1
  18. package/dist/{contributor-runner-DflutMFy.mjs → contributor-runner-DQCZLpvk.mjs} +3 -3
  19. package/dist/{contributor-runner-DflutMFy.mjs.map → contributor-runner-DQCZLpvk.mjs.map} +1 -1
  20. package/dist/core/adapter.mjs +1 -1
  21. package/dist/core/app-module.mjs +1 -1
  22. package/dist/core/cache.mjs +1 -1
  23. package/dist/core/container.mjs +2 -2
  24. package/dist/core/cron.mjs +2 -2
  25. package/dist/core/decorators.mjs +2 -2
  26. package/dist/core/errors.mjs +1 -1
  27. package/dist/core/interfaces.mjs +1 -1
  28. package/dist/core/logger.mjs +1 -1
  29. package/dist/core/path.mjs +1 -1
  30. package/dist/core/plugin.mjs +1 -1
  31. package/dist/core/reactivity.mjs +1 -1
  32. package/dist/{core-CTyRc4AM.mjs → core-DZmGThrF.mjs} +3 -3
  33. package/dist/{core-CTyRc4AM.mjs.map → core-DZmGThrF.mjs.map} +1 -1
  34. package/dist/{csrf-CMzwva6A.mjs → csrf-DPPIM72I.mjs} +3 -3
  35. package/dist/{csrf-CMzwva6A.mjs.map → csrf-DPPIM72I.mjs.map} +1 -1
  36. package/dist/{decorate-BbFyJ1kh.mjs → decorate-DHyinlPY.mjs} +1 -1
  37. package/dist/{define-adapter-CsDcNhlh.mjs → define-adapter-0asM4v0B.mjs} +2 -2
  38. package/dist/{define-adapter-CsDcNhlh.mjs.map → define-adapter-0asM4v0B.mjs.map} +1 -1
  39. package/dist/{disposables-CZ7vf6L_.mjs → disposables-BYYy0y_z.mjs} +2 -2
  40. package/dist/{disposables-CZ7vf6L_.mjs.map → disposables-BYYy0y_z.mjs.map} +1 -1
  41. package/dist/{env-BTOmTNsH.mjs → env-DWP_2owJ.mjs} +3 -3
  42. package/dist/{env-BTOmTNsH.mjs.map → env-DWP_2owJ.mjs.map} +1 -1
  43. package/dist/{handler-8OeK5Hkh.mjs → handler-B4MQmJR5.mjs} +3 -3
  44. package/dist/{handler-8OeK5Hkh.mjs.map → handler-B4MQmJR5.mjs.map} +1 -1
  45. package/dist/http/application.d.mts +1 -1
  46. package/dist/http/application.mjs +2 -2
  47. package/dist/http/bootstrap.d.mts +1 -1
  48. package/dist/http/bootstrap.mjs +2 -2
  49. package/dist/http/context.mjs +2 -2
  50. package/dist/http/middleware/cors.mjs +1 -1
  51. package/dist/http/middleware/csrf.mjs +2 -2
  52. package/dist/http/middleware/error-handler.mjs +2 -2
  53. package/dist/http/middleware/helmet.mjs +1 -1
  54. package/dist/http/middleware/rate-limit.mjs +2 -2
  55. package/dist/http/middleware/request-id.mjs +1 -1
  56. package/dist/http/middleware/request-logger.mjs +2 -2
  57. package/dist/http/middleware/session.mjs +2 -2
  58. package/dist/http/middleware/spa.d.mts +1 -1
  59. package/dist/http/middleware/spa.mjs +2 -2
  60. package/dist/http/middleware/upload.mjs +2 -2
  61. package/dist/http/middleware/validate.mjs +1 -1
  62. package/dist/http/middleware/views.d.mts +1 -1
  63. package/dist/http/middleware/views.mjs +2 -2
  64. package/dist/http/query/index.mjs +2 -2
  65. package/dist/http/router-builder.mjs +2 -2
  66. package/dist/http/runtimes/fastify.mjs +2 -2
  67. package/dist/http/runtimes/h3-web.d.mts.map +1 -1
  68. package/dist/http/runtimes/h3-web.mjs +2 -2
  69. package/dist/http/runtimes/h3-web.mjs.map +1 -1
  70. package/dist/http/runtimes/h3.mjs +2 -2
  71. package/dist/index.d.mts +2 -2
  72. package/dist/index.mjs +2 -2
  73. package/dist/index.mjs.map +1 -1
  74. package/dist/{kv-stores-C755yuvc.mjs → kv-stores-D2MKbvcu.mjs} +3 -3
  75. package/dist/{kv-stores-C755yuvc.mjs.map → kv-stores-D2MKbvcu.mjs.map} +1 -1
  76. package/dist/{metadata-C_bLigwT.mjs → metadata-Ceheg5tj.mjs} +2 -2
  77. package/dist/{metadata-C_bLigwT.mjs.map → metadata-Ceheg5tj.mjs.map} +1 -1
  78. package/dist/{module-registry-B_gw6smc.mjs → module-registry-RHo93bJa.mjs} +2 -2
  79. package/dist/{module-registry-B_gw6smc.mjs.map → module-registry-RHo93bJa.mjs.map} +1 -1
  80. package/dist/{query-B7_CJZaf.mjs → query-CWwMw9E6.mjs} +2 -2
  81. package/dist/{query-B7_CJZaf.mjs.map → query-CWwMw9E6.mjs.map} +1 -1
  82. package/dist/{respond-EdWjQfD6.mjs → respond-CI4CCFG4.mjs} +2 -2
  83. package/dist/{respond-EdWjQfD6.mjs.map → respond-CI4CCFG4.mjs.map} +1 -1
  84. package/dist/{route-flag-C7AilXtr.mjs → route-flag-B7t2wGJ2.mjs} +3 -3
  85. package/dist/{route-flag-C7AilXtr.mjs.map → route-flag-B7t2wGJ2.mjs.map} +1 -1
  86. package/dist/{route-policy-BQfQEuFn.mjs → route-policy-MQkq3QEO.mjs} +2 -2
  87. package/dist/{route-policy-BQfQEuFn.mjs.map → route-policy-MQkq3QEO.mjs.map} +1 -1
  88. package/dist/{router-builder-CFAHKq4e.mjs → router-builder-CK7_6DLH.mjs} +3 -3
  89. package/dist/{router-builder-CFAHKq4e.mjs.map → router-builder-CK7_6DLH.mjs.map} +1 -1
  90. package/dist/{runtime-B2oXJDwr.mjs → runtime-B3V_u8FS.mjs} +3 -3
  91. package/dist/{runtime-B2oXJDwr.mjs.map → runtime-B3V_u8FS.mjs.map} +1 -1
  92. package/dist/{upload-config-C23IAKGT.mjs → upload-config-C49VFeoh.mjs} +2 -2
  93. package/dist/{upload-config-C23IAKGT.mjs.map → upload-config-C49VFeoh.mjs.map} +1 -1
  94. package/dist/web.mjs +2 -2
  95. package/package.json +1 -1
  96. package/dist/application-C2WveUZr.d.mts.map +0 -1
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @forinda/kickjs v8.4.0
2
+ * @forinda/kickjs v8.5.0
3
3
  *
4
4
  * Copyright (c) Felix Orinda
5
5
  *
@@ -1,3 +1,3 @@
1
1
 
2
- import { h as ViewAdapterOptions, m as ViewAdapter } from "../../application-C2WveUZr.mjs";
2
+ import { h as ViewAdapterOptions, m as ViewAdapter } from "../../application-BRvykQ6h.mjs";
3
3
  export { ViewAdapter, ViewAdapterOptions };
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @forinda/kickjs v8.4.0
2
+ * @forinda/kickjs v8.5.0
3
3
  *
4
4
  * Copyright (c) Felix Orinda
5
5
  *
@@ -8,5 +8,5 @@
8
8
  *
9
9
  * @license MIT
10
10
  */
11
- import{Logger}from"../../core/logger.mjs";import"../../core-CTyRc4AM.mjs";import{t as defineAdapter}from"../../define-adapter-CsDcNhlh.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};
11
+ import{Logger}from"../../core/logger.mjs";import"../../core-DZmGThrF.mjs";import{t as defineAdapter}from"../../define-adapter-0asM4v0B.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
12
  //# sourceMappingURL=views.mjs.map
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @forinda/kickjs v8.4.0
2
+ * @forinda/kickjs v8.5.0
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-B7_CJZaf.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-CWwMw9E6.mjs";export{FILTER_OPERATORS,buildQueryParams,getQueryParsingDefaults,parseFilters,parsePagination,parseQuery,parseSearchQuery,parseSort,resetQueryParsingDefaults,setQueryParsingDefaults};
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @forinda/kickjs v8.4.0
2
+ * @forinda/kickjs v8.5.0
3
3
  *
4
4
  * Copyright (c) Felix Orinda
5
5
  *
@@ -8,4 +8,4 @@
8
8
  *
9
9
  * @license MIT
10
10
  */
11
- import{n as assertRouteUnique,r as buildRouteTable,t as _setExternalContributorSources}from"../router-builder-CFAHKq4e.mjs";export{_setExternalContributorSources,assertRouteUnique,buildRouteTable};
11
+ import{n as assertRouteUnique,r as buildRouteTable,t as _setExternalContributorSources}from"../router-builder-CK7_6DLH.mjs";export{_setExternalContributorSources,assertRouteUnique,buildRouteTable};
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @forinda/kickjs v8.4.0
2
+ * @forinda/kickjs v8.5.0
3
3
  *
4
4
  * Copyright (c) Felix Orinda
5
5
  *
@@ -8,6 +8,6 @@
8
8
  *
9
9
  * @license MIT
10
10
  */
11
- import{HttpException}from"../../core/errors.mjs";import{a as createRequestStore,f as unsupportedMediaTypeError,n as applyHandlerResult,o as disposeRequestStore,t as publishMatchedRoute}from"../../runtime-B2oXJDwr.mjs";import{i as requestStore,t as RequestContext}from"../../context-Xd8C4fIo.mjs";import{validate}from"../middleware/validate.mjs";import{t as applyUploadConfig}from"../../upload-config-C23IAKGT.mjs";import"../middleware/upload.mjs";import{createRequire}from"node:module";const peerRequire=createRequire(import.meta.url),loadPeer=name=>{let mod=peerRequire(name);return mod&&mod.__esModule&&mod.default?mod.default:mod.default??mod},QUEUE=Symbol(`kickjs.fastify.connectQueue`),READY=Symbol(`kickjs.fastify.ready`),NEXT=Symbol(`kickjs.fastify.next`),NEEDS_MULTIPART=Symbol(`kickjs.fastify.needsMultipart`),NOOP_NEXT=()=>{};var FastifyReplyDriver=class{reply;constructor(reply){this.reply=reply}status(code){return this.reply.code(code),this}json(data){return this.reply.send(data),this}send(data){return this.reply.send(data),this}type(contentType){return this.reply.type(contentType),this}setHeader(name,value){return this.reply.header(name,value),this}render(){throw Error(`ctx.render() is not supported on the Fastify runtime (no view engine).`)}writeHead(statusCode,headers){return this.reply.hijack(),this.reply.raw.writeHead(statusCode,headers),this}flushHeaders(){return this.reply.raw.flushHeaders?.(),this}write(chunk){return this.reply.raw.write(chunk)}end(data){return this.reply.raw.end(data),this}once(event,listener){return this.reply.raw.once(event,listener),this}get headersSent(){return this.reply.sent||this.reply.raw.headersSent}};function replyDriver(reply){return new FastifyReplyDriver(reply)}function routeHandler(entry){let validator=entry.meta.validation?validate(entry.meta.validation):void 0;return async(request,reply)=>{let raw=request.raw;if(raw.body=request.body,raw.params=request.params,raw.query=request.query,entry.meta.upload&&entry.meta.upload.mode!==`none`){if(typeof request.parts!=`function`)throw Error(`@forinda/kickjs: @FileUpload on the Fastify runtime requires '@fastify/multipart'.
11
+ import{HttpException}from"../../core/errors.mjs";import{a as createRequestStore,f as unsupportedMediaTypeError,n as applyHandlerResult,o as disposeRequestStore,t as publishMatchedRoute}from"../../runtime-B3V_u8FS.mjs";import{i as requestStore,t as RequestContext}from"../../context-B7N5oE7S.mjs";import{validate}from"../middleware/validate.mjs";import{t as applyUploadConfig}from"../../upload-config-C49VFeoh.mjs";import"../middleware/upload.mjs";import{createRequire}from"node:module";const peerRequire=createRequire(import.meta.url),loadPeer=name=>{let mod=peerRequire(name);return mod&&mod.__esModule&&mod.default?mod.default:mod.default??mod},QUEUE=Symbol(`kickjs.fastify.connectQueue`),READY=Symbol(`kickjs.fastify.ready`),NEXT=Symbol(`kickjs.fastify.next`),NEEDS_MULTIPART=Symbol(`kickjs.fastify.needsMultipart`),NOOP_NEXT=()=>{};var FastifyReplyDriver=class{reply;constructor(reply){this.reply=reply}status(code){return this.reply.code(code),this}json(data){return this.reply.send(data),this}send(data){return this.reply.send(data),this}type(contentType){return this.reply.type(contentType),this}setHeader(name,value){return this.reply.header(name,value),this}render(){throw Error(`ctx.render() is not supported on the Fastify runtime (no view engine).`)}writeHead(statusCode,headers){return this.reply.hijack(),this.reply.raw.writeHead(statusCode,headers),this}flushHeaders(){return this.reply.raw.flushHeaders?.(),this}write(chunk){return this.reply.raw.write(chunk)}end(data){return this.reply.raw.end(data),this}once(event,listener){return this.reply.raw.once(event,listener),this}get headersSent(){return this.reply.sent||this.reply.raw.headersSent}};function replyDriver(reply){return new FastifyReplyDriver(reply)}function routeHandler(entry){let validator=entry.meta.validation?validate(entry.meta.validation):void 0;return async(request,reply)=>{let raw=request.raw;if(raw.body=request.body,raw.params=request.params,raw.query=request.query,entry.meta.upload&&entry.meta.upload.mode!==`none`){if(typeof request.parts!=`function`)throw Error(`@forinda/kickjs: @FileUpload on the Fastify runtime requires '@fastify/multipart'.
12
12
  Install it as a peer dependency: pnpm add @fastify/multipart.`);let rawParts=[],fields={};for await(let part of request.parts())part.type===`file`&&part.toBuffer?rawParts.push({fieldname:part.fieldname,filename:part.filename??``,mimetype:part.mimetype??`application/octet-stream`,buffer:await part.toBuffer()}):fields[part.fieldname]=part.value;let{file,files}=applyUploadConfig(rawParts,entry.meta.upload);raw.file=file,raw.files=files,raw.body={...raw.body,...fields}}let headerId=raw.headers[`x-request-id`],requestId=(Array.isArray(headerId)?headerId[0]:headerId)||raw.requestId,store=createRequestStore(requestId);raw.requestId=store.requestId,reply.raw.once(`close`,()=>disposeRequestStore(store)),await requestStore.run(store,async()=>{publishMatchedRoute(raw,entry);let ctx=new RequestContext(raw,reply,NOOP_NEXT,replyDriver(reply));if(entry.earlyContributorRunner&&(await entry.earlyContributorRunner(ctx),reply.sent))return;validator&&await new Promise((resolve,reject)=>{validator(raw,void 0,err=>err?reject(err):resolve())});for(let mw of entry.middlewares){let advanced=!1;if(await new Promise((resolve,reject)=>{Promise.resolve(mw(ctx,err=>{advanced=!0,err?reject(err):resolve()})).catch(reject)}),!advanced||reply.sent)return}if(entry.contributorRunner&&await entry.contributorRunner(ctx),reply.sent)return;let result=await entry.handler(ctx);reply.sent||applyHandlerResult(ctx,result)})}}function fastifyRuntime(){return{name:`fastify`,createApp(options={}){let app=loadPeer(`fastify`)({logger:!1,routerOptions:{ignoreTrailingSlash:!0},trustProxy:typeof options.trustProxy!=`function`&&options.trustProxy});app[QUEUE]=[];let addParser=app.addContentTypeParser?.bind(app);return addParser&&(addParser(/^application\/[\w.+-]+\+json$/,{parseAs:`string`},(_req,body,done)=>{if(body===``)return done(null,void 0);try{done(null,JSON.parse(body))}catch(err){done(HttpException.badRequest(err instanceof Error?err.message:`Request body could not be parsed`),void 0)}}),addParser(`application/x-www-form-urlencoded`,{parseAs:`string`},(_req,body,done)=>{done(null,Object.fromEntries(new URLSearchParams(body)))}),addParser(/^text\//,{parseAs:`string`},(_req,body,done)=>{done(null,body)}),addParser(`*`,{parseAs:`string`},(req,body,done)=>{if(!body)return done(null,void 0);done(unsupportedMediaTypeError(req.headers?.[`content-type`]),void 0)})),app},nodeHandler(app){let state=app;state[READY]||(state[READY]=(async()=>{if(state[NEEDS_MULTIPART]){let multipart=loadPeer(`@fastify/multipart`);await app.register(multipart,{limits:{fileSize:2**53-1}})}let middie=loadPeer(`@fastify/middie`);await app.register(middie);for(let{mw,opts}of state[QUEUE]??[])opts?.path===void 0?app.use(mw):app.use(opts.path,mw);await app.ready()})());let readyP=state[READY];return(req,res,next)=>{next&&(req[NEXT]=next),readyP.then(()=>app.routing(req,res)).catch(err=>{next&&next(err)})}},mountRoutes(app,table){for(let{mountPath,routes}of table)for(let entry of routes){entry.meta.upload&&(app[NEEDS_MULTIPART]=!0);let url=joinPath(mountPath,entry.path);app.route({method:entry.method,url,handler:routeHandler(entry)})}},useConnect(app,mw,opts){app[QUEUE]?.push({mw,opts})},serveStatic(app,prefix,dir){let serveStatic=loadPeer(`serve-static`);this.useConnect(app,serveStatic(dir),{path:prefix})},setNotFound(app,mw){app.setNotFoundHandler((request,reply)=>{let next=request.raw[NEXT];if(next){reply.hijack(),next();return}mw(request.raw,replyDriver(reply),NOOP_NEXT)})},setErrorHandler(app,mw){app.setErrorHandler((err,request,reply)=>{mw(err,request.raw,replyDriver(reply),NOOP_NEXT)})},capabilities:{render:!1,uploads:!0,connectMiddleware:!0,nativeBodyParsing:!0}}}function joinPath(mountPath,path){let a=mountPath.endsWith(`/`)?mountPath.slice(0,-1):mountPath;return path===`/`||path===``?a===``?`/`:a:`${a}${path.startsWith(`/`)?path:`/${path}`}`}export{fastifyRuntime};
13
13
  //# sourceMappingURL=fastify.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"h3-web.d.mts","names":[],"sources":["../../../src/http/runtimes/h3-web.ts"],"mappings":";;;;UA0CU;EACR,GAAG,gBAAgB,cAAc,UAAU,OAAO;EAClD,IAAI,cAAc,UAAU,OAAO;EACnC,OAAO;EACP,MAAM,SAAS,UAAU,QAAQ;;UAEzB;EACR,KAAK;IAAY;MAAY;QAAS,KAAK;QAAiB,KAAK;;;;EACjE,KAAK;EACL;IAAW,SAAS;;;iBASL;;;;;;;;EAQf;;;;;;wBAsEc,aAAa,UAAS,sBAA2B,YAAY;;;;;iBAiH5D;EACf,SAAS;EACT,UAAU;EACV"}
1
+ {"version":3,"file":"h3-web.d.mts","names":[],"sources":["../../../src/http/runtimes/h3-web.ts"],"mappings":";;;;UA0CU;EACR,GAAG,gBAAgB,cAAc,UAAU,OAAO;EAClD,IAAI,cAAc,UAAU,OAAO;EACnC,OAAO;EACP,MAAM,SAAS,UAAU,QAAQ;;UAEzB;EACR,KAAK;IAAY;MAAY;QAAS,KAAK;QAAiB,KAAK;;;;EACjE,KAAK;EACL;IAAW,SAAS;;;iBASL;;;;;;;;EAQf;;;;;;wBA4Rc,aAAa,UAAS,sBAA2B,YAAY;;;;;iBAiH5D;EACf,SAAS;EACT,UAAU;EACV"}
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @forinda/kickjs v8.4.0
2
+ * @forinda/kickjs v8.5.0
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,describeError}from"../../core/logger.mjs";import{n as WebRequestShim,r as WebResponseDriver,t as compileWebRoute}from"../../handler-8OeK5Hkh.mjs";import{createRequire}from"node:module";const log=createLogger(`H3WebRuntime`),peerRequire=createRequire(import.meta.url),NOTFOUND_MW=Symbol(`kickjs.h3web.notFoundMw`),ERROR_MW=Symbol(`kickjs.h3web.errorMw`),ASSEMBLED=Symbol(`kickjs.h3web.assembled`),NOOP_NEXT=()=>{};function loadH3v2(injected){let m=injected??peerRequire(`h3`),resolved=m&&m.__esModule&&m.default?{...m.default,...m}:m;if(typeof resolved.H3!=`function`)throw Error("@forinda/kickjs: h3WebRuntime() requires h3 v2 (the web-standards line, npm dist-tag 'latest'), but the installed h3 has no H3 class — that is the v1 line. Either `pnpm add h3@latest` for this runtime, or keep h3 v1 and use h3Runtime() from '@forinda/kickjs/h3'.");return resolved}async function runConnectTerminal(mw,event,err){let req=new WebRequestShim(event.req,event.url),driver=new WebResponseDriver(event.req.signal);return mw&&(err===void 0?mw(req,driver,NOOP_NEXT):mw(err,req,driver,NOOP_NEXT)),driver.settled||(err===void 0?driver.status(404).json({error:`Not Found`}):(log.error(err,`h3-web: error handler did not settle the response — ${describeError(err)}`),driver.status(500).json({error:`Internal Server Error`,...typeof process<`u`&&process.env?.NODE_ENV===`production`?{}:{message:describeError(err)}}))),driver.ready}function h3WebRuntime(options={}){let{H3,toNodeHandler,fromNodeHandler}=loadH3v2(options.h3);return{name:`h3-web`,createApp(_options={}){let holder={},app=new H3({onError:(error,event)=>{let mw=holder.app?.[ERROR_MW];return runConnectTerminal(mw,event,error)}});return holder.app=app,app},nodeHandler(app){let state=app;state[ASSEMBLED]||(state[ASSEMBLED]=!0,app.all(`/**`,event=>{let mw=state[NOTFOUND_MW];return runConnectTerminal(mw,event)}));let listener=toNodeHandler(app);return(req,res,next)=>{try{let result=listener(req,res);result&&typeof result.then==`function`&&result.catch(err=>next?.(err))}catch(err){next?.(err)}}},mountRoutes(app,table){for(let{mountPath,routes}of table)for(let entry of routes){let url=joinPath(mountPath,entry.path),run=compileWebRoute(entry,{onError:async(err,req,driver)=>{let mw=app[ERROR_MW];mw&&mw(err,req,driver,NOOP_NEXT)}});app.on(entry.method,url,event=>run({request:event.req,url:event.url,params:event.context.params??{}}))}},useConnect(app,mw,opts){let handler=fromNodeHandler(mw);opts?.path===void 0?app.use(handler):app.use(joinPath(String(opts.path),`/**`),handler)},serveStatic(app,prefix,dir){let serveStatic=peerRequire(`serve-static`);this.useConnect(app,serveStatic(dir),{path:prefix})},setNotFound(app,mw){app[NOTFOUND_MW]=mw},setErrorHandler(app,mw){app[ERROR_MW]=mw},capabilities:{render:!1,uploads:!0,connectMiddleware:!0,nativeBodyParsing:!0}}}function joinPath(mountPath,path){let a=mountPath.endsWith(`/`)?mountPath.slice(0,-1):mountPath;return path===`/`||path===``?a===``?`/`:a:`${a}${path.startsWith(`/`)?path:`/${path}`}`}export{h3WebRuntime};
11
+ import{createLogger,describeError}from"../../core/logger.mjs";import{n as WebRequestShim,r as WebResponseDriver,t as compileWebRoute}from"../../handler-B4MQmJR5.mjs";import{createRequire}from"node:module";const log=createLogger(`H3WebRuntime`),peerRequire=createRequire(import.meta.url),NOTFOUND_MW=Symbol(`kickjs.h3web.notFoundMw`),ERROR_MW=Symbol(`kickjs.h3web.errorMw`),ASSEMBLED=Symbol(`kickjs.h3web.assembled`),NOOP_NEXT=()=>{};function loadH3v2(injected){let m=injected??peerRequire(`h3`),resolved=m&&m.__esModule&&m.default?{...m.default,...m}:m;if(typeof resolved.H3!=`function`)throw Error("@forinda/kickjs: h3WebRuntime() requires h3 v2 (the web-standards line, npm dist-tag 'latest'), but the installed h3 has no H3 class — that is the v1 line. Either `pnpm add h3@latest` for this runtime, or keep h3 v1 and use h3Runtime() from '@forinda/kickjs/h3'.");return resolved}async function runConnectTerminal(mw,event,err){let req=new WebRequestShim(event.req,event.url),driver=new WebResponseDriver(event.req.signal);return mw&&(err===void 0?mw(req,driver,NOOP_NEXT):mw(err,req,driver,NOOP_NEXT)),driver.settled||(err===void 0?driver.status(404).json({error:`Not Found`}):(log.error(err,`h3-web: error handler did not settle the response — ${describeError(err)}`),driver.status(500).json({error:`Internal Server Error`,...typeof process<`u`&&process.env?.NODE_ENV===`production`?{}:{message:describeError(err)}}))),driver.ready}const FETCH_CONNECT=new WeakMap;function fetchConnectState(event){let state=FETCH_CONNECT.get(event);return state||(state={req:new WebRequestShim(event.req,event.url),headers:new Headers},FETCH_CONNECT.set(event,state)),state}function withConnectHeaders(event,response){let state=FETCH_CONNECT.get(event);if(!state)return response;let missing=[...state.headers].filter(([name])=>name===`set-cookie`||!response.headers.has(name));if(state.headers=new Headers,missing.length===0)return response;try{for(let[name,value]of missing)response.headers.append(name,value);return response}catch{let headers=new Headers(response.headers);for(let[name,value]of missing)headers.append(name,value);return new Response(response.body,{status:response.status,statusText:response.statusText,headers})}}var FetchConnectResponse=class extends WebResponseDriver{prepared;code=200;listeners=[];constructor(prepared,signal){super(signal),this.prepared=prepared}get statusCode(){return this.code}set statusCode(code){this.status(code)}status(code){return this.code=code,super.status(code)}writeHead(code,headers){return this.code=code,super.writeHead(code,headers)}setHeader(name,value){if(Array.isArray(value)){this.prepared.delete(name);for(let v of value)this.prepared.append(name,String(v))}else this.prepared.set(name,String(value));return this}getHeader(name){return this.prepared.get(name)??void 0}hasHeader(name){return this.prepared.has(name)}removeHeader(name){this.prepared.delete(name)}once(event,listener){return this.listeners.push([event,listener]),this}on(event,listener){return this.once(event,listener)}removeListener(event,listener){return this.listeners=this.listeners.filter(([e,l])=>e!==event||l!==listener),this}off(event,listener){return this.removeListener(event,listener)}done(){for(let event of[`finish`,`close`]){for(let[e,listener]of this.listeners)e===event&&listener();this.listeners=this.listeners.filter(([e])=>e!==event)}}};function runConnectOnFetch(mw,event,next){let state=fetchConnectState(event),res=new FetchConnectResponse(state.headers,event.req.signal);return new Promise((resolve,reject)=>{let respond=response=>{res.done(),resolve(withConnectHeaders(event,response))},fail=err=>{res.done(),reject(err)};res.ready.then(respond);let connectNext=err=>{if(err)return fail(err);if(res.settled)return;let id=state.req.requestId;if(id&&event.req.headers.get(`x-request-id`)!==id)try{event.req.headers.set(`x-request-id`,id)}catch{}let downstream;try{downstream=next()}catch(e){return fail(e)}Promise.resolve(downstream).then(value=>{if(value instanceof Response)return respond(value);res.done(),resolve(value)},fail)};try{mw(state.req,res,connectNext)}catch(err){fail(err)}})}function assembleCatchAll(app){let state=app;state[ASSEMBLED]||(state[ASSEMBLED]=!0,app.all(`/**`,event=>{let mw=state[NOTFOUND_MW];return runConnectTerminal(mw,event)}))}function h3WebRuntime(options={}){let{H3,toNodeHandler,fromNodeHandler}=loadH3v2(options.h3);return{name:`h3-web`,createApp(_options={}){let holder={},app=new H3({onError:(error,event)=>{let mw=holder.app?.[ERROR_MW];return runConnectTerminal(mw,event,error).then(response=>withConnectHeaders(event,response))}});return holder.app=app,app},nodeHandler(app){assembleCatchAll(app);let listener=toNodeHandler(app);return(req,res,next)=>{try{let result=listener(req,res);result&&typeof result.then==`function`&&result.catch(err=>next?.(err))}catch(err){next?.(err)}}},mountRoutes(app,table){for(let{mountPath,routes}of table)for(let entry of routes){let url=joinPath(mountPath,entry.path),run=compileWebRoute(entry,{onError:async(err,req,driver)=>{let mw=app[ERROR_MW];mw&&mw(err,req,driver,NOOP_NEXT)}});app.on(entry.method,url,event=>run({request:event.req,url:event.url,params:event.context.params??{}}))}},useConnect(app,mw,opts){let viaNode=fromNodeHandler(mw),handler=(event,next)=>event.req.runtime?.node?.res?viaNode(event):runConnectOnFetch(mw,event,next);opts?.path===void 0?app.use(handler):app.use(joinPath(String(opts.path),`/**`),handler)},serveStatic(app,prefix,dir){let serveStatic=peerRequire(`serve-static`);this.useConnect(app,serveStatic(dir),{path:prefix})},setNotFound(app,mw){app[NOTFOUND_MW]=mw,assembleCatchAll(app)},setErrorHandler(app,mw){app[ERROR_MW]=mw},capabilities:{render:!1,uploads:!0,connectMiddleware:!0,nativeBodyParsing:!0}}}function joinPath(mountPath,path){let a=mountPath.endsWith(`/`)?mountPath.slice(0,-1):mountPath;return path===`/`||path===``?a===``?`/`:a:`${a}${path.startsWith(`/`)?path:`/${path}`}`}export{h3WebRuntime};
12
12
  //# sourceMappingURL=h3-web.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"h3-web.mjs","names":[],"sources":["../../../src/http/runtimes/h3-web.ts"],"sourcesContent":["// The h3 v2 (web-standards) runtime — `@forinda/kickjs/h3-web`.\n//\n// ADDITIVE runtime: the h3 v1 runtime (`./h3.ts`, `@forinda/kickjs/h3`)\n// stays untouched so existing adopters keep working (locked decision,\n// web-standards-edge-design.md §3.1). This runtime targets h3 >= 2 — the\n// web-standard rebase where `event.req` is a WHATWG Request, handlers\n// return values/Responses, and `app.fetch(request)` is the universal entry.\n//\n// The request pipeline runs through the shared web driver pair\n// (`../web/driver`, `../web/handler`) — the same code path the\n// `@forinda/kickjs/web` edge entry uses, so node bootstrap and edge deploys\n// exercise identical request semantics.\n//\n// Known limitation vs the v1 runtime: no Vite dev-server fall-through —\n// unmatched requests are answered by the kick notFound handler (h3 v2 owns\n// the full request; there is no node `next()` bail-out mid-engine). Use the\n// v1 h3 runtime or Express for Vite-integrated dev setups.\n\nimport type { IncomingMessage, ServerResponse } from 'node:http'\nimport { createRequire } from 'node:module'\n\nimport type {\n ConnectMiddleware,\n HttpRuntime,\n RouteTable,\n RuntimeAppOptions,\n UseConnectOptions,\n} from '../runtime'\nimport { compileWebRoute, type WebRouteHooks } from '../web/handler'\nimport { WebRequestShim, WebResponseDriver } from '../web/driver'\nimport { createLogger, describeError } from '../../core/logger'\n\nconst log = createLogger('H3WebRuntime')\n\nconst peerRequire = createRequire(import.meta.url)\n\nconst NOTFOUND_MW = Symbol('kickjs.h3web.notFoundMw')\nconst ERROR_MW = Symbol('kickjs.h3web.errorMw')\nconst ASSEMBLED = Symbol('kickjs.h3web.assembled')\nconst NOOP_NEXT = (): void => {}\n\n// Minimal structural surface of h3 v2 we depend on.\ninterface H3AppLike {\n on(method: string, path: string, handler: (event: H3EventLike) => unknown): unknown\n all(path: string, handler: (event: H3EventLike) => unknown): unknown\n use(...args: unknown[]): unknown\n fetch(request: Request): Promise<Response>\n}\ninterface H3EventLike {\n req: Request & { runtime?: { node?: { req: IncomingMessage; res: ServerResponse } } }\n url: URL\n context: { params?: Record<string, string> }\n}\n\ninterface H3v2Module {\n H3: new (config?: unknown) => H3AppLike\n toNodeHandler: (app: H3AppLike) => (req: IncomingMessage, res: ServerResponse) => void\n fromNodeHandler: (mw: unknown) => unknown\n}\n\nexport interface H3WebRuntimeOptions {\n /**\n * Pre-imported h3 v2 module. Two audiences:\n * - Edge/worker bundlers with no `createRequire` at runtime:\n * `h3WebRuntime({ h3: await import('h3') })`\n * - Tests running both h3 majors side by side via an npm alias.\n * Omitted → the peer is loaded via `createRequire` (node bootstrap path).\n */\n h3?: unknown\n}\n\n/** Resolve h3 (injected or peer-required) and fail fast unless it is v2. */\nfunction loadH3v2(injected?: unknown): H3v2Module {\n const mod = injected ?? peerRequire('h3')\n const m = mod as { __esModule?: boolean; default?: Record<string, unknown> } & Record<\n string,\n unknown\n >\n const resolved = (m && m.__esModule && m.default\n ? { ...m.default, ...m }\n : m) as unknown as H3v2Module\n if (typeof resolved.H3 !== 'function') {\n throw new Error(\n \"@forinda/kickjs: h3WebRuntime() requires h3 v2 (the web-standards line, npm dist-tag 'latest'), \" +\n 'but the installed h3 has no H3 class — that is the v1 line. ' +\n \"Either `pnpm add h3@latest` for this runtime, or keep h3 v1 and use h3Runtime() from '@forinda/kickjs/h3'.\",\n )\n }\n return resolved\n}\n\n/**\n * Bridge a connect-style terminal middleware (kick's notFound / error\n * handlers) onto the web driver pair, returning the produced Response.\n */\nasync function runConnectTerminal(\n mw: ConnectMiddleware | undefined,\n event: H3EventLike,\n err?: unknown,\n): Promise<Response> {\n const req = new WebRequestShim(event.req, event.url)\n const driver = new WebResponseDriver(event.req.signal)\n if (mw) {\n if (err !== undefined) {\n ;(mw as (e: unknown, rq: unknown, rs: unknown, n: () => void) => void)(\n err,\n req,\n driver,\n NOOP_NEXT,\n )\n } else {\n ;(mw as (rq: unknown, rs: unknown, n: () => void) => void)(req, driver, NOOP_NEXT)\n }\n }\n if (!driver.settled) {\n if (err !== undefined) {\n // The configured error handler ran but didn't settle the response\n // (or there wasn't one). Emitting a bare 500 with no log entry\n // makes this failure invisible on both sides — log it here, since\n // by definition nothing downstream will.\n log.error(err, `h3-web: error handler did not settle the response — ${describeError(err)}`)\n driver.status(500).json({\n error: 'Internal Server Error',\n ...(typeof process !== 'undefined' && process.env?.NODE_ENV === 'production'\n ? {}\n : { message: describeError(err) }),\n })\n } else {\n driver.status(404).json({ error: 'Not Found' })\n }\n }\n return driver.ready\n}\n\n/**\n * The h3 v2 HTTP runtime. Pass to `bootstrap({ runtime: h3WebRuntime() })`.\n * Requires the h3 v2 peer; fails fast with guidance when v1 is installed.\n */\nexport function h3WebRuntime(options: H3WebRuntimeOptions = {}): HttpRuntime<H3AppLike> {\n const { H3, toNodeHandler, fromNodeHandler } = loadH3v2(options.h3)\n\n return {\n name: 'h3-web',\n\n createApp(_options: RuntimeAppOptions = {}): H3AppLike {\n const holder: { app?: H3AppLike } = {}\n const app = new H3({\n // Engine-level errors (middleware throws outside the kick pipeline)\n // dispatch to the kick error handler once setErrorHandler stashes it.\n onError: (error: unknown, event: H3EventLike) => {\n const mw = (holder.app as unknown as Record<symbol, ConnectMiddleware | undefined>)?.[\n ERROR_MW\n ]\n return runConnectTerminal(mw, event, error)\n },\n })\n holder.app = app\n return app\n },\n\n nodeHandler(app) {\n const state = app as unknown as Record<symbol, unknown>\n if (!state[ASSEMBLED]) {\n state[ASSEMBLED] = true\n // Terminal catch-all AFTER all mounted routes: kick's own notFound\n // handler answers unmatched paths (h3 v2's default 404 never fires).\n app.all('/**', (event: H3EventLike) => {\n const mw = state[NOTFOUND_MW] as ConnectMiddleware | undefined\n return runConnectTerminal(mw, event)\n })\n }\n const listener = toNodeHandler(app)\n return (req: IncomingMessage, res: ServerResponse, next?: (err?: unknown) => void) => {\n try {\n const result = listener(req, res) as unknown\n if (result && typeof (result as Promise<unknown>).then === 'function') {\n void (result as Promise<unknown>).catch((err) => next?.(err))\n }\n } catch (err) {\n next?.(err)\n }\n }\n },\n\n mountRoutes(app, table: RouteTable) {\n for (const { mountPath, routes } of table) {\n for (const entry of routes) {\n const url = joinPath(mountPath, entry.path)\n const hooks: WebRouteHooks = {\n onError: async (err, req, driver) => {\n const mw = (app as unknown as Record<symbol, ConnectMiddleware | undefined>)[ERROR_MW]\n if (!mw) return\n ;(mw as (e: unknown, rq: unknown, rs: unknown, n: () => void) => void)(\n err,\n req,\n driver,\n NOOP_NEXT,\n )\n },\n }\n const run = compileWebRoute(entry, hooks)\n app.on(entry.method, url, (event: H3EventLike) =>\n run({\n request: event.req,\n url: event.url,\n params: event.context.params ?? {},\n }),\n )\n }\n }\n },\n\n useConnect(app, mw: ConnectMiddleware, opts?: UseConnectOptions) {\n // Node bootstrap path only — h3 v2 bridges node middleware via\n // fromNodeHandler (the edge entry never calls useConnect).\n const handler = fromNodeHandler(mw)\n if (opts?.path !== undefined) {\n // v2 `use` is exact-match; `/**` covers the subtree like v1's prefix.\n app.use(joinPath(String(opts.path), '/**'), handler)\n } else {\n app.use(handler)\n }\n },\n\n serveStatic(app, prefix, dir) {\n // serve-static bridged like any other connect middleware (node only).\n const serveStatic = peerRequire('serve-static')\n this.useConnect(app, serveStatic(dir) as ConnectMiddleware, { path: prefix })\n },\n\n setNotFound(app, mw: ConnectMiddleware) {\n ;(app as unknown as Record<symbol, ConnectMiddleware>)[NOTFOUND_MW] = mw\n },\n\n setErrorHandler(app, mw: ConnectMiddleware) {\n ;(app as unknown as Record<symbol, ConnectMiddleware>)[ERROR_MW] = mw\n },\n\n capabilities: {\n render: false,\n uploads: true,\n connectMiddleware: true,\n nativeBodyParsing: true,\n },\n }\n}\n\n/**\n * h3-web runtime engine types for the `kick/runtime` typegen augmentation —\n * mirrors {@link import('./h3').H3RuntimeTypes} for the v1 runtime.\n */\nexport interface H3WebRuntimeTypes {\n request: Request\n response: Response\n app: unknown\n}\n\n/** Join a mount prefix and a route path into one URL, collapsing slashes. */\nfunction joinPath(mountPath: string, path: string): string {\n const a = mountPath.endsWith('/') ? mountPath.slice(0, -1) : mountPath\n if (path === '/' || path === '') return a === '' ? '/' : a\n const b = path.startsWith('/') ? path : `/${path}`\n return `${a}${b}`\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"h3-web.mjs","names":[],"sources":["../../../src/http/runtimes/h3-web.ts"],"sourcesContent":["// The h3 v2 (web-standards) runtime — `@forinda/kickjs/h3-web`.\n//\n// ADDITIVE runtime: the h3 v1 runtime (`./h3.ts`, `@forinda/kickjs/h3`)\n// stays untouched so existing adopters keep working (locked decision,\n// web-standards-edge-design.md §3.1). This runtime targets h3 >= 2 — the\n// web-standard rebase where `event.req` is a WHATWG Request, handlers\n// return values/Responses, and `app.fetch(request)` is the universal entry.\n//\n// The request pipeline runs through the shared web driver pair\n// (`../web/driver`, `../web/handler`) — the same code path the\n// `@forinda/kickjs/web` edge entry uses, so node bootstrap and edge deploys\n// exercise identical request semantics.\n//\n// Known limitation vs the v1 runtime: no Vite dev-server fall-through —\n// unmatched requests are answered by the kick notFound handler (h3 v2 owns\n// the full request; there is no node `next()` bail-out mid-engine). Use the\n// v1 h3 runtime or Express for Vite-integrated dev setups.\n\nimport type { IncomingMessage, ServerResponse } from 'node:http'\nimport { createRequire } from 'node:module'\n\nimport type {\n ConnectMiddleware,\n HttpRuntime,\n RouteTable,\n RuntimeAppOptions,\n UseConnectOptions,\n} from '../runtime'\nimport { compileWebRoute, type WebRouteHooks } from '../web/handler'\nimport { WebRequestShim, WebResponseDriver } from '../web/driver'\nimport { createLogger, describeError } from '../../core/logger'\n\nconst log = createLogger('H3WebRuntime')\n\nconst peerRequire = createRequire(import.meta.url)\n\nconst NOTFOUND_MW = Symbol('kickjs.h3web.notFoundMw')\nconst ERROR_MW = Symbol('kickjs.h3web.errorMw')\nconst ASSEMBLED = Symbol('kickjs.h3web.assembled')\nconst NOOP_NEXT = (): void => {}\n\n// Minimal structural surface of h3 v2 we depend on.\ninterface H3AppLike {\n on(method: string, path: string, handler: (event: H3EventLike) => unknown): unknown\n all(path: string, handler: (event: H3EventLike) => unknown): unknown\n use(...args: unknown[]): unknown\n fetch(request: Request): Promise<Response>\n}\ninterface H3EventLike {\n req: Request & { runtime?: { node?: { req: IncomingMessage; res: ServerResponse } } }\n url: URL\n context: { params?: Record<string, string> }\n}\n\ninterface H3v2Module {\n H3: new (config?: unknown) => H3AppLike\n toNodeHandler: (app: H3AppLike) => (req: IncomingMessage, res: ServerResponse) => void\n fromNodeHandler: (mw: unknown) => unknown\n}\n\nexport interface H3WebRuntimeOptions {\n /**\n * Pre-imported h3 v2 module. Two audiences:\n * - Edge/worker bundlers with no `createRequire` at runtime:\n * `h3WebRuntime({ h3: await import('h3') })`\n * - Tests running both h3 majors side by side via an npm alias.\n * Omitted → the peer is loaded via `createRequire` (node bootstrap path).\n */\n h3?: unknown\n}\n\n/** Resolve h3 (injected or peer-required) and fail fast unless it is v2. */\nfunction loadH3v2(injected?: unknown): H3v2Module {\n const mod = injected ?? peerRequire('h3')\n const m = mod as { __esModule?: boolean; default?: Record<string, unknown> } & Record<\n string,\n unknown\n >\n const resolved = (m && m.__esModule && m.default\n ? { ...m.default, ...m }\n : m) as unknown as H3v2Module\n if (typeof resolved.H3 !== 'function') {\n throw new Error(\n \"@forinda/kickjs: h3WebRuntime() requires h3 v2 (the web-standards line, npm dist-tag 'latest'), \" +\n 'but the installed h3 has no H3 class — that is the v1 line. ' +\n \"Either `pnpm add h3@latest` for this runtime, or keep h3 v1 and use h3Runtime() from '@forinda/kickjs/h3'.\",\n )\n }\n return resolved\n}\n\n/**\n * Bridge a connect-style terminal middleware (kick's notFound / error\n * handlers) onto the web driver pair, returning the produced Response.\n */\nasync function runConnectTerminal(\n mw: ConnectMiddleware | undefined,\n event: H3EventLike,\n err?: unknown,\n): Promise<Response> {\n const req = new WebRequestShim(event.req, event.url)\n const driver = new WebResponseDriver(event.req.signal)\n if (mw) {\n if (err !== undefined) {\n ;(mw as (e: unknown, rq: unknown, rs: unknown, n: () => void) => void)(\n err,\n req,\n driver,\n NOOP_NEXT,\n )\n } else {\n ;(mw as (rq: unknown, rs: unknown, n: () => void) => void)(req, driver, NOOP_NEXT)\n }\n }\n if (!driver.settled) {\n if (err !== undefined) {\n // The configured error handler ran but didn't settle the response\n // (or there wasn't one). Emitting a bare 500 with no log entry\n // makes this failure invisible on both sides — log it here, since\n // by definition nothing downstream will.\n log.error(err, `h3-web: error handler did not settle the response — ${describeError(err)}`)\n driver.status(500).json({\n error: 'Internal Server Error',\n ...(typeof process !== 'undefined' && process.env?.NODE_ENV === 'production'\n ? {}\n : { message: describeError(err) }),\n })\n } else {\n driver.status(404).json({ error: 'Not Found' })\n }\n }\n return driver.ready\n}\n\n// ── Connect middleware on the fetch path ─────────────────────────────────\n//\n// `app.fetch(request)` (edge, Bun, Deno, a serverless function) carries no\n// node req/res, and h3's `fromNodeHandler` throws without one. Connect\n// middleware there runs against the web driver pair instead: one request shim\n// per event (so `req.requestId` set by one middleware is seen by the next) and\n// one header bag per event that is merged into whatever Response comes back.\n// The merge is ours rather than h3's `event.res.headers` because h3 skips\n// prepared headers on non-2xx responses, and a 404/422/500 must still carry\n// helmet's headers and the request id, exactly as on node.\n\ninterface FetchConnectState {\n req: WebRequestShim\n headers: Headers\n}\n\nconst FETCH_CONNECT = new WeakMap<object, FetchConnectState>()\n\nfunction fetchConnectState(event: H3EventLike): FetchConnectState {\n let state = FETCH_CONNECT.get(event)\n if (!state) {\n state = { req: new WebRequestShim(event.req, event.url), headers: new Headers() }\n FETCH_CONNECT.set(event, state)\n }\n return state\n}\n\n/**\n * Add the headers connect middleware set to `response`. The response's own\n * headers win — a later `setHeader` overrides an earlier one on node too.\n * Consumed once, so every middleware layer can call it on the way out.\n */\nfunction withConnectHeaders(event: H3EventLike, response: Response): Response {\n const state = FETCH_CONNECT.get(event)\n if (!state) return response\n const missing = [...state.headers].filter(\n ([name]) => name === 'set-cookie' || !response.headers.has(name),\n )\n state.headers = new Headers()\n if (missing.length === 0) return response\n try {\n for (const [name, value] of missing) response.headers.append(name, value)\n return response\n } catch {\n // Immutable headers (a Response from fetch) — rebuild around the body.\n const headers = new Headers(response.headers)\n for (const [name, value] of missing) headers.append(name, value)\n return new Response(response.body, {\n status: response.status,\n statusText: response.statusText,\n headers,\n })\n }\n}\n\n/**\n * The node `res` surface connect middleware uses, over the web driver:\n * headers go to the per-event bag, `statusCode`, and `finish`/`close`\n * emitted once the response exists.\n */\nclass FetchConnectResponse extends WebResponseDriver {\n private code = 200\n private listeners: Array<[string, (...args: unknown[]) => void]> = []\n\n constructor(\n private readonly prepared: Headers,\n signal: AbortSignal,\n ) {\n super(signal)\n }\n\n get statusCode(): number {\n return this.code\n }\n\n set statusCode(code: number) {\n this.status(code)\n }\n\n override status(code: number): this {\n this.code = code\n return super.status(code)\n }\n\n override writeHead(code: number, headers?: Record<string, string | number | string[]>): this {\n this.code = code\n return super.writeHead(code, headers)\n }\n\n override setHeader(name: string, value: unknown): this {\n if (Array.isArray(value)) {\n this.prepared.delete(name)\n for (const v of value) this.prepared.append(name, String(v))\n } else {\n this.prepared.set(name, String(value))\n }\n return this\n }\n\n getHeader(name: string): string | undefined {\n return this.prepared.get(name) ?? undefined\n }\n\n hasHeader(name: string): boolean {\n return this.prepared.has(name)\n }\n\n removeHeader(name: string): void {\n this.prepared.delete(name)\n }\n\n override once(event: string, listener: (...args: unknown[]) => void): this {\n this.listeners.push([event, listener])\n return this\n }\n\n on(event: string, listener: (...args: unknown[]) => void): this {\n return this.once(event, listener)\n }\n\n removeListener(event: string, listener: (...args: unknown[]) => void): this {\n this.listeners = this.listeners.filter(([e, l]) => e !== event || l !== listener)\n return this\n }\n\n off(event: string, listener: (...args: unknown[]) => void): this {\n return this.removeListener(event, listener)\n }\n\n /** The response exists (or the request failed): fire `finish` then `close`. */\n done(): void {\n for (const event of ['finish', 'close']) {\n for (const [e, listener] of this.listeners) if (e === event) listener()\n this.listeners = this.listeners.filter(([e]) => e !== event)\n }\n }\n}\n\nfunction runConnectOnFetch(\n mw: ConnectMiddleware,\n event: H3EventLike,\n next: () => unknown,\n): Promise<unknown> {\n const state = fetchConnectState(event)\n const res = new FetchConnectResponse(state.headers, event.req.signal)\n\n return new Promise((resolve, reject) => {\n const respond = (response: Response): void => {\n res.done()\n resolve(withConnectHeaders(event, response))\n }\n const fail = (err: unknown): void => {\n res.done()\n reject(err)\n }\n\n // The middleware answered itself (`res.end`, `res.json`, `writeHead`).\n void res.ready.then(respond)\n\n const connectNext = (err?: unknown): void => {\n if (err) return fail(err)\n if (res.settled) return\n // The route builds its request store from the inbound header; hand it the\n // id requestScope/requestId settled on so body, logs and header agree.\n const id = state.req.requestId\n if (id && event.req.headers.get('x-request-id') !== id) {\n try {\n event.req.headers.set('x-request-id', id)\n } catch {\n // Immutable request headers on some runtimes — the route mints its own id.\n }\n }\n let downstream: unknown\n try {\n // Synchronous, so downstream work starts inside any AsyncLocalStorage\n // scope this middleware opened (requestScopeMiddleware).\n downstream = next()\n } catch (e) {\n return fail(e)\n }\n Promise.resolve(downstream).then((value) => {\n if (value instanceof Response) return respond(value)\n res.done()\n resolve(value)\n }, fail)\n }\n\n try {\n ;(mw as (rq: unknown, rs: unknown, n: (err?: unknown) => void) => void)(\n state.req,\n res,\n connectNext,\n )\n } catch (err) {\n fail(err)\n }\n })\n}\n\n/**\n * Terminal catch-all AFTER all mounted routes: kick's own notFound handler\n * answers unmatched paths (h3 v2's default 404 never fires). rou3 ranks `/**`\n * below every concrete route, so registration time does not matter.\n */\nfunction assembleCatchAll(app: H3AppLike): void {\n const state = app as unknown as Record<symbol, unknown>\n if (state[ASSEMBLED]) return\n state[ASSEMBLED] = true\n app.all('/**', (event: H3EventLike) => {\n const mw = state[NOTFOUND_MW] as ConnectMiddleware | undefined\n return runConnectTerminal(mw, event)\n })\n}\n\n/**\n * The h3 v2 HTTP runtime. Pass to `bootstrap({ runtime: h3WebRuntime() })`.\n * Requires the h3 v2 peer; fails fast with guidance when v1 is installed.\n */\nexport function h3WebRuntime(options: H3WebRuntimeOptions = {}): HttpRuntime<H3AppLike> {\n const { H3, toNodeHandler, fromNodeHandler } = loadH3v2(options.h3)\n\n return {\n name: 'h3-web',\n\n createApp(_options: RuntimeAppOptions = {}): H3AppLike {\n const holder: { app?: H3AppLike } = {}\n const app = new H3({\n // Engine-level errors (middleware throws outside the kick pipeline)\n // dispatch to the kick error handler once setErrorHandler stashes it.\n onError: (error: unknown, event: H3EventLike) => {\n const mw = (holder.app as unknown as Record<symbol, ConnectMiddleware | undefined>)?.[\n ERROR_MW\n ]\n return runConnectTerminal(mw, event, error).then((response) =>\n withConnectHeaders(event, response),\n )\n },\n })\n holder.app = app\n return app\n },\n\n nodeHandler(app) {\n assembleCatchAll(app)\n const listener = toNodeHandler(app)\n return (req: IncomingMessage, res: ServerResponse, next?: (err?: unknown) => void) => {\n try {\n const result = listener(req, res) as unknown\n if (result && typeof (result as Promise<unknown>).then === 'function') {\n void (result as Promise<unknown>).catch((err) => next?.(err))\n }\n } catch (err) {\n next?.(err)\n }\n }\n },\n\n mountRoutes(app, table: RouteTable) {\n for (const { mountPath, routes } of table) {\n for (const entry of routes) {\n const url = joinPath(mountPath, entry.path)\n const hooks: WebRouteHooks = {\n onError: async (err, req, driver) => {\n const mw = (app as unknown as Record<symbol, ConnectMiddleware | undefined>)[ERROR_MW]\n if (!mw) return\n ;(mw as (e: unknown, rq: unknown, rs: unknown, n: () => void) => void)(\n err,\n req,\n driver,\n NOOP_NEXT,\n )\n },\n }\n const run = compileWebRoute(entry, hooks)\n app.on(entry.method, url, (event: H3EventLike) =>\n run({\n request: event.req,\n url: event.url,\n params: event.context.params ?? {},\n }),\n )\n }\n }\n },\n\n useConnect(app, mw: ConnectMiddleware, opts?: UseConnectOptions) {\n // Behind a node server (toNodeHandler) the event carries node req/res and\n // h3's own bridge runs the middleware unchanged. Called through\n // `app.fetch(request)` there is none and fromNodeHandler would throw, so\n // the middleware runs against the web driver pair instead.\n const viaNode = fromNodeHandler(mw) as (event: H3EventLike) => unknown\n const handler = (event: H3EventLike, next: () => unknown) =>\n event.req.runtime?.node?.res ? viaNode(event) : runConnectOnFetch(mw, event, next)\n if (opts?.path !== undefined) {\n // v2 `use` is exact-match; `/**` covers the subtree like v1's prefix.\n app.use(joinPath(String(opts.path), '/**'), handler)\n } else {\n app.use(handler)\n }\n },\n\n serveStatic(app, prefix, dir) {\n // serve-static bridged like any other connect middleware (node only).\n const serveStatic = peerRequire('serve-static')\n this.useConnect(app, serveStatic(dir) as ConnectMiddleware, { path: prefix })\n },\n\n setNotFound(app, mw: ConnectMiddleware) {\n ;(app as unknown as Record<symbol, ConnectMiddleware>)[NOTFOUND_MW] = mw\n // Here as well as in nodeHandler: an app only ever called through\n // `app.fetch` never reaches nodeHandler, and would answer h3's own 404.\n assembleCatchAll(app)\n },\n\n setErrorHandler(app, mw: ConnectMiddleware) {\n ;(app as unknown as Record<symbol, ConnectMiddleware>)[ERROR_MW] = mw\n },\n\n capabilities: {\n render: false,\n uploads: true,\n connectMiddleware: true,\n nativeBodyParsing: true,\n },\n }\n}\n\n/**\n * h3-web runtime engine types for the `kick/runtime` typegen augmentation —\n * mirrors {@link import('./h3').H3RuntimeTypes} for the v1 runtime.\n */\nexport interface H3WebRuntimeTypes {\n request: Request\n response: Response\n app: unknown\n}\n\n/** Join a mount prefix and a route path into one URL, collapsing slashes. */\nfunction joinPath(mountPath: string, path: string): string {\n const a = mountPath.endsWith('/') ? mountPath.slice(0, -1) : mountPath\n if (path === '/' || path === '') return a === '' ? '/' : a\n const b = path.startsWith('/') ? path : `/${path}`\n return `${a}${b}`\n}\n"],"mappings":"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"}
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @forinda/kickjs v8.4.0
2
+ * @forinda/kickjs v8.5.0
3
3
  *
4
4
  * Copyright (c) Felix Orinda
5
5
  *
@@ -8,5 +8,5 @@
8
8
  *
9
9
  * @license MIT
10
10
  */
11
- import{HttpException}from"../../core/errors.mjs";import{a as createRequestStore,f as unsupportedMediaTypeError,n as applyHandlerResult,o as disposeRequestStore,t as publishMatchedRoute,u as classifyMediaType}from"../../runtime-B2oXJDwr.mjs";import{i as requestStore,t as RequestContext}from"../../context-Xd8C4fIo.mjs";import{validate}from"../middleware/validate.mjs";import{t as applyUploadConfig}from"../../upload-config-C23IAKGT.mjs";import"../middleware/upload.mjs";import{createRequire}from"node:module";const peerRequire=createRequire(import.meta.url),h3=()=>peerRequire(`h3`),NEXT=Symbol(`kickjs.h3.next`),ERROR_MW=Symbol(`kickjs.h3.errorMw`),ROUTER=Symbol(`kickjs.h3.router`),NOTFOUND_MW=Symbol(`kickjs.h3.notFoundMw`),ASSEMBLED=Symbol(`kickjs.h3.assembled`),NOOP_NEXT=()=>{},BODY_METHODS=new Set([`POST`,`PUT`,`PATCH`,`DELETE`]);var NodeResDriver=class{res;constructor(res){this.res=res}status(code){return this.res.statusCode=code,this}json(data){return!this.res.headersSent&&!this.res.getHeader(`content-type`)&&this.res.setHeader(`content-type`,`application/json; charset=utf-8`),this.res.end(JSON.stringify(data)),this}send(data){return this.res.end(data),this}type(contentType){return this.res.setHeader(`content-type`,contentType),this}setHeader(name,value){return this.res.setHeader(name,value),this}render(){throw Error(`ctx.render() is not supported on the h3 runtime (no view engine).`)}writeHead(statusCode,headers){return this.res.writeHead(statusCode,headers),this}flushHeaders(){return this.res.flushHeaders(),this}write(chunk){return this.res.write(chunk)}end(data){return this.res.end(data),this}once(event,listener){return this.res.once(event,listener),this}get headersSent(){return this.res.headersSent}};function resDriver(res){return new NodeResDriver(res)}const TRUST_PROXY=Symbol(`kickjs.h3.trustProxy`);function makeEventHandler(entry,trustProxy){let{getRouterParams,getQuery,readRawBody,readMultipartFormData}=h3(),upload=entry.meta.upload,validator=entry.meta.validation?validate(entry.meta.validation):void 0;return async event=>{let req=event.node.req,res=event.node.res;if(trustProxy&&!req.ip){let forwarded=req.headers[`x-forwarded-for`],first=(Array.isArray(forwarded)?forwarded[0]:forwarded)?.split(`,`)[0]?.trim();first&&(req.ip=first)}if(req.params=getRouterParams(event)??{},req.query=getQuery(event)??{},upload&&upload.mode!==`none`){let form=await readMultipartFormData(event).catch(()=>void 0),rawParts=[],fields={};for(let part of form??[])part.filename?rawParts.push({fieldname:part.name??``,filename:part.filename,mimetype:part.type??`application/octet-stream`,buffer:part.data}):part.name&&(fields[part.name]=part.data.toString(`utf-8`));let{file,files}=applyUploadConfig(rawParts,upload);req.file=file,req.files=files,req.body=fields}else if(BODY_METHODS.has(req.method??`GET`)){let{"content-length":length,"transfer-encoding":encoding}=req.headers;if(encoding!==void 0||length!==void 0&&length!==`0`){let kind=classifyMediaType(req.headers[`content-type`]);if(kind!==`multipart`){let raw=await readRawBody(event,`utf8`);if(raw){if(kind===`unsupported`)throw unsupportedMediaTypeError(req.headers[`content-type`]);if(kind===`json`)try{req.body=JSON.parse(raw)}catch(err){throw HttpException.badRequest(err instanceof Error?err.message:`Request body could not be parsed`)}else req.body=kind===`urlencoded`?Object.fromEntries(new URLSearchParams(raw)):raw}}}}let headerId=req.headers[`x-request-id`],requestId=(Array.isArray(headerId)?headerId[0]:headerId)||req.requestId,store=createRequestStore(requestId);req.requestId=store.requestId,res.once(`close`,()=>disposeRequestStore(store)),await requestStore.run(store,async()=>{publishMatchedRoute(req,entry);let ctx=new RequestContext(req,res,NOOP_NEXT,resDriver(res));if(entry.earlyContributorRunner&&(await entry.earlyContributorRunner(ctx),res.writableEnded))return;validator&&await new Promise((resolve,reject)=>{validator(req,void 0,err=>err?reject(err):resolve())});for(let mw of entry.middlewares){let advanced=!1;if(await new Promise((resolve,reject)=>{Promise.resolve(mw(ctx,err=>{advanced=!0,err?reject(err):resolve()})).catch(reject)}),!advanced||res.writableEnded)return}if(entry.contributorRunner&&await entry.contributorRunner(ctx),res.writableEnded)return;let result=await entry.handler(ctx);!res.writableEnded&&!res.headersSent&&applyHandlerResult(ctx,result)})}}function unwrapH3Error(error){if(!(error instanceof Error))return error;let{cause}=error;return cause instanceof Error?cause:error}function h3Runtime(){return{name:`h3`,createApp(options={}){let{createApp}=h3(),app=createApp({onError:(error,event)=>{let res=event.node.res;if(res.writableEnded)return;let state=app;if(error?.statusCode===404){let next=event.node.req[NEXT];if(next){next();return}let nf=state[NOTFOUND_MW];if(nf){nf(event.node.req,resDriver(res),NOOP_NEXT);return}}let mw=state[ERROR_MW];mw&&mw(unwrapH3Error(error),event.node.req,resDriver(res),NOOP_NEXT)}});return app[TRUST_PROXY]=options.trustProxy,app},nodeHandler(app){let{toNodeListener}=h3(),state=app;state[ASSEMBLED]||(state[ASSEMBLED]=!0,state[ROUTER]&&app.use(state[ROUTER]));let listener=toNodeListener(app);return(req,res,next)=>{next&&(req[NEXT]=next),Promise.resolve(listener(req,res)).catch(err=>{next&&next(err)})}},mountRoutes(app,table){let{createRouter,eventHandler}=h3(),trustProxy=!!app[TRUST_PROXY],state=app;state[ROUTER]||(state[ROUTER]=createRouter());let router=state[ROUTER];for(let{mountPath,routes}of table)for(let entry of routes){let url=joinPath(mountPath,entry.path);router[entry.method.toLowerCase()](url,eventHandler(makeEventHandler(entry,trustProxy)))}},useConnect(app,mw,opts){let{fromNodeMiddleware}=h3(),handler=fromNodeMiddleware(mw);opts?.path===void 0?app.use(handler):app.use(opts.path,handler)},serveStatic(app,prefix,dir){let serveStatic=peerRequire(`serve-static`);this.useConnect(app,serveStatic(dir),{path:prefix})},setNotFound(app,mw){app[NOTFOUND_MW]=mw},setErrorHandler(app,mw){app[ERROR_MW]=mw},capabilities:{render:!1,uploads:!0,connectMiddleware:!0,nativeBodyParsing:!0}}}function joinPath(mountPath,path){let a=mountPath.endsWith(`/`)?mountPath.slice(0,-1):mountPath;return path===`/`||path===``?a===``?`/`:a:`${a}${path.startsWith(`/`)?path:`/${path}`}`}export{h3Runtime};
11
+ import{HttpException}from"../../core/errors.mjs";import{a as createRequestStore,f as unsupportedMediaTypeError,n as applyHandlerResult,o as disposeRequestStore,t as publishMatchedRoute,u as classifyMediaType}from"../../runtime-B3V_u8FS.mjs";import{i as requestStore,t as RequestContext}from"../../context-B7N5oE7S.mjs";import{validate}from"../middleware/validate.mjs";import{t as applyUploadConfig}from"../../upload-config-C49VFeoh.mjs";import"../middleware/upload.mjs";import{createRequire}from"node:module";const peerRequire=createRequire(import.meta.url),h3=()=>peerRequire(`h3`),NEXT=Symbol(`kickjs.h3.next`),ERROR_MW=Symbol(`kickjs.h3.errorMw`),ROUTER=Symbol(`kickjs.h3.router`),NOTFOUND_MW=Symbol(`kickjs.h3.notFoundMw`),ASSEMBLED=Symbol(`kickjs.h3.assembled`),NOOP_NEXT=()=>{},BODY_METHODS=new Set([`POST`,`PUT`,`PATCH`,`DELETE`]);var NodeResDriver=class{res;constructor(res){this.res=res}status(code){return this.res.statusCode=code,this}json(data){return!this.res.headersSent&&!this.res.getHeader(`content-type`)&&this.res.setHeader(`content-type`,`application/json; charset=utf-8`),this.res.end(JSON.stringify(data)),this}send(data){return this.res.end(data),this}type(contentType){return this.res.setHeader(`content-type`,contentType),this}setHeader(name,value){return this.res.setHeader(name,value),this}render(){throw Error(`ctx.render() is not supported on the h3 runtime (no view engine).`)}writeHead(statusCode,headers){return this.res.writeHead(statusCode,headers),this}flushHeaders(){return this.res.flushHeaders(),this}write(chunk){return this.res.write(chunk)}end(data){return this.res.end(data),this}once(event,listener){return this.res.once(event,listener),this}get headersSent(){return this.res.headersSent}};function resDriver(res){return new NodeResDriver(res)}const TRUST_PROXY=Symbol(`kickjs.h3.trustProxy`);function makeEventHandler(entry,trustProxy){let{getRouterParams,getQuery,readRawBody,readMultipartFormData}=h3(),upload=entry.meta.upload,validator=entry.meta.validation?validate(entry.meta.validation):void 0;return async event=>{let req=event.node.req,res=event.node.res;if(trustProxy&&!req.ip){let forwarded=req.headers[`x-forwarded-for`],first=(Array.isArray(forwarded)?forwarded[0]:forwarded)?.split(`,`)[0]?.trim();first&&(req.ip=first)}if(req.params=getRouterParams(event)??{},req.query=getQuery(event)??{},upload&&upload.mode!==`none`){let form=await readMultipartFormData(event).catch(()=>void 0),rawParts=[],fields={};for(let part of form??[])part.filename?rawParts.push({fieldname:part.name??``,filename:part.filename,mimetype:part.type??`application/octet-stream`,buffer:part.data}):part.name&&(fields[part.name]=part.data.toString(`utf-8`));let{file,files}=applyUploadConfig(rawParts,upload);req.file=file,req.files=files,req.body=fields}else if(BODY_METHODS.has(req.method??`GET`)){let{"content-length":length,"transfer-encoding":encoding}=req.headers;if(encoding!==void 0||length!==void 0&&length!==`0`){let kind=classifyMediaType(req.headers[`content-type`]);if(kind!==`multipart`){let raw=await readRawBody(event,`utf8`);if(raw){if(kind===`unsupported`)throw unsupportedMediaTypeError(req.headers[`content-type`]);if(kind===`json`)try{req.body=JSON.parse(raw)}catch(err){throw HttpException.badRequest(err instanceof Error?err.message:`Request body could not be parsed`)}else req.body=kind===`urlencoded`?Object.fromEntries(new URLSearchParams(raw)):raw}}}}let headerId=req.headers[`x-request-id`],requestId=(Array.isArray(headerId)?headerId[0]:headerId)||req.requestId,store=createRequestStore(requestId);req.requestId=store.requestId,res.once(`close`,()=>disposeRequestStore(store)),await requestStore.run(store,async()=>{publishMatchedRoute(req,entry);let ctx=new RequestContext(req,res,NOOP_NEXT,resDriver(res));if(entry.earlyContributorRunner&&(await entry.earlyContributorRunner(ctx),res.writableEnded))return;validator&&await new Promise((resolve,reject)=>{validator(req,void 0,err=>err?reject(err):resolve())});for(let mw of entry.middlewares){let advanced=!1;if(await new Promise((resolve,reject)=>{Promise.resolve(mw(ctx,err=>{advanced=!0,err?reject(err):resolve()})).catch(reject)}),!advanced||res.writableEnded)return}if(entry.contributorRunner&&await entry.contributorRunner(ctx),res.writableEnded)return;let result=await entry.handler(ctx);!res.writableEnded&&!res.headersSent&&applyHandlerResult(ctx,result)})}}function unwrapH3Error(error){if(!(error instanceof Error))return error;let{cause}=error;return cause instanceof Error?cause:error}function h3Runtime(){return{name:`h3`,createApp(options={}){let{createApp}=h3(),app=createApp({onError:(error,event)=>{let res=event.node.res;if(res.writableEnded)return;let state=app;if(error?.statusCode===404){let next=event.node.req[NEXT];if(next){next();return}let nf=state[NOTFOUND_MW];if(nf){nf(event.node.req,resDriver(res),NOOP_NEXT);return}}let mw=state[ERROR_MW];mw&&mw(unwrapH3Error(error),event.node.req,resDriver(res),NOOP_NEXT)}});return app[TRUST_PROXY]=options.trustProxy,app},nodeHandler(app){let{toNodeListener}=h3(),state=app;state[ASSEMBLED]||(state[ASSEMBLED]=!0,state[ROUTER]&&app.use(state[ROUTER]));let listener=toNodeListener(app);return(req,res,next)=>{next&&(req[NEXT]=next),Promise.resolve(listener(req,res)).catch(err=>{next&&next(err)})}},mountRoutes(app,table){let{createRouter,eventHandler}=h3(),trustProxy=!!app[TRUST_PROXY],state=app;state[ROUTER]||(state[ROUTER]=createRouter());let router=state[ROUTER];for(let{mountPath,routes}of table)for(let entry of routes){let url=joinPath(mountPath,entry.path);router[entry.method.toLowerCase()](url,eventHandler(makeEventHandler(entry,trustProxy)))}},useConnect(app,mw,opts){let{fromNodeMiddleware}=h3(),handler=fromNodeMiddleware(mw);opts?.path===void 0?app.use(handler):app.use(opts.path,handler)},serveStatic(app,prefix,dir){let serveStatic=peerRequire(`serve-static`);this.useConnect(app,serveStatic(dir),{path:prefix})},setNotFound(app,mw){app[NOTFOUND_MW]=mw},setErrorHandler(app,mw){app[ERROR_MW]=mw},capabilities:{render:!1,uploads:!0,connectMiddleware:!0,nativeBodyParsing:!0}}}function joinPath(mountPath,path){let a=mountPath.endsWith(`/`)?mountPath.slice(0,-1):mountPath;return path===`/`||path===``?a===``?`/`:a:`${a}${path.startsWith(`/`)?path:`/${path}`}`}export{h3Runtime};
12
12
  //# sourceMappingURL=h3.mjs.map
package/dist/index.d.mts CHANGED
@@ -9,7 +9,7 @@ import { $ as ModuleList, A as AdapterFactory, B as getClassMeta, C as UseConnec
9
9
  import { i as getCronJobs, n as Cron, r as CronJobMeta, t as CRON_META } from "./cron-DOOtTY4q.mjs";
10
10
  import { a as Cacheable, c as setCacheProvider, i as CacheProvider, n as CacheEvict, o as MemoryCacheProvider, r as CacheOptions, s as getCacheProvider } from "./cache-C0qL0NSD.mjs";
11
11
  import { a as describeError, i as createLogger, n as Logger, r as LoggerProvider, t as ConsoleLoggerProvider } from "./logger-DA43DvNY.mjs";
12
- import { $ as CircuitBreakerOptions, A as ClusterOptions, B as groupAssetKeys, C as getRequestStore, D as expressRuntime, E as buildRoutes, F as offerRoutePolicy, G as MountKind, H as DuplicateMountNameError, I as AssetKeyPair, J as ContributorCycleError, K as MountSortItem, L as AssetKeyStrategy, M as bootstrap, N as RoutePolicyTable, O as materializeRouter, P as bindRoutePolicy, Q as CircuitBreaker, R as GroupAssetKeysOptions, S as RequestStore, T as requestStore, U as MissingMountDepError, V as stripExt, W as MountCycleError, X as MissingContextValueError, Y as DuplicateContributorError, Z as MissingContributorError, _ as TraceContext, a as HEALTH_PROBE, at as KickErrorInit, b as traceContext, c as HealthModuleConfig, ct as disposeAll, d as SpaAdapter, et as CircuitBreakerState, f as SpaAdapterOptions, g as TRACEPARENT_HEADER, h as ViewAdapterOptions, it as KickError, j as isClusterPrimary, k as defineHttpContextDecorator, l as HealthProbe, lt as registerDisposable, m as ViewAdapter, n as ApplicationOptions, nt as CircuitOpenError, o as HealthCheckResult, ot as formatKickError, q as mountSort, r as MiddlewareEntry, rt as FormatKickErrorOptions, s as HealthController, st as Disposable, t as Application, tt as CircuitBreakerStats, u as healthModule, v as TraceContextOptions, w as getRequestValue, x as requestScopeMiddleware, y as parseTraceparent, z as GroupAssetKeysResult } from "./application-C2WveUZr.mjs";
12
+ import { $ as MissingContributorError, A as ClusterOptions, B as GroupAssetKeysOptions, C as getRequestStore, D as expressRuntime, E as buildRoutes, F as RoutePolicyTable, G as MissingMountDepError, H as groupAssetKeys, I as bindRoutePolicy, J as MountSortItem, K as MountCycleError, L as offerRoutePolicy, M as KickHandler, N as createHandler, O as materializeRouter, P as bootstrap, Q as MissingContextValueError, R as AssetKeyPair, S as RequestStore, T as requestStore, U as stripExt, V as GroupAssetKeysResult, W as DuplicateMountNameError, X as ContributorCycleError, Y as mountSort, Z as DuplicateContributorError, _ as TraceContext, a as HEALTH_PROBE, at as FormatKickErrorOptions, b as traceContext, c as HealthModuleConfig, ct as formatKickError, d as SpaAdapter, dt as registerDisposable, et as CircuitBreaker, f as SpaAdapterOptions, g as TRACEPARENT_HEADER, h as ViewAdapterOptions, it as CircuitOpenError, j as isClusterPrimary, k as defineHttpContextDecorator, l as HealthProbe, lt as Disposable, m as ViewAdapter, n as ApplicationOptions, nt as CircuitBreakerState, o as HealthCheckResult, ot as KickError, q as MountKind, r as MiddlewareEntry, rt as CircuitBreakerStats, s as HealthController, st as KickErrorInit, t as Application, tt as CircuitBreakerOptions, u as healthModule, ut as disposeAll, v as TraceContextOptions, w as getRequestValue, x as requestScopeMiddleware, y as parseTraceparent, z as AssetKeyStrategy } from "./application-BRvykQ6h.mjs";
13
13
  import { a as ProblemException, c as defaultProblemTitle, i as ProblemDetails, l as normalizeProblem, n as HttpStatus, o as Problems, r as HttpStatusCode, s as ValidationError, t as HttpException } from "./errors-By6UueCm.mjs";
14
14
  import { n as joinPaths, r as normalizePath, t as buildMountPath } from "./path-CMwIHsdv.mjs";
15
15
  import { a as isRef, c as toRefs, i as computed, l as unref, n as Ref, o as reactive, r as WatchOptions, s as ref, t as ComputedRef, u as watch } from "./reactivity-BkMNA0kp.mjs";
@@ -26,4 +26,4 @@ import { n as cors, t as CorsOptions } from "./cors-CsibNTQ6.mjs";
26
26
  import { n as RateLimitStore, r as rateLimit, t as RateLimitOptions } from "./rate-limit-D5FHbYKG.mjs";
27
27
  import { a as session, i as SessionStore, n as SessionData, r as SessionOptions, t as Session } from "./session-BHgRyfqZ.mjs";
28
28
  import { i as upload, l as resolveMimeTypes, n as buildUploadMiddleware, r as cleanupFiles, t as UploadOptions } from "./upload-DwGoAQ6R.mjs";
29
- export { ASSETS, ASSET_MANIFEST_VERSION, type ActiveRuntime, type AdapterAsyncOptions, type AdapterContext, type AdapterFactory, type AdapterHttp, type AdapterMiddleware, type AnyContributorRegistration, ApiQueryParams, type ApiQueryParamsConfig, type ApiQueryParamsConfig as QueryParamsConfig, type AppAdapter, type AppAdapterClass, type AppModule, type AppModuleClass, type AppModuleEntry, Application, type ApplicationOptions, Asset, type AssetKey, type AssetKeyPair, type AssetKeyStrategy, type AugmentationMeta, Autowired, type BareRouteFlag, type BaseUploadOptions, type BuildContext, type BuildPipelineOptions, type BuildRoutesOptions, type Buildable, Builder, type BuilderOf, CRON_META, CacheEvict, type CacheOptions, type CacheProvider, Cacheable, type CallSiteParams, CircuitBreaker, type CircuitBreakerOptions, type CircuitBreakerState, type CircuitBreakerStats, CircuitOpenError, type ClassKind, type ClusterOptions, type ColumnApiQueryParamsConfig, Component, type ComputedRef, ConfigService, type ConnectMiddleware, ConsoleLoggerProvider, type Constructor, Container, type ContainerChangeEvent, type ContainerChangeListener, type ContextDecorator, type ContextDecoratorRequiringParams, type ContextDecoratorSpec, type ContextDecoratorTarget, type ContextDecoratorWithDefaults, type ContextKeys, type ContextMeta, type ContextMetaKey, ContributorCycleError, type ContributorPipeline, type ContributorRegistration, type ContributorRegistrations, type ContributorSource, Controller, type CorsOptions, Cron, type CronJobMeta, type CsrfGuardOptions, type CsrfOptions, type Ctx, type CtxHandler, type DeepReadonly, type DefineAdapterOptions, type DefineModuleOptions, type DefinePluginOptions, Delete, type DepValue, type Disposable, DuplicateContributorError, DuplicateMountNameError, type Env, type EnvKey, type ExecutionContext, type ExpressRuntimeTypes, FILTER_OPERATORS, type FieldsOf, type FileTypeFilter, FileUpload, type FileUploadConfig, type FilterItem, type FilterOperator, type FormatKickErrorOptions, Get, type GroupAssetKeysOptions, type GroupAssetKeysResult, HEALTH_PROBE, type HealthCheckResult, HealthController, type HealthModuleConfig, type HealthProbe, type HelmetOptions, HttpException, type HttpRuntime, HttpStatus, type HttpStatusCode, INJECTION_TOKEN, type InferHandlerResponse, Inject, Injectable, type InjectionToken, type IntrospectFn, type IntrospectionKind, type IntrospectionSnapshot, type KickAssets, KickError, type KickErrorInit, type KickJsPluginName, type KickJsPluginRegistry, type KickJsRegistry, type KickPlugin, type KickRouteFlags, type KickRuntimeRegister, type KvLike, KvRateLimitStore, type KvRateLimitStoreOptions, KvSessionStore, type KvSessionStoreOptions, type LoggedRequest, type LoggedResponse, Logger, type LoggerProvider, METADATA, type MatchedRoute, type MaybePromise, MemoryCacheProvider, type MetaValue, Middleware, type MiddlewareEntry, type MiddlewareHandler, type MiddlewarePath, type MiddlewarePhase, MissingContextValueError, MissingContributorError, MissingMountDepError, type MissingParamKeys, type ModuleFactory, ModuleList, type ModuleRegistry, type ModuleRoutes, MountCycleError, type MountKind, type MountSortItem, MutableModuleRegistry, type NegatedRouteFlagName, type PaginatedResponse, type PaginationParams, type ParseQueryOptions, type ParsedQuery, Patch, type PluginAsyncOptions, type PluginFactory, Post, PostConstruct, type PostConstructStatus, PreDestroy, type ProblemDetails, ProblemException, Problems, Put, type QueryBuilderAdapter, type QueryFieldConfig, type QueryRejectReason, type QueryRejection, REQUEST_ID_HEADER, type RateLimitGuardOptions, type RateLimitOptions, type RateLimitStore, type Ref, type Reply, Repository, RequestContext, type RequestLoggerOptions, type RequestStore, type ResolvedDeps, type RouteDefinition, type RouteEntry, type RouteFlag, type RouteFlagContext, type RouteFlagDeclaration, type RouteFlagDeclarations, type RouteFlagName, type RouteFlagPredicate, type RouteFlagRecord, type RouteFlagTest, type RouteFlagValue, type RouteFlags, type RouteMeta, type RouteMethod, RoutePolicyTable, type RouteShape, type RouteTable, type RunContributorsOptions, type RuntimeAppOptions, type RuntimeCapabilities, type RuntimeResponse, type RuntimeTypeMap, Scope, Service, type ServiceOptions, type Session, type SessionData, type SessionOptions, type SessionStore, type SortItem, type SourcedRegistration, SpaAdapter, type SpaAdapterOptions, type SseHandler, TRACEPARENT_HEADER, type TraceContext, type TraceContextOptions, type TypedConfigService, type TypedParsedQuery, UnknownAssetError, type UploadOptions, type UseConnectOptions, type ValidationError, Value, type ValuedRouteFlag, ViewAdapter, type ViewAdapterOptions, type WatchOptions, applyHandlerResult, assets, baseEnvSchema, bindRoutePolicy, bootstrap, buildMountPath, buildPipeline, buildQueryParams, buildRouteTable, buildRoutes, buildUploadMiddleware, cleanupFiles, clearAssetCache, computed, cors, createConfigService, createLogger, createToken, csrf, csrfGuard, defaultProblemTitle, defineAdapter, defineAugmentation, defineContextDecorator, defineEnv, defineHttpContextDecorator, defineModule, defineModules, definePlugin, defineRouteFlag, describeError, disposeAll, errorHandler, expressRuntime, formatKickError, getCacheProvider, getClassMeta, getClassMetaOrUndefined, getCronJobs, getEnv, getMetaMap, getMetaRecord, getMethodMeta, getMethodMetaOrUndefined, getQueryParsingDefaults, getRequestStore, getRequestValue, getRouteFlags, groupAssetKeys, hasClassMeta, healthModule, helmet, isClusterPrimary, isInjectionToken, isRef, isReply, joinPaths, loadEnv, loadEnvFromSchema, matchesFlagTest, materializeRouter, mountSort, normalizeApiQueryParamsConfig, normalizePath, normalizeProblem, notFoundHandler, offerRoutePolicy, parseFilters, parsePagination, parseQuery, parseSearchQuery, parseSort, parseTraceparent, pushClassMeta, pushMethodMeta, rateLimit, rateLimitGuard, reactive, ref, registerDisposable, reloadEnv, reply, requestId, requestLogger, requestScopeMiddleware, requestStore, resetEnvCache, resetQueryParsingDefaults, resolveAsset, resolveMimeTypes, resolveRouteFlags, runContributors, session, setCacheProvider, setClassMeta, setInMetaMap, setInMetaRecord, setMethodMeta, setQueryParsingDefaults, stripExt, toRefs, tokenName, traceContext, unref, upload, useAssets, validate, watch, withBuilder };
29
+ export { ASSETS, ASSET_MANIFEST_VERSION, type ActiveRuntime, type AdapterAsyncOptions, type AdapterContext, type AdapterFactory, type AdapterHttp, type AdapterMiddleware, type AnyContributorRegistration, ApiQueryParams, type ApiQueryParamsConfig, type ApiQueryParamsConfig as QueryParamsConfig, type AppAdapter, type AppAdapterClass, type AppModule, type AppModuleClass, type AppModuleEntry, Application, type ApplicationOptions, Asset, type AssetKey, type AssetKeyPair, type AssetKeyStrategy, type AugmentationMeta, Autowired, type BareRouteFlag, type BaseUploadOptions, type BuildContext, type BuildPipelineOptions, type BuildRoutesOptions, type Buildable, Builder, type BuilderOf, CRON_META, CacheEvict, type CacheOptions, type CacheProvider, Cacheable, type CallSiteParams, CircuitBreaker, type CircuitBreakerOptions, type CircuitBreakerState, type CircuitBreakerStats, CircuitOpenError, type ClassKind, type ClusterOptions, type ColumnApiQueryParamsConfig, Component, type ComputedRef, ConfigService, type ConnectMiddleware, ConsoleLoggerProvider, type Constructor, Container, type ContainerChangeEvent, type ContainerChangeListener, type ContextDecorator, type ContextDecoratorRequiringParams, type ContextDecoratorSpec, type ContextDecoratorTarget, type ContextDecoratorWithDefaults, type ContextKeys, type ContextMeta, type ContextMetaKey, ContributorCycleError, type ContributorPipeline, type ContributorRegistration, type ContributorRegistrations, type ContributorSource, Controller, type CorsOptions, Cron, type CronJobMeta, type CsrfGuardOptions, type CsrfOptions, type Ctx, type CtxHandler, type DeepReadonly, type DefineAdapterOptions, type DefineModuleOptions, type DefinePluginOptions, Delete, type DepValue, type Disposable, DuplicateContributorError, DuplicateMountNameError, type Env, type EnvKey, type ExecutionContext, type ExpressRuntimeTypes, FILTER_OPERATORS, type FieldsOf, type FileTypeFilter, FileUpload, type FileUploadConfig, type FilterItem, type FilterOperator, type FormatKickErrorOptions, Get, type GroupAssetKeysOptions, type GroupAssetKeysResult, HEALTH_PROBE, type HealthCheckResult, HealthController, type HealthModuleConfig, type HealthProbe, type HelmetOptions, HttpException, type HttpRuntime, HttpStatus, type HttpStatusCode, INJECTION_TOKEN, type InferHandlerResponse, Inject, Injectable, type InjectionToken, type IntrospectFn, type IntrospectionKind, type IntrospectionSnapshot, type KickAssets, KickError, type KickErrorInit, type KickHandler, type KickJsPluginName, type KickJsPluginRegistry, type KickJsRegistry, type KickPlugin, type KickRouteFlags, type KickRuntimeRegister, type KvLike, KvRateLimitStore, type KvRateLimitStoreOptions, KvSessionStore, type KvSessionStoreOptions, type LoggedRequest, type LoggedResponse, Logger, type LoggerProvider, METADATA, type MatchedRoute, type MaybePromise, MemoryCacheProvider, type MetaValue, Middleware, type MiddlewareEntry, type MiddlewareHandler, type MiddlewarePath, type MiddlewarePhase, MissingContextValueError, MissingContributorError, MissingMountDepError, type MissingParamKeys, type ModuleFactory, ModuleList, type ModuleRegistry, type ModuleRoutes, MountCycleError, type MountKind, type MountSortItem, MutableModuleRegistry, type NegatedRouteFlagName, type PaginatedResponse, type PaginationParams, type ParseQueryOptions, type ParsedQuery, Patch, type PluginAsyncOptions, type PluginFactory, Post, PostConstruct, type PostConstructStatus, PreDestroy, type ProblemDetails, ProblemException, Problems, Put, type QueryBuilderAdapter, type QueryFieldConfig, type QueryRejectReason, type QueryRejection, REQUEST_ID_HEADER, type RateLimitGuardOptions, type RateLimitOptions, type RateLimitStore, type Ref, type Reply, Repository, RequestContext, type RequestLoggerOptions, type RequestStore, type ResolvedDeps, type RouteDefinition, type RouteEntry, type RouteFlag, type RouteFlagContext, type RouteFlagDeclaration, type RouteFlagDeclarations, type RouteFlagName, type RouteFlagPredicate, type RouteFlagRecord, type RouteFlagTest, type RouteFlagValue, type RouteFlags, type RouteMeta, type RouteMethod, RoutePolicyTable, type RouteShape, type RouteTable, type RunContributorsOptions, type RuntimeAppOptions, type RuntimeCapabilities, type RuntimeResponse, type RuntimeTypeMap, Scope, Service, type ServiceOptions, type Session, type SessionData, type SessionOptions, type SessionStore, type SortItem, type SourcedRegistration, SpaAdapter, type SpaAdapterOptions, type SseHandler, TRACEPARENT_HEADER, type TraceContext, type TraceContextOptions, type TypedConfigService, type TypedParsedQuery, UnknownAssetError, type UploadOptions, type UseConnectOptions, type ValidationError, Value, type ValuedRouteFlag, ViewAdapter, type ViewAdapterOptions, type WatchOptions, applyHandlerResult, assets, baseEnvSchema, bindRoutePolicy, bootstrap, buildMountPath, buildPipeline, buildQueryParams, buildRouteTable, buildRoutes, buildUploadMiddleware, cleanupFiles, clearAssetCache, computed, cors, createConfigService, createHandler, createLogger, createToken, csrf, csrfGuard, defaultProblemTitle, defineAdapter, defineAugmentation, defineContextDecorator, defineEnv, defineHttpContextDecorator, defineModule, defineModules, definePlugin, defineRouteFlag, describeError, disposeAll, errorHandler, expressRuntime, formatKickError, getCacheProvider, getClassMeta, getClassMetaOrUndefined, getCronJobs, getEnv, getMetaMap, getMetaRecord, getMethodMeta, getMethodMetaOrUndefined, getQueryParsingDefaults, getRequestStore, getRequestValue, getRouteFlags, groupAssetKeys, hasClassMeta, healthModule, helmet, isClusterPrimary, isInjectionToken, isRef, isReply, joinPaths, loadEnv, loadEnvFromSchema, matchesFlagTest, materializeRouter, mountSort, normalizeApiQueryParamsConfig, normalizePath, normalizeProblem, notFoundHandler, offerRoutePolicy, parseFilters, parsePagination, parseQuery, parseSearchQuery, parseSort, parseTraceparent, pushClassMeta, pushMethodMeta, rateLimit, rateLimitGuard, reactive, ref, registerDisposable, reloadEnv, reply, requestId, requestLogger, requestScopeMiddleware, requestStore, resetEnvCache, resetQueryParsingDefaults, resolveAsset, resolveMimeTypes, resolveRouteFlags, runContributors, session, setCacheProvider, setClassMeta, setInMetaMap, setInMetaRecord, setMethodMeta, setQueryParsingDefaults, stripExt, toRefs, tokenName, traceContext, unref, upload, useAssets, validate, watch, withBuilder };
package/dist/index.mjs CHANGED
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @forinda/kickjs v8.4.0
2
+ * @forinda/kickjs v8.5.0
3
3
  *
4
4
  * Copyright (c) Felix Orinda
5
5
  *
@@ -8,5 +8,5 @@
8
8
  *
9
9
  * @license MIT
10
10
  */
11
- import{a as loadEnvFromSchema,i as loadEnv,n as defineEnv,o as reloadEnv,r as getEnv,s as resetEnvCache,t as baseEnvSchema}from"./env-BTOmTNsH.mjs";import{METADATA,Scope}from"./core/interfaces.mjs";import{a as isInjectionToken,c as KickError,i as createToken,l as formatKickError,n as tokenName,r as INJECTION_TOKEN,t as Container}from"./container-BB_XC2ww.mjs";import{ConsoleLoggerProvider,Logger,createLogger,describeError}from"./core/logger.mjs";import{a as getMethodMeta,c as pushClassMeta,d as setInMetaMap,f as setInMetaRecord,i as getMetaRecord,l as pushMethodMeta,n as getClassMetaOrUndefined,o as getMethodMetaOrUndefined,p as setMethodMeta,r as getMetaMap,s as hasClassMeta,t as getClassMeta,u as setClassMeta}from"./metadata-C_bLigwT.mjs";import{ApiQueryParams,Asset,Autowired,Builder,Component,Controller,Delete,FileUpload,Get,Inject,Injectable,Middleware,Patch,Post,PostConstruct,PreDestroy,Put,Repository,Service,Value,normalizeApiQueryParamsConfig,withBuilder}from"./core/decorators.mjs";import{a as HEALTH_PROBE,c as DuplicateMountNameError,d as mountSort,f as defineModule,i as materializeRouter,l as MissingMountDepError,n as buildRoutes,o as HealthController,r as expressRuntime,s as healthModule,t as Application,u as MountCycleError}from"./application-Bm3wCm06.mjs";import{t as MutableModuleRegistry}from"./module-registry-B_gw6smc.mjs";import{CRON_META,Cron,getCronJobs}from"./core/cron.mjs";import{CacheEvict,Cacheable,MemoryCacheProvider,getCacheProvider,setCacheProvider}from"./core/cache.mjs";import{r as registerDisposable,t as disposeAll}from"./disposables-CZ7vf6L_.mjs";import{HttpException,HttpStatus,ProblemException,Problems,defaultProblemTitle,normalizeProblem}from"./core/errors.mjs";import{buildMountPath,joinPaths,normalizePath}from"./core/path.mjs";import{computed,isRef,reactive,ref,toRefs,unref,watch}from"./core/reactivity.mjs";import{l as resolveRouteFlags,o as getRouteFlags,r as defineRouteFlag,s as matchesFlagTest}from"./route-flag-C7AilXtr.mjs";import{a as clearAssetCache,c as groupAssetKeys,i as assets,l as stripExt,n as ASSET_MANIFEST_VERSION,o as resolveAsset,r as UnknownAssetError,s as useAssets,t as ASSETS,u as defineContextDecorator}from"./core-CTyRc4AM.mjs";import{i as MissingContributorError,n as DuplicateContributorError,r as MissingContextValueError,t as ContributorCycleError}from"./context-errors-doMQ4bAU.mjs";import{i as buildPipeline,r as buildRouteTable}from"./router-builder-CFAHKq4e.mjs";import{t as runContributors}from"./contributor-runner-DflutMFy.mjs";import{t as defineAdapter}from"./define-adapter-CsDcNhlh.mjs";import{n as bindRoutePolicy,r as offerRoutePolicy,t as RoutePolicyTable}from"./route-policy-BQfQEuFn.mjs";import{c as requestScopeMiddleware,i as reply,n as applyHandlerResult,r as isReply}from"./runtime-B2oXJDwr.mjs";import{REQUEST_ID_HEADER,requestId}from"./http/middleware/request-id.mjs";import{errorHandler,notFoundHandler}from"./http/middleware/error-handler.mjs";import{i as requestStore,n as getRequestStore,r as getRequestValue,t as RequestContext}from"./context-Xd8C4fIo.mjs";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-B7_CJZaf.mjs";import{validate}from"./http/middleware/validate.mjs";import{r as resolveMimeTypes}from"./upload-config-C23IAKGT.mjs";import{buildUploadMiddleware,cleanupFiles,upload}from"./http/middleware/upload.mjs";import{n as isClusterPrimary,t as bootstrap}from"./bootstrap-DHftqJ1m.mjs";import{n as csrfGuard,r as randomHex,t as csrf}from"./csrf-CMzwva6A.mjs";import{requestLogger}from"./http/middleware/request-logger.mjs";import{helmet}from"./http/middleware/helmet.mjs";import{cors}from"./http/middleware/cors.mjs";import{rateLimit}from"./http/middleware/rate-limit.mjs";import{n as KvSessionStore,r as rateLimitGuard,t as KvRateLimitStore}from"./kv-stores-C755yuvc.mjs";import{session}from"./http/middleware/session.mjs";import{ViewAdapter}from"./http/middleware/views.mjs";import{SpaAdapter}from"./http/middleware/spa.mjs";import{n as createConfigService,t as ConfigService}from"./config-pot4-2DS.mjs";var ModuleList=class extends Array{mount(module){return this.push(module),this}};function defineModules(...initial){let list=new ModuleList;for(let entry of initial)list.push(entry);return list}var CircuitOpenError=class extends Error{breakerName;constructor(breakerName){super(`Circuit breaker "${breakerName}" is open — request rejected`),this.breakerName=breakerName,this.name=`CircuitOpenError`}},CircuitBreaker=class{name;state=`closed`;failures=0;successes=0;halfOpenAttempts=0;lastFailure;openedAt;failureThreshold;resetTimeout;halfOpenMax;constructor(name,options){this.name=name,this.failureThreshold=options.failureThreshold,this.resetTimeout=options.resetTimeout,this.halfOpenMax=options.halfOpenMax??1}async execute(fn){if(this.maybeTransitionToHalfOpen(),this.state===`open`||this.state===`half_open`&&this.halfOpenAttempts>=this.halfOpenMax)throw new CircuitOpenError(this.name);this.state===`half_open`&&this.halfOpenAttempts++;try{let result=await fn();return this.onSuccess(),result}catch(error){throw this.onFailure(),error}}getState(){return this.maybeTransitionToHalfOpen(),this.state}getStats(){return this.maybeTransitionToHalfOpen(),{failures:this.failures,successes:this.successes,state:this.state,...this.lastFailure?{lastFailure:this.lastFailure}:{}}}reset(){this.state=`closed`,this.failures=0,this.successes=0,this.halfOpenAttempts=0,this.lastFailure=void 0,this.openedAt=void 0}onSuccess(){this.state===`half_open`&&(this.state=`closed`,this.failures=0,this.halfOpenAttempts=0,this.openedAt=void 0),this.successes++}onFailure(){this.failures++,this.lastFailure=new Date,this.state===`half_open`?(this.state=`open`,this.openedAt=Date.now(),this.halfOpenAttempts=0):this.state===`closed`&&this.failures>=this.failureThreshold&&(this.state=`open`,this.openedAt=Date.now())}maybeTransitionToHalfOpen(){this.state===`open`&&this.openedAt!=null&&Date.now()-this.openedAt>=this.resetTimeout&&(this.state=`half_open`,this.halfOpenAttempts=0)}};const mergeConfig=(defaults={},overrides={})=>({...defaults,...overrides}),composeName=(base,scope)=>`${base}:${scope}`;function definePlugin(options){let buildSync=(instanceName,scoped,overrides)=>{let config=mergeConfig(options.defaults,overrides),built=options.build(config,{name:instanceName,scoped});return built.name=instanceName,built},buildAsync=(instanceName,opts)=>{let inner,ensureInner=async container=>{if(inner)return inner;let deps=(opts.inject??[]).map(tok=>container.resolve(tok)),config=await opts.useFactory(...deps);return inner=buildSync(instanceName,!1,config),inner};return{name:instanceName,async onReady(container){let built=await ensureInner(container);built.register?.(container),await built.onReady?.(container)},async shutdown(){await inner?.shutdown?.()}}},factory=(config=>buildSync(options.name,!1,config));return factory.scoped=(scopeName,config)=>buildSync(composeName(options.name,scopeName),!0,config),factory.async=opts=>buildAsync(options.name,opts),Object.defineProperty(factory,"definition",{value:Object.freeze({...options})}),factory}function defineAugmentation(name,meta){}function defineHttpContextDecoratorImpl(spec){return defineContextDecorator(spec)}const defineHttpContextDecorator=Object.freeze(Object.assign(defineHttpContextDecoratorImpl,{withParams:()=>spec=>defineHttpContextDecoratorImpl(spec)})),TRACEPARENT_HEADER=`traceparent`,TRACEPARENT_RE=/^([0-9a-f]{2})-([0-9a-f]{32})-([0-9a-f]{16})-([0-9a-f]{2})$/;function generateTraceId(){return randomHex(16)}function generateSpanId(){return randomHex(8)}function parseTraceparent(header){let match=TRACEPARENT_RE.exec(header.trim().toLowerCase());if(!match)return null;let version=match[1],traceId=match[2],parentSpanId=match[3],flags=match[4];return version===`ff`||traceId===`00000000000000000000000000000000`||parentSpanId===`0000000000000000`?null:{version,traceId,parentSpanId,flags}}function traceContext(options={}){return(req,res,next)=>{let store=requestStore.getStore(),traceparentHeader=req.headers[TRACEPARENT_HEADER],raw=Array.isArray(traceparentHeader)?traceparentHeader[0]:traceparentHeader,parsed=raw?parseTraceparent(raw):null,traceId=parsed?.traceId??generateTraceId(),spanId=generateSpanId();store&&(store.values.set(`traceId`,traceId),store.values.set(`spanId`,spanId),parsed&&(store.values.set(`parentSpanId`,parsed.parentSpanId),store.values.set(`traceFlags`,parsed.flags),store.values.set(`traceVersion`,parsed.version))),req.traceId=traceId,req.spanId=spanId,options.propagateResponse&&res.setHeader(`traceresponse`,traceId),next()}}export{ASSETS,ASSET_MANIFEST_VERSION,ApiQueryParams,Application,Asset,Autowired,Builder,CRON_META,CacheEvict,Cacheable,CircuitBreaker,CircuitOpenError,Component,ConfigService,ConsoleLoggerProvider,Container,ContributorCycleError,Controller,Cron,Delete,DuplicateContributorError,DuplicateMountNameError,FILTER_OPERATORS,FileUpload,Get,HEALTH_PROBE,HealthController,HttpException,HttpStatus,INJECTION_TOKEN,Inject,Injectable,KickError,KvRateLimitStore,KvSessionStore,Logger,METADATA,MemoryCacheProvider,Middleware,MissingContextValueError,MissingContributorError,MissingMountDepError,ModuleList,MountCycleError,MutableModuleRegistry,Patch,Post,PostConstruct,PreDestroy,ProblemException,Problems,Put,REQUEST_ID_HEADER,Repository,RequestContext,RoutePolicyTable,Scope,Service,SpaAdapter,TRACEPARENT_HEADER,UnknownAssetError,Value,ViewAdapter,applyHandlerResult,assets,baseEnvSchema,bindRoutePolicy,bootstrap,buildMountPath,buildPipeline,buildQueryParams,buildRouteTable,buildRoutes,buildUploadMiddleware,cleanupFiles,clearAssetCache,computed,cors,createConfigService,createLogger,createToken,csrf,csrfGuard,defaultProblemTitle,defineAdapter,defineAugmentation,defineContextDecorator,defineEnv,defineHttpContextDecorator,defineModule,defineModules,definePlugin,defineRouteFlag,describeError,disposeAll,errorHandler,expressRuntime,formatKickError,getCacheProvider,getClassMeta,getClassMetaOrUndefined,getCronJobs,getEnv,getMetaMap,getMetaRecord,getMethodMeta,getMethodMetaOrUndefined,getQueryParsingDefaults,getRequestStore,getRequestValue,getRouteFlags,groupAssetKeys,hasClassMeta,healthModule,helmet,isClusterPrimary,isInjectionToken,isRef,isReply,joinPaths,loadEnv,loadEnvFromSchema,matchesFlagTest,materializeRouter,mountSort,normalizeApiQueryParamsConfig,normalizePath,normalizeProblem,notFoundHandler,offerRoutePolicy,parseFilters,parsePagination,parseQuery,parseSearchQuery,parseSort,parseTraceparent,pushClassMeta,pushMethodMeta,rateLimit,rateLimitGuard,reactive,ref,registerDisposable,reloadEnv,reply,requestId,requestLogger,requestScopeMiddleware,requestStore,resetEnvCache,resetQueryParsingDefaults,resolveAsset,resolveMimeTypes,resolveRouteFlags,runContributors,session,setCacheProvider,setClassMeta,setInMetaMap,setInMetaRecord,setMethodMeta,setQueryParsingDefaults,stripExt,toRefs,tokenName,traceContext,unref,upload,useAssets,validate,watch,withBuilder};
11
+ import{a as loadEnvFromSchema,i as loadEnv,n as defineEnv,o as reloadEnv,r as getEnv,s as resetEnvCache,t as baseEnvSchema}from"./env-DWP_2owJ.mjs";import{METADATA,Scope}from"./core/interfaces.mjs";import{a as isInjectionToken,c as KickError,i as createToken,l as formatKickError,n as tokenName,r as INJECTION_TOKEN,t as Container}from"./container-Cj2hqlfm.mjs";import{ConsoleLoggerProvider,Logger,createLogger,describeError}from"./core/logger.mjs";import{a as getMethodMeta,c as pushClassMeta,d as setInMetaMap,f as setInMetaRecord,i as getMetaRecord,l as pushMethodMeta,n as getClassMetaOrUndefined,o as getMethodMetaOrUndefined,p as setMethodMeta,r as getMetaMap,s as hasClassMeta,t as getClassMeta,u as setClassMeta}from"./metadata-Ceheg5tj.mjs";import{ApiQueryParams,Asset,Autowired,Builder,Component,Controller,Delete,FileUpload,Get,Inject,Injectable,Middleware,Patch,Post,PostConstruct,PreDestroy,Put,Repository,Service,Value,normalizeApiQueryParamsConfig,withBuilder}from"./core/decorators.mjs";import{a as HEALTH_PROBE,c as DuplicateMountNameError,d as mountSort,f as defineModule,i as materializeRouter,l as MissingMountDepError,n as buildRoutes,o as HealthController,r as expressRuntime,s as healthModule,t as Application,u as MountCycleError}from"./application-BFKE8ac5.mjs";import{t as MutableModuleRegistry}from"./module-registry-RHo93bJa.mjs";import{CRON_META,Cron,getCronJobs}from"./core/cron.mjs";import{CacheEvict,Cacheable,MemoryCacheProvider,getCacheProvider,setCacheProvider}from"./core/cache.mjs";import{r as registerDisposable,t as disposeAll}from"./disposables-BYYy0y_z.mjs";import{HttpException,HttpStatus,ProblemException,Problems,defaultProblemTitle,normalizeProblem}from"./core/errors.mjs";import{buildMountPath,joinPaths,normalizePath}from"./core/path.mjs";import{computed,isRef,reactive,ref,toRefs,unref,watch}from"./core/reactivity.mjs";import{l as resolveRouteFlags,o as getRouteFlags,r as defineRouteFlag,s as matchesFlagTest}from"./route-flag-B7t2wGJ2.mjs";import{a as clearAssetCache,c as groupAssetKeys,i as assets,l as stripExt,n as ASSET_MANIFEST_VERSION,o as resolveAsset,r as UnknownAssetError,s as useAssets,t as ASSETS,u as defineContextDecorator}from"./core-DZmGThrF.mjs";import{i as MissingContributorError,n as DuplicateContributorError,r as MissingContextValueError,t as ContributorCycleError}from"./context-errors-Cj2_aDaj.mjs";import{i as buildPipeline,r as buildRouteTable}from"./router-builder-CK7_6DLH.mjs";import{t as runContributors}from"./contributor-runner-DQCZLpvk.mjs";import{t as defineAdapter}from"./define-adapter-0asM4v0B.mjs";import{n as bindRoutePolicy,r as offerRoutePolicy,t as RoutePolicyTable}from"./route-policy-MQkq3QEO.mjs";import{c as requestScopeMiddleware,i as reply,n as applyHandlerResult,r as isReply}from"./runtime-B3V_u8FS.mjs";import{REQUEST_ID_HEADER,requestId}from"./http/middleware/request-id.mjs";import{errorHandler,notFoundHandler}from"./http/middleware/error-handler.mjs";import{i as requestStore,n as getRequestStore,r as getRequestValue,t as RequestContext}from"./context-B7N5oE7S.mjs";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-CWwMw9E6.mjs";import{validate}from"./http/middleware/validate.mjs";import{r as resolveMimeTypes}from"./upload-config-C49VFeoh.mjs";import{buildUploadMiddleware,cleanupFiles,upload}from"./http/middleware/upload.mjs";import{n as isClusterPrimary,t as bootstrap}from"./bootstrap-CPRgpW3i.mjs";import{n as csrfGuard,r as randomHex,t as csrf}from"./csrf-DPPIM72I.mjs";import{requestLogger}from"./http/middleware/request-logger.mjs";import{helmet}from"./http/middleware/helmet.mjs";import{cors}from"./http/middleware/cors.mjs";import{rateLimit}from"./http/middleware/rate-limit.mjs";import{n as KvSessionStore,r as rateLimitGuard,t as KvRateLimitStore}from"./kv-stores-D2MKbvcu.mjs";import{session}from"./http/middleware/session.mjs";import{ViewAdapter}from"./http/middleware/views.mjs";import{SpaAdapter}from"./http/middleware/spa.mjs";import{n as createConfigService,t as ConfigService}from"./config-Cajrc3qr.mjs";import http from"node:http";var ModuleList=class extends Array{mount(module){return this.push(module),this}};function defineModules(...initial){let list=new ModuleList;for(let entry of initial)list.push(entry);return list}var CircuitOpenError=class extends Error{breakerName;constructor(breakerName){super(`Circuit breaker "${breakerName}" is open — request rejected`),this.breakerName=breakerName,this.name=`CircuitOpenError`}},CircuitBreaker=class{name;state=`closed`;failures=0;successes=0;halfOpenAttempts=0;lastFailure;openedAt;failureThreshold;resetTimeout;halfOpenMax;constructor(name,options){this.name=name,this.failureThreshold=options.failureThreshold,this.resetTimeout=options.resetTimeout,this.halfOpenMax=options.halfOpenMax??1}async execute(fn){if(this.maybeTransitionToHalfOpen(),this.state===`open`||this.state===`half_open`&&this.halfOpenAttempts>=this.halfOpenMax)throw new CircuitOpenError(this.name);this.state===`half_open`&&this.halfOpenAttempts++;try{let result=await fn();return this.onSuccess(),result}catch(error){throw this.onFailure(),error}}getState(){return this.maybeTransitionToHalfOpen(),this.state}getStats(){return this.maybeTransitionToHalfOpen(),{failures:this.failures,successes:this.successes,state:this.state,...this.lastFailure?{lastFailure:this.lastFailure}:{}}}reset(){this.state=`closed`,this.failures=0,this.successes=0,this.halfOpenAttempts=0,this.lastFailure=void 0,this.openedAt=void 0}onSuccess(){this.state===`half_open`&&(this.state=`closed`,this.failures=0,this.halfOpenAttempts=0,this.openedAt=void 0),this.successes++}onFailure(){this.failures++,this.lastFailure=new Date,this.state===`half_open`?(this.state=`open`,this.openedAt=Date.now(),this.halfOpenAttempts=0):this.state===`closed`&&this.failures>=this.failureThreshold&&(this.state=`open`,this.openedAt=Date.now())}maybeTransitionToHalfOpen(){this.state===`open`&&this.openedAt!=null&&Date.now()-this.openedAt>=this.resetTimeout&&(this.state=`half_open`,this.halfOpenAttempts=0)}};const mergeConfig=(defaults={},overrides={})=>({...defaults,...overrides}),composeName=(base,scope)=>`${base}:${scope}`;function definePlugin(options){let buildSync=(instanceName,scoped,overrides)=>{let config=mergeConfig(options.defaults,overrides),built=options.build(config,{name:instanceName,scoped});return built.name=instanceName,built},buildAsync=(instanceName,opts)=>{let inner,ensureInner=async container=>{if(inner)return inner;let deps=(opts.inject??[]).map(tok=>container.resolve(tok)),config=await opts.useFactory(...deps);return inner=buildSync(instanceName,!1,config),inner};return{name:instanceName,async onReady(container){let built=await ensureInner(container);built.register?.(container),await built.onReady?.(container)},async shutdown(){await inner?.shutdown?.()}}},factory=(config=>buildSync(options.name,!1,config));return factory.scoped=(scopeName,config)=>buildSync(composeName(options.name,scopeName),!0,config),factory.async=opts=>buildAsync(options.name,opts),Object.defineProperty(factory,"definition",{value:Object.freeze({...options})}),factory}function defineAugmentation(name,meta){}const HOP_BY_HOP_REQUEST=[`connection`,`keep-alive`,`proxy-connection`,`transfer-encoding`,`upgrade`,`te`,`trailer`,`host`,`content-length`],HOP_BY_HOP_RESPONSE=[`connection`,`keep-alive`,`proxy-connection`,`transfer-encoding`,`upgrade`,`trailer`,`content-encoding`,`content-length`];function createHandler(options){let app,forwarding,ready=()=>(app??=(async()=>{let instance=new Application(options);try{await instance.startWithoutServer()}catch(err){throw app=void 0,await instance.shutdown().catch(()=>{}),err}return instance})(),app),forwardingServer=instance=>(forwarding??=new Promise((resolve,reject)=>{let server=http.createServer((req,res)=>instance.handle(req,res));server.once(`error`,reject),server.listen(0,`127.0.0.1`,()=>{server.unref(),resolve({origin:`http://127.0.0.1:${server.address().port}`,server})})}).catch(err=>{throw forwarding=void 0,err}),forwarding),forward=async(instance,request)=>{let{origin}=await forwardingServer(instance),url=new URL(request.url),headers=new Headers(request.headers);for(let name of HOP_BY_HOP_REQUEST)headers.delete(name);headers.has(`x-forwarded-host`)||headers.set(`x-forwarded-host`,url.host),headers.has(`x-forwarded-proto`)||headers.set(`x-forwarded-proto`,url.protocol.slice(0,-1));let body=request.method===`GET`||request.method===`HEAD`?void 0:await request.arrayBuffer(),upstream=await fetch(origin+url.pathname+url.search,{method:request.method,headers,body:body&&body.byteLength>0?body:void 0,redirect:`manual`}),responseHeaders=new Headers(upstream.headers),named=responseHeaders.get(`connection`)?.split(`,`)??[];for(let name of[...HOP_BY_HOP_RESPONSE,...named])responseHeaders.delete(name.trim());return new Response(upstream.body,{status:upstream.status,statusText:upstream.statusText,headers:responseHeaders})};return{ready,async fetch(request){let instance=await ready(),runtimeApp=instance.getRuntimeApp();return typeof runtimeApp?.fetch==`function`?await runtimeApp.fetch(request):forward(instance,request)},async node(req,res){(await ready()).handle(req,res)},async close(){let started=await forwarding?.catch(()=>void 0);forwarding=void 0,started&&await new Promise(resolve=>started.server.close(()=>resolve()));let current=app;app=void 0,current&&await(await current).shutdown()}}}function defineHttpContextDecoratorImpl(spec){return defineContextDecorator(spec)}const defineHttpContextDecorator=Object.freeze(Object.assign(defineHttpContextDecoratorImpl,{withParams:()=>spec=>defineHttpContextDecoratorImpl(spec)})),TRACEPARENT_HEADER=`traceparent`,TRACEPARENT_RE=/^([0-9a-f]{2})-([0-9a-f]{32})-([0-9a-f]{16})-([0-9a-f]{2})$/;function generateTraceId(){return randomHex(16)}function generateSpanId(){return randomHex(8)}function parseTraceparent(header){let match=TRACEPARENT_RE.exec(header.trim().toLowerCase());if(!match)return null;let version=match[1],traceId=match[2],parentSpanId=match[3],flags=match[4];return version===`ff`||traceId===`00000000000000000000000000000000`||parentSpanId===`0000000000000000`?null:{version,traceId,parentSpanId,flags}}function traceContext(options={}){return(req,res,next)=>{let store=requestStore.getStore(),traceparentHeader=req.headers[TRACEPARENT_HEADER],raw=Array.isArray(traceparentHeader)?traceparentHeader[0]:traceparentHeader,parsed=raw?parseTraceparent(raw):null,traceId=parsed?.traceId??generateTraceId(),spanId=generateSpanId();store&&(store.values.set(`traceId`,traceId),store.values.set(`spanId`,spanId),parsed&&(store.values.set(`parentSpanId`,parsed.parentSpanId),store.values.set(`traceFlags`,parsed.flags),store.values.set(`traceVersion`,parsed.version))),req.traceId=traceId,req.spanId=spanId,options.propagateResponse&&res.setHeader(`traceresponse`,traceId),next()}}export{ASSETS,ASSET_MANIFEST_VERSION,ApiQueryParams,Application,Asset,Autowired,Builder,CRON_META,CacheEvict,Cacheable,CircuitBreaker,CircuitOpenError,Component,ConfigService,ConsoleLoggerProvider,Container,ContributorCycleError,Controller,Cron,Delete,DuplicateContributorError,DuplicateMountNameError,FILTER_OPERATORS,FileUpload,Get,HEALTH_PROBE,HealthController,HttpException,HttpStatus,INJECTION_TOKEN,Inject,Injectable,KickError,KvRateLimitStore,KvSessionStore,Logger,METADATA,MemoryCacheProvider,Middleware,MissingContextValueError,MissingContributorError,MissingMountDepError,ModuleList,MountCycleError,MutableModuleRegistry,Patch,Post,PostConstruct,PreDestroy,ProblemException,Problems,Put,REQUEST_ID_HEADER,Repository,RequestContext,RoutePolicyTable,Scope,Service,SpaAdapter,TRACEPARENT_HEADER,UnknownAssetError,Value,ViewAdapter,applyHandlerResult,assets,baseEnvSchema,bindRoutePolicy,bootstrap,buildMountPath,buildPipeline,buildQueryParams,buildRouteTable,buildRoutes,buildUploadMiddleware,cleanupFiles,clearAssetCache,computed,cors,createConfigService,createHandler,createLogger,createToken,csrf,csrfGuard,defaultProblemTitle,defineAdapter,defineAugmentation,defineContextDecorator,defineEnv,defineHttpContextDecorator,defineModule,defineModules,definePlugin,defineRouteFlag,describeError,disposeAll,errorHandler,expressRuntime,formatKickError,getCacheProvider,getClassMeta,getClassMetaOrUndefined,getCronJobs,getEnv,getMetaMap,getMetaRecord,getMethodMeta,getMethodMetaOrUndefined,getQueryParsingDefaults,getRequestStore,getRequestValue,getRouteFlags,groupAssetKeys,hasClassMeta,healthModule,helmet,isClusterPrimary,isInjectionToken,isRef,isReply,joinPaths,loadEnv,loadEnvFromSchema,matchesFlagTest,materializeRouter,mountSort,normalizeApiQueryParamsConfig,normalizePath,normalizeProblem,notFoundHandler,offerRoutePolicy,parseFilters,parsePagination,parseQuery,parseSearchQuery,parseSort,parseTraceparent,pushClassMeta,pushMethodMeta,rateLimit,rateLimitGuard,reactive,ref,registerDisposable,reloadEnv,reply,requestId,requestLogger,requestScopeMiddleware,requestStore,resetEnvCache,resetQueryParsingDefaults,resolveAsset,resolveMimeTypes,resolveRouteFlags,runContributors,session,setCacheProvider,setClassMeta,setInMetaMap,setInMetaRecord,setMethodMeta,setQueryParsingDefaults,stripExt,toRefs,tokenName,traceContext,unref,upload,useAssets,validate,watch,withBuilder};
12
12
  //# sourceMappingURL=index.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.mjs","names":[],"sources":["../src/core/define-modules.ts","../src/core/circuit-breaker.ts","../src/core/define-plugin.ts","../src/core/augmentation.ts","../src/http/define-http-context-decorator.ts","../src/http/middleware/trace-context.ts"],"sourcesContent":["import type { AppModuleEntry } from './app-module'\n\n/**\n * Chainable registry returned by {@link defineModules}. Extends\n * `Array<AppModuleEntry>` so it drops into `bootstrap({ modules })`\n * unchanged — the framework loader already iterates the array, so a\n * `ModuleList` IS a valid `modules` value with no special handling.\n *\n * The added affordance is `.mount(module)` returning `this` so\n * adopters can build the list fluently:\n *\n * ```ts\n * const modules = defineModules()\n * .mount(HelloModule())\n * .mount(AdminModule())\n *\n * bootstrap({ modules })\n * ```\n *\n * **Why not just use a plain array?** Two reasons. First, the\n * fluent shape reads more naturally for module-list construction —\n * adopters used to `definePlugin().scoped(...)` / `defineAdapter(...)`\n * see the same call-then-call pattern. Second, the registry is the\n * stable extension point: a future `.use(module)` for non-HTTP\n * modules (queues, cron, workers) lands as a method on `ModuleList`\n * without breaking the `Array<AppModuleEntry>` superclass contract.\n */\nexport class ModuleList extends Array<AppModuleEntry> {\n /**\n * Append a module to the list. Returns `this` for chaining.\n *\n * Accepts both class form (`SomeModule extends AppModule`) and\n * `defineModule` factory output — same as the underlying\n * `bootstrap({ modules })` array. The framework loader\n * discriminates `typeof entry === 'function'` at boot.\n */\n mount(module: AppModuleEntry): this {\n this.push(module)\n return this\n }\n}\n\n/**\n * Build a {@link ModuleList} for the application. Optional vararg\n * lets adopters seed the list inline; subsequent `.mount()` calls\n * append.\n *\n * @example\n * ```ts\n * import { bootstrap, defineModules } from '@forinda/kickjs'\n * import { HelloModule } from './modules/hello/hello.module'\n * import { AdminModule } from './modules/admin/admin.module'\n *\n * // Fluent — most common\n * const modules = defineModules()\n * .mount(HelloModule())\n * .mount(AdminModule())\n *\n * // Or seeded inline + chained\n * const modules2 = defineModules(HelloModule()).mount(AdminModule())\n *\n * await bootstrap({ modules })\n * ```\n *\n * The returned value is an `AppModuleEntry[]` subclass — `bootstrap`\n * accepts it directly without any special-casing. For conditional /\n * dynamic registration at bootstrap time (env flags, runtime config,\n * tenant lists), use the `setup(registry)` callback on `bootstrap`\n * instead — both surfaces compose.\n */\nexport function defineModules(...initial: AppModuleEntry[]): ModuleList {\n const list = new ModuleList()\n for (const entry of initial) list.push(entry)\n return list\n}\n","/**\n * Circuit Breaker pattern for external service calls.\n *\n * Protects your application from cascading failures when downstream\n * services are unhealthy by short-circuiting requests after a\n * configurable failure threshold.\n *\n * @example\n * ```ts\n * const breaker = new CircuitBreaker('payment-api', {\n * failureThreshold: 5,\n * resetTimeout: 30_000,\n * })\n *\n * const result = await breaker.execute(() => fetch('https://payment.example.com/charge'))\n * ```\n */\n\nexport type CircuitBreakerState = 'closed' | 'open' | 'half_open'\n\nexport interface CircuitBreakerOptions {\n /** Number of consecutive failures before the circuit opens. */\n failureThreshold: number\n /** Milliseconds to wait before transitioning from OPEN to HALF_OPEN. */\n resetTimeout: number\n /** Max requests allowed in HALF_OPEN state before deciding (default 1). */\n halfOpenMax?: number\n}\n\nexport interface CircuitBreakerStats {\n failures: number\n successes: number\n state: CircuitBreakerState\n lastFailure?: Date\n}\n\n/**\n * Error thrown when the circuit is open and calls are being rejected.\n */\nexport class CircuitOpenError extends Error {\n constructor(public readonly breakerName: string) {\n super(`Circuit breaker \"${breakerName}\" is open — request rejected`)\n this.name = 'CircuitOpenError'\n }\n}\n\nexport class CircuitBreaker {\n private state: CircuitBreakerState = 'closed'\n private failures = 0\n private successes = 0\n private halfOpenAttempts = 0\n private lastFailure?: Date\n private openedAt?: number\n\n private readonly failureThreshold: number\n private readonly resetTimeout: number\n private readonly halfOpenMax: number\n\n constructor(\n public readonly name: string,\n options: CircuitBreakerOptions,\n ) {\n this.failureThreshold = options.failureThreshold\n this.resetTimeout = options.resetTimeout\n this.halfOpenMax = options.halfOpenMax ?? 1\n }\n\n /**\n * Execute an async function through the circuit breaker.\n * Throws `CircuitOpenError` if the circuit is open.\n */\n async execute<T>(fn: () => Promise<T>): Promise<T> {\n this.maybeTransitionToHalfOpen()\n\n if (this.state === 'open') {\n throw new CircuitOpenError(this.name)\n }\n\n if (this.state === 'half_open' && this.halfOpenAttempts >= this.halfOpenMax) {\n throw new CircuitOpenError(this.name)\n }\n\n if (this.state === 'half_open') {\n this.halfOpenAttempts++\n }\n\n try {\n const result = await fn()\n this.onSuccess()\n return result\n } catch (error) {\n this.onFailure()\n throw error\n }\n }\n\n /** Returns the current circuit state. */\n getState(): CircuitBreakerState {\n this.maybeTransitionToHalfOpen()\n return this.state\n }\n\n /** Returns current statistics. */\n getStats(): CircuitBreakerStats {\n this.maybeTransitionToHalfOpen()\n return {\n failures: this.failures,\n successes: this.successes,\n state: this.state,\n ...(this.lastFailure ? { lastFailure: this.lastFailure } : {}),\n }\n }\n\n /** Manually reset the circuit breaker to CLOSED state. */\n reset(): void {\n this.state = 'closed'\n this.failures = 0\n this.successes = 0\n this.halfOpenAttempts = 0\n this.lastFailure = undefined\n this.openedAt = undefined\n }\n\n private onSuccess(): void {\n if (this.state === 'half_open') {\n // Recovery confirmed — close the circuit\n this.state = 'closed'\n this.failures = 0\n this.halfOpenAttempts = 0\n this.openedAt = undefined\n }\n this.successes++\n }\n\n private onFailure(): void {\n this.failures++\n this.lastFailure = new Date()\n\n if (this.state === 'half_open') {\n // Recovery failed — re-open\n this.state = 'open'\n this.openedAt = Date.now()\n this.halfOpenAttempts = 0\n } else if (this.state === 'closed' && this.failures >= this.failureThreshold) {\n this.state = 'open'\n this.openedAt = Date.now()\n }\n }\n\n private maybeTransitionToHalfOpen(): void {\n if (this.state === 'open' && this.openedAt != null) {\n if (Date.now() - this.openedAt >= this.resetTimeout) {\n this.state = 'half_open'\n this.halfOpenAttempts = 0\n }\n }\n }\n}\n","import type { Container } from './container'\nimport type { KickPlugin } from './plugin'\n\n/**\n * Options passed to {@link definePlugin}. Mirrors the spec in\n * `architecture.md` §21.3.1 + §21.2.2 (Phase A \"lite\").\n */\nexport interface DefinePluginOptions<TConfig> {\n /** Stable identity used for logging, `dependsOn` lookups, and `.scoped()` namespacing. */\n name: string\n\n /** Optional plugin version — surfaced to DevTools and `kick add` compatibility checks (Phase B). */\n version?: string\n\n /**\n * Peer-version ranges this plugin needs from the framework or other\n * plugins. Recorded as metadata; runtime enforcement lands in §21.4.4.\n */\n requires?: { kickjs?: string }\n\n /** Default config merged under any caller overrides. */\n defaults?: Partial<TConfig>\n\n /** Builds the underlying {@link KickPlugin} from the resolved config. */\n build(config: TConfig, ctx: BuildContext): Omit<KickPlugin, 'name'>\n}\n\n/**\n * Hook context handed to a plugin/adapter `build` function. `name` is the\n * resolved instance name (the bare definition name for the bare call,\n * or `${defName}:${scope}` for `.scoped()`). `scoped` is the discriminator\n * authors use to namespace DI tokens or resource keys.\n */\nexport interface BuildContext {\n name: string\n scoped: boolean\n}\n\n/**\n * Async-config form of a plugin or adapter — `inject` lists DI tokens to\n * resolve from the container, then `useFactory` produces the config.\n *\n * Plugins resolve this lazily inside `onReady`, so any module/adapter/\n * middleware/contributor a plugin contributes via `build` is **not\n * available** when `.async()` is used. Use the bare/`.scoped()` form for\n * plugins that need to register modules or middleware.\n */\nexport interface PluginAsyncOptions<TConfig> {\n inject?: ReadonlyArray<unknown>\n useFactory(...deps: any[]): TConfig | Promise<TConfig>\n}\n\n/**\n * Factory returned by {@link definePlugin}. Callable form is the singleton\n * (`AuthPlugin(config)`); `.scoped()` and `.async()` are the multi-instance\n * and deferred-config forms.\n */\nexport interface PluginFactory<TConfig> {\n (config?: Partial<TConfig>): KickPlugin\n scoped(scopeName: string, config?: Partial<TConfig>): KickPlugin\n async(opts: PluginAsyncOptions<TConfig>): KickPlugin\n /** Read-only access to the original definition — useful for DevTools introspection. */\n readonly definition: Readonly<DefinePluginOptions<TConfig>>\n}\n\nconst mergeConfig = <TConfig>(\n defaults: Partial<TConfig> = {},\n overrides: Partial<TConfig> = {},\n): TConfig => ({ ...defaults, ...overrides }) as TConfig\n\nconst composeName = (base: string, scope: string): string => `${base}:${scope}`\n\n/**\n * Build a {@link KickPlugin} factory from a typed definition. See\n * `architecture.md` §21.2.2 for the design rationale.\n *\n * @example\n * ```ts\n * const FlagsPlugin = definePlugin<FlagsConfig>({\n * name: 'FlagsPlugin',\n * defaults: { defaultTtl: 60_000 },\n * build(config) {\n * return {\n * register(container) {\n * container.registerInstance(FLAGS, makeProvider(config))\n * },\n * }\n * },\n * })\n *\n * bootstrap({ plugins: [FlagsPlugin({ provider: launchDarkly })] })\n * ```\n */\nexport function definePlugin<TConfig = Record<string, unknown>>(\n options: DefinePluginOptions<TConfig>,\n): PluginFactory<TConfig> {\n const buildSync = (\n instanceName: string,\n scoped: boolean,\n overrides?: Partial<TConfig>,\n ): KickPlugin => {\n const config = mergeConfig(options.defaults, overrides)\n // Mutate `name` on the build result instead of spreading — spread\n // strips prototype methods when `build()` returns a class instance.\n const built = options.build(config, { name: instanceName, scoped }) as KickPlugin\n built.name = instanceName\n return built\n }\n\n const buildAsync = (instanceName: string, opts: PluginAsyncOptions<TConfig>): KickPlugin => {\n let inner: KickPlugin | undefined\n\n const ensureInner = async (container: Container): Promise<KickPlugin> => {\n if (inner) return inner\n const deps = (opts.inject ?? []).map((tok) => container.resolve(tok as never))\n const config = await opts.useFactory(...deps)\n inner = buildSync(instanceName, false, config as Partial<TConfig>)\n return inner\n }\n\n return {\n name: instanceName,\n async onReady(container: Container) {\n const built = await ensureInner(container)\n // Run the inner plugin's register() now that we have the config —\n // late but better than never; `.async()` plugins skip the early\n // module/middleware contribution surface by design.\n built.register?.(container)\n await built.onReady?.(container)\n },\n async shutdown() {\n await inner?.shutdown?.()\n },\n }\n }\n\n const factory = ((config?: Partial<TConfig>) =>\n buildSync(options.name, false, config)) as PluginFactory<TConfig>\n\n factory.scoped = (scopeName: string, config?: Partial<TConfig>) =>\n buildSync(composeName(options.name, scopeName), true, config)\n\n factory.async = (opts: PluginAsyncOptions<TConfig>) => buildAsync(options.name, opts)\n\n Object.defineProperty(factory, 'definition', { value: Object.freeze({ ...options }) })\n\n return factory\n}\n","/**\n * Augmentation registry — runtime no-op + the canonical\n * `KickJsPluginRegistry` interface that `kick typegen` augments.\n *\n * See `architecture.md` §21.2.1 (typegen for `dependsOn`) and §21.3.3\n * (standardized augmentation registry) for the design rationale.\n *\n * @module @forinda/kickjs/core/augmentation\n */\n\n/**\n * Marker interface that lists every plugin/adapter in the project. The\n * keys are the literal `name` field passed to `defineAdapter` /\n * `definePlugin` (or declared on a `class implements AppAdapter`); the\n * values are the kind tag (`'plugin' | 'adapter'`).\n *\n * The framework ships this empty. `kick typegen` augments it from\n * source so `keyof KickJsPluginRegistry` resolves to a string-literal\n * union of every name in scope — and therefore so do `dependsOn`\n * declarations on plugins/adapters.\n */\nexport interface KickJsPluginRegistry {}\n\n/**\n * Resolves to a string-literal union of every registered plugin/adapter\n * name when the project's typegen has populated `KickJsPluginRegistry`,\n * or to `string` when the registry is empty (no typegen pass yet).\n *\n * Falling back to `string` keeps fresh projects compiling — the typegen\n * narrowing is a progressive enhancement, not a hard prerequisite.\n */\nexport type KickJsPluginName = keyof KickJsPluginRegistry extends never\n ? string\n : keyof KickJsPluginRegistry & string\n\n/**\n * Metadata attached to a `defineAugmentation` call. The fields are\n * documentation-only — `kick typegen` surfaces them in the generated\n * `.kickjs/types/kick__augmentations.d.ts` so adopters can browse every\n * augmentable interface from one place.\n *\n * `description` and `example` may both be multi-line — typegen preserves\n * line breaks when rendering them as JSDoc. There is no upper limit on\n * the example size; entire shape definitions or worked snippets are fine.\n */\nexport interface AugmentationMeta {\n /**\n * Free-form description of what the augmentation customises. May be\n * multi-line — newlines are preserved in the generated JSDoc.\n */\n description?: string\n /**\n * TS snippet showing a typical shape. May be multi-line; rendered\n * inside a fenced code block in the generated catalogue. Use this\n * for anything from `'{ foo: string }'` up to a full interface body\n * — typegen no longer flattens newlines.\n */\n example?: string\n}\n\n/**\n * @deprecated Since 7.2. This was tooling for a time when Context\n * Contributors were still settling — a catalogue so adopters could discover\n * which interfaces were augmentable. Contributors are a stable, typed API now\n * (`defineContextDecorator`, `ContextMeta`), and the catalogue adds a second\n * call that must be kept in step with the `declare module` block for no\n * type-level benefit.\n *\n * Nothing breaks: `kick typegen` still discovers the call and still writes the\n * catalogue. Just drop it — the `declare module '@forinda/kickjs'` block alone\n * gives you the types, which is all it ever gave you.\n *\n * What it actually emits, for the record: one empty marker interface per call\n * in `.kickjs/types/kick__augmentations.d.ts` —\n *\n * ```ts\n * // from defineAugmentation('ContextMeta', { description, example })\n * export interface ContextMetaAugmentation {}\n * ```\n *\n * with your `description` / `example` rendered as its JSDoc and a `@see` back\n * to the call site. The interface is empty and unreferenced; nothing consumes\n * it at type level.\n *\n * Advertise an augmentable interface so `kick typegen` can list it in\n * `.kickjs/types/kick__augmentations.d.ts` for project-wide discovery.\n *\n * **This function is a runtime AND type-level no-op.** It does NOT\n * augment the interface for TypeScript. The actual augmentation is\n * the `declare module` block — `defineAugmentation` only adds an\n * entry to the typegen catalogue (`.kickjs/types/kick__augmentations.d.ts`)\n * so other contributors / adopters can find the interface and know its\n * expected shape.\n *\n * Both calls are needed:\n *\n * ```ts\n * import { defineAugmentation } from '@forinda/kickjs'\n *\n * // (1) The actual TS augmentation — what `ctx.get('tenant')` reads.\n * declare module '@forinda/kickjs' {\n * interface ContextMeta {\n * tenant: { id: string; name: string }\n * }\n * }\n *\n * // (2) Catalogue entry — what `kick typegen` lists in\n * // `.kickjs/types/kick__augmentations.d.ts` for browseability.\n * defineAugmentation('ContextMeta', {\n * description: 'Tenant resolved from x-tenant-id by TenantAdapter',\n * example: `{\n * tenant: {\n * id: string\n * name: string\n * plan: 'free' | 'pro' | 'enterprise'\n * featureFlags: Record<string, boolean>\n * }\n * }`,\n * })\n * ```\n *\n * Skip `defineAugmentation` if you don't care about the catalogue — the\n * `declare module` block alone is enough for runtime + type behaviour.\n *\n * @deprecated Low value in practice: it does nothing at runtime or at\n * the type level — the `declare module` block alone gives you the\n * augmentation, and the generated `.kickjs/types/kick__augmentations.d.ts`\n * catalogue it feeds is documentation-only. Prefer a plain\n * `declare module '@forinda/kickjs' { ... }` block and (optionally) a\n * JSDoc comment on your own interface. `defineAugmentation` and the\n * `kick/augmentations` typegen plugin will be removed in a future major.\n */\nexport function defineAugmentation(name: string, meta?: AugmentationMeta): void {\n // No-op at runtime — `kick typegen` discovers the call statically and\n // emits the augmentation catalogue. Touch the args so esbuild / tsc\n // don't drop the call as dead code under aggressive minification\n // (the marker has to survive the build for static scanners that look\n // at compiled output, e.g. third-party tools).\n void name\n void meta\n}\n","/**\n * HTTP-flavoured wrapper around {@link defineContextDecorator}.\n *\n * The core factory leaves `Ctx` defaulted to {@link ExecutionContext} so the\n * Context Contributor pipeline stays transport-agnostic — future WebSocket,\n * queue, and cron contexts share the same primitive. The cost is that the\n * vast majority of contributors (which are HTTP) have to spell the fourth\n * generic by hand to get `ctx.req` / `ctx.headers` typing:\n *\n * ```ts\n * // Verbose: spell every generic, including the params shape `P`.\n * defineContextDecorator<'tenant', Record<string, never>, Record<string, never>, RequestContext>({\n * key: 'tenant',\n * resolve: (ctx) => ({ id: ctx.req.headers['x-tenant-id'] as string }),\n * })\n * ```\n *\n * `defineHttpContextDecorator` removes that ceremony — the spec is typed\n * against `RequestContext` from the start, so resolvers can read `ctx.req`,\n * `ctx.headers`, `ctx.params`, etc. without a cast or generic dance:\n *\n * ```ts\n * import { defineHttpContextDecorator } from '@forinda/kickjs'\n *\n * const LoadTenant = defineHttpContextDecorator({\n * key: 'tenant',\n * resolve: (ctx) => ({ id: ctx.req.headers['x-tenant-id'] as string }),\n * })\n *\n * // Parameterised — the positional form forces you to also spell `K`\n * // and `D`, which loses automatic `deps` inference. Prefer the curried\n * // `.withParams<P>()` entry point below.\n * const LoadTenantParameterised = defineHttpContextDecorator<\n * 'tenant',\n * Record<string, never>,\n * { source: 'header' | 'subdomain' }\n * >({\n * key: 'tenant',\n * paramDefaults: { source: 'header' },\n * resolve: (ctx, _deps, params) => {\n * // params.source narrows inside `if` branches.\n * },\n * })\n *\n * // Parameterised + deps — only `P` is spelled; `K` and `D` infer from\n * // the spec, so `deps.repo` is fully typed in the resolver.\n * const LoadTenantWithRepo = defineHttpContextDecorator.withParams<{\n * source: 'header' | 'subdomain'\n * }>()({\n * key: 'tenant',\n * deps: { repo: TENANT_REPO },\n * paramDefaults: { source: 'header' },\n * resolve: (ctx, { repo }, params) =>\n * repo.findFor(ctx.req.headers['x-tenant-id'] as string, params.source),\n * })\n * ```\n *\n * Use {@link defineContextDecorator} directly when authoring contributors\n * for non-HTTP transports or when you want to share one contributor across\n * HTTP + WS + queue (the resolver then has to stick to the\n * `ExecutionContext` surface — `ctx.get` / `ctx.set` / `ctx.requestId`).\n */\n\nimport {\n defineContextDecorator,\n type ContextDecorator,\n type ContextDecoratorSpec,\n type ContextMetaKey,\n type DepValue,\n} from '../core/context-decorator'\nimport type { RequestContext } from './context'\n\n/**\n * Curried form returned by {@link DefineHttpContextDecoratorFn.withParams}.\n * Spell only the per-call params shape `P`; `K` and `D` are inferred\n * from the spec, and `Ctx` is locked to `RequestContext`.\n */\nexport interface DefineHttpContextDecoratorWithParams<P extends Record<string, unknown>> {\n <K extends ContextMetaKey, D extends Record<string, DepValue> = Record<string, never>>(\n spec: ContextDecoratorSpec<K, D, P, RequestContext>,\n ): ContextDecorator<K, D, P, RequestContext>\n}\n\n/**\n * Public shape of {@link defineHttpContextDecorator} — the positional\n * call signature plus the curried `.withParams<P>()` helper that fixes\n * partial-inference for the parameterised case.\n */\nexport interface DefineHttpContextDecoratorFn {\n <\n K extends ContextMetaKey,\n D extends Record<string, DepValue> = Record<string, never>,\n P extends Record<string, unknown> = Record<string, never>,\n >(\n spec: ContextDecoratorSpec<K, D, P, RequestContext>,\n ): ContextDecorator<K, D, P, RequestContext>\n\n /**\n * Curried entry point. Spell only `P`; `K` and `D` infer from the\n * spec. `Ctx` is locked to `RequestContext`.\n *\n * ```ts\n * const LoadTenant = defineHttpContextDecorator.withParams<{\n * source: 'header' | 'subdomain'\n * }>()({\n * key: 'tenant',\n * deps: { repo: TENANT_REPO }, // D inferred\n * paramDefaults: { source: 'header' },\n * resolve: (ctx, { repo }, params) => repo.findFor(ctx, params),\n * })\n * ```\n */\n withParams<P extends Record<string, unknown>>(): DefineHttpContextDecoratorWithParams<P>\n}\n\nfunction defineHttpContextDecoratorImpl<\n K extends ContextMetaKey,\n D extends Record<string, DepValue> = Record<string, never>,\n P extends Record<string, unknown> = Record<string, never>,\n>(spec: ContextDecoratorSpec<K, D, P, RequestContext>): ContextDecorator<K, D, P, RequestContext> {\n return defineContextDecorator<K, D, P, RequestContext>(spec)\n}\n\nexport const defineHttpContextDecorator: DefineHttpContextDecoratorFn = Object.freeze(\n Object.assign(defineHttpContextDecoratorImpl, {\n withParams: <P extends Record<string, unknown>>(): DefineHttpContextDecoratorWithParams<P> => {\n return <K extends ContextMetaKey, D extends Record<string, DepValue> = Record<string, never>>(\n spec: ContextDecoratorSpec<K, D, P, RequestContext>,\n ): ContextDecorator<K, D, P, RequestContext> => defineHttpContextDecoratorImpl<K, D, P>(spec)\n },\n }),\n) as DefineHttpContextDecoratorFn\n","import type { Request, Response, NextFunction } from 'express'\nimport { requestStore } from '../request-store'\n\nimport { randomHex } from '../../core/web-crypto'\n\n/**\n * W3C Trace Context header name.\n * @see https://www.w3.org/TR/trace-context/#traceparent-header\n */\nexport const TRACEPARENT_HEADER = 'traceparent'\n\n/** Regex for a valid W3C traceparent: {version}-{trace-id}-{parent-id}-{flags} */\nconst TRACEPARENT_RE = /^([0-9a-f]{2})-([0-9a-f]{32})-([0-9a-f]{16})-([0-9a-f]{2})$/\n\nexport interface TraceContextOptions {\n /**\n * When true, respond with a `traceresponse` header containing the trace ID.\n * Useful for debugging. Default: false.\n */\n propagateResponse?: boolean\n}\n\n/**\n * Parsed W3C trace context fields.\n */\nexport interface TraceContext {\n /** W3C traceparent version (usually '00') */\n version: string\n /** 32-hex-char distributed trace ID */\n traceId: string\n /** 16-hex-char parent span ID */\n parentSpanId: string\n /** 2-hex-char trace flags */\n flags: string\n}\n\n/**\n * Generate a random 32-hex-character trace ID.\n */\nfunction generateTraceId(): string {\n return randomHex(16)\n}\n\n/**\n * Generate a random 16-hex-character span ID.\n */\nfunction generateSpanId(): string {\n return randomHex(8)\n}\n\n/**\n * Parse a W3C traceparent header value.\n * Returns null if the format is invalid.\n */\nexport function parseTraceparent(header: string): TraceContext | null {\n const match = TRACEPARENT_RE.exec(header.trim().toLowerCase())\n if (!match) return null\n\n const version = match[1]\n const traceId = match[2]\n const parentSpanId = match[3]\n const flags = match[4]\n\n // W3C spec: version ff is invalid, all-zero trace-id and parent-id are invalid\n if (\n version === 'ff' ||\n traceId === '00000000000000000000000000000000' ||\n parentSpanId === '0000000000000000'\n ) {\n return null\n }\n\n return { version, traceId, parentSpanId, flags }\n}\n\n/**\n * Middleware that extracts W3C `traceparent` header and stores trace context\n * in the request's AsyncLocalStorage store.\n *\n * If no valid `traceparent` header is present, a new traceId is generated\n * so that every request always has a trace ID available for correlation.\n *\n * Must be mounted **after** `requestScopeMiddleware()` (which creates the store).\n *\n * @example\n * ```ts\n * bootstrap({\n * middlewares: [\n * requestScopeMiddleware(),\n * traceContext(), // extracts or generates traceId\n * requestLogger(),\n * express.json(),\n * ],\n * })\n * ```\n */\nexport function traceContext(options: TraceContextOptions = {}) {\n return (req: Request, res: Response, next: NextFunction) => {\n const store = requestStore.getStore()\n\n const traceparentHeader = req.headers[TRACEPARENT_HEADER]\n const raw = Array.isArray(traceparentHeader) ? traceparentHeader[0] : traceparentHeader\n const parsed = raw ? parseTraceparent(raw) : null\n\n const traceId = parsed?.traceId ?? generateTraceId()\n const spanId = generateSpanId()\n\n // Attach to the request store so logger + downstream code can access it\n if (store) {\n store.values.set('traceId', traceId)\n store.values.set('spanId', spanId)\n if (parsed) {\n store.values.set('parentSpanId', parsed.parentSpanId)\n store.values.set('traceFlags', parsed.flags)\n store.values.set('traceVersion', parsed.version)\n }\n }\n\n // Also expose on req for convenience\n ;(req as any).traceId = traceId\n ;(req as any).spanId = spanId\n\n if (options.propagateResponse) {\n res.setHeader('traceresponse', traceId)\n }\n\n next()\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.mjs","names":[],"sources":["../src/core/define-modules.ts","../src/core/circuit-breaker.ts","../src/core/define-plugin.ts","../src/core/augmentation.ts","../src/http/handler.ts","../src/http/define-http-context-decorator.ts","../src/http/middleware/trace-context.ts"],"sourcesContent":["import type { AppModuleEntry } from './app-module'\n\n/**\n * Chainable registry returned by {@link defineModules}. Extends\n * `Array<AppModuleEntry>` so it drops into `bootstrap({ modules })`\n * unchanged — the framework loader already iterates the array, so a\n * `ModuleList` IS a valid `modules` value with no special handling.\n *\n * The added affordance is `.mount(module)` returning `this` so\n * adopters can build the list fluently:\n *\n * ```ts\n * const modules = defineModules()\n * .mount(HelloModule())\n * .mount(AdminModule())\n *\n * bootstrap({ modules })\n * ```\n *\n * **Why not just use a plain array?** Two reasons. First, the\n * fluent shape reads more naturally for module-list construction —\n * adopters used to `definePlugin().scoped(...)` / `defineAdapter(...)`\n * see the same call-then-call pattern. Second, the registry is the\n * stable extension point: a future `.use(module)` for non-HTTP\n * modules (queues, cron, workers) lands as a method on `ModuleList`\n * without breaking the `Array<AppModuleEntry>` superclass contract.\n */\nexport class ModuleList extends Array<AppModuleEntry> {\n /**\n * Append a module to the list. Returns `this` for chaining.\n *\n * Accepts both class form (`SomeModule extends AppModule`) and\n * `defineModule` factory output — same as the underlying\n * `bootstrap({ modules })` array. The framework loader\n * discriminates `typeof entry === 'function'` at boot.\n */\n mount(module: AppModuleEntry): this {\n this.push(module)\n return this\n }\n}\n\n/**\n * Build a {@link ModuleList} for the application. Optional vararg\n * lets adopters seed the list inline; subsequent `.mount()` calls\n * append.\n *\n * @example\n * ```ts\n * import { bootstrap, defineModules } from '@forinda/kickjs'\n * import { HelloModule } from './modules/hello/hello.module'\n * import { AdminModule } from './modules/admin/admin.module'\n *\n * // Fluent — most common\n * const modules = defineModules()\n * .mount(HelloModule())\n * .mount(AdminModule())\n *\n * // Or seeded inline + chained\n * const modules2 = defineModules(HelloModule()).mount(AdminModule())\n *\n * await bootstrap({ modules })\n * ```\n *\n * The returned value is an `AppModuleEntry[]` subclass — `bootstrap`\n * accepts it directly without any special-casing. For conditional /\n * dynamic registration at bootstrap time (env flags, runtime config,\n * tenant lists), use the `setup(registry)` callback on `bootstrap`\n * instead — both surfaces compose.\n */\nexport function defineModules(...initial: AppModuleEntry[]): ModuleList {\n const list = new ModuleList()\n for (const entry of initial) list.push(entry)\n return list\n}\n","/**\n * Circuit Breaker pattern for external service calls.\n *\n * Protects your application from cascading failures when downstream\n * services are unhealthy by short-circuiting requests after a\n * configurable failure threshold.\n *\n * @example\n * ```ts\n * const breaker = new CircuitBreaker('payment-api', {\n * failureThreshold: 5,\n * resetTimeout: 30_000,\n * })\n *\n * const result = await breaker.execute(() => fetch('https://payment.example.com/charge'))\n * ```\n */\n\nexport type CircuitBreakerState = 'closed' | 'open' | 'half_open'\n\nexport interface CircuitBreakerOptions {\n /** Number of consecutive failures before the circuit opens. */\n failureThreshold: number\n /** Milliseconds to wait before transitioning from OPEN to HALF_OPEN. */\n resetTimeout: number\n /** Max requests allowed in HALF_OPEN state before deciding (default 1). */\n halfOpenMax?: number\n}\n\nexport interface CircuitBreakerStats {\n failures: number\n successes: number\n state: CircuitBreakerState\n lastFailure?: Date\n}\n\n/**\n * Error thrown when the circuit is open and calls are being rejected.\n */\nexport class CircuitOpenError extends Error {\n constructor(public readonly breakerName: string) {\n super(`Circuit breaker \"${breakerName}\" is open — request rejected`)\n this.name = 'CircuitOpenError'\n }\n}\n\nexport class CircuitBreaker {\n private state: CircuitBreakerState = 'closed'\n private failures = 0\n private successes = 0\n private halfOpenAttempts = 0\n private lastFailure?: Date\n private openedAt?: number\n\n private readonly failureThreshold: number\n private readonly resetTimeout: number\n private readonly halfOpenMax: number\n\n constructor(\n public readonly name: string,\n options: CircuitBreakerOptions,\n ) {\n this.failureThreshold = options.failureThreshold\n this.resetTimeout = options.resetTimeout\n this.halfOpenMax = options.halfOpenMax ?? 1\n }\n\n /**\n * Execute an async function through the circuit breaker.\n * Throws `CircuitOpenError` if the circuit is open.\n */\n async execute<T>(fn: () => Promise<T>): Promise<T> {\n this.maybeTransitionToHalfOpen()\n\n if (this.state === 'open') {\n throw new CircuitOpenError(this.name)\n }\n\n if (this.state === 'half_open' && this.halfOpenAttempts >= this.halfOpenMax) {\n throw new CircuitOpenError(this.name)\n }\n\n if (this.state === 'half_open') {\n this.halfOpenAttempts++\n }\n\n try {\n const result = await fn()\n this.onSuccess()\n return result\n } catch (error) {\n this.onFailure()\n throw error\n }\n }\n\n /** Returns the current circuit state. */\n getState(): CircuitBreakerState {\n this.maybeTransitionToHalfOpen()\n return this.state\n }\n\n /** Returns current statistics. */\n getStats(): CircuitBreakerStats {\n this.maybeTransitionToHalfOpen()\n return {\n failures: this.failures,\n successes: this.successes,\n state: this.state,\n ...(this.lastFailure ? { lastFailure: this.lastFailure } : {}),\n }\n }\n\n /** Manually reset the circuit breaker to CLOSED state. */\n reset(): void {\n this.state = 'closed'\n this.failures = 0\n this.successes = 0\n this.halfOpenAttempts = 0\n this.lastFailure = undefined\n this.openedAt = undefined\n }\n\n private onSuccess(): void {\n if (this.state === 'half_open') {\n // Recovery confirmed — close the circuit\n this.state = 'closed'\n this.failures = 0\n this.halfOpenAttempts = 0\n this.openedAt = undefined\n }\n this.successes++\n }\n\n private onFailure(): void {\n this.failures++\n this.lastFailure = new Date()\n\n if (this.state === 'half_open') {\n // Recovery failed — re-open\n this.state = 'open'\n this.openedAt = Date.now()\n this.halfOpenAttempts = 0\n } else if (this.state === 'closed' && this.failures >= this.failureThreshold) {\n this.state = 'open'\n this.openedAt = Date.now()\n }\n }\n\n private maybeTransitionToHalfOpen(): void {\n if (this.state === 'open' && this.openedAt != null) {\n if (Date.now() - this.openedAt >= this.resetTimeout) {\n this.state = 'half_open'\n this.halfOpenAttempts = 0\n }\n }\n }\n}\n","import type { Container } from './container'\nimport type { KickPlugin } from './plugin'\n\n/**\n * Options passed to {@link definePlugin}. Mirrors the spec in\n * `architecture.md` §21.3.1 + §21.2.2 (Phase A \"lite\").\n */\nexport interface DefinePluginOptions<TConfig> {\n /** Stable identity used for logging, `dependsOn` lookups, and `.scoped()` namespacing. */\n name: string\n\n /** Optional plugin version — surfaced to DevTools and `kick add` compatibility checks (Phase B). */\n version?: string\n\n /**\n * Peer-version ranges this plugin needs from the framework or other\n * plugins. Recorded as metadata; runtime enforcement lands in §21.4.4.\n */\n requires?: { kickjs?: string }\n\n /** Default config merged under any caller overrides. */\n defaults?: Partial<TConfig>\n\n /** Builds the underlying {@link KickPlugin} from the resolved config. */\n build(config: TConfig, ctx: BuildContext): Omit<KickPlugin, 'name'>\n}\n\n/**\n * Hook context handed to a plugin/adapter `build` function. `name` is the\n * resolved instance name (the bare definition name for the bare call,\n * or `${defName}:${scope}` for `.scoped()`). `scoped` is the discriminator\n * authors use to namespace DI tokens or resource keys.\n */\nexport interface BuildContext {\n name: string\n scoped: boolean\n}\n\n/**\n * Async-config form of a plugin or adapter — `inject` lists DI tokens to\n * resolve from the container, then `useFactory` produces the config.\n *\n * Plugins resolve this lazily inside `onReady`, so any module/adapter/\n * middleware/contributor a plugin contributes via `build` is **not\n * available** when `.async()` is used. Use the bare/`.scoped()` form for\n * plugins that need to register modules or middleware.\n */\nexport interface PluginAsyncOptions<TConfig> {\n inject?: ReadonlyArray<unknown>\n useFactory(...deps: any[]): TConfig | Promise<TConfig>\n}\n\n/**\n * Factory returned by {@link definePlugin}. Callable form is the singleton\n * (`AuthPlugin(config)`); `.scoped()` and `.async()` are the multi-instance\n * and deferred-config forms.\n */\nexport interface PluginFactory<TConfig> {\n (config?: Partial<TConfig>): KickPlugin\n scoped(scopeName: string, config?: Partial<TConfig>): KickPlugin\n async(opts: PluginAsyncOptions<TConfig>): KickPlugin\n /** Read-only access to the original definition — useful for DevTools introspection. */\n readonly definition: Readonly<DefinePluginOptions<TConfig>>\n}\n\nconst mergeConfig = <TConfig>(\n defaults: Partial<TConfig> = {},\n overrides: Partial<TConfig> = {},\n): TConfig => ({ ...defaults, ...overrides }) as TConfig\n\nconst composeName = (base: string, scope: string): string => `${base}:${scope}`\n\n/**\n * Build a {@link KickPlugin} factory from a typed definition. See\n * `architecture.md` §21.2.2 for the design rationale.\n *\n * @example\n * ```ts\n * const FlagsPlugin = definePlugin<FlagsConfig>({\n * name: 'FlagsPlugin',\n * defaults: { defaultTtl: 60_000 },\n * build(config) {\n * return {\n * register(container) {\n * container.registerInstance(FLAGS, makeProvider(config))\n * },\n * }\n * },\n * })\n *\n * bootstrap({ plugins: [FlagsPlugin({ provider: launchDarkly })] })\n * ```\n */\nexport function definePlugin<TConfig = Record<string, unknown>>(\n options: DefinePluginOptions<TConfig>,\n): PluginFactory<TConfig> {\n const buildSync = (\n instanceName: string,\n scoped: boolean,\n overrides?: Partial<TConfig>,\n ): KickPlugin => {\n const config = mergeConfig(options.defaults, overrides)\n // Mutate `name` on the build result instead of spreading — spread\n // strips prototype methods when `build()` returns a class instance.\n const built = options.build(config, { name: instanceName, scoped }) as KickPlugin\n built.name = instanceName\n return built\n }\n\n const buildAsync = (instanceName: string, opts: PluginAsyncOptions<TConfig>): KickPlugin => {\n let inner: KickPlugin | undefined\n\n const ensureInner = async (container: Container): Promise<KickPlugin> => {\n if (inner) return inner\n const deps = (opts.inject ?? []).map((tok) => container.resolve(tok as never))\n const config = await opts.useFactory(...deps)\n inner = buildSync(instanceName, false, config as Partial<TConfig>)\n return inner\n }\n\n return {\n name: instanceName,\n async onReady(container: Container) {\n const built = await ensureInner(container)\n // Run the inner plugin's register() now that we have the config —\n // late but better than never; `.async()` plugins skip the early\n // module/middleware contribution surface by design.\n built.register?.(container)\n await built.onReady?.(container)\n },\n async shutdown() {\n await inner?.shutdown?.()\n },\n }\n }\n\n const factory = ((config?: Partial<TConfig>) =>\n buildSync(options.name, false, config)) as PluginFactory<TConfig>\n\n factory.scoped = (scopeName: string, config?: Partial<TConfig>) =>\n buildSync(composeName(options.name, scopeName), true, config)\n\n factory.async = (opts: PluginAsyncOptions<TConfig>) => buildAsync(options.name, opts)\n\n Object.defineProperty(factory, 'definition', { value: Object.freeze({ ...options }) })\n\n return factory\n}\n","/**\n * Augmentation registry — runtime no-op + the canonical\n * `KickJsPluginRegistry` interface that `kick typegen` augments.\n *\n * See `architecture.md` §21.2.1 (typegen for `dependsOn`) and §21.3.3\n * (standardized augmentation registry) for the design rationale.\n *\n * @module @forinda/kickjs/core/augmentation\n */\n\n/**\n * Marker interface that lists every plugin/adapter in the project. The\n * keys are the literal `name` field passed to `defineAdapter` /\n * `definePlugin` (or declared on a `class implements AppAdapter`); the\n * values are the kind tag (`'plugin' | 'adapter'`).\n *\n * The framework ships this empty. `kick typegen` augments it from\n * source so `keyof KickJsPluginRegistry` resolves to a string-literal\n * union of every name in scope — and therefore so do `dependsOn`\n * declarations on plugins/adapters.\n */\nexport interface KickJsPluginRegistry {}\n\n/**\n * Resolves to a string-literal union of every registered plugin/adapter\n * name when the project's typegen has populated `KickJsPluginRegistry`,\n * or to `string` when the registry is empty (no typegen pass yet).\n *\n * Falling back to `string` keeps fresh projects compiling — the typegen\n * narrowing is a progressive enhancement, not a hard prerequisite.\n */\nexport type KickJsPluginName = keyof KickJsPluginRegistry extends never\n ? string\n : keyof KickJsPluginRegistry & string\n\n/**\n * Metadata attached to a `defineAugmentation` call. The fields are\n * documentation-only — `kick typegen` surfaces them in the generated\n * `.kickjs/types/kick__augmentations.d.ts` so adopters can browse every\n * augmentable interface from one place.\n *\n * `description` and `example` may both be multi-line — typegen preserves\n * line breaks when rendering them as JSDoc. There is no upper limit on\n * the example size; entire shape definitions or worked snippets are fine.\n */\nexport interface AugmentationMeta {\n /**\n * Free-form description of what the augmentation customises. May be\n * multi-line — newlines are preserved in the generated JSDoc.\n */\n description?: string\n /**\n * TS snippet showing a typical shape. May be multi-line; rendered\n * inside a fenced code block in the generated catalogue. Use this\n * for anything from `'{ foo: string }'` up to a full interface body\n * — typegen no longer flattens newlines.\n */\n example?: string\n}\n\n/**\n * @deprecated Since 7.2. This was tooling for a time when Context\n * Contributors were still settling — a catalogue so adopters could discover\n * which interfaces were augmentable. Contributors are a stable, typed API now\n * (`defineContextDecorator`, `ContextMeta`), and the catalogue adds a second\n * call that must be kept in step with the `declare module` block for no\n * type-level benefit.\n *\n * Nothing breaks: `kick typegen` still discovers the call and still writes the\n * catalogue. Just drop it — the `declare module '@forinda/kickjs'` block alone\n * gives you the types, which is all it ever gave you.\n *\n * What it actually emits, for the record: one empty marker interface per call\n * in `.kickjs/types/kick__augmentations.d.ts` —\n *\n * ```ts\n * // from defineAugmentation('ContextMeta', { description, example })\n * export interface ContextMetaAugmentation {}\n * ```\n *\n * with your `description` / `example` rendered as its JSDoc and a `@see` back\n * to the call site. The interface is empty and unreferenced; nothing consumes\n * it at type level.\n *\n * Advertise an augmentable interface so `kick typegen` can list it in\n * `.kickjs/types/kick__augmentations.d.ts` for project-wide discovery.\n *\n * **This function is a runtime AND type-level no-op.** It does NOT\n * augment the interface for TypeScript. The actual augmentation is\n * the `declare module` block — `defineAugmentation` only adds an\n * entry to the typegen catalogue (`.kickjs/types/kick__augmentations.d.ts`)\n * so other contributors / adopters can find the interface and know its\n * expected shape.\n *\n * Both calls are needed:\n *\n * ```ts\n * import { defineAugmentation } from '@forinda/kickjs'\n *\n * // (1) The actual TS augmentation — what `ctx.get('tenant')` reads.\n * declare module '@forinda/kickjs' {\n * interface ContextMeta {\n * tenant: { id: string; name: string }\n * }\n * }\n *\n * // (2) Catalogue entry — what `kick typegen` lists in\n * // `.kickjs/types/kick__augmentations.d.ts` for browseability.\n * defineAugmentation('ContextMeta', {\n * description: 'Tenant resolved from x-tenant-id by TenantAdapter',\n * example: `{\n * tenant: {\n * id: string\n * name: string\n * plan: 'free' | 'pro' | 'enterprise'\n * featureFlags: Record<string, boolean>\n * }\n * }`,\n * })\n * ```\n *\n * Skip `defineAugmentation` if you don't care about the catalogue — the\n * `declare module` block alone is enough for runtime + type behaviour.\n *\n * @deprecated Low value in practice: it does nothing at runtime or at\n * the type level — the `declare module` block alone gives you the\n * augmentation, and the generated `.kickjs/types/kick__augmentations.d.ts`\n * catalogue it feeds is documentation-only. Prefer a plain\n * `declare module '@forinda/kickjs' { ... }` block and (optionally) a\n * JSDoc comment on your own interface. `defineAugmentation` and the\n * `kick/augmentations` typegen plugin will be removed in a future major.\n */\nexport function defineAugmentation(name: string, meta?: AugmentationMeta): void {\n // No-op at runtime — `kick typegen` discovers the call statically and\n // emits the augmentation catalogue. Touch the args so esbuild / tsc\n // don't drop the call as dead code under aggressive minification\n // (the marker has to survive the build for static scanners that look\n // at compiled output, e.g. third-party tools).\n void name\n void meta\n}\n","/**\n * The app as a request handler, with no listening server of its own — for\n * platforms that hand you requests instead of a port: Netlify Functions,\n * Vercel Functions, and any other serverless or embedding host.\n *\n * @module @forinda/kickjs/http/handler\n */\nimport http, { type IncomingMessage, type ServerResponse } from 'node:http'\nimport type { AddressInfo } from 'node:net'\nimport { Application, type ApplicationOptions } from './application'\n\n/** A KickJS app exposed as request handlers. See {@link createHandler}. */\nexport interface KickHandler {\n /**\n * Web-standard handler: `fetch(Request) → Response`. Netlify Functions,\n * Vercel's fetch export, and anything else that speaks `Request`.\n */\n fetch(request: Request): Promise<Response>\n /** Node handler: `(req, res)`. Vercel Node functions, `http.createServer`. */\n node(req: IncomingMessage, res: ServerResponse): Promise<void>\n /** Set the app up now instead of on the first request (warm-up). */\n ready(): Promise<Application>\n /** Shut adapters down and stop the internal forwarding server, if one started. */\n close(): Promise<void>\n}\n\n/**\n * Request headers that describe one hop, not the request. Forwarding them\n * makes Node's `fetch` reject the request (\"fetch failed\") or misframe it —\n * `content-length` is recomputed from the buffered body.\n */\nconst HOP_BY_HOP_REQUEST = [\n 'connection',\n 'keep-alive',\n 'proxy-connection',\n 'transfer-encoding',\n 'upgrade',\n 'te',\n 'trailer',\n 'host',\n 'content-length',\n]\n\nconst HOP_BY_HOP_RESPONSE = [\n 'connection',\n 'keep-alive',\n 'proxy-connection',\n 'transfer-encoding',\n 'upgrade',\n 'trailer',\n 'content-encoding',\n 'content-length',\n]\n\n/**\n * Build a KickJS app as request handlers instead of a listening server.\n *\n * Takes the same options as `bootstrap()`. The app is set up once per process\n * (per function instance), lazily on the first request, and reused after that.\n * Nothing listens on a port, `afterStart` does not run, and no process signal\n * handlers are registered — the platform owns the process.\n *\n * `fetch` uses the runtime's own fetch when it has one (the h3 v2 runtime).\n * Runtimes built on Node request/response objects — Express, the default —\n * are served through a server bound to `127.0.0.1` on a random port inside the\n * same process, started on first use: the `Request` is forwarded to it and its\n * response returned. Request bodies are buffered on that path; response bodies\n * stream. Adapters that rewrite the `res` prototype (Express does) make a\n * direct Request→`res` bridge unreliable, which is why this forwards instead.\n *\n * One handler per process: the DI container is process-wide.\n *\n * @example\n * ```ts\n * // server/src/serverless.ts\n * import 'reflect-metadata'\n * import './config'\n * import { createHandler } from '@forinda/kickjs'\n * import { modules } from './modules'\n *\n * export const handler = createHandler({ modules })\n *\n * // netlify/functions/api.mjs\n * export default (request) => handler.fetch(request)\n * export const config = { path: '/api/*' }\n * ```\n */\nexport function createHandler(options: ApplicationOptions): KickHandler {\n let app: Promise<Application> | undefined\n let forwarding: Promise<{ origin: string; server: http.Server }> | undefined\n\n const ready = (): Promise<Application> => {\n app ??= (async () => {\n const instance = new Application(options)\n try {\n await instance.startWithoutServer()\n } catch (err) {\n // A failed setup (a database that was briefly down, say) is retried on\n // the next request. Shut this attempt down first so its adapters don't\n // stay live next to the retry's.\n app = undefined\n await instance.shutdown().catch(() => {})\n throw err\n }\n return instance\n })()\n return app\n }\n\n const forwardingServer = (instance: Application) => {\n forwarding ??= new Promise<{ origin: string; server: http.Server }>((resolve, reject) => {\n const server = http.createServer((req, res) => instance.handle(req, res))\n server.once('error', reject)\n server.listen(0, '127.0.0.1', () => {\n // Never keep a function instance alive on its own account.\n server.unref()\n resolve({ origin: `http://127.0.0.1:${(server.address() as AddressInfo).port}`, server })\n })\n }).catch((err) => {\n forwarding = undefined\n throw err\n })\n return forwarding\n }\n\n const forward = async (instance: Application, request: Request): Promise<Response> => {\n const { origin } = await forwardingServer(instance)\n const url = new URL(request.url)\n\n const headers = new Headers(request.headers)\n for (const name of HOP_BY_HOP_REQUEST) headers.delete(name)\n // The forwarded request arrives from 127.0.0.1; keep what the platform saw.\n if (!headers.has('x-forwarded-host')) headers.set('x-forwarded-host', url.host)\n if (!headers.has('x-forwarded-proto'))\n headers.set('x-forwarded-proto', url.protocol.slice(0, -1))\n\n // Buffered: a body-less POST arrives as an empty stream, which Node's fetch\n // rejects, and serverless platforms buffer request bodies anyway.\n const body =\n request.method === 'GET' || request.method === 'HEAD'\n ? undefined\n : await request.arrayBuffer()\n\n const upstream = await fetch(origin + url.pathname + url.search, {\n method: request.method,\n headers,\n body: body && body.byteLength > 0 ? body : undefined,\n redirect: 'manual',\n })\n\n // Node's fetch has already decoded a compressed body, so the encoding and\n // length headers no longer describe what is being returned. Connection\n // headers describe the loopback hop.\n const responseHeaders = new Headers(upstream.headers)\n const named = responseHeaders.get('connection')?.split(',') ?? []\n for (const name of [...HOP_BY_HOP_RESPONSE, ...named]) responseHeaders.delete(name.trim())\n return new Response(upstream.body, {\n status: upstream.status,\n statusText: upstream.statusText,\n headers: responseHeaders,\n })\n }\n\n return {\n ready,\n\n async fetch(request) {\n const instance = await ready()\n const runtimeApp = instance.getRuntimeApp() as { fetch?: (request: Request) => unknown }\n if (typeof runtimeApp?.fetch === 'function') {\n return (await runtimeApp.fetch(request)) as Response\n }\n return forward(instance, request)\n },\n\n async node(req, res) {\n const instance = await ready()\n instance.handle(req, res)\n },\n\n async close() {\n const started = await forwarding?.catch(() => undefined)\n forwarding = undefined\n if (started) await new Promise<void>((resolve) => started.server.close(() => resolve()))\n const current = app\n app = undefined\n if (current) await (await current).shutdown()\n },\n }\n}\n","/**\n * HTTP-flavoured wrapper around {@link defineContextDecorator}.\n *\n * The core factory leaves `Ctx` defaulted to {@link ExecutionContext} so the\n * Context Contributor pipeline stays transport-agnostic — future WebSocket,\n * queue, and cron contexts share the same primitive. The cost is that the\n * vast majority of contributors (which are HTTP) have to spell the fourth\n * generic by hand to get `ctx.req` / `ctx.headers` typing:\n *\n * ```ts\n * // Verbose: spell every generic, including the params shape `P`.\n * defineContextDecorator<'tenant', Record<string, never>, Record<string, never>, RequestContext>({\n * key: 'tenant',\n * resolve: (ctx) => ({ id: ctx.req.headers['x-tenant-id'] as string }),\n * })\n * ```\n *\n * `defineHttpContextDecorator` removes that ceremony — the spec is typed\n * against `RequestContext` from the start, so resolvers can read `ctx.req`,\n * `ctx.headers`, `ctx.params`, etc. without a cast or generic dance:\n *\n * ```ts\n * import { defineHttpContextDecorator } from '@forinda/kickjs'\n *\n * const LoadTenant = defineHttpContextDecorator({\n * key: 'tenant',\n * resolve: (ctx) => ({ id: ctx.req.headers['x-tenant-id'] as string }),\n * })\n *\n * // Parameterised — the positional form forces you to also spell `K`\n * // and `D`, which loses automatic `deps` inference. Prefer the curried\n * // `.withParams<P>()` entry point below.\n * const LoadTenantParameterised = defineHttpContextDecorator<\n * 'tenant',\n * Record<string, never>,\n * { source: 'header' | 'subdomain' }\n * >({\n * key: 'tenant',\n * paramDefaults: { source: 'header' },\n * resolve: (ctx, _deps, params) => {\n * // params.source narrows inside `if` branches.\n * },\n * })\n *\n * // Parameterised + deps — only `P` is spelled; `K` and `D` infer from\n * // the spec, so `deps.repo` is fully typed in the resolver.\n * const LoadTenantWithRepo = defineHttpContextDecorator.withParams<{\n * source: 'header' | 'subdomain'\n * }>()({\n * key: 'tenant',\n * deps: { repo: TENANT_REPO },\n * paramDefaults: { source: 'header' },\n * resolve: (ctx, { repo }, params) =>\n * repo.findFor(ctx.req.headers['x-tenant-id'] as string, params.source),\n * })\n * ```\n *\n * Use {@link defineContextDecorator} directly when authoring contributors\n * for non-HTTP transports or when you want to share one contributor across\n * HTTP + WS + queue (the resolver then has to stick to the\n * `ExecutionContext` surface — `ctx.get` / `ctx.set` / `ctx.requestId`).\n */\n\nimport {\n defineContextDecorator,\n type ContextDecorator,\n type ContextDecoratorSpec,\n type ContextMetaKey,\n type DepValue,\n} from '../core/context-decorator'\nimport type { RequestContext } from './context'\n\n/**\n * Curried form returned by {@link DefineHttpContextDecoratorFn.withParams}.\n * Spell only the per-call params shape `P`; `K` and `D` are inferred\n * from the spec, and `Ctx` is locked to `RequestContext`.\n */\nexport interface DefineHttpContextDecoratorWithParams<P extends Record<string, unknown>> {\n <K extends ContextMetaKey, D extends Record<string, DepValue> = Record<string, never>>(\n spec: ContextDecoratorSpec<K, D, P, RequestContext>,\n ): ContextDecorator<K, D, P, RequestContext>\n}\n\n/**\n * Public shape of {@link defineHttpContextDecorator} — the positional\n * call signature plus the curried `.withParams<P>()` helper that fixes\n * partial-inference for the parameterised case.\n */\nexport interface DefineHttpContextDecoratorFn {\n <\n K extends ContextMetaKey,\n D extends Record<string, DepValue> = Record<string, never>,\n P extends Record<string, unknown> = Record<string, never>,\n >(\n spec: ContextDecoratorSpec<K, D, P, RequestContext>,\n ): ContextDecorator<K, D, P, RequestContext>\n\n /**\n * Curried entry point. Spell only `P`; `K` and `D` infer from the\n * spec. `Ctx` is locked to `RequestContext`.\n *\n * ```ts\n * const LoadTenant = defineHttpContextDecorator.withParams<{\n * source: 'header' | 'subdomain'\n * }>()({\n * key: 'tenant',\n * deps: { repo: TENANT_REPO }, // D inferred\n * paramDefaults: { source: 'header' },\n * resolve: (ctx, { repo }, params) => repo.findFor(ctx, params),\n * })\n * ```\n */\n withParams<P extends Record<string, unknown>>(): DefineHttpContextDecoratorWithParams<P>\n}\n\nfunction defineHttpContextDecoratorImpl<\n K extends ContextMetaKey,\n D extends Record<string, DepValue> = Record<string, never>,\n P extends Record<string, unknown> = Record<string, never>,\n>(spec: ContextDecoratorSpec<K, D, P, RequestContext>): ContextDecorator<K, D, P, RequestContext> {\n return defineContextDecorator<K, D, P, RequestContext>(spec)\n}\n\nexport const defineHttpContextDecorator: DefineHttpContextDecoratorFn = Object.freeze(\n Object.assign(defineHttpContextDecoratorImpl, {\n withParams: <P extends Record<string, unknown>>(): DefineHttpContextDecoratorWithParams<P> => {\n return <K extends ContextMetaKey, D extends Record<string, DepValue> = Record<string, never>>(\n spec: ContextDecoratorSpec<K, D, P, RequestContext>,\n ): ContextDecorator<K, D, P, RequestContext> => defineHttpContextDecoratorImpl<K, D, P>(spec)\n },\n }),\n) as DefineHttpContextDecoratorFn\n","import type { Request, Response, NextFunction } from 'express'\nimport { requestStore } from '../request-store'\n\nimport { randomHex } from '../../core/web-crypto'\n\n/**\n * W3C Trace Context header name.\n * @see https://www.w3.org/TR/trace-context/#traceparent-header\n */\nexport const TRACEPARENT_HEADER = 'traceparent'\n\n/** Regex for a valid W3C traceparent: {version}-{trace-id}-{parent-id}-{flags} */\nconst TRACEPARENT_RE = /^([0-9a-f]{2})-([0-9a-f]{32})-([0-9a-f]{16})-([0-9a-f]{2})$/\n\nexport interface TraceContextOptions {\n /**\n * When true, respond with a `traceresponse` header containing the trace ID.\n * Useful for debugging. Default: false.\n */\n propagateResponse?: boolean\n}\n\n/**\n * Parsed W3C trace context fields.\n */\nexport interface TraceContext {\n /** W3C traceparent version (usually '00') */\n version: string\n /** 32-hex-char distributed trace ID */\n traceId: string\n /** 16-hex-char parent span ID */\n parentSpanId: string\n /** 2-hex-char trace flags */\n flags: string\n}\n\n/**\n * Generate a random 32-hex-character trace ID.\n */\nfunction generateTraceId(): string {\n return randomHex(16)\n}\n\n/**\n * Generate a random 16-hex-character span ID.\n */\nfunction generateSpanId(): string {\n return randomHex(8)\n}\n\n/**\n * Parse a W3C traceparent header value.\n * Returns null if the format is invalid.\n */\nexport function parseTraceparent(header: string): TraceContext | null {\n const match = TRACEPARENT_RE.exec(header.trim().toLowerCase())\n if (!match) return null\n\n const version = match[1]\n const traceId = match[2]\n const parentSpanId = match[3]\n const flags = match[4]\n\n // W3C spec: version ff is invalid, all-zero trace-id and parent-id are invalid\n if (\n version === 'ff' ||\n traceId === '00000000000000000000000000000000' ||\n parentSpanId === '0000000000000000'\n ) {\n return null\n }\n\n return { version, traceId, parentSpanId, flags }\n}\n\n/**\n * Middleware that extracts W3C `traceparent` header and stores trace context\n * in the request's AsyncLocalStorage store.\n *\n * If no valid `traceparent` header is present, a new traceId is generated\n * so that every request always has a trace ID available for correlation.\n *\n * Must be mounted **after** `requestScopeMiddleware()` (which creates the store).\n *\n * @example\n * ```ts\n * bootstrap({\n * middlewares: [\n * requestScopeMiddleware(),\n * traceContext(), // extracts or generates traceId\n * requestLogger(),\n * express.json(),\n * ],\n * })\n * ```\n */\nexport function traceContext(options: TraceContextOptions = {}) {\n return (req: Request, res: Response, next: NextFunction) => {\n const store = requestStore.getStore()\n\n const traceparentHeader = req.headers[TRACEPARENT_HEADER]\n const raw = Array.isArray(traceparentHeader) ? traceparentHeader[0] : traceparentHeader\n const parsed = raw ? parseTraceparent(raw) : null\n\n const traceId = parsed?.traceId ?? generateTraceId()\n const spanId = generateSpanId()\n\n // Attach to the request store so logger + downstream code can access it\n if (store) {\n store.values.set('traceId', traceId)\n store.values.set('spanId', spanId)\n if (parsed) {\n store.values.set('parentSpanId', parsed.parentSpanId)\n store.values.set('traceFlags', parsed.flags)\n store.values.set('traceVersion', parsed.version)\n }\n }\n\n // Also expose on req for convenience\n ;(req as any).traceId = traceId\n ;(req as any).spanId = spanId\n\n if (options.propagateResponse) {\n res.setHeader('traceresponse', traceId)\n }\n\n next()\n }\n}\n"],"mappings":"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"}