@forinda/kickjs 5.10.0 → 5.12.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/application-BAVtRjLt.mjs +12 -0
- package/dist/application-BAVtRjLt.mjs.map +1 -0
- package/dist/{application-BpRV6_s8.d.mts → application-BNxhBgji.d.mts} +2 -3
- package/dist/application-BNxhBgji.d.mts.map +1 -0
- package/dist/{bootstrap-2i95JKev.mjs → bootstrap-DpnpCnL0.mjs} +3 -3
- package/dist/{bootstrap-2i95JKev.mjs.map → bootstrap-DpnpCnL0.mjs.map} +1 -1
- package/dist/{bootstrap-DJ3Qutd_.d.mts → bootstrap-qvftPBfr.d.mts} +2 -2
- package/dist/{bootstrap-DJ3Qutd_.d.mts.map → bootstrap-qvftPBfr.d.mts.map} +1 -1
- package/dist/config/index.mjs +2 -2
- package/dist/{config-DGr5YzRC.mjs → config-DF9KJwp8.mjs} +3 -3
- package/dist/{config-DGr5YzRC.mjs.map → config-DF9KJwp8.mjs.map} +1 -1
- package/dist/{container-L0a0Fr7l.mjs → container-Dwl5vSSQ.mjs} +3 -3
- package/dist/{container-L0a0Fr7l.mjs.map → container-Dwl5vSSQ.mjs.map} +1 -1
- package/dist/{context-CTFsdvjK.mjs → context-Cm6r9rSR.mjs} +3 -3
- package/dist/{context-CTFsdvjK.mjs.map → context-Cm6r9rSR.mjs.map} +1 -1
- package/dist/core/adapter.mjs +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.mjs +1 -1
- package/dist/core/interfaces.mjs +1 -1
- package/dist/core/logger.d.mts +2 -2
- package/dist/core/logger.mjs +2 -2
- package/dist/core/logger.mjs.map +1 -1
- package/dist/core/path.mjs +1 -1
- package/dist/core/plugin.mjs +1 -1
- package/dist/core/reactivity.mjs +1 -1
- package/dist/{core-BW7iWK85.mjs → core-pTiSM6v2.mjs} +3 -3
- package/dist/{core-BW7iWK85.mjs.map → core-pTiSM6v2.mjs.map} +1 -1
- package/dist/{env-DZNbXR4Y.mjs → env-iO4nTPjc.mjs} +3 -3
- package/dist/{env-DZNbXR4Y.mjs.map → env-iO4nTPjc.mjs.map} +1 -1
- 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.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.mjs +2 -2
- package/dist/http/middleware/upload.mjs +3 -2
- package/dist/http/middleware/upload.mjs.map +1 -1
- package/dist/http/middleware/validate.mjs +2 -2
- package/dist/http/middleware/views.mjs +2 -2
- package/dist/http/query/index.mjs +2 -2
- package/dist/http/router-builder.mjs +2 -2
- package/dist/http/router-builder.mjs.map +1 -1
- package/dist/index-qZqR_Mxr.d.mts.map +1 -1
- package/dist/index.d.mts +4 -4
- package/dist/index.mjs +2 -2
- package/dist/index.mjs.map +1 -1
- package/dist/{logger-CLVRZf2N.d.mts → logger-SKhhzmU2.d.mts} +36 -22
- package/dist/logger-SKhhzmU2.d.mts.map +1 -0
- package/dist/{metadata-Zbr39cFH.mjs → metadata-PnPdY-2N.mjs} +2 -2
- package/dist/{metadata-Zbr39cFH.mjs.map → metadata-PnPdY-2N.mjs.map} +1 -1
- package/dist/{query-DJ3dOObD.mjs → query-bbA6sG2R.mjs} +2 -2
- package/dist/{query-DJ3dOObD.mjs.map → query-bbA6sG2R.mjs.map} +1 -1
- package/dist/router-builder-R6dyZ-A3.d.mts.map +1 -1
- package/dist/upload-5goxbO9A.d.mts.map +1 -1
- package/package.json +6 -6
- package/dist/application-BpRV6_s8.d.mts.map +0 -1
- package/dist/application-CTsF-R68.mjs +0 -12
- package/dist/application-CTsF-R68.mjs.map +0 -1
- package/dist/logger-CLVRZf2N.d.mts.map +0 -1
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* @forinda/kickjs v5.
|
|
2
|
+
* @forinda/kickjs v5.12.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}from"../../core/logger.mjs";import"../../core-
|
|
11
|
+
import{createLogger}from"../../core/logger.mjs";import"../../core-pTiSM6v2.mjs";import{HttpException}from"../../core/errors.mjs";const log=createLogger(`ErrorHandler`);function notFoundHandler(){return(_req,res,_next)=>{res.status(404).json({message:`Not Found`})}}function errorHandler(){let isProduction=process.env.NODE_ENV===`production`;return(err,req,res,_next)=>{if(res.headersSent){log.warn(`Error after headers sent: ${err?.message||`Unknown`}`);return}if(err?.name===`ZodError`){let firstIssue=err.issues?.[0];return res.status(422).json({message:firstIssue?.message||`Validation failed`,...isProduction?{}:{errors:err.issues}})}if(err instanceof HttpException){if(err.status>=500&&log.error(err,err.message),err.headers)for(let[k,v]of Object.entries(err.headers))res.setHeader(k,v);let exposeDetails=!isProduction&&err.details!==void 0;return res.status(err.status).json({message:err.message,...exposeDetails?{errors:err.details}:{}})}let status=err.status||err.statusCode||500;log.error(err,`${req.method} ${req.originalUrl} — ${err.message||`Unhandled error`}`);let message=status===500?`Internal Server Error`:err.message||`Error`;res.status(status).json({message})}}export{errorHandler,notFoundHandler};
|
|
12
12
|
//# sourceMappingURL=error-handler.mjs.map
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* @forinda/kickjs v5.
|
|
2
|
+
* @forinda/kickjs v5.12.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}from"../../core/logger.mjs";import"../../core-
|
|
11
|
+
import{createLogger}from"../../core/logger.mjs";import"../../core-pTiSM6v2.mjs";function requestLogger(options={}){let log=createLogger(options.name??`HTTP`),level=options.level??`info`,skip=options.skip??[];return(req,res,next)=>{if(skip.some(prefix=>req.path.startsWith(prefix)))return next();let start=Date.now();res.on(`finish`,()=>{let duration=Date.now()-start,requestId=req.requestId||req.headers[`x-request-id`]||`-`,status=res.statusCode;log[level](`${req.method} ${req.originalUrl} ${status} ${duration}ms ${requestId}`)}),next()}}export{requestLogger};
|
|
12
12
|
//# sourceMappingURL=request-logger.mjs.map
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* @forinda/kickjs v5.
|
|
2
|
+
* @forinda/kickjs v5.12.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{h as __require}from"../../container-
|
|
11
|
+
import{h as __require}from"../../container-Dwl5vSSQ.mjs";import{Logger}from"../../core/logger.mjs";import"../../core-pTiSM6v2.mjs";import{existsSync,readFileSync}from"node:fs";import{join,resolve}from"node:path";const log=Logger.for(`SpaAdapter`);var SpaAdapter=class{options;name=`SpaAdapter`;clientDir;apiPrefixes;excludePaths;cacheControl;indexCacheControl;indexHtml=null;constructor(options={}){this.options=options,this.clientDir=resolve(options.clientDir??`dist/client`),this.excludePaths=options.exclude??[],this.cacheControl=options.cacheControl??`public, max-age=31536000, immutable`,this.indexCacheControl=options.indexCacheControl??`no-cache`;let prefix=options.apiPrefix??`/api`;this.apiPrefixes=Array.isArray(prefix)?prefix:[prefix]}beforeMount({app}){if(!existsSync(this.clientDir)){log.warn(`SPA client directory not found: ${this.clientDir}`),log.warn(`Build your frontend first, or set clientDir to the correct path.`);return}let indexPath=join(this.clientDir,`index.html`);if(existsSync(indexPath))this.indexHtml=readFileSync(indexPath,`utf-8`);else{log.warn(`index.html not found in ${this.clientDir}`);return}try{let express=__require(`express`),staticOpts={};this.cacheControl&&(staticOpts.setHeaders=(res,filePath)=>{filePath.endsWith(`.html`)?res.setHeader(`Cache-Control`,this.indexCacheControl):res.setHeader(`Cache-Control`,this.cacheControl)}),app.use(express.static(this.clientDir,staticOpts))}catch{log.error(`express.static not available — SPA static file serving disabled`);return}log.debug(`Serving SPA from ${this.clientDir}`)}beforeStart({app}){this.indexHtml&&app.use((req,res,next)=>{for(let prefix of this.apiPrefixes)if(req.path.startsWith(prefix))return next();for(let path of this.excludePaths)if(req.path.startsWith(path))return next();if(req.path.includes(`.`)||req.method!==`GET`)return next();res.setHeader(`Content-Type`,`text/html`),res.setHeader(`Cache-Control`,this.indexCacheControl),res.send(this.indexHtml)})}};export{SpaAdapter};
|
|
12
12
|
//# sourceMappingURL=spa.mjs.map
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* @forinda/kickjs v5.
|
|
2
|
+
* @forinda/kickjs v5.12.0
|
|
3
3
|
*
|
|
4
4
|
* Copyright (c) Felix Orinda
|
|
5
5
|
*
|
|
@@ -8,5 +8,6 @@
|
|
|
8
8
|
*
|
|
9
9
|
* @license MIT
|
|
10
10
|
*/
|
|
11
|
-
import{
|
|
11
|
+
import{createRequire}from"node:module";import{unlink}from"node:fs/promises";const requireFromHere=createRequire(import.meta.url);let _multer;function loadMulter(){if(_multer)return _multer;try{return _multer=requireFromHere(`multer`),_multer}catch{throw Error(`@forinda/kickjs: file uploads require the 'multer' package, which is not installed.
|
|
12
|
+
Install it as a peer dependency: pnpm add multer (or npm i multer / yarn add multer).`)}}const MIME_MAP={jpg:`image/jpeg`,jpeg:`image/jpeg`,png:`image/png`,gif:`image/gif`,webp:`image/webp`,svg:`image/svg+xml`,bmp:`image/bmp`,ico:`image/x-icon`,tiff:`image/tiff`,tif:`image/tiff`,avif:`image/avif`,pdf:`application/pdf`,doc:`application/msword`,docx:`application/vnd.openxmlformats-officedocument.wordprocessingml.document`,xls:`application/vnd.ms-excel`,xlsx:`application/vnd.openxmlformats-officedocument.spreadsheetml.sheet`,ppt:`application/vnd.ms-powerpoint`,pptx:`application/vnd.openxmlformats-officedocument.presentationml.presentation`,odt:`application/vnd.oasis.opendocument.text`,ods:`application/vnd.oasis.opendocument.spreadsheet`,odp:`application/vnd.oasis.opendocument.presentation`,rtf:`application/rtf`,txt:`text/plain`,csv:`text/csv`,zip:`application/zip`,gz:`application/gzip`,tar:`application/x-tar`,rar:`application/vnd.rar`,"7z":`application/x-7z-compressed`,mp3:`audio/mpeg`,wav:`audio/wav`,ogg:`audio/ogg`,flac:`audio/flac`,aac:`audio/aac`,mp4:`video/mp4`,webm:`video/webm`,avi:`video/x-msvideo`,mov:`video/quicktime`,mkv:`video/x-matroska`,json:`application/json`,xml:`application/xml`,html:`text/html`};function resolveMimeTypes(types){return types.map(t=>MIME_MAP[t.toLowerCase().replace(/^\./,``)]??t)}function createMulter(options){let mimeMap=options.customMimeMap?{...MIME_MAP,...options.customMimeMap}:MIME_MAP,limits={fileSize:options.maxSize??5*1024*1024},fileFilter;if(typeof options.allowedTypes==`function`){let filterFn=options.allowedTypes;fileFilter=(_req,file,cb)=>{filterFn(file.mimetype,file.originalname)?cb(null,!0):cb(Error(`File type ${file.mimetype} is not allowed`))}}else if(Array.isArray(options.allowedTypes)){let resolvedTypes=options.allowedTypes.map(t=>mimeMap[t.toLowerCase().replace(/^\./,``)]??t);fileFilter=(_req,file,cb)=>{resolvedTypes.some(type=>type.endsWith(`/*`)?file.mimetype.startsWith(type.replace(`/*`,`/`)):file.mimetype===type)?cb(null,!0):cb(Error(`File type ${file.mimetype} is not allowed`))}}let multerOptions={limits,...fileFilter?{fileFilter}:{},...options.storage?{storage:options.storage}:{},...options.dest?{dest:options.dest}:{}};return loadMulter()(multerOptions)}function single(fieldName,options={}){return createMulter(options).single(fieldName)}function array(fieldName,maxCount=10,options={}){return createMulter(options).array(fieldName,maxCount)}function none(options={}){return createMulter(options).none()}function cleanupFiles(){return(req,res,next)=>{res.on(`finish`,async()=>{let files=[];if(req.file?.path&&files.push(req.file),Array.isArray(req.files))for(let f of req.files)f?.path&&files.push(f);for(let file of files)try{await unlink(file.path)}catch{}}),next()}}function buildUploadMiddleware(config){let options={};config.maxSize&&(options.maxSize=config.maxSize),config.allowedTypes&&(options.allowedTypes=config.allowedTypes),config.customMimeMap&&(options.customMimeMap=config.customMimeMap);let fieldName=config.fieldName??`file`;switch(config.mode){case`single`:return single(fieldName,options);case`array`:return array(fieldName,config.maxCount??10,options);case`none`:return none(options)}}const upload={single,array,none};export{buildUploadMiddleware,cleanupFiles,resolveMimeTypes,upload};
|
|
12
13
|
//# sourceMappingURL=upload.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"upload.mjs","names":[],"sources":["../../../src/http/middleware/upload.ts"],"sourcesContent":["import { unlink } from 'node:fs/promises'\nimport type { Request, Response, NextFunction, RequestHandler } from 'express'\nimport multer, { type Options as MulterOptions } from 'multer'\nimport type { BaseUploadOptions, FileUploadConfig } from '../../core'\n\n/**\n * Maps short file extensions to their MIME types.\n * Users can pass `['jpg', 'png', 'pdf']` instead of full MIME strings.\n */\nconst MIME_MAP: Record<string, string> = {\n // Images\n jpg: 'image/jpeg',\n jpeg: 'image/jpeg',\n png: 'image/png',\n gif: 'image/gif',\n webp: 'image/webp',\n svg: 'image/svg+xml',\n bmp: 'image/bmp',\n ico: 'image/x-icon',\n tiff: 'image/tiff',\n tif: 'image/tiff',\n avif: 'image/avif',\n // Documents\n pdf: 'application/pdf',\n doc: 'application/msword',\n docx: 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',\n xls: 'application/vnd.ms-excel',\n xlsx: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',\n ppt: 'application/vnd.ms-powerpoint',\n pptx: 'application/vnd.openxmlformats-officedocument.presentationml.presentation',\n odt: 'application/vnd.oasis.opendocument.text',\n ods: 'application/vnd.oasis.opendocument.spreadsheet',\n odp: 'application/vnd.oasis.opendocument.presentation',\n rtf: 'application/rtf',\n txt: 'text/plain',\n csv: 'text/csv',\n // Archives\n zip: 'application/zip',\n gz: 'application/gzip',\n tar: 'application/x-tar',\n rar: 'application/vnd.rar',\n '7z': 'application/x-7z-compressed',\n // Audio\n mp3: 'audio/mpeg',\n wav: 'audio/wav',\n ogg: 'audio/ogg',\n flac: 'audio/flac',\n aac: 'audio/aac',\n // Video\n mp4: 'video/mp4',\n webm: 'video/webm',\n avi: 'video/x-msvideo',\n mov: 'video/quicktime',\n mkv: 'video/x-matroska',\n // Other\n json: 'application/json',\n xml: 'application/xml',\n html: 'text/html',\n}\n\n/**\n * Resolves a list of file type identifiers to MIME type strings.\n * Accepts short extensions (`'jpg'`, `'pdf'`) or full MIME types (`'image/jpeg'`).\n *\n * @example\n * ```ts\n * resolveMimeTypes(['jpg', 'png', 'application/pdf'])\n * // → ['image/jpeg', 'image/png', 'application/pdf']\n * ```\n */\nexport function resolveMimeTypes(types: string[]): string[] {\n return types.map((t) => {\n const lower = t.toLowerCase().replace(/^\\./, '')\n return MIME_MAP[lower] ?? t\n })\n}\n\n/**\n * Upload options for the middleware.\n * Extends BaseUploadOptions from core (shared with @FileUpload decorator)\n * and adds Multer-specific storage options.\n */\nexport interface UploadOptions extends BaseUploadOptions {\n /** Multer storage config (default: memory storage) */\n storage?: MulterOptions['storage']\n /** Multer dest for disk storage shorthand */\n dest?: string\n}\n\nfunction createMulter(options: UploadOptions) {\n const mimeMap = options.customMimeMap ? { ...MIME_MAP, ...options.customMimeMap } : MIME_MAP\n\n const limits: MulterOptions['limits'] = {\n fileSize: options.maxSize ?? 5 * 1024 * 1024,\n }\n\n let fileFilter: MulterOptions['fileFilter'] | undefined\n\n if (typeof options.allowedTypes === 'function') {\n // Custom filter function\n const filterFn = options.allowedTypes\n fileFilter = (_req, file, cb) => {\n if (filterFn(file.mimetype, file.originalname)) {\n cb(null, true)\n } else {\n cb(new Error(`File type ${file.mimetype} is not allowed`))\n }\n }\n } else if (Array.isArray(options.allowedTypes)) {\n // String array — resolve short extensions using the (possibly extended) MIME map\n const resolvedTypes = options.allowedTypes.map((t) => {\n const lower = t.toLowerCase().replace(/^\\./, '')\n return mimeMap[lower] ?? t\n })\n fileFilter = (_req, file, cb) => {\n const allowed = resolvedTypes.some((type) => {\n if (type.endsWith('/*')) {\n return file.mimetype.startsWith(type.replace('/*', '/'))\n }\n return file.mimetype === type\n })\n if (allowed) {\n cb(null, true)\n } else {\n cb(new Error(`File type ${file.mimetype} is not allowed`))\n }\n }\n }\n\n const multerOptions: MulterOptions = {\n limits,\n ...(fileFilter ? { fileFilter } : {}),\n ...(options.storage ? { storage: options.storage } : {}),\n ...(options.dest ? { dest: options.dest } : {}),\n }\n\n return multer(multerOptions)\n}\n\n/**\n * Single file upload middleware. Attaches the file to `req.file`.\n *\n * @example\n * ```ts\n * @Post('/avatar')\n * @Middleware(upload.single('avatar', { maxSize: 2 * 1024 * 1024, allowedTypes: ['jpg', 'png'] }))\n * async uploadAvatar(ctx: RequestContext) {\n * ctx.json({ filename: ctx.file.originalname })\n * }\n * ```\n */\nfunction single(fieldName: string, options: UploadOptions = {}): RequestHandler {\n const m = createMulter(options)\n return m.single(fieldName) as RequestHandler\n}\n\n/**\n * Multiple file upload middleware. Attaches files to `req.files`.\n */\nfunction array(fieldName: string, maxCount = 10, options: UploadOptions = {}): RequestHandler {\n const m = createMulter(options)\n return m.array(fieldName, maxCount) as RequestHandler\n}\n\n/**\n * No file upload — just parse multipart form data without file fields.\n */\nfunction none(options: UploadOptions = {}): RequestHandler {\n const m = createMulter(options)\n return m.none() as RequestHandler\n}\n\n/**\n * Removes temporary files from disk after the response is sent.\n * Attach this as Express middleware after the upload middleware.\n * Works with both `req.file` (single) and `req.files` (array).\n *\n * @example\n * ```ts\n * @Post('/process')\n * @Middleware(upload.single('document', { dest: '/tmp/uploads' }), cleanupFiles())\n * async processDocument(ctx: RequestContext) {\n * ctx.json({ ok: true })\n * }\n * ```\n */\nexport function cleanupFiles() {\n return (req: Request, res: Response, next: NextFunction) => {\n res.on('finish', async () => {\n const files: any[] = []\n\n if ((req as any).file?.path) {\n files.push((req as any).file)\n }\n if (Array.isArray((req as any).files)) {\n for (const f of (req as any).files) {\n if (f?.path) files.push(f)\n }\n }\n\n for (const file of files) {\n try {\n await unlink(file.path)\n } catch {\n // File may already be moved/deleted by the handler — ignore\n }\n }\n })\n\n next()\n }\n}\n\n/**\n * Build upload middleware from a @FileUpload decorator config.\n * Used internally by the router builder when it detects FILE_UPLOAD metadata.\n * Accepts the same FileUploadConfig interface used by the @FileUpload decorator.\n */\nexport function buildUploadMiddleware(config: FileUploadConfig): RequestHandler {\n const options: UploadOptions = {}\n if (config.maxSize) options.maxSize = config.maxSize\n if (config.allowedTypes) options.allowedTypes = config.allowedTypes\n if (config.customMimeMap) options.customMimeMap = config.customMimeMap\n\n const fieldName = config.fieldName ?? 'file'\n\n switch (config.mode) {\n case 'single':\n return single(fieldName, options)\n case 'array':\n return array(fieldName, config.maxCount ?? 10, options)\n case 'none':\n return none(options)\n }\n}\n\n/** Upload middleware factory with `.single()`, `.array()`, `.none()` methods */\nexport const upload = { single, array, none }\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"upload.mjs","names":[],"sources":["../../../src/http/middleware/upload.ts"],"sourcesContent":["import { unlink } from 'node:fs/promises'\nimport { createRequire } from 'node:module'\nimport type { Request, Response, NextFunction, RequestHandler } from 'express'\nimport type { Options as MulterOptions } from 'multer'\nimport type { BaseUploadOptions, FileUploadConfig } from '../../core'\n\n// `multer` is an optional peer dependency. We load it lazily via\n// `createRequire` so importing this module never touches `multer` —\n// only constructing an upload middleware does. Adopters who never\n// call `upload.single/array/none()` or use `@FileUpload` don't need\n// `multer` installed at all.\n//\n// multer uses CJS `export = multer`, so the module is itself the\n// callable factory — no `.default` indirection on either the type\n// or the runtime side.\nconst requireFromHere = createRequire(import.meta.url)\ntype MulterFactory = typeof import('multer')\nlet _multer: MulterFactory | undefined\n\nfunction loadMulter(): MulterFactory {\n if (_multer) return _multer\n try {\n _multer = requireFromHere('multer') as MulterFactory\n return _multer\n } catch {\n throw new Error(\n \"@forinda/kickjs: file uploads require the 'multer' package, which is not installed.\\n\" +\n 'Install it as a peer dependency: pnpm add multer (or npm i multer / yarn add multer).',\n )\n }\n}\n\n/**\n * Maps short file extensions to their MIME types.\n * Users can pass `['jpg', 'png', 'pdf']` instead of full MIME strings.\n */\nconst MIME_MAP: Record<string, string> = {\n // Images\n jpg: 'image/jpeg',\n jpeg: 'image/jpeg',\n png: 'image/png',\n gif: 'image/gif',\n webp: 'image/webp',\n svg: 'image/svg+xml',\n bmp: 'image/bmp',\n ico: 'image/x-icon',\n tiff: 'image/tiff',\n tif: 'image/tiff',\n avif: 'image/avif',\n // Documents\n pdf: 'application/pdf',\n doc: 'application/msword',\n docx: 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',\n xls: 'application/vnd.ms-excel',\n xlsx: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',\n ppt: 'application/vnd.ms-powerpoint',\n pptx: 'application/vnd.openxmlformats-officedocument.presentationml.presentation',\n odt: 'application/vnd.oasis.opendocument.text',\n ods: 'application/vnd.oasis.opendocument.spreadsheet',\n odp: 'application/vnd.oasis.opendocument.presentation',\n rtf: 'application/rtf',\n txt: 'text/plain',\n csv: 'text/csv',\n // Archives\n zip: 'application/zip',\n gz: 'application/gzip',\n tar: 'application/x-tar',\n rar: 'application/vnd.rar',\n '7z': 'application/x-7z-compressed',\n // Audio\n mp3: 'audio/mpeg',\n wav: 'audio/wav',\n ogg: 'audio/ogg',\n flac: 'audio/flac',\n aac: 'audio/aac',\n // Video\n mp4: 'video/mp4',\n webm: 'video/webm',\n avi: 'video/x-msvideo',\n mov: 'video/quicktime',\n mkv: 'video/x-matroska',\n // Other\n json: 'application/json',\n xml: 'application/xml',\n html: 'text/html',\n}\n\n/**\n * Resolves a list of file type identifiers to MIME type strings.\n * Accepts short extensions (`'jpg'`, `'pdf'`) or full MIME types (`'image/jpeg'`).\n *\n * @example\n * ```ts\n * resolveMimeTypes(['jpg', 'png', 'application/pdf'])\n * // → ['image/jpeg', 'image/png', 'application/pdf']\n * ```\n */\nexport function resolveMimeTypes(types: string[]): string[] {\n return types.map((t) => {\n const lower = t.toLowerCase().replace(/^\\./, '')\n return MIME_MAP[lower] ?? t\n })\n}\n\n/**\n * Upload options for the middleware.\n * Extends BaseUploadOptions from core (shared with @FileUpload decorator)\n * and adds Multer-specific storage options.\n */\nexport interface UploadOptions extends BaseUploadOptions {\n /** Multer storage config (default: memory storage) */\n storage?: MulterOptions['storage']\n /** Multer dest for disk storage shorthand */\n dest?: string\n}\n\nfunction createMulter(options: UploadOptions) {\n const mimeMap = options.customMimeMap ? { ...MIME_MAP, ...options.customMimeMap } : MIME_MAP\n\n const limits: MulterOptions['limits'] = {\n fileSize: options.maxSize ?? 5 * 1024 * 1024,\n }\n\n let fileFilter: MulterOptions['fileFilter'] | undefined\n\n if (typeof options.allowedTypes === 'function') {\n // Custom filter function\n const filterFn = options.allowedTypes\n fileFilter = (_req, file, cb) => {\n if (filterFn(file.mimetype, file.originalname)) {\n cb(null, true)\n } else {\n cb(new Error(`File type ${file.mimetype} is not allowed`))\n }\n }\n } else if (Array.isArray(options.allowedTypes)) {\n // String array — resolve short extensions using the (possibly extended) MIME map\n const resolvedTypes = options.allowedTypes.map((t) => {\n const lower = t.toLowerCase().replace(/^\\./, '')\n return mimeMap[lower] ?? t\n })\n fileFilter = (_req, file, cb) => {\n const allowed = resolvedTypes.some((type) => {\n if (type.endsWith('/*')) {\n return file.mimetype.startsWith(type.replace('/*', '/'))\n }\n return file.mimetype === type\n })\n if (allowed) {\n cb(null, true)\n } else {\n cb(new Error(`File type ${file.mimetype} is not allowed`))\n }\n }\n }\n\n const multerOptions: MulterOptions = {\n limits,\n ...(fileFilter ? { fileFilter } : {}),\n ...(options.storage ? { storage: options.storage } : {}),\n ...(options.dest ? { dest: options.dest } : {}),\n }\n\n return loadMulter()(multerOptions)\n}\n\n/**\n * Single file upload middleware. Attaches the file to `req.file`.\n *\n * @example\n * ```ts\n * @Post('/avatar')\n * @Middleware(upload.single('avatar', { maxSize: 2 * 1024 * 1024, allowedTypes: ['jpg', 'png'] }))\n * async uploadAvatar(ctx: RequestContext) {\n * ctx.json({ filename: ctx.file.originalname })\n * }\n * ```\n */\nfunction single(fieldName: string, options: UploadOptions = {}): RequestHandler {\n const m = createMulter(options)\n return m.single(fieldName) as RequestHandler\n}\n\n/**\n * Multiple file upload middleware. Attaches files to `req.files`.\n */\nfunction array(fieldName: string, maxCount = 10, options: UploadOptions = {}): RequestHandler {\n const m = createMulter(options)\n return m.array(fieldName, maxCount) as RequestHandler\n}\n\n/**\n * No file upload — just parse multipart form data without file fields.\n */\nfunction none(options: UploadOptions = {}): RequestHandler {\n const m = createMulter(options)\n return m.none() as RequestHandler\n}\n\n/**\n * Removes temporary files from disk after the response is sent.\n * Attach this as Express middleware after the upload middleware.\n * Works with both `req.file` (single) and `req.files` (array).\n *\n * @example\n * ```ts\n * @Post('/process')\n * @Middleware(upload.single('document', { dest: '/tmp/uploads' }), cleanupFiles())\n * async processDocument(ctx: RequestContext) {\n * ctx.json({ ok: true })\n * }\n * ```\n */\nexport function cleanupFiles() {\n return (req: Request, res: Response, next: NextFunction) => {\n res.on('finish', async () => {\n const files: any[] = []\n\n if ((req as any).file?.path) {\n files.push((req as any).file)\n }\n if (Array.isArray((req as any).files)) {\n for (const f of (req as any).files) {\n if (f?.path) files.push(f)\n }\n }\n\n for (const file of files) {\n try {\n await unlink(file.path)\n } catch {\n // File may already be moved/deleted by the handler — ignore\n }\n }\n })\n\n next()\n }\n}\n\n/**\n * Build upload middleware from a @FileUpload decorator config.\n * Used internally by the router builder when it detects FILE_UPLOAD metadata.\n * Accepts the same FileUploadConfig interface used by the @FileUpload decorator.\n */\nexport function buildUploadMiddleware(config: FileUploadConfig): RequestHandler {\n const options: UploadOptions = {}\n if (config.maxSize) options.maxSize = config.maxSize\n if (config.allowedTypes) options.allowedTypes = config.allowedTypes\n if (config.customMimeMap) options.customMimeMap = config.customMimeMap\n\n const fieldName = config.fieldName ?? 'file'\n\n switch (config.mode) {\n case 'single':\n return single(fieldName, options)\n case 'array':\n return array(fieldName, config.maxCount ?? 10, options)\n case 'none':\n return none(options)\n }\n}\n\n/** Upload middleware factory with `.single()`, `.array()`, `.none()` methods */\nexport const upload = { single, array, none }\n"],"mappings":"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"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* @forinda/kickjs v5.
|
|
2
|
+
* @forinda/kickjs v5.12.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"../../core-
|
|
11
|
+
import"../../core-pTiSM6v2.mjs";import{HttpException,HttpStatus}from"../../core/errors.mjs";function toValidationException(error,message,useFirstIssueMessage){let issues=error.issues||[],details=issues.map(i=>({field:i.path?.join(`.`)??``,message:i.message})),finalMessage=useFirstIssueMessage?issues[0]?.message??message:message;return new HttpException(HttpStatus.UNPROCESSABLE_ENTITY,finalMessage,details)}function assignReqProperty(req,key,value){Object.defineProperty(req,key,{value,writable:!0,configurable:!0,enumerable:!0})}function validate(schema){return(req,_res,next)=>{try{if(schema.body){let result=schema.body.safeParse(req.body);if(!result.success)return next(toValidationException(result.error,`Validation failed`,!0));req.body=result.data}if(schema.query){let result=schema.query.safeParse(req.query);if(!result.success)return next(toValidationException(result.error,`Invalid query parameters`,!1));assignReqProperty(req,`query`,result.data)}if(schema.params){let result=schema.params.safeParse(req.params);if(!result.success)return next(toValidationException(result.error,`Invalid path parameters`,!1));assignReqProperty(req,`params`,result.data)}next()}catch(err){next(err)}}}export{validate};
|
|
12
12
|
//# sourceMappingURL=validate.mjs.map
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* @forinda/kickjs v5.
|
|
2
|
+
* @forinda/kickjs v5.12.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{n as defineAdapter}from"../../core-
|
|
11
|
+
import{Logger}from"../../core/logger.mjs";import{n as defineAdapter}from"../../core-pTiSM6v2.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 v5.
|
|
2
|
+
* @forinda/kickjs v5.12.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 parseSearchQuery,i as parseQuery,n as parseFilters,o as parseSort,r as parsePagination,s as FILTER_OPERATORS,t as buildQueryParams}from"../../query-
|
|
11
|
+
import{a as parseSearchQuery,i as parseQuery,n as parseFilters,o as parseSort,r as parsePagination,s as FILTER_OPERATORS,t as buildQueryParams}from"../../query-bbA6sG2R.mjs";export{FILTER_OPERATORS,buildQueryParams,parseFilters,parsePagination,parseQuery,parseSearchQuery,parseSort};
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* @forinda/kickjs v5.
|
|
2
|
+
* @forinda/kickjs v5.12.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-Dwl5vSSQ.mjs";import{METADATA}from"../core/interfaces.mjs";import{a as getMethodMeta,o as getMethodMetaOrUndefined,t as getClassMeta}from"../metadata-PnPdY-2N.mjs";import{c as runContributors,l as buildPipeline}from"../core-pTiSM6v2.mjs";import{t as RequestContext}from"../context-Cm6r9rSR.mjs";import{validate}from"./middleware/validate.mjs";import{buildUploadMiddleware}from"./middleware/upload.mjs";import{Router}from"express";let _externalContributorSources=[];function _setExternalContributorSources(sources){_externalContributorSources=sources}function buildRoutes(controllerClass,options={}){let router=Router(),container=Container.getInstance(),externalSources=options.externalSources??_externalContributorSources,routes=getClassMeta(METADATA.ROUTES,controllerClass,[]),classMiddlewares=getClassMeta(METADATA.CLASS_MIDDLEWARES,controllerClass,[]),classContributors=getClassMeta(METADATA.CLASS_CONTRIBUTORS,controllerClass,[]);for(let route of routes){let method=route.method.toLowerCase(),fullPath=route.path||`/`,methodMiddlewares=getMethodMeta(METADATA.METHOD_MIDDLEWARES,controllerClass,route.handlerName,[]),handlers=[];route.validation&&handlers.push(validate(route.validation));let fileUploadConfig=getMethodMetaOrUndefined(METADATA.FILE_UPLOAD,controllerClass,route.handlerName);fileUploadConfig&&handlers.push(buildUploadMiddleware(fileUploadConfig));for(let mw of[...classMiddlewares,...methodMiddlewares])handlers.push((req,res,next)=>{let ctx=new RequestContext(req,res,next);Promise.resolve(mw(ctx,next)).catch(next)});let methodContributors=getMethodMeta(METADATA.METHOD_CONTRIBUTORS,controllerClass,route.handlerName,[]);if(classContributors.length>0||methodContributors.length>0||externalSources.length>0){let pipeline=buildPipeline([...methodContributors.map((registration,i)=>({source:`method`,registration,label:`${controllerClass.name}.${String(route.handlerName)}#${i}(${registration.key})`})),...classContributors.map((registration,i)=>({source:`class`,registration,label:`${controllerClass.name}.@class#${i}(${registration.key})`})),...externalSources],{route:`${route.method.toUpperCase()} ${fullPath}`});handlers.push(async(req,res,next)=>{let ctx=new RequestContext(req,res,next);try{await runContributors({pipeline,ctx,container}),next()}catch(err){next(err)}})}handlers.push(async(req,res,next)=>{let ctx=new RequestContext(req,res,next);try{await container.resolve(controllerClass)[route.handlerName](ctx)}catch(err){next(err)}}),router[method](fullPath,...handlers)}return router}export{_setExternalContributorSources,buildRoutes};
|
|
12
12
|
//# sourceMappingURL=router-builder.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"router-builder.mjs","names":[],"sources":["../../src/http/router-builder.ts"],"sourcesContent":["import { Router, type Request, type Response, type NextFunction } from 'express'\nimport {\n buildPipeline,\n Container,\n METADATA,\n runContributors,\n type ContributorRegistration,\n type FileUploadConfig,\n type MiddlewareHandler,\n type RouteDefinition,\n type SourcedRegistration,\n} from '../core'\nimport { getClassMeta, getMethodMeta, getMethodMetaOrUndefined } from '../core/metadata'\nimport { RequestContext } from './context'\nimport { validate } from './middleware/validate'\nimport { buildUploadMiddleware } from './middleware/upload'\n\n/**\n * Per-module SourcedRegistration[] threaded through the route-mount loop by\n * Application.setup(). Carries module + adapter + global contributors so\n * buildRoutes() can merge them with class + method ones into a single pipeline.\n *\n * Module setup is sequential, so this slot is race-free. Cleared in a finally\n * block after each module mounts. Outside of Application setup the slot is\n * empty — direct buildRoutes() callers (mostly tests) see only class + method\n * contributors unless they pass `externalSources` explicitly.\n *\n * Same idiom as `Container._requestStoreProvider
|
|
1
|
+
{"version":3,"file":"router-builder.mjs","names":[],"sources":["../../src/http/router-builder.ts"],"sourcesContent":["import { Router, type Request, type Response, type NextFunction } from 'express'\nimport {\n buildPipeline,\n Container,\n METADATA,\n runContributors,\n type ContributorRegistration,\n type FileUploadConfig,\n type MiddlewareHandler,\n type RouteDefinition,\n type SourcedRegistration,\n} from '../core'\nimport { getClassMeta, getMethodMeta, getMethodMetaOrUndefined } from '../core/metadata'\nimport { RequestContext } from './context'\nimport { validate } from './middleware/validate'\nimport { buildUploadMiddleware } from './middleware/upload'\n\n/**\n * Per-module SourcedRegistration[] threaded through the route-mount loop by\n * Application.setup(). Carries module + adapter + global contributors so\n * buildRoutes() can merge them with class + method ones into a single pipeline.\n *\n * Module setup is sequential, so this slot is race-free. Cleared in a finally\n * block after each module mounts. Outside of Application setup the slot is\n * empty — direct buildRoutes() callers (mostly tests) see only class + method\n * contributors unless they pass `externalSources` explicitly.\n *\n * Same idiom as `Container._requestStoreProvider`: an internal escape hatch for\n * cross-module wiring without inversion-of-control gymnastics.\n *\n * @internal\n */\nlet _externalContributorSources: readonly SourcedRegistration[] = []\n\n/** @internal — set by Application.setup() before each `mod.routes()` call. */\nexport function _setExternalContributorSources(sources: readonly SourcedRegistration[]): void {\n _externalContributorSources = sources\n}\n\nexport interface BuildRoutesOptions {\n /**\n * Extra contributors to merge into the per-route pipeline at their declared\n * precedence levels. Pass explicitly when calling buildRoutes outside the\n * Application route-mount loop (typically in tests). When omitted, falls\n * back to the slot set by Application.setup().\n */\n externalSources?: readonly SourcedRegistration[]\n}\n\n/**\n * Build an Express Router from a controller class decorated with @Get, @Post, etc.\n * Resolves the controller from the DI container, wraps handlers in RequestContext,\n * and applies class-level and method-level middleware.\n *\n * Routes are registered using only the method-level decorator paths (e.g. @Get('/me') → '/me').\n * The @Controller path is NOT baked into the router — it serves as metadata only\n * (used by Swagger and other adapters for introspection).\n * The module's routes().path is the single source of truth for the mount prefix,\n * which avoids path doubling when both the module and controller specify the same path.\n */\nexport function buildRoutes(controllerClass: any, options: BuildRoutesOptions = {}): Router {\n const router = Router()\n const container = Container.getInstance()\n const externalSources = options.externalSources ?? _externalContributorSources\n const routes: RouteDefinition[] = getClassMeta<RouteDefinition[]>(\n METADATA.ROUTES,\n controllerClass,\n [],\n )\n\n // Class-level middleware\n const classMiddlewares: MiddlewareHandler[] = getClassMeta<MiddlewareHandler[]>(\n METADATA.CLASS_MIDDLEWARES,\n controllerClass,\n [],\n )\n\n // Class-level Context Contributors (#107) — applied to every method on the\n // controller. Method-level contributors are added per-route below.\n const classContributors: ContributorRegistration[] = getClassMeta<ContributorRegistration[]>(\n METADATA.CLASS_CONTRIBUTORS,\n controllerClass,\n [],\n )\n\n for (const route of routes) {\n const method = route.method.toLowerCase() as 'get' | 'post' | 'put' | 'delete' | 'patch'\n const fullPath = route.path || '/'\n\n // Method-level middleware\n const methodMiddlewares: MiddlewareHandler[] = getMethodMeta<MiddlewareHandler[]>(\n METADATA.METHOD_MIDDLEWARES,\n controllerClass,\n route.handlerName,\n [],\n )\n\n // Build handler chain\n const handlers: any[] = []\n\n // Validation middleware (shared with standalone validate() export)\n if (route.validation) {\n handlers.push(validate(route.validation))\n }\n\n // @FileUpload decorator — auto-attach upload middleware from metadata\n const fileUploadConfig = getMethodMetaOrUndefined<FileUploadConfig>(\n METADATA.FILE_UPLOAD,\n controllerClass,\n route.handlerName,\n )\n if (fileUploadConfig) {\n handlers.push(buildUploadMiddleware(fileUploadConfig))\n }\n\n // Class + method middleware (wrapped as Express middleware with error catching)\n for (const mw of [...classMiddlewares, ...methodMiddlewares]) {\n handlers.push((req: Request, res: Response, next: NextFunction) => {\n const ctx = new RequestContext(req, res, next)\n Promise.resolve(mw(ctx, next)).catch(next)\n })\n }\n\n // Context Contributor pipeline (#107) — class + method contributors,\n // built once at mount time so cycle/missing-dep failures abort boot.\n const methodContributors: ContributorRegistration[] = getMethodMeta<ContributorRegistration[]>(\n METADATA.METHOD_CONTRIBUTORS,\n controllerClass,\n route.handlerName,\n [],\n )\n\n if (\n classContributors.length > 0 ||\n methodContributors.length > 0 ||\n externalSources.length > 0\n ) {\n // Labels are surfaced in DuplicateContributorError messages — include\n // the registration's key + the original index so a same-key collision\n // at one precedence level points at the conflicting decorator slot,\n // not just the host method/class.\n const sources: SourcedRegistration[] = [\n ...methodContributors.map(\n (registration, i): SourcedRegistration => ({\n source: 'method',\n registration,\n label: `${controllerClass.name}.${String(route.handlerName)}#${i}(${registration.key})`,\n }),\n ),\n ...classContributors.map(\n (registration, i): SourcedRegistration => ({\n source: 'class',\n registration,\n label: `${controllerClass.name}.@class#${i}(${registration.key})`,\n }),\n ),\n ...externalSources,\n ]\n const pipeline = buildPipeline(sources, {\n route: `${route.method.toUpperCase()} ${fullPath}`,\n })\n\n handlers.push(async (req: Request, res: Response, next: NextFunction) => {\n const ctx = new RequestContext(req, res, next)\n try {\n await runContributors({ pipeline, ctx, container })\n next()\n } catch (err) {\n next(err)\n }\n })\n }\n\n // Main handler — resolve controller per-request to respect DI scoping\n handlers.push(async (req: Request, res: Response, next: NextFunction) => {\n const ctx = new RequestContext(req, res, next)\n try {\n const controller = container.resolve(controllerClass)\n await controller[route.handlerName](ctx)\n } catch (err: any) {\n next(err)\n }\n })\n ;(router as any)[method](fullPath, ...handlers)\n }\n\n return router\n}\n"],"mappings":";;;;;;;;;;sdAgCA,IAAI,4BAA8D,CAAC,EAGnE,SAAgB,+BAA+B,QAA+C,CAC5F,4BAA8B,OAChC,CAuBA,SAAgB,YAAY,gBAAsB,QAA8B,CAAC,EAAW,CAC1F,IAAM,OAAS,OAAO,EAChB,UAAY,UAAU,YAAY,EAClC,gBAAkB,QAAQ,iBAAmB,4BAC7C,OAA4B,aAChC,SAAS,OACT,gBACA,CAAC,CACH,EAGM,iBAAwC,aAC5C,SAAS,kBACT,gBACA,CAAC,CACH,EAIM,kBAA+C,aACnD,SAAS,mBACT,gBACA,CAAC,CACH,EAEA,IAAK,IAAM,SAAS,OAAQ,CAC1B,IAAM,OAAS,MAAM,OAAO,YAAY,EAClC,SAAW,MAAM,MAAQ,IAGzB,kBAAyC,cAC7C,SAAS,mBACT,gBACA,MAAM,YACN,CAAC,CACH,EAGM,SAAkB,CAAC,EAGrB,MAAM,YACR,SAAS,KAAK,SAAS,MAAM,UAAU,CAAC,EAI1C,IAAM,iBAAmB,yBACvB,SAAS,YACT,gBACA,MAAM,WACR,EACI,kBACF,SAAS,KAAK,sBAAsB,gBAAgB,CAAC,EAIvD,IAAK,IAAM,KAAM,CAAC,GAAG,iBAAkB,GAAG,iBAAiB,EACzD,SAAS,MAAM,IAAc,IAAe,OAAuB,CACjE,IAAM,IAAM,IAAI,eAAe,IAAK,IAAK,IAAI,EAC7C,QAAQ,QAAQ,GAAG,IAAK,IAAI,CAAC,EAAE,MAAM,IAAI,CAC3C,CAAC,EAKH,IAAM,mBAAgD,cACpD,SAAS,oBACT,gBACA,MAAM,YACN,CAAC,CACH,EAEA,GACE,kBAAkB,OAAS,GAC3B,mBAAmB,OAAS,GAC5B,gBAAgB,OAAS,EACzB,CAsBA,IAAM,SAAW,cAAc,CAhB7B,GAAG,mBAAmB,KACnB,aAAc,KAA4B,CACzC,OAAQ,SACR,aACA,MAAO,GAAG,gBAAgB,KAAK,GAAG,OAAO,MAAM,WAAW,EAAE,GAAG,EAAE,GAAG,aAAa,IAAI,EACvF,EACF,EACA,GAAG,kBAAkB,KAClB,aAAc,KAA4B,CACzC,OAAQ,QACR,aACA,MAAO,GAAG,gBAAgB,KAAK,UAAU,EAAE,GAAG,aAAa,IAAI,EACjE,EACF,EACA,GAAG,eAEgC,EAAG,CACtC,MAAO,GAAG,MAAM,OAAO,YAAY,EAAE,GAAG,UAC1C,CAAC,EAED,SAAS,KAAK,MAAO,IAAc,IAAe,OAAuB,CACvE,IAAM,IAAM,IAAI,eAAe,IAAK,IAAK,IAAI,EAC7C,GAAI,CACF,MAAM,gBAAgB,CAAE,SAAU,IAAK,SAAU,CAAC,EAClD,KAAK,CACP,OAAS,IAAK,CACZ,KAAK,GAAG,CACV,CACF,CAAC,CACH,CAGA,SAAS,KAAK,MAAO,IAAc,IAAe,OAAuB,CACvE,IAAM,IAAM,IAAI,eAAe,IAAK,IAAK,IAAI,EAC7C,GAAI,CAEF,MADmB,UAAU,QAAQ,eACtB,EAAE,MAAM,aAAa,GAAG,CACzC,OAAS,IAAU,CACjB,KAAK,GAAG,CACV,CACF,CAAC,EACA,OAAgB,QAAQ,SAAU,GAAG,QAAQ,CAChD,CAEA,OAAO,MACT"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index-qZqR_Mxr.d.mts","names":[],"sources":["../src/core/define-plugin.ts","../src/core/define-module.ts","../src/core/define-modules.ts","../src/core/metadata.ts","../src/core/circuit-breaker.ts","../src/core/context-errors.ts","../src/core/contributor-pipeline.ts","../src/core/contributor-runner.ts","../src/core/mount-sort.ts","../src/core/define-adapter.ts","../src/core/asset-keys.ts"],"mappings":";;;;;;;;;;;;UAOiB,mBAAA;;EAEf,IAAA;;EAGA,OAAA
|
|
1
|
+
{"version":3,"file":"index-qZqR_Mxr.d.mts","names":[],"sources":["../src/core/define-plugin.ts","../src/core/define-module.ts","../src/core/define-modules.ts","../src/core/metadata.ts","../src/core/circuit-breaker.ts","../src/core/context-errors.ts","../src/core/contributor-pipeline.ts","../src/core/contributor-runner.ts","../src/core/mount-sort.ts","../src/core/define-adapter.ts","../src/core/asset-keys.ts"],"mappings":"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"}
|
package/dist/index.d.mts
CHANGED
|
@@ -10,13 +10,13 @@ import { i as ModuleRoutes, n as AppModuleClass, r as AppModuleEntry, t as AppMo
|
|
|
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-XrNWj1KQ.mjs";
|
|
11
11
|
import { i as getCronJobs, n as Cron, r as CronJobMeta, t as CRON_META } from "./cron-GNoYydfg.mjs";
|
|
12
12
|
import { i as ValidationError, n as HttpStatus, r as HttpStatusCode, t as HttpException } from "./errors-uaHCeXRz.mjs";
|
|
13
|
-
import {
|
|
13
|
+
import { i as createLogger, n as Logger, r as LoggerProvider, t as ConsoleLoggerProvider } from "./logger-SKhhzmU2.mjs";
|
|
14
14
|
import { n as normalizePath, t as joinPaths } from "./path-Diviu6hv.mjs";
|
|
15
15
|
import { n as ModuleRegistry, r as MutableModuleRegistry, t as KickPlugin } from "./plugin-CyoGnRbq.mjs";
|
|
16
16
|
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-BRvj7bdG.mjs";
|
|
17
17
|
import { $ as PluginFactory, A as CircuitBreakerStats, B as pushMethodMeta, C as buildPipeline, D as CircuitBreaker, E as MissingContributorError, F as getMetaRecord, G as ModuleList, H as setInMetaMap, I as getMethodMeta, J as ModuleFactory, K as defineModules, L as getMethodMetaOrUndefined, M as getClassMeta, N as getClassMetaOrUndefined, O as CircuitBreakerOptions, P as getMetaMap, Q as PluginAsyncOptions, R as hasClassMeta, S as SourcedRegistration, T as DuplicateContributorError, U as setInMetaRecord, V as setClassMeta, W as setMethodMeta, X as BuildContext, Y as defineModule, Z as DefinePluginOptions, _ as RunContributorsOptions, a as groupAssetKeys, b as ContributorPipeline, c as AdapterFactory, d as DuplicateMountNameError, et as definePlugin, f as MissingMountDepError, g as mountSort, h as MountSortItem, i as GroupAssetKeysResult, j as CircuitOpenError, k as CircuitBreakerState, l as DefineAdapterOptions, m as MountKind, n as AssetKeyStrategy, o as stripExt, p as MountCycleError, q as DefineModuleOptions, r as GroupAssetKeysOptions, s as AdapterAsyncOptions, t as AssetKeyPair, u as defineAdapter, v as runContributors, w as ContributorCycleError, x as ContributorSource, y as BuildPipelineOptions, z as pushClassMeta } from "./index-qZqR_Mxr.mjs";
|
|
18
|
-
import { n as ApplicationOptions, r as MiddlewareEntry, t as Application } from "./application-
|
|
19
|
-
import { t as bootstrap } from "./bootstrap-
|
|
18
|
+
import { n as ApplicationOptions, r as MiddlewareEntry, t as Application } from "./application-BNxhBgji.mjs";
|
|
19
|
+
import { t as bootstrap } from "./bootstrap-qvftPBfr.mjs";
|
|
20
20
|
import { _ as SortItem, a as parseSearchQuery, c as FILTER_OPERATORS, d as FilterOperator, f as PaginatedResponse, g as QueryFieldConfig, h as QueryBuilderAdapter, i as parseQuery, l as FieldsOf, m as ParsedQuery, n as parseFilters, o as parseSort, p as PaginationParams, r as parsePagination, t as buildQueryParams, u as FilterItem, y as TypedParsedQuery } from "./index-B9cyOQAe.mjs";
|
|
21
21
|
import { i as RouteShape, n as DeepReadonly, r as RequestContext, t as Ctx } from "./context-C2yPZ22U.mjs";
|
|
22
22
|
import { n as cors, t as CorsOptions } from "./cors-BfgqfLPd.mjs";
|
|
@@ -32,4 +32,4 @@ import { a as upload, i as resolveMimeTypes, n as buildUploadMiddleware, r as cl
|
|
|
32
32
|
import { n as validate } from "./validate-HwAyWTwH.mjs";
|
|
33
33
|
import { a as TraceContextOptions, c as requestScopeMiddleware, d as getRequestValue, f as requestStore, h as isClusterPrimary, i as TraceContext, l as RequestStore, m as ClusterOptions, n as ViewAdapterOptions, o as parseTraceparent, p as defineHttpContextDecorator, r as TRACEPARENT_HEADER, s as traceContext, t as ViewAdapter, u as getRequestStore } from "./views-BvKu3uGv.mjs";
|
|
34
34
|
import { r as buildRoutes } from "./router-builder-R6dyZ-A3.mjs";
|
|
35
|
-
export { ASSETS, ASSET_MANIFEST_VERSION, AdapterAsyncOptions, AdapterContext, AdapterFactory, AdapterMiddleware, AnyContributorRegistration, ApiQueryParams, ApiQueryParamsConfig, ApiQueryParamsConfig as QueryParamsConfig, AppAdapter, AppAdapterClass, AppModule, AppModuleClass, AppModuleEntry, Application, ApplicationOptions, Asset, AssetKey, AssetKeyPair, AssetKeyStrategy, AugmentationMeta, Autowired, BaseUploadOptions, BuildContext, BuildPipelineOptions, Buildable, Builder, BuilderOf, CRON_META, CacheEvict, CacheOptions, CacheProvider, Cacheable, CircuitBreaker, CircuitBreakerOptions, CircuitBreakerState, CircuitBreakerStats, CircuitOpenError, ClassKind, ClusterOptions, ColumnApiQueryParamsConfig, Component, ComputedRef, ConfigService, ConsoleLoggerProvider, Constructor, Container, ContainerChangeEvent, ContainerChangeListener, ContextDecorator, ContextDecoratorSpec, ContextDecoratorTarget, ContextMeta, ContextMetaKey, ContributorCycleError, ContributorPipeline, ContributorRegistration, ContributorRegistrations, ContributorSource, Controller, CorsOptions, Cron, CronJobMeta, CsrfOptions, Ctx, DeepReadonly, DefineAdapterOptions, DefineModuleOptions, DefinePluginOptions, Delete, DepValue, DuplicateContributorError, DuplicateMountNameError, Env, EnvKey, ExecutionContext, FILTER_OPERATORS, FieldsOf, FileTypeFilter, FileUpload, FileUploadConfig, FilterItem, FilterOperator, Get, GroupAssetKeysOptions, GroupAssetKeysResult, HelmetOptions, HttpException, HttpStatus, HttpStatusCode, INJECTION_TOKEN, Inject, Injectable, InjectionToken, IntrospectFn, IntrospectionKind, IntrospectionSnapshot, KickAssets, KickJsPluginName, KickJsPluginRegistry, KickJsRegistry, KickPlugin, Logger, LoggerProvider, METADATA, MaybePromise, MemoryCacheProvider, MetaValue, Middleware, MiddlewareEntry, MiddlewareHandler, MiddlewarePath, MiddlewarePhase, MissingContributorError, MissingMountDepError, ModuleFactory, ModuleList, ModuleRegistry, ModuleRoutes, MountCycleError, MountKind, MountSortItem, MutableModuleRegistry, PaginatedResponse, PaginationParams, ParsedQuery, Patch, PluginAsyncOptions, PluginFactory, Post, PostConstruct, PostConstructStatus, Put, QueryBuilderAdapter, QueryFieldConfig, REQUEST_ID_HEADER, RateLimitOptions, RateLimitStore, Ref, Repository, RequestContext, RequestLoggerOptions, RequestStore, ResolvedDeps, RouteDefinition, RouteShape, RunContributorsOptions, Scope, Service, ServiceOptions, Session, SessionData, SessionOptions, SessionStore, SortItem, SourcedRegistration, SpaAdapter, SpaAdapterOptions, TRACEPARENT_HEADER, TraceContext, TraceContextOptions, TypedConfigService, TypedParsedQuery, UnknownAssetError, UploadOptions, ValidationError, Value, ViewAdapter, ViewAdapterOptions, WatchOptions, assets, baseEnvSchema, bootstrap, buildPipeline, buildQueryParams, buildRoutes, buildUploadMiddleware, cleanupFiles, clearAssetCache, computed, cors, createConfigService, createLogger, createToken, csrf, defineAdapter, defineAugmentation, defineContextDecorator, defineEnv, defineHttpContextDecorator, defineModule, defineModules, definePlugin, errorHandler, getCacheProvider, getClassMeta, getClassMetaOrUndefined, getCronJobs, getEnv, getMetaMap, getMetaRecord, getMethodMeta, getMethodMetaOrUndefined, getRequestStore, getRequestValue, groupAssetKeys, hasClassMeta, helmet, isClusterPrimary, isInjectionToken, isRef, joinPaths, loadEnv, mountSort, normalizeApiQueryParamsConfig, normalizePath, notFoundHandler, parseFilters, parsePagination, parseQuery, parseSearchQuery, parseSort, parseTraceparent, pushClassMeta, pushMethodMeta, rateLimit, reactive, ref, reloadEnv, requestId, requestLogger, requestScopeMiddleware, requestStore, resetEnvCache, resolveAsset, resolveMimeTypes,
|
|
35
|
+
export { ASSETS, ASSET_MANIFEST_VERSION, AdapterAsyncOptions, AdapterContext, AdapterFactory, AdapterMiddleware, AnyContributorRegistration, ApiQueryParams, ApiQueryParamsConfig, ApiQueryParamsConfig as QueryParamsConfig, AppAdapter, AppAdapterClass, AppModule, AppModuleClass, AppModuleEntry, Application, ApplicationOptions, Asset, AssetKey, AssetKeyPair, AssetKeyStrategy, AugmentationMeta, Autowired, BaseUploadOptions, BuildContext, BuildPipelineOptions, Buildable, Builder, BuilderOf, CRON_META, CacheEvict, CacheOptions, CacheProvider, Cacheable, CircuitBreaker, CircuitBreakerOptions, CircuitBreakerState, CircuitBreakerStats, CircuitOpenError, ClassKind, ClusterOptions, ColumnApiQueryParamsConfig, Component, ComputedRef, ConfigService, ConsoleLoggerProvider, Constructor, Container, ContainerChangeEvent, ContainerChangeListener, ContextDecorator, ContextDecoratorSpec, ContextDecoratorTarget, ContextMeta, ContextMetaKey, ContributorCycleError, ContributorPipeline, ContributorRegistration, ContributorRegistrations, ContributorSource, Controller, CorsOptions, Cron, CronJobMeta, CsrfOptions, Ctx, DeepReadonly, DefineAdapterOptions, DefineModuleOptions, DefinePluginOptions, Delete, DepValue, DuplicateContributorError, DuplicateMountNameError, Env, EnvKey, ExecutionContext, FILTER_OPERATORS, FieldsOf, FileTypeFilter, FileUpload, FileUploadConfig, FilterItem, FilterOperator, Get, GroupAssetKeysOptions, GroupAssetKeysResult, HelmetOptions, HttpException, HttpStatus, HttpStatusCode, INJECTION_TOKEN, Inject, Injectable, InjectionToken, IntrospectFn, IntrospectionKind, IntrospectionSnapshot, KickAssets, KickJsPluginName, KickJsPluginRegistry, KickJsRegistry, KickPlugin, Logger, LoggerProvider, METADATA, MaybePromise, MemoryCacheProvider, MetaValue, Middleware, MiddlewareEntry, MiddlewareHandler, MiddlewarePath, MiddlewarePhase, MissingContributorError, MissingMountDepError, ModuleFactory, ModuleList, ModuleRegistry, ModuleRoutes, MountCycleError, MountKind, MountSortItem, MutableModuleRegistry, PaginatedResponse, PaginationParams, ParsedQuery, Patch, PluginAsyncOptions, PluginFactory, Post, PostConstruct, PostConstructStatus, Put, QueryBuilderAdapter, QueryFieldConfig, REQUEST_ID_HEADER, RateLimitOptions, RateLimitStore, Ref, Repository, RequestContext, RequestLoggerOptions, RequestStore, ResolvedDeps, RouteDefinition, RouteShape, RunContributorsOptions, Scope, Service, ServiceOptions, Session, SessionData, SessionOptions, SessionStore, SortItem, SourcedRegistration, SpaAdapter, SpaAdapterOptions, TRACEPARENT_HEADER, TraceContext, TraceContextOptions, TypedConfigService, TypedParsedQuery, UnknownAssetError, UploadOptions, ValidationError, Value, ViewAdapter, ViewAdapterOptions, WatchOptions, assets, baseEnvSchema, bootstrap, buildPipeline, buildQueryParams, buildRoutes, buildUploadMiddleware, cleanupFiles, clearAssetCache, computed, cors, createConfigService, createLogger, createToken, csrf, defineAdapter, defineAugmentation, defineContextDecorator, defineEnv, defineHttpContextDecorator, defineModule, defineModules, definePlugin, errorHandler, getCacheProvider, getClassMeta, getClassMetaOrUndefined, getCronJobs, getEnv, getMetaMap, getMetaRecord, getMethodMeta, getMethodMetaOrUndefined, getRequestStore, getRequestValue, groupAssetKeys, hasClassMeta, helmet, isClusterPrimary, isInjectionToken, isRef, joinPaths, loadEnv, mountSort, normalizeApiQueryParamsConfig, normalizePath, notFoundHandler, parseFilters, parsePagination, parseQuery, parseSearchQuery, parseSort, parseTraceparent, pushClassMeta, pushMethodMeta, rateLimit, reactive, ref, reloadEnv, requestId, requestLogger, requestScopeMiddleware, requestStore, resetEnvCache, resolveAsset, resolveMimeTypes, runContributors, session, setCacheProvider, setClassMeta, setInMetaMap, setInMetaRecord, setMethodMeta, stripExt, toRefs, tokenName, traceContext, unref, upload, useAssets, validate, watch, withBuilder };
|
package/dist/index.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* @forinda/kickjs v5.
|
|
2
|
+
* @forinda/kickjs v5.12.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 UnknownAssetError,c as resolveAsset,d as stripExt,f as INJECTION_TOKEN,i as ASSET_MANIFEST_VERSION,l as useAssets,m as isInjectionToken,n as tokenName,o as assets,p as createToken,r as ASSETS,s as clearAssetCache,t as Container,u as groupAssetKeys}from"./container-
|
|
11
|
+
import{a as UnknownAssetError,c as resolveAsset,d as stripExt,f as INJECTION_TOKEN,i as ASSET_MANIFEST_VERSION,l as useAssets,m as isInjectionToken,n as tokenName,o as assets,p as createToken,r as ASSETS,s as clearAssetCache,t as Container,u as groupAssetKeys}from"./container-Dwl5vSSQ.mjs";import{METADATA,Scope}from"./core/interfaces.mjs";import{ConsoleLoggerProvider,Logger,createLogger}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-PnPdY-2N.mjs";import{ApiQueryParams,Asset,Autowired,Builder,Component,Controller,Delete,FileUpload,Get,Inject,Injectable,Middleware,Patch,Post,PostConstruct,Put,Repository,Service,Value,normalizeApiQueryParamsConfig,withBuilder}from"./core/decorators.mjs";import{_ as ModuleList,a as MissingMountDepError,c as runContributors,d as DuplicateContributorError,f as MissingContributorError,g as MutableModuleRegistry,h as CircuitOpenError,i as DuplicateMountNameError,l as buildPipeline,m as CircuitBreaker,n as defineAdapter,o as MountCycleError,p as defineContextDecorator,r as definePlugin,s as mountSort,t as defineAugmentation,u as ContributorCycleError,v as defineModules,y as defineModule}from"./core-pTiSM6v2.mjs";import{CRON_META,Cron,getCronJobs}from"./core/cron.mjs";import{CacheEvict,Cacheable,MemoryCacheProvider,getCacheProvider,setCacheProvider}from"./core/cache.mjs";import{HttpException,HttpStatus}from"./core/errors.mjs";import{joinPaths,normalizePath}from"./core/path.mjs";import{computed,isRef,reactive,ref,toRefs,unref,watch}from"./core/reactivity.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-Cm6r9rSR.mjs";import{n as requestScopeMiddleware,t as Application}from"./application-BAVtRjLt.mjs";import{a as parseSearchQuery,i as parseQuery,n as parseFilters,o as parseSort,r as parsePagination,s as FILTER_OPERATORS,t as buildQueryParams}from"./query-bbA6sG2R.mjs";import{validate}from"./http/middleware/validate.mjs";import{buildUploadMiddleware,cleanupFiles,resolveMimeTypes,upload}from"./http/middleware/upload.mjs";import{buildRoutes}from"./http/router-builder.mjs";import{a as reloadEnv,i as loadEnv,n as defineEnv,o as resetEnvCache,r as getEnv,t as baseEnvSchema}from"./env-iO4nTPjc.mjs";import{n as isClusterPrimary,t as bootstrap}from"./bootstrap-DpnpCnL0.mjs";import{csrf}from"./http/middleware/csrf.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{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-DF9KJwp8.mjs";import crypto from"node:crypto";function defineHttpContextDecorator(spec){return defineContextDecorator(spec)}const TRACEPARENT_HEADER=`traceparent`,TRACEPARENT_RE=/^([0-9a-f]{2})-([0-9a-f]{32})-([0-9a-f]{16})-([0-9a-f]{2})$/;function generateTraceId(){return crypto.randomBytes(16).toString(`hex`)}function generateSpanId(){return crypto.randomBytes(8).toString(`hex`)}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,HttpException,HttpStatus,INJECTION_TOKEN,Inject,Injectable,Logger,METADATA,MemoryCacheProvider,Middleware,MissingContributorError,MissingMountDepError,ModuleList,MountCycleError,MutableModuleRegistry,Patch,Post,PostConstruct,Put,REQUEST_ID_HEADER,Repository,RequestContext,Scope,Service,SpaAdapter,TRACEPARENT_HEADER,UnknownAssetError,Value,ViewAdapter,assets,baseEnvSchema,bootstrap,buildPipeline,buildQueryParams,buildRoutes,buildUploadMiddleware,cleanupFiles,clearAssetCache,computed,cors,createConfigService,createLogger,createToken,csrf,defineAdapter,defineAugmentation,defineContextDecorator,defineEnv,defineHttpContextDecorator,defineModule,defineModules,definePlugin,errorHandler,getCacheProvider,getClassMeta,getClassMetaOrUndefined,getCronJobs,getEnv,getMetaMap,getMetaRecord,getMethodMeta,getMethodMetaOrUndefined,getRequestStore,getRequestValue,groupAssetKeys,hasClassMeta,helmet,isClusterPrimary,isInjectionToken,isRef,joinPaths,loadEnv,mountSort,normalizeApiQueryParamsConfig,normalizePath,notFoundHandler,parseFilters,parsePagination,parseQuery,parseSearchQuery,parseSort,parseTraceparent,pushClassMeta,pushMethodMeta,rateLimit,reactive,ref,reloadEnv,requestId,requestLogger,requestScopeMiddleware,requestStore,resetEnvCache,resolveAsset,resolveMimeTypes,runContributors,session,setCacheProvider,setClassMeta,setInMetaMap,setInMetaRecord,setMethodMeta,stripExt,toRefs,tokenName,traceContext,unref,upload,useAssets,validate,watch,withBuilder};
|
|
12
12
|
//# sourceMappingURL=index.mjs.map
|
package/dist/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.mjs","names":[],"sources":["../src/http/define-http-context-decorator.ts","../src/http/middleware/trace-context.ts"],"sourcesContent":["/**\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 third generic carries the per-call params shape.\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 *\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 DepValue,\n} from '../core/context-decorator'\nimport type { RequestContext } from './context'\n\nexport function defineHttpContextDecorator<\n K extends string,\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","import crypto from 'node:crypto'\nimport type { Request, Response, NextFunction } from 'express'\nimport { requestStore } from '../request-store'\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 crypto.randomBytes(16).toString('hex')\n}\n\n/**\n * Generate a random 16-hex-character span ID.\n */\nfunction generateSpanId(): string {\n return crypto.randomBytes(8).toString('hex')\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 * middleware: [\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":";;;;;;;;;;
|
|
1
|
+
{"version":3,"file":"index.mjs","names":[],"sources":["../src/http/define-http-context-decorator.ts","../src/http/middleware/trace-context.ts"],"sourcesContent":["/**\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 third generic carries the per-call params shape.\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 *\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 DepValue,\n} from '../core/context-decorator'\nimport type { RequestContext } from './context'\n\nexport function defineHttpContextDecorator<\n K extends string,\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","import crypto from 'node:crypto'\nimport type { Request, Response, NextFunction } from 'express'\nimport { requestStore } from '../request-store'\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 crypto.randomBytes(16).toString('hex')\n}\n\n/**\n * Generate a random 16-hex-character span ID.\n */\nfunction generateSpanId(): string {\n return crypto.randomBytes(8).toString('hex')\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 * middleware: [\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":";;;;;;;;;;upGAyDA,SAAgB,2BAId,KAAgG,CAChG,OAAO,uBAAgD,IAAI,CAC7D,CCvDA,MAAa,mBAAqB,cAG5B,eAAiB,8DA2BvB,SAAS,iBAA0B,CACjC,OAAO,OAAO,YAAY,EAAE,EAAE,SAAS,KAAK,CAC9C,CAKA,SAAS,gBAAyB,CAChC,OAAO,OAAO,YAAY,CAAC,EAAE,SAAS,KAAK,CAC7C,CAMA,SAAgB,iBAAiB,OAAqC,CACpE,IAAM,MAAQ,eAAe,KAAK,OAAO,KAAK,EAAE,YAAY,CAAC,EAC7D,GAAI,CAAC,MAAO,OAAO,KAEnB,IAAM,QAAU,MAAM,GAChB,QAAU,MAAM,GAChB,aAAe,MAAM,GACrB,MAAQ,MAAM,GAWpB,OAPE,UAAY,MACZ,UAAY,oCACZ,eAAiB,mBAEV,KAGF,CAAE,QAAS,QAAS,aAAc,KAAM,CACjD,CAuBA,SAAgB,aAAa,QAA+B,CAAC,EAAG,CAC9D,OAAQ,IAAc,IAAe,OAAuB,CAC1D,IAAM,MAAQ,aAAa,SAAS,EAE9B,kBAAoB,IAAI,QAAQ,oBAChC,IAAM,MAAM,QAAQ,iBAAiB,EAAI,kBAAkB,GAAK,kBAChE,OAAS,IAAM,iBAAiB,GAAG,EAAI,KAEvC,QAAU,QAAQ,SAAW,gBAAgB,EAC7C,OAAS,eAAe,EAG1B,QACF,MAAM,OAAO,IAAI,UAAW,OAAO,EACnC,MAAM,OAAO,IAAI,SAAU,MAAM,EAC7B,SACF,MAAM,OAAO,IAAI,eAAgB,OAAO,YAAY,EACpD,MAAM,OAAO,IAAI,aAAc,OAAO,KAAK,EAC3C,MAAM,OAAO,IAAI,eAAgB,OAAO,OAAO,IAKlD,IAAa,QAAU,QACvB,IAAa,OAAS,OAEnB,QAAQ,mBACV,IAAI,UAAU,gBAAiB,OAAO,EAGxC,KAAK,CACP,CACF"}
|
|
@@ -1,14 +1,33 @@
|
|
|
1
1
|
|
|
2
|
-
import pino from "pino";
|
|
3
|
-
|
|
4
2
|
//#region src/core/logger.d.ts
|
|
5
|
-
/** Root pino logger instance */
|
|
6
|
-
declare const rootLogger: pino.Logger<never, boolean>;
|
|
7
3
|
/**
|
|
8
4
|
* Pluggable logger backend.
|
|
9
5
|
*
|
|
10
|
-
* Implement this interface to
|
|
11
|
-
*
|
|
6
|
+
* Implement this interface to plug in any logging library (pino,
|
|
7
|
+
* winston, bunyan, console, etc.). The framework only ever calls the
|
|
8
|
+
* methods declared here — it doesn't know or care which logger is
|
|
9
|
+
* underneath.
|
|
10
|
+
*
|
|
11
|
+
* Default: `ConsoleLoggerProvider` (zero runtime deps).
|
|
12
|
+
*
|
|
13
|
+
* @example
|
|
14
|
+
* ```ts
|
|
15
|
+
* import pino from 'pino'
|
|
16
|
+
* import { Logger, type LoggerProvider } from '@forinda/kickjs'
|
|
17
|
+
*
|
|
18
|
+
* class PinoProvider implements LoggerProvider {
|
|
19
|
+
* constructor(private p = pino()) {}
|
|
20
|
+
* info(msg, ...args) { this.p.info(msg, ...args) }
|
|
21
|
+
* warn(msg, ...args) { this.p.warn(msg, ...args) }
|
|
22
|
+
* error(msg, ...args) { this.p.error(msg, ...args) }
|
|
23
|
+
* debug(msg, ...args) { this.p.debug(msg, ...args) }
|
|
24
|
+
* child({ component }) { return new PinoProvider(this.p.child({ component })) }
|
|
25
|
+
* }
|
|
26
|
+
*
|
|
27
|
+
* Logger.setProvider(new PinoProvider())
|
|
28
|
+
* ```
|
|
29
|
+
*
|
|
30
|
+
* See `docs/guide/logging.md` for Pino, Winston, and silent-logger recipes.
|
|
12
31
|
*/
|
|
13
32
|
interface LoggerProvider {
|
|
14
33
|
info(msg: string, ...args: any[]): void;
|
|
@@ -23,8 +42,11 @@ interface LoggerProvider {
|
|
|
23
42
|
}): LoggerProvider;
|
|
24
43
|
}
|
|
25
44
|
/**
|
|
26
|
-
*
|
|
27
|
-
*
|
|
45
|
+
* Default provider — emits through `console.*` methods. Zero deps.
|
|
46
|
+
*
|
|
47
|
+
* Swap it for pino, winston, bunyan, or anything else by implementing
|
|
48
|
+
* the `LoggerProvider` interface and calling `Logger.setProvider()`
|
|
49
|
+
* before `bootstrap()`.
|
|
28
50
|
*/
|
|
29
51
|
declare class ConsoleLoggerProvider implements LoggerProvider {
|
|
30
52
|
private prefix;
|
|
@@ -53,8 +75,8 @@ declare class ConsoleLoggerProvider implements LoggerProvider {
|
|
|
53
75
|
* // Shorthand function
|
|
54
76
|
* const log = createLogger('OrderService')
|
|
55
77
|
*
|
|
56
|
-
* // Pluggable backend
|
|
57
|
-
* Logger.setProvider(new
|
|
78
|
+
* // Pluggable backend — see docs/guide/logging.md
|
|
79
|
+
* Logger.setProvider(new MyCustomProvider())
|
|
58
80
|
*
|
|
59
81
|
* // Injectable — auto-named from class
|
|
60
82
|
* class MyService {
|
|
@@ -68,12 +90,6 @@ declare class Logger {
|
|
|
68
90
|
private _provider;
|
|
69
91
|
private _providerVersion;
|
|
70
92
|
private _name?;
|
|
71
|
-
/**
|
|
72
|
-
* Optional context provider for request-scoped log enrichment.
|
|
73
|
-
* Set by the HTTP package to inject requestId from AsyncLocalStorage.
|
|
74
|
-
* Returns extra fields to merge into every log call, or null if outside a request.
|
|
75
|
-
*/
|
|
76
|
-
static _contextProvider: (() => Record<string, any> | null) | null;
|
|
77
93
|
/** Incremented on every setProvider/resetProvider so instances know to refresh */
|
|
78
94
|
private static _providerVersion;
|
|
79
95
|
constructor(name?: string);
|
|
@@ -86,14 +102,14 @@ declare class Logger {
|
|
|
86
102
|
*
|
|
87
103
|
* @example
|
|
88
104
|
* ```ts
|
|
89
|
-
* Logger.setProvider(new
|
|
105
|
+
* Logger.setProvider(new MyWinstonProvider())
|
|
90
106
|
* ```
|
|
91
107
|
*/
|
|
92
108
|
static setProvider(provider: LoggerProvider): void;
|
|
93
109
|
/** Return the currently active provider (useful for testing) */
|
|
94
110
|
static getProvider(): LoggerProvider;
|
|
95
111
|
/**
|
|
96
|
-
* Reset the provider back to the default
|
|
112
|
+
* Reset the provider back to the default `ConsoleLoggerProvider`.
|
|
97
113
|
* Primarily intended for test teardown.
|
|
98
114
|
*/
|
|
99
115
|
static resetProvider(): void;
|
|
@@ -101,8 +117,6 @@ declare class Logger {
|
|
|
101
117
|
static for(name: string): Logger;
|
|
102
118
|
/** Create a child logger with a sub-component name */
|
|
103
119
|
child(name: string): Logger;
|
|
104
|
-
/** Get request context (requestId, etc.) if inside a request */
|
|
105
|
-
private ctx;
|
|
106
120
|
info(msg: string, ...args: any[]): void;
|
|
107
121
|
warn(msg: string, ...args: any[]): void;
|
|
108
122
|
error(msgOrObj: any, msg?: string, ...args: any[]): void;
|
|
@@ -113,5 +127,5 @@ declare class Logger {
|
|
|
113
127
|
/** Shorthand for Logger.for(name) */
|
|
114
128
|
declare function createLogger(name: string): Logger;
|
|
115
129
|
//#endregion
|
|
116
|
-
export {
|
|
117
|
-
//# sourceMappingURL=logger-
|
|
130
|
+
export { createLogger as i, Logger as n, LoggerProvider as r, ConsoleLoggerProvider as t };
|
|
131
|
+
//# sourceMappingURL=logger-SKhhzmU2.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"logger-SKhhzmU2.d.mts","names":[],"sources":["../src/core/logger.ts"],"mappings":";;;AA+BA;;;;;;;;;;;;;;;;;;;;;;;;;;;AAQwD;UARvC,cAAA;EACf,IAAA,CAAK,GAAA,aAAgB,IAAA;EACrB,IAAA,CAAK,GAAA,aAAgB,IAAA;EACrB,KAAA,CAAM,GAAA,aAAgB,IAAA;EACtB,KAAA,CAAM,GAAA,aAAgB,IAAA;EACtB,KAAA,EAAO,GAAA,aAAgB,IAAA;EACvB,KAAA,EAAO,GAAA,aAAgB,IAAA;EAiBX;EAfZ,KAAA,CAAM,QAAA;IAAY,SAAA;EAAA,IAAsB,cAAc;AAAA;;;;;;;;cAY3C,qBAAA,YAAiC,cAAc;EAAA,QAClD,MAAA;cAEI,MAAA;EAAA,QAIJ,GAAA;EAIR,IAAA,CAAK,GAAA,aAAgB,IAAA;EAGrB,IAAA,CAAK,GAAA,aAAgB,IAAA;EAGrB,KAAA,CAAM,GAAA,aAAgB,IAAA;EAGtB,KAAA,CAAM,GAAA,aAAgB,IAAA;EAGtB,KAAA,CAAM,GAAA,aAAgB,IAAA;EAGtB,KAAA,CAAM,GAAA,aAAgB,IAAA;EAGtB,KAAA,CAAM,QAAA;IAAY,SAAA;EAAA,IAAsB,cAAA;AAAA;AAoC1C;;;;;;;;;;;;;;;;;;;;;;;;AAAA,cAAa,MAAA;EAAA,QACH,SAAA;EAAA,QACA,gBAAA;EAAA,QACA,KAAA;EAkER;EAAA,eA/De,gBAAA;cAEH,IAAA;EAiEZ;EAAA,YA1DY,QAAA,CAAA;EA0DS;;;;;;;;;;EAAA,OAxCd,WAAA,CAAY,QAAA,EAAU,cAAA;EA+D7B;EAAA,OAxDO,WAAA,CAAA,GAAe,cAAA;EAwDA;;AAAI;AAO5B;EAPwB,OAhDf,aAAA,CAAA;;SAOA,GAAA,CAAI,IAAA,WAAe,MAAA;EAgDsB;EAtChD,KAAA,CAAM,IAAA,WAAe,MAAA;EAIrB,IAAA,CAAK,GAAA,aAAgB,IAAA;EAIrB,IAAA,CAAK,GAAA,aAAgB,IAAA;EAIrB,KAAA,CAAM,QAAA,OAAe,GAAA,cAAiB,IAAA;EAUtC,KAAA,CAAM,GAAA,aAAgB,IAAA;EAItB,KAAA,CAAM,GAAA,aAAgB,IAAA;EAKtB,KAAA,CAAM,GAAA,aAAgB,IAAA;AAAA;;iBAOR,YAAA,CAAa,IAAA,WAAe,MAAM"}
|