@forinda/kickjs 5.16.0 → 5.18.0-alpha.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.
- package/dist/adapter-D_uzU-QA.d.mts +2121 -0
- package/dist/adapter-D_uzU-QA.d.mts.map +1 -0
- package/dist/{context-decorator-DDZ30BIW.d.mts → app-module-CuAS6hJC.d.mts} +184 -4
- package/dist/app-module-CuAS6hJC.d.mts.map +1 -0
- package/dist/application-BU5N6o_M.mjs +12 -0
- package/dist/application-BU5N6o_M.mjs.map +1 -0
- package/dist/{application-CAnpDQ8d.d.mts → application-pbx53JnX.d.mts} +31 -5
- package/dist/application-pbx53JnX.d.mts.map +1 -0
- package/dist/{bootstrap-CFK2aAjA.mjs → bootstrap-CFog4v_L.mjs} +3 -3
- package/dist/{bootstrap-CFK2aAjA.mjs.map → bootstrap-CFog4v_L.mjs.map} +1 -1
- package/dist/{bootstrap-8DDzBjhx.d.mts → bootstrap-DzfBj6Ja.d.mts} +2 -2
- package/dist/{bootstrap-8DDzBjhx.d.mts.map → bootstrap-DzfBj6Ja.d.mts.map} +1 -1
- package/dist/config/index.mjs +2 -2
- package/dist/{config-BW5taOVX.mjs → config-Di3HlRTS.mjs} +3 -3
- package/dist/{config-BW5taOVX.mjs.map → config-Di3HlRTS.mjs.map} +1 -1
- package/dist/{container-D1gfs6__.mjs → container-BiGimG12.mjs} +3 -3
- package/dist/{container-D1gfs6__.mjs.map → container-BiGimG12.mjs.map} +1 -1
- package/dist/context-leZajQAj.mjs +12 -0
- package/dist/context-leZajQAj.mjs.map +1 -0
- package/dist/core/adapter.d.mts +1 -1
- package/dist/core/adapter.mjs +1 -1
- package/dist/core/app-module.d.mts +1 -1
- package/dist/core/app-module.mjs +1 -1
- package/dist/core/cache.mjs +1 -1
- package/dist/core/container.mjs +2 -2
- package/dist/core/cron.mjs +2 -2
- package/dist/core/decorators.mjs +2 -2
- package/dist/core/errors.d.mts +1 -1
- package/dist/core/errors.mjs +2 -2
- package/dist/core/errors.mjs.map +1 -1
- package/dist/core/interfaces.mjs +1 -1
- package/dist/core/logger.mjs +1 -1
- package/dist/core/path.mjs +1 -1
- package/dist/core/plugin.d.mts +1 -1
- package/dist/core/plugin.mjs +1 -1
- package/dist/core/reactivity.mjs +1 -1
- package/dist/{core-Db2uyqtM.mjs → core-Y_xSqZ7v.mjs} +3 -3
- package/dist/{core-Db2uyqtM.mjs.map → core-Y_xSqZ7v.mjs.map} +1 -1
- package/dist/{env-nwsfCpdy.mjs → env-BoMBrGWs.mjs} +3 -3
- package/dist/{env-nwsfCpdy.mjs.map → env-BoMBrGWs.mjs.map} +1 -1
- package/dist/{errors-CRCTjEUK.d.mts → errors-n0H96eEz.d.mts} +3 -1
- package/dist/errors-n0H96eEz.d.mts.map +1 -0
- package/dist/http/application.d.mts +1 -1
- package/dist/http/application.mjs +2 -2
- package/dist/http/bootstrap.d.mts +1 -1
- package/dist/http/bootstrap.mjs +2 -2
- package/dist/http/context.d.mts +2 -2
- package/dist/http/context.mjs +2 -2
- package/dist/http/middleware/cors.mjs +1 -1
- package/dist/http/middleware/csrf.mjs +1 -1
- package/dist/http/middleware/error-handler.mjs +2 -2
- package/dist/http/middleware/helmet.mjs +1 -1
- package/dist/http/middleware/rate-limit.mjs +1 -1
- package/dist/http/middleware/request-id.mjs +1 -1
- package/dist/http/middleware/request-logger.mjs +2 -2
- package/dist/http/middleware/session.mjs +1 -1
- package/dist/http/middleware/spa.d.mts +1 -1
- package/dist/http/middleware/spa.mjs +2 -2
- package/dist/http/middleware/upload.d.mts +2 -2
- package/dist/http/middleware/upload.mjs +3 -3
- package/dist/http/middleware/upload.mjs.map +1 -1
- package/dist/http/middleware/validate.mjs +2 -2
- package/dist/http/middleware/views.d.mts +1 -1
- package/dist/http/middleware/views.mjs +2 -2
- package/dist/http/query/index.d.mts +2 -2
- package/dist/http/query/index.mjs +2 -2
- package/dist/http/router-builder.d.mts +2 -2
- package/dist/http/router-builder.mjs +2 -2
- package/dist/http/router-builder.mjs.map +1 -1
- package/dist/http/runtimes/fastify.d.mts +66 -0
- package/dist/http/runtimes/fastify.d.mts.map +1 -0
- package/dist/http/runtimes/fastify.mjs +13 -0
- package/dist/http/runtimes/fastify.mjs.map +1 -0
- package/dist/http/runtimes/h3.d.mts +29 -0
- package/dist/http/runtimes/h3.d.mts.map +1 -0
- package/dist/http/runtimes/h3.mjs +12 -0
- package/dist/http/runtimes/h3.mjs.map +1 -0
- package/dist/{index-kEmG8nWU.d.mts → index-BtWJ9SLP.d.mts} +53 -7
- package/dist/{index-kEmG8nWU.d.mts.map → index-BtWJ9SLP.d.mts.map} +1 -1
- package/dist/index.d.mts +12 -17
- package/dist/index.mjs +2 -2
- package/dist/index.mjs.map +1 -1
- package/dist/{metadata-Cll3P0N0.mjs → metadata-Pvgc-K8a.mjs} +2 -2
- package/dist/{metadata-Cll3P0N0.mjs.map → metadata-Pvgc-K8a.mjs.map} +1 -1
- package/dist/query-B3PhfU6M.mjs +12 -0
- package/dist/query-B3PhfU6M.mjs.map +1 -0
- package/dist/request-scope-BaM8_e_8.mjs +12 -0
- package/dist/request-scope-BaM8_e_8.mjs.map +1 -0
- package/dist/router-builder-Bh3qSiDz.d.mts +39 -0
- package/dist/router-builder-Bh3qSiDz.d.mts.map +1 -0
- package/dist/{spa-IRFC2eMN.d.mts → spa-BdvZFXJz.d.mts} +3 -2
- package/dist/spa-BdvZFXJz.d.mts.map +1 -0
- package/dist/{upload-D6edAELH.d.mts → upload-Bc_rBRtE.d.mts} +37 -2
- package/dist/upload-Bc_rBRtE.d.mts.map +1 -0
- package/dist/{views-BCl-mETX.d.mts → views-DcTVDiOh.d.mts} +31 -7
- package/dist/views-DcTVDiOh.d.mts.map +1 -0
- package/package.json +29 -1
- package/dist/adapter-CkpcZwzZ.d.mts +0 -407
- package/dist/adapter-CkpcZwzZ.d.mts.map +0 -1
- package/dist/app-module-BTzb-Vd6.d.mts +0 -92
- package/dist/app-module-BTzb-Vd6.d.mts.map +0 -1
- package/dist/application-CAnpDQ8d.d.mts.map +0 -1
- package/dist/application-DnnqoDWx.mjs +0 -12
- package/dist/application-DnnqoDWx.mjs.map +0 -1
- package/dist/context-Dnt2Di7p.d.mts +0 -434
- package/dist/context-Dnt2Di7p.d.mts.map +0 -1
- package/dist/context-MD7Mc_o_.mjs +0 -12
- package/dist/context-MD7Mc_o_.mjs.map +0 -1
- package/dist/context-decorator-DDZ30BIW.d.mts.map +0 -1
- package/dist/errors-CRCTjEUK.d.mts.map +0 -1
- package/dist/execution-context-B4cfhivz.d.mts +0 -98
- package/dist/execution-context-B4cfhivz.d.mts.map +0 -1
- package/dist/index-frSEHiL_.d.mts +0 -796
- package/dist/index-frSEHiL_.d.mts.map +0 -1
- package/dist/plugin-BQCn6zyj.d.mts +0 -260
- package/dist/plugin-BQCn6zyj.d.mts.map +0 -1
- package/dist/query-D-FiLfmd.mjs +0 -12
- package/dist/query-D-FiLfmd.mjs.map +0 -1
- package/dist/router-builder-oQpcQMWl.d.mts +0 -31
- package/dist/router-builder-oQpcQMWl.d.mts.map +0 -1
- package/dist/spa-IRFC2eMN.d.mts.map +0 -1
- package/dist/upload-D6edAELH.d.mts.map +0 -1
- package/dist/views-BCl-mETX.d.mts.map +0 -1
package/dist/core/cache.mjs
CHANGED
package/dist/core/container.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* @forinda/kickjs v5.
|
|
2
|
+
* @forinda/kickjs v5.18.0-alpha.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 tokenName,t as Container}from"../container-
|
|
11
|
+
import{n as tokenName,t as Container}from"../container-BiGimG12.mjs";export{Container,tokenName};
|
package/dist/core/cron.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* @forinda/kickjs v5.
|
|
2
|
+
* @forinda/kickjs v5.18.0-alpha.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{c as pushClassMeta,t as getClassMeta}from"../metadata-
|
|
11
|
+
import{c as pushClassMeta,t as getClassMeta}from"../metadata-Pvgc-K8a.mjs";const CRON_META=`kick/cron`;function Cron(expression,options){return(target,propertyKey)=>{pushClassMeta(CRON_META,target.constructor,{expression,handlerName:propertyKey,description:options?.description,timezone:options?.timezone,runOnInit:options?.runOnInit})}}function getCronJobs(target){return getClassMeta(CRON_META,target,[])}export{CRON_META,Cron,getCronJobs};
|
|
12
12
|
//# sourceMappingURL=cron.mjs.map
|
package/dist/core/decorators.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* @forinda/kickjs v5.
|
|
2
|
+
* @forinda/kickjs v5.18.0-alpha.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{t as Container}from"../container-
|
|
11
|
+
import{t as Container}from"../container-BiGimG12.mjs";import{METADATA}from"./interfaces.mjs";import{c as pushClassMeta,d as setInMetaMap,f as setInMetaRecord,l as pushMethodMeta,p as setMethodMeta,u as setClassMeta}from"../metadata-Pvgc-K8a.mjs";import"reflect-metadata";const pendingRegistrations=[],allRegistrations=new Map;let containerRef=null;function flushPending(container){containerRef=container;for(let{target,scope}of pendingRegistrations)container.has(target)||container.register(target,target,scope);pendingRegistrations.length=0}Container._onReady=flushPending,Container._onReset=container=>{containerRef=container;for(let[,{target,scope}]of allRegistrations)container.has(target)||container.register(target,target,scope)};function registerInContainer(target,scope){setClassMeta(METADATA.INJECTABLE,!0,target),setClassMeta(METADATA.SCOPE,scope,target);let name=target.name||String(target);allRegistrations.set(name,{target,scope}),containerRef?containerRef.has(target)||containerRef.register(target,target,scope):pendingRegistrations.push({target,scope})}function Injectable(options){return target=>{setClassMeta(METADATA.CLASS_KIND,`injectable`,target),registerInContainer(target,options?.scope??`singleton`)}}function Service(options){return target=>{setClassMeta(METADATA.CLASS_KIND,`service`,target),registerInContainer(target,options?.scope??`singleton`)}}function Component(options){return target=>{setClassMeta(METADATA.CLASS_KIND,`component`,target),registerInContainer(target,options?.scope??`singleton`)}}function Repository(options){return target=>{setClassMeta(METADATA.CLASS_KIND,`repository`,target),registerInContainer(target,options?.scope??`singleton`)}}function Controller(){return target=>{setClassMeta(METADATA.CLASS_KIND,`controller`,target),registerInContainer(target,`singleton`)}}function PostConstruct(){return(target,propertyKey)=>{setClassMeta(METADATA.POST_CONSTRUCT,propertyKey,target)}}function applyInjection(token,target,propertyKey,parameterIndex){if(typeof parameterIndex==`number`){setInMetaRecord(METADATA.INJECT,target,parameterIndex,token);return}propertyKey!=null&&setInMetaMap(METADATA.AUTOWIRED,target,propertyKey,token)}function Autowired(token){return((target,propertyKey,parameterIndex)=>{applyInjection(token,target,propertyKey,parameterIndex)})}function Inject(token){return((target,propertyKey,parameterIndex)=>{applyInjection(token,target,propertyKey,parameterIndex)})}function Value(envKey,defaultValue){return(target,propertyKey)=>{setInMetaMap(METADATA.VALUE,target,propertyKey,{envKey,defaultValue})}}function Asset(assetKey){return(target,propertyKey)=>{setInMetaMap(METADATA.ASSET,target,propertyKey,{assetKey})}}function createRouteDecorator(method){return(path,validation)=>(target,propertyKey)=>{pushClassMeta(METADATA.ROUTES,target.constructor,{method,path:path||`/`,handlerName:propertyKey,validation})}}const Get=createRouteDecorator(`GET`),Post=createRouteDecorator(`POST`),Put=createRouteDecorator(`PUT`),Delete=createRouteDecorator(`DELETE`),Patch=createRouteDecorator(`PATCH`);function normalizeApiQueryParamsConfig(config){return`columns`in config&&config.columns&&typeof config.columns==`object`?{filterable:Object.keys(config.columns),sortable:config.sortable?Object.keys(config.sortable):void 0,searchable:config.searchColumns?config.searchColumns.map(col=>col?.name??``).filter(Boolean):void 0}:config}function ApiQueryParams(config){return(target,propertyKey)=>{let normalized=normalizeApiQueryParamsConfig(config);setMethodMeta(METADATA.QUERY_PARAMS,normalized,target.constructor,propertyKey)}}function Middleware(...handlers){return(target,propertyKey)=>{propertyKey?pushMethodMeta(METADATA.METHOD_MIDDLEWARES,target.constructor,propertyKey,...handlers):pushClassMeta(METADATA.CLASS_MIDDLEWARES,target,...handlers)}}function FileUpload(config){return(target,propertyKey)=>{setMethodMeta(METADATA.FILE_UPLOAD,config,target.constructor,propertyKey)}}function attachBuilder(target){setClassMeta(METADATA.BUILDER,!0,target),target.builder=function(){let props={},proxy=new Proxy({},{get(_,key){return key===`build`?()=>Object.assign(new target,props):value=>(props[key]=value,proxy)}});return proxy}}function Builder(target){attachBuilder(target)}function withBuilder(ctor){return attachBuilder(ctor),ctor}export{ApiQueryParams,Asset,Autowired,Builder,Component,Controller,Delete,FileUpload,Get,Inject,Injectable,Middleware,Patch,Post,PostConstruct,Put,Repository,Service,Value,normalizeApiQueryParamsConfig,withBuilder};
|
|
12
12
|
//# sourceMappingURL=decorators.mjs.map
|
package/dist/core/errors.d.mts
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
|
|
2
|
-
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-
|
|
2
|
+
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-n0H96eEz.mjs";
|
|
3
3
|
export { HttpException, HttpStatus, HttpStatusCode, ProblemDetails, ProblemException, Problems, ValidationError, defaultProblemTitle, normalizeProblem };
|
package/dist/core/errors.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* @forinda/kickjs v5.
|
|
2
|
+
* @forinda/kickjs v5.18.0-alpha.0
|
|
3
3
|
*
|
|
4
4
|
* Copyright (c) Felix Orinda
|
|
5
5
|
*
|
|
@@ -8,5 +8,5 @@
|
|
|
8
8
|
*
|
|
9
9
|
* @license MIT
|
|
10
10
|
*/
|
|
11
|
-
const HttpStatus={OK:200,CREATED:201,ACCEPTED:202,NO_CONTENT:204,MOVED_PERMANENTLY:301,FOUND:302,NOT_MODIFIED:304,TEMPORARY_REDIRECT:307,PERMANENT_REDIRECT:308,BAD_REQUEST:400,UNAUTHORIZED:401,PAYMENT_REQUIRED:402,FORBIDDEN:403,NOT_FOUND:404,METHOD_NOT_ALLOWED:405,NOT_ACCEPTABLE:406,CONFLICT:409,GONE:410,UNPROCESSABLE_ENTITY:422,TOO_MANY_REQUESTS:429,INTERNAL_SERVER_ERROR:500,NOT_IMPLEMENTED:501,BAD_GATEWAY:502,SERVICE_UNAVAILABLE:503,GATEWAY_TIMEOUT:504},STATUS_REASONS={400:`Bad Request`,401:`Unauthorized`,402:`Payment Required`,403:`Forbidden`,404:`Not Found`,405:`Method Not Allowed`,406:`Not Acceptable`,409:`Conflict`,410:`Gone`,422:`Unprocessable Entity`,429:`Too Many Requests`,500:`Internal Server Error`,501:`Not Implemented`,502:`Bad Gateway`,503:`Service Unavailable`,504:`Gateway Timeout`};var HttpException=class HttpException extends Error{status;details;headers;constructor(status,message,details,headers){super(message),this.status=status,this.details=details,this.headers=headers,this.name=`HttpException`}withHeaders(headers){return new HttpException(this.status,this.message,this.details,{...this.headers,...headers})}static fromZodError(error,message){let firstIssue=error.issues?.[0],details=(error.issues||[]).map(issue=>({field:issue.path?.join(`.`)||``,message:issue.message,code:issue.code}));return new HttpException(HttpStatus.UNPROCESSABLE_ENTITY,message||firstIssue?.message||`Validation failed`,details)}static badRequest(message=`Bad Request`){return new HttpException(HttpStatus.BAD_REQUEST,message)}static unauthorized(message=`Unauthorized`,wwwAuthenticate){return new HttpException(HttpStatus.UNAUTHORIZED,message,void 0,wwwAuthenticate?{"WWW-Authenticate":wwwAuthenticate}:void 0)}static forbidden(message=`Forbidden`){return new HttpException(HttpStatus.FORBIDDEN,message)}static notFound(message=`Not Found`){return new HttpException(HttpStatus.NOT_FOUND,message)}static methodNotAllowed(allowedMethods,message=`Method Not Allowed`){return new HttpException(HttpStatus.METHOD_NOT_ALLOWED,message,void 0,{Allow:allowedMethods.join(`, `)})}static conflict(message=`Conflict`){return new HttpException(HttpStatus.CONFLICT,message)}static unprocessable(message=`Unprocessable Entity`,details){return new HttpException(HttpStatus.UNPROCESSABLE_ENTITY,message,details)}static tooManyRequests(message=`Too Many Requests`,retryAfterSeconds){return new HttpException(HttpStatus.TOO_MANY_REQUESTS,message,void 0,retryAfterSeconds===void 0?void 0:{"Retry-After":String(retryAfterSeconds)})}static serviceUnavailable(message=`Service Unavailable`,retryAfterSeconds){return new HttpException(HttpStatus.SERVICE_UNAVAILABLE,message,void 0,retryAfterSeconds===void 0?void 0:{"Retry-After":String(retryAfterSeconds)})}static internal(message=`Internal Server Error`){return new HttpException(HttpStatus.INTERNAL_SERVER_ERROR,message)}};function defaultProblemTitle(status){return STATUS_REASONS[status]??`Error`}var ProblemException=class ProblemException extends HttpException{problem;constructor(problem,headers){let title=problem.title??defaultProblemTitle(problem.status),detail=problem.detail??title;super(problem.status,detail,void 0,headers),this.name=`ProblemException`,this.problem={...problem,title}}withHeaders(headers){return new ProblemException(this.problem,{...this.headers,...headers})}};const Problems={badRequest(input={}){return new ProblemException({status:400,...input})},unauthorized(input={},wwwAuthenticate){return new ProblemException({status:401,...input},wwwAuthenticate?{"WWW-Authenticate":wwwAuthenticate}:void 0)},forbidden(input={}){return new ProblemException({status:403,...input})},notFound(input={}){return new ProblemException({status:404,...input})},methodNotAllowed(allowedMethods,input={}){return new ProblemException({status:405,...input},{Allow:allowedMethods.join(`, `)})},conflict(input={}){return new ProblemException({status:409,...input})},unprocessable(input={}){return new ProblemException({status:422,...input})},tooManyRequests(input={},retryAfterSeconds){return new ProblemException({status:429,...input},retryAfterSeconds===void 0?void 0:{"Retry-After":String(retryAfterSeconds)})},serviceUnavailable(input={},retryAfterSeconds){return new ProblemException({status:503,...input},retryAfterSeconds===void 0?void 0:{"Retry-After":String(retryAfterSeconds)})},internal(input={}){return new ProblemException({status:500,...input})},fromZodError(error,input={}){let issues=(error.issues||[]).map(issue=>({field:issue.path?.join(`.`)||``,message:issue.message,code:issue.code}));return new ProblemException({status:422,detail:error.issues?.[0]?.message,...input,errors:issues})}};function normalizeProblem(input){return{...input,type:input.type??`about:blank`,title:input.title??defaultProblemTitle(input.status)}}export{HttpException,HttpStatus,ProblemException,Problems,defaultProblemTitle,normalizeProblem};
|
|
11
|
+
const HttpStatus={OK:200,CREATED:201,ACCEPTED:202,NO_CONTENT:204,MOVED_PERMANENTLY:301,FOUND:302,NOT_MODIFIED:304,TEMPORARY_REDIRECT:307,PERMANENT_REDIRECT:308,BAD_REQUEST:400,UNAUTHORIZED:401,PAYMENT_REQUIRED:402,FORBIDDEN:403,NOT_FOUND:404,METHOD_NOT_ALLOWED:405,NOT_ACCEPTABLE:406,CONFLICT:409,GONE:410,PAYLOAD_TOO_LARGE:413,UNSUPPORTED_MEDIA_TYPE:415,UNPROCESSABLE_ENTITY:422,TOO_MANY_REQUESTS:429,INTERNAL_SERVER_ERROR:500,NOT_IMPLEMENTED:501,BAD_GATEWAY:502,SERVICE_UNAVAILABLE:503,GATEWAY_TIMEOUT:504},STATUS_REASONS={400:`Bad Request`,401:`Unauthorized`,402:`Payment Required`,403:`Forbidden`,404:`Not Found`,405:`Method Not Allowed`,406:`Not Acceptable`,409:`Conflict`,410:`Gone`,413:`Payload Too Large`,415:`Unsupported Media Type`,422:`Unprocessable Entity`,429:`Too Many Requests`,500:`Internal Server Error`,501:`Not Implemented`,502:`Bad Gateway`,503:`Service Unavailable`,504:`Gateway Timeout`};var HttpException=class HttpException extends Error{status;details;headers;constructor(status,message,details,headers){super(message),this.status=status,this.details=details,this.headers=headers,this.name=`HttpException`}withHeaders(headers){return new HttpException(this.status,this.message,this.details,{...this.headers,...headers})}static fromZodError(error,message){let firstIssue=error.issues?.[0],details=(error.issues||[]).map(issue=>({field:issue.path?.join(`.`)||``,message:issue.message,code:issue.code}));return new HttpException(HttpStatus.UNPROCESSABLE_ENTITY,message||firstIssue?.message||`Validation failed`,details)}static badRequest(message=`Bad Request`){return new HttpException(HttpStatus.BAD_REQUEST,message)}static unauthorized(message=`Unauthorized`,wwwAuthenticate){return new HttpException(HttpStatus.UNAUTHORIZED,message,void 0,wwwAuthenticate?{"WWW-Authenticate":wwwAuthenticate}:void 0)}static forbidden(message=`Forbidden`){return new HttpException(HttpStatus.FORBIDDEN,message)}static notFound(message=`Not Found`){return new HttpException(HttpStatus.NOT_FOUND,message)}static methodNotAllowed(allowedMethods,message=`Method Not Allowed`){return new HttpException(HttpStatus.METHOD_NOT_ALLOWED,message,void 0,{Allow:allowedMethods.join(`, `)})}static conflict(message=`Conflict`){return new HttpException(HttpStatus.CONFLICT,message)}static unprocessable(message=`Unprocessable Entity`,details){return new HttpException(HttpStatus.UNPROCESSABLE_ENTITY,message,details)}static tooManyRequests(message=`Too Many Requests`,retryAfterSeconds){return new HttpException(HttpStatus.TOO_MANY_REQUESTS,message,void 0,retryAfterSeconds===void 0?void 0:{"Retry-After":String(retryAfterSeconds)})}static serviceUnavailable(message=`Service Unavailable`,retryAfterSeconds){return new HttpException(HttpStatus.SERVICE_UNAVAILABLE,message,void 0,retryAfterSeconds===void 0?void 0:{"Retry-After":String(retryAfterSeconds)})}static internal(message=`Internal Server Error`){return new HttpException(HttpStatus.INTERNAL_SERVER_ERROR,message)}};function defaultProblemTitle(status){return STATUS_REASONS[status]??`Error`}var ProblemException=class ProblemException extends HttpException{problem;constructor(problem,headers){let title=problem.title??defaultProblemTitle(problem.status),detail=problem.detail??title;super(problem.status,detail,void 0,headers),this.name=`ProblemException`,this.problem={...problem,title}}withHeaders(headers){return new ProblemException(this.problem,{...this.headers,...headers})}};const Problems={badRequest(input={}){return new ProblemException({status:400,...input})},unauthorized(input={},wwwAuthenticate){return new ProblemException({status:401,...input},wwwAuthenticate?{"WWW-Authenticate":wwwAuthenticate}:void 0)},forbidden(input={}){return new ProblemException({status:403,...input})},notFound(input={}){return new ProblemException({status:404,...input})},methodNotAllowed(allowedMethods,input={}){return new ProblemException({status:405,...input},{Allow:allowedMethods.join(`, `)})},conflict(input={}){return new ProblemException({status:409,...input})},unprocessable(input={}){return new ProblemException({status:422,...input})},tooManyRequests(input={},retryAfterSeconds){return new ProblemException({status:429,...input},retryAfterSeconds===void 0?void 0:{"Retry-After":String(retryAfterSeconds)})},serviceUnavailable(input={},retryAfterSeconds){return new ProblemException({status:503,...input},retryAfterSeconds===void 0?void 0:{"Retry-After":String(retryAfterSeconds)})},internal(input={}){return new ProblemException({status:500,...input})},fromZodError(error,input={}){let issues=(error.issues||[]).map(issue=>({field:issue.path?.join(`.`)||``,message:issue.message,code:issue.code}));return new ProblemException({status:422,detail:error.issues?.[0]?.message,...input,errors:issues})}};function normalizeProblem(input){return{...input,type:input.type??`about:blank`,title:input.title??defaultProblemTitle(input.status)}}export{HttpException,HttpStatus,ProblemException,Problems,defaultProblemTitle,normalizeProblem};
|
|
12
12
|
//# sourceMappingURL=errors.mjs.map
|
package/dist/core/errors.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"errors.mjs","names":[],"sources":["../../src/core/errors.ts"],"sourcesContent":["/**\n * Standard HTTP status codes as a const enum.\n * Use instead of raw numbers for readability and type safety.\n *\n * @example\n * ```ts\n * throw new HttpException(HttpStatus.NOT_FOUND, 'User not found')\n * ctx.res.status(HttpStatus.CREATED).json(data)\n * ```\n */\nexport const HttpStatus = {\n // 2xx Success\n OK: 200,\n CREATED: 201,\n ACCEPTED: 202,\n NO_CONTENT: 204,\n\n // 3xx Redirection\n MOVED_PERMANENTLY: 301,\n FOUND: 302,\n NOT_MODIFIED: 304,\n TEMPORARY_REDIRECT: 307,\n PERMANENT_REDIRECT: 308,\n\n // 4xx Client Errors\n BAD_REQUEST: 400,\n UNAUTHORIZED: 401,\n PAYMENT_REQUIRED: 402,\n FORBIDDEN: 403,\n NOT_FOUND: 404,\n METHOD_NOT_ALLOWED: 405,\n NOT_ACCEPTABLE: 406,\n CONFLICT: 409,\n GONE: 410,\n UNPROCESSABLE_ENTITY: 422,\n TOO_MANY_REQUESTS: 429,\n\n // 5xx Server Errors\n INTERNAL_SERVER_ERROR: 500,\n NOT_IMPLEMENTED: 501,\n BAD_GATEWAY: 502,\n SERVICE_UNAVAILABLE: 503,\n GATEWAY_TIMEOUT: 504,\n} as const\n\nexport type HttpStatusCode = (typeof HttpStatus)[keyof typeof HttpStatus]\n\n/**\n * IANA HTTP status reason phrases for the codes the framework's typed\n * helpers cover. Used as the default `title` when a {@link ProblemException}\n * is constructed without one. Keep in sync with {@link HttpStatus}.\n */\nconst STATUS_REASONS: Record<number, string> = {\n 400: 'Bad Request',\n 401: 'Unauthorized',\n 402: 'Payment Required',\n 403: 'Forbidden',\n 404: 'Not Found',\n 405: 'Method Not Allowed',\n 406: 'Not Acceptable',\n 409: 'Conflict',\n 410: 'Gone',\n 422: 'Unprocessable Entity',\n 429: 'Too Many Requests',\n 500: 'Internal Server Error',\n 501: 'Not Implemented',\n 502: 'Bad Gateway',\n 503: 'Service Unavailable',\n 504: 'Gateway Timeout',\n}\n\n/** Validation error detail — shape used by `unprocessable()` and `fromZodError()`. */\nexport interface ValidationError {\n field: string\n message: string\n code?: string\n}\n\n/**\n * RFC 9457 — Problem Details for HTTP APIs.\n * https://datatracker.ietf.org/doc/html/rfc9457\n *\n * Canonical error shape for HTTP responses. Only `status` is required;\n * everything else has a sensible default. Extension members (any other\n * JSON-compatible field) are allowed per §3.2 — pass them on the same\n * object and the framework forwards them through.\n *\n * @example\n * ```ts\n * const problem: ProblemDetails = {\n * type: 'https://api.example.com/problems/out-of-credit',\n * status: 403,\n * title: 'You do not have enough credit',\n * detail: 'Your balance is 30, but that costs 50.',\n * instance: '/account/12345/messages/abc',\n * // extension members per §3.2\n * balance: 30,\n * }\n * ```\n */\nexport interface ProblemDetails {\n /**\n * URI reference identifying the problem type. Per §4.2.1, when\n * dereferenced it SHOULD return human-readable documentation. Defaults\n * to `about:blank` when omitted (RFC 9457 §3.1.1).\n */\n type?: string\n /**\n * Short human-readable summary, advisable to be the same regardless of\n * the occurrence (§3.1.4). Defaults to the IANA reason phrase for\n * `status` when omitted.\n */\n title?: string\n /** HTTP status code generated by the origin server. Required. */\n status: number\n /**\n * Human-readable explanation specific to this occurrence (§3.1.5).\n * Per the RFC's safety guidance, do not include sensitive information\n * (tokens, full SQL, stack traces) — those belong in logs.\n */\n detail?: string\n /**\n * URI reference identifying the specific occurrence (§3.1.6).\n * Typically the request path. Adopters set this explicitly — the\n * framework does not auto-populate it to avoid leaking unexpected\n * structure.\n */\n instance?: string\n /**\n * Extension members per §3.2 — any other JSON-compatible field.\n * Common examples: `balance`, `errors`, `traceId`, `accounts`.\n */\n [key: string]: unknown\n}\n\n/**\n * Typed HTTP exception with status code, free-form details, and optional\n * response headers. Provides static factory methods for common HTTP errors.\n *\n * `details` is intentionally typed as `unknown` — it serializes straight into\n * the response body's `errors` field, so any JSON-compatible shape works\n * (string, object, array of mixed values, ValidationError[]).\n *\n * `headers` are merged into the response by the global error handler so\n * spec-mandated headers (Retry-After, WWW-Authenticate, Allow, Location)\n * stay on the exception, not on ad-hoc try/catch chains.\n *\n * For RFC 9457 — Problem Details responses, throw {@link ProblemException}\n * instead — the global error handler emits `application/problem+json` for\n * those automatically.\n */\nexport class HttpException extends Error {\n constructor(\n public readonly status: number,\n message: string,\n public readonly details?: unknown,\n public readonly headers?: Record<string, string>,\n ) {\n super(message)\n this.name = 'HttpException'\n }\n\n /** Return a new exception with `headers` shallow-merged onto this one. */\n withHeaders(headers: Record<string, string>): HttpException {\n return new HttpException(this.status, this.message, this.details, {\n ...this.headers,\n ...headers,\n })\n }\n\n /** Create from a Zod error */\n static fromZodError(error: any, message?: string): HttpException {\n const firstIssue = error.issues?.[0]\n const details: ValidationError[] = (error.issues || []).map((issue: any) => ({\n field: issue.path?.join('.') || '',\n message: issue.message,\n code: issue.code,\n }))\n return new HttpException(\n HttpStatus.UNPROCESSABLE_ENTITY,\n message || firstIssue?.message || 'Validation failed',\n details,\n )\n }\n\n static badRequest(message = 'Bad Request') {\n return new HttpException(HttpStatus.BAD_REQUEST, message)\n }\n static unauthorized(message = 'Unauthorized', wwwAuthenticate?: string) {\n return new HttpException(\n HttpStatus.UNAUTHORIZED,\n message,\n undefined,\n wwwAuthenticate ? { 'WWW-Authenticate': wwwAuthenticate } : undefined,\n )\n }\n static forbidden(message = 'Forbidden') {\n return new HttpException(HttpStatus.FORBIDDEN, message)\n }\n static notFound(message = 'Not Found') {\n return new HttpException(HttpStatus.NOT_FOUND, message)\n }\n static methodNotAllowed(allowedMethods: string[], message = 'Method Not Allowed') {\n return new HttpException(HttpStatus.METHOD_NOT_ALLOWED, message, undefined, {\n Allow: allowedMethods.join(', '),\n })\n }\n static conflict(message = 'Conflict') {\n return new HttpException(HttpStatus.CONFLICT, message)\n }\n static unprocessable(message = 'Unprocessable Entity', details?: ValidationError[]) {\n return new HttpException(HttpStatus.UNPROCESSABLE_ENTITY, message, details)\n }\n static tooManyRequests(message = 'Too Many Requests', retryAfterSeconds?: number) {\n return new HttpException(\n HttpStatus.TOO_MANY_REQUESTS,\n message,\n undefined,\n retryAfterSeconds !== undefined ? { 'Retry-After': String(retryAfterSeconds) } : undefined,\n )\n }\n static serviceUnavailable(message = 'Service Unavailable', retryAfterSeconds?: number) {\n return new HttpException(\n HttpStatus.SERVICE_UNAVAILABLE,\n message,\n undefined,\n retryAfterSeconds !== undefined ? { 'Retry-After': String(retryAfterSeconds) } : undefined,\n )\n }\n static internal(message = 'Internal Server Error') {\n return new HttpException(HttpStatus.INTERNAL_SERVER_ERROR, message)\n }\n}\n\n/**\n * Default `title` for an RFC 9457 problem with the given status — the IANA\n * reason phrase, or `'Error'` for codes outside the framework's table.\n * Exposed so {@link ProblemException} construction and {@link RequestContext}'s\n * `problem` helpers share a single source of truth.\n */\nexport function defaultProblemTitle(status: number): string {\n return STATUS_REASONS[status] ?? 'Error'\n}\n\n/**\n * Exception that carries an RFC 9457 — Problem Details payload. When\n * thrown, the framework error handler emits `application/problem+json`\n * with the canonical shape; `type` defaults to `about:blank`, `title`\n * to the IANA reason phrase for `status`.\n *\n * Extends {@link HttpException} so existing `instanceof HttpException`\n * catches still see it. Use `new ProblemException(...)` directly for\n * full control, or {@link Problems} for the pre-filled-status\n * convenience factories.\n *\n * Static factories deliberately live on {@link Problems} rather than\n * this class — putting them here would shadow `HttpException`'s\n * same-named statics with incompatible (object vs string) signatures,\n * which TypeScript correctly rejects.\n *\n * @example\n * ```ts\n * throw new ProblemException({\n * type: 'https://api.example.com/problems/out-of-credit',\n * status: 403,\n * title: 'You do not have enough credit',\n * detail: 'Your balance is 30, but that costs 50.',\n * instance: '/account/12345/messages/abc',\n * balance: 30, // extension\n * })\n *\n * // Or via the Problems convenience factory:\n * throw Problems.forbidden({\n * type: 'https://api.example.com/problems/out-of-credit',\n * detail: 'Your balance is 30, but that costs 50.',\n * balance: 30,\n * })\n * ```\n */\nexport class ProblemException extends HttpException {\n public readonly problem: ProblemDetails\n\n constructor(problem: ProblemDetails, headers?: Record<string, string>) {\n const title = problem.title ?? defaultProblemTitle(problem.status)\n const detail = problem.detail ?? title\n super(problem.status, detail, undefined, headers)\n this.name = 'ProblemException'\n this.problem = { ...problem, title }\n }\n\n /** Return a new exception with `headers` shallow-merged onto this one. */\n withHeaders(headers: Record<string, string>): ProblemException {\n return new ProblemException(this.problem, { ...this.headers, ...headers })\n }\n}\n\n/**\n * Convenience factories for {@link ProblemException}. Pre-fill `status`\n * (and `title` via {@link defaultProblemTitle}) for the common HTTP\n * codes — same shortcut set the `ctx.problem.*` response helpers cover.\n *\n * Lives in a separate namespace rather than as statics on\n * {@link ProblemException} to avoid shadowing {@link HttpException}'s\n * same-named statics, which would create a TypeScript variance\n * conflict (parent's `notFound(message?: string)` vs the child's\n * desired `notFound(input?: ProblemInput)`).\n *\n * @example\n * ```ts\n * throw Problems.notFound({ detail: 'User abc not found' })\n * throw Problems.tooManyRequests({}, 60) // sets Retry-After: 60\n * throw Problems.fromZodError(zodResult.error)\n * ```\n */\nexport const Problems = {\n /** 400 Bad Request with optional detail / instance / extensions. */\n badRequest(input: Omit<ProblemDetails, 'status'> = {}): ProblemException {\n return new ProblemException({ status: 400, ...input })\n },\n /** 401 Unauthorized. Pass a `WWW-Authenticate` challenge via the headers arg. */\n unauthorized(\n input: Omit<ProblemDetails, 'status'> = {},\n wwwAuthenticate?: string,\n ): ProblemException {\n return new ProblemException(\n { status: 401, ...input },\n wwwAuthenticate ? { 'WWW-Authenticate': wwwAuthenticate } : undefined,\n )\n },\n /** 403 Forbidden. */\n forbidden(input: Omit<ProblemDetails, 'status'> = {}): ProblemException {\n return new ProblemException({ status: 403, ...input })\n },\n /** 404 Not Found. */\n notFound(input: Omit<ProblemDetails, 'status'> = {}): ProblemException {\n return new ProblemException({ status: 404, ...input })\n },\n /** 405 Method Not Allowed. Pass the allowed methods so the Allow header is set. */\n methodNotAllowed(\n allowedMethods: string[],\n input: Omit<ProblemDetails, 'status'> = {},\n ): ProblemException {\n return new ProblemException({ status: 405, ...input }, { Allow: allowedMethods.join(', ') })\n },\n /** 409 Conflict. */\n conflict(input: Omit<ProblemDetails, 'status'> = {}): ProblemException {\n return new ProblemException({ status: 409, ...input })\n },\n /**\n * 422 Unprocessable Entity. Pass per-field issues via the `errors`\n * extension — keep the array shape per the RFC's recommended convention\n * (`{ field, message, code }`).\n */\n unprocessable(input: Omit<ProblemDetails, 'status'> = {}): ProblemException {\n return new ProblemException({ status: 422, ...input })\n },\n /** 429 Too Many Requests. Pass `retryAfterSeconds` to set the Retry-After header. */\n tooManyRequests(\n input: Omit<ProblemDetails, 'status'> = {},\n retryAfterSeconds?: number,\n ): ProblemException {\n return new ProblemException(\n { status: 429, ...input },\n retryAfterSeconds !== undefined ? { 'Retry-After': String(retryAfterSeconds) } : undefined,\n )\n },\n /** 503 Service Unavailable. */\n serviceUnavailable(\n input: Omit<ProblemDetails, 'status'> = {},\n retryAfterSeconds?: number,\n ): ProblemException {\n return new ProblemException(\n { status: 503, ...input },\n retryAfterSeconds !== undefined ? { 'Retry-After': String(retryAfterSeconds) } : undefined,\n )\n },\n /** 500 Internal Server Error. */\n internal(input: Omit<ProblemDetails, 'status'> = {}): ProblemException {\n return new ProblemException({ status: 500, ...input })\n },\n\n /**\n * Build from a Zod error — 422 with the issues serialized into the\n * `errors` extension per RFC 9457 §3.2's array convention.\n */\n fromZodError(error: any, input: Omit<ProblemDetails, 'status'> = {}): ProblemException {\n const issues: ValidationError[] = (error.issues || []).map((issue: any) => ({\n field: issue.path?.join('.') || '',\n message: issue.message,\n code: issue.code,\n }))\n return new ProblemException({\n status: 422,\n detail: error.issues?.[0]?.message,\n ...input,\n errors: issues,\n })\n },\n} as const\n\n/**\n * Normalize an RFC 9457 problem into the wire shape — fill in `type` →\n * `'about:blank'` and `title` → IANA reason phrase. The same function is\n * used by {@link RequestContext}'s `problem` helpers and the global\n * error handler so the response is identical regardless of entry point.\n *\n * Defaults are applied **after** the spread, so a caller passing\n * `{ type: undefined }` (e.g. a partial built up from optional fields)\n * still gets `'about:blank'` on the wire — `...input` would otherwise\n * re-overwrite the fallback with the explicit `undefined`.\n */\nexport function normalizeProblem(input: ProblemDetails): ProblemDetails {\n return {\n ...input,\n type: input.type ?? 'about:blank',\n title: input.title ?? defaultProblemTitle(input.status),\n }\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"errors.mjs","names":[],"sources":["../../src/core/errors.ts"],"sourcesContent":["/**\n * Standard HTTP status codes as a const enum.\n * Use instead of raw numbers for readability and type safety.\n *\n * @example\n * ```ts\n * throw new HttpException(HttpStatus.NOT_FOUND, 'User not found')\n * ctx.res.status(HttpStatus.CREATED).json(data)\n * ```\n */\nexport const HttpStatus = {\n // 2xx Success\n OK: 200,\n CREATED: 201,\n ACCEPTED: 202,\n NO_CONTENT: 204,\n\n // 3xx Redirection\n MOVED_PERMANENTLY: 301,\n FOUND: 302,\n NOT_MODIFIED: 304,\n TEMPORARY_REDIRECT: 307,\n PERMANENT_REDIRECT: 308,\n\n // 4xx Client Errors\n BAD_REQUEST: 400,\n UNAUTHORIZED: 401,\n PAYMENT_REQUIRED: 402,\n FORBIDDEN: 403,\n NOT_FOUND: 404,\n METHOD_NOT_ALLOWED: 405,\n NOT_ACCEPTABLE: 406,\n CONFLICT: 409,\n GONE: 410,\n PAYLOAD_TOO_LARGE: 413,\n UNSUPPORTED_MEDIA_TYPE: 415,\n UNPROCESSABLE_ENTITY: 422,\n TOO_MANY_REQUESTS: 429,\n\n // 5xx Server Errors\n INTERNAL_SERVER_ERROR: 500,\n NOT_IMPLEMENTED: 501,\n BAD_GATEWAY: 502,\n SERVICE_UNAVAILABLE: 503,\n GATEWAY_TIMEOUT: 504,\n} as const\n\nexport type HttpStatusCode = (typeof HttpStatus)[keyof typeof HttpStatus]\n\n/**\n * IANA HTTP status reason phrases for the codes the framework's typed\n * helpers cover. Used as the default `title` when a {@link ProblemException}\n * is constructed without one. Keep in sync with {@link HttpStatus}.\n */\nconst STATUS_REASONS: Record<number, string> = {\n 400: 'Bad Request',\n 401: 'Unauthorized',\n 402: 'Payment Required',\n 403: 'Forbidden',\n 404: 'Not Found',\n 405: 'Method Not Allowed',\n 406: 'Not Acceptable',\n 409: 'Conflict',\n 410: 'Gone',\n 413: 'Payload Too Large',\n 415: 'Unsupported Media Type',\n 422: 'Unprocessable Entity',\n 429: 'Too Many Requests',\n 500: 'Internal Server Error',\n 501: 'Not Implemented',\n 502: 'Bad Gateway',\n 503: 'Service Unavailable',\n 504: 'Gateway Timeout',\n}\n\n/** Validation error detail — shape used by `unprocessable()` and `fromZodError()`. */\nexport interface ValidationError {\n field: string\n message: string\n code?: string\n}\n\n/**\n * RFC 9457 — Problem Details for HTTP APIs.\n * https://datatracker.ietf.org/doc/html/rfc9457\n *\n * Canonical error shape for HTTP responses. Only `status` is required;\n * everything else has a sensible default. Extension members (any other\n * JSON-compatible field) are allowed per §3.2 — pass them on the same\n * object and the framework forwards them through.\n *\n * @example\n * ```ts\n * const problem: ProblemDetails = {\n * type: 'https://api.example.com/problems/out-of-credit',\n * status: 403,\n * title: 'You do not have enough credit',\n * detail: 'Your balance is 30, but that costs 50.',\n * instance: '/account/12345/messages/abc',\n * // extension members per §3.2\n * balance: 30,\n * }\n * ```\n */\nexport interface ProblemDetails {\n /**\n * URI reference identifying the problem type. Per §4.2.1, when\n * dereferenced it SHOULD return human-readable documentation. Defaults\n * to `about:blank` when omitted (RFC 9457 §3.1.1).\n */\n type?: string\n /**\n * Short human-readable summary, advisable to be the same regardless of\n * the occurrence (§3.1.4). Defaults to the IANA reason phrase for\n * `status` when omitted.\n */\n title?: string\n /** HTTP status code generated by the origin server. Required. */\n status: number\n /**\n * Human-readable explanation specific to this occurrence (§3.1.5).\n * Per the RFC's safety guidance, do not include sensitive information\n * (tokens, full SQL, stack traces) — those belong in logs.\n */\n detail?: string\n /**\n * URI reference identifying the specific occurrence (§3.1.6).\n * Typically the request path. Adopters set this explicitly — the\n * framework does not auto-populate it to avoid leaking unexpected\n * structure.\n */\n instance?: string\n /**\n * Extension members per §3.2 — any other JSON-compatible field.\n * Common examples: `balance`, `errors`, `traceId`, `accounts`.\n */\n [key: string]: unknown\n}\n\n/**\n * Typed HTTP exception with status code, free-form details, and optional\n * response headers. Provides static factory methods for common HTTP errors.\n *\n * `details` is intentionally typed as `unknown` — it serializes straight into\n * the response body's `errors` field, so any JSON-compatible shape works\n * (string, object, array of mixed values, ValidationError[]).\n *\n * `headers` are merged into the response by the global error handler so\n * spec-mandated headers (Retry-After, WWW-Authenticate, Allow, Location)\n * stay on the exception, not on ad-hoc try/catch chains.\n *\n * For RFC 9457 — Problem Details responses, throw {@link ProblemException}\n * instead — the global error handler emits `application/problem+json` for\n * those automatically.\n */\nexport class HttpException extends Error {\n constructor(\n public readonly status: number,\n message: string,\n public readonly details?: unknown,\n public readonly headers?: Record<string, string>,\n ) {\n super(message)\n this.name = 'HttpException'\n }\n\n /** Return a new exception with `headers` shallow-merged onto this one. */\n withHeaders(headers: Record<string, string>): HttpException {\n return new HttpException(this.status, this.message, this.details, {\n ...this.headers,\n ...headers,\n })\n }\n\n /** Create from a Zod error */\n static fromZodError(error: any, message?: string): HttpException {\n const firstIssue = error.issues?.[0]\n const details: ValidationError[] = (error.issues || []).map((issue: any) => ({\n field: issue.path?.join('.') || '',\n message: issue.message,\n code: issue.code,\n }))\n return new HttpException(\n HttpStatus.UNPROCESSABLE_ENTITY,\n message || firstIssue?.message || 'Validation failed',\n details,\n )\n }\n\n static badRequest(message = 'Bad Request') {\n return new HttpException(HttpStatus.BAD_REQUEST, message)\n }\n static unauthorized(message = 'Unauthorized', wwwAuthenticate?: string) {\n return new HttpException(\n HttpStatus.UNAUTHORIZED,\n message,\n undefined,\n wwwAuthenticate ? { 'WWW-Authenticate': wwwAuthenticate } : undefined,\n )\n }\n static forbidden(message = 'Forbidden') {\n return new HttpException(HttpStatus.FORBIDDEN, message)\n }\n static notFound(message = 'Not Found') {\n return new HttpException(HttpStatus.NOT_FOUND, message)\n }\n static methodNotAllowed(allowedMethods: string[], message = 'Method Not Allowed') {\n return new HttpException(HttpStatus.METHOD_NOT_ALLOWED, message, undefined, {\n Allow: allowedMethods.join(', '),\n })\n }\n static conflict(message = 'Conflict') {\n return new HttpException(HttpStatus.CONFLICT, message)\n }\n static unprocessable(message = 'Unprocessable Entity', details?: ValidationError[]) {\n return new HttpException(HttpStatus.UNPROCESSABLE_ENTITY, message, details)\n }\n static tooManyRequests(message = 'Too Many Requests', retryAfterSeconds?: number) {\n return new HttpException(\n HttpStatus.TOO_MANY_REQUESTS,\n message,\n undefined,\n retryAfterSeconds !== undefined ? { 'Retry-After': String(retryAfterSeconds) } : undefined,\n )\n }\n static serviceUnavailable(message = 'Service Unavailable', retryAfterSeconds?: number) {\n return new HttpException(\n HttpStatus.SERVICE_UNAVAILABLE,\n message,\n undefined,\n retryAfterSeconds !== undefined ? { 'Retry-After': String(retryAfterSeconds) } : undefined,\n )\n }\n static internal(message = 'Internal Server Error') {\n return new HttpException(HttpStatus.INTERNAL_SERVER_ERROR, message)\n }\n}\n\n/**\n * Default `title` for an RFC 9457 problem with the given status — the IANA\n * reason phrase, or `'Error'` for codes outside the framework's table.\n * Exposed so {@link ProblemException} construction and {@link RequestContext}'s\n * `problem` helpers share a single source of truth.\n */\nexport function defaultProblemTitle(status: number): string {\n return STATUS_REASONS[status] ?? 'Error'\n}\n\n/**\n * Exception that carries an RFC 9457 — Problem Details payload. When\n * thrown, the framework error handler emits `application/problem+json`\n * with the canonical shape; `type` defaults to `about:blank`, `title`\n * to the IANA reason phrase for `status`.\n *\n * Extends {@link HttpException} so existing `instanceof HttpException`\n * catches still see it. Use `new ProblemException(...)` directly for\n * full control, or {@link Problems} for the pre-filled-status\n * convenience factories.\n *\n * Static factories deliberately live on {@link Problems} rather than\n * this class — putting them here would shadow `HttpException`'s\n * same-named statics with incompatible (object vs string) signatures,\n * which TypeScript correctly rejects.\n *\n * @example\n * ```ts\n * throw new ProblemException({\n * type: 'https://api.example.com/problems/out-of-credit',\n * status: 403,\n * title: 'You do not have enough credit',\n * detail: 'Your balance is 30, but that costs 50.',\n * instance: '/account/12345/messages/abc',\n * balance: 30, // extension\n * })\n *\n * // Or via the Problems convenience factory:\n * throw Problems.forbidden({\n * type: 'https://api.example.com/problems/out-of-credit',\n * detail: 'Your balance is 30, but that costs 50.',\n * balance: 30,\n * })\n * ```\n */\nexport class ProblemException extends HttpException {\n public readonly problem: ProblemDetails\n\n constructor(problem: ProblemDetails, headers?: Record<string, string>) {\n const title = problem.title ?? defaultProblemTitle(problem.status)\n const detail = problem.detail ?? title\n super(problem.status, detail, undefined, headers)\n this.name = 'ProblemException'\n this.problem = { ...problem, title }\n }\n\n /** Return a new exception with `headers` shallow-merged onto this one. */\n withHeaders(headers: Record<string, string>): ProblemException {\n return new ProblemException(this.problem, { ...this.headers, ...headers })\n }\n}\n\n/**\n * Convenience factories for {@link ProblemException}. Pre-fill `status`\n * (and `title` via {@link defaultProblemTitle}) for the common HTTP\n * codes — same shortcut set the `ctx.problem.*` response helpers cover.\n *\n * Lives in a separate namespace rather than as statics on\n * {@link ProblemException} to avoid shadowing {@link HttpException}'s\n * same-named statics, which would create a TypeScript variance\n * conflict (parent's `notFound(message?: string)` vs the child's\n * desired `notFound(input?: ProblemInput)`).\n *\n * @example\n * ```ts\n * throw Problems.notFound({ detail: 'User abc not found' })\n * throw Problems.tooManyRequests({}, 60) // sets Retry-After: 60\n * throw Problems.fromZodError(zodResult.error)\n * ```\n */\nexport const Problems = {\n /** 400 Bad Request with optional detail / instance / extensions. */\n badRequest(input: Omit<ProblemDetails, 'status'> = {}): ProblemException {\n return new ProblemException({ status: 400, ...input })\n },\n /** 401 Unauthorized. Pass a `WWW-Authenticate` challenge via the headers arg. */\n unauthorized(\n input: Omit<ProblemDetails, 'status'> = {},\n wwwAuthenticate?: string,\n ): ProblemException {\n return new ProblemException(\n { status: 401, ...input },\n wwwAuthenticate ? { 'WWW-Authenticate': wwwAuthenticate } : undefined,\n )\n },\n /** 403 Forbidden. */\n forbidden(input: Omit<ProblemDetails, 'status'> = {}): ProblemException {\n return new ProblemException({ status: 403, ...input })\n },\n /** 404 Not Found. */\n notFound(input: Omit<ProblemDetails, 'status'> = {}): ProblemException {\n return new ProblemException({ status: 404, ...input })\n },\n /** 405 Method Not Allowed. Pass the allowed methods so the Allow header is set. */\n methodNotAllowed(\n allowedMethods: string[],\n input: Omit<ProblemDetails, 'status'> = {},\n ): ProblemException {\n return new ProblemException({ status: 405, ...input }, { Allow: allowedMethods.join(', ') })\n },\n /** 409 Conflict. */\n conflict(input: Omit<ProblemDetails, 'status'> = {}): ProblemException {\n return new ProblemException({ status: 409, ...input })\n },\n /**\n * 422 Unprocessable Entity. Pass per-field issues via the `errors`\n * extension — keep the array shape per the RFC's recommended convention\n * (`{ field, message, code }`).\n */\n unprocessable(input: Omit<ProblemDetails, 'status'> = {}): ProblemException {\n return new ProblemException({ status: 422, ...input })\n },\n /** 429 Too Many Requests. Pass `retryAfterSeconds` to set the Retry-After header. */\n tooManyRequests(\n input: Omit<ProblemDetails, 'status'> = {},\n retryAfterSeconds?: number,\n ): ProblemException {\n return new ProblemException(\n { status: 429, ...input },\n retryAfterSeconds !== undefined ? { 'Retry-After': String(retryAfterSeconds) } : undefined,\n )\n },\n /** 503 Service Unavailable. */\n serviceUnavailable(\n input: Omit<ProblemDetails, 'status'> = {},\n retryAfterSeconds?: number,\n ): ProblemException {\n return new ProblemException(\n { status: 503, ...input },\n retryAfterSeconds !== undefined ? { 'Retry-After': String(retryAfterSeconds) } : undefined,\n )\n },\n /** 500 Internal Server Error. */\n internal(input: Omit<ProblemDetails, 'status'> = {}): ProblemException {\n return new ProblemException({ status: 500, ...input })\n },\n\n /**\n * Build from a Zod error — 422 with the issues serialized into the\n * `errors` extension per RFC 9457 §3.2's array convention.\n */\n fromZodError(error: any, input: Omit<ProblemDetails, 'status'> = {}): ProblemException {\n const issues: ValidationError[] = (error.issues || []).map((issue: any) => ({\n field: issue.path?.join('.') || '',\n message: issue.message,\n code: issue.code,\n }))\n return new ProblemException({\n status: 422,\n detail: error.issues?.[0]?.message,\n ...input,\n errors: issues,\n })\n },\n} as const\n\n/**\n * Normalize an RFC 9457 problem into the wire shape — fill in `type` →\n * `'about:blank'` and `title` → IANA reason phrase. The same function is\n * used by {@link RequestContext}'s `problem` helpers and the global\n * error handler so the response is identical regardless of entry point.\n *\n * Defaults are applied **after** the spread, so a caller passing\n * `{ type: undefined }` (e.g. a partial built up from optional fields)\n * still gets `'about:blank'` on the wire — `...input` would otherwise\n * re-overwrite the fallback with the explicit `undefined`.\n */\nexport function normalizeProblem(input: ProblemDetails): ProblemDetails {\n return {\n ...input,\n type: input.type ?? 'about:blank',\n title: input.title ?? defaultProblemTitle(input.status),\n }\n}\n"],"mappings":"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"}
|
package/dist/core/interfaces.mjs
CHANGED
package/dist/core/logger.mjs
CHANGED
package/dist/core/path.mjs
CHANGED
package/dist/core/plugin.d.mts
CHANGED
package/dist/core/plugin.mjs
CHANGED
package/dist/core/reactivity.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* @forinda/kickjs v5.
|
|
2
|
+
* @forinda/kickjs v5.18.0-alpha.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"./container-
|
|
11
|
+
import"./container-BiGimG12.mjs";import{METADATA}from"./core/interfaces.mjs";import"./core/logger.mjs";import{c as pushClassMeta,l as pushMethodMeta}from"./metadata-Pvgc-K8a.mjs";import"./core/decorators.mjs";import"./core/cron.mjs";import"./core/cache.mjs";import"reflect-metadata";const mergeConfig$2=(defaults={},overrides={})=>({...defaults,...overrides}),composeName$2=(base,scope)=>`${base}:${scope}`;function defineModule(options){if(typeof options!=`object`||!options)throw TypeError(`defineModule: options must be an object literal. See architecture.md §21 for the spec shape.`);if(typeof options.name!=`string`||options.name.length===0){let got=typeof options.name==`string`?`""`:typeof options.name;throw TypeError(`defineModule: options.name must be a non-empty string (got ${got}). Module names appear in diagnostics and \`.scoped()\` namespacing — anonymous modules make cycle / missing-dep errors hard to localize.`)}if(typeof options.build!=`function`)throw TypeError(`defineModule(${options.name}): options.build is required and must be a function (got ${typeof options.build}). The build function returns the AppModule shape — register() / routes() / contributors() — wired with the resolved config.`);let buildSync=(instanceName,scoped,overrides)=>{let config=mergeConfig$2(options.defaults,overrides),built=options.build(config,{name:instanceName,scoped});return Object.defineProperty(built,"__moduleName",{value:instanceName,enumerable:!1,writable:!1,configurable:!1}),built},factory=(config=>buildSync(options.name,!1,config));return factory.scoped=(scopeName,config)=>buildSync(composeName$2(options.name,scopeName),!0,config),Object.defineProperty(factory,"definition",{value:Object.freeze({...options}),writable:!1,enumerable:!0,configurable:!1}),factory}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 MutableModuleRegistry=class{entries=[];mount(module){this.entries.push(module)}},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)}};function defineContextDecoratorImpl(spec){if(typeof spec!=`object`||!spec)throw TypeError(`defineContextDecorator: spec must be an object literal. See architecture.md §20.4 for the spec shape.`);if(typeof spec.key!=`string`||spec.key.length===0){let got=typeof spec.key==`string`?`""`:typeof spec.key;throw TypeError(`defineContextDecorator: spec.key must be a non-empty string (got ${got}). Pick a name that matches a key declared on \`ContextMeta\` (or one of the framework keys).`)}if(typeof spec.resolve!=`function`)throw TypeError(`defineContextDecorator(${spec.key}): spec.resolve is required and must be a function (got ${typeof spec.resolve}). Each contributor needs a resolver that produces the value to write into ctx.set(${JSON.stringify(spec.key)}, …).`);if(spec.onError!==void 0&&typeof spec.onError!=`function`)throw TypeError(`defineContextDecorator(${spec.key}): spec.onError must be a function when provided (got ${typeof spec.onError}).`);if(spec.dependsOn!==void 0&&!Array.isArray(spec.dependsOn))throw TypeError(`defineContextDecorator(${spec.key}): spec.dependsOn must be an array when provided (got ${typeof spec.dependsOn}).`);if(Array.isArray(spec.dependsOn)&&spec.dependsOn.some(dep=>typeof dep!=`string`||dep.length===0))throw TypeError(`defineContextDecorator(${spec.key}): spec.dependsOn entries must be non-empty strings.`);let definedAt=Error().stack,defaults=Object.freeze({...spec.paramDefaults??{}}),sharedDeps=Object.freeze({...spec.deps??{}}),sharedDependsOn=Object.freeze([...spec.dependsOn??[]]),sharedOptional=spec.optional??!1,buildRegistration=params=>{let frozenParams=Object.freeze({...params}),onError=spec.onError?(err,ctx)=>spec.onError(err,ctx,frozenParams):void 0;return Object.freeze({key:spec.key,deps:sharedDeps,dependsOn:sharedDependsOn,optional:sharedOptional,onError,resolve:(ctx,deps)=>spec.resolve(ctx,deps,frozenParams),definedAt})},defaultRegistration=buildRegistration({...defaults}),isDecoratorCall=args=>args.length===0?!1:args.length>=2||typeof args[0]==`function`,applyAsDecorator=(registration,target,propertyKey)=>{if(propertyKey===void 0)pushClassMeta(METADATA.CLASS_CONTRIBUTORS,target,registration);else{let constructor=target.constructor;pushMethodMeta(METADATA.METHOD_CONTRIBUTORS,constructor,String(propertyKey),registration)}},isPlainObject=value=>{let proto=Object.getPrototypeOf(value);return proto===Object.prototype||proto===null},mergeParams=override=>{if(override===void 0)return{...defaults};if(typeof override!=`object`||!override||Array.isArray(override)||!isPlainObject(override)){let got=override===null?`null`:Array.isArray(override)?`array`:typeof override==`object`?`instance of ${override.constructor?.name??`unknown class`}`:typeof override;throw TypeError(`defineContextDecorator(${spec.key}): factory call requires a plain object literal, got ${got}. Class instances and built-ins (Map, Date, etc) silently spread to empty objects — call the decorator with a spread object literal instead, e.g. \`MyDecorator({ ...someInstance })\`.`)}return{...defaults,...override}};function decoratorOrFactory(...args){if(isDecoratorCall(args)){let[target,propertyKey]=args;applyAsDecorator(defaultRegistration,target,propertyKey);return}let registration=buildRegistration(mergeParams(args[0]));return(target,propertyKey)=>{applyAsDecorator(registration,target,propertyKey)}}Object.defineProperty(decoratorOrFactory,"name",{value:`ContextDecorator(${spec.key})`,writable:!1,enumerable:!1,configurable:!0});let decorator=Object.assign(decoratorOrFactory,{registration:defaultRegistration,with:params=>({registration:buildRegistration(mergeParams(params))})});return Object.freeze(decorator)}const defineContextDecorator=Object.freeze(Object.assign(defineContextDecoratorImpl,{withParams:()=>spec=>defineContextDecoratorImpl(spec)}));var MissingContributorError=class extends Error{key;dependent;route;dependentDefinedAt;constructor(key,dependent,route,dependentDefinedAt){let where=route?` on route ${route}`:``,declaredAt=formatDeclaredAt(dependentDefinedAt);super(`Missing context contributor '${key}' required by '${dependent}'${where}${declaredAt}`),this.name=`MissingContributorError`,this.key=key,this.dependent=dependent,this.route=route,this.dependentDefinedAt=dependentDefinedAt}};function formatDeclaredAt(stack){if(!stack)return``;let lines=stack.split(`
|
|
12
12
|
`);for(let line of lines){let trimmed=line.trim();if(trimmed.startsWith(`at `)&&!trimmed.includes(`context-decorator.`)&&!trimmed.includes(`context-errors.`))return`\n declared at ${trimmed.replace(/^at /,``)}`}return``}var ContributorCycleError=class extends Error{cycle;route;constructor(cycle,route){let where=route?` on route ${route}`:``;super(`Cycle in context contributors${where}: ${cycle.join(` → `)}`),this.name=`ContributorCycleError`,this.cycle=Object.freeze([...cycle]),this.route=route}},DuplicateContributorError=class extends Error{key;sources;constructor(key,sources){super(`Duplicate context contributor for key '${key}' at the same precedence level. Sources: ${sources.join(`, `)}`),this.name=`DuplicateContributorError`,this.key=key,this.sources=Object.freeze([...sources])}};const PRECEDENCE_ORDER=[`method`,`class`,`module`,`adapter`,`global`];function buildPipeline(sources,options={}){let route=options.route,bySource=new Map;for(let src of PRECEDENCE_ORDER)bySource.set(src,[]);for(let entry of sources)bySource.get(entry.source).push(entry);let winners=new Map;for(let src of PRECEDENCE_ORDER){let rows=bySource.get(src),keysAtThisLevel=new Map;for(let row of rows){let key=row.registration.key,existing=keysAtThisLevel.get(key)??[];existing.push(row),keysAtThisLevel.set(key,existing)}for(let[key,rowsForKey]of keysAtThisLevel){if(rowsForKey.length>1)throw new DuplicateContributorError(key,rowsForKey.map((r,i)=>r.label??`${src}#${i}`));winners.has(key)||winners.set(key,rowsForKey[0])}}let survivors=[...winners.values()].map(r=>r.registration),allKeys=new Set(survivors.map(r=>r.key));for(let reg of survivors)for(let dep of reg.dependsOn)if(!allKeys.has(dep))throw new MissingContributorError(dep,reg.key,route,reg.definedAt);let sorted=topoSort(survivors,route);return Object.freeze({contributors:Object.freeze(sorted),keys:allKeys})}function topoSort(registrations,route){let indegree=new Map,dependents=new Map,byKey=new Map;for(let reg of registrations)indegree.set(reg.key,reg.dependsOn.length),byKey.set(reg.key,reg);for(let reg of registrations)for(let dep of reg.dependsOn){let list=dependents.get(dep)??[];list.push(reg),dependents.set(dep,list)}let queue=[];for(let reg of registrations)indegree.get(reg.key)===0&&queue.push(reg);let sorted=[];for(;queue.length>0;){let node=queue.shift();sorted.push(node);for(let dependent of dependents.get(node.key)??[]){let next=(indegree.get(dependent.key)??0)-1;indegree.set(dependent.key,next),next===0&&queue.push(dependent)}}if(sorted.length!==registrations.length)throw new ContributorCycleError(reconstructCycle$1(registrations.filter(r=>(indegree.get(r.key)??0)>0),byKey),route);return sorted}function reconstructCycle$1(residual,byKey){let residualKeys=new Set(residual.map(r=>r.key)),start=residual[0].key,path=[start],seen=new Set([start]),cursor=start;for(;;){let nextDep=byKey.get(cursor).dependsOn.find(d=>residualKeys.has(d));if(nextDep===void 0)break;if(seen.has(nextDep)){let cycleStart=path.indexOf(nextDep);return[...path.slice(cycleStart),nextDep]}path.push(nextDep),seen.add(nextDep),cursor=nextDep}return path}async function runContributors(options){let{pipeline,ctx,container}=options;for(let reg of pipeline.contributors)await runOne(reg,ctx,container)}async function runOne(reg,ctx,container){let value;try{let deps=resolveDeps(reg,container);value=await reg.resolve(ctx,deps)}catch(err){if(reg.optional)return;if(reg.onError){let replacement=await reg.onError(err,ctx);if(replacement===void 0)return;ctx.set(reg.key,replacement);return}throw err}ctx.set(reg.key,value)}function resolveDeps(reg,container){let out={};for(let[key,token]of Object.entries(reg.deps))out[key]=container.resolve(token);return out}var DuplicateMountNameError=class extends Error{kind;mountName;constructor(kind,mountName){super(`Duplicate ${kind} name '${mountName}' — every ${kind} must declare a unique name`),this.name=`DuplicateMountNameError`,this.kind=kind,this.mountName=mountName}},MissingMountDepError=class extends Error{kind;missing;dependent;constructor(kind,missing,dependent){super(`Missing ${kind} dependency '${missing}' required by '${dependent}' — is the ${kind} installed and named correctly?`),this.name=`MissingMountDepError`,this.kind=kind,this.missing=missing,this.dependent=dependent}},MountCycleError=class extends Error{kind;cycle;constructor(kind,cycle){super(`Cycle in ${kind} dependsOn declarations: ${cycle.join(` → `)}`),this.name=`MountCycleError`,this.kind=kind,this.cycle=Object.freeze([...cycle])}};function mountSort(items,kind){let byName=new Map;for(let item of items){if(byName.has(item.name))throw new DuplicateMountNameError(kind,item.name);byName.set(item.name,item)}let indegree=new Map,dependents=new Map;for(let item of items)indegree.set(item.name,item.dependsOn?.length??0);for(let item of items)for(let dep of item.dependsOn??[]){if(!byName.has(dep))throw new MissingMountDepError(kind,dep,item.name);let list=dependents.get(dep)??[];list.push(item),dependents.set(dep,list)}let queue=[];for(let item of items)indegree.get(item.name)===0&&queue.push(item);let sorted=[];for(;queue.length>0;){let node=queue.shift();sorted.push(node);for(let dependent of dependents.get(node.name)??[]){let next=(indegree.get(dependent.name)??0)-1;indegree.set(dependent.name,next),next===0&&queue.push(dependent)}}if(sorted.length!==items.length)throw new MountCycleError(kind,reconstructCycle(items.filter(it=>(indegree.get(it.name)??0)>0),byName));return sorted}function reconstructCycle(residual,byName){let residualNames=new Set(residual.map(r=>r.name)),start=residual[0].name,path=[start],seen=new Set([start]),cursor=start;for(;;){let nextDep=byName.get(cursor).dependsOn?.find(d=>residualNames.has(d));if(nextDep===void 0)break;if(seen.has(nextDep)){let cycleStart=path.indexOf(nextDep);return[...path.slice(cycleStart),nextDep]}path.push(nextDep),seen.add(nextDep),cursor=nextDep}return path}const mergeConfig$1=(defaults={},overrides={})=>({...defaults,...overrides}),composeName$1=(base,scope)=>`${base}:${scope}`;function definePlugin(options){let buildSync=(instanceName,scoped,overrides)=>{let config=mergeConfig$1(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));return inner=buildSync(instanceName,!1,await opts.useFactory(...deps)),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$1(options.name,scopeName),!0,config),factory.async=opts=>buildAsync(options.name,opts),Object.defineProperty(factory,"definition",{value:Object.freeze({...options})}),factory}const mergeConfig=(defaults={},overrides={})=>({...defaults,...overrides}),composeName=(base,scope)=>`${base}:${scope}`;function defineAdapter(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;return{name:instanceName,async beforeStart(ctx){let deps=(opts.inject??[]).map(tok=>ctx.container.resolve(tok));inner=buildSync(instanceName,!1,await opts.useFactory(...deps)),await inner.beforeStart?.(ctx)},async afterStart(ctx){await inner?.afterStart?.(ctx)},async shutdown(){await inner?.shutdown?.()},async onHealthCheck(){return await inner?.onHealthCheck?.()??{name:instanceName,status:`up`}}}},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){}export{ModuleList as _,MissingMountDepError as a,runContributors as c,DuplicateContributorError as d,MissingContributorError as f,MutableModuleRegistry as g,CircuitOpenError as h,DuplicateMountNameError as i,buildPipeline as l,CircuitBreaker as m,defineAdapter as n,MountCycleError as o,defineContextDecorator as p,definePlugin as r,mountSort as s,defineAugmentation as t,ContributorCycleError as u,defineModules as v,defineModule as y};
|
|
13
|
-
//# sourceMappingURL=core-
|
|
13
|
+
//# sourceMappingURL=core-Y_xSqZ7v.mjs.map
|