@noxfly/noxus 2.5.0 → 3.0.0-dev.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 +405 -340
- package/dist/app-injector-Bz3Upc0y.d.mts +125 -0
- package/dist/app-injector-Bz3Upc0y.d.ts +125 -0
- package/dist/child.d.mts +157 -23
- package/dist/child.d.ts +157 -23
- package/dist/child.js +1111 -1341
- package/dist/child.mjs +1086 -1294
- package/dist/main.d.mts +720 -284
- package/dist/main.d.ts +720 -284
- package/dist/main.js +1471 -1650
- package/dist/main.mjs +1409 -1559
- package/dist/preload.d.mts +28 -0
- package/dist/preload.d.ts +28 -0
- package/dist/preload.js +95 -0
- package/dist/preload.mjs +70 -0
- package/dist/renderer.d.mts +159 -22
- package/dist/renderer.d.ts +159 -22
- package/dist/renderer.js +104 -177
- package/dist/renderer.mjs +100 -172
- package/dist/request-BlTtiHbi.d.ts +112 -0
- package/dist/request-qJ9EiDZc.d.mts +112 -0
- package/package.json +24 -19
- package/src/DI/app-injector.ts +95 -106
- package/src/DI/injector-explorer.ts +93 -119
- package/src/DI/token.ts +53 -0
- package/src/decorators/controller.decorator.ts +38 -27
- package/src/decorators/guards.decorator.ts +5 -64
- package/src/decorators/injectable.decorator.ts +68 -15
- package/src/decorators/method.decorator.ts +40 -81
- package/src/decorators/middleware.decorator.ts +5 -72
- package/src/index.ts +4 -5
- package/src/internal/app.ts +217 -0
- package/src/internal/bootstrap.ts +108 -0
- package/src/{preload-bridge.ts → internal/preload-bridge.ts} +1 -1
- package/src/{renderer-client.ts → internal/renderer-client.ts} +2 -2
- package/src/{renderer-events.ts → internal/renderer-events.ts} +1 -1
- package/src/{request.ts → internal/request.ts} +3 -3
- package/src/internal/router.ts +353 -0
- package/src/internal/routes.ts +78 -0
- package/src/{socket.ts → internal/socket.ts} +4 -4
- package/src/main.ts +10 -14
- package/src/non-electron-process.ts +1 -2
- package/src/preload.ts +10 -0
- package/src/renderer.ts +13 -0
- package/src/window/window-manager.ts +255 -0
- package/tsconfig.json +5 -10
- package/tsup.config.ts +29 -13
- package/dist/app-injector-B3MvgV3k.d.mts +0 -95
- package/dist/app-injector-B3MvgV3k.d.ts +0 -95
- package/dist/request-CdpZ9qZL.d.ts +0 -167
- package/dist/request-Dx_5Prte.d.mts +0 -167
- package/src/app.ts +0 -244
- package/src/bootstrap.ts +0 -84
- package/src/decorators/inject.decorator.ts +0 -24
- package/src/decorators/injectable.metadata.ts +0 -15
- package/src/decorators/module.decorator.ts +0 -75
- package/src/router.ts +0 -594
- /package/src/{exceptions.ts → internal/exceptions.ts} +0 -0
|
@@ -1,167 +0,0 @@
|
|
|
1
|
-
import { M as MaybeAsync, T as Type, A as AppInjector } from './app-injector-B3MvgV3k.js';
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* @copyright 2025 NoxFly
|
|
5
|
-
* @license MIT
|
|
6
|
-
* @author NoxFly
|
|
7
|
-
*/
|
|
8
|
-
|
|
9
|
-
/**
|
|
10
|
-
* IGuard interface defines a guard that can be used to protect routes.
|
|
11
|
-
* It has a `canActivate` method that takes a request and returns a MaybeAsync boolean.
|
|
12
|
-
* The `canActivate` method can return either a value or a Promise.
|
|
13
|
-
* Use it on a class that should be registered as a guard in the application.
|
|
14
|
-
* Guards can be used to protect routes or controller actions.
|
|
15
|
-
* For example, you can use guards to check if the user is authenticated or has the right permissions.
|
|
16
|
-
* You can use the `Authorize` decorator to register guards for a controller or a controller action.
|
|
17
|
-
* @see Authorize
|
|
18
|
-
*/
|
|
19
|
-
interface IGuard {
|
|
20
|
-
canActivate(request: Request): MaybeAsync<boolean>;
|
|
21
|
-
}
|
|
22
|
-
/**
|
|
23
|
-
* Can be used to protect the routes of a controller.
|
|
24
|
-
* Can be used on a controller class or on a controller method.
|
|
25
|
-
*/
|
|
26
|
-
declare function Authorize(...guardClasses: Type<IGuard>[]): MethodDecorator & ClassDecorator;
|
|
27
|
-
/**
|
|
28
|
-
* Gets the guards for a controller or a controller action.
|
|
29
|
-
* @param controllerName The name of the controller to get the guards for.
|
|
30
|
-
* @returns An array of guards for the controller.
|
|
31
|
-
*/
|
|
32
|
-
declare function getGuardForController(controllerName: string): Type<IGuard>[];
|
|
33
|
-
/**
|
|
34
|
-
* Gets the guards for a controller action.
|
|
35
|
-
* @param controllerName The name of the controller to get the guards for.
|
|
36
|
-
* @param actionName The name of the action to get the guards for.
|
|
37
|
-
* @returns An array of guards for the controller action.
|
|
38
|
-
*/
|
|
39
|
-
declare function getGuardForControllerAction(controllerName: string, actionName: string): Type<IGuard>[];
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
/**
|
|
43
|
-
* IRouteMetadata interface defines the metadata for a route.
|
|
44
|
-
* It includes the HTTP method, path, handler name, and guards associated with the route.
|
|
45
|
-
* This metadata is used to register the route in the application.
|
|
46
|
-
* This is the configuration that waits a route's decorator.
|
|
47
|
-
*/
|
|
48
|
-
interface IRouteMetadata {
|
|
49
|
-
method: HttpMethod;
|
|
50
|
-
path: string;
|
|
51
|
-
handler: string;
|
|
52
|
-
guards: Type<IGuard>[];
|
|
53
|
-
}
|
|
54
|
-
/**
|
|
55
|
-
* The different HTTP methods that can be used in the application.
|
|
56
|
-
*/
|
|
57
|
-
type HttpMethod = 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE' | 'BATCH';
|
|
58
|
-
/**
|
|
59
|
-
* Atomic HTTP verbs supported by controllers. BATCH is handled at the router level only.
|
|
60
|
-
*/
|
|
61
|
-
type AtomicHttpMethod = Exclude<HttpMethod, 'BATCH'>;
|
|
62
|
-
/**
|
|
63
|
-
* Gets the route metadata for a given target class.
|
|
64
|
-
* This metadata includes the HTTP method, path, handler, and guards defined by the route decorators.
|
|
65
|
-
* @see Get
|
|
66
|
-
* @see Post
|
|
67
|
-
* @see Put
|
|
68
|
-
* @see Patch
|
|
69
|
-
* @see Delete
|
|
70
|
-
* @param target The target class to get the route metadata from.
|
|
71
|
-
* @returns An array of route metadata if it exists, otherwise an empty array.
|
|
72
|
-
*/
|
|
73
|
-
declare function getRouteMetadata(target: Type<unknown>): IRouteMetadata[];
|
|
74
|
-
/**
|
|
75
|
-
* Route decorator that defines a leaf in the routing tree, attaching it to a controller method
|
|
76
|
-
* that will be called when the route is matched.
|
|
77
|
-
* This route will have to be called with the GET method.
|
|
78
|
-
*/
|
|
79
|
-
declare const Get: (path: string) => MethodDecorator;
|
|
80
|
-
/**
|
|
81
|
-
* Route decorator that defines a leaf in the routing tree, attaching it to a controller method
|
|
82
|
-
* that will be called when the route is matched.
|
|
83
|
-
* This route will have to be called with the POST method.
|
|
84
|
-
*/
|
|
85
|
-
declare const Post: (path: string) => MethodDecorator;
|
|
86
|
-
/**
|
|
87
|
-
* Route decorator that defines a leaf in the routing tree, attaching it to a controller method
|
|
88
|
-
* that will be called when the route is matched.
|
|
89
|
-
* This route will have to be called with the PUT method.
|
|
90
|
-
*/
|
|
91
|
-
declare const Put: (path: string) => MethodDecorator;
|
|
92
|
-
/**
|
|
93
|
-
* Route decorator that defines a leaf in the routing tree, attaching it to a controller method
|
|
94
|
-
* that will be called when the route is matched.
|
|
95
|
-
* This route will have to be called with the PATCH method.
|
|
96
|
-
*/
|
|
97
|
-
declare const Patch: (path: string) => MethodDecorator;
|
|
98
|
-
/**
|
|
99
|
-
* Route decorator that defines a leaf in the routing tree, attaching it to a controller method
|
|
100
|
-
* that will be called when the route is matched.
|
|
101
|
-
* This route will have to be called with the DELETE method.
|
|
102
|
-
*/
|
|
103
|
-
declare const Delete: (path: string) => MethodDecorator;
|
|
104
|
-
declare const ROUTE_METADATA_KEY: unique symbol;
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
/**
|
|
108
|
-
* The Request class represents an HTTP request in the Noxus framework.
|
|
109
|
-
* It encapsulates the request data, including the event, ID, method, path, and body.
|
|
110
|
-
* It also provides a context for dependency injection through the AppInjector.
|
|
111
|
-
*/
|
|
112
|
-
declare class Request {
|
|
113
|
-
readonly event: Electron.MessageEvent;
|
|
114
|
-
readonly senderId: number;
|
|
115
|
-
readonly id: string;
|
|
116
|
-
readonly method: HttpMethod;
|
|
117
|
-
readonly path: string;
|
|
118
|
-
readonly body: any;
|
|
119
|
-
readonly context: AppInjector;
|
|
120
|
-
readonly params: Record<string, string>;
|
|
121
|
-
constructor(event: Electron.MessageEvent, senderId: number, id: string, method: HttpMethod, path: string, body: any);
|
|
122
|
-
}
|
|
123
|
-
/**
|
|
124
|
-
* The IRequest interface defines the structure of a request object.
|
|
125
|
-
* It includes properties for the sender ID, request ID, path, method, and an optional body.
|
|
126
|
-
* This interface is used to standardize the request data across the application.
|
|
127
|
-
*/
|
|
128
|
-
interface IRequest<TBody = unknown> {
|
|
129
|
-
senderId: number;
|
|
130
|
-
requestId: string;
|
|
131
|
-
path: string;
|
|
132
|
-
method: HttpMethod;
|
|
133
|
-
body?: TBody;
|
|
134
|
-
}
|
|
135
|
-
interface IBatchRequestItem<TBody = unknown> {
|
|
136
|
-
requestId?: string;
|
|
137
|
-
path: string;
|
|
138
|
-
method: AtomicHttpMethod;
|
|
139
|
-
body?: TBody;
|
|
140
|
-
}
|
|
141
|
-
interface IBatchRequestPayload {
|
|
142
|
-
requests: IBatchRequestItem[];
|
|
143
|
-
}
|
|
144
|
-
/**
|
|
145
|
-
* Creates a Request object from the IPC event data.
|
|
146
|
-
* This function extracts the necessary information from the IPC event and constructs a Request instance.
|
|
147
|
-
*/
|
|
148
|
-
interface IResponse<TBody = unknown> {
|
|
149
|
-
requestId: string;
|
|
150
|
-
status: number;
|
|
151
|
-
body?: TBody;
|
|
152
|
-
error?: string;
|
|
153
|
-
stack?: string;
|
|
154
|
-
}
|
|
155
|
-
interface IBatchResponsePayload {
|
|
156
|
-
responses: IResponse[];
|
|
157
|
-
}
|
|
158
|
-
declare const RENDERER_EVENT_TYPE = "noxus:event";
|
|
159
|
-
interface IRendererEventMessage<TPayload = unknown> {
|
|
160
|
-
type: typeof RENDERER_EVENT_TYPE;
|
|
161
|
-
event: string;
|
|
162
|
-
payload?: TPayload;
|
|
163
|
-
}
|
|
164
|
-
declare function createRendererEventMessage<TPayload = unknown>(event: string, payload?: TPayload): IRendererEventMessage<TPayload>;
|
|
165
|
-
declare function isRendererEventMessage(value: unknown): value is IRendererEventMessage;
|
|
166
|
-
|
|
167
|
-
export { type AtomicHttpMethod as A, Delete as D, Get as G, type HttpMethod as H, type IRendererEventMessage as I, Post as P, Request as R, type IResponse as a, type IRequest as b, type IBatchRequestItem as c, type IBatchResponsePayload as d, type IBatchRequestPayload as e, RENDERER_EVENT_TYPE as f, createRendererEventMessage as g, type IGuard as h, isRendererEventMessage as i, Authorize as j, getGuardForController as k, getGuardForControllerAction as l, type IRouteMetadata as m, getRouteMetadata as n, Put as o, Patch as p, ROUTE_METADATA_KEY as q };
|
|
@@ -1,167 +0,0 @@
|
|
|
1
|
-
import { M as MaybeAsync, T as Type, A as AppInjector } from './app-injector-B3MvgV3k.mjs';
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* @copyright 2025 NoxFly
|
|
5
|
-
* @license MIT
|
|
6
|
-
* @author NoxFly
|
|
7
|
-
*/
|
|
8
|
-
|
|
9
|
-
/**
|
|
10
|
-
* IGuard interface defines a guard that can be used to protect routes.
|
|
11
|
-
* It has a `canActivate` method that takes a request and returns a MaybeAsync boolean.
|
|
12
|
-
* The `canActivate` method can return either a value or a Promise.
|
|
13
|
-
* Use it on a class that should be registered as a guard in the application.
|
|
14
|
-
* Guards can be used to protect routes or controller actions.
|
|
15
|
-
* For example, you can use guards to check if the user is authenticated or has the right permissions.
|
|
16
|
-
* You can use the `Authorize` decorator to register guards for a controller or a controller action.
|
|
17
|
-
* @see Authorize
|
|
18
|
-
*/
|
|
19
|
-
interface IGuard {
|
|
20
|
-
canActivate(request: Request): MaybeAsync<boolean>;
|
|
21
|
-
}
|
|
22
|
-
/**
|
|
23
|
-
* Can be used to protect the routes of a controller.
|
|
24
|
-
* Can be used on a controller class or on a controller method.
|
|
25
|
-
*/
|
|
26
|
-
declare function Authorize(...guardClasses: Type<IGuard>[]): MethodDecorator & ClassDecorator;
|
|
27
|
-
/**
|
|
28
|
-
* Gets the guards for a controller or a controller action.
|
|
29
|
-
* @param controllerName The name of the controller to get the guards for.
|
|
30
|
-
* @returns An array of guards for the controller.
|
|
31
|
-
*/
|
|
32
|
-
declare function getGuardForController(controllerName: string): Type<IGuard>[];
|
|
33
|
-
/**
|
|
34
|
-
* Gets the guards for a controller action.
|
|
35
|
-
* @param controllerName The name of the controller to get the guards for.
|
|
36
|
-
* @param actionName The name of the action to get the guards for.
|
|
37
|
-
* @returns An array of guards for the controller action.
|
|
38
|
-
*/
|
|
39
|
-
declare function getGuardForControllerAction(controllerName: string, actionName: string): Type<IGuard>[];
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
/**
|
|
43
|
-
* IRouteMetadata interface defines the metadata for a route.
|
|
44
|
-
* It includes the HTTP method, path, handler name, and guards associated with the route.
|
|
45
|
-
* This metadata is used to register the route in the application.
|
|
46
|
-
* This is the configuration that waits a route's decorator.
|
|
47
|
-
*/
|
|
48
|
-
interface IRouteMetadata {
|
|
49
|
-
method: HttpMethod;
|
|
50
|
-
path: string;
|
|
51
|
-
handler: string;
|
|
52
|
-
guards: Type<IGuard>[];
|
|
53
|
-
}
|
|
54
|
-
/**
|
|
55
|
-
* The different HTTP methods that can be used in the application.
|
|
56
|
-
*/
|
|
57
|
-
type HttpMethod = 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE' | 'BATCH';
|
|
58
|
-
/**
|
|
59
|
-
* Atomic HTTP verbs supported by controllers. BATCH is handled at the router level only.
|
|
60
|
-
*/
|
|
61
|
-
type AtomicHttpMethod = Exclude<HttpMethod, 'BATCH'>;
|
|
62
|
-
/**
|
|
63
|
-
* Gets the route metadata for a given target class.
|
|
64
|
-
* This metadata includes the HTTP method, path, handler, and guards defined by the route decorators.
|
|
65
|
-
* @see Get
|
|
66
|
-
* @see Post
|
|
67
|
-
* @see Put
|
|
68
|
-
* @see Patch
|
|
69
|
-
* @see Delete
|
|
70
|
-
* @param target The target class to get the route metadata from.
|
|
71
|
-
* @returns An array of route metadata if it exists, otherwise an empty array.
|
|
72
|
-
*/
|
|
73
|
-
declare function getRouteMetadata(target: Type<unknown>): IRouteMetadata[];
|
|
74
|
-
/**
|
|
75
|
-
* Route decorator that defines a leaf in the routing tree, attaching it to a controller method
|
|
76
|
-
* that will be called when the route is matched.
|
|
77
|
-
* This route will have to be called with the GET method.
|
|
78
|
-
*/
|
|
79
|
-
declare const Get: (path: string) => MethodDecorator;
|
|
80
|
-
/**
|
|
81
|
-
* Route decorator that defines a leaf in the routing tree, attaching it to a controller method
|
|
82
|
-
* that will be called when the route is matched.
|
|
83
|
-
* This route will have to be called with the POST method.
|
|
84
|
-
*/
|
|
85
|
-
declare const Post: (path: string) => MethodDecorator;
|
|
86
|
-
/**
|
|
87
|
-
* Route decorator that defines a leaf in the routing tree, attaching it to a controller method
|
|
88
|
-
* that will be called when the route is matched.
|
|
89
|
-
* This route will have to be called with the PUT method.
|
|
90
|
-
*/
|
|
91
|
-
declare const Put: (path: string) => MethodDecorator;
|
|
92
|
-
/**
|
|
93
|
-
* Route decorator that defines a leaf in the routing tree, attaching it to a controller method
|
|
94
|
-
* that will be called when the route is matched.
|
|
95
|
-
* This route will have to be called with the PATCH method.
|
|
96
|
-
*/
|
|
97
|
-
declare const Patch: (path: string) => MethodDecorator;
|
|
98
|
-
/**
|
|
99
|
-
* Route decorator that defines a leaf in the routing tree, attaching it to a controller method
|
|
100
|
-
* that will be called when the route is matched.
|
|
101
|
-
* This route will have to be called with the DELETE method.
|
|
102
|
-
*/
|
|
103
|
-
declare const Delete: (path: string) => MethodDecorator;
|
|
104
|
-
declare const ROUTE_METADATA_KEY: unique symbol;
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
/**
|
|
108
|
-
* The Request class represents an HTTP request in the Noxus framework.
|
|
109
|
-
* It encapsulates the request data, including the event, ID, method, path, and body.
|
|
110
|
-
* It also provides a context for dependency injection through the AppInjector.
|
|
111
|
-
*/
|
|
112
|
-
declare class Request {
|
|
113
|
-
readonly event: Electron.MessageEvent;
|
|
114
|
-
readonly senderId: number;
|
|
115
|
-
readonly id: string;
|
|
116
|
-
readonly method: HttpMethod;
|
|
117
|
-
readonly path: string;
|
|
118
|
-
readonly body: any;
|
|
119
|
-
readonly context: AppInjector;
|
|
120
|
-
readonly params: Record<string, string>;
|
|
121
|
-
constructor(event: Electron.MessageEvent, senderId: number, id: string, method: HttpMethod, path: string, body: any);
|
|
122
|
-
}
|
|
123
|
-
/**
|
|
124
|
-
* The IRequest interface defines the structure of a request object.
|
|
125
|
-
* It includes properties for the sender ID, request ID, path, method, and an optional body.
|
|
126
|
-
* This interface is used to standardize the request data across the application.
|
|
127
|
-
*/
|
|
128
|
-
interface IRequest<TBody = unknown> {
|
|
129
|
-
senderId: number;
|
|
130
|
-
requestId: string;
|
|
131
|
-
path: string;
|
|
132
|
-
method: HttpMethod;
|
|
133
|
-
body?: TBody;
|
|
134
|
-
}
|
|
135
|
-
interface IBatchRequestItem<TBody = unknown> {
|
|
136
|
-
requestId?: string;
|
|
137
|
-
path: string;
|
|
138
|
-
method: AtomicHttpMethod;
|
|
139
|
-
body?: TBody;
|
|
140
|
-
}
|
|
141
|
-
interface IBatchRequestPayload {
|
|
142
|
-
requests: IBatchRequestItem[];
|
|
143
|
-
}
|
|
144
|
-
/**
|
|
145
|
-
* Creates a Request object from the IPC event data.
|
|
146
|
-
* This function extracts the necessary information from the IPC event and constructs a Request instance.
|
|
147
|
-
*/
|
|
148
|
-
interface IResponse<TBody = unknown> {
|
|
149
|
-
requestId: string;
|
|
150
|
-
status: number;
|
|
151
|
-
body?: TBody;
|
|
152
|
-
error?: string;
|
|
153
|
-
stack?: string;
|
|
154
|
-
}
|
|
155
|
-
interface IBatchResponsePayload {
|
|
156
|
-
responses: IResponse[];
|
|
157
|
-
}
|
|
158
|
-
declare const RENDERER_EVENT_TYPE = "noxus:event";
|
|
159
|
-
interface IRendererEventMessage<TPayload = unknown> {
|
|
160
|
-
type: typeof RENDERER_EVENT_TYPE;
|
|
161
|
-
event: string;
|
|
162
|
-
payload?: TPayload;
|
|
163
|
-
}
|
|
164
|
-
declare function createRendererEventMessage<TPayload = unknown>(event: string, payload?: TPayload): IRendererEventMessage<TPayload>;
|
|
165
|
-
declare function isRendererEventMessage(value: unknown): value is IRendererEventMessage;
|
|
166
|
-
|
|
167
|
-
export { type AtomicHttpMethod as A, Delete as D, Get as G, type HttpMethod as H, type IRendererEventMessage as I, Post as P, Request as R, type IResponse as a, type IRequest as b, type IBatchRequestItem as c, type IBatchResponsePayload as d, type IBatchRequestPayload as e, RENDERER_EVENT_TYPE as f, createRendererEventMessage as g, type IGuard as h, isRendererEventMessage as i, Authorize as j, getGuardForController as k, getGuardForControllerAction as l, type IRouteMetadata as m, getRouteMetadata as n, Put as o, Patch as p, ROUTE_METADATA_KEY as q };
|
package/src/app.ts
DELETED
|
@@ -1,244 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @copyright 2025 NoxFly
|
|
3
|
-
* @license MIT
|
|
4
|
-
* @author NoxFly
|
|
5
|
-
*/
|
|
6
|
-
|
|
7
|
-
import { app, BrowserWindow, ipcMain, MessageChannelMain } from "electron/main";
|
|
8
|
-
import { Injectable } from "src/decorators/injectable.decorator";
|
|
9
|
-
import { IMiddleware } from "src/decorators/middleware.decorator";
|
|
10
|
-
import { inject } from "src/DI/app-injector";
|
|
11
|
-
import { InjectorExplorer } from "src/DI/injector-explorer";
|
|
12
|
-
import { IRequest, IResponse, Request } from "src/request";
|
|
13
|
-
import { NoxSocket } from "src/socket";
|
|
14
|
-
import { Router } from "src/router";
|
|
15
|
-
import { Logger } from "src/utils/logger";
|
|
16
|
-
import { Type } from "src/utils/types";
|
|
17
|
-
|
|
18
|
-
/**
|
|
19
|
-
* The application service should implement this interface, as
|
|
20
|
-
* the NoxApp class instance will use it to notify the given service
|
|
21
|
-
* about application lifecycle events.
|
|
22
|
-
*/
|
|
23
|
-
export interface IApp {
|
|
24
|
-
dispose(): Promise<void>;
|
|
25
|
-
onReady(mainWindow?: BrowserWindow): Promise<void>;
|
|
26
|
-
onActivated(): Promise<void>;
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
/**
|
|
30
|
-
* NoxApp is the main application class that manages the application lifecycle,
|
|
31
|
-
* handles IPC communication, and integrates with the Router.
|
|
32
|
-
*/
|
|
33
|
-
@Injectable('singleton')
|
|
34
|
-
export class NoxApp {
|
|
35
|
-
private app: IApp | undefined;
|
|
36
|
-
private mainWindow: BrowserWindow | undefined;
|
|
37
|
-
|
|
38
|
-
/**
|
|
39
|
-
*
|
|
40
|
-
*/
|
|
41
|
-
private readonly onRendererMessage = async (event: Electron.MessageEvent): Promise<void> => {
|
|
42
|
-
const { senderId, requestId, path, method, body }: IRequest = event.data;
|
|
43
|
-
|
|
44
|
-
const channels = this.socket.get(senderId);
|
|
45
|
-
|
|
46
|
-
if(!channels) {
|
|
47
|
-
Logger.error(`No message channel found for sender ID: ${senderId}`);
|
|
48
|
-
return;
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
try {
|
|
52
|
-
const request = new Request(event, senderId, requestId, method, path, body);
|
|
53
|
-
const response = await this.router.handle(request);
|
|
54
|
-
channels.request.port1.postMessage(response);
|
|
55
|
-
}
|
|
56
|
-
catch(err: any) {
|
|
57
|
-
const response: IResponse = {
|
|
58
|
-
requestId,
|
|
59
|
-
status: 500,
|
|
60
|
-
body: null,
|
|
61
|
-
error: err.message || 'Internal Server Error',
|
|
62
|
-
};
|
|
63
|
-
|
|
64
|
-
channels.request.port1.postMessage(response);
|
|
65
|
-
}
|
|
66
|
-
};
|
|
67
|
-
|
|
68
|
-
constructor(
|
|
69
|
-
private readonly router: Router,
|
|
70
|
-
private readonly socket: NoxSocket,
|
|
71
|
-
) {}
|
|
72
|
-
|
|
73
|
-
/**
|
|
74
|
-
* Initializes the NoxApp instance.
|
|
75
|
-
* This method sets up the IPC communication, registers event listeners,
|
|
76
|
-
* and prepares the application for use.
|
|
77
|
-
*/
|
|
78
|
-
public async init(): Promise<NoxApp> {
|
|
79
|
-
ipcMain.on('gimme-my-port', this.giveTheRendererAPort.bind(this));
|
|
80
|
-
|
|
81
|
-
app.once('activate', this.onAppActivated.bind(this));
|
|
82
|
-
app.once('window-all-closed', this.onAllWindowsClosed.bind(this));
|
|
83
|
-
|
|
84
|
-
console.log(''); // create a new line in the console to separate setup logs from the future logs
|
|
85
|
-
|
|
86
|
-
return this;
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
/**
|
|
90
|
-
* Handles the request from the renderer process.
|
|
91
|
-
* This method creates a Request object from the IPC event data,
|
|
92
|
-
* processes it through the Router, and sends the response back
|
|
93
|
-
* to the renderer process using the MessageChannel.
|
|
94
|
-
*/
|
|
95
|
-
private giveTheRendererAPort(event: Electron.IpcMainInvokeEvent): void {
|
|
96
|
-
const senderId = event.sender.id;
|
|
97
|
-
|
|
98
|
-
if(this.socket.get(senderId)) {
|
|
99
|
-
this.shutdownChannel(senderId);
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
const requestChannel = new MessageChannelMain();
|
|
103
|
-
const socketChannel = new MessageChannelMain();
|
|
104
|
-
|
|
105
|
-
requestChannel.port1.on('message', this.onRendererMessage);
|
|
106
|
-
requestChannel.port1.start();
|
|
107
|
-
socketChannel.port1.start();
|
|
108
|
-
|
|
109
|
-
this.socket.register(senderId, requestChannel, socketChannel);
|
|
110
|
-
|
|
111
|
-
event.sender.postMessage('port', { senderId }, [requestChannel.port2, socketChannel.port2]);
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
/**
|
|
115
|
-
* MacOS specific behavior.
|
|
116
|
-
*/
|
|
117
|
-
private onAppActivated(): void {
|
|
118
|
-
if(process.platform === 'darwin' && BrowserWindow.getAllWindows().length === 0) {
|
|
119
|
-
this.app?.onActivated();
|
|
120
|
-
}
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
/**
|
|
124
|
-
* Shuts down the message channel for a specific sender ID.
|
|
125
|
-
* This method closes the IPC channel for the specified sender ID and
|
|
126
|
-
* removes it from the messagePorts map.
|
|
127
|
-
* @param channelSenderId - The ID of the sender channel to shut down.
|
|
128
|
-
* @param remove - Whether to remove the channel from the messagePorts map.
|
|
129
|
-
*/
|
|
130
|
-
private shutdownChannel(channelSenderId: number): void {
|
|
131
|
-
const channels = this.socket.get(channelSenderId);
|
|
132
|
-
|
|
133
|
-
if(!channels) {
|
|
134
|
-
Logger.warn(`No message channel found for sender ID: ${channelSenderId}`);
|
|
135
|
-
return;
|
|
136
|
-
}
|
|
137
|
-
|
|
138
|
-
channels.request.port1.off('message', this.onRendererMessage);
|
|
139
|
-
channels.request.port1.close();
|
|
140
|
-
channels.request.port2.close();
|
|
141
|
-
|
|
142
|
-
channels.socket.port1.close();
|
|
143
|
-
channels.socket.port2.close();
|
|
144
|
-
|
|
145
|
-
this.socket.unregister(channelSenderId);
|
|
146
|
-
}
|
|
147
|
-
|
|
148
|
-
/**
|
|
149
|
-
* Handles the application shutdown process.
|
|
150
|
-
* This method is called when all windows are closed, and it cleans up the message channels
|
|
151
|
-
*/
|
|
152
|
-
private async onAllWindowsClosed(): Promise<void> {
|
|
153
|
-
for(const senderId of this.socket.getSenderIds()) {
|
|
154
|
-
this.shutdownChannel(senderId);
|
|
155
|
-
}
|
|
156
|
-
|
|
157
|
-
Logger.info('All windows closed, shutting down application...');
|
|
158
|
-
await this.app?.dispose();
|
|
159
|
-
|
|
160
|
-
if(process.platform !== 'darwin') {
|
|
161
|
-
app.quit();
|
|
162
|
-
}
|
|
163
|
-
}
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
// ---
|
|
167
|
-
|
|
168
|
-
/**
|
|
169
|
-
* Sets the main BrowserWindow that was created early by bootstrapApplication.
|
|
170
|
-
* This window will be passed to IApp.onReady when start() is called.
|
|
171
|
-
* @param window - The BrowserWindow created during bootstrap.
|
|
172
|
-
*/
|
|
173
|
-
public setMainWindow(window: BrowserWindow): void {
|
|
174
|
-
this.mainWindow = window;
|
|
175
|
-
}
|
|
176
|
-
|
|
177
|
-
/**
|
|
178
|
-
* Registers a lazy-loaded route. The module behind this path prefix
|
|
179
|
-
* will only be dynamically imported when the first IPC request
|
|
180
|
-
* targets this prefix — like Angular's loadChildren.
|
|
181
|
-
*
|
|
182
|
-
* @example
|
|
183
|
-
* ```ts
|
|
184
|
-
* noxApp.lazy("auth", () => import("./modules/auth/auth.module.js"));
|
|
185
|
-
* noxApp.lazy("printing", () => import("./modules/printing/printing.module.js"));
|
|
186
|
-
* ```
|
|
187
|
-
*
|
|
188
|
-
* @param pathPrefix - The route prefix (e.g. "auth", "cash-register").
|
|
189
|
-
* @param loadModule - A function returning a dynamic import promise.
|
|
190
|
-
* @returns NoxApp instance for method chaining.
|
|
191
|
-
*/
|
|
192
|
-
public lazy(pathPrefix: string, loadModule: () => Promise<unknown>): NoxApp {
|
|
193
|
-
this.router.registerLazyRoute(pathPrefix, loadModule);
|
|
194
|
-
return this;
|
|
195
|
-
}
|
|
196
|
-
|
|
197
|
-
/**
|
|
198
|
-
* Eagerly loads one or more modules with a two-phase DI guarantee.
|
|
199
|
-
* Use this when a service needed at startup lives inside a module
|
|
200
|
-
* (e.g. the Application service depends on LoaderService).
|
|
201
|
-
*
|
|
202
|
-
* All dynamic imports run in parallel; bindings are registered first,
|
|
203
|
-
* then singletons are resolved — safe regardless of import ordering.
|
|
204
|
-
*
|
|
205
|
-
* @param importFns - Functions returning dynamic import promises.
|
|
206
|
-
*/
|
|
207
|
-
public async loadModules(importFns: Array<() => Promise<unknown>>): Promise<void> {
|
|
208
|
-
InjectorExplorer.beginAccumulate();
|
|
209
|
-
await Promise.all(importFns.map(fn => fn()));
|
|
210
|
-
InjectorExplorer.flushAccumulated();
|
|
211
|
-
}
|
|
212
|
-
|
|
213
|
-
/**
|
|
214
|
-
* Configures the NoxApp instance with the provided application class.
|
|
215
|
-
* This method allows you to set the application class that will handle lifecycle events.
|
|
216
|
-
* @param app - The application class to configure.
|
|
217
|
-
* @returns NoxApp instance for method chaining.
|
|
218
|
-
*/
|
|
219
|
-
public configure(app: Type<IApp>): NoxApp {
|
|
220
|
-
this.app = inject(app);
|
|
221
|
-
return this;
|
|
222
|
-
}
|
|
223
|
-
|
|
224
|
-
/**
|
|
225
|
-
* Registers a middleware for the root of the application.
|
|
226
|
-
* This method allows you to define a middleware that will be applied to all requests
|
|
227
|
-
* @param middleware - The middleware class to register.
|
|
228
|
-
* @returns NoxApp instance for method chaining.
|
|
229
|
-
*/
|
|
230
|
-
public use(middleware: Type<IMiddleware>): NoxApp {
|
|
231
|
-
this.router.defineRootMiddleware(middleware);
|
|
232
|
-
return this;
|
|
233
|
-
}
|
|
234
|
-
|
|
235
|
-
/**
|
|
236
|
-
* Should be called after the bootstrapApplication function is called.
|
|
237
|
-
* Passes the early-created BrowserWindow (if any) to the configured IApp service.
|
|
238
|
-
* @returns NoxApp instance for method chaining.
|
|
239
|
-
*/
|
|
240
|
-
public start(): NoxApp {
|
|
241
|
-
this.app?.onReady(this.mainWindow);
|
|
242
|
-
return this;
|
|
243
|
-
}
|
|
244
|
-
}
|
package/src/bootstrap.ts
DELETED
|
@@ -1,84 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @copyright 2025 NoxFly
|
|
3
|
-
* @license MIT
|
|
4
|
-
* @author NoxFly
|
|
5
|
-
*/
|
|
6
|
-
|
|
7
|
-
import { app, BrowserWindow, screen } from "electron/main";
|
|
8
|
-
import { NoxApp } from "src/app";
|
|
9
|
-
import { getModuleMetadata } from "src/decorators/module.decorator";
|
|
10
|
-
import { inject } from "src/DI/app-injector";
|
|
11
|
-
import { InjectorExplorer } from "src/DI/injector-explorer";
|
|
12
|
-
import { Type } from "src/utils/types";
|
|
13
|
-
|
|
14
|
-
/**
|
|
15
|
-
* Options for bootstrapping the Noxus application.
|
|
16
|
-
*/
|
|
17
|
-
export interface BootstrapOptions {
|
|
18
|
-
/**
|
|
19
|
-
* If provided, Noxus creates a BrowserWindow immediately after Electron is ready,
|
|
20
|
-
* before any DI processing occurs. This window is passed to the configured
|
|
21
|
-
* IApp service via onReady(). It allows the user to see a window as fast as possible,
|
|
22
|
-
* even before the application is fully initialized.
|
|
23
|
-
*/
|
|
24
|
-
window?: Electron.BrowserWindowConstructorOptions;
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
/**
|
|
28
|
-
* Bootstraps the Noxus application.
|
|
29
|
-
* This function initializes the application by creating an instance of NoxApp,
|
|
30
|
-
* registering the root module, and starting the application.
|
|
31
|
-
*
|
|
32
|
-
* When {@link BootstrapOptions.window} is provided, a BrowserWindow is created
|
|
33
|
-
* immediately after Electron readiness — before DI resolution — so the user
|
|
34
|
-
* sees a window as quickly as possible.
|
|
35
|
-
*
|
|
36
|
-
* @param rootModule - The root module of the application, decorated with @Module.
|
|
37
|
-
* @param options - Optional bootstrap configuration.
|
|
38
|
-
* @return A promise that resolves to the NoxApp instance.
|
|
39
|
-
* @throws Error if the root module is not decorated with @Module, or if the electron process could not start.
|
|
40
|
-
*/
|
|
41
|
-
export async function bootstrapApplication(rootModule?: Type<any> | null, options?: BootstrapOptions): Promise<NoxApp> {
|
|
42
|
-
if(rootModule && !getModuleMetadata(rootModule)) {
|
|
43
|
-
throw new Error(`Root module must be decorated with @Module`);
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
await app.whenReady();
|
|
47
|
-
|
|
48
|
-
// Create window immediately after Electron is ready, before DI processing.
|
|
49
|
-
// This gets pixels on screen as fast as possible.
|
|
50
|
-
let mainWindow: BrowserWindow | undefined;
|
|
51
|
-
|
|
52
|
-
if(options?.window) {
|
|
53
|
-
mainWindow = new BrowserWindow(options.window);
|
|
54
|
-
|
|
55
|
-
mainWindow.once("ready-to-show", () => {
|
|
56
|
-
mainWindow?.show();
|
|
57
|
-
});
|
|
58
|
-
|
|
59
|
-
const primaryDisplay = screen.getPrimaryDisplay();
|
|
60
|
-
const { width, height } = primaryDisplay.workAreaSize;
|
|
61
|
-
|
|
62
|
-
if(options.window.minWidth && options.window.minHeight) {
|
|
63
|
-
mainWindow.setSize(
|
|
64
|
-
Math.min(width, options.window.minWidth),
|
|
65
|
-
Math.min(height, options.window.minHeight),
|
|
66
|
-
true,
|
|
67
|
-
);
|
|
68
|
-
}
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
// Process all deferred injectable registrations (two-phase: bindings then resolution)
|
|
72
|
-
InjectorExplorer.processPending();
|
|
73
|
-
|
|
74
|
-
const noxApp = inject(NoxApp);
|
|
75
|
-
|
|
76
|
-
if(mainWindow) {
|
|
77
|
-
noxApp.setMainWindow(mainWindow);
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
await noxApp.init();
|
|
81
|
-
|
|
82
|
-
return noxApp;
|
|
83
|
-
}
|
|
84
|
-
|
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @copyright 2025 NoxFly
|
|
3
|
-
* @license MIT
|
|
4
|
-
* @author NoxFly
|
|
5
|
-
*/
|
|
6
|
-
|
|
7
|
-
import 'reflect-metadata';
|
|
8
|
-
|
|
9
|
-
export const INJECT_METADATA_KEY = 'custom:inject';
|
|
10
|
-
|
|
11
|
-
/**
|
|
12
|
-
* Decorator to manually inject a dependency.
|
|
13
|
-
* Useful for handling circular dependencies with `forwardRef` or injecting specific tokens.
|
|
14
|
-
*
|
|
15
|
-
* @param token The token or forward reference to inject.
|
|
16
|
-
*/
|
|
17
|
-
export function Inject(token: any): ParameterDecorator {
|
|
18
|
-
return (target, propertyKey, parameterIndex) => {
|
|
19
|
-
// target is the constructor for constructor parameters
|
|
20
|
-
const existingParameters = Reflect.getOwnMetadata(INJECT_METADATA_KEY, target) || [];
|
|
21
|
-
existingParameters[parameterIndex] = token;
|
|
22
|
-
Reflect.defineMetadata(INJECT_METADATA_KEY, existingParameters, target);
|
|
23
|
-
};
|
|
24
|
-
}
|