@noxfly/noxus 3.0.0-dev.4 → 3.0.0-dev.5

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.
Files changed (45) hide show
  1. package/dist/child.js.map +1 -0
  2. package/dist/child.mjs.map +1 -0
  3. package/dist/main.js.map +1 -0
  4. package/dist/main.mjs.map +1 -0
  5. package/dist/preload.js.map +1 -0
  6. package/dist/preload.mjs.map +1 -0
  7. package/dist/renderer.js.map +1 -0
  8. package/dist/renderer.mjs.map +1 -0
  9. package/package.json +10 -9
  10. package/.editorconfig +0 -16
  11. package/.github/copilot-instructions.md +0 -128
  12. package/.vscode/settings.json +0 -3
  13. package/AGENTS.md +0 -5
  14. package/eslint.config.js +0 -109
  15. package/scripts/postbuild.js +0 -31
  16. package/src/DI/app-injector.ts +0 -173
  17. package/src/DI/injector-explorer.ts +0 -201
  18. package/src/DI/token.ts +0 -53
  19. package/src/decorators/controller.decorator.ts +0 -58
  20. package/src/decorators/guards.decorator.ts +0 -15
  21. package/src/decorators/injectable.decorator.ts +0 -81
  22. package/src/decorators/method.decorator.ts +0 -66
  23. package/src/decorators/middleware.decorator.ts +0 -15
  24. package/src/index.ts +0 -10
  25. package/src/internal/app.ts +0 -219
  26. package/src/internal/bootstrap.ts +0 -141
  27. package/src/internal/exceptions.ts +0 -57
  28. package/src/internal/preload-bridge.ts +0 -75
  29. package/src/internal/renderer-client.ts +0 -374
  30. package/src/internal/renderer-events.ts +0 -110
  31. package/src/internal/request.ts +0 -102
  32. package/src/internal/router.ts +0 -365
  33. package/src/internal/routes.ts +0 -142
  34. package/src/internal/socket.ts +0 -75
  35. package/src/main.ts +0 -26
  36. package/src/non-electron-process.ts +0 -22
  37. package/src/preload.ts +0 -10
  38. package/src/renderer.ts +0 -13
  39. package/src/utils/forward-ref.ts +0 -31
  40. package/src/utils/logger.ts +0 -430
  41. package/src/utils/radix-tree.ts +0 -243
  42. package/src/utils/types.ts +0 -21
  43. package/src/window/window-manager.ts +0 -302
  44. package/tsconfig.json +0 -29
  45. package/tsup.config.ts +0 -50
