@noxfly/noxus 3.0.0-dev.1 → 3.0.0-dev.10

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 (57) hide show
  1. package/README.md +121 -8
  2. package/dist/child.d.mts +7 -1
  3. package/dist/child.d.ts +7 -1
  4. package/dist/child.js +402 -859
  5. package/dist/child.js.map +1 -0
  6. package/dist/child.mjs +389 -847
  7. package/dist/child.mjs.map +1 -0
  8. package/dist/main.d.mts +173 -125
  9. package/dist/main.d.ts +173 -125
  10. package/dist/main.js +990 -890
  11. package/dist/main.js.map +1 -0
  12. package/dist/main.mjs +939 -840
  13. package/dist/main.mjs.map +1 -0
  14. package/dist/preload.js.map +1 -0
  15. package/dist/preload.mjs.map +1 -0
  16. package/dist/renderer.d.mts +30 -4
  17. package/dist/renderer.d.ts +30 -4
  18. package/dist/renderer.js +163 -116
  19. package/dist/renderer.js.map +1 -0
  20. package/dist/renderer.mjs +152 -104
  21. package/dist/renderer.mjs.map +1 -0
  22. package/package.json +18 -9
  23. package/.editorconfig +0 -16
  24. package/.github/copilot-instructions.md +0 -32
  25. package/.vscode/settings.json +0 -3
  26. package/eslint.config.js +0 -109
  27. package/scripts/postbuild.js +0 -31
  28. package/src/DI/app-injector.ts +0 -151
  29. package/src/DI/injector-explorer.ts +0 -143
  30. package/src/DI/token.ts +0 -53
  31. package/src/decorators/controller.decorator.ts +0 -58
  32. package/src/decorators/guards.decorator.ts +0 -15
  33. package/src/decorators/injectable.decorator.ts +0 -81
  34. package/src/decorators/method.decorator.ts +0 -66
  35. package/src/decorators/middleware.decorator.ts +0 -15
  36. package/src/index.ts +0 -10
  37. package/src/internal/app.ts +0 -217
  38. package/src/internal/bootstrap.ts +0 -108
  39. package/src/internal/exceptions.ts +0 -57
  40. package/src/internal/preload-bridge.ts +0 -75
  41. package/src/internal/renderer-client.ts +0 -338
  42. package/src/internal/renderer-events.ts +0 -110
  43. package/src/internal/request.ts +0 -97
  44. package/src/internal/router.ts +0 -353
  45. package/src/internal/routes.ts +0 -78
  46. package/src/internal/socket.ts +0 -73
  47. package/src/main.ts +0 -26
  48. package/src/non-electron-process.ts +0 -22
  49. package/src/preload.ts +0 -10
  50. package/src/renderer.ts +0 -13
  51. package/src/utils/forward-ref.ts +0 -31
  52. package/src/utils/logger.ts +0 -430
  53. package/src/utils/radix-tree.ts +0 -210
  54. package/src/utils/types.ts +0 -21
  55. package/src/window/window-manager.ts +0 -255
  56. package/tsconfig.json +0 -29
  57. package/tsup.config.ts +0 -50
package/README.md CHANGED
@@ -120,19 +120,30 @@ export class AppService implements IApp {
120
120
  }
121
121
  ```
122
122
 
123
- ### 4. Bootstrap the application
123
+ ### 4. Define routes
124
+
125
+ ```ts
126
+ // routes.ts
127
+ import { defineRoutes } from '@noxfly/noxus/main';
128
+
129
+ export const routes = defineRoutes([
130
+ { path: 'users', load: () => import('./controllers/user.controller.js') },
131
+ { path: 'orders', load: () => import('./controllers/order.controller.js') },
132
+ ]);
133
+ ```
134
+
135
+ ### 5. Bootstrap the application
124
136
 
125
137
  ```ts
126
138
  // main.ts
127
139
  import { bootstrapApplication } from '@noxfly/noxus/main';
128
140
  import { AppService } from './app.service';
141
+ import { routes } from './routes';
129
142
 
