@noxfly/noxus 1.1.1 → 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/src/app.ts CHANGED
@@ -13,12 +13,21 @@ import { Router } from "src/router";
13
13
  import { Logger } from "src/utils/logger";
14
14
  import { Type } from "src/utils/types";
15
15
 
16
+ /**
17
+ * The application service should implement this interface, as
18
+ * the NoxApp class instance will use it to notify the given service
19
+ * about application lifecycle events.
20
+ */
16
21
  export interface IApp {
17
22
  dispose(): Promise<void>;
18
23
  onReady(): Promise<void>;
19
24
  onActivated(): Promise<void>;
20
25
  }
21
26
 
27
+ /**
28
+ * NoxApp is the main application class that manages the application lifecycle,
29
+ * handles IPC communication, and integrates with the Router.
30
+ */
22
31
  @Injectable('singleton')
23
32
  export class NoxApp {
24
33
  private readonly messagePorts = new Map<number, Electron.MessageChannelMain>();
@@ -29,7 +38,9 @@ export class NoxApp {
29
38
  ) {}
30
39
 
31
40
  /**
32
- *
41
+ * Initializes the NoxApp instance.
42
+ * This method sets up the IPC communication, registers event listeners,
43
+ * and prepares the application for use.
33
44
  */
34
45
  public async init(): Promise<NoxApp> {
35
46
  ipcMain.on('gimme-my-port', this.giveTheRendererAPort.bind(this));
@@ -43,7 +54,10 @@ export class NoxApp {
43
54
  }
44
55
 
45
56
  /**
46
- *
57
+ * Handles the request from the renderer process.
58
+ * This method creates a Request object from the IPC event data,
59
+ * processes it through the Router, and sends the response back
60
+ * to the renderer process using the MessageChannel.
47
61
  */
48
62
  private giveTheRendererAPort(event: Electron.IpcMainInvokeEvent): void {
49
63
  const senderId = event.sender.id;
@@ -74,7 +88,6 @@ export class NoxApp {
74
88
  Logger.error(`No message channel found for sender ID: ${senderId}`);
75
89
  return;
76
90
  }
77
-
78
91
  try {
79
92
  const request = new Request(event, requestId, method, path, body);
80
93
  const response = await this.router.handle(request);
@@ -101,7 +114,14 @@ export class NoxApp {
101
114
  }
102
115
  }
103
116
 
104
- private shutdownChannel(channelSenderId: number, remove: boolean = true): void {
117
+ /**
118
+ * Shuts down the message channel for a specific sender ID.
119
+ * This method closes the IPC channel for the specified sender ID and
120
+ * removes it from the messagePorts map.
121
+ * @param channelSenderId - The ID of the sender channel to shut down.
122
+ * @param remove - Whether to remove the channel from the messagePorts map.
123
+ */
124
+ private shutdownChannel(channelSenderId: number): void {
105
125
  const channel = this.messagePorts.get(channelSenderId);
106
126
 
107
127
  if(!channel) {
@@ -117,11 +137,12 @@ export class NoxApp {
117
137
  }
118
138
 
119
139
  /**
120
- *
140
+ * Handles the application shutdown process.
141
+ * This method is called when all windows are closed, and it cleans up the message channels
121
142
  */
122
143
  private async onAllWindowsClosed(): Promise<void> {
123
144
  this.messagePorts.forEach((channel, senderId) => {
124
- this.shutdownChannel(senderId, false);
145
+ this.shutdownChannel(senderId);
125
146
  });
126
147
 
127
148
  this.messagePorts.clear();
@@ -136,12 +157,23 @@ export class NoxApp {
136
157
 
137
158
  // ---
138
159
 
139
-
160
+ /**
161
+ * Configures the NoxApp instance with the provided application class.
162
+ * This method allows you to set the application class that will handle lifecycle events.
163
+ * @param app - The application class to configure.
164
+ * @returns NoxApp instance for method chaining.
165
+ */
140
166
  public configure(app: Type<IApp>): NoxApp {
141
167
  this.app = inject(app);
142
168
  return this;
143
169
  }
144
170
 
171
+ /**
172
+ * Registers a middleware for the root of the application.
173
+ * This method allows you to define a middleware that will be applied to all requests
174
+ * @param middleware - The middleware class to register.
175
+ * @returns NoxApp instance for method chaining.
176
+ */
145
177
  public use(middleware: Type<IMiddleware>): NoxApp {
146
178
  this.router.defineRootMiddleware(middleware);
147
179
  return this;
@@ -149,6 +181,7 @@ export class NoxApp {
149
181
 
150
182
  /**
151
183
  * Should be called after the bootstrapApplication function is called.
184
+ * @returns NoxApp instance for method chaining.
152
185
  */
153
186
  public start(): NoxApp {
154
187
  this.app?.onReady();
package/src/bootstrap.ts CHANGED
@@ -11,7 +11,12 @@ import { inject } from "src/DI/app-injector";
11
11
  import { Type } from "src/utils/types";
12
12
 
13
13
  /**
14
- *
14
+ * Bootstraps the Noxus application.
15
+ * This function initializes the application by creating an instance of NoxApp,
16
+ * registering the root module, and starting the application.
17
+ * @param rootModule - The root module of the application, decorated with @Module.
18
+ * @return A promise that resolves to the NoxApp instance.
19
+ * @throws Error if the root module is not decorated with @Module, or if the electron process could not start.
15
20
  */
16
21
  export async function bootstrapApplication(rootModule: Type<any>): Promise<NoxApp> {
17
22
  if(!getModuleMetadata(rootModule)) {
@@ -8,11 +8,20 @@ import { getGuardForController, IGuard } from "src/decorators/guards.decorator";
8
8
  import { Injectable } from "src/decorators/injectable.decorator";
9
9
  import { Type } from "src/utils/types";
10
10
 
11
+ /**
12
+ * The configuration that waits a controller's decorator.
13
+ */
11
14
  export interface IControllerMetadata {
12
15
  path: string;
13
16
  guards: Type<IGuard>[];
14
17
  }
15
18
 
19
+ /**
20
+ * Controller decorator is used to define a controller in the application.
21
+ * It is a kind of node in the routing tree, that can contains routes and middlewares.
22
+ *
23
+ * @param path - The path for the controller.
24
+ */
16
25
  export function Controller(path: string): ClassDecorator {
17
26
  return (target) => {
18
27
  const data: IControllerMetadata = {
@@ -25,8 +34,14 @@ export function Controller(path: string): ClassDecorator {
25
34
  };
26
35
  }
27
36
 
28
- export const CONTROLLER_METADATA_KEY = Symbol('CONTROLLER_METADATA_KEY');
29
-
37
+ /**
38
+ * Gets the controller metadata for a given target class.
39
+ * This metadata includes the path and guards defined by the @Controller decorator.
40
+ * @param target - The target class to get the controller metadata from.
41
+ * @returns The controller metadata if it exists, otherwise undefined.
42
+ */
30
43
  export function getControllerMetadata(target: Type<unknown>): IControllerMetadata | undefined {
31
44
  return Reflect.getMetadata(CONTROLLER_METADATA_KEY, target);
32
- }
45
+ }
46
+
47
+ export const CONTROLLER_METADATA_KEY = Symbol('CONTROLLER_METADATA_KEY');
@@ -8,15 +8,23 @@ import { Request } from 'src/request';
8
8
  import { Logger } from 'src/utils/logger';
9
9
  import { MaybeAsync, Type } from 'src/utils/types';
10
10
 
11
+ /**
12
+ * IGuard interface defines a guard that can be used to protect routes.
13
+ * It has a `canActivate` method that takes a request and returns a MaybeAsync boolean.
14
+ * The `canActivate` method can return either a value or a Promise.
15
+ * Use it on a class that should be registered as a guard in the application.
16
+ * Guards can be used to protect routes or controller actions.
17
+ * For example, you can use guards to check if the user is authenticated or has the right permissions.
18
+ * You can use the `Authorize` decorator to register guards for a controller or a controller action.
19
+ * @see Authorize
20
+ */
11
21
  export interface IGuard {
12
22
  canActivate(request: Request): MaybeAsync<boolean>;
13
23
  }
14
24
 
15
- const authorizations = new Map<string, Type<IGuard>[]>();
16
-
17
25
  /**
18
- * Peut être utilisé pour protéger les routes d'un contrôleur.
19
- * Peut être utilisé sur une classe controleur, ou sur une méthode de contrôleur.
26
+ * Can be used to protect the routes of a controller.
27
+ * Can be used on a controller class or on a controller method.
20
28
  */
21
29
  export function Authorize(...guardClasses: Type<IGuard>[]): MethodDecorator & ClassDecorator {
22
30
  return (target: Function | object, propertyKey?: string | symbol) => {
@@ -44,13 +52,25 @@ export function Authorize(...guardClasses: Type<IGuard>[]): MethodDecorator & Cl
44
52
  };
45
53
  }
46
54
 
47
-
55
+ /**
56
+ * Gets the guards for a controller or a controller action.
57
+ * @param controllerName The name of the controller to get the guards for.
58
+ * @returns An array of guards for the controller.
59
+ */
48
60
  export function getGuardForController(controllerName: string): Type<IGuard>[] {
49
61
  const key = `${controllerName}`;
50
62
  return authorizations.get(key) ?? [];
51
63
  }
52
64
 
65
+ /**
66
+ * Gets the guards for a controller action.
67
+ * @param controllerName The name of the controller to get the guards for.
68
+ * @param actionName The name of the action to get the guards for.
69
+ * @returns An array of guards for the controller action.
70
+ */
53
71
  export function getGuardForControllerAction(controllerName: string, actionName: string): Type<IGuard>[] {
54
72
  const key = `${controllerName}.${actionName}`;
55
73
  return authorizations.get(key) ?? [];
56
74
  }
75
+
76
+ const authorizations = new Map<string, Type<IGuard>[]>();
@@ -8,6 +8,13 @@ import { Lifetime } from "src/DI/app-injector";
8
8
  import { InjectorExplorer } from "src/DI/injector-explorer";
9
9
  import { Type } from "src/utils/types";
10
10
 
11
+ /**
12
+ * The Injectable decorator marks a class as injectable.
13
+ * It allows the class to be registered in the dependency injection system.
14
+ * A class decorated with @Injectable can be injected into other classes
15
+ * either from the constructor of the class that needs it of from the `inject` function.
16
+ * @param lifetime - The lifetime of the injectable. Can be 'singleton', 'scope', or 'transient'.
17
+ */
11
18
  export function Injectable(lifetime: Lifetime = 'scope'): ClassDecorator {
12
19
  return (target) => {
13
20
  if(typeof target !== 'function' || !target.prototype) {
@@ -19,8 +26,14 @@ export function Injectable(lifetime: Lifetime = 'scope'): ClassDecorator {
19
26
  };
20
27
  }
21
28
 
22
- export const INJECTABLE_METADATA_KEY = Symbol('INJECTABLE_METADATA_KEY');
23
-
29
+ /**
30
+ * Gets the injectable metadata for a given target class.
31
+ * This metadata includes the lifetime of the injectable defined by the @Injectable decorator.
32
+ * @param target - The target class to get the injectable metadata from.
33
+ * @returns The lifetime of the injectable if it exists, otherwise undefined.
34
+ */
24
35
  export function getInjectableMetadata(target: Type<unknown>): Lifetime | undefined {
25
36
  return Reflect.getMetadata(INJECTABLE_METADATA_KEY, target);
26
- }
37
+ }
38
+
39
+ export const INJECTABLE_METADATA_KEY = Symbol('INJECTABLE_METADATA_KEY');
@@ -7,6 +7,30 @@
7
7
  import { getGuardForControllerAction, IGuard } from "src/decorators/guards.decorator";
8
8
  import { Type } from "src/utils/types";
9
9
 
10
+ /**
11
+ * IRouteMetadata interface defines the metadata for a route.
12
+ * It includes the HTTP method, path, handler name, and guards associated with the route.
13
+ * This metadata is used to register the route in the application.
14
+ * This is the configuration that waits a route's decorator.
15
+ */
16
+ export interface IRouteMetadata {
17
+ method: HttpMethod;
18
+ path: string;
19
+ handler: string;
20
+ guards: Type<IGuard>[];
21
+ }
22
+
23
+ /**
24
+ * The different HTTP methods that can be used in the application.
25
+ */
26
+ export type HttpMethod = 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE';
27
+
28
+ /**
29
+ * The configuration that waits a route's decorator.
30
+ * It contains the HTTP method, path, handler, and guards for the route.
31
+ * @param verb The HTTP method for the route.
32
+ * @returns A method decorator that registers the route with the specified HTTP method.
33
+ */
10
34
  function createRouteDecorator(verb: HttpMethod): (path: string) => MethodDecorator {
11
35
  return (path: string): MethodDecorator => {
12
36
  return (target, propertyKey) => {
@@ -26,23 +50,53 @@ function createRouteDecorator(verb: HttpMethod): (path: string) => MethodDecorat
26
50
  };
27
51
  }
28
52
 
29
- export interface IRouteMetadata {
30
- method: HttpMethod;
31
- path: string;
32
- handler: string;
33
- guards: Type<IGuard>[];
53
+ /**
54
+ * Gets the route metadata for a given target class.
55
+ * This metadata includes the HTTP method, path, handler, and guards defined by the route decorators.
56
+ * @see Get
57
+ * @see Post
58
+ * @see Put
59
+ * @see Patch
60
+ * @see Delete
61
+ * @param target The target class to get the route metadata from.
62
+ * @returns An array of route metadata if it exists, otherwise an empty array.
63
+ */
64
+ export function getRouteMetadata(target: Type<unknown>): IRouteMetadata[] {
65
+ return Reflect.getMetadata(ROUTE_METADATA_KEY, target) || [];
34
66
  }
35
67
 
36
- export type HttpMethod = 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE';
37
-
68
+ /**
69
+ * Route decorator that defines a leaf in the routing tree, attaching it to a controller method
70
+ * that will be called when the route is matched.
71
+ * This route will have to be called with the GET method.
72
+ */
38
73
  export const Get = createRouteDecorator('GET');
74
+
75
+ /**
76
+ * Route decorator that defines a leaf in the routing tree, attaching it to a controller method
77
+ * that will be called when the route is matched.
78
+ * This route will have to be called with the POST method.
79
+ */
39
80
  export const Post = createRouteDecorator('POST');
81
+
82
+ /**
83
+ * Route decorator that defines a leaf in the routing tree, attaching it to a controller method
84
+ * that will be called when the route is matched.
85
+ * This route will have to be called with the PUT method.
86
+ */
40
87
  export const Put = createRouteDecorator('PUT');
88
+ /**
89
+ * Route decorator that defines a leaf in the routing tree, attaching it to a controller method
90
+ * that will be called when the route is matched.
91
+ * This route will have to be called with the PATCH method.
92
+ */
41
93
  export const Patch = createRouteDecorator('PATCH');
94
+
95
+ /**
96
+ * Route decorator that defines a leaf in the routing tree, attaching it to a controller method
97
+ * that will be called when the route is matched.
98
+ * This route will have to be called with the DELETE method.
99
+ */
42
100
  export const Delete = createRouteDecorator('DELETE');
43
101
 
44
102
  export const ROUTE_METADATA_KEY = Symbol('ROUTE_METADATA_KEY');
45
-
46
- export function getRouteMetadata(target: Type<unknown>): IRouteMetadata[] {
47
- return Reflect.getMetadata(ROUTE_METADATA_KEY, target) || [];
48
- }
@@ -8,15 +8,28 @@ import { IResponse, Request } from "src/request";
8
8
  import { Logger } from "src/utils/logger";
9
9
  import { MaybeAsync, Type } from "src/utils/types";
10
10
 
11
-
11
+ /**
12
+ * NextFunction is a function that is called to continue the middleware chain.
13
+ * It returns an Promise that emits when the next middleware is done.
14
+ */
12
15
  export type NextFunction = () => Promise<void>;
13
16
 
17
+ /**
18
+ * IMiddleware interface defines a middleware that can be used in the application.
19
+ * It has an `invoke` method that takes a request, a response, and a next function.
20
+ * The `invoke` method can return a MaybeAsync, which means it can return either a value or a Promise.
21
+ *
22
+ * Use it on a class that should be registered as a middleware in the application.
23
+ */
14
24
  export interface IMiddleware {
15
25
  invoke(request: Request, response: IResponse, next: NextFunction): MaybeAsync<void>;
16
26
  }
17
27
 
18
- const middlewares = new Map<string, Type<IMiddleware>[]>();
19
-
28
+ /**
29
+ * UseMiddlewares decorator can be used to register middlewares for a controller or a controller action.
30
+ *
31
+ * @param mdlw - The middlewares list to register for the controller or the controller action.
32
+ */
20
33
  export function UseMiddlewares(mdlw: Type<IMiddleware>[]): ClassDecorator & MethodDecorator {
21
34
  return (target: Function | object, propertyKey?: string | symbol) => {
22
35
  let key: string;
@@ -43,12 +56,29 @@ export function UseMiddlewares(mdlw: Type<IMiddleware>[]): ClassDecorator & Meth
43
56
  };
44
57
  }
45
58
 
59
+ /**
60
+ * Gets the middlewares for a controller or a controller action.
61
+ * This function retrieves the middlewares registered with the UseMiddlewares decorator.
62
+ * It returns an array of middleware classes that can be used to process requests for the specified controller.
63
+ * @param controllerName The name of the controller to get the middlewares for.
64
+ * @returns An array of middlewares for the controller.
65
+ */
46
66
  export function getMiddlewaresForController(controllerName: string): Type<IMiddleware>[] {
47
67
  const key = `${controllerName}`;
48
68
  return middlewares.get(key) ?? [];
49
69
  }
50
70
 
71
+ /**
72
+ * Gets the middlewares for a controller action.
73
+ * This function retrieves the middlewares registered with the UseMiddlewares decorator for a specific action in a controller.
74
+ * It returns an array of middleware classes that can be used to process requests for the specified controller action.
75
+ * @param controllerName The name of the controller to get the middlewares for.
76
+ * @param actionName The name of the action to get the middlewares for.
77
+ * @returns An array of middlewares for the controller action.
78
+ */
51
79
  export function getMiddlewaresForControllerAction(controllerName: string, actionName: string): Type<IMiddleware>[] {
52
80
  const key = `${controllerName}.${actionName}`;
53
81
  return middlewares.get(key) ?? [];
54
- }
82
+ }
83
+
84
+ const middlewares = new Map<string, Type<IMiddleware>[]>();
@@ -8,13 +8,26 @@ import { CONTROLLER_METADATA_KEY } from "src/decorators/controller.decorator";
8
8
  import { Injectable, INJECTABLE_METADATA_KEY } from "src/decorators/injectable.decorator";
9
9
  import { Type } from "src/utils/types";
10
10
 
11
+ export interface IModuleMetadata {
12
+ imports?: Type<unknown>[];
13
+ exports?: Type<unknown>[];
14
+ providers?: Type<unknown>[];
15
+ controllers?: Type<unknown>[];
16
+ }
17
+
18
+ /**
19
+ * Module decorator is used to define a module in the application.
20
+ * It is a kind of node in the routing tree, that can contains controllers, services, and other modules.
21
+ *
22
+ * @param metadata - The metadata for the module.
23
+ */
11
24
  export function Module(metadata: IModuleMetadata): ClassDecorator {
12
25
  return (target: Function) => {
13
26
  // Validate imports and exports: must be decorated with @Module
14
27
  const checkModule = (arr?: Type<unknown>[], arrName?: string): void => {
15
28
  if(!arr)
16
29
  return;
17
-
30
+
18
31
  for(const clazz of arr) {
19
32
  if(!Reflect.getMetadata(MODULE_METADATA_KEY, clazz)) {
20
33
  throw new Error(`Class ${clazz.name} in ${arrName} must be decorated with @Module`);
@@ -55,15 +68,8 @@ export function Module(metadata: IModuleMetadata): ClassDecorator {
55
68
  };
56
69
  }
57
70
 
58
- export const MODULE_METADATA_KEY = Symbol('MODULE_METADATA_KEY');
59
-
60
- export interface IModuleMetadata {
61
- imports?: Type<unknown>[];
62
- exports?: Type<unknown>[];
63
- providers?: Type<unknown>[];
64
- controllers?: Type<unknown>[];
65
- }
66
-
67
71
  export function getModuleMetadata(target: Function): IModuleMetadata | undefined {
68
72
  return Reflect.getMetadata(MODULE_METADATA_KEY, target);
69
- }
73
+ }
74
+
75
+ export const MODULE_METADATA_KEY = Symbol('MODULE_METADATA_KEY');
package/src/request.ts CHANGED
@@ -8,6 +8,11 @@ import 'reflect-metadata';
8
8
  import { HttpMethod } from 'src/decorators/method.decorator';
9
9
  import { AppInjector, RootInjector } from 'src/DI/app-injector';
10
10
 
11
+ /**
12
+ * The Request class represents an HTTP request in the Noxus framework.
13
+ * It encapsulates the request data, including the event, ID, method, path, and body.
14
+ * It also provides a context for dependency injection through the AppInjector.
15
+ */
11
16
  export class Request {
12
17
  public readonly context: AppInjector = RootInjector.createScope();
13
18
 
@@ -24,6 +29,11 @@ export class Request {
24
29
  }
25
30
  }
26
31
 
32
+ /**
33
+ * The IRequest interface defines the structure of a request object.
34
+ * It includes properties for the sender ID, request ID, path, method, and an optional body.
35
+ * This interface is used to standardize the request data across the application.
36
+ */
27
37
  export interface IRequest<T = any> {
28
38
  senderId: number;
29
39
  requestId: string;
@@ -32,6 +42,10 @@ export interface IRequest<T = any> {
32
42
  body?: T;
33
43
  }
34
44
 
45
+ /**
46
+ * Creates a Request object from the IPC event data.
47
+ * This function extracts the necessary information from the IPC event and constructs a Request instance.
48
+ */
35
49
  export interface IResponse<T = any> {
36
50
  requestId: string;
37
51
  status: number;