@noxfly/noxus 1.0.5 → 1.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +78 -1
- package/dist/noxus.d.mts +48 -5
- package/dist/noxus.d.ts +48 -5
- package/dist/noxus.js +158 -28
- package/dist/noxus.mjs +154 -28
- package/dist/noxus.mjs.map +1 -1
- package/eslint.config.js +1 -0
- package/package.json +50 -50
- package/src/DI/app-injector.ts +5 -2
- package/src/app.ts +11 -5
- package/src/decorators/guards.decorator.ts +2 -2
- package/src/decorators/middleware.decorator.ts +54 -0
- package/src/decorators/module.decorator.ts +0 -2
- package/src/exceptions.ts +42 -27
- package/src/index.ts +1 -0
- package/src/request.ts +2 -2
- package/src/router.ts +97 -19
- package/dist/noxus.js.map +0 -1
- package/images/screenshot-requests.png +0 -0
- package/images/screenshot-startup.png +0 -0
package/README.md
CHANGED
|
@@ -402,7 +402,84 @@ const instance: MyClass = inject(MyClass);
|
|
|
402
402
|
|
|
403
403
|
### Middlewares
|
|
404
404
|
|
|
405
|
-
|
|
405
|
+
Declare middlewares as follow :
|
|
406
|
+
|
|
407
|
+
```ts
|
|
408
|
+
// renderer/middlewares.ts
|
|
409
|
+
|
|
410
|
+
import { IMiddleware, Injectable, Request, IResponse, NextFunction } from '@noxfly/noxus';
|
|
411
|
+
|
|
412
|
+
@Injectable()
|
|
413
|
+
export class MiddlewareA implements IMiddleware {
|
|
414
|
+
public async invoke(request: Request, response: IResponse, next: NextFunction): Promise<void> {
|
|
415
|
+
console.log(`[Middleware A] before next()`);
|
|
416
|
+
await next();
|
|
417
|
+
console.log(`[Middleware A] after next()`);
|
|
418
|
+
}
|
|
419
|
+
}
|
|
420
|
+
|
|
421
|
+
@Injectable()
|
|
422
|
+
export class MiddlewareB implements IMiddleware {
|
|
423
|
+
public async invoke(request: Request, response: IResponse, next: NextFunction): Promise<void> {
|
|
424
|
+
console.log(`[Middleware B] before next()`);
|
|
425
|
+
await next();
|
|
426
|
+
console.log(`[Middleware B] after next()`);
|
|
427
|
+
}
|
|
428
|
+
}
|
|
429
|
+
```
|
|
430
|
+
|
|
431
|
+
It is highly recommended to `await` the call of the `next` function.
|
|
432
|
+
|
|
433
|
+
Register these by 3 possible ways :
|
|
434
|
+
|
|
435
|
+
1. For a root scope. Will be present for each routes.
|
|
436
|
+
|
|
437
|
+
```ts
|
|
438
|
+
const noxApp = bootstrapApplication(AppModule);
|
|
439
|
+
|
|
440
|
+
noxApp.configure(Application);
|
|
441
|
+
|
|
442
|
+
noxApp.use(MiddlewareA);
|
|
443
|
+
noxApp.use(MiddlewareB);
|
|
444
|
+
|
|
445
|
+
noxApp.start();
|
|
446
|
+
```
|
|
447
|
+
|
|
448
|
+
2. Or for a controller or action's scope :
|
|
449
|
+
|
|
450
|
+
```ts
|
|
451
|
+
@Controller('user')
|
|
452
|
+
@UseMiddlewares([MiddlewareA, MiddlewareB])
|
|
453
|
+
export class UserController {
|
|
454
|
+
@Get('all')
|
|
455
|
+
@UseMiddlewares([MiddlewareA, MiddlewareB])
|
|
456
|
+
public getAll(): Promise<void> {
|
|
457
|
+
// ...
|
|
458
|
+
}
|
|
459
|
+
}
|
|
460
|
+
```
|
|
461
|
+
|
|
462
|
+
Note that if, for a given action, it has registered multiples times the same middleware, only the first registration will be saved.
|
|
463
|
+
|
|
464
|
+
For instance, registering MiddlewareA for root, on the controller and on the action is useless.
|
|
465
|
+
|
|
466
|
+
The order of declaration of use of middlewares is important.
|
|
467
|
+
|
|
468
|
+
assume we do this :
|
|
469
|
+
1. Use Middleware A for root
|
|
470
|
+
2. Use Middleware B for root just after MiddlewareA
|
|
471
|
+
3. Use Middleware C for controller
|
|
472
|
+
4. Use Middleware D for action
|
|
473
|
+
5. Use AuthGuard on the controller
|
|
474
|
+
6. Use RoleGuard on the action
|
|
475
|
+
|
|
476
|
+
Then the executing pipeline will be as follow :
|
|
477
|
+
|
|
478
|
+
```r
|
|
479
|
+
A -> B -> C -> D -> AuthGuard -> RoleGuard -> [action] -> D -> C -> B -> A.
|
|
480
|
+
```
|
|
481
|
+
|
|
482
|
+
if a middleware throw any exception or put the response status higher or equal to 400, the pipeline immediatly stops and the response is returned, weither it is done before or after the call to the next function.
|
|
406
483
|
|
|
407
484
|
## Contributing
|
|
408
485
|
|
package/dist/noxus.d.mts
CHANGED
|
@@ -62,7 +62,7 @@ declare class Request {
|
|
|
62
62
|
readonly method: HttpMethod;
|
|
63
63
|
readonly path: string;
|
|
64
64
|
readonly body: any;
|
|
65
|
-
readonly context:
|
|
65
|
+
readonly context: AppInjector;
|
|
66
66
|
readonly params: Record<string, string>;
|
|
67
67
|
constructor(event: Electron.MessageEvent, id: string, method: HttpMethod, path: string, body: any);
|
|
68
68
|
}
|
|
@@ -93,21 +93,62 @@ declare function getGuardForController(controllerName: string): Type<IGuard>[];
|
|
|
93
93
|
declare function getGuardForControllerAction(controllerName: string, actionName: string): Type<IGuard>[];
|
|
94
94
|
|
|
95
95
|
|
|
96
|
+
type NextFunction = () => Promise<void>;
|
|
97
|
+
interface IMiddleware {
|
|
98
|
+
invoke(request: Request, response: IResponse, next: NextFunction): MaybeAsync<void>;
|
|
99
|
+
}
|
|
100
|
+
declare function UseMiddlewares(mdlw: Type<IMiddleware>[]): ClassDecorator & MethodDecorator;
|
|
101
|
+
declare function getMiddlewaresForController(controllerName: string): Type<IMiddleware>[];
|
|
102
|
+
declare function getMiddlewaresForControllerAction(controllerName: string, actionName: string): Type<IMiddleware>[];
|
|
103
|
+
|
|
104
|
+
|
|
96
105
|
interface IRouteDefinition {
|
|
97
106
|
method: string;
|
|
98
107
|
path: string;
|
|
99
108
|
controller: Type<any>;
|
|
100
109
|
handler: string;
|
|
101
110
|
guards: Type<IGuard>[];
|
|
111
|
+
middlewares: Type<IMiddleware>[];
|
|
102
112
|
}
|
|
103
113
|
type ControllerAction = (request: Request, response: IResponse) => any;
|
|
104
114
|
declare class Router {
|
|
105
115
|
private readonly routes;
|
|
116
|
+
private readonly rootMiddlewares;
|
|
117
|
+
/**
|
|
118
|
+
*
|
|
119
|
+
*/
|
|
106
120
|
registerController(controllerClass: Type<unknown>): Router;
|
|
121
|
+
/**
|
|
122
|
+
*
|
|
123
|
+
*/
|
|
124
|
+
defineRootMiddleware(middleware: Type<IMiddleware>): Router;
|
|
125
|
+
/**
|
|
126
|
+
*
|
|
127
|
+
*/
|
|
107
128
|
handle(request: Request): Promise<IResponse>;
|
|
129
|
+
/**
|
|
130
|
+
*
|
|
131
|
+
*/
|
|
108
132
|
private findRoute;
|
|
133
|
+
/**
|
|
134
|
+
*
|
|
135
|
+
*/
|
|
109
136
|
private resolveController;
|
|
110
|
-
|
|
137
|
+
/**
|
|
138
|
+
*
|
|
139
|
+
*/
|
|
140
|
+
private runRequestPipeline;
|
|
141
|
+
/**
|
|
142
|
+
*
|
|
143
|
+
*/
|
|
144
|
+
private runMiddleware;
|
|
145
|
+
/**
|
|
146
|
+
*
|
|
147
|
+
*/
|
|
148
|
+
private runGuard;
|
|
149
|
+
/**
|
|
150
|
+
*
|
|
151
|
+
*/
|
|
111
152
|
private extractParams;
|
|
112
153
|
}
|
|
113
154
|
|
|
@@ -145,6 +186,7 @@ declare class NoxApp {
|
|
|
145
186
|
*/
|
|
146
187
|
private onAllWindowsClosed;
|
|
147
188
|
configure(app: Type<IApp>): NoxApp;
|
|
189
|
+
use(middleware: Type<IMiddleware>): NoxApp;
|
|
148
190
|
/**
|
|
149
191
|
* Should be called after the bootstrapApplication function is called.
|
|
150
192
|
*/
|
|
@@ -157,9 +199,10 @@ declare class NoxApp {
|
|
|
157
199
|
*/
|
|
158
200
|
declare function bootstrapApplication(rootModule: Type<any>): Promise<NoxApp>;
|
|
159
201
|
|
|
160
|
-
declare
|
|
161
|
-
|
|
202
|
+
declare class ResponseException extends Error {
|
|
203
|
+
readonly status: number;
|
|
162
204
|
constructor(message?: string);
|
|
205
|
+
constructor(statusCode?: number, message?: string);
|
|
163
206
|
}
|
|
164
207
|
declare class BadRequestException extends ResponseException {
|
|
165
208
|
readonly status = 400;
|
|
@@ -284,4 +327,4 @@ declare namespace Logger {
|
|
|
284
327
|
function debug(...args: any[]): void;
|
|
285
328
|
}
|
|
286
329
|
|
|
287
|
-
export { Authorize, BadGatewayException, BadRequestException, CONTROLLER_METADATA_KEY, ConflictException, Controller, type ControllerAction, Delete, ForbiddenException, GatewayTimeoutException, Get, type HttpMethod, HttpVersionNotSupportedException, type IApp, type IBinding, type IControllerMetadata, type IGuard, type IModuleMetadata, INJECTABLE_METADATA_KEY, type IRequest, type IResponse, type IRouteDefinition, type IRouteMetadata, Injectable, InsufficientStorageException, InternalServerException, type Lifetime, type LogLevel, Logger, LoopDetectedException, MODULE_METADATA_KEY, type MaybeAsync, MethodNotAllowedException, Module, NetworkAuthenticationRequiredException, NetworkConnectTimeoutException, NotAcceptableException, NotExtendedException, NotFoundException, NotImplementedException, NoxApp, Patch, PaymentRequiredException, Post, Put, ROUTE_METADATA_KEY, Request, RequestTimeoutException, ResponseException, RootInjector, Router, ServiceUnavailableException, TooManyRequestsException, type Type, UnauthorizedException, UpgradeRequiredException, VariantAlsoNegotiatesException, bootstrapApplication, getControllerMetadata, getGuardForController, getGuardForControllerAction, getInjectableMetadata, getModuleMetadata, getRouteMetadata, inject };
|
|
330
|
+
export { AppInjector, Authorize, BadGatewayException, BadRequestException, CONTROLLER_METADATA_KEY, ConflictException, Controller, type ControllerAction, Delete, ForbiddenException, GatewayTimeoutException, Get, type HttpMethod, HttpVersionNotSupportedException, type IApp, type IBinding, type IControllerMetadata, type IGuard, type IMiddleware, type IModuleMetadata, INJECTABLE_METADATA_KEY, type IRequest, type IResponse, type IRouteDefinition, type IRouteMetadata, Injectable, InsufficientStorageException, InternalServerException, type Lifetime, type LogLevel, Logger, LoopDetectedException, MODULE_METADATA_KEY, type MaybeAsync, MethodNotAllowedException, Module, NetworkAuthenticationRequiredException, NetworkConnectTimeoutException, type NextFunction, NotAcceptableException, NotExtendedException, NotFoundException, NotImplementedException, NoxApp, Patch, PaymentRequiredException, Post, Put, ROUTE_METADATA_KEY, Request, RequestTimeoutException, ResponseException, RootInjector, Router, ServiceUnavailableException, TooManyRequestsException, type Type, UnauthorizedException, UpgradeRequiredException, UseMiddlewares, VariantAlsoNegotiatesException, bootstrapApplication, getControllerMetadata, getGuardForController, getGuardForControllerAction, getInjectableMetadata, getMiddlewaresForController, getMiddlewaresForControllerAction, getModuleMetadata, getRouteMetadata, inject };
|
package/dist/noxus.d.ts
CHANGED
|
@@ -62,7 +62,7 @@ declare class Request {
|
|
|
62
62
|
readonly method: HttpMethod;
|
|
63
63
|
readonly path: string;
|
|
64
64
|
readonly body: any;
|
|
65
|
-
readonly context:
|
|
65
|
+
readonly context: AppInjector;
|
|
66
66
|
readonly params: Record<string, string>;
|
|
67
67
|
constructor(event: Electron.MessageEvent, id: string, method: HttpMethod, path: string, body: any);
|
|
68
68
|
}
|
|
@@ -93,21 +93,62 @@ declare function getGuardForController(controllerName: string): Type<IGuard>[];
|
|
|
93
93
|
declare function getGuardForControllerAction(controllerName: string, actionName: string): Type<IGuard>[];
|
|
94
94
|
|
|
95
95
|
|
|
96
|
+
type NextFunction = () => Promise<void>;
|
|
97
|
+
interface IMiddleware {
|
|
98
|
+
invoke(request: Request, response: IResponse, next: NextFunction): MaybeAsync<void>;
|
|
99
|
+
}
|
|
100
|
+
declare function UseMiddlewares(mdlw: Type<IMiddleware>[]): ClassDecorator & MethodDecorator;
|
|
101
|
+
declare function getMiddlewaresForController(controllerName: string): Type<IMiddleware>[];
|
|
102
|
+
declare function getMiddlewaresForControllerAction(controllerName: string, actionName: string): Type<IMiddleware>[];
|
|
103
|
+
|
|
104
|
+
|
|
96
105
|
interface IRouteDefinition {
|
|
97
106
|
method: string;
|
|
98
107
|
path: string;
|
|
99
108
|
controller: Type<any>;
|
|
100
109
|
handler: string;
|
|
101
110
|
guards: Type<IGuard>[];
|
|
111
|
+
middlewares: Type<IMiddleware>[];
|
|
102
112
|
}
|
|
103
113
|
type ControllerAction = (request: Request, response: IResponse) => any;
|
|
104
114
|
declare class Router {
|
|
105
115
|
private readonly routes;
|
|
116
|
+
private readonly rootMiddlewares;
|
|
117
|
+
/**
|
|
118
|
+
*
|
|
119
|
+
*/
|
|
106
120
|
registerController(controllerClass: Type<unknown>): Router;
|
|
121
|
+
/**
|
|
122
|
+
*
|
|
123
|
+
*/
|
|
124
|
+
defineRootMiddleware(middleware: Type<IMiddleware>): Router;
|
|
125
|
+
/**
|
|
126
|
+
*
|
|
127
|
+
*/
|
|
107
128
|
handle(request: Request): Promise<IResponse>;
|
|
129
|
+
/**
|
|
130
|
+
*
|
|
131
|
+
*/
|
|
108
132
|
private findRoute;
|
|
133
|
+
/**
|
|
134
|
+
*
|
|
135
|
+
*/
|
|
109
136
|
private resolveController;
|
|
110
|
-
|
|
137
|
+
/**
|
|
138
|
+
*
|
|
139
|
+
*/
|
|
140
|
+
private runRequestPipeline;
|
|
141
|
+
/**
|
|
142
|
+
*
|
|
143
|
+
*/
|
|
144
|
+
private runMiddleware;
|
|
145
|
+
/**
|
|
146
|
+
*
|
|
147
|
+
*/
|
|
148
|
+
private runGuard;
|
|
149
|
+
/**
|
|
150
|
+
*
|
|
151
|
+
*/
|
|
111
152
|
private extractParams;
|
|
112
153
|
}
|
|
113
154
|
|
|
@@ -145,6 +186,7 @@ declare class NoxApp {
|
|
|
145
186
|
*/
|
|
146
187
|
private onAllWindowsClosed;
|
|
147
188
|
configure(app: Type<IApp>): NoxApp;
|
|
189
|
+
use(middleware: Type<IMiddleware>): NoxApp;
|
|
148
190
|
/**
|
|
149
191
|
* Should be called after the bootstrapApplication function is called.
|
|
150
192
|
*/
|
|
@@ -157,9 +199,10 @@ declare class NoxApp {
|
|
|
157
199
|
*/
|
|
158
200
|
declare function bootstrapApplication(rootModule: Type<any>): Promise<NoxApp>;
|
|
159
201
|
|
|
160
|
-
declare
|
|
161
|
-
|
|
202
|
+
declare class ResponseException extends Error {
|
|
203
|
+
readonly status: number;
|
|
162
204
|
constructor(message?: string);
|
|
205
|
+
constructor(statusCode?: number, message?: string);
|
|
163
206
|
}
|
|
164
207
|
declare class BadRequestException extends ResponseException {
|
|
165
208
|
readonly status = 400;
|
|
@@ -284,4 +327,4 @@ declare namespace Logger {
|
|
|
284
327
|
function debug(...args: any[]): void;
|
|
285
328
|
}
|
|
286
329
|
|
|
287
|
-
export { Authorize, BadGatewayException, BadRequestException, CONTROLLER_METADATA_KEY, ConflictException, Controller, type ControllerAction, Delete, ForbiddenException, GatewayTimeoutException, Get, type HttpMethod, HttpVersionNotSupportedException, type IApp, type IBinding, type IControllerMetadata, type IGuard, type IModuleMetadata, INJECTABLE_METADATA_KEY, type IRequest, type IResponse, type IRouteDefinition, type IRouteMetadata, Injectable, InsufficientStorageException, InternalServerException, type Lifetime, type LogLevel, Logger, LoopDetectedException, MODULE_METADATA_KEY, type MaybeAsync, MethodNotAllowedException, Module, NetworkAuthenticationRequiredException, NetworkConnectTimeoutException, NotAcceptableException, NotExtendedException, NotFoundException, NotImplementedException, NoxApp, Patch, PaymentRequiredException, Post, Put, ROUTE_METADATA_KEY, Request, RequestTimeoutException, ResponseException, RootInjector, Router, ServiceUnavailableException, TooManyRequestsException, type Type, UnauthorizedException, UpgradeRequiredException, VariantAlsoNegotiatesException, bootstrapApplication, getControllerMetadata, getGuardForController, getGuardForControllerAction, getInjectableMetadata, getModuleMetadata, getRouteMetadata, inject };
|
|
330
|
+
export { AppInjector, Authorize, BadGatewayException, BadRequestException, CONTROLLER_METADATA_KEY, ConflictException, Controller, type ControllerAction, Delete, ForbiddenException, GatewayTimeoutException, Get, type HttpMethod, HttpVersionNotSupportedException, type IApp, type IBinding, type IControllerMetadata, type IGuard, type IMiddleware, type IModuleMetadata, INJECTABLE_METADATA_KEY, type IRequest, type IResponse, type IRouteDefinition, type IRouteMetadata, Injectable, InsufficientStorageException, InternalServerException, type Lifetime, type LogLevel, Logger, LoopDetectedException, MODULE_METADATA_KEY, type MaybeAsync, MethodNotAllowedException, Module, NetworkAuthenticationRequiredException, NetworkConnectTimeoutException, type NextFunction, NotAcceptableException, NotExtendedException, NotFoundException, NotImplementedException, NoxApp, Patch, PaymentRequiredException, Post, Put, ROUTE_METADATA_KEY, Request, RequestTimeoutException, ResponseException, RootInjector, Router, ServiceUnavailableException, TooManyRequestsException, type Type, UnauthorizedException, UpgradeRequiredException, UseMiddlewares, VariantAlsoNegotiatesException, bootstrapApplication, getControllerMetadata, getGuardForController, getGuardForControllerAction, getInjectableMetadata, getMiddlewaresForController, getMiddlewaresForControllerAction, getModuleMetadata, getRouteMetadata, inject };
|
package/dist/noxus.js
CHANGED
|
@@ -28,6 +28,7 @@ var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "sy
|
|
|
28
28
|
// src/index.ts
|
|
29
29
|
var src_exports = {};
|
|
30
30
|
__export(src_exports, {
|
|
31
|
+
AppInjector: () => AppInjector,
|
|
31
32
|
Authorize: () => Authorize,
|
|
32
33
|
BadGatewayException: () => BadGatewayException,
|
|
33
34
|
BadRequestException: () => BadRequestException,
|
|
@@ -69,12 +70,15 @@ __export(src_exports, {
|
|
|
69
70
|
TooManyRequestsException: () => TooManyRequestsException,
|
|
70
71
|
UnauthorizedException: () => UnauthorizedException,
|
|
71
72
|
UpgradeRequiredException: () => UpgradeRequiredException,
|
|
73
|
+
UseMiddlewares: () => UseMiddlewares,
|
|
72
74
|
VariantAlsoNegotiatesException: () => VariantAlsoNegotiatesException,
|
|
73
75
|
bootstrapApplication: () => bootstrapApplication,
|
|
74
76
|
getControllerMetadata: () => getControllerMetadata,
|
|
75
77
|
getGuardForController: () => getGuardForController,
|
|
76
78
|
getGuardForControllerAction: () => getGuardForControllerAction,
|
|
77
79
|
getInjectableMetadata: () => getInjectableMetadata,
|
|
80
|
+
getMiddlewaresForController: () => getMiddlewaresForController,
|
|
81
|
+
getMiddlewaresForControllerAction: () => getMiddlewaresForControllerAction,
|
|
78
82
|
getModuleMetadata: () => getModuleMetadata,
|
|
79
83
|
getRouteMetadata: () => getRouteMetadata,
|
|
80
84
|
inject: () => inject
|
|
@@ -86,8 +90,18 @@ var import_reflect_metadata = require("reflect-metadata");
|
|
|
86
90
|
|
|
87
91
|
// src/exceptions.ts
|
|
88
92
|
var _ResponseException = class _ResponseException extends Error {
|
|
89
|
-
constructor(message
|
|
90
|
-
|
|
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
|
+
}
|
|
91
105
|
this.name = this.constructor.name.replace(/([A-Z])/g, " $1");
|
|
92
106
|
}
|
|
93
107
|
};
|
|
@@ -279,8 +293,7 @@ __name(_NetworkConnectTimeoutException, "NetworkConnectTimeoutException");
|
|
|
279
293
|
var NetworkConnectTimeoutException = _NetworkConnectTimeoutException;
|
|
280
294
|
|
|
281
295
|
// src/DI/app-injector.ts
|
|
282
|
-
var
|
|
283
|
-
var AppInjector = (_a = class {
|
|
296
|
+
var _AppInjector = class _AppInjector {
|
|
284
297
|
constructor(name = null) {
|
|
285
298
|
__publicField(this, "name");
|
|
286
299
|
__publicField(this, "bindings", /* @__PURE__ */ new Map());
|
|
@@ -293,7 +306,7 @@ var AppInjector = (_a = class {
|
|
|
293
306
|
* au niveau "scope" (donc durée de vie d'une requête)
|
|
294
307
|
*/
|
|
295
308
|
createScope() {
|
|
296
|
-
const scope = new
|
|
309
|
+
const scope = new _AppInjector();
|
|
297
310
|
scope.bindings = this.bindings;
|
|
298
311
|
scope.singletons = this.singletons;
|
|
299
312
|
return scope;
|
|
@@ -304,7 +317,8 @@ var AppInjector = (_a = class {
|
|
|
304
317
|
*/
|
|
305
318
|
resolve(target) {
|
|
306
319
|
const binding = this.bindings.get(target);
|
|
307
|
-
if (!binding) throw new InternalServerException(`Failed to resolve a dependency injection : No binding for type ${target.name}
|
|
320
|
+
if (!binding) throw new InternalServerException(`Failed to resolve a dependency injection : No binding for type ${target.name}.
|
|
321
|
+
Did you forget to use @Injectable() decorator ?`);
|
|
308
322
|
switch (binding.lifetime) {
|
|
309
323
|
case "transient":
|
|
310
324
|
return this.instantiate(binding.implementation);
|
|
@@ -333,7 +347,9 @@ var AppInjector = (_a = class {
|
|
|
333
347
|
const params = paramTypes.map((p) => this.resolve(p));
|
|
334
348
|
return new target(...params);
|
|
335
349
|
}
|
|
336
|
-
}
|
|
350
|
+
};
|
|
351
|
+
__name(_AppInjector, "AppInjector");
|
|
352
|
+
var AppInjector = _AppInjector;
|
|
337
353
|
var RootInjector = new AppInjector("root");
|
|
338
354
|
function inject(t) {
|
|
339
355
|
return RootInjector.resolve(t);
|
|
@@ -473,7 +489,7 @@ function Authorize(...guardClasses) {
|
|
|
473
489
|
if (authorizations.has(key)) {
|
|
474
490
|
throw new Error(`Guard(s) already registered for ${key}`);
|
|
475
491
|
}
|
|
476
|
-
Logger.debug(`Registering
|
|
492
|
+
Logger.debug(`Registering guard(s) for ${key}: ${guardClasses.map((c) => c.name).join(", ")}`);
|
|
477
493
|
authorizations.set(key, guardClasses);
|
|
478
494
|
};
|
|
479
495
|
}
|
|
@@ -636,9 +652,41 @@ function getControllerMetadata(target) {
|
|
|
636
652
|
}
|
|
637
653
|
__name(getControllerMetadata, "getControllerMetadata");
|
|
638
654
|
|
|
655
|
+
// src/decorators/middleware.decorator.ts
|
|
656
|
+
var middlewares = /* @__PURE__ */ new Map();
|
|
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
|
+
|
|
639
687
|
// src/utils/radix-tree.ts
|
|
640
|
-
var
|
|
641
|
-
var RadixNode = (
|
|
688
|
+
var _a;
|
|
689
|
+
var RadixNode = (_a = class {
|
|
642
690
|
constructor(segment) {
|
|
643
691
|
__publicField(this, "segment");
|
|
644
692
|
__publicField(this, "children", []);
|
|
@@ -663,7 +711,7 @@ var RadixNode = (_a2 = class {
|
|
|
663
711
|
addChild(node) {
|
|
664
712
|
this.children.push(node);
|
|
665
713
|
}
|
|
666
|
-
}, __name(
|
|
714
|
+
}, __name(_a, "RadixNode"), _a);
|
|
667
715
|
var _RadixTree = class _RadixTree {
|
|
668
716
|
constructor() {
|
|
669
717
|
__publicField(this, "root", new RadixNode(""));
|
|
@@ -750,19 +798,29 @@ __name(_ts_decorate, "_ts_decorate");
|
|
|
750
798
|
var _Router = class _Router {
|
|
751
799
|
constructor() {
|
|
752
800
|
__publicField(this, "routes", new RadixTree());
|
|
801
|
+
__publicField(this, "rootMiddlewares", []);
|
|
753
802
|
}
|
|
803
|
+
/**
|
|
804
|
+
*
|
|
805
|
+
*/
|
|
754
806
|
registerController(controllerClass) {
|
|
755
807
|
const controllerMeta = getControllerMetadata(controllerClass);
|
|
756
808
|
const controllerGuards = getGuardForController(controllerClass.name);
|
|
809
|
+
const controllerMiddlewares = getMiddlewaresForController(controllerClass.name);
|
|
757
810
|
if (!controllerMeta) throw new Error(`Missing @Controller decorator on ${controllerClass.name}`);
|
|
758
811
|
const routeMetadata = getRouteMetadata(controllerClass);
|
|
759
812
|
for (const def of routeMetadata) {
|
|
760
813
|
const fullPath = `${controllerMeta.path}/${def.path}`.replace(/\/+/g, "/");
|
|
761
814
|
const routeGuards = getGuardForControllerAction(controllerClass.name, def.handler);
|
|
815
|
+
const routeMiddlewares = getMiddlewaresForControllerAction(controllerClass.name, def.handler);
|
|
762
816
|
const guards = /* @__PURE__ */ new Set([
|
|
763
817
|
...controllerGuards,
|
|
764
818
|
...routeGuards
|
|
765
819
|
]);
|
|
820
|
+
const middlewares2 = /* @__PURE__ */ new Set([
|
|
821
|
+
...controllerMiddlewares,
|
|
822
|
+
...routeMiddlewares
|
|
823
|
+
]);
|
|
766
824
|
const routeDef = {
|
|
767
825
|
method: def.method,
|
|
768
826
|
path: fullPath,
|
|
@@ -770,6 +828,9 @@ var _Router = class _Router {
|
|
|
770
828
|
handler: def.handler,
|
|
771
829
|
guards: [
|
|
772
830
|
...guards
|
|
831
|
+
],
|
|
832
|
+
middlewares: [
|
|
833
|
+
...middlewares2
|
|
773
834
|
]
|
|
774
835
|
};
|
|
775
836
|
this.routes.insert(fullPath + "/" + def.method, routeDef);
|
|
@@ -782,6 +843,17 @@ var _Router = class _Router {
|
|
|
782
843
|
Logger.log(`Mapped ${controllerClass.name}${controllerGuardsInfo} controller's routes`);
|
|
783
844
|
return this;
|
|
784
845
|
}
|
|
846
|
+
/**
|
|
847
|
+
*
|
|
848
|
+
*/
|
|
849
|
+
defineRootMiddleware(middleware) {
|
|
850
|
+
Logger.debug(`Registering root middleware: ${middleware.name}`);
|
|
851
|
+
this.rootMiddlewares.push(middleware);
|
|
852
|
+
return this;
|
|
853
|
+
}
|
|
854
|
+
/**
|
|
855
|
+
*
|
|
856
|
+
*/
|
|
785
857
|
async handle(request) {
|
|
786
858
|
Logger.log(`> Received request: {${request.method} /${request.path}}`);
|
|
787
859
|
const t0 = performance.now();
|
|
@@ -793,10 +865,10 @@ var _Router = class _Router {
|
|
|
793
865
|
};
|
|
794
866
|
try {
|
|
795
867
|
const routeDef = this.findRoute(request);
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
868
|
+
await this.resolveController(request, response, routeDef);
|
|
869
|
+
if (response.status > 400) {
|
|
870
|
+
throw new ResponseException(response.status, response.error);
|
|
871
|
+
}
|
|
800
872
|
} catch (error) {
|
|
801
873
|
if (error instanceof ResponseException) {
|
|
802
874
|
response.status = error.status;
|
|
@@ -820,6 +892,9 @@ var _Router = class _Router {
|
|
|
820
892
|
return response;
|
|
821
893
|
}
|
|
822
894
|
}
|
|
895
|
+
/**
|
|
896
|
+
*
|
|
897
|
+
*/
|
|
823
898
|
findRoute(request) {
|
|
824
899
|
const matchedRoutes = this.routes.search(request.path);
|
|
825
900
|
if (matchedRoutes?.node === void 0 || matchedRoutes.node.children.length === 0) {
|
|
@@ -831,21 +906,68 @@ var _Router = class _Router {
|
|
|
831
906
|
}
|
|
832
907
|
return routeDef.value;
|
|
833
908
|
}
|
|
834
|
-
|
|
909
|
+
/**
|
|
910
|
+
*
|
|
911
|
+
*/
|
|
912
|
+
async resolveController(request, response, routeDef) {
|
|
835
913
|
const controllerInstance = request.context.resolve(routeDef.controller);
|
|
836
914
|
Object.assign(request.params, this.extractParams(request.path, routeDef.path));
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
915
|
+
await this.runRequestPipeline(request, response, routeDef, controllerInstance);
|
|
916
|
+
}
|
|
917
|
+
/**
|
|
918
|
+
*
|
|
919
|
+
*/
|
|
920
|
+
async runRequestPipeline(request, response, routeDef, controllerInstance) {
|
|
921
|
+
const middlewares2 = [
|
|
922
|
+
.../* @__PURE__ */ new Set([
|
|
923
|
+
...this.rootMiddlewares,
|
|
924
|
+
...routeDef.middlewares
|
|
925
|
+
])
|
|
926
|
+
];
|
|
927
|
+
const middlewareMaxIndex = middlewares2.length - 1;
|
|
928
|
+
const guardsMaxIndex = middlewareMaxIndex + routeDef.guards.length;
|
|
929
|
+
let index = -1;
|
|
930
|
+
const dispatch = /* @__PURE__ */ __name(async (i) => {
|
|
931
|
+
if (i <= index) throw new Error("next() called multiple times");
|
|
932
|
+
index = i;
|
|
933
|
+
if (i <= middlewareMaxIndex) {
|
|
934
|
+
const nextFn = dispatch.bind(null, i + 1);
|
|
935
|
+
await this.runMiddleware(request, response, nextFn, middlewares2[i]);
|
|
936
|
+
if (response.status >= 400) {
|
|
937
|
+
throw new ResponseException(response.status, response.error);
|
|
938
|
+
}
|
|
939
|
+
return;
|
|
842
940
|
}
|
|
843
|
-
|
|
844
|
-
|
|
941
|
+
if (i <= guardsMaxIndex) {
|
|
942
|
+
const guardIndex = i - middlewares2.length;
|
|
943
|
+
const guardType = routeDef.guards[guardIndex];
|
|
944
|
+
await this.runGuard(request, guardType);
|
|
945
|
+
dispatch(i + 1);
|
|
946
|
+
return;
|
|
947
|
+
}
|
|
948
|
+
const action = controllerInstance[routeDef.handler];
|
|
949
|
+
response.body = await action.call(controllerInstance, request, response);
|
|
950
|
+
}, "dispatch");
|
|
951
|
+
await dispatch(0);
|
|
845
952
|
}
|
|
846
|
-
|
|
847
|
-
|
|
953
|
+
/**
|
|
954
|
+
*
|
|
955
|
+
*/
|
|
956
|
+
async runMiddleware(request, response, next, middlewareType) {
|
|
957
|
+
const middleware = request.context.resolve(middlewareType);
|
|
958
|
+
await middleware.invoke(request, response, next);
|
|
959
|
+
}
|
|
960
|
+
/**
|
|
961
|
+
*
|
|
962
|
+
*/
|
|
963
|
+
async runGuard(request, guardType) {
|
|
964
|
+
const guard = request.context.resolve(guardType);
|
|
965
|
+
const allowed = await guard.canActivate(request);
|
|
966
|
+
if (!allowed) throw new UnauthorizedException(`Unauthorized for ${request.method} ${request.path}`);
|
|
848
967
|
}
|
|
968
|
+
/**
|
|
969
|
+
*
|
|
970
|
+
*/
|
|
849
971
|
extractParams(actual, template) {
|
|
850
972
|
const aParts = actual.split("/");
|
|
851
973
|
const tParts = template.split("/");
|
|
@@ -909,7 +1031,7 @@ var _NoxApp = class _NoxApp {
|
|
|
909
1031
|
this.router = router;
|
|
910
1032
|
}
|
|
911
1033
|
/**
|
|
912
|
-
*
|
|
1034
|
+
*
|
|
913
1035
|
*/
|
|
914
1036
|
async init() {
|
|
915
1037
|
import_main.ipcMain.on("gimme-my-port", this.giveTheRendererAPort.bind(this));
|
|
@@ -919,7 +1041,7 @@ var _NoxApp = class _NoxApp {
|
|
|
919
1041
|
return this;
|
|
920
1042
|
}
|
|
921
1043
|
/**
|
|
922
|
-
*
|
|
1044
|
+
*
|
|
923
1045
|
*/
|
|
924
1046
|
giveTheRendererAPort(event) {
|
|
925
1047
|
const senderId = event.sender.id;
|
|
@@ -981,7 +1103,7 @@ var _NoxApp = class _NoxApp {
|
|
|
981
1103
|
this.messagePorts.delete(channelSenderId);
|
|
982
1104
|
}
|
|
983
1105
|
/**
|
|
984
|
-
*
|
|
1106
|
+
*
|
|
985
1107
|
*/
|
|
986
1108
|
async onAllWindowsClosed() {
|
|
987
1109
|
this.messagePorts.forEach((channel, senderId) => {
|
|
@@ -998,6 +1120,10 @@ var _NoxApp = class _NoxApp {
|
|
|
998
1120
|
this.app = inject(app3);
|
|
999
1121
|
return this;
|
|
1000
1122
|
}
|
|
1123
|
+
use(middleware) {
|
|
1124
|
+
this.router.defineRootMiddleware(middleware);
|
|
1125
|
+
return this;
|
|
1126
|
+
}
|
|
1001
1127
|
/**
|
|
1002
1128
|
* Should be called after the bootstrapApplication function is called.
|
|
1003
1129
|
*/
|
|
@@ -1030,6 +1156,7 @@ async function bootstrapApplication(rootModule) {
|
|
|
1030
1156
|
__name(bootstrapApplication, "bootstrapApplication");
|
|
1031
1157
|
// Annotate the CommonJS export names for ESM import in node:
|
|
1032
1158
|
0 && (module.exports = {
|
|
1159
|
+
AppInjector,
|
|
1033
1160
|
Authorize,
|
|
1034
1161
|
BadGatewayException,
|
|
1035
1162
|
BadRequestException,
|
|
@@ -1071,12 +1198,15 @@ __name(bootstrapApplication, "bootstrapApplication");
|
|
|
1071
1198
|
TooManyRequestsException,
|
|
1072
1199
|
UnauthorizedException,
|
|
1073
1200
|
UpgradeRequiredException,
|
|
1201
|
+
UseMiddlewares,
|
|
1074
1202
|
VariantAlsoNegotiatesException,
|
|
1075
1203
|
bootstrapApplication,
|
|
1076
1204
|
getControllerMetadata,
|
|
1077
1205
|
getGuardForController,
|
|
1078
1206
|
getGuardForControllerAction,
|
|
1079
1207
|
getInjectableMetadata,
|
|
1208
|
+
getMiddlewaresForController,
|
|
1209
|
+
getMiddlewaresForControllerAction,
|
|
1080
1210
|
getModuleMetadata,
|
|
1081
1211
|
getRouteMetadata,
|
|
1082
1212
|
inject
|