130
- const noxApp = await bootstrapApplication();
143
+ const noxApp = await bootstrapApplication({ routes });
131
144
 
132
145
  noxApp
133
146
  .configure(AppService)
134
- .lazy('users', () => import('./controllers/user.controller.js'))
135
- .lazy('orders', () => import('./controllers/order.controller.js'))
136
147
  .start();
137
148
  ```
138
149
 
@@ -195,6 +206,9 @@ import { inject } from '@noxfly/noxus/main';
195
206
  const userService = inject(UserService);
196
207
  ```
197
208
 
209
+ When you decide to inject manually with `inject()`, you may not duplicate the dependency in the `deps` array of `@Injectable`.
210
+ The resolve dependency in deps will be ignored in the constructor and will be re-solved at runtime by `inject()`.
211
+
198
212
  Useful outside a constructor — in callbacks, factories, etc.
199
213
 
200
214
  ### `forwardRef()` — Circular dependencies
@@ -238,6 +252,21 @@ getProduct(req: Request) {
238
252
  }
239
253
  ```
240
254
 
255
+ ### Query parameters
256
+
257
+ ```ts
258
+ // Renderer side:
259
+ await client.request({ method: 'GET', path: 'users/list', query: { role: 'admin', page: '1' } });
260
+
261
+ // Controller side:
262
+ @Get('list')
263
+ list(req: Request) {
264
+ const role = req.query['role']; // 'admin'
265
+ const page = req.query['page']; // '1'
266
+ return this.svc.findAll({ role, page: parseInt(page!) });
267
+ }
268
+ ```
269
+
241
270
  ### Request body
242
271
 
243
272
  ```ts