package/src/DI/token.ts DELETED
@@ -1,53 +0,0 @@
1
- /**
2
- * @copyright 2025 NoxFly
3
- * @license MIT
4
- * @author NoxFly
5
- */
6
-
7
- import { Type } from '../utils/types';
8
-
9
- /**
10
- * A DI token uniquely identifies a dependency.
11
- * It can wrap a class (Type<T>) or be a named symbol token.
12
- *
13
- * Using tokens instead of reflect-metadata means dependencies are
14
- * declared explicitly — no magic type inference, no emitDecoratorMetadata.
15
- *
16
- * @example
17
- * // Class token (most common)
18
- * const MY_SERVICE = token(MyService);
19
- *
20
- * // Named symbol token (for interfaces or non-class values)
21
- * const DB_URL = token<string>('DB_URL');
22
- */
23
- export class Token<T> {
24
- public readonly description: string;
25
-
26
- constructor(
27
- public readonly target: Type<T> | string,
28
- ) {
29
- this.description = typeof target === 'string' ? target : target.name;
30
- }
31
-
32
- public toString(): string {
33
- return `Token(${this.description})`;
34
- }
35
- }
36
-
37
- /**
38
- * Creates a DI token for a class type or a named value.
39
- *
40
- * @example
41
- * export const MY_SERVICE = token(MyService);
42
- * export const DB_URL = token<string>('DB_URL');
43
- */
44
- export function token<T>(target: Type<T> | string): Token<T> {
45
- return new Token<T>(target);
46
- }
47
-
48
- /**
49
- * The key used to look up a class token in the registry.
50
- * For class tokens, the key is the class constructor itself.
51
- * For named tokens, the key is the Token instance.
52
- */
53
- export type TokenKey<T = unknown> = Type<T> | Token<T>;
@@ -1,58 +0,0 @@
1
- /**
2
- * @copyright 2025 NoxFly
3
- * @license MIT
4
- * @author NoxFly
5
- */
6
-
7
- import { InjectorExplorer } from '../DI/injector-explorer';
8
- import { TokenKey } from '../DI/token';
9
- import { Type } from '../utils/types';
10
-
11
- export interface ControllerOptions {
12
- /**
13
- * Explicit constructor dependencies.
14
- */
15
- deps?: ReadonlyArray<TokenKey>;
16
- }
17
-
18
- export interface IControllerMetadata {
19
- deps: ReadonlyArray<TokenKey>;
20
- }
21
-
22
- const controllerMetaMap = new WeakMap<object, IControllerMetadata>();
23
-
24
- /**
25
- * Marks a class as a Noxus controller.
26
- * Controllers are always scope-scoped injectables.
27
- * The route prefix and guards/middlewares are declared in defineRoutes(), not here.
28
- *
29
- * @example
30
- * @Controller({ deps: [UserService] })
31
- * export class UserController {
32
- * constructor(private svc: UserService) {}
33
- *
34
- * @Get('byId/:userId')
35
- * getUserById(req: Request) { ... }
36
- * }
37
- */
38
- export function Controller(options: ControllerOptions = {}): ClassDecorator {
39
- return (target) => {
40
- const meta: IControllerMetadata = {
41
- deps: options.deps ?? [],
42
- };
43
-
44
- controllerMetaMap.set(target, meta);
45
-
46
- InjectorExplorer.enqueue({
47
- key: target as unknown as Type<unknown>,
48
- implementation: target as unknown as Type<unknown>,
49
- lifetime: 'scope',
50
- deps: options.deps ?? [],
51
- isController: true,
52
- });
53
- };
54
- }
55
-
56
- export function getControllerMetadata(target: object): IControllerMetadata | undefined {
57
- return controllerMetaMap.get(target);
58
- }
@@ -1,15 +0,0 @@
1
- /**
2
- * @copyright 2025 NoxFly
3
- * @license MIT
4
- * @author NoxFly
5
- */
6
-
7
- import { Request } from '../internal/request';
8
- import { MaybeAsync } from '../utils/types';
9
-
10
- /**
11
- * A guard decides whether an incoming request should reach the handler.
12
- * Implement this interface and pass the class to @Controller({ guards }) or @Get('path', { guards }).
13
- */
14
-
15
- export type Guard = (request: Request) => MaybeAsync<boolean>;
@@ -1,81 +0,0 @@
1
- /**
2
- * @copyright 2025 NoxFly
3
- * @license MIT
4
- * @author NoxFly
5
- */
6
-
7
- import { Lifetime } from '../DI/app-injector';
8
- import { InjectorExplorer } from '../DI/injector-explorer';
9
- import { Token, TokenKey } from '../DI/token';
10
- import { Type } from '../utils/types';
11
-
12
- export interface InjectableOptions {
13
- /**
14
- * Lifetime of this injectable.
15
- * @default 'scope'
16
- */
17
- lifetime?: Lifetime;
18
-
19
- /**
20
- * Explicit list of constructor dependencies, in the same order as the constructor parameters.
21
- * Each entry is either a class constructor or a Token created with token().
22
- *
23
- * This replaces reflect-metadata / emitDecoratorMetadata entirely.
24
- *
25
- * @example
26
- * @Injectable({ lifetime: 'singleton', deps: [MyRepo, DB_URL] })
27
- * class MyService {
28
- * constructor(private repo: MyRepo, private dbUrl: string) {}
29
- * }
30
- */
31
- deps?: ReadonlyArray<TokenKey>;
32
- }
33
-
34
- /**
35
- * Marks a class as injectable into the Noxus DI container.
36
- *
37
- * Unlike the v2 @Injectable, this decorator:
38
- * - Does NOT require reflect-metadata or emitDecoratorMetadata.
39
- * - Requires you to declare deps explicitly when the class has constructor parameters.
40
- * - Supports standalone usage — no module declaration needed.
41
- *
42
- * @example
43
- * // No dependencies
44
- * @Injectable()
45
- * class Logger {}
46
- *
47
- * // With dependencies
48
- * @Injectable({ lifetime: 'singleton', deps: [Logger, MyRepo] })
49
- * class MyService {
50
- * constructor(private logger: Logger, private repo: MyRepo) {}
51
- * }
52
- *
53
- * // With a named token
54
- * const DB_URL = token<string>('DB_URL');
55
- *
56
- * @Injectable({ deps: [DB_URL] })
57
- * class DbService {
58
- * constructor(private url: string) {}
59
- * }
60
- */
61
- export function Injectable(options: InjectableOptions = {}): ClassDecorator {
62
- const { lifetime = 'scope', deps = [] } = options;
63
-
64
- return (target) => {
65
- if (typeof target !== 'function' || !target.prototype) {
66
- throw new Error(`@Injectable can only be applied to classes, not ${typeof target}`);
67
- }
68
-
69
- const key = target as unknown as Type<unknown>;
70
-
71
- InjectorExplorer.enqueue({
72
- key,
73
- implementation: key,
74
- lifetime,
75
- deps,
76
- isController: false,
77
- });
78
- };
79
- }
80
-
81
- export { Token, TokenKey };
@@ -1,66 +0,0 @@
1
- /**
2
- * @copyright 2025 NoxFly
3
- * @license MIT
4
- * @author NoxFly
5
- */
6
-
7
- import { Guard } from './guards.decorator';
8
- import { Middleware } from './middleware.decorator';
9
-
10
- export type HttpMethod = 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE' | 'BATCH';
11
- export type AtomicHttpMethod = Exclude<HttpMethod, 'BATCH'>;
12
-
13
- const ATOMIC_METHODS = new Set<AtomicHttpMethod>(['GET', 'POST', 'PUT', 'PATCH', 'DELETE']);
14
- export function isAtomicHttpMethod(m: unknown): m is AtomicHttpMethod {
15
- return typeof m === 'string' && ATOMIC_METHODS.has(m as AtomicHttpMethod);
16
- }
17
-
18
- export interface IRouteOptions {
19
- /**
20
- * Guards specific to this route (merged with controller guards).
21
- */
22
- guards?: Guard[];
23
- /**
24
- * Middlewares specific to this route (merged with controller middlewares).
25
- */
26
- middlewares?: Middleware[];
27
- }
28
-
29
- export interface IRouteMetadata {
30
- method: HttpMethod;
31
- path: string;
32
- handler: string;
33
- guards: Guard[];
34
- middlewares: Middleware[];
35
- }
36
-
37
- const routeMetaMap = new WeakMap<object, IRouteMetadata[]>();
38
-
39
- function createRouteDecorator(verb: HttpMethod) {
40
- return (path: string, options: IRouteOptions = {}): MethodDecorator => {
41
- return (target, propertyKey) => {
42
- const ctor = target.constructor;
43
- const existing: IRouteMetadata[] = routeMetaMap.get(ctor) ?? [];
44
-
45
- existing.push({
46
- method: verb,
47
- path: (path ?? '').trim().replace(/^\/|\/$/g, ''),
48
- handler: propertyKey as string,
49
- guards: options.guards ?? [],
50
- middlewares: options.middlewares ?? [],
51
- });
52
-
53
- routeMetaMap.set(ctor, existing);
54
- };
55
- };
56
- }
57
-
58
- export function getRouteMetadata(target: object): IRouteMetadata[] {
59
- return routeMetaMap.get(target) ?? [];
60
- }
61
-
62
- export const Get = createRouteDecorator('GET');
63
- export const Post = createRouteDecorator('POST');
64
- export const Put = createRouteDecorator('PUT');
65
- export const Patch = createRouteDecorator('PATCH');
66
- export const Delete = createRouteDecorator('DELETE');
@@ -1,15 +0,0 @@
1
- /**
2
- * @copyright 2025 NoxFly
3
- * @license MIT
4
- * @author NoxFly
5
- */
6
-
7
- import { IResponse, Request } from '../internal/request';
8
- import { MaybeAsync } from '../utils/types';
9
-
10
- /**
11
- * A middleware intercepts requests before they reach guards and the handler.
12
- * Implement this interface and pass the class to @Controller({ middlewares }) or per-route options.
13
- */
14
- export type Middleware = (request: Request, response: IResponse, next: NextFunction) => MaybeAsync<void>;
15
- export type NextFunction = () => Promise<void>;
package/src/index.ts DELETED
@@ -1,10 +0,0 @@
1
- /**
2
- * @copyright 2025 NoxFly
3
- * @license MIT
4
- * @author NoxFly
5
- *
6
- * Entry point for renderer process and preload consumers.
7
- */
8
-
9
- // src/index.ts — redirige vers renderer
10
- export * from './renderer';
@@ -1,219 +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 { Guard } from "../decorators/guards.decorator";
9
- import { Injectable } from '../decorators/injectable.decorator';
10
- import { Middleware } from '../decorators/middleware.decorator';
11
- import { inject } from '../DI/app-injector';
12
- import { InjectorExplorer } from '../DI/injector-explorer';
13
- import { Logger } from '../utils/logger';
14
- import { Type } from '../utils/types';
15
- import { WindowManager } from '../window/window-manager';
16
- import { IResponse, Request } from './request';
17
- import { Router } from './router';
18
- import { NoxSocket } from './socket';
19
-
20
- /**
21
- * Your application service should implement IApp.
22
- * Noxus calls these lifecycle methods at the appropriate time.
23
- *
24
- * Unlike v2, IApp no longer receives a BrowserWindow in onReady.
25
- * Use the injected WindowManager instead — it is more flexible and
26
- * does not couple the lifecycle to a single pre-created window.
27
- *
28
- * @example
29
- * @Injectable({ lifetime: 'singleton', deps: [WindowManager, MyService] })
30
- * class AppService implements IApp {
31
- * constructor(private wm: WindowManager, private svc: MyService) {}
32
- *
33
- * async onReady() {
34
- * const win = await this.wm.createSplash({ webPreferences: { preload: ... } });
35
- * win.loadFile('index.html');
36
- * }
37
- *
38
- * async onActivated() { ... }
39
- * async dispose() { ... }
40
- * }
41
- */
42
- export interface IApp {
43
- dispose(): Promise<void>;
44
- onReady(): Promise<void>;
45
- onActivated(): Promise<void>;
46
- }
47
-
48
- @Injectable({ lifetime: 'singleton', deps: [Router, NoxSocket, WindowManager] })
49
- export class NoxApp {
50
- private appService: IApp | undefined;
51
-
52
- constructor(
53
- private readonly router: Router,
54
- private readonly socket: NoxSocket,
55
- public readonly windowManager: WindowManager,
56
- ) {}
57
-
58
- // -------------------------------------------------------------------------
59
- // Initialisation
60
- // -------------------------------------------------------------------------
61
-
62
- public async init(): Promise<this> {
63
- ipcMain.on('gimme-my-port', this.giveTheRendererAPort.bind(this));
64
- app.once('activate', this.onAppActivated.bind(this));
65
- app.once('window-all-closed', this.onAllWindowsClosed.bind(this));
66
- console.log('');
67
- return this;
68
- }
69
-
70
- // -------------------------------------------------------------------------
71
- // Public API
72
- // -------------------------------------------------------------------------
73
-
74
- /**
75
- * Registers a lazy route. The file behind this prefix is dynamically
76
- * imported on the first IPC request that targets it.
77
- *
78
- * The import function should NOT statically reference heavy modules —
79
- * the whole point is to defer their loading.
80
- *
81
- * @example
82
- * noxApp.lazy('auth', () => import('./modules/auth/auth.controller.js'));
83
- * noxApp.lazy('reporting', () => import('./modules/reporting/index.js'));
84
- */
85
- public lazy(
86
- pathPrefix: string,
87
- load: () => Promise<unknown>,
88
- guards: Guard[] = [],
89
- middlewares: Middleware[] = [],
90
- ): this {
91
- this.router.registerLazyRoute(pathPrefix, load, guards, middlewares);
92
- return this;
93
- }
94
-
95
- /**
96
- * Eagerly loads a set of modules (controllers + services) before start().
97
- * Use this for modules that provide services needed by your IApp.onReady().
98
- *
99
- * All imports run in parallel; DI is flushed with the two-phase guarantee.
100
- */
101
- public async load(importFns: Array<() => Promise<unknown>>): Promise<this> {
102
- InjectorExplorer.beginAccumulate();
103
- await Promise.all(importFns.map((fn) => fn()));
104
- await InjectorExplorer.flushAccumulated();
105
- return this;
106
- }
107
-
108
- /**
109
- * Registers a global middleware applied to every route.
110
- */
111
- public use(middleware: Middleware): this {
112
- this.router.defineRootMiddleware(middleware);
113
- return this;
114
- }
115
-
116
- /**
117
- * Sets the application service (implements IApp) that receives lifecycle events.
118
- * @param appClass - Class decorated with @Injectable that implements IApp.
119
- */
120
- public configure(appClass: Type<IApp>): this {
121
- this.appService = inject(appClass);
122
- return this;
123
- }
124
-
125
- /**
126
- * Calls IApp.onReady(). Should be called after configure() and any lazy()
127
- * registrations are set up.
128
- */
129
- public start(): this {
130
- this.appService?.onReady();
131
- return this;
132
- }
133
-
134
- // -------------------------------------------------------------------------
135
- // IPC
136
- // -------------------------------------------------------------------------
137
-
138
- private readonly onRendererMessage = async (event: Electron.MessageEvent): Promise<void> => {
139
- const { senderId, requestId, path, method, body, query }: import('./request').IRequest = event.data;
140
- const channels = this.socket.get(senderId);
141
-
142
- if (!channels) {
143
- Logger.error(`No message channel found for sender ID: ${senderId}`);
144
- return;
145
- }
146
-
147
- try {
148
- const request = new Request(event, senderId, requestId, method, path, body, query);
149
- const response = await this.router.handle(request);
150
- channels.request.port1.postMessage(response);
151
- }
152
- catch (err: unknown) {
153
- const response: IResponse = {
154
- requestId,
155
- status: 500,
156
- body: null,
157
- error: err instanceof Error ? err.message : 'Internal Server Error',
158
- };
159
- channels.request.port1.postMessage(response);
160
- }
161
- };
162
-
163
- private giveTheRendererAPort(event: Electron.IpcMainInvokeEvent): void {
164
- const senderId = event.sender.id;
165
-
166
- if (this.socket.get(senderId)) {
167
- this.shutdownChannel(senderId);
168
- }
169
-
170
- const requestChannel = new MessageChannelMain();
171
- const socketChannel = new MessageChannelMain();
172
-
173
- requestChannel.port1.on('message', this.onRendererMessage);
174
- requestChannel.port1.start();
175
- socketChannel.port1.start();
176
-
177
- event.sender.once('destroyed', () => this.shutdownChannel(senderId));
178
-
179
- this.socket.register(senderId, requestChannel, socketChannel);
180
- event.sender.postMessage('port', { senderId }, [requestChannel.port2, socketChannel.port2]);
181
- }
182
-
183
- // -------------------------------------------------------------------------
184
- // Lifecycle
185
- // -------------------------------------------------------------------------
186
-
187
- private onAppActivated(): void {
188
- if (process.platform === 'darwin' && BrowserWindow.getAllWindows().length === 0) {
189
- this.appService?.onActivated();
190
- }
191
- }
192
-
193
- private async onAllWindowsClosed(): Promise<void> {
194
- for (const senderId of this.socket.getSenderIds()) {
195
- this.shutdownChannel(senderId);
196
- }
197
-
198
- Logger.info('All windows closed, shutting down application...');
199
- await this.appService?.dispose();
200
-
201
- if (process.platform !== 'darwin') app.quit();
202
- }
203
-
204
- private shutdownChannel(channelSenderId: number): void {
205
- const channels = this.socket.get(channelSenderId);
206
-
207
- if (!channels) {
208
- return;
209
- }
210
-
211
- channels.request.port1.off('message', this.onRendererMessage);
212
- channels.request.port1.close();
213
- channels.request.port2.close();
214
- channels.socket.port1.close();
215
- channels.socket.port2.close();
216
-
217
- this.socket.unregister(channelSenderId);
218
- }
219
- }
@@ -1,141 +0,0 @@
1
- /**
2
- * @copyright 2025 NoxFly
3
- * @license MIT
4
- * @author NoxFly
5
- */
6
-
7
- import { app } from 'electron/main';
8
- import { inject, RootInjector } from '../DI/app-injector';
9
- import { InjectorExplorer } from '../DI/injector-explorer';
10
- import { TokenKey } from '../DI/token';
11
- import { Logger } from '../utils/logger';
12
- import { NoxApp } from './app';
13
- import { RouteDefinition } from "./routes";
14
- import { Router } from './router';
15
-
16
- /**
17
- * A singleton value override: provides an already-constructed instance
18
- * for a given token, bypassing the DI factory.
19
- *
20
- * Useful for injecting external singletons (e.g. a database connection,
21
- * a logger already configured, a third-party SDK wrapper) that cannot
22
- * or should not be constructed by the DI container.
23
- *
24
- * @example
25
- * { token: MikroORM, useValue: await MikroORM.init(config) }
26
- * { token: DB_URL, useValue: process.env.DATABASE_URL }
27
- */
28
- export interface SingletonOverride<T = unknown> {
29
- token: TokenKey<T>;
30
- useValue: T;
31
- }
32
-
33
- /**
34
- * Configuration object for bootstrapApplication.
35
- */
36
- export interface BootstrapConfig {
37
- /**
38
- * Application routing table, produced by defineRoutes().
39
- * All lazy routes are registered before the app starts.
40
- */
41
- routes?: RouteDefinition[];
42
-
43
- /**
44
- * Pre-built singleton instances to inject into the DI container
45
- * before the application starts.
46
- *
47
- * This replaces the v2 module/provider declaration pattern for
48
- * external singletons.
49
- *
50
- * @example
51
- * singletons: [
52
- * { token: MikroORM, useValue: await MikroORM.init(ormConfig) },
53
- * { token: DB_URL, useValue: process.env.DATABASE_URL! },
54
- * ]
55
- */
56
- singletons?: SingletonOverride[];
57
-
58
- /**
59
- * Controllers and services to eagerly load before NoxApp.start() is called.
60
- * Each entry is a dynamic import function — files are imported in parallel.
61
- *
62
- * Use this only for things needed at startup (e.g. if your IApp service
63
- * depends on a service in an otherwise lazy module).
64
- *
65
- * Everything else should be registered via noxApp.lazy().
66
- *
67
- * @example
68
- * eagerLoad: [
69
- * () => import('./modules/auth/auth.controller.js'),
70
- * ]
71
- */
72
- eagerLoad?: Array<() => Promise<unknown>>;
73
-
74
- /**
75
- * Controls framework log verbosity.
76
- * - `'debug'`: all messages (default during development).
77
- * - `'info'`: info, warn, error, critical only.
78
- * - `'none'`: completely silent — no framework logs.
79
- *
80
- * You can also pass an array of specific log levels to enable.
81
- */
82
- logLevel?: 'debug' | 'info' | 'none' | import('../utils/logger').LogLevel[];
83
- }
84
-
85
- /**
86
- * Bootstraps the Noxus application.
87
- */
88
- export async function bootstrapApplication(config: BootstrapConfig = {}): Promise<NoxApp> {
89
- await app.whenReady();
90
-
91
- // Apply log level configuration
92
- if (config.logLevel !== undefined) {
93
- if (config.logLevel === 'none') {
94
- Logger.setLogLevel([]);
95
- } else if (Array.isArray(config.logLevel)) {
96
- Logger.setLogLevel(config.logLevel);
97
- } else {
98
- Logger.setLogLevel(config.logLevel);
99
- }
100
- }
101
-
102
- // Build override map for the DI flush phase
103
- const overrides = new Map<TokenKey, unknown>();
104
-
105
- for (const { token, useValue } of config.singletons ?? []) {
106
- overrides.set(token, useValue);
107
- // Pre-register the binding so the injector knows the token exists
108
- RootInjector.singletons.set(token as any, useValue);
109
- }
110
-
111
- // Flush all classes enqueued by decorators at import time (two-phase)
112
- // Wire the controller registrar so InjectorExplorer can register controllers
113
- // without directly importing Router (avoids circular dependency).
114
- InjectorExplorer.setControllerRegistrar((controllerClass, pathPrefix, routeGuards, routeMiddlewares) => {
115
- const router = inject(Router);
116
- router.registerController(controllerClass, pathPrefix, routeGuards, routeMiddlewares);
117
- });
118
-
119
- InjectorExplorer.processPending(overrides);
120
-
121
- // Resolve core framework singletons
122
- const noxApp = inject(NoxApp);
123
-
124
- // Register routes from the routing table
125
- if (config.routes?.length) {
126
- for (const route of config.routes) {
127
- if (route.load) {
128
- noxApp.lazy(route.path, route.load, route.guards, route.middlewares);
129
- }
130
- }
131
- }
132
-
133
- // Eagerly load optional modules
134
- if (config.eagerLoad?.length) {
135
- await noxApp.load(config.eagerLoad);
136
- }
137
-
138
- await noxApp.init();
139
-
140
- return noxApp;
141
- }