@noxfly/noxus 1.1.2 → 1.1.4
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/noxus.js +1335 -5
- package/dist/noxus.mjs +1257 -5
- package/package.json +1 -1
- package/tsup.config.ts +2 -1
- package/dist/noxus.mjs.map +0 -1
package/dist/noxus.js
CHANGED
|
@@ -3,11 +3,1341 @@
|
|
|
3
3
|
* @license MIT
|
|
4
4
|
* @author NoxFly
|
|
5
5
|
*/
|
|
6
|
-
"use strict";
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
`)??[])[3]?.trim().match(/at (.+?)(?:\..+)? .+$/)?.[1]?.replace("Object","")||"App"}n(I,"getCallee");function O(o){return Qt[o]>=Qt[Xt]}n(O,"canLog");var Xt="log",Qt={debug:0,log:1,info:2,warn:3,error:4};(function(o){function t(c){Xt=c}n(t,"setLogLevel"),o.setLogLevel=t;function e(...c){if(!O("log"))return;let m=I(),f=C(m,"log",o.colors.green);console.log(f,...T(f,c,o.colors.green))}n(e,"log"),o.log=e;function r(...c){if(!O("info"))return;let m=I(),f=C(m,"info",o.colors.blue);console.info(f,...T(f,c,o.colors.blue))}n(r,"info"),o.info=r;function s(...c){if(!O("warn"))return;let m=I(),f=C(m,"warn",o.colors.brown);console.warn(f,...T(f,c,o.colors.brown))}n(s,"warn"),o.warn=s;function a(...c){if(!O("error"))return;let m=I(),f=C(m,"error",o.colors.red);console.error(f,...T(f,c,o.colors.red))}n(a,"error"),o.error=a;function l(...c){if(!O("debug"))return;let m=I(),f=C(m,"debug",o.colors.purple);console.debug(f,...T(f,c,o.colors.purple))}n(l,"debug"),o.debug=l,o.colors={black:"\x1B[0;30m",grey:"\x1B[0;37m",red:"\x1B[0;31m",green:"\x1B[0;32m",brown:"\x1B[0;33m",blue:"\x1B[0;34m",purple:"\x1B[0;35m",darkGrey:"\x1B[1;30m",lightRed:"\x1B[1;31m",lightGreen:"\x1B[1;32m",yellow:"\x1B[1;33m",lightBlue:"\x1B[1;34m",magenta:"\x1B[1;35m",cyan:"\x1B[1;36m",white:"\x1B[1;37m",initial:"\x1B[0m"}})(d||(d={}));var d;function ue(...o){return(t,e)=>{let r;if(e?r=`${t.constructor.name}.${e}`:r=`${t.name}`,J.has(r))throw new Error(`Guard(s) already registered for ${r}`);d.debug(`Registering guard(s) for ${r}: ${o.map(s=>s.name).join(", ")}`),J.set(r,o)}}n(ue,"Authorize");function D(o){let t=`${o}`;return J.get(t)??[]}n(D,"getGuardForController");function G(o,t){let e=`${o}.${t}`;return J.get(e)??[]}n(G,"getGuardForControllerAction");var J=new Map;function S(o){return t=>(e,r)=>{let s=Reflect.getMetadata(U,e.constructor)||[],a={method:o,path:t.trim().replace(/^\/|\/$/g,""),handler:r,guards:G(e.constructor.__controllerName,r)};s.push(a),Reflect.defineMetadata(U,s,e.constructor)}}n(S,"createRouteDecorator");function N(o){return Reflect.getMetadata(U,o)||[]}n(N,"getRouteMetadata");var fe=S("GET"),me=S("POST"),he=S("PUT"),pe=S("PATCH"),ge=S("DELETE"),U=Symbol("ROUTE_METADATA_KEY");function we(o){return t=>{let e=n((a,l)=>{if(a){for(let c of a)if(!Reflect.getMetadata(B,c))throw new Error(`Class ${c.name} in ${l} must be decorated with @Module`)}},"checkModule"),r=n(a=>{if(a){for(let l of a)if(!Reflect.getMetadata(F,l))throw new Error(`Class ${l.name} in providers must be decorated with @Injectable`)}},"checkInjectable"),s=n(a=>{if(a){for(let l of a)if(!Reflect.getMetadata(Y,l))throw new Error(`Class ${l.name} in controllers must be decorated with @Controller`)}},"checkController");e(o.imports,"imports"),e(o.exports,"exports"),r(o.providers),s(o.controllers),Reflect.defineMetadata(B,o,t),x("singleton")(t)}}n(we,"Module");function z(o){return Reflect.getMetadata(B,o)}n(z,"getModuleMetadata");var B=Symbol("MODULE_METADATA_KEY");var Wt=class Wt{static register(t,e){return d.debug(`Registering ${t.name} as ${e}`),h.bindings.has(t)?h:(h.bindings.set(t,{implementation:t,lifetime:e}),e==="singleton"&&h.resolve(t),z(t)?(d.log(`${t.name} dependencies initialized`),h):E(t)?(h.resolve(g)?.registerController(t),h):N(t)?h:Kt(t)?(d.log(`Registered ${t.name} as ${e}`),h):h)}};n(Wt,"InjectorExplorer");var Z=Wt;function x(o="scope"){return t=>{if(typeof t!="function"||!t.prototype)throw new Error(`@Injectable can only be used on classes, not on ${typeof t}`);Reflect.defineMetadata(F,o,t),Z.register(t,o)}}n(x,"Injectable");function Kt(o){return Reflect.getMetadata(F,o)}n(Kt,"getInjectableMetadata");var F=Symbol("INJECTABLE_METADATA_KEY");function xe(o){return t=>{let e={path:o,guards:D(t.name)};Reflect.defineMetadata(Y,e,t),x("scope")(t)}}n(xe,"Controller");function E(o){return Reflect.getMetadata(Y,o)}n(E,"getControllerMetadata");var Y=Symbol("CONTROLLER_METADATA_KEY");function $e(o){return(t,e)=>{let r;if(e?r=`${t.constructor.name}.${e}`:r=`${t.name}`,H.has(r))throw new Error(`Middlewares(s) already registered for ${r}`);d.debug(`Registering middleware(s) for ${r}: ${o.map(s=>s.name).join(", ")}`),H.set(r,o)}}n($e,"UseMiddlewares");function kt(o){let t=`${o}`;return H.get(t)??[]}n(kt,"getMiddlewaresForController");function Jt(o,t){let e=`${o}.${t}`;return H.get(e)??[]}n(Jt,"getMiddlewaresForControllerAction");var H=new Map;var M,Vt=(M=class{constructor(t){i(this,"segment");i(this,"children",[]);i(this,"value");i(this,"isParam");i(this,"paramName");this.segment=t,this.isParam=t.startsWith(":"),this.isParam&&(this.paramName=t.slice(1))}matchChild(t){for(let e of this.children)if(e.isParam||t.startsWith(e.segment))return e}findExactChild(t){return this.children.find(e=>e.segment===t)}addChild(t){this.children.push(t)}},n(M,"RadixNode"),M),Ut=class Ut{constructor(){i(this,"root",new Vt(""))}insert(t,e){let r=this.normalize(t);this.insertRecursive(this.root,r,e)}insertRecursive(t,e,r){if(e.length===0){t.value=r;return}let s=e[0]??"",a=t.children.find(l=>l.isParam===s.startsWith(":")&&(l.isParam||l.segment===s));a||(a=new Vt(s),t.addChild(a)),this.insertRecursive(a,e.slice(1),r)}search(t){let e=this.normalize(t);return this.searchRecursive(this.root,e,{})}searchRecursive(t,e,r){if(e.length===0)return t.value!==void 0?{node:t,params:r}:void 0;let[s,...a]=e;for(let l of t.children)if(l.isParam){let c=l.paramName,m={...r,[c]:s??""};if(a.length===0)return{node:l,params:m};let f=this.searchRecursive(l,a,m);if(f)return f}else if(s===l.segment){if(a.length===0)return{node:l,params:r};let c=this.searchRecursive(l,a,r);if(c)return c}}normalize(t){return["",...t.replace(/^\/+|\/+$/g,"").split("/").filter(Boolean)]}};n(Ut,"RadixTree");var Q=Ut;function Me(o,t,e,r){var s=arguments.length,a=s<3?t:r===null?r=Object.getOwnPropertyDescriptor(t,e):r,l;if(typeof Reflect=="object"&&typeof Reflect.decorate=="function")a=Reflect.decorate(o,t,e,r);else for(var c=o.length-1;c>=0;c--)(l=o[c])&&(a=(s<3?l(a):s>3?l(t,e,a):l(t,e))||a);return s>3&&a&&Object.defineProperty(t,e,a),a}n(Me,"_ts_decorate");var Bt=class Bt{constructor(){i(this,"routes",new Q);i(this,"rootMiddlewares",[])}registerController(t){let e=E(t),r=D(t.name),s=kt(t.name);if(!e)throw new Error(`Missing @Controller decorator on ${t.name}`);let a=N(t);for(let m of a){let f=`${e.path}/${m.path}`.replace(/\/+/g,"/"),p=G(t.name,m.handler),X=Jt(t.name,m.handler),b=new Set([...r,...p]),V=new Set([...s,...X]),W={method:m.method,path:f,controller:t,handler:m.handler,guards:[...b],middlewares:[...V]};this.routes.insert(f+"/"+m.method,W);let te=W.guards.length>0?"<"+W.guards.map(ee=>ee.name).join("|")+">":"";d.log(`Mapped {${W.method} /${f}}${te} route`)}let c=e.guards.length>0?"<"+e.guards.map(m=>m.name).join("|")+">":"";return d.log(`Mapped ${t.name}${c} controller's routes`),this}defineRootMiddleware(t){return d.debug(`Registering root middleware: ${t.name}`),this.rootMiddlewares.push(t),this}async handle(t){d.log(`> Received request: {${t.method} /${t.path}}`);let e=performance.now(),r={requestId:t.id,status:200,body:null,error:void 0};try{let s=this.findRoute(t);if(await this.resolveController(t,r,s),r.status>400)throw new u(r.status,r.error)}catch(s){s instanceof u?(r.status=s.status,r.error=s.message):s instanceof Error?(r.status=500,r.error=s.message||"Internal Server Error"):(r.status=500,r.error="Unknown error occurred")}finally{let s=performance.now(),a=`< ${r.status} ${t.method} /${t.path} ${d.colors.yellow}${Math.round(s-e)}ms${d.colors.initial}`;return r.status<400?d.log(a):r.status<500?d.warn(a):d.error(a),r.error!==void 0&&d.error(r.error),r}}findRoute(t){let e=this.routes.search(t.path);if(e?.node===void 0||e.node.children.length===0)throw new y(`No route matches ${t.method} ${t.path}`);let r=e.node.findExactChild(t.method);if(r?.value===void 0)throw new v(`Method Not Allowed for ${t.method} ${t.path}`);return r.value}async resolveController(t,e,r){let s=t.context.resolve(r.controller);Object.assign(t.params,this.extractParams(t.path,r.path)),await this.runRequestPipeline(t,e,r,s)}async runRequestPipeline(t,e,r,s){let a=[...new Set([...this.rootMiddlewares,...r.middlewares])],l=a.length-1,c=l+r.guards.length,m=-1,f=n(async p=>{if(p<=m)throw new Error("next() called multiple times");if(m=p,p<=l){let b=f.bind(null,p+1);if(await this.runMiddleware(t,e,b,a[p]),e.status>=400)throw new u(e.status,e.error);return}if(p<=c){let b=p-a.length,V=r.guards[b];await this.runGuard(t,V),f(p+1);return}let X=s[r.handler];e.body=await X.call(s,t,e)},"dispatch");await f(0)}async runMiddleware(t,e,r,s){await t.context.resolve(s).invoke(t,e,r)}async runGuard(t,e){if(!await t.context.resolve(e).canActivate(t))throw new A(`Unauthorized for ${t.method} ${t.path}`)}extractParams(t,e){let r=t.split("/"),s=e.split("/"),a={};return s.forEach((l,c)=>{l.startsWith(":")&&(a[l.slice(1)]=r[c]??"")}),a}};n(Bt,"Router");var g=Bt;g=Me([x("singleton")],g);var w=require("electron/main");var Rr=require("reflect-metadata");var Zt=class Zt{constructor(t,e,r,s,a){i(this,"event");i(this,"id");i(this,"method");i(this,"path");i(this,"body");i(this,"context",h.createScope());i(this,"params",{});this.event=t,this.id=e,this.method=r,this.path=s,this.body=a,this.path=s.replace(/^\/|\/$/g,"")}};n(Zt,"Request");var L=Zt;function be(o,t,e,r){var s=arguments.length,a=s<3?t:r===null?r=Object.getOwnPropertyDescriptor(t,e):r,l;if(typeof Reflect=="object"&&typeof Reflect.decorate=="function")a=Reflect.decorate(o,t,e,r);else for(var c=o.length-1;c>=0;c--)(l=o[c])&&(a=(s<3?l(a):s>3?l(t,e,a):l(t,e))||a);return s>3&&a&&Object.defineProperty(t,e,a),a}n(be,"_ts_decorate");function _t(o,t){if(typeof Reflect=="object"&&typeof Reflect.metadata=="function")return Reflect.metadata(o,t)}n(_t,"_ts_metadata");var Ht=class Ht{constructor(t){i(this,"router");i(this,"messagePorts",new Map);i(this,"app");this.router=t}async init(){return w.ipcMain.on("gimme-my-port",this.giveTheRendererAPort.bind(this)),w.app.once("activate",this.onAppActivated.bind(this)),w.app.once("window-all-closed",this.onAllWindowsClosed.bind(this)),console.log(""),this}giveTheRendererAPort(t){let e=t.sender.id;this.messagePorts.has(e)&&this.shutdownChannel(e);let r=new w.MessageChannelMain;this.messagePorts.set(e,r),r.port1.on("message",this.onRendererMessage.bind(this)),r.port1.start(),t.sender.postMessage("port",{senderId:e},[r.port2])}async onRendererMessage(t){let{senderId:e,requestId:r,path:s,method:a,body:l}=t.data,c=this.messagePorts.get(e);if(!c){d.error(`No message channel found for sender ID: ${e}`);return}try{let m=new L(t,r,a,s,l),f=await this.router.handle(m);c.port1.postMessage(f)}catch(m){let f={requestId:r,status:500,body:null,error:m.message||"Internal Server Error"};c.port1.postMessage(f)}}onAppActivated(){process.platform==="darwin"&&w.BrowserWindow.getAllWindows().length===0&&this.app?.onActivated()}shutdownChannel(t){let e=this.messagePorts.get(t);if(!e){d.warn(`No message channel found for sender ID: ${t}`);return}e.port1.off("message",this.onRendererMessage.bind(this)),e.port1.close(),e.port2.close(),this.messagePorts.delete(t)}async onAllWindowsClosed(){this.messagePorts.forEach((t,e)=>{this.shutdownChannel(e)}),this.messagePorts.clear(),this.app?.dispose(),process.platform!=="darwin"&&w.app.quit()}configure(t){return this.app=j(t),this}use(t){return this.router.defineRootMiddleware(t),this}start(){return this.app?.onReady(),this}};n(Ht,"NoxApp");var $=Ht;$=be([x("singleton"),_t("design:type",Function),_t("design:paramtypes",[typeof g>"u"?Object:g])],$);var qt=require("electron/main");async function Re(o){if(!z(o))throw new Error("Root module must be decorated with @Module");await qt.app.whenReady();let t=j($);return await t.init(),t}n(Re,"bootstrapApplication");0&&(module.exports={AppInjector,Authorize,BadGatewayException,BadRequestException,CONTROLLER_METADATA_KEY,ConflictException,Controller,Delete,ForbiddenException,GatewayTimeoutException,Get,HttpVersionNotSupportedException,INJECTABLE_METADATA_KEY,Injectable,InsufficientStorageException,InternalServerException,Logger,LoopDetectedException,MODULE_METADATA_KEY,MethodNotAllowedException,Module,NetworkAuthenticationRequiredException,NetworkConnectTimeoutException,NotAcceptableException,NotExtendedException,NotFoundException,NotImplementedException,NoxApp,Patch,PaymentRequiredException,Post,Put,ROUTE_METADATA_KEY,Request,RequestTimeoutException,ResponseException,RootInjector,Router,ServiceUnavailableException,TooManyRequestsException,UnauthorizedException,UpgradeRequiredException,UseMiddlewares,VariantAlsoNegotiatesException,bootstrapApplication,getControllerMetadata,getGuardForController,getGuardForControllerAction,getInjectableMetadata,getMiddlewaresForController,getMiddlewaresForControllerAction,getModuleMetadata,getRouteMetadata,inject});
|
|
6
|
+
"use strict";
|
|
7
|
+
var __defProp = Object.defineProperty;
|
|
8
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
9
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
10
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
11
|
+
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
12
|
+
var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
|
|
13
|
+
var __export = (target, all) => {
|
|
14
|
+
for (var name in all)
|
|
15
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
16
|
+
};
|
|
17
|
+
var __copyProps = (to, from, except, desc) => {
|
|
18
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
19
|
+
for (let key of __getOwnPropNames(from))
|
|
20
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
21
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
22
|
+
}
|
|
23
|
+
return to;
|
|
24
|
+
};
|
|
25
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
26
|
+
var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
27
|
+
|
|
28
|
+
// src/index.ts
|
|
29
|
+
var src_exports = {};
|
|
30
|
+
__export(src_exports, {
|
|
31
|
+
AppInjector: () => AppInjector,
|
|
32
|
+
Authorize: () => Authorize,
|
|
33
|
+
BadGatewayException: () => BadGatewayException,
|
|
34
|
+
BadRequestException: () => BadRequestException,
|
|
35
|
+
CONTROLLER_METADATA_KEY: () => CONTROLLER_METADATA_KEY,
|
|
36
|
+
ConflictException: () => ConflictException,
|
|
37
|
+
Controller: () => Controller,
|
|
38
|
+
Delete: () => Delete,
|
|
39
|
+
ForbiddenException: () => ForbiddenException,
|
|
40
|
+
GatewayTimeoutException: () => GatewayTimeoutException,
|
|
41
|
+
Get: () => Get,
|
|
42
|
+
HttpVersionNotSupportedException: () => HttpVersionNotSupportedException,
|
|
43
|
+
INJECTABLE_METADATA_KEY: () => INJECTABLE_METADATA_KEY,
|
|
44
|
+
Injectable: () => Injectable,
|
|
45
|
+
InsufficientStorageException: () => InsufficientStorageException,
|
|
46
|
+
InternalServerException: () => InternalServerException,
|
|
47
|
+
Logger: () => Logger,
|
|
48
|
+
LoopDetectedException: () => LoopDetectedException,
|
|
49
|
+
MODULE_METADATA_KEY: () => MODULE_METADATA_KEY,
|
|
50
|
+
MethodNotAllowedException: () => MethodNotAllowedException,
|
|
51
|
+
Module: () => Module,
|
|
52
|
+
NetworkAuthenticationRequiredException: () => NetworkAuthenticationRequiredException,
|
|
53
|
+
NetworkConnectTimeoutException: () => NetworkConnectTimeoutException,
|
|
54
|
+
NotAcceptableException: () => NotAcceptableException,
|
|
55
|
+
NotExtendedException: () => NotExtendedException,
|
|
56
|
+
NotFoundException: () => NotFoundException,
|
|
57
|
+
NotImplementedException: () => NotImplementedException,
|
|
58
|
+
NoxApp: () => NoxApp,
|
|
59
|
+
Patch: () => Patch,
|
|
60
|
+
PaymentRequiredException: () => PaymentRequiredException,
|
|
61
|
+
Post: () => Post,
|
|
62
|
+
Put: () => Put,
|
|
63
|
+
ROUTE_METADATA_KEY: () => ROUTE_METADATA_KEY,
|
|
64
|
+
Request: () => Request,
|
|
65
|
+
RequestTimeoutException: () => RequestTimeoutException,
|
|
66
|
+
ResponseException: () => ResponseException,
|
|
67
|
+
RootInjector: () => RootInjector,
|
|
68
|
+
Router: () => Router,
|
|
69
|
+
ServiceUnavailableException: () => ServiceUnavailableException,
|
|
70
|
+
TooManyRequestsException: () => TooManyRequestsException,
|
|
71
|
+
UnauthorizedException: () => UnauthorizedException,
|
|
72
|
+
UpgradeRequiredException: () => UpgradeRequiredException,
|
|
73
|
+
UseMiddlewares: () => UseMiddlewares,
|
|
74
|
+
VariantAlsoNegotiatesException: () => VariantAlsoNegotiatesException,
|
|
75
|
+
bootstrapApplication: () => bootstrapApplication,
|
|
76
|
+
getControllerMetadata: () => getControllerMetadata,
|
|
77
|
+
getGuardForController: () => getGuardForController,
|
|
78
|
+
getGuardForControllerAction: () => getGuardForControllerAction,
|
|
79
|
+
getInjectableMetadata: () => getInjectableMetadata,
|
|
80
|
+
getMiddlewaresForController: () => getMiddlewaresForController,
|
|
81
|
+
getMiddlewaresForControllerAction: () => getMiddlewaresForControllerAction,
|
|
82
|
+
getModuleMetadata: () => getModuleMetadata,
|
|
83
|
+
getRouteMetadata: () => getRouteMetadata,
|
|
84
|
+
inject: () => inject
|
|
85
|
+
});
|
|
86
|
+
module.exports = __toCommonJS(src_exports);
|
|
87
|
+
|
|
88
|
+
// src/DI/app-injector.ts
|
|
89
|
+
var import_reflect_metadata = require("reflect-metadata");
|
|
90
|
+
|
|
91
|
+
// src/exceptions.ts
|
|
92
|
+
var _ResponseException = class _ResponseException extends Error {
|
|
93
|
+
constructor(statusOrMessage, message) {
|
|
94
|
+
let statusCode;
|
|
95
|
+
if (typeof statusOrMessage === "number") {
|
|
96
|
+
statusCode = statusOrMessage;
|
|
97
|
+
} else if (typeof statusOrMessage === "string") {
|
|
98
|
+
message = statusOrMessage;
|
|
99
|
+
}
|
|
100
|
+
super(message ?? "");
|
|
101
|
+
__publicField(this, "status", 0);
|
|
102
|
+
if (statusCode !== void 0) {
|
|
103
|
+
this.status = statusCode;
|
|
104
|
+
}
|
|
105
|
+
this.name = this.constructor.name.replace(/([A-Z])/g, " $1");
|
|
106
|
+
}
|
|
107
|
+
};
|
|
108
|
+
__name(_ResponseException, "ResponseException");
|
|
109
|
+
var ResponseException = _ResponseException;
|
|
110
|
+
var _BadRequestException = class _BadRequestException extends ResponseException {
|
|
111
|
+
constructor() {
|
|
112
|
+
super(...arguments);
|
|
113
|
+
__publicField(this, "status", 400);
|
|
114
|
+
}
|
|
115
|
+
};
|
|
116
|
+
__name(_BadRequestException, "BadRequestException");
|
|
117
|
+
var BadRequestException = _BadRequestException;
|
|
118
|
+
var _UnauthorizedException = class _UnauthorizedException extends ResponseException {
|
|
119
|
+
constructor() {
|
|
120
|
+
super(...arguments);
|
|
121
|
+
__publicField(this, "status", 401);
|
|
122
|
+
}
|
|
123
|
+
};
|
|
124
|
+
__name(_UnauthorizedException, "UnauthorizedException");
|
|
125
|
+
var UnauthorizedException = _UnauthorizedException;
|
|
126
|
+
var _PaymentRequiredException = class _PaymentRequiredException extends ResponseException {
|
|
127
|
+
constructor() {
|
|
128
|
+
super(...arguments);
|
|
129
|
+
__publicField(this, "status", 402);
|
|
130
|
+
}
|
|
131
|
+
};
|
|
132
|
+
__name(_PaymentRequiredException, "PaymentRequiredException");
|
|
133
|
+
var PaymentRequiredException = _PaymentRequiredException;
|
|
134
|
+
var _ForbiddenException = class _ForbiddenException extends ResponseException {
|
|
135
|
+
constructor() {
|
|
136
|
+
super(...arguments);
|
|
137
|
+
__publicField(this, "status", 403);
|
|
138
|
+
}
|
|
139
|
+
};
|
|
140
|
+
__name(_ForbiddenException, "ForbiddenException");
|
|
141
|
+
var ForbiddenException = _ForbiddenException;
|
|
142
|
+
var _NotFoundException = class _NotFoundException extends ResponseException {
|
|
143
|
+
constructor() {
|
|
144
|
+
super(...arguments);
|
|
145
|
+
__publicField(this, "status", 404);
|
|
146
|
+
}
|
|
147
|
+
};
|
|
148
|
+
__name(_NotFoundException, "NotFoundException");
|
|
149
|
+
var NotFoundException = _NotFoundException;
|
|
150
|
+
var _MethodNotAllowedException = class _MethodNotAllowedException extends ResponseException {
|
|
151
|
+
constructor() {
|
|
152
|
+
super(...arguments);
|
|
153
|
+
__publicField(this, "status", 405);
|
|
154
|
+
}
|
|
155
|
+
};
|
|
156
|
+
__name(_MethodNotAllowedException, "MethodNotAllowedException");
|
|
157
|
+
var MethodNotAllowedException = _MethodNotAllowedException;
|
|
158
|
+
var _NotAcceptableException = class _NotAcceptableException extends ResponseException {
|
|
159
|
+
constructor() {
|
|
160
|
+
super(...arguments);
|
|
161
|
+
__publicField(this, "status", 406);
|
|
162
|
+
}
|
|
163
|
+
};
|
|
164
|
+
__name(_NotAcceptableException, "NotAcceptableException");
|
|
165
|
+
var NotAcceptableException = _NotAcceptableException;
|
|
166
|
+
var _RequestTimeoutException = class _RequestTimeoutException extends ResponseException {
|
|
167
|
+
constructor() {
|
|
168
|
+
super(...arguments);
|
|
169
|
+
__publicField(this, "status", 408);
|
|
170
|
+
}
|
|
171
|
+
};
|
|
172
|
+
__name(_RequestTimeoutException, "RequestTimeoutException");
|
|
173
|
+
var RequestTimeoutException = _RequestTimeoutException;
|
|
174
|
+
var _ConflictException = class _ConflictException extends ResponseException {
|
|
175
|
+
constructor() {
|
|
176
|
+
super(...arguments);
|
|
177
|
+
__publicField(this, "status", 409);
|
|
178
|
+
}
|
|
179
|
+
};
|
|
180
|
+
__name(_ConflictException, "ConflictException");
|
|
181
|
+
var ConflictException = _ConflictException;
|
|
182
|
+
var _UpgradeRequiredException = class _UpgradeRequiredException extends ResponseException {
|
|
183
|
+
constructor() {
|
|
184
|
+
super(...arguments);
|
|
185
|
+
__publicField(this, "status", 426);
|
|
186
|
+
}
|
|
187
|
+
};
|
|
188
|
+
__name(_UpgradeRequiredException, "UpgradeRequiredException");
|
|
189
|
+
var UpgradeRequiredException = _UpgradeRequiredException;
|
|
190
|
+
var _TooManyRequestsException = class _TooManyRequestsException extends ResponseException {
|
|
191
|
+
constructor() {
|
|
192
|
+
super(...arguments);
|
|
193
|
+
__publicField(this, "status", 429);
|
|
194
|
+
}
|
|
195
|
+
};
|
|
196
|
+
__name(_TooManyRequestsException, "TooManyRequestsException");
|
|
197
|
+
var TooManyRequestsException = _TooManyRequestsException;
|
|
198
|
+
var _InternalServerException = class _InternalServerException extends ResponseException {
|
|
199
|
+
constructor() {
|
|
200
|
+
super(...arguments);
|
|
201
|
+
__publicField(this, "status", 500);
|
|
202
|
+
}
|
|
203
|
+
};
|
|
204
|
+
__name(_InternalServerException, "InternalServerException");
|
|
205
|
+
var InternalServerException = _InternalServerException;
|
|
206
|
+
var _NotImplementedException = class _NotImplementedException extends ResponseException {
|
|
207
|
+
constructor() {
|
|
208
|
+
super(...arguments);
|
|
209
|
+
__publicField(this, "status", 501);
|
|
210
|
+
}
|
|
211
|
+
};
|
|
212
|
+
__name(_NotImplementedException, "NotImplementedException");
|
|
213
|
+
var NotImplementedException = _NotImplementedException;
|
|
214
|
+
var _BadGatewayException = class _BadGatewayException extends ResponseException {
|
|
215
|
+
constructor() {
|
|
216
|
+
super(...arguments);
|
|
217
|
+
__publicField(this, "status", 502);
|
|
218
|
+
}
|
|
219
|
+
};
|
|
220
|
+
__name(_BadGatewayException, "BadGatewayException");
|
|
221
|
+
var BadGatewayException = _BadGatewayException;
|
|
222
|
+
var _ServiceUnavailableException = class _ServiceUnavailableException extends ResponseException {
|
|
223
|
+
constructor() {
|
|
224
|
+
super(...arguments);
|
|
225
|
+
__publicField(this, "status", 503);
|
|
226
|
+
}
|
|
227
|
+
};
|
|
228
|
+
__name(_ServiceUnavailableException, "ServiceUnavailableException");
|
|
229
|
+
var ServiceUnavailableException = _ServiceUnavailableException;
|
|
230
|
+
var _GatewayTimeoutException = class _GatewayTimeoutException extends ResponseException {
|
|
231
|
+
constructor() {
|
|
232
|
+
super(...arguments);
|
|
233
|
+
__publicField(this, "status", 504);
|
|
234
|
+
}
|
|
235
|
+
};
|
|
236
|
+
__name(_GatewayTimeoutException, "GatewayTimeoutException");
|
|
237
|
+
var GatewayTimeoutException = _GatewayTimeoutException;
|
|
238
|
+
var _HttpVersionNotSupportedException = class _HttpVersionNotSupportedException extends ResponseException {
|
|
239
|
+
constructor() {
|
|
240
|
+
super(...arguments);
|
|
241
|
+
__publicField(this, "status", 505);
|
|
242
|
+
}
|
|
243
|
+
};
|
|
244
|
+
__name(_HttpVersionNotSupportedException, "HttpVersionNotSupportedException");
|
|
245
|
+
var HttpVersionNotSupportedException = _HttpVersionNotSupportedException;
|
|
246
|
+
var _VariantAlsoNegotiatesException = class _VariantAlsoNegotiatesException extends ResponseException {
|
|
247
|
+
constructor() {
|
|
248
|
+
super(...arguments);
|
|
249
|
+
__publicField(this, "status", 506);
|
|
250
|
+
}
|
|
251
|
+
};
|
|
252
|
+
__name(_VariantAlsoNegotiatesException, "VariantAlsoNegotiatesException");
|
|
253
|
+
var VariantAlsoNegotiatesException = _VariantAlsoNegotiatesException;
|
|
254
|
+
var _InsufficientStorageException = class _InsufficientStorageException extends ResponseException {
|
|
255
|
+
constructor() {
|
|
256
|
+
super(...arguments);
|
|
257
|
+
__publicField(this, "status", 507);
|
|
258
|
+
}
|
|
259
|
+
};
|
|
260
|
+
__name(_InsufficientStorageException, "InsufficientStorageException");
|
|
261
|
+
var InsufficientStorageException = _InsufficientStorageException;
|
|
262
|
+
var _LoopDetectedException = class _LoopDetectedException extends ResponseException {
|
|
263
|
+
constructor() {
|
|
264
|
+
super(...arguments);
|
|
265
|
+
__publicField(this, "status", 508);
|
|
266
|
+
}
|
|
267
|
+
};
|
|
268
|
+
__name(_LoopDetectedException, "LoopDetectedException");
|
|
269
|
+
var LoopDetectedException = _LoopDetectedException;
|
|
270
|
+
var _NotExtendedException = class _NotExtendedException extends ResponseException {
|
|
271
|
+
constructor() {
|
|
272
|
+
super(...arguments);
|
|
273
|
+
__publicField(this, "status", 510);
|
|
274
|
+
}
|
|
275
|
+
};
|
|
276
|
+
__name(_NotExtendedException, "NotExtendedException");
|
|
277
|
+
var NotExtendedException = _NotExtendedException;
|
|
278
|
+
var _NetworkAuthenticationRequiredException = class _NetworkAuthenticationRequiredException extends ResponseException {
|
|
279
|
+
constructor() {
|
|
280
|
+
super(...arguments);
|
|
281
|
+
__publicField(this, "status", 511);
|
|
282
|
+
}
|
|
283
|
+
};
|
|
284
|
+
__name(_NetworkAuthenticationRequiredException, "NetworkAuthenticationRequiredException");
|
|
285
|
+
var NetworkAuthenticationRequiredException = _NetworkAuthenticationRequiredException;
|
|
286
|
+
var _NetworkConnectTimeoutException = class _NetworkConnectTimeoutException extends ResponseException {
|
|
287
|
+
constructor() {
|
|
288
|
+
super(...arguments);
|
|
289
|
+
__publicField(this, "status", 599);
|
|
290
|
+
}
|
|
291
|
+
};
|
|
292
|
+
__name(_NetworkConnectTimeoutException, "NetworkConnectTimeoutException");
|
|
293
|
+
var NetworkConnectTimeoutException = _NetworkConnectTimeoutException;
|
|
294
|
+
|
|
295
|
+
// src/DI/app-injector.ts
|
|
296
|
+
var _AppInjector = class _AppInjector {
|
|
297
|
+
constructor(name = null) {
|
|
298
|
+
__publicField(this, "name");
|
|
299
|
+
__publicField(this, "bindings", /* @__PURE__ */ new Map());
|
|
300
|
+
__publicField(this, "singletons", /* @__PURE__ */ new Map());
|
|
301
|
+
__publicField(this, "scoped", /* @__PURE__ */ new Map());
|
|
302
|
+
this.name = name;
|
|
303
|
+
}
|
|
304
|
+
/**
|
|
305
|
+
* Typically used to create a dependency injection scope
|
|
306
|
+
* at the "scope" level (i.e., per-request lifetime).
|
|
307
|
+
*
|
|
308
|
+
* SHOULD NOT BE USED by anything else than the framework itself.
|
|
309
|
+
*/
|
|
310
|
+
createScope() {
|
|
311
|
+
const scope = new _AppInjector();
|
|
312
|
+
scope.bindings = this.bindings;
|
|
313
|
+
scope.singletons = this.singletons;
|
|
314
|
+
return scope;
|
|
315
|
+
}
|
|
316
|
+
/**
|
|
317
|
+
* Called when resolving a dependency,
|
|
318
|
+
* i.e., retrieving the instance of a given class.
|
|
319
|
+
*/
|
|
320
|
+
resolve(target) {
|
|
321
|
+
const binding = this.bindings.get(target);
|
|
322
|
+
if (!binding) throw new InternalServerException(`Failed to resolve a dependency injection : No binding for type ${target.name}.
|
|
323
|
+
Did you forget to use @Injectable() decorator ?`);
|
|
324
|
+
switch (binding.lifetime) {
|
|
325
|
+
case "transient":
|
|
326
|
+
return this.instantiate(binding.implementation);
|
|
327
|
+
case "scope": {
|
|
328
|
+
if (this.scoped.has(target)) {
|
|
329
|
+
return this.scoped.get(target);
|
|
330
|
+
}
|
|
331
|
+
const instance = this.instantiate(binding.implementation);
|
|
332
|
+
this.scoped.set(target, instance);
|
|
333
|
+
return instance;
|
|
334
|
+
}
|
|
335
|
+
case "singleton": {
|
|
336
|
+
if (binding.instance === void 0 && this.name === "root") {
|
|
337
|
+
binding.instance = this.instantiate(binding.implementation);
|
|
338
|
+
this.singletons.set(target, binding.instance);
|
|
339
|
+
}
|
|
340
|
+
return binding.instance;
|
|
341
|
+
}
|
|
342
|
+
}
|
|
343
|
+
}
|
|
344
|
+
/**
|
|
345
|
+
*
|
|
346
|
+
*/
|
|
347
|
+
instantiate(target) {
|
|
348
|
+
const paramTypes = Reflect.getMetadata("design:paramtypes", target) || [];
|
|
349
|
+
const params = paramTypes.map((p) => this.resolve(p));
|
|
350
|
+
return new target(...params);
|
|
351
|
+
}
|
|
352
|
+
};
|
|
353
|
+
__name(_AppInjector, "AppInjector");
|
|
354
|
+
var AppInjector = _AppInjector;
|
|
355
|
+
function inject(t) {
|
|
356
|
+
return RootInjector.resolve(t);
|
|
357
|
+
}
|
|
358
|
+
__name(inject, "inject");
|
|
359
|
+
var RootInjector = new AppInjector("root");
|
|
360
|
+
|
|
361
|
+
// src/router.ts
|
|
362
|
+
var import_reflect_metadata2 = require("reflect-metadata");
|
|
363
|
+
|
|
364
|
+
// src/utils/logger.ts
|
|
365
|
+
function getPrettyTimestamp() {
|
|
366
|
+
const now = /* @__PURE__ */ new Date();
|
|
367
|
+
return `${now.getDate().toString().padStart(2, "0")}/${(now.getMonth() + 1).toString().padStart(2, "0")}/${now.getFullYear()} ${now.getHours().toString().padStart(2, "0")}:${now.getMinutes().toString().padStart(2, "0")}:${now.getSeconds().toString().padStart(2, "0")}`;
|
|
368
|
+
}
|
|
369
|
+
__name(getPrettyTimestamp, "getPrettyTimestamp");
|
|
370
|
+
function getLogPrefix(callee, messageType, color) {
|
|
371
|
+
const timestamp = getPrettyTimestamp();
|
|
372
|
+
const spaces = " ".repeat(10 - messageType.length);
|
|
373
|
+
return `${color}[APP] ${process.pid} - ${Logger.colors.initial}${timestamp}${spaces}${color}${messageType.toUpperCase()}${Logger.colors.initial} ${Logger.colors.yellow}[${callee}]${Logger.colors.initial}`;
|
|
374
|
+
}
|
|
375
|
+
__name(getLogPrefix, "getLogPrefix");
|
|
376
|
+
function formatObject(prefix, arg) {
|
|
377
|
+
const json = JSON.stringify(arg, null, 2);
|
|
378
|
+
const prefixedJson = json.split("\n").map((line, idx) => idx === 0 ? `${Logger.colors.darkGrey}${line}` : `${prefix} ${Logger.colors.grey}${line}`).join("\n") + Logger.colors.initial;
|
|
379
|
+
return prefixedJson;
|
|
380
|
+
}
|
|
381
|
+
__name(formatObject, "formatObject");
|
|
382
|
+
function formattedArgs(prefix, args, color) {
|
|
383
|
+
return args.map((arg) => {
|
|
384
|
+
if (typeof arg === "string") {
|
|
385
|
+
return `${color}${arg}${Logger.colors.initial}`;
|
|
386
|
+
} else if (typeof arg === "object") {
|
|
387
|
+
return formatObject(prefix, arg);
|
|
388
|
+
}
|
|
389
|
+
return arg;
|
|
390
|
+
});
|
|
391
|
+
}
|
|
392
|
+
__name(formattedArgs, "formattedArgs");
|
|
393
|
+
function getCallee() {
|
|
394
|
+
const stack = new Error().stack?.split("\n") ?? [];
|
|
395
|
+
const caller = stack[3]?.trim().match(/at (.+?)(?:\..+)? .+$/)?.[1]?.replace("Object", "") || "App";
|
|
396
|
+
return caller;
|
|
397
|
+
}
|
|
398
|
+
__name(getCallee, "getCallee");
|
|
399
|
+
function canLog(level) {
|
|
400
|
+
return logLevelRank[level] >= logLevelRank[logLevel];
|
|
401
|
+
}
|
|
402
|
+
__name(canLog, "canLog");
|
|
403
|
+
var logLevel = "log";
|
|
404
|
+
var logLevelRank = {
|
|
405
|
+
debug: 0,
|
|
406
|
+
log: 1,
|
|
407
|
+
info: 2,
|
|
408
|
+
warn: 3,
|
|
409
|
+
error: 4
|
|
410
|
+
};
|
|
411
|
+
(function(Logger2) {
|
|
412
|
+
function setLogLevel(level) {
|
|
413
|
+
logLevel = level;
|
|
414
|
+
}
|
|
415
|
+
__name(setLogLevel, "setLogLevel");
|
|
416
|
+
Logger2.setLogLevel = setLogLevel;
|
|
417
|
+
function log(...args) {
|
|
418
|
+
if (!canLog("log")) return;
|
|
419
|
+
const callee = getCallee();
|
|
420
|
+
const prefix = getLogPrefix(callee, "log", Logger2.colors.green);
|
|
421
|
+
console.log(prefix, ...formattedArgs(prefix, args, Logger2.colors.green));
|
|
422
|
+
}
|
|
423
|
+
__name(log, "log");
|
|
424
|
+
Logger2.log = log;
|
|
425
|
+
function info(...args) {
|
|
426
|
+
if (!canLog("info")) return;
|
|
427
|
+
const callee = getCallee();
|
|
428
|
+
const prefix = getLogPrefix(callee, "info", Logger2.colors.blue);
|
|
429
|
+
console.info(prefix, ...formattedArgs(prefix, args, Logger2.colors.blue));
|
|
430
|
+
}
|
|
431
|
+
__name(info, "info");
|
|
432
|
+
Logger2.info = info;
|
|
433
|
+
function warn(...args) {
|
|
434
|
+
if (!canLog("warn")) return;
|
|
435
|
+
const callee = getCallee();
|
|
436
|
+
const prefix = getLogPrefix(callee, "warn", Logger2.colors.brown);
|
|
437
|
+
console.warn(prefix, ...formattedArgs(prefix, args, Logger2.colors.brown));
|
|
438
|
+
}
|
|
439
|
+
__name(warn, "warn");
|
|
440
|
+
Logger2.warn = warn;
|
|
441
|
+
function error(...args) {
|
|
442
|
+
if (!canLog("error")) return;
|
|
443
|
+
const callee = getCallee();
|
|
444
|
+
const prefix = getLogPrefix(callee, "error", Logger2.colors.red);
|
|
445
|
+
console.error(prefix, ...formattedArgs(prefix, args, Logger2.colors.red));
|
|
446
|
+
}
|
|
447
|
+
__name(error, "error");
|
|
448
|
+
Logger2.error = error;
|
|
449
|
+
function debug(...args) {
|
|
450
|
+
if (!canLog("debug")) return;
|
|
451
|
+
const callee = getCallee();
|
|
452
|
+
const prefix = getLogPrefix(callee, "debug", Logger2.colors.purple);
|
|
453
|
+
console.debug(prefix, ...formattedArgs(prefix, args, Logger2.colors.purple));
|
|
454
|
+
}
|
|
455
|
+
__name(debug, "debug");
|
|
456
|
+
Logger2.debug = debug;
|
|
457
|
+
Logger2.colors = {
|
|
458
|
+
black: "\x1B[0;30m",
|
|
459
|
+
grey: "\x1B[0;37m",
|
|
460
|
+
red: "\x1B[0;31m",
|
|
461
|
+
green: "\x1B[0;32m",
|
|
462
|
+
brown: "\x1B[0;33m",
|
|
463
|
+
blue: "\x1B[0;34m",
|
|
464
|
+
purple: "\x1B[0;35m",
|
|
465
|
+
darkGrey: "\x1B[1;30m",
|
|
466
|
+
lightRed: "\x1B[1;31m",
|
|
467
|
+
lightGreen: "\x1B[1;32m",
|
|
468
|
+
yellow: "\x1B[1;33m",
|
|
469
|
+
lightBlue: "\x1B[1;34m",
|
|
470
|
+
magenta: "\x1B[1;35m",
|
|
471
|
+
cyan: "\x1B[1;36m",
|
|
472
|
+
white: "\x1B[1;37m",
|
|
473
|
+
initial: "\x1B[0m"
|
|
474
|
+
};
|
|
475
|
+
})(Logger || (Logger = {}));
|
|
476
|
+
var Logger;
|
|
477
|
+
|
|
478
|
+
// src/decorators/guards.decorator.ts
|
|
479
|
+
function Authorize(...guardClasses) {
|
|
480
|
+
return (target, propertyKey) => {
|
|
481
|
+
let key;
|
|
482
|
+
if (propertyKey) {
|
|
483
|
+
const ctrlName = target.constructor.name;
|
|
484
|
+
const actionName = propertyKey;
|
|
485
|
+
key = `${ctrlName}.${actionName}`;
|
|
486
|
+
} else {
|
|
487
|
+
const ctrlName = target.name;
|
|
488
|
+
key = `${ctrlName}`;
|
|
489
|
+
}
|
|
490
|
+
if (authorizations.has(key)) {
|
|
491
|
+
throw new Error(`Guard(s) already registered for ${key}`);
|
|
492
|
+
}
|
|
493
|
+
Logger.debug(`Registering guard(s) for ${key}: ${guardClasses.map((c) => c.name).join(", ")}`);
|
|
494
|
+
authorizations.set(key, guardClasses);
|
|
495
|
+
};
|
|
496
|
+
}
|
|
497
|
+
__name(Authorize, "Authorize");
|
|
498
|
+
function getGuardForController(controllerName) {
|
|
499
|
+
const key = `${controllerName}`;
|
|
500
|
+
return authorizations.get(key) ?? [];
|
|
501
|
+
}
|
|
502
|
+
__name(getGuardForController, "getGuardForController");
|
|
503
|
+
function getGuardForControllerAction(controllerName, actionName) {
|
|
504
|
+
const key = `${controllerName}.${actionName}`;
|
|
505
|
+
return authorizations.get(key) ?? [];
|
|
506
|
+
}
|
|
507
|
+
__name(getGuardForControllerAction, "getGuardForControllerAction");
|
|
508
|
+
var authorizations = /* @__PURE__ */ new Map();
|
|
509
|
+
|
|
510
|
+
// src/decorators/method.decorator.ts
|
|
511
|
+
function createRouteDecorator(verb) {
|
|
512
|
+
return (path) => {
|
|
513
|
+
return (target, propertyKey) => {
|
|
514
|
+
const existingRoutes = Reflect.getMetadata(ROUTE_METADATA_KEY, target.constructor) || [];
|
|
515
|
+
const metadata = {
|
|
516
|
+
method: verb,
|
|
517
|
+
path: path.trim().replace(/^\/|\/$/g, ""),
|
|
518
|
+
handler: propertyKey,
|
|
519
|
+
guards: getGuardForControllerAction(target.constructor.__controllerName, propertyKey)
|
|
520
|
+
};
|
|
521
|
+
existingRoutes.push(metadata);
|
|
522
|
+
Reflect.defineMetadata(ROUTE_METADATA_KEY, existingRoutes, target.constructor);
|
|
523
|
+
};
|
|
524
|
+
};
|
|
525
|
+
}
|
|
526
|
+
__name(createRouteDecorator, "createRouteDecorator");
|
|
527
|
+
function getRouteMetadata(target) {
|
|
528
|
+
return Reflect.getMetadata(ROUTE_METADATA_KEY, target) || [];
|
|
529
|
+
}
|
|
530
|
+
__name(getRouteMetadata, "getRouteMetadata");
|
|
531
|
+
var Get = createRouteDecorator("GET");
|
|
532
|
+
var Post = createRouteDecorator("POST");
|
|
533
|
+
var Put = createRouteDecorator("PUT");
|
|
534
|
+
var Patch = createRouteDecorator("PATCH");
|
|
535
|
+
var Delete = createRouteDecorator("DELETE");
|
|
536
|
+
var ROUTE_METADATA_KEY = Symbol("ROUTE_METADATA_KEY");
|
|
537
|
+
|
|
538
|
+
// src/decorators/module.decorator.ts
|
|
539
|
+
function Module(metadata) {
|
|
540
|
+
return (target) => {
|
|
541
|
+
const checkModule = /* @__PURE__ */ __name((arr, arrName) => {
|
|
542
|
+
if (!arr) return;
|
|
543
|
+
for (const clazz of arr) {
|
|
544
|
+
if (!Reflect.getMetadata(MODULE_METADATA_KEY, clazz)) {
|
|
545
|
+
throw new Error(`Class ${clazz.name} in ${arrName} must be decorated with @Module`);
|
|
546
|
+
}
|
|
547
|
+
}
|
|
548
|
+
}, "checkModule");
|
|
549
|
+
const checkInjectable = /* @__PURE__ */ __name((arr) => {
|
|
550
|
+
if (!arr) return;
|
|
551
|
+
for (const clazz of arr) {
|
|
552
|
+
if (!Reflect.getMetadata(INJECTABLE_METADATA_KEY, clazz)) {
|
|
553
|
+
throw new Error(`Class ${clazz.name} in providers must be decorated with @Injectable`);
|
|
554
|
+
}
|
|
555
|
+
}
|
|
556
|
+
}, "checkInjectable");
|
|
557
|
+
const checkController = /* @__PURE__ */ __name((arr) => {
|
|
558
|
+
if (!arr) return;
|
|
559
|
+
for (const clazz of arr) {
|
|
560
|
+
if (!Reflect.getMetadata(CONTROLLER_METADATA_KEY, clazz)) {
|
|
561
|
+
throw new Error(`Class ${clazz.name} in controllers must be decorated with @Controller`);
|
|
562
|
+
}
|
|
563
|
+
}
|
|
564
|
+
}, "checkController");
|
|
565
|
+
checkModule(metadata.imports, "imports");
|
|
566
|
+
checkModule(metadata.exports, "exports");
|
|
567
|
+
checkInjectable(metadata.providers);
|
|
568
|
+
checkController(metadata.controllers);
|
|
569
|
+
Reflect.defineMetadata(MODULE_METADATA_KEY, metadata, target);
|
|
570
|
+
Injectable("singleton")(target);
|
|
571
|
+
};
|
|
572
|
+
}
|
|
573
|
+
__name(Module, "Module");
|
|
574
|
+
function getModuleMetadata(target) {
|
|
575
|
+
return Reflect.getMetadata(MODULE_METADATA_KEY, target);
|
|
576
|
+
}
|
|
577
|
+
__name(getModuleMetadata, "getModuleMetadata");
|
|
578
|
+
var MODULE_METADATA_KEY = Symbol("MODULE_METADATA_KEY");
|
|
579
|
+
|
|
580
|
+
// src/DI/injector-explorer.ts
|
|
581
|
+
var _InjectorExplorer = class _InjectorExplorer {
|
|
582
|
+
/**
|
|
583
|
+
* Registers the class as injectable.
|
|
584
|
+
* When a class is instantiated, if it has dependencies and those dependencies
|
|
585
|
+
* are listed using this method, they will be injected into the class constructor.
|
|
586
|
+
*/
|
|
587
|
+
static register(target, lifetime) {
|
|
588
|
+
Logger.debug(`Registering ${target.name} as ${lifetime}`);
|
|
589
|
+
if (RootInjector.bindings.has(target)) return RootInjector;
|
|
590
|
+
RootInjector.bindings.set(target, {
|
|
591
|
+
implementation: target,
|
|
592
|
+
lifetime
|
|
593
|
+
});
|
|
594
|
+
if (lifetime === "singleton") {
|
|
595
|
+
RootInjector.resolve(target);
|
|
596
|
+
}
|
|
597
|
+
if (getModuleMetadata(target)) {
|
|
598
|
+
Logger.log(`${target.name} dependencies initialized`);
|
|
599
|
+
return RootInjector;
|
|
600
|
+
}
|
|
601
|
+
const controllerMeta = getControllerMetadata(target);
|
|
602
|
+
if (controllerMeta) {
|
|
603
|
+
const router = RootInjector.resolve(Router);
|
|
604
|
+
router?.registerController(target);
|
|
605
|
+
return RootInjector;
|
|
606
|
+
}
|
|
607
|
+
const routeMeta = getRouteMetadata(target);
|
|
608
|
+
if (routeMeta) {
|
|
609
|
+
return RootInjector;
|
|
610
|
+
}
|
|
611
|
+
if (getInjectableMetadata(target)) {
|
|
612
|
+
Logger.log(`Registered ${target.name} as ${lifetime}`);
|
|
613
|
+
return RootInjector;
|
|
614
|
+
}
|
|
615
|
+
return RootInjector;
|
|
616
|
+
}
|
|
617
|
+
};
|
|
618
|
+
__name(_InjectorExplorer, "InjectorExplorer");
|
|
619
|
+
var InjectorExplorer = _InjectorExplorer;
|
|
620
|
+
|
|
621
|
+
// src/decorators/injectable.decorator.ts
|
|
622
|
+
function Injectable(lifetime = "scope") {
|
|
623
|
+
return (target) => {
|
|
624
|
+
if (typeof target !== "function" || !target.prototype) {
|
|
625
|
+
throw new Error(`@Injectable can only be used on classes, not on ${typeof target}`);
|
|
626
|
+
}
|
|
627
|
+
Reflect.defineMetadata(INJECTABLE_METADATA_KEY, lifetime, target);
|
|
628
|
+
InjectorExplorer.register(target, lifetime);
|
|
629
|
+
};
|
|
630
|
+
}
|
|
631
|
+
__name(Injectable, "Injectable");
|
|
632
|
+
function getInjectableMetadata(target) {
|
|
633
|
+
return Reflect.getMetadata(INJECTABLE_METADATA_KEY, target);
|
|
634
|
+
}
|
|
635
|
+
__name(getInjectableMetadata, "getInjectableMetadata");
|
|
636
|
+
var INJECTABLE_METADATA_KEY = Symbol("INJECTABLE_METADATA_KEY");
|
|
637
|
+
|
|
638
|
+
// src/decorators/controller.decorator.ts
|
|
639
|
+
function Controller(path) {
|
|
640
|
+
return (target) => {
|
|
641
|
+
const data = {
|
|
642
|
+
path,
|
|
643
|
+
guards: getGuardForController(target.name)
|
|
644
|
+
};
|
|
645
|
+
Reflect.defineMetadata(CONTROLLER_METADATA_KEY, data, target);
|
|
646
|
+
Injectable("scope")(target);
|
|
647
|
+
};
|
|
648
|
+
}
|
|
649
|
+
__name(Controller, "Controller");
|
|
650
|
+
function getControllerMetadata(target) {
|
|
651
|
+
return Reflect.getMetadata(CONTROLLER_METADATA_KEY, target);
|
|
652
|
+
}
|
|
653
|
+
__name(getControllerMetadata, "getControllerMetadata");
|
|
654
|
+
var CONTROLLER_METADATA_KEY = Symbol("CONTROLLER_METADATA_KEY");
|
|
655
|
+
|
|
656
|
+
// src/decorators/middleware.decorator.ts
|
|
657
|
+
function UseMiddlewares(mdlw) {
|
|
658
|
+
return (target, propertyKey) => {
|
|
659
|
+
let key;
|
|
660
|
+
if (propertyKey) {
|
|
661
|
+
const ctrlName = target.constructor.name;
|
|
662
|
+
const actionName = propertyKey;
|
|
663
|
+
key = `${ctrlName}.${actionName}`;
|
|
664
|
+
} else {
|
|
665
|
+
const ctrlName = target.name;
|
|
666
|
+
key = `${ctrlName}`;
|
|
667
|
+
}
|
|
668
|
+
if (middlewares.has(key)) {
|
|
669
|
+
throw new Error(`Middlewares(s) already registered for ${key}`);
|
|
670
|
+
}
|
|
671
|
+
Logger.debug(`Registering middleware(s) for ${key}: ${mdlw.map((c) => c.name).join(", ")}`);
|
|
672
|
+
middlewares.set(key, mdlw);
|
|
673
|
+
};
|
|
674
|
+
}
|
|
675
|
+
__name(UseMiddlewares, "UseMiddlewares");
|
|
676
|
+
function getMiddlewaresForController(controllerName) {
|
|
677
|
+
const key = `${controllerName}`;
|
|
678
|
+
return middlewares.get(key) ?? [];
|
|
679
|
+
}
|
|
680
|
+
__name(getMiddlewaresForController, "getMiddlewaresForController");
|
|
681
|
+
function getMiddlewaresForControllerAction(controllerName, actionName) {
|
|
682
|
+
const key = `${controllerName}.${actionName}`;
|
|
683
|
+
return middlewares.get(key) ?? [];
|
|
684
|
+
}
|
|
685
|
+
__name(getMiddlewaresForControllerAction, "getMiddlewaresForControllerAction");
|
|
686
|
+
var middlewares = /* @__PURE__ */ new Map();
|
|
687
|
+
|
|
688
|
+
// src/utils/radix-tree.ts
|
|
689
|
+
var _a;
|
|
690
|
+
var RadixNode = (_a = class {
|
|
691
|
+
/**
|
|
692
|
+
* Creates a new RadixNode.
|
|
693
|
+
* @param segment - The segment of the path this node represents.
|
|
694
|
+
*/
|
|
695
|
+
constructor(segment) {
|
|
696
|
+
__publicField(this, "segment");
|
|
697
|
+
__publicField(this, "children", []);
|
|
698
|
+
__publicField(this, "value");
|
|
699
|
+
__publicField(this, "isParam");
|
|
700
|
+
__publicField(this, "paramName");
|
|
701
|
+
this.segment = segment;
|
|
702
|
+
this.isParam = segment.startsWith(":");
|
|
703
|
+
if (this.isParam) {
|
|
704
|
+
this.paramName = segment.slice(1);
|
|
705
|
+
}
|
|
706
|
+
}
|
|
707
|
+
/**
|
|
708
|
+
* Matches a child node against a given segment.
|
|
709
|
+
* This method checks if the segment matches any of the children nodes.
|
|
710
|
+
* @param segment - The segment to match against the children of this node.
|
|
711
|
+
* @returns A child node that matches the segment, or undefined if no match is found.
|
|
712
|
+
*/
|
|
713
|
+
matchChild(segment) {
|
|
714
|
+
for (const child of this.children) {
|
|
715
|
+
if (child.isParam || segment.startsWith(child.segment)) return child;
|
|
716
|
+
}
|
|
717
|
+
return void 0;
|
|
718
|
+
}
|
|
719
|
+
/**
|
|
720
|
+
* Finds a child node that matches the segment exactly.
|
|
721
|
+
* This method checks if there is a child node that matches the segment exactly.
|
|
722
|
+
* @param segment - The segment to find an exact match for among the children of this node.
|
|
723
|
+
* @returns A child node that matches the segment exactly, or undefined if no match is found.
|
|
724
|
+
*/
|
|
725
|
+
findExactChild(segment) {
|
|
726
|
+
return this.children.find((c) => c.segment === segment);
|
|
727
|
+
}
|
|
728
|
+
/**
|
|
729
|
+
* Adds a child node to this node's children.
|
|
730
|
+
* This method adds a new child node to the list of children for this node.
|
|
731
|
+
* @param node - The child node to add to this node's children.
|
|
732
|
+
*/
|
|
733
|
+
addChild(node) {
|
|
734
|
+
this.children.push(node);
|
|
735
|
+
}
|
|
736
|
+
}, __name(_a, "RadixNode"), _a);
|
|
737
|
+
var _RadixTree = class _RadixTree {
|
|
738
|
+
constructor() {
|
|
739
|
+
__publicField(this, "root", new RadixNode(""));
|
|
740
|
+
}
|
|
741
|
+
/**
|
|
742
|
+
* Inserts a path and its associated value into the Radix Tree.
|
|
743
|
+
* This method normalizes the path and inserts it into the tree, associating it with
|
|
744
|
+
* @param path - The path to insert into the tree.
|
|
745
|
+
* @param value - The value to associate with the path.
|
|
746
|
+
*/
|
|
747
|
+
insert(path, value) {
|
|
748
|
+
const segments = this.normalize(path);
|
|
749
|
+
this.insertRecursive(this.root, segments, value);
|
|
750
|
+
}
|
|
751
|
+
/**
|
|
752
|
+
* Recursively inserts a path into the Radix Tree.
|
|
753
|
+
* This method traverses the tree and inserts the segments of the path, creating new nodes
|
|
754
|
+
* @param node - The node to start inserting from.
|
|
755
|
+
* @param segments - The segments of the path to insert.
|
|
756
|
+
* @param value - The value to associate with the path.
|
|
757
|
+
*/
|
|
758
|
+
insertRecursive(node, segments, value) {
|
|
759
|
+
if (segments.length === 0) {
|
|
760
|
+
node.value = value;
|
|
761
|
+
return;
|
|
762
|
+
}
|
|
763
|
+
const segment = segments[0] ?? "";
|
|
764
|
+
let child = node.children.find((c) => c.isParam === segment.startsWith(":") && (c.isParam || c.segment === segment));
|
|
765
|
+
if (!child) {
|
|
766
|
+
child = new RadixNode(segment);
|
|
767
|
+
node.addChild(child);
|
|
768
|
+
}
|
|
769
|
+
this.insertRecursive(child, segments.slice(1), value);
|
|
770
|
+
}
|
|
771
|
+
/**
|
|
772
|
+
* Searches for a path in the Radix Tree.
|
|
773
|
+
* This method normalizes the path and searches for it in the tree, returning the node
|
|
774
|
+
* @param path - The path to search for in the Radix Tree.
|
|
775
|
+
* @returns An ISearchResult containing the node and parameters if a match is found, otherwise undefined.
|
|
776
|
+
*/
|
|
777
|
+
search(path) {
|
|
778
|
+
const segments = this.normalize(path);
|
|
779
|
+
return this.searchRecursive(this.root, segments, {});
|
|
780
|
+
}
|
|
781
|
+
/**
|
|
782
|
+
* Recursively searches for a path in the Radix Tree.
|
|
783
|
+
* This method traverses the tree and searches for the segments of the path, collecting parameters
|
|
784
|
+
* @param node - The node to start searching from.
|
|
785
|
+
* @param segments - The segments of the path to search for.
|
|
786
|
+
* @param params - The parameters collected during the search.
|
|
787
|
+
* @returns An ISearchResult containing the node and parameters if a match is found, otherwise undefined.
|
|
788
|
+
*/
|
|
789
|
+
searchRecursive(node, segments, params) {
|
|
790
|
+
if (segments.length === 0) {
|
|
791
|
+
if (node.value !== void 0) {
|
|
792
|
+
return {
|
|
793
|
+
node,
|
|
794
|
+
params
|
|
795
|
+
};
|
|
796
|
+
}
|
|
797
|
+
return void 0;
|
|
798
|
+
}
|
|
799
|
+
const [segment, ...rest] = segments;
|
|
800
|
+
for (const child of node.children) {
|
|
801
|
+
if (child.isParam) {
|
|
802
|
+
const paramName = child.paramName;
|
|
803
|
+
const childParams = {
|
|
804
|
+
...params,
|
|
805
|
+
[paramName]: segment ?? ""
|
|
806
|
+
};
|
|
807
|
+
if (rest.length === 0) {
|
|
808
|
+
return {
|
|
809
|
+
node: child,
|
|
810
|
+
params: childParams
|
|
811
|
+
};
|
|
812
|
+
}
|
|
813
|
+
const result = this.searchRecursive(child, rest, childParams);
|
|
814
|
+
if (result) return result;
|
|
815
|
+
} else if (segment === child.segment) {
|
|
816
|
+
if (rest.length === 0) {
|
|
817
|
+
return {
|
|
818
|
+
node: child,
|
|
819
|
+
params
|
|
820
|
+
};
|
|
821
|
+
}
|
|
822
|
+
const result = this.searchRecursive(child, rest, params);
|
|
823
|
+
if (result) return result;
|
|
824
|
+
}
|
|
825
|
+
}
|
|
826
|
+
return void 0;
|
|
827
|
+
}
|
|
828
|
+
/**
|
|
829
|
+
* Normalizes a path into an array of segments.
|
|
830
|
+
* This method removes leading and trailing slashes, splits the path by slashes, and
|
|
831
|
+
* @param path - The path to normalize.
|
|
832
|
+
* @returns An array of normalized path segments.
|
|
833
|
+
*/
|
|
834
|
+
normalize(path) {
|
|
835
|
+
const segments = path.replace(/^\/+|\/+$/g, "").split("/").filter(Boolean);
|
|
836
|
+
return [
|
|
837
|
+
"",
|
|
838
|
+
...segments
|
|
839
|
+
];
|
|
840
|
+
}
|
|
841
|
+
};
|
|
842
|
+
__name(_RadixTree, "RadixTree");
|
|
843
|
+
var RadixTree = _RadixTree;
|
|
844
|
+
|
|
845
|
+
// src/router.ts
|
|
846
|
+
function _ts_decorate(decorators, target, key, desc) {
|
|
847
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
848
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
849
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
850
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
851
|
+
}
|
|
852
|
+
__name(_ts_decorate, "_ts_decorate");
|
|
853
|
+
var _Router = class _Router {
|
|
854
|
+
constructor() {
|
|
855
|
+
__publicField(this, "routes", new RadixTree());
|
|
856
|
+
__publicField(this, "rootMiddlewares", []);
|
|
857
|
+
}
|
|
858
|
+
/**
|
|
859
|
+
* Registers a controller class with the router.
|
|
860
|
+
* This method extracts the route metadata from the controller class and registers it in the routing tree.
|
|
861
|
+
* It also handles the guards and middlewares associated with the controller.
|
|
862
|
+
* @param controllerClass - The controller class to register.
|
|
863
|
+
*/
|
|
864
|
+
registerController(controllerClass) {
|
|
865
|
+
const controllerMeta = getControllerMetadata(controllerClass);
|
|
866
|
+
const controllerGuards = getGuardForController(controllerClass.name);
|
|
867
|
+
const controllerMiddlewares = getMiddlewaresForController(controllerClass.name);
|
|
868
|
+
if (!controllerMeta) throw new Error(`Missing @Controller decorator on ${controllerClass.name}`);
|
|
869
|
+
const routeMetadata = getRouteMetadata(controllerClass);
|
|
870
|
+
for (const def of routeMetadata) {
|
|
871
|
+
const fullPath = `${controllerMeta.path}/${def.path}`.replace(/\/+/g, "/");
|
|
872
|
+
const routeGuards = getGuardForControllerAction(controllerClass.name, def.handler);
|
|
873
|
+
const routeMiddlewares = getMiddlewaresForControllerAction(controllerClass.name, def.handler);
|
|
874
|
+
const guards = /* @__PURE__ */ new Set([
|
|
875
|
+
...controllerGuards,
|
|
876
|
+
...routeGuards
|
|
877
|
+
]);
|
|
878
|
+
const middlewares2 = /* @__PURE__ */ new Set([
|
|
879
|
+
...controllerMiddlewares,
|
|
880
|
+
...routeMiddlewares
|
|
881
|
+
]);
|
|
882
|
+
const routeDef = {
|
|
883
|
+
method: def.method,
|
|
884
|
+
path: fullPath,
|
|
885
|
+
controller: controllerClass,
|
|
886
|
+
handler: def.handler,
|
|
887
|
+
guards: [
|
|
888
|
+
...guards
|
|
889
|
+
],
|
|
890
|
+
middlewares: [
|
|
891
|
+
...middlewares2
|
|
892
|
+
]
|
|
893
|
+
};
|
|
894
|
+
this.routes.insert(fullPath + "/" + def.method, routeDef);
|
|
895
|
+
const hasActionGuards = routeDef.guards.length > 0;
|
|
896
|
+
const actionGuardsInfo = hasActionGuards ? "<" + routeDef.guards.map((g) => g.name).join("|") + ">" : "";
|
|
897
|
+
Logger.log(`Mapped {${routeDef.method} /${fullPath}}${actionGuardsInfo} route`);
|
|
898
|
+
}
|
|
899
|
+
const hasCtrlGuards = controllerMeta.guards.length > 0;
|
|
900
|
+
const controllerGuardsInfo = hasCtrlGuards ? "<" + controllerMeta.guards.map((g) => g.name).join("|") + ">" : "";
|
|
901
|
+
Logger.log(`Mapped ${controllerClass.name}${controllerGuardsInfo} controller's routes`);
|
|
902
|
+
return this;
|
|
903
|
+
}
|
|
904
|
+
/**
|
|
905
|
+
* Defines a middleware for the root of the application.
|
|
906
|
+
* This method allows you to register a middleware that will be applied to all requests
|
|
907
|
+
* to the application, regardless of the controller or action.
|
|
908
|
+
* @param middleware - The middleware class to register.
|
|
909
|
+
*/
|
|
910
|
+
defineRootMiddleware(middleware) {
|
|
911
|
+
Logger.debug(`Registering root middleware: ${middleware.name}`);
|
|
912
|
+
this.rootMiddlewares.push(middleware);
|
|
913
|
+
return this;
|
|
914
|
+
}
|
|
915
|
+
/**
|
|
916
|
+
* Shuts down the message channel for a specific sender ID.
|
|
917
|
+
* This method closes the IPC channel for the specified sender ID and
|
|
918
|
+
* removes it from the messagePorts map.
|
|
919
|
+
* @param channelSenderId - The ID of the sender channel to shut down.
|
|
920
|
+
*/
|
|
921
|
+
async handle(request) {
|
|
922
|
+
Logger.log(`> Received request: {${request.method} /${request.path}}`);
|
|
923
|
+
const t0 = performance.now();
|
|
924
|
+
const response = {
|
|
925
|
+
requestId: request.id,
|
|
926
|
+
status: 200,
|
|
927
|
+
body: null,
|
|
928
|
+
error: void 0
|
|
929
|
+
};
|
|
930
|
+
try {
|
|
931
|
+
const routeDef = this.findRoute(request);
|
|
932
|
+
await this.resolveController(request, response, routeDef);
|
|
933
|
+
if (response.status > 400) {
|
|
934
|
+
throw new ResponseException(response.status, response.error);
|
|
935
|
+
}
|
|
936
|
+
} catch (error) {
|
|
937
|
+
if (error instanceof ResponseException) {
|
|
938
|
+
response.status = error.status;
|
|
939
|
+
response.error = error.message;
|
|
940
|
+
} else if (error instanceof Error) {
|
|
941
|
+
response.status = 500;
|
|
942
|
+
response.error = error.message || "Internal Server Error";
|
|
943
|
+
} else {
|
|
944
|
+
response.status = 500;
|
|
945
|
+
response.error = "Unknown error occurred";
|
|
946
|
+
}
|
|
947
|
+
} finally {
|
|
948
|
+
const t1 = performance.now();
|
|
949
|
+
const message = `< ${response.status} ${request.method} /${request.path} ${Logger.colors.yellow}${Math.round(t1 - t0)}ms${Logger.colors.initial}`;
|
|
950
|
+
if (response.status < 400) Logger.log(message);
|
|
951
|
+
else if (response.status < 500) Logger.warn(message);
|
|
952
|
+
else Logger.error(message);
|
|
953
|
+
if (response.error !== void 0) {
|
|
954
|
+
Logger.error(response.error);
|
|
955
|
+
}
|
|
956
|
+
return response;
|
|
957
|
+
}
|
|
958
|
+
}
|
|
959
|
+
/**
|
|
960
|
+
* Finds the route definition for a given request.
|
|
961
|
+
* This method searches the routing tree for a matching route based on the request's path and method.
|
|
962
|
+
* If no matching route is found, it throws a NotFoundException.
|
|
963
|
+
* @param request - The Request object containing the method and path to search for.
|
|
964
|
+
* @returns The IRouteDefinition for the matched route.
|
|
965
|
+
*/
|
|
966
|
+
findRoute(request) {
|
|
967
|
+
const matchedRoutes = this.routes.search(request.path);
|
|
968
|
+
if (matchedRoutes?.node === void 0 || matchedRoutes.node.children.length === 0) {
|
|
969
|
+
throw new NotFoundException(`No route matches ${request.method} ${request.path}`);
|
|
970
|
+
}
|
|
971
|
+
const routeDef = matchedRoutes.node.findExactChild(request.method);
|
|
972
|
+
if (routeDef?.value === void 0) {
|
|
973
|
+
throw new MethodNotAllowedException(`Method Not Allowed for ${request.method} ${request.path}`);
|
|
974
|
+
}
|
|
975
|
+
return routeDef.value;
|
|
976
|
+
}
|
|
977
|
+
/**
|
|
978
|
+
* Resolves the controller for a given route definition.
|
|
979
|
+
* This method creates an instance of the controller class and prepares the request parameters.
|
|
980
|
+
* It also runs the request pipeline, which includes executing middlewares and guards.
|
|
981
|
+
* @param request - The Request object containing the request data.
|
|
982
|
+
* @param response - The IResponse object to populate with the response data.
|
|
983
|
+
* @param routeDef - The IRouteDefinition for the matched route.
|
|
984
|
+
* @return A Promise that resolves when the controller action has been executed.
|
|
985
|
+
* @throws UnauthorizedException if the request is not authorized by the guards.
|
|
986
|
+
*/
|
|
987
|
+
async resolveController(request, response, routeDef) {
|
|
988
|
+
const controllerInstance = request.context.resolve(routeDef.controller);
|
|
989
|
+
Object.assign(request.params, this.extractParams(request.path, routeDef.path));
|
|
990
|
+
await this.runRequestPipeline(request, response, routeDef, controllerInstance);
|
|
991
|
+
}
|
|
992
|
+
/**
|
|
993
|
+
* Runs the request pipeline for a given request.
|
|
994
|
+
* This method executes the middlewares and guards associated with the route,
|
|
995
|
+
* and finally calls the controller action.
|
|
996
|
+
* @param request - The Request object containing the request data.
|
|
997
|
+
* @param response - The IResponse object to populate with the response data.
|
|
998
|
+
* @param routeDef - The IRouteDefinition for the matched route.
|
|
999
|
+
* @param controllerInstance - The instance of the controller class.
|
|
1000
|
+
* @return A Promise that resolves when the request pipeline has been executed.
|
|
1001
|
+
* @throws ResponseException if the response status is not successful.
|
|
1002
|
+
*/
|
|
1003
|
+
async runRequestPipeline(request, response, routeDef, controllerInstance) {
|
|
1004
|
+
const middlewares2 = [
|
|
1005
|
+
.../* @__PURE__ */ new Set([
|
|
1006
|
+
...this.rootMiddlewares,
|
|
1007
|
+
...routeDef.middlewares
|
|
1008
|
+
])
|
|
1009
|
+
];
|
|
1010
|
+
const middlewareMaxIndex = middlewares2.length - 1;
|
|
1011
|
+
const guardsMaxIndex = middlewareMaxIndex + routeDef.guards.length;
|
|
1012
|
+
let index = -1;
|
|
1013
|
+
const dispatch = /* @__PURE__ */ __name(async (i) => {
|
|
1014
|
+
if (i <= index) throw new Error("next() called multiple times");
|
|
1015
|
+
index = i;
|
|
1016
|
+
if (i <= middlewareMaxIndex) {
|
|
1017
|
+
const nextFn = dispatch.bind(null, i + 1);
|
|
1018
|
+
await this.runMiddleware(request, response, nextFn, middlewares2[i]);
|
|
1019
|
+
if (response.status >= 400) {
|
|
1020
|
+
throw new ResponseException(response.status, response.error);
|
|
1021
|
+
}
|
|
1022
|
+
return;
|
|
1023
|
+
}
|
|
1024
|
+
if (i <= guardsMaxIndex) {
|
|
1025
|
+
const guardIndex = i - middlewares2.length;
|
|
1026
|
+
const guardType = routeDef.guards[guardIndex];
|
|
1027
|
+
await this.runGuard(request, guardType);
|
|
1028
|
+
dispatch(i + 1);
|
|
1029
|
+
return;
|
|
1030
|
+
}
|
|
1031
|
+
const action = controllerInstance[routeDef.handler];
|
|
1032
|
+
response.body = await action.call(controllerInstance, request, response);
|
|
1033
|
+
}, "dispatch");
|
|
1034
|
+
await dispatch(0);
|
|
1035
|
+
}
|
|
1036
|
+
/**
|
|
1037
|
+
* Runs a middleware function in the request pipeline.
|
|
1038
|
+
* This method creates an instance of the middleware and invokes its `invoke` method,
|
|
1039
|
+
* passing the request, response, and next function.
|
|
1040
|
+
* @param request - The Request object containing the request data.
|
|
1041
|
+
* @param response - The IResponse object to populate with the response data.
|
|
1042
|
+
* @param next - The NextFunction to call to continue the middleware chain.
|
|
1043
|
+
* @param middlewareType - The type of the middleware to run.
|
|
1044
|
+
* @return A Promise that resolves when the middleware has been executed.
|
|
1045
|
+
*/
|
|
1046
|
+
async runMiddleware(request, response, next, middlewareType) {
|
|
1047
|
+
const middleware = request.context.resolve(middlewareType);
|
|
1048
|
+
await middleware.invoke(request, response, next);
|
|
1049
|
+
}
|
|
1050
|
+
/**
|
|
1051
|
+
* Runs a guard to check if the request is authorized.
|
|
1052
|
+
* This method creates an instance of the guard and calls its `canActivate` method.
|
|
1053
|
+
* If the guard returns false, it throws an UnauthorizedException.
|
|
1054
|
+
* @param request - The Request object containing the request data.
|
|
1055
|
+
* @param guardType - The type of the guard to run.
|
|
1056
|
+
* @return A Promise that resolves if the guard allows the request, or throws an UnauthorizedException if not.
|
|
1057
|
+
* @throws UnauthorizedException if the guard denies access to the request.
|
|
1058
|
+
*/
|
|
1059
|
+
async runGuard(request, guardType) {
|
|
1060
|
+
const guard = request.context.resolve(guardType);
|
|
1061
|
+
const allowed = await guard.canActivate(request);
|
|
1062
|
+
if (!allowed) throw new UnauthorizedException(`Unauthorized for ${request.method} ${request.path}`);
|
|
1063
|
+
}
|
|
1064
|
+
/**
|
|
1065
|
+
* Extracts parameters from the actual request path based on the template path.
|
|
1066
|
+
* This method splits the actual path and the template path into segments,
|
|
1067
|
+
* then maps the segments to parameters based on the template.
|
|
1068
|
+
* @param actual - The actual request path.
|
|
1069
|
+
* @param template - The template path to extract parameters from.
|
|
1070
|
+
* @returns An object containing the extracted parameters.
|
|
1071
|
+
*/
|
|
1072
|
+
extractParams(actual, template) {
|
|
1073
|
+
const aParts = actual.split("/");
|
|
1074
|
+
const tParts = template.split("/");
|
|
1075
|
+
const params = {};
|
|
1076
|
+
tParts.forEach((part, i) => {
|
|
1077
|
+
if (part.startsWith(":")) {
|
|
1078
|
+
params[part.slice(1)] = aParts[i] ?? "";
|
|
1079
|
+
}
|
|
1080
|
+
});
|
|
1081
|
+
return params;
|
|
1082
|
+
}
|
|
1083
|
+
};
|
|
1084
|
+
__name(_Router, "Router");
|
|
1085
|
+
var Router = _Router;
|
|
1086
|
+
Router = _ts_decorate([
|
|
1087
|
+
Injectable("singleton")
|
|
1088
|
+
], Router);
|
|
1089
|
+
|
|
1090
|
+
// src/app.ts
|
|
1091
|
+
var import_main = require("electron/main");
|
|
1092
|
+
|
|
1093
|
+
// src/request.ts
|
|
1094
|
+
var import_reflect_metadata3 = require("reflect-metadata");
|
|
1095
|
+
var _Request = class _Request {
|
|
1096
|
+
constructor(event, id, method, path, body) {
|
|
1097
|
+
__publicField(this, "event");
|
|
1098
|
+
__publicField(this, "id");
|
|
1099
|
+
__publicField(this, "method");
|
|
1100
|
+
__publicField(this, "path");
|
|
1101
|
+
__publicField(this, "body");
|
|
1102
|
+
__publicField(this, "context", RootInjector.createScope());
|
|
1103
|
+
__publicField(this, "params", {});
|
|
1104
|
+
this.event = event;
|
|
1105
|
+
this.id = id;
|
|
1106
|
+
this.method = method;
|
|
1107
|
+
this.path = path;
|
|
1108
|
+
this.body = body;
|
|
1109
|
+
this.path = path.replace(/^\/|\/$/g, "");
|
|
1110
|
+
}
|
|
1111
|
+
};
|
|
1112
|
+
__name(_Request, "Request");
|
|
1113
|
+
var Request = _Request;
|
|
1114
|
+
|
|
1115
|
+
// src/app.ts
|
|
1116
|
+
function _ts_decorate2(decorators, target, key, desc) {
|
|
1117
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
1118
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
1119
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
1120
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
1121
|
+
}
|
|
1122
|
+
__name(_ts_decorate2, "_ts_decorate");
|
|
1123
|
+
function _ts_metadata(k, v) {
|
|
1124
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
1125
|
+
}
|
|
1126
|
+
__name(_ts_metadata, "_ts_metadata");
|
|
1127
|
+
var _NoxApp = class _NoxApp {
|
|
1128
|
+
constructor(router) {
|
|
1129
|
+
__publicField(this, "router");
|
|
1130
|
+
__publicField(this, "messagePorts", /* @__PURE__ */ new Map());
|
|
1131
|
+
__publicField(this, "app");
|
|
1132
|
+
this.router = router;
|
|
1133
|
+
}
|
|
1134
|
+
/**
|
|
1135
|
+
* Initializes the NoxApp instance.
|
|
1136
|
+
* This method sets up the IPC communication, registers event listeners,
|
|
1137
|
+
* and prepares the application for use.
|
|
1138
|
+
*/
|
|
1139
|
+
async init() {
|
|
1140
|
+
import_main.ipcMain.on("gimme-my-port", this.giveTheRendererAPort.bind(this));
|
|
1141
|
+
import_main.app.once("activate", this.onAppActivated.bind(this));
|
|
1142
|
+
import_main.app.once("window-all-closed", this.onAllWindowsClosed.bind(this));
|
|
1143
|
+
console.log("");
|
|
1144
|
+
return this;
|
|
1145
|
+
}
|
|
1146
|
+
/**
|
|
1147
|
+
* Handles the request from the renderer process.
|
|
1148
|
+
* This method creates a Request object from the IPC event data,
|
|
1149
|
+
* processes it through the Router, and sends the response back
|
|
1150
|
+
* to the renderer process using the MessageChannel.
|
|
1151
|
+
*/
|
|
1152
|
+
giveTheRendererAPort(event) {
|
|
1153
|
+
const senderId = event.sender.id;
|
|
1154
|
+
if (this.messagePorts.has(senderId)) {
|
|
1155
|
+
this.shutdownChannel(senderId);
|
|
1156
|
+
}
|
|
1157
|
+
const channel = new import_main.MessageChannelMain();
|
|
1158
|
+
this.messagePorts.set(senderId, channel);
|
|
1159
|
+
channel.port1.on("message", this.onRendererMessage.bind(this));
|
|
1160
|
+
channel.port1.start();
|
|
1161
|
+
event.sender.postMessage("port", {
|
|
1162
|
+
senderId
|
|
1163
|
+
}, [
|
|
1164
|
+
channel.port2
|
|
1165
|
+
]);
|
|
1166
|
+
}
|
|
1167
|
+
/**
|
|
1168
|
+
* Electron specific message handling.
|
|
1169
|
+
* Replaces HTTP calls by using Electron's IPC mechanism.
|
|
1170
|
+
*/
|
|
1171
|
+
async onRendererMessage(event) {
|
|
1172
|
+
const { senderId, requestId, path, method, body } = event.data;
|
|
1173
|
+
const channel = this.messagePorts.get(senderId);
|
|
1174
|
+
if (!channel) {
|
|
1175
|
+
Logger.error(`No message channel found for sender ID: ${senderId}`);
|
|
1176
|
+
return;
|
|
1177
|
+
}
|
|
1178
|
+
try {
|
|
1179
|
+
const request = new Request(event, requestId, method, path, body);
|
|
1180
|
+
const response = await this.router.handle(request);
|
|
1181
|
+
channel.port1.postMessage(response);
|
|
1182
|
+
} catch (err) {
|
|
1183
|
+
const response = {
|
|
1184
|
+
requestId,
|
|
1185
|
+
status: 500,
|
|
1186
|
+
body: null,
|
|
1187
|
+
error: err.message || "Internal Server Error"
|
|
1188
|
+
};
|
|
1189
|
+
channel.port1.postMessage(response);
|
|
1190
|
+
}
|
|
1191
|
+
}
|
|
1192
|
+
/**
|
|
1193
|
+
* MacOS specific behavior.
|
|
1194
|
+
*/
|
|
1195
|
+
onAppActivated() {
|
|
1196
|
+
if (process.platform === "darwin" && import_main.BrowserWindow.getAllWindows().length === 0) {
|
|
1197
|
+
this.app?.onActivated();
|
|
1198
|
+
}
|
|
1199
|
+
}
|
|
1200
|
+
/**
|
|
1201
|
+
* Shuts down the message channel for a specific sender ID.
|
|
1202
|
+
* This method closes the IPC channel for the specified sender ID and
|
|
1203
|
+
* removes it from the messagePorts map.
|
|
1204
|
+
* @param channelSenderId - The ID of the sender channel to shut down.
|
|
1205
|
+
* @param remove - Whether to remove the channel from the messagePorts map.
|
|
1206
|
+
*/
|
|
1207
|
+
shutdownChannel(channelSenderId) {
|
|
1208
|
+
const channel = this.messagePorts.get(channelSenderId);
|
|
1209
|
+
if (!channel) {
|
|
1210
|
+
Logger.warn(`No message channel found for sender ID: ${channelSenderId}`);
|
|
1211
|
+
return;
|
|
1212
|
+
}
|
|
1213
|
+
channel.port1.off("message", this.onRendererMessage.bind(this));
|
|
1214
|
+
channel.port1.close();
|
|
1215
|
+
channel.port2.close();
|
|
1216
|
+
this.messagePorts.delete(channelSenderId);
|
|
1217
|
+
}
|
|
1218
|
+
/**
|
|
1219
|
+
* Handles the application shutdown process.
|
|
1220
|
+
* This method is called when all windows are closed, and it cleans up the message channels
|
|
1221
|
+
*/
|
|
1222
|
+
async onAllWindowsClosed() {
|
|
1223
|
+
this.messagePorts.forEach((channel, senderId) => {
|
|
1224
|
+
this.shutdownChannel(senderId);
|
|
1225
|
+
});
|
|
1226
|
+
this.messagePorts.clear();
|
|
1227
|
+
this.app?.dispose();
|
|
1228
|
+
if (process.platform !== "darwin") {
|
|
1229
|
+
import_main.app.quit();
|
|
1230
|
+
}
|
|
1231
|
+
}
|
|
1232
|
+
// ---
|
|
1233
|
+
/**
|
|
1234
|
+
* Configures the NoxApp instance with the provided application class.
|
|
1235
|
+
* This method allows you to set the application class that will handle lifecycle events.
|
|
1236
|
+
* @param app - The application class to configure.
|
|
1237
|
+
* @returns NoxApp instance for method chaining.
|
|
1238
|
+
*/
|
|
1239
|
+
configure(app3) {
|
|
1240
|
+
this.app = inject(app3);
|
|
1241
|
+
return this;
|
|
1242
|
+
}
|
|
1243
|
+
/**
|
|
1244
|
+
* Registers a middleware for the root of the application.
|
|
1245
|
+
* This method allows you to define a middleware that will be applied to all requests
|
|
1246
|
+
* @param middleware - The middleware class to register.
|
|
1247
|
+
* @returns NoxApp instance for method chaining.
|
|
1248
|
+
*/
|
|
1249
|
+
use(middleware) {
|
|
1250
|
+
this.router.defineRootMiddleware(middleware);
|
|
1251
|
+
return this;
|
|
1252
|
+
}
|
|
1253
|
+
/**
|
|
1254
|
+
* Should be called after the bootstrapApplication function is called.
|
|
1255
|
+
* @returns NoxApp instance for method chaining.
|
|
1256
|
+
*/
|
|
1257
|
+
start() {
|
|
1258
|
+
this.app?.onReady();
|
|
1259
|
+
return this;
|
|
1260
|
+
}
|
|
1261
|
+
};
|
|
1262
|
+
__name(_NoxApp, "NoxApp");
|
|
1263
|
+
var NoxApp = _NoxApp;
|
|
1264
|
+
NoxApp = _ts_decorate2([
|
|
1265
|
+
Injectable("singleton"),
|
|
1266
|
+
_ts_metadata("design:type", Function),
|
|
1267
|
+
_ts_metadata("design:paramtypes", [
|
|
1268
|
+
typeof Router === "undefined" ? Object : Router
|
|
1269
|
+
])
|
|
1270
|
+
], NoxApp);
|
|
1271
|
+
|
|
1272
|
+
// src/bootstrap.ts
|
|
1273
|
+
var import_main2 = require("electron/main");
|
|
1274
|
+
async function bootstrapApplication(rootModule) {
|
|
1275
|
+
if (!getModuleMetadata(rootModule)) {
|
|
1276
|
+
throw new Error(`Root module must be decorated with @Module`);
|
|
1277
|
+
}
|
|
1278
|
+
await import_main2.app.whenReady();
|
|
1279
|
+
const noxApp = inject(NoxApp);
|
|
1280
|
+
await noxApp.init();
|
|
1281
|
+
return noxApp;
|
|
1282
|
+
}
|
|
1283
|
+
__name(bootstrapApplication, "bootstrapApplication");
|
|
1284
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
1285
|
+
0 && (module.exports = {
|
|
1286
|
+
AppInjector,
|
|
1287
|
+
Authorize,
|
|
1288
|
+
BadGatewayException,
|
|
1289
|
+
BadRequestException,
|
|
1290
|
+
CONTROLLER_METADATA_KEY,
|
|
1291
|
+
ConflictException,
|
|
1292
|
+
Controller,
|
|
1293
|
+
Delete,
|
|
1294
|
+
ForbiddenException,
|
|
1295
|
+
GatewayTimeoutException,
|
|
1296
|
+
Get,
|
|
1297
|
+
HttpVersionNotSupportedException,
|
|
1298
|
+
INJECTABLE_METADATA_KEY,
|
|
1299
|
+
Injectable,
|
|
1300
|
+
InsufficientStorageException,
|
|
1301
|
+
InternalServerException,
|
|
1302
|
+
Logger,
|
|
1303
|
+
LoopDetectedException,
|
|
1304
|
+
MODULE_METADATA_KEY,
|
|
1305
|
+
MethodNotAllowedException,
|
|
1306
|
+
Module,
|
|
1307
|
+
NetworkAuthenticationRequiredException,
|
|
1308
|
+
NetworkConnectTimeoutException,
|
|
1309
|
+
NotAcceptableException,
|
|
1310
|
+
NotExtendedException,
|
|
1311
|
+
NotFoundException,
|
|
1312
|
+
NotImplementedException,
|
|
1313
|
+
NoxApp,
|
|
1314
|
+
Patch,
|
|
1315
|
+
PaymentRequiredException,
|
|
1316
|
+
Post,
|
|
1317
|
+
Put,
|
|
1318
|
+
ROUTE_METADATA_KEY,
|
|
1319
|
+
Request,
|
|
1320
|
+
RequestTimeoutException,
|
|
1321
|
+
ResponseException,
|
|
1322
|
+
RootInjector,
|
|
1323
|
+
Router,
|
|
1324
|
+
ServiceUnavailableException,
|
|
1325
|
+
TooManyRequestsException,
|
|
1326
|
+
UnauthorizedException,
|
|
1327
|
+
UpgradeRequiredException,
|
|
1328
|
+
UseMiddlewares,
|
|
1329
|
+
VariantAlsoNegotiatesException,
|
|
1330
|
+
bootstrapApplication,
|
|
1331
|
+
getControllerMetadata,
|
|
1332
|
+
getGuardForController,
|
|
1333
|
+
getGuardForControllerAction,
|
|
1334
|
+
getInjectableMetadata,
|
|
1335
|
+
getMiddlewaresForController,
|
|
1336
|
+
getMiddlewaresForControllerAction,
|
|
1337
|
+
getModuleMetadata,
|
|
1338
|
+
getRouteMetadata,
|
|
1339
|
+
inject
|
|
1340
|
+
});
|
|
11
1341
|
/**
|
|
12
1342
|
* @copyright 2025 NoxFly
|
|
13
1343
|
* @license MIT
|