@@ -261,10 +290,43 @@ create(req: Request, res: IResponse) {
261
290
 
262
291
  ---
263
292
 
293
+ ## Route definitions (`defineRoutes`)
294
+
295
+ `defineRoutes` is the single source of truth for your routing table. It validates prefixes, detects duplicates and overlapping paths, and supports nested routes:
296
+
297
+ ```ts
298
+ import { defineRoutes } from '@noxfly/noxus/main';
299
+
300
+ export const routes = defineRoutes([
301
+ { path: 'users', load: () => import('./modules/users/users.controller.js'), guards: [authGuard] },
302
+ { path: 'orders', load: () => import('./modules/orders/orders.controller.js') },
303
+ ]);
304
+ ```
305
+
306
+ ### Nested routes
307
+
308
+ Parent routes can omit `load` and only serve as a shared prefix with inherited guards/middlewares:
309
+
310
+ ```ts
311
+ export const routes = defineRoutes([
312
+ {
313
+ path: 'admin',
314
+ guards: [authGuard, adminGuard],
315
+ children: [
316
+ { path: 'users', load: () => import('./admin/users.controller.js') },
317
+ { path: 'products', load: () => import('./admin/products.controller.js') },
318
+ ],
319
+ },
320
+ ]);
321
+ // Produces flat routes: admin/users and admin/products, both inheriting authGuard + adminGuard.
322
+ ```
323
+
264
324
  ## Lazy loading
265
325
 
266
326
  This is the core mechanism for keeping startup fast. A lazy controller is never imported until an IPC request targets its prefix.
267
327
 
328
+ Routes declared via `defineRoutes` are lazy by default. You can also register lazy routes manually:
329
+
268
330
  ```ts
269
331
  noxApp
270
332
  .lazy('users', () => import('./modules/users/users.controller.js'))
@@ -451,9 +513,9 @@ class UserRepository {
451
513
 
452
514
  ```ts
453
515
  // preload.ts
454
- import { createPreloadBridge } from '@noxfly/noxus';
516
+ import { exposeNoxusBridge } from '@noxfly/noxus/preload';
455
517
 
456
- createPreloadBridge(); // exposes window.__noxus__ to the renderer
518
+ exposeNoxusBridge(); // exposes window.__noxus__ to the renderer
457
519
  ```
458
520
 
459
521
  ### IPC client
@@ -462,15 +524,24 @@ createPreloadBridge(); // exposes window.__noxus__ to the renderer
462
524
  // In the renderer (Angular, React, Vue, Vanilla...)
463
525
  import { NoxRendererClient } from '@noxfly/noxus';
464
526
 
465
- const client = new NoxRendererClient();
527
+ const client = new NoxRendererClient({
528
+ requestTimeout: 10_000, // 10s (default). Set to 0 to disable.
529
+ });
466
530
  await client.setup(); // requests the MessagePort from main
467
531
 
468
532
  // Requests
469
533
  const users = await client.request<User[]>({ method: 'GET', path: 'users/list' });
470
534
  const user = await client.request<User> ({ method: 'GET', path: 'users/42' });
535
+ await client.request({ method: 'GET', path: 'users/list', query: { role: 'admin' } });
471
536
  await client.request({ method: 'POST', path: 'users/create', body: { name: 'Bob' } });
472
537
  await client.request({ method: 'PUT', path: 'users/42', body: { name: 'Bob Updated' } });
473
538
  await client.request({ method: 'DELETE', path: 'users/42' });
539
+
540
+ // Per-request timeout override (takes precedence over the global requestTimeout)
541
+ const report = await client.request<Report>(
542
+ { method: 'GET', path: 'reports/heavy' },
543
+ { timeout: 60_000 }, // 60s for this specific request
544
+ );
474
545
  ```
475
546
 
476
547
  ### Push events (main → renderer)
@@ -511,7 +582,7 @@ Multiple IPC requests in a single round-trip:
511
582
 
512
583
  ```ts
513
584
  const results = await client.batch([
514
- { method: 'GET', path: 'users/list' },
585
+ { method: 'GET', path: 'users/list', query: { role: 'admin' } },
515
586
  { method: 'GET', path: 'products/list' },
516
587
  { method: 'POST', path: 'orders/create', body: { ... } },
517
588
  ]);
@@ -571,3 +642,45 @@ src/
571
642
  ```
572
643
 
573
644
  Each `module/` folder is **self-contained** — the controller imports its own services directly, with no central declaration. `main.ts` only knows the lazy loading paths.
645
+
646
+ ---
647
+
648
+ ## Log level
649
+
650
+ By default, all framework logs are enabled (`debug` level). Control verbosity via `bootstrapApplication`:
651
+
652
+ ```ts
653
+ const noxApp = await bootstrapApplication({
654
+ logLevel: 'none', // 'debug' | 'info' | 'none'
655
+ });
656
+ ```
657
+
658
+ You can also pass an array of specific levels:
659
+
660
+ ```ts
661
+ bootstrapApplication({ logLevel: ['warn', 'error', 'critical'] });
662
+ ```
663
+
664
+ Or change it at runtime:
665
+
666
+ ```ts
667
+ import { Logger } from '@noxfly/noxus/main';
668
+
669
+ Logger.setLogLevel('info');
670
+ ```
671
+
672
+ ---
673
+
674
+ ## Testing
675
+
676
+ To reset the DI container between tests (avoids leaking singletons across test suites):
677
+
678
+ ```ts
679
+ import { resetRootInjector } from '@noxfly/noxus/main';
680
+
681
+ afterEach(() => {
682
+ resetRootInjector();
683
+ });
684
+ ```
685
+
686
+ This clears all bindings, singletons, and scoped instances from the root injector.
package/dist/child.d.mts CHANGED
@@ -109,6 +109,12 @@ declare class AppInjector {
109
109
  * The global root injector. All singletons live here.
110
110
  */
111
111
  declare const RootInjector: AppInjector;
112
+ /**
113
+ * Resets the root injector to a clean state.
114
+ * **Intended for testing only** — clears all bindings, singletons, and scoped instances
115
+ * so that each test can start from a fresh DI container without restarting the process.
116
+ */
117
+ declare function resetRootInjector(): void;
112
118
  /**
113
119
  * Convenience function: resolve a token from the root injector.
114
120
  */
@@ -340,4 +346,4 @@ declare namespace Logger {
340
346
  };
341
347
  }
342
348
 
343
- export { AppInjector, BadGatewayException, BadRequestException, ConflictException, ForbiddenException, type ForwardRefFn, ForwardReference, GatewayTimeoutException, HttpVersionNotSupportedException, type IBinding, Injectable, type InjectableOptions, InsufficientStorageException, InternalServerException, type Lifetime, type LogLevel, Logger, LoopDetectedException, type MaybeAsync, MethodNotAllowedException, NetworkAuthenticationRequiredException, NetworkConnectTimeoutException, NotAcceptableException, NotExtendedException, NotFoundException, NotImplementedException, PaymentRequiredException, RequestTimeoutException, ResponseException, RootInjector, ServiceUnavailableException, Token, type TokenKey, TooManyRequestsException, type Type, UnauthorizedException, UpgradeRequiredException, VariantAlsoNegotiatesException, forwardRef, inject };
349
+ export { AppInjector, BadGatewayException, BadRequestException, ConflictException, ForbiddenException, type ForwardRefFn, ForwardReference, GatewayTimeoutException, HttpVersionNotSupportedException, type IBinding, Injectable, type InjectableOptions, InsufficientStorageException, InternalServerException, type Lifetime, type LogLevel, Logger, LoopDetectedException, type MaybeAsync, MethodNotAllowedException, NetworkAuthenticationRequiredException, NetworkConnectTimeoutException, NotAcceptableException, NotExtendedException, NotFoundException, NotImplementedException, PaymentRequiredException, RequestTimeoutException, ResponseException, RootInjector, ServiceUnavailableException, Token, type TokenKey, TooManyRequestsException, type Type, UnauthorizedException, UpgradeRequiredException, VariantAlsoNegotiatesException, forwardRef, inject, resetRootInjector };
package/dist/child.d.ts CHANGED
@@ -109,6 +109,12 @@ declare class AppInjector {
109
109
  * The global root injector. All singletons live here.
110
110
  */
111
111
  declare const RootInjector: AppInjector;
112
+ /**
113
+ * Resets the root injector to a clean state.
114
+ * **Intended for testing only** — clears all bindings, singletons, and scoped instances
115
+ * so that each test can start from a fresh DI container without restarting the process.
116
+ */
117
+ declare function resetRootInjector(): void;
112
118
  /**
113
119
  * Convenience function: resolve a token from the root injector.
114
120
  */
@@ -340,4 +346,4 @@ declare namespace Logger {
340
346
  };
341
347
  }
342
348
 
343
- export { AppInjector, BadGatewayException, BadRequestException, ConflictException, ForbiddenException, type ForwardRefFn, ForwardReference, GatewayTimeoutException, HttpVersionNotSupportedException, type IBinding, Injectable, type InjectableOptions, InsufficientStorageException, InternalServerException, type Lifetime, type LogLevel, Logger, LoopDetectedException, type MaybeAsync, MethodNotAllowedException, NetworkAuthenticationRequiredException, NetworkConnectTimeoutException, NotAcceptableException, NotExtendedException, NotFoundException, NotImplementedException, PaymentRequiredException, RequestTimeoutException, ResponseException, RootInjector, ServiceUnavailableException, Token, type TokenKey, TooManyRequestsException, type Type, UnauthorizedException, UpgradeRequiredException, VariantAlsoNegotiatesException, forwardRef, inject };
349
+ export { AppInjector, BadGatewayException, BadRequestException, ConflictException, ForbiddenException, type ForwardRefFn, ForwardReference, GatewayTimeoutException, HttpVersionNotSupportedException, type IBinding, Injectable, type InjectableOptions, InsufficientStorageException, InternalServerException, type Lifetime, type LogLevel, Logger, LoopDetectedException, type MaybeAsync, MethodNotAllowedException, NetworkAuthenticationRequiredException, NetworkConnectTimeoutException, NotAcceptableException, NotExtendedException, NotFoundException, NotImplementedException, PaymentRequiredException, RequestTimeoutException, ResponseException, RootInjector, ServiceUnavailableException, Token, type TokenKey, TooManyRequestsException, type Type, UnauthorizedException, UpgradeRequiredException, VariantAlsoNegotiatesException, forwardRef, inject, resetRootInjector };