@noxfly/noxus 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +348 -0
- package/dist/noxus.d.mts +231 -0
- package/dist/noxus.d.ts +231 -0
- package/dist/noxus.js +1011 -0
- package/dist/noxus.js.map +1 -0
- package/dist/noxus.mjs +940 -0
- package/dist/noxus.mjs.map +1 -0
- package/eslint.config.js +108 -0
- package/images/screenshot-requests.png +0 -0
- package/images/screenshot-startup.png +0 -0
- package/package.json +41 -0
- package/src/app-injector.ts +80 -0
- package/src/app.ts +72 -0
- package/src/bootstrap.ts +126 -0
- package/src/exceptions.ts +35 -0
- package/src/guards.ts +51 -0
- package/src/index.ts +10 -0
- package/src/injector-explorer.ts +53 -0
- package/src/logger.ts +136 -0
- package/src/metadata.ts +52 -0
- package/src/misc.ts +1 -0
- package/src/radix-tree.ts +137 -0
- package/src/request.ts +38 -0
- package/src/router.ts +221 -0
- package/tsconfig.json +34 -0
- package/tsup.config.ts +20 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 NoxFly
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,348 @@
|
|
|
1
|
+
# ⚡ Noxus — The NestJS-Inspired Framework Built for Electron
|
|
2
|
+
|
|
3
|
+
Noxus brings the elegance and power of NestJS-like architecture to Electron applications — but with a purpose-built design for IPC and MessagePort communication instead of HTTP.
|
|
4
|
+
|
|
5
|
+
While NestJS is an excellent framework for building web servers, it is not suited for Electron environments where communication between the main process and the renderer is critical.
|
|
6
|
+
|
|
7
|
+
Transferring data between these using a local server and using HTTP request would be a waste of resources for the user's target device.
|
|
8
|
+
|
|
9
|
+
Noxus fills that gap.
|
|
10
|
+
|
|
11
|
+
✅ Use of decorators
|
|
12
|
+
|
|
13
|
+
✅ Use of dependency injection, with lifetimes management (singleton, scope, transient)
|
|
14
|
+
|
|
15
|
+
✅ Modular architecture with the use of modules, defining a map of controllers and services
|
|
16
|
+
|
|
17
|
+
✅ Automatic and performant controller and route registration with path and method mapping
|
|
18
|
+
|
|
19
|
+
✅ A true request/response model built on top of MessagePort to look like HTTP requests
|
|
20
|
+
|
|
21
|
+
✅ Custom exception handling and unified error responses
|
|
22
|
+
|
|
23
|
+
✅ Decorator-based guard system for route and controller authorization
|
|
24
|
+
|
|
25
|
+
✅ Scoped dependency injection per request context
|
|
26
|
+
|
|
27
|
+
✅ Setup the electron application and communication with your renderer easily and with flexibility
|
|
28
|
+
|
|
29
|
+
✅ TypeScript-first with full type safety and metadata reflection
|
|
30
|
+
|
|
31
|
+
✅ Pluggable logging with color-coded output for different log levels
|
|
32
|
+
|
|
33
|
+
<sub>* If you see any issue and you'd like to enhance this framework, feel free to open an issue, fork and do a pull request.</sub>
|
|
34
|
+
|
|
35
|
+
## Installation
|
|
36
|
+
|
|
37
|
+
Install the package in your main process application :
|
|
38
|
+
|
|
39
|
+
```sh
|
|
40
|
+
npm i @noxfly/noxus
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
If you have a separated renderer from the main process, you'd like to install the package as well to get typed requests/responses models, for development purposes :
|
|
44
|
+
|
|
45
|
+
```sh
|
|
46
|
+
npm i -D @noxfly/noxus
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
Because you only need types during development, using the `-D` argument will make this package a `devDependency`, thus won't be present on your build.
|
|
50
|
+
|
|
51
|
+
## Basic use
|
|
52
|
+
|
|
53
|
+
When employing "main", we consider this is the electron side of your application.
|
|
54
|
+
|
|
55
|
+
When employing "renderer", this is the separated renderer side of your application.
|
|
56
|
+
|
|
57
|
+
However, you can feel free to keep both merged, this won't change anything, but for further examples, this will be done to show you where the code should go.
|
|
58
|
+
|
|
59
|
+
### Setup Main Process side
|
|
60
|
+
|
|
61
|
+
```ts
|
|
62
|
+
// main/index.ts
|
|
63
|
+
|
|
64
|
+
import { bootstrapApplication } from '@noxfly/noxus';
|
|
65
|
+
import { Application } from './modules/app.service.ts';
|
|
66
|
+
|
|
67
|
+
async function main() {
|
|
68
|
+
const application = await bootstrapApplication(Application, AppModule);
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
main();
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
> ℹ️ Note that you have to specify which service you'd like to see as your application root's service, so the framework can interact with it and setup things on it.
|
|
75
|
+
|
|
76
|
+
```ts
|
|
77
|
+
// main/modules/app.service.ts
|
|
78
|
+
|
|
79
|
+
import { IApp, Injectable, Logger } from '@noxfly/noxus';
|
|
80
|
+
|
|
81
|
+
@Injectable('singleton')
|
|
82
|
+
export class Application implements IApp {
|
|
83
|
+
constructor(
|
|
84
|
+
private readonly windowManager: WindowManager, // An Injectable too
|
|
85
|
+
) {}
|
|
86
|
+
|
|
87
|
+
// automatically called by the bootstrapApplication function
|
|
88
|
+
// once it is all setup
|
|
89
|
+
public async onReady(): Promise<void> {
|
|
90
|
+
Logger.info("Application's ready");
|
|
91
|
+
this.windowManager.createMain(); // Your custom logic here to create a window
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
```ts
|
|
97
|
+
// main/modules/app.module.ts
|
|
98
|
+
|
|
99
|
+
import { Module } from '@noxfly/noxus';
|
|
100
|
+
|
|
101
|
+
@Module({
|
|
102
|
+
imports: [UsersModule], // import modules to be found here
|
|
103
|
+
providers: [], // define services that should be found here
|
|
104
|
+
controllers: [], // define controllers that this module has to create a route node
|
|
105
|
+
})
|
|
106
|
+
export class AppModule {}
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
> ℹ️ Note that we do not register Application service in it because it already has been registered when bootstraping the application.
|
|
110
|
+
|
|
111
|
+
```ts
|
|
112
|
+
// main/modules/users/users.module.ts
|
|
113
|
+
|
|
114
|
+
import { Module } from '@noxfly/noxus';
|
|
115
|
+
|
|
116
|
+
@Module({
|
|
117
|
+
providers: [UsersService],
|
|
118
|
+
controllers: [UsersController],
|
|
119
|
+
})
|
|
120
|
+
export class UsersModule {}
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
```ts
|
|
124
|
+
// main/modules/users/users.service.ts
|
|
125
|
+
|
|
126
|
+
import { Injectable } from '@noxfly/noxus';
|
|
127
|
+
|
|
128
|
+
@Injectable()
|
|
129
|
+
export class UsersService {
|
|
130
|
+
public async findAll(): Promise<User[]> {
|
|
131
|
+
// ...
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
public async findOneById(id: string): Promise<User> {
|
|
135
|
+
// ...
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
> ℹ️ You can specify the lifetime of an injectable passing a value in the decorator, between `singleton`, `scope` or `transient` (default to `scope`).
|
|
141
|
+
|
|
142
|
+
```ts
|
|
143
|
+
// main/modules/users/users.controller.ts
|
|
144
|
+
|
|
145
|
+
import { Controller, Get } from '@noxfly/noxus';
|
|
146
|
+
import { UsersService } from './users.service.ts';
|
|
147
|
+
|
|
148
|
+
@Controller('users')
|
|
149
|
+
export class UsersController {
|
|
150
|
+
constructor(
|
|
151
|
+
private readonly usersService: UsersService,
|
|
152
|
+
) {}
|
|
153
|
+
|
|
154
|
+
@Get('all')
|
|
155
|
+
public getAll(): Promise<User[]> {
|
|
156
|
+
return await this.usersService.findAll();
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
@Get('profile/:id')
|
|
160
|
+
@Authorize(AuthGuard)
|
|
161
|
+
public getProfile(IRequest request, IResponse response): Promise<User | undefined> {
|
|
162
|
+
return await this.usersService.findOneById(request.params.id);
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
Further upgrades might include new decorators like `@Param()`, `@Body()` etc... like Nest.js offers.
|
|
168
|
+
|
|
169
|
+
```ts
|
|
170
|
+
// main/guards/auth.guard.ts
|
|
171
|
+
|
|
172
|
+
import { IGuard, Injectable, MaybeAsync, Request } from 'nox';
|
|
173
|
+
|
|
174
|
+
@Injectable()
|
|
175
|
+
export class AuthGuard implements IGuard {
|
|
176
|
+
constructor(
|
|
177
|
+
private readonly authService: AuthService
|
|
178
|
+
) {}
|
|
179
|
+
|
|
180
|
+
public async canActivate(IRequest request): MaybeAsync<boolean> {
|
|
181
|
+
return this.authService.isAuthenticated();
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
```
|
|
185
|
+
|
|
186
|
+
Here is the output (not with that exact same example) when running the main process :
|
|
187
|
+
|
|
188
|
+

|
|
189
|
+
|
|
190
|
+
|
|
191
|
+
### Setup Preload
|
|
192
|
+
|
|
193
|
+
We need some configuration on the preload so the main process can give the renderer a port (MessagePort) to communicate with. Everytime this is requested, a new channel is created, an d the previous is closed.
|
|
194
|
+
|
|
195
|
+
```ts
|
|
196
|
+
// main/preload.ts
|
|
197
|
+
|
|
198
|
+
import { contextBridge, ipcRenderer } from 'electron/renderer';
|
|
199
|
+
|
|
200
|
+
// .invoke -> front sends to back
|
|
201
|
+
// .on -> back sends to front
|
|
202
|
+
|
|
203
|
+
type fn = (...args: any[]) => void;
|
|
204
|
+
|
|
205
|
+
contextBridge.exposeInMainWorld('ipcRenderer', {
|
|
206
|
+
requestPort: () => ipcRenderer.send('gimme-my-port'),
|
|
207
|
+
|
|
208
|
+
hereIsMyPort: () => ipcRenderer.once('port', (e) => {
|
|
209
|
+
e.ports[0]?.start();
|
|
210
|
+
window.postMessage({ type: 'init-port' }, '*', [e.ports[0]!]);
|
|
211
|
+
}),
|
|
212
|
+
});
|
|
213
|
+
```
|
|
214
|
+
|
|
215
|
+
> ⚠️ As the Electron documentation warns well, you should NEVER expose the whole ipcRenderer to the renderer. Expose only restricted API that your renderer could use.
|
|
216
|
+
|
|
217
|
+
We need to use `window.postMessage()` and not a custom callback function, otherwise the port would have been structuredCloned and would only arrive to the renderer with the `onmessage` function, and nothing else (a bit frustrating to not request, isn't it).
|
|
218
|
+
|
|
219
|
+
|
|
220
|
+
### Setup Renderer
|
|
221
|
+
|
|
222
|
+
I am personnally using Angular as renderer, so there might be some changes if you use another framework or vanilla js, but it is only about typescript's configuration and types.
|
|
223
|
+
|
|
224
|
+
Maybe this should become a class directly available from @noxfly/noxus;
|
|
225
|
+
|
|
226
|
+
```ts
|
|
227
|
+
// renderer/anyFileAtStartup.ts
|
|
228
|
+
|
|
229
|
+
import { IRequest, IResponse } from '@noxfly/noxus';
|
|
230
|
+
|
|
231
|
+
interface PendingRequestHandlers<T> {
|
|
232
|
+
resolve: (value: IResponse<T>) => void;
|
|
233
|
+
reject: (reason?: IResponse<T>) => void;
|
|
234
|
+
request: IRequest;
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
// might be a singleton service
|
|
238
|
+
class ElectronService {
|
|
239
|
+
private readonly bridge: any;
|
|
240
|
+
private readonly ipcRenderer: any; // if you know how to get a type, tell me
|
|
241
|
+
|
|
242
|
+
private port: MessagePort | undefined;
|
|
243
|
+
private readonly pendingRequests = new Map<string, PendingRequestsHandlers<any>>();
|
|
244
|
+
|
|
245
|
+
constructor() {
|
|
246
|
+
this.bridge = window as any;
|
|
247
|
+
this.ipcRenderer = this.bridge.ipcRenderer;
|
|
248
|
+
|
|
249
|
+
// when receiving the port given by the main renderer -> preload -> renderer
|
|
250
|
+
window.addEventListener('message', (event: MessageEvent) => {
|
|
251
|
+
if(event.data?.type === 'init-port' && event.ports.length > 0) {
|
|
252
|
+
this.port = event.ports[0]!;
|
|
253
|
+
this.port.onmessage = onResponse;
|
|
254
|
+
}
|
|
255
|
+
});
|
|
256
|
+
|
|
257
|
+
ipcRenderer.requestPort();
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
/**
|
|
261
|
+
* Resolve the signal-based response
|
|
262
|
+
*/
|
|
263
|
+
private onResponse(event: MessageEvent): void {
|
|
264
|
+
const response: IResponse<unknown> = event.data;
|
|
265
|
+
|
|
266
|
+
if(!response || !response.requestId) {
|
|
267
|
+
console.error('Received invalid response:', response);
|
|
268
|
+
return;
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
const pending = this.pendingRequests.get(response.requestId);
|
|
272
|
+
|
|
273
|
+
if(!pending) {
|
|
274
|
+
console.error(`No handler found for request ID: ${response.requestId}`);
|
|
275
|
+
return;
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
this.pendingRequests.delete(response.requestId);
|
|
279
|
+
|
|
280
|
+
let fn: (response: IResponse<unknown>) => void = pending.resolve;
|
|
281
|
+
|
|
282
|
+
console.groupCollapsed(`${response.status} ${pending.request.method} /${pending.request.path}`);
|
|
283
|
+
|
|
284
|
+
if(response.error) {
|
|
285
|
+
console.error('error message:', response.error);
|
|
286
|
+
fn = pending.reject;
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
console.info('response:', response.body);
|
|
290
|
+
console.info('request:', pending.request);
|
|
291
|
+
|
|
292
|
+
console.groupEnd();
|
|
293
|
+
|
|
294
|
+
fn(response);
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
/**
|
|
298
|
+
* Initiate a request to the main process
|
|
299
|
+
*/
|
|
300
|
+
public request<T>(request: Omit<IRequest, 'requestId'>): Promise<T> {
|
|
301
|
+
return new Promise<T>((resolve, reject) => {
|
|
302
|
+
if(!this.port) {
|
|
303
|
+
return reject(new Error("MessagePort is not available"));
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
const req: IRequest = {
|
|
307
|
+
requestId: /* Create a random ID with the function of your choice */,
|
|
308
|
+
...request,
|
|
309
|
+
};
|
|
310
|
+
|
|
311
|
+
this.pendingRequests.set(req.requestId, {
|
|
312
|
+
resolve: (response: IResponse<T>) => (response.status < 400)
|
|
313
|
+
? resolve(response.body as T)
|
|
314
|
+
: reject(response);
|
|
315
|
+
reject: (response?: IResponse<T>) => reject(response),
|
|
316
|
+
request: req,
|
|
317
|
+
});
|
|
318
|
+
|
|
319
|
+
this.port.postMessage(req);
|
|
320
|
+
});
|
|
321
|
+
}
|
|
322
|
+
}
|
|
323
|
+
```
|
|
324
|
+
|
|
325
|
+
Use it like that :
|
|
326
|
+
|
|
327
|
+
```ts
|
|
328
|
+
const response: User[] = await electronService.request<User[]>({
|
|
329
|
+
method: 'GET',
|
|
330
|
+
path: 'users/all',
|
|
331
|
+
});
|
|
332
|
+
```
|
|
333
|
+
|
|
334
|
+

|
|
335
|
+
|
|
336
|
+
|
|
337
|
+
## Contributing
|
|
338
|
+
|
|
339
|
+
1. Clone the repo
|
|
340
|
+
1. `npm i`
|
|
341
|
+
1. Develop
|
|
342
|
+
1. Push changes (automatically builds)
|
|
343
|
+
1. Create a PR
|
|
344
|
+
|
|
345
|
+
if you'd like to test your changes locally :
|
|
346
|
+
1. `npm run build`
|
|
347
|
+
1. from an electron project, `npm i ../<path/to/repo>`
|
|
348
|
+
|
package/dist/noxus.d.mts
ADDED
|
@@ -0,0 +1,231 @@
|
|
|
1
|
+
type MaybeAsync<T> = T | Promise<T>;
|
|
2
|
+
|
|
3
|
+
interface IApp {
|
|
4
|
+
dispose(): Promise<void>;
|
|
5
|
+
onReady(): Promise<void>;
|
|
6
|
+
}
|
|
7
|
+
declare function Injectable(lifetime?: Lifetime): ClassDecorator;
|
|
8
|
+
declare function Module(metadata: IModuleMetadata): ClassDecorator;
|
|
9
|
+
|
|
10
|
+
type HttpMethod = 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE';
|
|
11
|
+
interface IRouteDefinition {
|
|
12
|
+
method: string;
|
|
13
|
+
path: string;
|
|
14
|
+
controller: Type<any>;
|
|
15
|
+
handler: string;
|
|
16
|
+
guards: Type<IGuard>[];
|
|
17
|
+
}
|
|
18
|
+
type ControllerAction = (request: Request, response: IResponse) => any;
|
|
19
|
+
declare function Controller(path: string): ClassDecorator;
|
|
20
|
+
declare const Get: (path: string) => MethodDecorator;
|
|
21
|
+
declare const Post: (path: string) => MethodDecorator;
|
|
22
|
+
declare const Put: (path: string) => MethodDecorator;
|
|
23
|
+
declare const Patch: (path: string) => MethodDecorator;
|
|
24
|
+
declare const Delete: (path: string) => MethodDecorator;
|
|
25
|
+
declare class Router {
|
|
26
|
+
private readonly routes;
|
|
27
|
+
registerController(controllerClass: Type<unknown>): Router;
|
|
28
|
+
handle(request: Request): Promise<IResponse>;
|
|
29
|
+
private findRoute;
|
|
30
|
+
private resolveController;
|
|
31
|
+
private verifyRequestBody;
|
|
32
|
+
private extractParams;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
declare class Request {
|
|
36
|
+
readonly app: IApp;
|
|
37
|
+
readonly event: Electron.MessageEvent;
|
|
38
|
+
readonly id: string;
|
|
39
|
+
readonly method: HttpMethod;
|
|
40
|
+
readonly path: string;
|
|
41
|
+
readonly body: any;
|
|
42
|
+
readonly context: any;
|
|
43
|
+
readonly params: Record<string, string>;
|
|
44
|
+
constructor(app: IApp, event: Electron.MessageEvent, id: string, method: HttpMethod, path: string, body: any);
|
|
45
|
+
}
|
|
46
|
+
interface IRequest<T = any> {
|
|
47
|
+
requestId: string;
|
|
48
|
+
path: string;
|
|
49
|
+
method: HttpMethod;
|
|
50
|
+
body?: T;
|
|
51
|
+
}
|
|
52
|
+
interface IResponse<T = any> {
|
|
53
|
+
requestId: string;
|
|
54
|
+
status: number;
|
|
55
|
+
body?: T;
|
|
56
|
+
error?: string;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
interface IGuard {
|
|
60
|
+
canActivate(request: Request): MaybeAsync<boolean>;
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Peut être utilisé pour protéger les routes d'un contrôleur.
|
|
64
|
+
* Peut être utilisé sur une classe controleur, ou sur une méthode de contrôleur.
|
|
65
|
+
*/
|
|
66
|
+
declare function Authorize(...guardClasses: Type<IGuard>[]): MethodDecorator & ClassDecorator;
|
|
67
|
+
declare function getGuardForController(controllerName: string): Type<IGuard>[];
|
|
68
|
+
declare function getGuardForControllerAction(controllerName: string, actionName: string): Type<IGuard>[];
|
|
69
|
+
|
|
70
|
+
interface Type<T> extends Function {
|
|
71
|
+
new (...args: any[]): T;
|
|
72
|
+
}
|
|
73
|
+
declare const MODULE_METADATA_KEY: unique symbol;
|
|
74
|
+
declare const INJECTABLE_METADATA_KEY: unique symbol;
|
|
75
|
+
declare const CONTROLLER_METADATA_KEY: unique symbol;
|
|
76
|
+
declare const ROUTE_METADATA_KEY: unique symbol;
|
|
77
|
+
interface IModuleMetadata {
|
|
78
|
+
imports?: Type<unknown>[];
|
|
79
|
+
providers?: Type<unknown>[];
|
|
80
|
+
controllers?: Type<unknown>[];
|
|
81
|
+
exports?: Type<unknown>[];
|
|
82
|
+
}
|
|
83
|
+
interface IRouteMetadata {
|
|
84
|
+
method: HttpMethod;
|
|
85
|
+
path: string;
|
|
86
|
+
handler: string;
|
|
87
|
+
guards: Type<IGuard>[];
|
|
88
|
+
}
|
|
89
|
+
interface IControllerMetadata {
|
|
90
|
+
path: string;
|
|
91
|
+
guards: Type<IGuard>[];
|
|
92
|
+
}
|
|
93
|
+
declare function getControllerMetadata(target: Type<unknown>): IControllerMetadata | undefined;
|
|
94
|
+
declare function getRouteMetadata(target: Type<unknown>): IRouteMetadata[];
|
|
95
|
+
declare function getModuleMetadata(target: Function): IModuleMetadata | undefined;
|
|
96
|
+
declare function getInjectableMetadata(target: Type<unknown>): Lifetime | undefined;
|
|
97
|
+
|
|
98
|
+
type Lifetime = 'singleton' | 'scope' | 'transient';
|
|
99
|
+
interface IBinding {
|
|
100
|
+
lifetime: Lifetime;
|
|
101
|
+
implementation: Type<unknown>;
|
|
102
|
+
instance?: InstanceType<Type<unknown>>;
|
|
103
|
+
}
|
|
104
|
+
declare class AppInjector {
|
|
105
|
+
readonly name: string | null;
|
|
106
|
+
bindings: Map<Type<unknown>, IBinding>;
|
|
107
|
+
singletons: Map<Type<unknown>, unknown>;
|
|
108
|
+
scoped: Map<Type<unknown>, unknown>;
|
|
109
|
+
constructor(name?: string | null);
|
|
110
|
+
/**
|
|
111
|
+
* Utilisé généralement pour créer un scope d'injection de dépendances
|
|
112
|
+
* au niveau "scope" (donc durée de vie d'une requête)
|
|
113
|
+
*/
|
|
114
|
+
createScope(): AppInjector;
|
|
115
|
+
/**
|
|
116
|
+
* Appelé lorsqu'on souhaite résoudre une dépendance,
|
|
117
|
+
* c'est-à-dire récupérer l'instance d'une classe donnée.
|
|
118
|
+
*/
|
|
119
|
+
resolve<T extends Type<unknown>>(target: T): InstanceType<T>;
|
|
120
|
+
/**
|
|
121
|
+
*
|
|
122
|
+
*/
|
|
123
|
+
private instantiate;
|
|
124
|
+
}
|
|
125
|
+
declare const RootInjector: AppInjector;
|
|
126
|
+
|
|
127
|
+
/**
|
|
128
|
+
*
|
|
129
|
+
*/
|
|
130
|
+
declare function bootstrapApplication(root: Type<IApp>, rootModule: Type<any>): Promise<IApp>;
|
|
131
|
+
|
|
132
|
+
declare abstract class ResponseException extends Error {
|
|
133
|
+
abstract readonly status: number;
|
|
134
|
+
constructor(message: string);
|
|
135
|
+
}
|
|
136
|
+
declare class BadRequestException extends ResponseException {
|
|
137
|
+
readonly status = 400;
|
|
138
|
+
}
|
|
139
|
+
declare class UnauthorizedException extends ResponseException {
|
|
140
|
+
readonly status = 401;
|
|
141
|
+
}
|
|
142
|
+
declare class ForbiddenException extends ResponseException {
|
|
143
|
+
readonly status = 403;
|
|
144
|
+
}
|
|
145
|
+
declare class NotFoundException extends ResponseException {
|
|
146
|
+
readonly status = 404;
|
|
147
|
+
}
|
|
148
|
+
declare class MethodNotAllowedException extends ResponseException {
|
|
149
|
+
readonly status = 405;
|
|
150
|
+
}
|
|
151
|
+
declare class NotAcceptableException extends ResponseException {
|
|
152
|
+
readonly status = 406;
|
|
153
|
+
}
|
|
154
|
+
declare class RequestTimeoutException extends ResponseException {
|
|
155
|
+
readonly status = 408;
|
|
156
|
+
}
|
|
157
|
+
declare class ConflictException extends ResponseException {
|
|
158
|
+
readonly status = 409;
|
|
159
|
+
}
|
|
160
|
+
declare class UpgradeRequiredException extends ResponseException {
|
|
161
|
+
readonly status = 426;
|
|
162
|
+
}
|
|
163
|
+
declare class TooManyRequestsException extends ResponseException {
|
|
164
|
+
readonly status = 429;
|
|
165
|
+
}
|
|
166
|
+
declare class InternalServerException extends ResponseException {
|
|
167
|
+
readonly status = 500;
|
|
168
|
+
}
|
|
169
|
+
declare class NotImplementedException extends ResponseException {
|
|
170
|
+
readonly status = 501;
|
|
171
|
+
}
|
|
172
|
+
declare class BadGatewayException extends ResponseException {
|
|
173
|
+
readonly status = 502;
|
|
174
|
+
}
|
|
175
|
+
declare class ServiceUnavailableException extends ResponseException {
|
|
176
|
+
readonly status = 503;
|
|
177
|
+
}
|
|
178
|
+
declare class GatewayTimeoutException extends ResponseException {
|
|
179
|
+
readonly status = 504;
|
|
180
|
+
}
|
|
181
|
+
declare class HttpVersionNotSupportedException extends ResponseException {
|
|
182
|
+
readonly status = 505;
|
|
183
|
+
}
|
|
184
|
+
declare class VariantAlsoNegotiatesException extends ResponseException {
|
|
185
|
+
readonly status = 506;
|
|
186
|
+
}
|
|
187
|
+
declare class InsufficientStorageException extends ResponseException {
|
|
188
|
+
readonly status = 507;
|
|
189
|
+
}
|
|
190
|
+
declare class LoopDetectedException extends ResponseException {
|
|
191
|
+
readonly status = 508;
|
|
192
|
+
}
|
|
193
|
+
declare class NotExtendedException extends ResponseException {
|
|
194
|
+
readonly status = 510;
|
|
195
|
+
}
|
|
196
|
+
declare class NetworkAuthenticationRequiredException extends ResponseException {
|
|
197
|
+
readonly status = 511;
|
|
198
|
+
}
|
|
199
|
+
declare class NetworkConnectTimeoutException extends ResponseException {
|
|
200
|
+
readonly status = 599;
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
type LogLevel = 'log' | 'info' | 'warn' | 'error' | 'debug';
|
|
204
|
+
declare namespace Logger {
|
|
205
|
+
function setLogLevel(level: LogLevel): void;
|
|
206
|
+
const colors: {
|
|
207
|
+
black: string;
|
|
208
|
+
grey: string;
|
|
209
|
+
red: string;
|
|
210
|
+
green: string;
|
|
211
|
+
brown: string;
|
|
212
|
+
blue: string;
|
|
213
|
+
purple: string;
|
|
214
|
+
darkGrey: string;
|
|
215
|
+
lightRed: string;
|
|
216
|
+
lightGreen: string;
|
|
217
|
+
yellow: string;
|
|
218
|
+
lightBlue: string;
|
|
219
|
+
magenta: string;
|
|
220
|
+
cyan: string;
|
|
221
|
+
white: string;
|
|
222
|
+
initial: string;
|
|
223
|
+
};
|
|
224
|
+
function log(...args: any[]): void;
|
|
225
|
+
function info(...args: any[]): void;
|
|
226
|
+
function warn(...args: any[]): void;
|
|
227
|
+
function error(...args: any[]): void;
|
|
228
|
+
function debug(...args: any[]): void;
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
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, Patch, Post, Put, ROUTE_METADATA_KEY, Request, RequestTimeoutException, ResponseException, RootInjector, Router, ServiceUnavailableException, TooManyRequestsException, type Type, UnauthorizedException, UpgradeRequiredException, VariantAlsoNegotiatesException, bootstrapApplication, getControllerMetadata, getGuardForController, getGuardForControllerAction, getInjectableMetadata, getModuleMetadata, getRouteMetadata };
|