@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/dist/main.js CHANGED
@@ -86,113 +86,6 @@ var init_token = __esm({
86
86
  }
87
87
  });
88
88
 
89
- // src/DI/app-injector.ts
90
- function keyOf(k) {
91
- return k;
92
- }
93
- function inject(t) {
94
- return RootInjector.resolve(t);
95
- }
96
- var _AppInjector, AppInjector, RootInjector;
97
- var init_app_injector = __esm({
98
- "src/DI/app-injector.ts"() {
99
- "use strict";
100
- init_forward_ref();
101
- init_token();
102
- __name(keyOf, "keyOf");
103
- _AppInjector = class _AppInjector {
104
- constructor(name = null) {
105
- this.name = name;
106
- this.bindings = /* @__PURE__ */ new Map();
107
- this.singletons = /* @__PURE__ */ new Map();
108
- this.scoped = /* @__PURE__ */ new Map();
109
- }
110
- /**
111
- * Creates a child scope for per-request lifetime resolution.
112
- */
113
- createScope() {
114
- const scope = new _AppInjector();
115
- scope.bindings = this.bindings;
116
- scope.singletons = this.singletons;
117
- return scope;
118
- }
119
- /**
120
- * Registers a binding explicitly.
121
- */
122
- register(key, implementation, lifetime, deps = []) {
123
- const k = keyOf(key);
124
- if (!this.bindings.has(k)) {
125
- this.bindings.set(k, { lifetime, implementation, deps });
126
- }
127
- }
128
- /**
129
- * Resolves a dependency by token or class reference.
130
- */
131
- resolve(target) {
132
- if (target instanceof ForwardReference) {
133
- return this._resolveForwardRef(target);
134
- }
135
- const k = keyOf(target);
136
- const binding = this.bindings.get(k);
137
- if (!binding) {
138
- const name = target instanceof Token ? target.description : target.name ?? "unknown";
139
- throw new Error(
140
- `[Noxus DI] No binding found for "${name}".
141
- Did you forget to declare it in @Injectable({ deps }) or in bootstrapApplication({ singletons })?`
142
- );
143
- }
144
- switch (binding.lifetime) {
145
- case "transient":
146
- return this._instantiate(binding);
147
- case "scope": {
148
- if (this.scoped.has(k)) return this.scoped.get(k);
149
- const inst = this._instantiate(binding);
150
- this.scoped.set(k, inst);
151
- return inst;
152
- }
153
- case "singleton": {
154
- if (this.singletons.has(k)) return this.singletons.get(k);
155
- const inst = this._instantiate(binding);
156
- this.singletons.set(k, inst);
157
- if (binding.instance === void 0) {
158
- binding.instance = inst;
159
- }
160
- return inst;
161
- }
162
- }
163
- }
164
- // -------------------------------------------------------------------------
165
- _resolveForwardRef(ref) {
166
- return new Proxy({}, {
167
- get: /* @__PURE__ */ __name((_obj, prop, receiver) => {
168
- const realType = ref.forwardRefFn();
169
- const instance = this.resolve(realType);
170
- const value = Reflect.get(instance, prop, receiver);
171
- return typeof value === "function" ? value.bind(instance) : value;
172
- }, "get"),
173
- set: /* @__PURE__ */ __name((_obj, prop, value, receiver) => {
174
- const realType = ref.forwardRefFn();
175
- const instance = this.resolve(realType);
176
- return Reflect.set(instance, prop, value, receiver);
177
- }, "set"),
178
- getPrototypeOf: /* @__PURE__ */ __name(() => {
179
- const realType = ref.forwardRefFn();
180
- return realType.prototype;
181
- }, "getPrototypeOf")
182
- });
183
- }
184
- _instantiate(binding) {
185
- const resolvedDeps = binding.deps.map((dep) => this.resolve(dep));
186
- return new binding.implementation(...resolvedDeps);
187
- }
188
- };
189
- __name(_AppInjector, "AppInjector");
190
- AppInjector = _AppInjector;
191
- RootInjector = new AppInjector("root");
192
- __name(inject, "inject");
193
- }
194
- });
195
-
196
89
  // src/utils/logger.ts
197
90
  function getPrettyTimestamp() {
198
91
  const now = /* @__PURE__ */ new Date();
@@ -441,6 +334,10 @@ var init_logger = __esm({
441
334
  });
442
335
 
443
336
  // src/DI/injector-explorer.ts
337
+ var injector_explorer_exports = {};
338
+ __export(injector_explorer_exports, {
339
+ InjectorExplorer: () => InjectorExplorer
340
+ });
444
341
  var _InjectorExplorer, InjectorExplorer;
445
342
  var init_injector_explorer = __esm({
446
343
  "src/DI/injector-explorer.ts"() {
@@ -451,6 +348,13 @@ var init_injector_explorer = __esm({
451
348
  // -------------------------------------------------------------------------
452
349
  // Public API
453
350
  // -------------------------------------------------------------------------
351
+ /**
352
+ * Sets the callback used to register controllers.
353
+ * Must be called once before processPending (typically by bootstrapApplication).
354
+ */
355
+ static setControllerRegistrar(registrar) {
356
+ _InjectorExplorer.controllerRegistrar = registrar;
357
+ }
454
358
  static enqueue(reg) {
455
359
  if (_InjectorExplorer.processed && !_InjectorExplorer.accumulating) {
456
360
  _InjectorExplorer._registerImmediate(reg);
@@ -476,16 +380,37 @@ var init_injector_explorer = __esm({
476
380
  /**
477
381
  * Exits accumulation mode and flushes queued registrations
478
382
  * with the same two-phase guarantee as processPending.
383
+ * Serialised through a lock to prevent concurrent lazy loads from corrupting the queue.
479
384
  */
480
385
  static flushAccumulated(routeGuards = [], routeMiddlewares = [], pathPrefix = "") {
481
- _InjectorExplorer.accumulating = false;
482
- const queue = [..._InjectorExplorer.pending];
386
+ _InjectorExplorer.loadingLock = _InjectorExplorer.loadingLock.then(() => {
387
+ _InjectorExplorer.accumulating = false;
388
+ const queue = [..._InjectorExplorer.pending];
389
+ _InjectorExplorer.pending.length = 0;
390
+ _InjectorExplorer._phaseOne(queue);
391
+ for (const reg of queue) {
392
+ if (reg.isController) reg.pathPrefix = pathPrefix;
393
+ }
394
+ _InjectorExplorer._phaseTwo(queue, void 0, routeGuards, routeMiddlewares);
395
+ });
396
+ return _InjectorExplorer.loadingLock;
397
+ }
398
+ /**
399
+ * Returns a Promise that resolves once all pending flushAccumulated calls
400
+ * have completed. Useful for awaiting lazy-load serialisation.
401
+ */
402
+ static waitForFlush() {
403
+ return _InjectorExplorer.loadingLock;
404
+ }
405
+ /**
406
+ * Resets the explorer state. Intended for tests only.
407
+ */
408
+ static reset() {
483
409
  _InjectorExplorer.pending.length = 0;
484
- _InjectorExplorer._phaseOne(queue);
485
- for (const reg of queue) {
486
- if (reg.isController) reg.pathPrefix = pathPrefix;
487
- }
488
- _InjectorExplorer._phaseTwo(queue, void 0, routeGuards, routeMiddlewares);
410
+ _InjectorExplorer.processed = false;
411
+ _InjectorExplorer.accumulating = false;
412
+ _InjectorExplorer.loadingLock = Promise.resolve();
413
+ _InjectorExplorer.controllerRegistrar = null;
489
414
  }
490
415
  // -------------------------------------------------------------------------
491
416
  // Private helpers
@@ -496,8 +421,15 @@ var init_injector_explorer = __esm({
496
421
  RootInjector.register(reg.key, reg.implementation, reg.lifetime, reg.deps);
497
422
  }
498
423
  }
499
- /** Phase 2: resolve singletons and register controllers in the router. */
424
+ /** Phase 2: validate deps, resolve singletons and register controllers via the registrar callback. */
500
425
  static _phaseTwo(queue, overrides, routeGuards = [], routeMiddlewares = []) {
426
+ for (const reg of queue) {
427
+ for (const dep of reg.deps) {
428
+ if (!RootInjector.bindings.has(dep) && !RootInjector.singletons.has(dep)) {
429
+ Logger.warn(`[Noxus DI] "${reg.implementation.name}" declares dep "${dep.name ?? dep}" which has no binding`);
430
+ }
431
+ }
432
+ }
501
433
  for (const reg of queue) {
502
434
  if (overrides?.has(reg.key)) {
503
435
  const override = overrides.get(reg.key);
@@ -509,9 +441,15 @@ var init_injector_explorer = __esm({
509
441
  RootInjector.resolve(reg.key);
510
442
  }
511
443
  if (reg.isController) {
512
- const { Router: Router2 } = (init_router(), __toCommonJS(router_exports));
513
- const router = RootInjector.resolve(Router2);
514
- router.registerController(reg.implementation, reg.pathPrefix ?? "", routeGuards, routeMiddlewares);
444
+ if (!_InjectorExplorer.controllerRegistrar) {
445
+ throw new Error("[Noxus DI] No controller registrar set. Call InjectorExplorer.setControllerRegistrar() before processing.");
446
+ }
447
+ _InjectorExplorer.controllerRegistrar(
448
+ reg.implementation,
449
+ reg.pathPrefix ?? "",
450
+ routeGuards,
451
+ routeMiddlewares
452
+ );
515
453
  } else if (reg.lifetime !== "singleton") {
516
454
  Logger.log(`Registered ${reg.implementation.name} as ${reg.lifetime}`);
517
455
  }
@@ -522,10 +460,8 @@ var init_injector_explorer = __esm({
522
460
  if (reg.lifetime === "singleton") {
523
461
  RootInjector.resolve(reg.key);
524
462
  }
525
- if (reg.isController) {
526
- const { Router: Router2 } = (init_router(), __toCommonJS(router_exports));
527
- const router = RootInjector.resolve(Router2);
528
- router.registerController(reg.implementation);
463
+ if (reg.isController && _InjectorExplorer.controllerRegistrar) {
464
+ _InjectorExplorer.controllerRegistrar(reg.implementation, "", [], []);
529
465
  }
530
466
  }
531
467
  };
@@ -533,11 +469,193 @@ var init_injector_explorer = __esm({
533
469
  _InjectorExplorer.pending = [];
534
470
  _InjectorExplorer.processed = false;
535
471
  _InjectorExplorer.accumulating = false;
472
+ _InjectorExplorer.loadingLock = Promise.resolve();
473
+ _InjectorExplorer.controllerRegistrar = null;
536
474
  InjectorExplorer = _InjectorExplorer;
537
475
  }
538
476
  });
539
477
 
478
+ // src/DI/app-injector.ts
479
+ function keyOf(k) {
480
+ return k;
481
+ }
482
+ function resetRootInjector() {
483
+ RootInjector.bindings.clear();
484
+ RootInjector.singletons.clear();
485
+ RootInjector.scoped.clear();
486
+ const { InjectorExplorer: InjectorExplorer2 } = (init_injector_explorer(), __toCommonJS(injector_explorer_exports));
487
+ InjectorExplorer2.reset();
488
+ }
489
+ function inject(t) {
490
+ return RootInjector.resolve(t);
491
+ }
492
+ var _AppInjector, AppInjector, RootInjector;
493
+ var init_app_injector = __esm({
494
+ "src/DI/app-injector.ts"() {
495
+ "use strict";
496
+ init_forward_ref();
497
+ init_token();
498
+ __name(keyOf, "keyOf");
499
+ _AppInjector = class _AppInjector {
500
+ constructor(name = null) {
501
+ this.name = name;
502
+ this.bindings = /* @__PURE__ */ new Map();
503
+ this.singletons = /* @__PURE__ */ new Map();
504
+ this.scoped = /* @__PURE__ */ new Map();
505
+ }
506
+ /**
507
+ * Creates a child scope for per-request lifetime resolution.
508
+ */
509
+ createScope() {
510
+ const scope = new _AppInjector();
511
+ scope.bindings = this.bindings;
512
+ scope.singletons = this.singletons;
513
+ return scope;
514
+ }
515
+ /**
516
+ * Registers a binding explicitly.
517
+ */
518
+ register(key, implementation, lifetime, deps = []) {
519
+ const k = keyOf(key);
520
+ if (!this.bindings.has(k)) {
521
+ this.bindings.set(k, { lifetime, implementation, deps });
522
+ }
523
+ }
524
+ /**
525
+ * Resolves a dependency by token or class reference.
526
+ */
527
+ resolve(target) {
528
+ if (target instanceof ForwardReference) {
529
+ return this._resolveForwardRef(target);
530
+ }
531
+ const k = keyOf(target);
532
+ if (this.singletons.has(k)) {
533
+ return this.singletons.get(k);
534
+ }
535
+ const binding = this.bindings.get(k);
536
+ if (!binding) {
537
+ const name = target instanceof Token ? target.description : target.name ?? "unknown";
538
+ throw new Error(
539
+ `[Noxus DI] No binding found for "${name}".
540
+ Did you forget to declare it in @Injectable({ deps }) or in bootstrapApplication({ singletons })?`
541
+ );
542
+ }
543
+ switch (binding.lifetime) {
544
+ case "transient":
545
+ return this._instantiate(binding);
546
+ case "scope": {
547
+ if (this.scoped.has(k)) return this.scoped.get(k);
548
+ const inst = this._instantiate(binding);
549
+ this.scoped.set(k, inst);
550
+ return inst;
551
+ }
552
+ case "singleton": {
553
+ if (this.singletons.has(k)) return this.singletons.get(k);
554
+ const inst = this._instantiate(binding);
555
+ this.singletons.set(k, inst);
556
+ if (binding.instance === void 0) {
557
+ binding.instance = inst;
558
+ }
559
+ return inst;
560
+ }
561
+ }
562
+ }
563
+ // -------------------------------------------------------------------------
564
+ _resolveForwardRef(ref) {
565
+ let resolved;
566
+ return new Proxy({}, {
567
+ get: /* @__PURE__ */ __name((_obj, prop, receiver) => {
568
+ resolved ?? (resolved = this.resolve(ref.forwardRefFn()));
569
+ const value = Reflect.get(resolved, prop, receiver);
570
+ return typeof value === "function" ? value.bind(resolved) : value;
571
+ }, "get"),
572
+ set: /* @__PURE__ */ __name((_obj, prop, value, receiver) => {
573
+ resolved ?? (resolved = this.resolve(ref.forwardRefFn()));
574
+ return Reflect.set(resolved, prop, value, receiver);
575
+ }, "set"),
576
+ getPrototypeOf: /* @__PURE__ */ __name(() => {
577
+ resolved ?? (resolved = this.resolve(ref.forwardRefFn()));
578
+ return Object.getPrototypeOf(resolved);
579
+ }, "getPrototypeOf")
580
+ });
581
+ }
582
+ _instantiate(binding) {
583
+ const resolvedDeps = binding.deps.map((dep) => this.resolve(dep));
584
+ return new binding.implementation(...resolvedDeps);
585
+ }
586
+ };
587
+ __name(_AppInjector, "AppInjector");
588
+ AppInjector = _AppInjector;
589
+ RootInjector = new AppInjector("root");
590
+ __name(resetRootInjector, "resetRootInjector");
591
+ __name(inject, "inject");
592
+ }
593
+ });
594
+
595
+ // src/main.ts
596
+ var main_exports = {};
597
+ __export(main_exports, {
598
+ AppInjector: () => AppInjector,
599
+ BadGatewayException: () => BadGatewayException,
600
+ BadRequestException: () => BadRequestException,
601
+ ConflictException: () => ConflictException,
602
+ Controller: () => Controller,
603
+ Delete: () => Delete,
604
+ ForbiddenException: () => ForbiddenException,
605
+ ForwardReference: () => ForwardReference,
606
+ GatewayTimeoutException: () => GatewayTimeoutException,
607
+ Get: () => Get,
608
+ HttpVersionNotSupportedException: () => HttpVersionNotSupportedException,
609
+ Injectable: () => Injectable,
610
+ InsufficientStorageException: () => InsufficientStorageException,
611
+ InternalServerException: () => InternalServerException,
612
+ Logger: () => Logger,
613
+ LoopDetectedException: () => LoopDetectedException,
614
+ MethodNotAllowedException: () => MethodNotAllowedException,
615
+ NetworkAuthenticationRequiredException: () => NetworkAuthenticationRequiredException,
616
+ NetworkConnectTimeoutException: () => NetworkConnectTimeoutException,
617
+ NotAcceptableException: () => NotAcceptableException,
618
+ NotExtendedException: () => NotExtendedException,
619
+ NotFoundException: () => NotFoundException,
620
+ NotImplementedException: () => NotImplementedException,
621
+ NoxApp: () => NoxApp,
622
+ NoxSocket: () => NoxSocket,
623
+ Patch: () => Patch,
624
+ PaymentRequiredException: () => PaymentRequiredException,
625
+ Post: () => Post,
626
+ Put: () => Put,
627
+ RENDERER_EVENT_TYPE: () => RENDERER_EVENT_TYPE,
628
+ Request: () => Request,
629
+ RequestTimeoutException: () => RequestTimeoutException,
630
+ ResponseException: () => ResponseException,
631
+ RootInjector: () => RootInjector,
632
+ Router: () => Router,
633
+ ServiceUnavailableException: () => ServiceUnavailableException,
634
+ Token: () => Token,
635
+ TooManyRequestsException: () => TooManyRequestsException,
636
+ UnauthorizedException: () => UnauthorizedException,
637
+ UpgradeRequiredException: () => UpgradeRequiredException,
638
+ VariantAlsoNegotiatesException: () => VariantAlsoNegotiatesException,
639
+ WindowManager: () => WindowManager,
640
+ bootstrapApplication: () => bootstrapApplication,
641
+ createRendererEventMessage: () => createRendererEventMessage,
642
+ defineRoutes: () => defineRoutes,
643
+ forwardRef: () => forwardRef,
644
+ getControllerMetadata: () => getControllerMetadata,
645
+ getRouteMetadata: () => getRouteMetadata,
646
+ inject: () => inject,
647
+ isAtomicHttpMethod: () => isAtomicHttpMethod,
648
+ isRendererEventMessage: () => isRendererEventMessage,
649
+ resetRootInjector: () => resetRootInjector,
650
+ token: () => token
651
+ });
652
+ module.exports = __toCommonJS(main_exports);
653
+ init_app_injector();
654
+ init_token();
655
+
540
656
  // src/decorators/controller.decorator.ts
657
+ init_injector_explorer();
658
+ var controllerMetaMap = /* @__PURE__ */ new WeakMap();
541
659
  function Controller(options = {}) {
542
660
  return (target) => {
543
661
  const meta = {
@@ -553,21 +671,15 @@ function Controller(options = {}) {
553
671
  });
554
672
  };
555
673
  }
674
+ __name(Controller, "Controller");
556
675
  function getControllerMetadata(target) {
557
676
  return controllerMetaMap.get(target);
558
677
  }
559
- var controllerMetaMap;
560
- var init_controller_decorator = __esm({
561
- "src/decorators/controller.decorator.ts"() {
562
- "use strict";
563
- init_injector_explorer();
564
- controllerMetaMap = /* @__PURE__ */ new WeakMap();
565
- __name(Controller, "Controller");
566
- __name(getControllerMetadata, "getControllerMetadata");
567
- }
568
- });
678
+ __name(getControllerMetadata, "getControllerMetadata");
569
679
 
570
680
  // src/decorators/injectable.decorator.ts
681
+ init_injector_explorer();
682
+ init_token();
571
683
  function Injectable(options = {}) {
572
684
  const { lifetime = "scope", deps = [] } = options;
573
685
  return (target) => {
@@ -584,19 +696,15 @@ function Injectable(options = {}) {
584
696
  });
585
697
  };
586
698
  }
587
- var init_injectable_decorator = __esm({
588
- "src/decorators/injectable.decorator.ts"() {
589
- "use strict";
590
- init_injector_explorer();
591
- init_token();
592
- __name(Injectable, "Injectable");
593
- }
594
- });
699
+ __name(Injectable, "Injectable");
595
700
 
596
701
  // src/decorators/method.decorator.ts
702
+ var ATOMIC_METHODS = /* @__PURE__ */ new Set(["GET", "POST", "PUT", "PATCH", "DELETE"]);
597
703
  function isAtomicHttpMethod(m) {
598
704
  return typeof m === "string" && ATOMIC_METHODS.has(m);
599
705
  }
706
+ __name(isAtomicHttpMethod, "isAtomicHttpMethod");
707
+ var routeMetaMap = /* @__PURE__ */ new WeakMap();
600
708
  function createRouteDecorator(verb) {
601
709
  return (path2, options = {}) => {
602
710
  return (target, propertyKey) => {
@@ -613,399 +721,416 @@ function createRouteDecorator(verb) {
613
721
  };
614
722
  };
615
723
  }
724
+ __name(createRouteDecorator, "createRouteDecorator");
616
725
  function getRouteMetadata(target) {
617
726
  return routeMetaMap.get(target) ?? [];
618
727
  }
619
- var ATOMIC_METHODS, routeMetaMap, Get, Post, Put, Patch, Delete;
620
- var init_method_decorator = __esm({
621
- "src/decorators/method.decorator.ts"() {
622
- "use strict";
623
- ATOMIC_METHODS = /* @__PURE__ */ new Set(["GET", "POST", "PUT", "PATCH", "DELETE"]);
624
- __name(isAtomicHttpMethod, "isAtomicHttpMethod");
625
- routeMetaMap = /* @__PURE__ */ new WeakMap();
626
- __name(createRouteDecorator, "createRouteDecorator");
627
- __name(getRouteMetadata, "getRouteMetadata");
628
- Get = createRouteDecorator("GET");
629
- Post = createRouteDecorator("POST");
630
- Put = createRouteDecorator("PUT");
631
- Patch = createRouteDecorator("PATCH");
632
- Delete = createRouteDecorator("DELETE");
633
- }
634
- });
728
+ __name(getRouteMetadata, "getRouteMetadata");
729
+ var Get = createRouteDecorator("GET");
730
+ var Post = createRouteDecorator("POST");
731
+ var Put = createRouteDecorator("PUT");
732
+ var Patch = createRouteDecorator("PATCH");
733
+ var Delete = createRouteDecorator("DELETE");
734
+
735
+ // src/internal/router.ts
736
+ init_injector_explorer();
737
+ init_logger();
635
738
 
636
739
  // src/utils/radix-tree.ts
637
- var _RadixNode, RadixNode, _RadixTree, RadixTree;
638
- var init_radix_tree = __esm({
639
- "src/utils/radix-tree.ts"() {
640
- "use strict";
641
- _RadixNode = class _RadixNode {
642
- /**
643
- * Creates a new RadixNode.
644
- * @param segment - The segment of the path this node represents.
645
- */
646
- constructor(segment) {
647
- this.children = [];
648
- this.segment = segment;
649
- this.isParam = segment.startsWith(":");
650
- if (this.isParam) {
651
- this.paramName = segment.slice(1);
652
- }
653
- }
654
- /**
655
- * Matches a child node against a given segment.
656
- * This method checks if the segment matches any of the children nodes.
657
- * @param segment - The segment to match against the children of this node.
658
- * @returns A child node that matches the segment, or undefined if no match is found.
659
- */
660
- matchChild(segment) {
661
- for (const child of this.children) {
662
- if (child.isParam || segment.startsWith(child.segment))
663
- return child;
664
- }
665
- return void 0;
666
- }
667
- /**
668
- * Finds a child node that matches the segment exactly.
669
- * This method checks if there is a child node that matches the segment exactly.
670
- * @param segment - The segment to find an exact match for among the children of this node.
671
- * @returns A child node that matches the segment exactly, or undefined if no match is found.
672
- */
673
- findExactChild(segment) {
674
- return this.children.find((c) => c.segment === segment);
675
- }
676
- /**
677
- * Adds a child node to this node's children.
678
- * This method adds a new child node to the list of children for this node.
679
- * @param node - The child node to add to this node's children.
680
- */
681
- addChild(node) {
682
- this.children.push(node);
683
- }
684
- };
685
- __name(_RadixNode, "RadixNode");
686
- RadixNode = _RadixNode;
687
- _RadixTree = class _RadixTree {
688
- constructor() {
689
- this.root = new RadixNode("");
740
+ var _RadixNode = class _RadixNode {
741
+ /**
742
+ * Creates a new RadixNode.
743
+ * @param segment - The segment of the path this node represents.
744
+ */
745
+ constructor(segment) {
746
+ this.children = [];
747
+ this.segment = segment;
748
+ this.isParam = segment.startsWith(":");
749
+ if (this.isParam) {
750
+ this.paramName = segment.slice(1);
751
+ }
752
+ }
753
+ /**
754
+ * Matches a child node against a given segment.
755
+ * This method checks if the segment matches any of the children nodes.
756
+ * @param segment - The segment to match against the children of this node.
757
+ * @returns A child node that matches the segment, or undefined if no match is found.
758
+ */
759
+ matchChild(segment) {
760
+ for (const child of this.children) {
761
+ if (child.isParam || segment.startsWith(child.segment))
762
+ return child;
763
+ }
764
+ return void 0;
765
+ }
766
+ /**
767
+ * Finds a child node that matches the segment exactly.
768
+ * This method checks if there is a child node that matches the segment exactly.
769
+ * @param segment - The segment to find an exact match for among the children of this node.
770
+ * @returns A child node that matches the segment exactly, or undefined if no match is found.
771
+ */
772
+ findExactChild(segment) {
773
+ return this.children.find((c) => c.segment === segment);
774
+ }
775
+ /**
776
+ * Adds a child node to this node's children.
777
+ * This method adds a new child node to the list of children for this node.
778
+ * @param node - The child node to add to this node's children.
779
+ */
780
+ addChild(node) {
781
+ this.children.push(node);
782
+ }
783
+ };
784
+ __name(_RadixNode, "RadixNode");
785
+ var RadixNode = _RadixNode;
786
+ var _RadixTree = class _RadixTree {
787
+ constructor() {
788
+ this.root = new RadixNode("");
789
+ }
790
+ /**
791
+ * Inserts a path and its associated value into the Radix Tree.
792
+ * This method normalizes the path and inserts it into the tree, associating it with
793
+ * @param path - The path to insert into the tree.
794
+ * @param value - The value to associate with the path.
795
+ */
796
+ insert(path2, value) {
797
+ const segments = this.normalize(path2);
798
+ this.insertRecursive(this.root, segments, value);
799
+ }
800
+ /**
801
+ * Recursively inserts a path into the Radix Tree.
802
+ * This method traverses the tree and inserts the segments of the path, creating new nodes
803
+ * @param node - The node to start inserting from.
804
+ * @param segments - The segments of the path to insert.
805
+ * @param value - The value to associate with the path.
806
+ */
807
+ insertRecursive(node, segments, value) {
808
+ if (segments.length === 0) {
809
+ node.value = value;
810
+ return;
811
+ }
812
+ const segment = segments[0] ?? "";
813
+ let child = node.children.find(
814
+ (c) => c.isParam === segment.startsWith(":") && (c.isParam || c.segment === segment)
815
+ );
816
+ if (!child) {
817
+ child = new RadixNode(segment);
818
+ node.addChild(child);
819
+ }
820
+ this.insertRecursive(child, segments.slice(1), value);
821
+ }
822
+ /**
823
+ * Searches for a path in the Radix Tree.
824
+ * This method normalizes the path and searches for it in the tree, returning the node
825
+ * @param path - The path to search for in the Radix Tree.
826
+ * @returns An ISearchResult containing the node and parameters if a match is found, otherwise undefined.
827
+ */
828
+ search(path2) {
829
+ const segments = this.normalize(path2);
830
+ return this.searchRecursive(this.root, segments, {});
831
+ }
832
+ collectValues(node, values = []) {
833
+ if (!node) {
834
+ node = this.root;
835
+ }
836
+ if (node.value !== void 0) {
837
+ values.push(node.value);
838
+ }
839
+ for (const child of node.children) {
840
+ this.collectValues(child, values);
841
+ }
842
+ return values;
843
+ }
844
+ /**
845
+ * Recursively searches for a path in the Radix Tree.
846
+ * This method traverses the tree and searches for the segments of the path, collecting parameters
847
+ * @param node - The node to start searching from.
848
+ * @param segments - The segments of the path to search for.
849
+ * @param params - The parameters collected during the search.
850
+ * @returns An ISearchResult containing the node and parameters if a match is found, otherwise undefined.
851
+ */
852
+ searchRecursive(node, segments, params) {
853
+ if (segments.length === 0) {
854
+ if (node.value !== void 0) {
855
+ return {
856
+ node,
857
+ params
858
+ };
690
859
  }
691
- /**
692
- * Inserts a path and its associated value into the Radix Tree.
693
- * This method normalizes the path and inserts it into the tree, associating it with
694
- * @param path - The path to insert into the tree.
695
- * @param value - The value to associate with the path.
696
- */
697
- insert(path2, value) {
698
- const segments = this.normalize(path2);
699
- this.insertRecursive(this.root, segments, value);
860
+ return void 0;
861
+ }
862
+ const [segment, ...rest] = segments;
863
+ const staticChildren = [];
864
+ const paramChildren = [];
865
+ for (const child of node.children) {
866
+ if (child.isParam) {
867
+ paramChildren.push(child);
868
+ } else if (segment === child.segment) {
869
+ staticChildren.push(child);
700
870
  }
701
- /**
702
- * Recursively inserts a path into the Radix Tree.
703
- * This method traverses the tree and inserts the segments of the path, creating new nodes
704
- * @param node - The node to start inserting from.
705
- * @param segments - The segments of the path to insert.
706
- * @param value - The value to associate with the path.
707
- */
708
- insertRecursive(node, segments, value) {
709
- if (segments.length === 0) {
710
- node.value = value;
711
- return;
712
- }
713
- const segment = segments[0] ?? "";
714
- let child = node.children.find(
715
- (c) => c.isParam === segment.startsWith(":") && (c.isParam || c.segment === segment)
716
- );
717
- if (!child) {
718
- child = new RadixNode(segment);
719
- node.addChild(child);
871
+ }
872
+ for (const child of staticChildren) {
873
+ if (rest.length === 0) {
874
+ if (child.value !== void 0 || child.children.length > 0) {
875
+ return { node: child, params };
720
876
  }
721
- this.insertRecursive(child, segments.slice(1), value);
722
- }
723
- /**
724
- * Searches for a path in the Radix Tree.
725
- * This method normalizes the path and searches for it in the tree, returning the node
726
- * @param path - The path to search for in the Radix Tree.
727
- * @returns An ISearchResult containing the node and parameters if a match is found, otherwise undefined.
728
- */
729
- search(path2) {
730
- const segments = this.normalize(path2);
731
- return this.searchRecursive(this.root, segments, {});
732
877
  }
733
- /**
734
- * Recursively searches for a path in the Radix Tree.
735
- * This method traverses the tree and searches for the segments of the path, collecting parameters
736
- * @param node - The node to start searching from.
737
- * @param segments - The segments of the path to search for.
738
- * @param params - The parameters collected during the search.
739
- * @returns An ISearchResult containing the node and parameters if a match is found, otherwise undefined.
740
- */
741
- searchRecursive(node, segments, params) {
742
- if (segments.length === 0) {
743
- if (node.value !== void 0) {
744
- return {
745
- node,
746
- params
747
- };
748
- }
749
- return void 0;
750
- }
751
- const [segment, ...rest] = segments;
752
- for (const child of node.children) {
753
- if (child.isParam) {
754
- const paramName = child.paramName;
755
- const childParams = {
756
- ...params,
757
- [paramName]: segment ?? ""
758
- };
759
- if (rest.length === 0) {
760
- return {
761
- node: child,
762
- params: childParams
763
- };
764
- }
765
- const result = this.searchRecursive(child, rest, childParams);
766
- if (result)
767
- return result;
768
- } else if (segment === child.segment) {
769
- if (rest.length === 0) {
770
- return {
771
- node: child,
772
- params
773
- };
774
- }
775
- const result = this.searchRecursive(child, rest, params);
776
- if (result)
777
- return result;
778
- }
878
+ const result = this.searchRecursive(child, rest, params);
879
+ if (result) return result;
880
+ }
881
+ for (const child of paramChildren) {
882
+ const paramName = child.paramName;
883
+ const childParams = {
884
+ ...params,
885
+ [paramName]: segment ?? ""
886
+ };
887
+ if (rest.length === 0) {
888
+ if (child.value !== void 0 || child.children.length > 0) {
889
+ return { node: child, params: childParams };
779
890
  }
780
- return void 0;
781
- }
782
- /**
783
- * Normalizes a path into an array of segments.
784
- * This method removes leading and trailing slashes, splits the path by slashes, and
785
- * @param path - The path to normalize.
786
- * @returns An array of normalized path segments.
787
- */
788
- normalize(path2) {
789
- const segments = path2.replace(/^\/+|\/+$/g, "").split("/").filter(Boolean);
790
- return ["", ...segments];
791
891
  }
792
- };
793
- __name(_RadixTree, "RadixTree");
794
- RadixTree = _RadixTree;
892
+ const result = this.searchRecursive(child, rest, childParams);
893
+ if (result) return result;
894
+ }
895
+ return void 0;
795
896
  }
796
- });
897
+ /**
898
+ * Normalizes a path into an array of segments.
899
+ * This method removes leading and trailing slashes, splits the path by slashes, and
900
+ * @param path - The path to normalize.
901
+ * @returns An array of normalized path segments.
902
+ */
903
+ normalize(path2) {
904
+ const segments = path2.replace(/^\/+|\/+$/g, "").split("/").filter(Boolean);
905
+ return ["", ...segments];
906
+ }
907
+ };
908
+ __name(_RadixTree, "RadixTree");
909
+ var RadixTree = _RadixTree;
797
910
 
798
911
  // src/internal/exceptions.ts
799
- var _ResponseException, ResponseException, _BadRequestException, BadRequestException, _UnauthorizedException, UnauthorizedException, _PaymentRequiredException, PaymentRequiredException, _ForbiddenException, ForbiddenException, _NotFoundException, NotFoundException, _MethodNotAllowedException, MethodNotAllowedException, _NotAcceptableException, NotAcceptableException, _RequestTimeoutException, RequestTimeoutException, _ConflictException, ConflictException, _UpgradeRequiredException, UpgradeRequiredException, _TooManyRequestsException, TooManyRequestsException, _InternalServerException, InternalServerException, _NotImplementedException, NotImplementedException, _BadGatewayException, BadGatewayException, _ServiceUnavailableException, ServiceUnavailableException, _GatewayTimeoutException, GatewayTimeoutException, _HttpVersionNotSupportedException, HttpVersionNotSupportedException, _VariantAlsoNegotiatesException, VariantAlsoNegotiatesException, _InsufficientStorageException, InsufficientStorageException, _LoopDetectedException, LoopDetectedException, _NotExtendedException, NotExtendedException, _NetworkAuthenticationRequiredException, NetworkAuthenticationRequiredException, _NetworkConnectTimeoutException, NetworkConnectTimeoutException;
800
- var init_exceptions = __esm({
801
- "src/internal/exceptions.ts"() {
802
- "use strict";
803
- _ResponseException = class _ResponseException extends Error {
804
- constructor(statusOrMessage, message) {
805
- let statusCode;
806
- if (typeof statusOrMessage === "number") {
807
- statusCode = statusOrMessage;
808
- } else if (typeof statusOrMessage === "string") {
809
- message = statusOrMessage;
810
- }
811
- super(message ?? "");
812
- this.status = 0;
813
- if (statusCode !== void 0) {
814
- this.status = statusCode;
815
- }
816
- this.name = this.constructor.name.replace(/([A-Z])/g, " $1");
817
- }
818
- };
819
- __name(_ResponseException, "ResponseException");
820
- ResponseException = _ResponseException;
821
- _BadRequestException = class _BadRequestException extends ResponseException {
822
- constructor() {
823
- super(...arguments);
824
- this.status = 400;
825
- }
826
- };
827
- __name(_BadRequestException, "BadRequestException");
828
- BadRequestException = _BadRequestException;
829
- _UnauthorizedException = class _UnauthorizedException extends ResponseException {
830
- constructor() {
831
- super(...arguments);
832
- this.status = 401;
833
- }
834
- };
835
- __name(_UnauthorizedException, "UnauthorizedException");
836
- UnauthorizedException = _UnauthorizedException;
837
- _PaymentRequiredException = class _PaymentRequiredException extends ResponseException {
838
- constructor() {
839
- super(...arguments);
840
- this.status = 402;
841
- }
842
- };
843
- __name(_PaymentRequiredException, "PaymentRequiredException");
844
- PaymentRequiredException = _PaymentRequiredException;
845
- _ForbiddenException = class _ForbiddenException extends ResponseException {
846
- constructor() {
847
- super(...arguments);
848
- this.status = 403;
849
- }
850
- };
851
- __name(_ForbiddenException, "ForbiddenException");
852
- ForbiddenException = _ForbiddenException;
853
- _NotFoundException = class _NotFoundException extends ResponseException {
854
- constructor() {
855
- super(...arguments);
856
- this.status = 404;
857
- }
858
- };
859
- __name(_NotFoundException, "NotFoundException");
860
- NotFoundException = _NotFoundException;
861
- _MethodNotAllowedException = class _MethodNotAllowedException extends ResponseException {
862
- constructor() {
863
- super(...arguments);
864
- this.status = 405;
865
- }
866
- };
867
- __name(_MethodNotAllowedException, "MethodNotAllowedException");
868
- MethodNotAllowedException = _MethodNotAllowedException;
869
- _NotAcceptableException = class _NotAcceptableException extends ResponseException {
870
- constructor() {
871
- super(...arguments);
872
- this.status = 406;
873
- }
874
- };
875
- __name(_NotAcceptableException, "NotAcceptableException");
876
- NotAcceptableException = _NotAcceptableException;
877
- _RequestTimeoutException = class _RequestTimeoutException extends ResponseException {
878
- constructor() {
879
- super(...arguments);
880
- this.status = 408;
881
- }
882
- };
883
- __name(_RequestTimeoutException, "RequestTimeoutException");
884
- RequestTimeoutException = _RequestTimeoutException;
885
- _ConflictException = class _ConflictException extends ResponseException {
886
- constructor() {
887
- super(...arguments);
888
- this.status = 409;
889
- }
890
- };
891
- __name(_ConflictException, "ConflictException");
892
- ConflictException = _ConflictException;
893
- _UpgradeRequiredException = class _UpgradeRequiredException extends ResponseException {
894
- constructor() {
895
- super(...arguments);
896
- this.status = 426;
897
- }
898
- };
899
- __name(_UpgradeRequiredException, "UpgradeRequiredException");
900
- UpgradeRequiredException = _UpgradeRequiredException;
901
- _TooManyRequestsException = class _TooManyRequestsException extends ResponseException {
902
- constructor() {
903
- super(...arguments);
904
- this.status = 429;
905
- }
906
- };
907
- __name(_TooManyRequestsException, "TooManyRequestsException");
908
- TooManyRequestsException = _TooManyRequestsException;
909
- _InternalServerException = class _InternalServerException extends ResponseException {
910
- constructor() {
911
- super(...arguments);
912
- this.status = 500;
913
- }
914
- };
915
- __name(_InternalServerException, "InternalServerException");
916
- InternalServerException = _InternalServerException;
917
- _NotImplementedException = class _NotImplementedException extends ResponseException {
918
- constructor() {
919
- super(...arguments);
920
- this.status = 501;
921
- }
922
- };
923
- __name(_NotImplementedException, "NotImplementedException");
924
- NotImplementedException = _NotImplementedException;
925
- _BadGatewayException = class _BadGatewayException extends ResponseException {
926
- constructor() {
927
- super(...arguments);
928
- this.status = 502;
929
- }
930
- };
931
- __name(_BadGatewayException, "BadGatewayException");
932
- BadGatewayException = _BadGatewayException;
933
- _ServiceUnavailableException = class _ServiceUnavailableException extends ResponseException {
934
- constructor() {
935
- super(...arguments);
936
- this.status = 503;
937
- }
938
- };
939
- __name(_ServiceUnavailableException, "ServiceUnavailableException");
940
- ServiceUnavailableException = _ServiceUnavailableException;
941
- _GatewayTimeoutException = class _GatewayTimeoutException extends ResponseException {
942
- constructor() {
943
- super(...arguments);
944
- this.status = 504;
945
- }
946
- };
947
- __name(_GatewayTimeoutException, "GatewayTimeoutException");
948
- GatewayTimeoutException = _GatewayTimeoutException;
949
- _HttpVersionNotSupportedException = class _HttpVersionNotSupportedException extends ResponseException {
950
- constructor() {
951
- super(...arguments);
952
- this.status = 505;
953
- }
954
- };
955
- __name(_HttpVersionNotSupportedException, "HttpVersionNotSupportedException");
956
- HttpVersionNotSupportedException = _HttpVersionNotSupportedException;
957
- _VariantAlsoNegotiatesException = class _VariantAlsoNegotiatesException extends ResponseException {
958
- constructor() {
959
- super(...arguments);
960
- this.status = 506;
961
- }
962
- };
963
- __name(_VariantAlsoNegotiatesException, "VariantAlsoNegotiatesException");
964
- VariantAlsoNegotiatesException = _VariantAlsoNegotiatesException;
965
- _InsufficientStorageException = class _InsufficientStorageException extends ResponseException {
966
- constructor() {
967
- super(...arguments);
968
- this.status = 507;
969
- }
970
- };
971
- __name(_InsufficientStorageException, "InsufficientStorageException");
972
- InsufficientStorageException = _InsufficientStorageException;
973
- _LoopDetectedException = class _LoopDetectedException extends ResponseException {
974
- constructor() {
975
- super(...arguments);
976
- this.status = 508;
977
- }
978
- };
979
- __name(_LoopDetectedException, "LoopDetectedException");
980
- LoopDetectedException = _LoopDetectedException;
981
- _NotExtendedException = class _NotExtendedException extends ResponseException {
982
- constructor() {
983
- super(...arguments);
984
- this.status = 510;
985
- }
986
- };
987
- __name(_NotExtendedException, "NotExtendedException");
988
- NotExtendedException = _NotExtendedException;
989
- _NetworkAuthenticationRequiredException = class _NetworkAuthenticationRequiredException extends ResponseException {
990
- constructor() {
991
- super(...arguments);
992
- this.status = 511;
993
- }
994
- };
995
- __name(_NetworkAuthenticationRequiredException, "NetworkAuthenticationRequiredException");
996
- NetworkAuthenticationRequiredException = _NetworkAuthenticationRequiredException;
997
- _NetworkConnectTimeoutException = class _NetworkConnectTimeoutException extends ResponseException {
998
- constructor() {
999
- super(...arguments);
1000
- this.status = 599;
1001
- }
1002
- };
1003
- __name(_NetworkConnectTimeoutException, "NetworkConnectTimeoutException");
1004
- NetworkConnectTimeoutException = _NetworkConnectTimeoutException;
912
+ var _ResponseException = class _ResponseException extends Error {
913
+ constructor(statusOrMessage, message) {
914
+ let statusCode;
915
+ if (typeof statusOrMessage === "number") {
916
+ statusCode = statusOrMessage;
917
+ } else if (typeof statusOrMessage === "string") {
918
+ message = statusOrMessage;
919
+ }
920
+ super(message ?? "");
921
+ this.status = 0;
922
+ if (statusCode !== void 0) {
923
+ this.status = statusCode;
924
+ }
925
+ this.name = this.constructor.name.replace(/([A-Z])/g, " $1");
926
+ }
927
+ };
928
+ __name(_ResponseException, "ResponseException");
929
+ var ResponseException = _ResponseException;
930
+ var _BadRequestException = class _BadRequestException extends ResponseException {
931
+ constructor() {
932
+ super(...arguments);
933
+ this.status = 400;
934
+ }
935
+ };
936
+ __name(_BadRequestException, "BadRequestException");
937
+ var BadRequestException = _BadRequestException;
938
+ var _UnauthorizedException = class _UnauthorizedException extends ResponseException {
939
+ constructor() {
940
+ super(...arguments);
941
+ this.status = 401;
942
+ }
943
+ };
944
+ __name(_UnauthorizedException, "UnauthorizedException");
945
+ var UnauthorizedException = _UnauthorizedException;
946
+ var _PaymentRequiredException = class _PaymentRequiredException extends ResponseException {
947
+ constructor() {
948
+ super(...arguments);
949
+ this.status = 402;
950
+ }
951
+ };
952
+ __name(_PaymentRequiredException, "PaymentRequiredException");
953
+ var PaymentRequiredException = _PaymentRequiredException;
954
+ var _ForbiddenException = class _ForbiddenException extends ResponseException {
955
+ constructor() {
956
+ super(...arguments);
957
+ this.status = 403;
958
+ }
959
+ };
960
+ __name(_ForbiddenException, "ForbiddenException");
961
+ var ForbiddenException = _ForbiddenException;
962
+ var _NotFoundException = class _NotFoundException extends ResponseException {
963
+ constructor() {
964
+ super(...arguments);
965
+ this.status = 404;
966
+ }
967
+ };
968
+ __name(_NotFoundException, "NotFoundException");
969
+ var NotFoundException = _NotFoundException;
970
+ var _MethodNotAllowedException = class _MethodNotAllowedException extends ResponseException {
971
+ constructor() {
972
+ super(...arguments);
973
+ this.status = 405;
1005
974
  }
1006
- });
975
+ };
976
+ __name(_MethodNotAllowedException, "MethodNotAllowedException");
977
+ var MethodNotAllowedException = _MethodNotAllowedException;
978
+ var _NotAcceptableException = class _NotAcceptableException extends ResponseException {
979
+ constructor() {
980
+ super(...arguments);
981
+ this.status = 406;
982
+ }
983
+ };
984
+ __name(_NotAcceptableException, "NotAcceptableException");
985
+ var NotAcceptableException = _NotAcceptableException;
986
+ var _RequestTimeoutException = class _RequestTimeoutException extends ResponseException {
987
+ constructor() {
988
+ super(...arguments);
989
+ this.status = 408;
990
+ }
991
+ };
992
+ __name(_RequestTimeoutException, "RequestTimeoutException");
993
+ var RequestTimeoutException = _RequestTimeoutException;
994
+ var _ConflictException = class _ConflictException extends ResponseException {
995
+ constructor() {
996
+ super(...arguments);
997
+ this.status = 409;
998
+ }
999
+ };
1000
+ __name(_ConflictException, "ConflictException");
1001
+ var ConflictException = _ConflictException;
1002
+ var _UpgradeRequiredException = class _UpgradeRequiredException extends ResponseException {
1003
+ constructor() {
1004
+ super(...arguments);
1005
+ this.status = 426;
1006
+ }
1007
+ };
1008
+ __name(_UpgradeRequiredException, "UpgradeRequiredException");
1009
+ var UpgradeRequiredException = _UpgradeRequiredException;
1010
+ var _TooManyRequestsException = class _TooManyRequestsException extends ResponseException {
1011
+ constructor() {
1012
+ super(...arguments);
1013
+ this.status = 429;
1014
+ }
1015
+ };
1016
+ __name(_TooManyRequestsException, "TooManyRequestsException");
1017
+ var TooManyRequestsException = _TooManyRequestsException;
1018
+ var _InternalServerException = class _InternalServerException extends ResponseException {
1019
+ constructor() {
1020
+ super(...arguments);
1021
+ this.status = 500;
1022
+ }
1023
+ };
1024
+ __name(_InternalServerException, "InternalServerException");
1025
+ var InternalServerException = _InternalServerException;
1026
+ var _NotImplementedException = class _NotImplementedException extends ResponseException {
1027
+ constructor() {
1028
+ super(...arguments);
1029
+ this.status = 501;
1030
+ }
1031
+ };
1032
+ __name(_NotImplementedException, "NotImplementedException");
1033
+ var NotImplementedException = _NotImplementedException;
1034
+ var _BadGatewayException = class _BadGatewayException extends ResponseException {
1035
+ constructor() {
1036
+ super(...arguments);
1037
+ this.status = 502;
1038
+ }
1039
+ };
1040
+ __name(_BadGatewayException, "BadGatewayException");
1041
+ var BadGatewayException = _BadGatewayException;
1042
+ var _ServiceUnavailableException = class _ServiceUnavailableException extends ResponseException {
1043
+ constructor() {
1044
+ super(...arguments);
1045
+ this.status = 503;
1046
+ }
1047
+ };
1048
+ __name(_ServiceUnavailableException, "ServiceUnavailableException");
1049
+ var ServiceUnavailableException = _ServiceUnavailableException;
1050
+ var _GatewayTimeoutException = class _GatewayTimeoutException extends ResponseException {
1051
+ constructor() {
1052
+ super(...arguments);
1053
+ this.status = 504;
1054
+ }
1055
+ };
1056
+ __name(_GatewayTimeoutException, "GatewayTimeoutException");
1057
+ var GatewayTimeoutException = _GatewayTimeoutException;
1058
+ var _HttpVersionNotSupportedException = class _HttpVersionNotSupportedException extends ResponseException {
1059
+ constructor() {
1060
+ super(...arguments);
1061
+ this.status = 505;
1062
+ }
1063
+ };
1064
+ __name(_HttpVersionNotSupportedException, "HttpVersionNotSupportedException");
1065
+ var HttpVersionNotSupportedException = _HttpVersionNotSupportedException;
1066
+ var _VariantAlsoNegotiatesException = class _VariantAlsoNegotiatesException extends ResponseException {
1067
+ constructor() {
1068
+ super(...arguments);
1069
+ this.status = 506;
1070
+ }
1071
+ };
1072
+ __name(_VariantAlsoNegotiatesException, "VariantAlsoNegotiatesException");
1073
+ var VariantAlsoNegotiatesException = _VariantAlsoNegotiatesException;
1074
+ var _InsufficientStorageException = class _InsufficientStorageException extends ResponseException {
1075
+ constructor() {
1076
+ super(...arguments);
1077
+ this.status = 507;
1078
+ }
1079
+ };
1080
+ __name(_InsufficientStorageException, "InsufficientStorageException");
1081
+ var InsufficientStorageException = _InsufficientStorageException;
1082
+ var _LoopDetectedException = class _LoopDetectedException extends ResponseException {
1083
+ constructor() {
1084
+ super(...arguments);
1085
+ this.status = 508;
1086
+ }
1087
+ };
1088
+ __name(_LoopDetectedException, "LoopDetectedException");
1089
+ var LoopDetectedException = _LoopDetectedException;
1090
+ var _NotExtendedException = class _NotExtendedException extends ResponseException {
1091
+ constructor() {
1092
+ super(...arguments);
1093
+ this.status = 510;
1094
+ }
1095
+ };
1096
+ __name(_NotExtendedException, "NotExtendedException");
1097
+ var NotExtendedException = _NotExtendedException;
1098
+ var _NetworkAuthenticationRequiredException = class _NetworkAuthenticationRequiredException extends ResponseException {
1099
+ constructor() {
1100
+ super(...arguments);
1101
+ this.status = 511;
1102
+ }
1103
+ };
1104
+ __name(_NetworkAuthenticationRequiredException, "NetworkAuthenticationRequiredException");
1105
+ var NetworkAuthenticationRequiredException = _NetworkAuthenticationRequiredException;
1106
+ var _NetworkConnectTimeoutException = class _NetworkConnectTimeoutException extends ResponseException {
1107
+ constructor() {
1108
+ super(...arguments);
1109
+ this.status = 599;
1110
+ }
1111
+ };
1112
+ __name(_NetworkConnectTimeoutException, "NetworkConnectTimeoutException");
1113
+ var NetworkConnectTimeoutException = _NetworkConnectTimeoutException;
1007
1114
 
1008
1115
  // src/internal/request.ts
1116
+ init_app_injector();
1117
+ var _Request = class _Request {
1118
+ constructor(event, senderId, id, method, path2, body, query) {
1119
+ this.event = event;
1120
+ this.senderId = senderId;
1121
+ this.id = id;
1122
+ this.method = method;
1123
+ this.path = path2;
1124
+ this.body = body;
1125
+ this.context = RootInjector.createScope();
1126
+ this.params = {};
1127
+ this.path = path2.replace(/^\/|\/$/g, "");
1128
+ this.query = query ?? {};
1129
+ }
1130
+ };
1131
+ __name(_Request, "Request");
1132
+ var Request = _Request;
1133
+ var RENDERER_EVENT_TYPE = "noxus:event";
1009
1134
  function createRendererEventMessage(event, payload) {
1010
1135
  return {
1011
1136
  type: RENDERER_EVENT_TYPE,
@@ -1013,6 +1138,7 @@ function createRendererEventMessage(event, payload) {
1013
1138
  payload
1014
1139
  };
1015
1140
  }
1141
+ __name(createRendererEventMessage, "createRendererEventMessage");
1016
1142
  function isRendererEventMessage(value) {
1017
1143
  if (value === null || typeof value !== "object") {
1018
1144
  return false;
@@ -1020,362 +1146,273 @@ function isRendererEventMessage(value) {
1020
1146
  const possibleMessage = value;
1021
1147
  return possibleMessage.type === RENDERER_EVENT_TYPE && typeof possibleMessage.event === "string";
1022
1148
  }
1023
- var _Request, Request, RENDERER_EVENT_TYPE;
1024
- var init_request = __esm({
1025
- "src/internal/request.ts"() {
1026
- "use strict";
1027
- init_app_injector();
1028
- _Request = class _Request {
1029
- constructor(event, senderId, id, method, path2, body) {
1030
- this.event = event;
1031
- this.senderId = senderId;
1032
- this.id = id;
1033
- this.method = method;
1034
- this.path = path2;
1035
- this.body = body;
1036
- this.context = RootInjector.createScope();
1037
- this.params = {};
1038
- this.path = path2.replace(/^\/|\/$/g, "");
1039
- }
1040
- };
1041
- __name(_Request, "Request");
1042
- Request = _Request;
1043
- RENDERER_EVENT_TYPE = "noxus:event";
1044
- __name(createRendererEventMessage, "createRendererEventMessage");
1045
- __name(isRendererEventMessage, "isRendererEventMessage");
1046
- }
1047
- });
1149
+ __name(isRendererEventMessage, "isRendererEventMessage");
1048
1150
 
1049
1151
  // src/internal/router.ts
1050
- var router_exports = {};
1051
- __export(router_exports, {
1052
- Router: () => Router
1053
- });
1054
- var Router;
1055
- var init_router = __esm({
1056
- "src/internal/router.ts"() {
1057
- "use strict";
1058
- init_controller_decorator();
1059
- init_injectable_decorator();
1060
- init_method_decorator();
1061
- init_injector_explorer();
1062
- init_logger();
1063
- init_radix_tree();
1064
- init_exceptions();
1065
- init_request();
1066
- Router = class {
1067
- constructor() {
1068
- this.routes = new RadixTree();
1069
- this.rootMiddlewares = [];
1070
- this.lazyRoutes = /* @__PURE__ */ new Map();
1071
- }
1072
- // -------------------------------------------------------------------------
1073
- // Registration
1074
- // -------------------------------------------------------------------------
1075
- registerController(controllerClass, pathPrefix, routeGuards = [], routeMiddlewares = []) {
1076
- const meta = getControllerMetadata(controllerClass);
1077
- if (!meta) {
1078
- throw new Error(`[Noxus] Missing @Controller decorator on ${controllerClass.name}`);
1079
- }
1080
- const routeMeta = getRouteMetadata(controllerClass);
1081
- for (const def of routeMeta) {
1082
- const fullPath = `${pathPrefix}/${def.path}`.replace(/\/+/g, "/").replace(/\/$/, "") || "/";
1083
- const guards = [.../* @__PURE__ */ new Set([...routeGuards, ...def.guards])];
1084
- const middlewares = [.../* @__PURE__ */ new Set([...routeMiddlewares, ...def.middlewares])];
1085
- const routeDef = {
1086
- method: def.method,
1087
- path: fullPath,
1088
- controller: controllerClass,
1089
- handler: def.handler,
1090
- guards,
1091
- middlewares
1092
- };
1093
- this.routes.insert(fullPath + "/" + def.method, routeDef);
1094
- const guardInfo = guards.length ? `<${guards.map((g) => g.name).join("|")}>` : "";
1095
- Logger.log(`Mapped {${def.method} /${fullPath}}${guardInfo} route`);
1096
- }
1097
- const ctrlGuardInfo = routeGuards.length ? `<${routeGuards.map((g) => g.name).join("|")}>` : "";
1098
- Logger.log(`Mapped ${controllerClass.name}${ctrlGuardInfo} controller's routes`);
1099
- return this;
1100
- }
1101
- registerLazyRoute(pathPrefix, load, guards = [], middlewares = []) {
1102
- const normalized = pathPrefix.replace(/^\/+|\/+$/g, "");
1103
- this.lazyRoutes.set(normalized, { load, guards, middlewares, loading: null, loaded: false });
1104
- Logger.log(`Registered lazy route prefix {${normalized}}`);
1105
- return this;
1106
- }
1107
- defineRootMiddleware(middleware) {
1108
- this.rootMiddlewares.push(middleware);
1109
- return this;
1110
- }
1111
- // -------------------------------------------------------------------------
1112
- // Request handling
1113
- // -------------------------------------------------------------------------
1114
- async handle(request) {
1115
- return request.method === "BATCH" ? this.handleBatch(request) : this.handleAtomic(request);
1116
- }
1117
- async handleAtomic(request) {
1118
- Logger.comment(`> ${request.method} /${request.path}`);
1119
- const t0 = performance.now();
1120
- const response = { requestId: request.id, status: 200, body: null };
1121
- let isCritical = false;
1122
- try {
1123
- const routeDef = await this.findRoute(request);
1124
- await this.resolveController(request, response, routeDef);
1125
- if (response.status >= 400) throw new ResponseException(response.status, response.error);
1126
- } catch (error) {
1127
- this.fillErrorResponse(response, error, (c) => {
1128
- isCritical = c;
1129
- });
1130
- } finally {
1131
- this.logResponse(request, response, performance.now() - t0, isCritical);
1132
- return response;
1133
- }
1134
- }
1135
- async handleBatch(request) {
1136
- Logger.comment(`> ${request.method} /${request.path}`);
1137
- const t0 = performance.now();
1138
- const response = {
1139
- requestId: request.id,
1140
- status: 200,
1141
- body: { responses: [] }
1142
- };
1143
- let isCritical = false;
1144
- try {
1145
- const payload = this.normalizeBatchPayload(request.body);
1146
- response.body.responses = await Promise.all(
1147
- payload.requests.map((item, i) => {
1148
- const id = item.requestId ?? `${request.id}:${i}`;
1149
- return this.handleAtomic(new Request(request.event, request.senderId, id, item.method, item.path, item.body));
1150
- })
1151
- );
1152
- } catch (error) {
1153
- this.fillErrorResponse(response, error, (c) => {
1154
- isCritical = c;
1155
- });
1156
- } finally {
1157
- this.logResponse(request, response, performance.now() - t0, isCritical);
1158
- return response;
1159
- }
1160
- }
1161
- // -------------------------------------------------------------------------
1162
- // Route resolution
1163
- // -------------------------------------------------------------------------
1164
- tryFindRoute(request) {
1165
- const matched = this.routes.search(request.path);
1166
- if (!matched?.node || matched.node.children.length === 0) return void 0;
1167
- return matched.node.findExactChild(request.method)?.value;
1168
- }
1169
- async findRoute(request) {
1170
- const direct = this.tryFindRoute(request);
1171
- if (direct) return direct;
1172
- await this.tryLoadLazyRoute(request.path);
1173
- const afterLazy = this.tryFindRoute(request);
1174
- if (afterLazy) return afterLazy;
1175
- throw new NotFoundException(`No route matches ${request.method} ${request.path}`);
1176
- }
1177
- async tryLoadLazyRoute(requestPath) {
1178
- const firstSegment = requestPath.replace(/^\/+/, "").split("/")[0] ?? "";
1179
- for (const [prefix, entry] of this.lazyRoutes) {
1180
- if (entry.loaded) continue;
1181
- const normalized = requestPath.replace(/^\/+/, "");
1182
- if (normalized === prefix || normalized.startsWith(prefix + "/") || firstSegment === prefix) {
1183
- if (!entry.loading) entry.loading = this.loadLazyModule(prefix, entry);
1184
- await entry.loading;
1185
- return;
1186
- }
1187
- }
1188
- }
1189
- async loadLazyModule(prefix, entry) {
1190
- const t0 = performance.now();
1191
- InjectorExplorer.beginAccumulate();
1192
- await entry.load?.();
1193
- entry.loading = null;
1194
- entry.load = null;
1195
- InjectorExplorer.flushAccumulated(entry.guards, entry.middlewares, prefix);
1196
- entry.loaded = true;
1197
- Logger.info(`Lazy-loaded module for prefix {${prefix}} in ${Math.round(performance.now() - t0)}ms`);
1198
- }
1199
- // -------------------------------------------------------------------------
1200
- // Pipeline
1201
- // -------------------------------------------------------------------------
1202
- async resolveController(request, response, routeDef) {
1203
- const instance = request.context.resolve(routeDef.controller);
1204
- Object.assign(request.params, this.extractParams(request.path, routeDef.path));
1205
- await this.runPipeline(request, response, routeDef, instance);
1206
- }
1207
- async runPipeline(request, response, routeDef, controllerInstance) {
1208
- const middlewares = [.../* @__PURE__ */ new Set([...this.rootMiddlewares, ...routeDef.middlewares])];
1209
- const mwMax = middlewares.length - 1;
1210
- const guardMax = mwMax + routeDef.guards.length;
1211
- let index = -1;
1212
- const dispatch = /* @__PURE__ */ __name(async (i) => {
1213
- if (i <= index) throw new Error("next() called multiple times");
1214
- index = i;
1215
- if (i <= mwMax) {
1216
- await this.runMiddleware(request, response, dispatch.bind(null, i + 1), middlewares[i]);
1217
- if (response.status >= 400) throw new ResponseException(response.status, response.error);
1218
- return;
1219
- }
1220
- if (i <= guardMax) {
1221
- await this.runGuard(request, routeDef.guards[i - middlewares.length]);
1222
- await dispatch(i + 1);
1223
- return;
1224
- }
1225
- const action = controllerInstance[routeDef.handler];
1226
- response.body = await action.call(controllerInstance, request, response);
1227
- if (response.body === void 0) response.body = {};
1228
- }, "dispatch");
1229
- await dispatch(0);
1230
- }
1231
- async runMiddleware(request, response, next, middleware) {
1232
- await middleware(request, response, next);
1233
- }
1234
- async runGuard(request, guard) {
1235
- if (!await guard(request)) {
1236
- throw new UnauthorizedException(`Unauthorized for ${request.method} ${request.path}`);
1237
- }
1238
- }
1239
- // -------------------------------------------------------------------------
1240
- // Utilities
1241
- // -------------------------------------------------------------------------
1242
- extractParams(actual, template) {
1243
- const aParts = actual.split("/");
1244
- const tParts = template.split("/");
1245
- const params = {};
1246
- tParts.forEach((part, i) => {
1247
- if (part.startsWith(":")) params[part.slice(1)] = aParts[i] ?? "";
1248
- });
1249
- return params;
1250
- }
1251
- normalizeBatchPayload(body) {
1252
- if (body === null || typeof body !== "object") {
1253
- throw new BadRequestException("Batch payload must be an object containing a requests array.");
1254
- }
1255
- const { requests } = body;
1256
- if (!Array.isArray(requests)) throw new BadRequestException("Batch payload must define a requests array.");
1257
- return { requests: requests.map((e, i) => this.normalizeBatchItem(e, i)) };
1258
- }
1259
- normalizeBatchItem(entry, index) {
1260
- if (entry === null || typeof entry !== "object") throw new BadRequestException(`Batch request at index ${index} must be an object.`);
1261
- const { requestId, path: path2, method, body } = entry;
1262
- if (requestId !== void 0 && typeof requestId !== "string") throw new BadRequestException(`Batch request at index ${index} has an invalid requestId.`);
1263
- if (typeof path2 !== "string" || !path2.length) throw new BadRequestException(`Batch request at index ${index} must define a non-empty path.`);
1264
- if (typeof method !== "string") throw new BadRequestException(`Batch request at index ${index} must define an HTTP method.`);
1265
- const normalized = method.toUpperCase();
1266
- if (!isAtomicHttpMethod(normalized)) throw new BadRequestException(`Batch request at index ${index} uses unsupported method ${method}.`);
1267
- return { requestId, path: path2, method: normalized, body };
1152
+ var Router = class {
1153
+ constructor() {
1154
+ this.routes = new RadixTree();
1155
+ this.rootMiddlewares = [];
1156
+ this.lazyRoutes = /* @__PURE__ */ new Map();
1157
+ this.lazyLoadLock = Promise.resolve();
1158
+ }
1159
+ // -------------------------------------------------------------------------
1160
+ // Registration
1161
+ // -------------------------------------------------------------------------
1162
+ registerController(controllerClass, pathPrefix, routeGuards = [], routeMiddlewares = []) {
1163
+ const meta = getControllerMetadata(controllerClass);
1164
+ if (!meta) {
1165
+ throw new Error(`[Noxus] Missing @Controller decorator on ${controllerClass.name}`);
1166
+ }
1167
+ const routeMeta = getRouteMetadata(controllerClass);
1168
+ for (const def of routeMeta) {
1169
+ const fullPath = `${pathPrefix}/${def.path}`.replace(/\/+/g, "/").replace(/\/$/, "") || "/";
1170
+ const guards = [.../* @__PURE__ */ new Set([...routeGuards, ...def.guards])];
1171
+ const middlewares = [.../* @__PURE__ */ new Set([...routeMiddlewares, ...def.middlewares])];
1172
+ const routeDef = {
1173
+ method: def.method,
1174
+ path: fullPath,
1175
+ controller: controllerClass,
1176
+ handler: def.handler,
1177
+ guards,
1178
+ middlewares
1179
+ };
1180
+ this.routes.insert(fullPath + "/" + def.method, routeDef);
1181
+ const guardInfo = guards.length ? `<${guards.map((g) => g.name).join("|")}>` : "";
1182
+ Logger.log(`Mapped {${def.method} /${fullPath}}${guardInfo} route`);
1183
+ }
1184
+ const ctrlGuardInfo = routeGuards.length ? `<${routeGuards.map((g) => g.name).join("|")}>` : "";
1185
+ Logger.log(`Mapped ${controllerClass.name}${ctrlGuardInfo} controller's routes`);
1186
+ return this;
1187
+ }
1188
+ registerLazyRoute(pathPrefix, load, guards = [], middlewares = []) {
1189
+ const normalized = pathPrefix.replace(/^\/+|\/+$/g, "");
1190
+ this.lazyRoutes.set(normalized, { load, guards, middlewares, loading: null, loaded: false });
1191
+ Logger.log(`Registered lazy route prefix {${normalized}}`);
1192
+ return this;
1193
+ }
1194
+ defineRootMiddleware(middleware) {
1195
+ this.rootMiddlewares.push(middleware);
1196
+ return this;
1197
+ }
1198
+ getRegisteredRoutes() {
1199
+ const allRoutes = this.routes.collectValues();
1200
+ return allRoutes.map((r) => ({ method: r.method, path: r.path }));
1201
+ }
1202
+ getLazyRoutes() {
1203
+ return [...this.lazyRoutes.entries()].map(([prefix, entry]) => ({
1204
+ prefix,
1205
+ loaded: entry.loaded
1206
+ }));
1207
+ }
1208
+ // -------------------------------------------------------------------------
1209
+ // Request handling
1210
+ // -------------------------------------------------------------------------
1211
+ async handle(request) {
1212
+ return request.method === "BATCH" ? this.handleBatch(request) : this.handleAtomic(request);
1213
+ }
1214
+ async handleAtomic(request) {
1215
+ Logger.comment(`> ${request.method} /${request.path}`);
1216
+ const t0 = performance.now();
1217
+ const response = { requestId: request.id, status: 200, body: null };
1218
+ let isCritical = false;
1219
+ try {
1220
+ const routeDef = await this.findRoute(request);
1221
+ await this.resolveController(request, response, routeDef);
1222
+ if (response.status >= 400) throw new ResponseException(response.status, response.error);
1223
+ } catch (error) {
1224
+ this.fillErrorResponse(response, error, (c) => {
1225
+ isCritical = c;
1226
+ });
1227
+ } finally {
1228
+ this.logResponse(request, response, performance.now() - t0, isCritical);
1229
+ return response;
1230
+ }
1231
+ }
1232
+ async handleBatch(request) {
1233
+ Logger.comment(`> ${request.method} /${request.path}`);
1234
+ const t0 = performance.now();
1235
+ const response = {
1236
+ requestId: request.id,
1237
+ status: 200,
1238
+ body: { responses: [] }
1239
+ };
1240
+ let isCritical = false;
1241
+ try {
1242
+ const payload = this.normalizeBatchPayload(request.body);
1243
+ response.body.responses = await Promise.all(
1244
+ payload.requests.map((item, i) => {
1245
+ const id = item.requestId ?? `${request.id}:${i}`;
1246
+ return this.handleAtomic(new Request(request.event, request.senderId, id, item.method, item.path, item.body, item.query));
1247
+ })
1248
+ );
1249
+ } catch (error) {
1250
+ this.fillErrorResponse(response, error, (c) => {
1251
+ isCritical = c;
1252
+ });
1253
+ } finally {
1254
+ this.logResponse(request, response, performance.now() - t0, isCritical);
1255
+ return response;
1256
+ }
1257
+ }
1258
+ // -------------------------------------------------------------------------
1259
+ // Route resolution
1260
+ // -------------------------------------------------------------------------
1261
+ tryFindRoute(request) {
1262
+ const matched = this.routes.search(request.path);
1263
+ if (!matched?.node || matched.node.children.length === 0) return void 0;
1264
+ return matched.node.findExactChild(request.method)?.value;
1265
+ }
1266
+ async findRoute(request) {
1267
+ const direct = this.tryFindRoute(request);
1268
+ if (direct) return direct;
1269
+ await this.tryLoadLazyRoute(request.path);
1270
+ const afterLazy = this.tryFindRoute(request);
1271
+ if (afterLazy) return afterLazy;
1272
+ throw new NotFoundException(`No route matches ${request.method} ${request.path}`);
1273
+ }
1274
+ async tryLoadLazyRoute(requestPath) {
1275
+ const firstSegment = requestPath.replace(/^\/+/, "").split("/")[0] ?? "";
1276
+ for (const [prefix, entry] of this.lazyRoutes) {
1277
+ if (entry.loaded) continue;
1278
+ const normalized = requestPath.replace(/^\/+/, "");
1279
+ if (normalized === prefix || normalized.startsWith(prefix + "/") || firstSegment === prefix) {
1280
+ if (!entry.loading) entry.loading = this.loadLazyModule(prefix, entry);
1281
+ await entry.loading;
1282
+ return;
1268
1283
  }
1269
- fillErrorResponse(response, error, setCritical) {
1270
- response.body = void 0;
1271
- if (error instanceof ResponseException) {
1272
- response.status = error.status;
1273
- response.error = error.message;
1274
- response.stack = error.stack;
1275
- } else if (error instanceof Error) {
1276
- setCritical(true);
1277
- response.status = 500;
1278
- response.error = error.message || "Internal Server Error";
1279
- response.stack = error.stack;
1280
- } else {
1281
- setCritical(true);
1282
- response.status = 500;
1283
- response.error = "Unknown error occurred";
1284
- }
1284
+ }
1285
+ }
1286
+ loadLazyModule(prefix, entry) {
1287
+ const task = this.lazyLoadLock.then(async () => {
1288
+ const t0 = performance.now();
1289
+ InjectorExplorer.beginAccumulate();
1290
+ await entry.load?.();
1291
+ entry.load = null;
1292
+ await InjectorExplorer.flushAccumulated(entry.guards, entry.middlewares, prefix);
1293
+ entry.loaded = true;
1294
+ entry.loading = null;
1295
+ Logger.info(`Lazy-loaded module for prefix {${prefix}} in ${Math.round(performance.now() - t0)}ms`);
1296
+ });
1297
+ this.lazyLoadLock = task;
1298
+ return task;
1299
+ }
1300
+ // -------------------------------------------------------------------------
1301
+ // Pipeline
1302
+ // -------------------------------------------------------------------------
1303
+ async resolveController(request, response, routeDef) {
1304
+ const instance = request.context.resolve(routeDef.controller);
1305
+ Object.assign(request.params, this.extractParams(request.path, routeDef.path));
1306
+ await this.runPipeline(request, response, routeDef, instance);
1307
+ }
1308
+ async runPipeline(request, response, routeDef, controllerInstance) {
1309
+ const middlewares = [.../* @__PURE__ */ new Set([...this.rootMiddlewares, ...routeDef.middlewares])];
1310
+ const mwMax = middlewares.length - 1;
1311
+ const guardMax = mwMax + routeDef.guards.length;
1312
+ let index = -1;
1313
+ const dispatch = /* @__PURE__ */ __name(async (i) => {
1314
+ if (i <= index) throw new Error("next() called multiple times");
1315
+ index = i;
1316
+ if (i <= mwMax) {
1317
+ await this.runMiddleware(request, response, dispatch.bind(null, i + 1), middlewares[i]);
1318
+ if (response.status >= 400) throw new ResponseException(response.status, response.error);
1319
+ return;
1285
1320
  }
1286
- logResponse(request, response, ms, isCritical) {
1287
- const msg = `< ${response.status} ${request.method} /${request.path} ${Logger.colors.yellow}${Math.round(ms)}ms${Logger.colors.initial}`;
1288
- if (response.status < 400) Logger.log(msg);
1289
- else if (response.status < 500) Logger.warn(msg);
1290
- else isCritical ? Logger.critical(msg) : Logger.error(msg);
1291
- if (response.error) {
1292
- isCritical ? Logger.critical(response.error) : Logger.error(response.error);
1293
- if (response.stack) Logger.errorStack(response.stack);
1294
- }
1321
+ if (i <= guardMax) {
1322
+ await this.runGuard(request, routeDef.guards[i - middlewares.length]);
1323
+ await dispatch(i + 1);
1324
+ return;
1295
1325
  }
1296
- };
1297
- __name(Router, "Router");
1298
- Router = __decorateClass([
1299
- Injectable({ lifetime: "singleton" })
1300
- ], Router);
1326
+ const action = controllerInstance[routeDef.handler];
1327
+ response.body = await action.call(controllerInstance, request, response);
1328
+ if (response.body === void 0) response.body = {};
1329
+ }, "dispatch");
1330
+ await dispatch(0);
1301
1331
  }
1302
- });
1303
-
1304
- // src/main.ts
1305
- var main_exports = {};
1306
- __export(main_exports, {
1307
- AppInjector: () => AppInjector,
1308
- BadGatewayException: () => BadGatewayException,
1309
- BadRequestException: () => BadRequestException,
1310
- ConflictException: () => ConflictException,
1311
- Controller: () => Controller,
1312
- Delete: () => Delete,
1313
- ForbiddenException: () => ForbiddenException,
1314
- ForwardReference: () => ForwardReference,
1315
- GatewayTimeoutException: () => GatewayTimeoutException,
1316
- Get: () => Get,
1317
- HttpVersionNotSupportedException: () => HttpVersionNotSupportedException,
1318
- Injectable: () => Injectable,
1319
- InsufficientStorageException: () => InsufficientStorageException,
1320
- InternalServerException: () => InternalServerException,
1321
- Logger: () => Logger,
1322
- LoopDetectedException: () => LoopDetectedException,
1323
- MethodNotAllowedException: () => MethodNotAllowedException,
1324
- NetworkAuthenticationRequiredException: () => NetworkAuthenticationRequiredException,
1325
- NetworkConnectTimeoutException: () => NetworkConnectTimeoutException,
1326
- NotAcceptableException: () => NotAcceptableException,
1327
- NotExtendedException: () => NotExtendedException,
1328
- NotFoundException: () => NotFoundException,
1329
- NotImplementedException: () => NotImplementedException,
1330
- NoxApp: () => NoxApp,
1331
- NoxSocket: () => NoxSocket,
1332
- Patch: () => Patch,
1333
- PaymentRequiredException: () => PaymentRequiredException,
1334
- Post: () => Post,
1335
- Put: () => Put,
1336
- RENDERER_EVENT_TYPE: () => RENDERER_EVENT_TYPE,
1337
- Request: () => Request,
1338
- RequestTimeoutException: () => RequestTimeoutException,
1339
- ResponseException: () => ResponseException,
1340
- RootInjector: () => RootInjector,
1341
- Router: () => Router,
1342
- ServiceUnavailableException: () => ServiceUnavailableException,
1343
- Token: () => Token,
1344
- TooManyRequestsException: () => TooManyRequestsException,
1345
- UnauthorizedException: () => UnauthorizedException,
1346
- UpgradeRequiredException: () => UpgradeRequiredException,
1347
- VariantAlsoNegotiatesException: () => VariantAlsoNegotiatesException,
1348
- WindowManager: () => WindowManager,
1349
- bootstrapApplication: () => bootstrapApplication,
1350
- createRendererEventMessage: () => createRendererEventMessage,
1351
- defineRoutes: () => defineRoutes,
1352
- forwardRef: () => forwardRef,
1353
- getControllerMetadata: () => getControllerMetadata,
1354
- getRouteMetadata: () => getRouteMetadata,
1355
- inject: () => inject,
1356
- isAtomicHttpMethod: () => isAtomicHttpMethod,
1357
- isRendererEventMessage: () => isRendererEventMessage,
1358
- token: () => token
1359
- });
1360
- module.exports = __toCommonJS(main_exports);
1361
- init_app_injector();
1362
- init_token();
1363
- init_router();
1332
+ async runMiddleware(request, response, next, middleware) {
1333
+ await middleware(request, response, next);
1334
+ }
1335
+ async runGuard(request, guard) {
1336
+ if (!await guard(request)) {
1337
+ throw new UnauthorizedException(`Unauthorized for ${request.method} ${request.path}`);
1338
+ }
1339
+ }
1340
+ // -------------------------------------------------------------------------
1341
+ // Utilities
1342
+ // -------------------------------------------------------------------------
1343
+ extractParams(actual, template) {
1344
+ const aParts = actual.split("/");
1345
+ const tParts = template.split("/");
1346
+ const params = {};
1347
+ tParts.forEach((part, i) => {
1348
+ if (part.startsWith(":")) params[part.slice(1)] = aParts[i] ?? "";
1349
+ });
1350
+ return params;
1351
+ }
1352
+ normalizeBatchPayload(body) {
1353
+ if (body === null || typeof body !== "object") {
1354
+ throw new BadRequestException("Batch payload must be an object containing a requests array.");
1355
+ }
1356
+ const { requests } = body;
1357
+ if (!Array.isArray(requests)) throw new BadRequestException("Batch payload must define a requests array.");
1358
+ return { requests: requests.map((e, i) => this.normalizeBatchItem(e, i)) };
1359
+ }
1360
+ normalizeBatchItem(entry, index) {
1361
+ if (entry === null || typeof entry !== "object") throw new BadRequestException(`Batch request at index ${index} must be an object.`);
1362
+ const { requestId, path: path2, method, body, query } = entry;
1363
+ if (requestId !== void 0 && typeof requestId !== "string") throw new BadRequestException(`Batch request at index ${index} has an invalid requestId.`);
1364
+ if (typeof path2 !== "string" || !path2.length) throw new BadRequestException(`Batch request at index ${index} must define a non-empty path.`);
1365
+ if (typeof method !== "string") throw new BadRequestException(`Batch request at index ${index} must define an HTTP method.`);
1366
+ const normalized = method.toUpperCase();
1367
+ if (!isAtomicHttpMethod(normalized)) throw new BadRequestException(`Batch request at index ${index} uses unsupported method ${method}.`);
1368
+ return { requestId, path: path2, method: normalized, body, query };
1369
+ }
1370
+ fillErrorResponse(response, error, setCritical) {
1371
+ response.body = void 0;
1372
+ if (error instanceof ResponseException) {
1373
+ response.status = error.status;
1374
+ response.error = error.message;
1375
+ response.stack = error.stack;
1376
+ } else if (error instanceof Error) {
1377
+ setCritical(true);
1378
+ response.status = 500;
1379
+ response.error = error.message || "Internal Server Error";
1380
+ response.stack = error.stack;
1381
+ } else {
1382
+ setCritical(true);
1383
+ response.status = 500;
1384
+ response.error = "Unknown error occurred";
1385
+ }
1386
+ }
1387
+ logResponse(request, response, ms, isCritical) {
1388
+ const msg = `< ${response.status} ${request.method} /${request.path} ${Logger.colors.yellow}${Math.round(ms)}ms${Logger.colors.initial}`;
1389
+ if (response.status < 400) Logger.log(msg);
1390
+ else if (response.status < 500) Logger.warn(msg);
1391
+ else isCritical ? Logger.critical(msg) : Logger.error(msg);
1392
+ if (response.error) {
1393
+ isCritical ? Logger.critical(response.error) : Logger.error(response.error);
1394
+ if (response.stack) Logger.errorStack(response.stack);
1395
+ }
1396
+ }
1397
+ };
1398
+ __name(Router, "Router");
1399
+ Router = __decorateClass([
1400
+ Injectable({ lifetime: "singleton" })
1401
+ ], Router);
1364
1402
 
1365
1403
  // src/internal/app.ts
1366
1404
  var import_main2 = require("electron/main");
1367
- init_injectable_decorator();
1368
1405
  init_app_injector();
1369
1406
  init_injector_explorer();
1370
1407
  init_logger();
1371
1408
 
1372
1409
  // src/window/window-manager.ts
1373
1410
  var import_main = require("electron/main");
1374
- init_injectable_decorator();
1375
1411
  init_logger();
1376
1412
  var WindowManager = class {
1377
1413
  constructor() {
1378
1414
  this._windows = /* @__PURE__ */ new Map();
1415
+ this.listeners = /* @__PURE__ */ new Map();
1379
1416
  }
1380
1417
  // -------------------------------------------------------------------------
1381
1418
  // Creation
@@ -1425,18 +1462,24 @@ var WindowManager = class {
1425
1462
  * win.loadFile('index.html');
1426
1463
  */
1427
1464
  async createSplash(options = {}) {
1428
- const { animationDuration = 600, ...bwOptions } = options;
1465
+ const {
1466
+ animationDuration = 10,
1467
+ expandToWorkArea = true,
1468
+ ...bwOptions
1469
+ } = options;
1429
1470
  const win = new import_main.BrowserWindow({
1430
1471
  width: 600,
1431
1472
  height: 600,
1432
1473
  center: true,
1433
- frame: false,
1434
1474
  show: true,
1435
1475
  ...bwOptions
1436
1476
  });
1437
1477
  this._register(win, true);
1438
1478
  Logger.log(`[WindowManager] Splash window #${win.id} created`);
1439
- await this._expandToWorkArea(win, animationDuration);
1479
+ if (expandToWorkArea) {
1480
+ await (() => new Promise((r) => setTimeout(r, 500)))();
1481
+ await this._expandToWorkArea(win, animationDuration);
1482
+ }
1440
1483
  return win;
1441
1484
  }
1442
1485
  // -------------------------------------------------------------------------
@@ -1495,10 +1538,24 @@ var WindowManager = class {
1495
1538
  */
1496
1539
  broadcast(channel, ...args) {
1497
1540
  for (const win of this._windows.values()) {
1498
- if (!win.isDestroyed()) win.webContents.send(channel, ...args);
1541
+ if (!win.isDestroyed()) {
1542
+ win.webContents.send(channel, ...args);
1543
+ }
1499
1544
  }
1500
1545
  }
1501
1546
  // -------------------------------------------------------------------------
1547
+ // Events
1548
+ // -------------------------------------------------------------------------
1549
+ on(event, handler) {
1550
+ const set = this.listeners.get(event) ?? /* @__PURE__ */ new Set();
1551
+ set.add(handler);
1552
+ this.listeners.set(event, set);
1553
+ return () => set.delete(handler);
1554
+ }
1555
+ _emit(event, win) {
1556
+ this.listeners.get(event)?.forEach((h) => h(win));
1557
+ }
1558
+ // -------------------------------------------------------------------------
1502
1559
  // Private
1503
1560
  // -------------------------------------------------------------------------
1504
1561
  _register(win, isMain) {
@@ -1506,10 +1563,16 @@ var WindowManager = class {
1506
1563
  if (isMain && this._mainWindowId === void 0) {
1507
1564
  this._mainWindowId = win.id;
1508
1565
  }
1566
+ this._emit("created", win);
1567
+ win.on("focus", () => this._emit("focused", win));
1568
+ win.on("blur", () => this._emit("blurred", win));
1509
1569
  win.once("closed", () => {
1510
1570
  this._windows.delete(win.id);
1511
- if (this._mainWindowId === win.id) this._mainWindowId = void 0;
1571
+ if (this._mainWindowId === win.id) {
1572
+ this._mainWindowId = void 0;
1573
+ }
1512
1574
  Logger.log(`[WindowManager] Window #${win.id} closed`);
1575
+ this._emit("closed", win);
1513
1576
  });
1514
1577
  }
1515
1578
  /**
@@ -1519,17 +1582,18 @@ var WindowManager = class {
1519
1582
  */
1520
1583
  _expandToWorkArea(win, animationDuration) {
1521
1584
  return new Promise((resolve) => {
1522
- const { x, y, width, height } = import_main.screen.getPrimaryDisplay().workArea;
1523
- win.setBounds({ x, y, width, height }, true);
1585
+ win.maximize();
1524
1586
  let resolved = false;
1525
1587
  const done = /* @__PURE__ */ __name(() => {
1526
- if (resolved) return;
1588
+ if (resolved) {
1589
+ return;
1590
+ }
1527
1591
  resolved = true;
1528
1592
  win.removeListener("resize", done);
1529
1593
  resolve();
1530
1594
  }, "done");
1531
1595
  win.once("resize", done);
1532
- setTimeout(done, animationDuration + 100);
1596
+ setTimeout(done, animationDuration);
1533
1597
  });
1534
1598
  }
1535
1599
  };
@@ -1538,14 +1602,8 @@ WindowManager = __decorateClass([
1538
1602
  Injectable({ lifetime: "singleton" })
1539
1603
  ], WindowManager);
1540
1604
 
1541
- // src/internal/app.ts
1542
- init_request();
1543
- init_router();
1544
-
1545
1605
  // src/internal/socket.ts
1546
- init_injectable_decorator();
1547
1606
  init_logger();
1548
- init_request();
1549
1607
  var NoxSocket = class {
1550
1608
  constructor() {
1551
1609
  this.channels = /* @__PURE__ */ new Map();
@@ -1568,7 +1626,6 @@ var NoxSocket = class {
1568
1626
  throw new Error("Renderer event name must be a non-empty string.");
1569
1627
  }
1570
1628
  const recipients = targetSenderIds ?? this.getSenderIds();
1571
- let delivered = 0;
1572
1629
  for (const senderId of recipients) {
1573
1630
  const channel = this.channels.get(senderId);
1574
1631
  if (!channel) {
@@ -1577,15 +1634,17 @@ var NoxSocket = class {
1577
1634
  }
1578
1635
  try {
1579
1636
  channel.socket.port1.postMessage(createRendererEventMessage(normalizedEvent, payload));
1580
- delivered++;
1581
1637
  } catch (error) {
1582
1638
  Logger.error(`[Noxus] Failed to emit "${normalizedEvent}" to sender ${senderId}.`, error);
1583
1639
  }
1584
1640
  }
1585
- return delivered;
1586
1641
  }
1587
1642
  emitToRenderer(senderId, eventName, payload) {
1588
- return this.emit(eventName, payload, [senderId]) > 0;
1643
+ if (!this.channels.has(senderId)) {
1644
+ return false;
1645
+ }
1646
+ this.emit(eventName, payload, [senderId]);
1647
+ return true;
1589
1648
  }
1590
1649
  };
1591
1650
  __name(NoxSocket, "NoxSocket");
@@ -1595,22 +1654,22 @@ NoxSocket = __decorateClass([
1595
1654
 
1596
1655
  // src/internal/app.ts
1597
1656
  var NoxApp = class {
1598
- constructor() {
1599
- this.router = inject(Router);
1600
- this.socket = inject(NoxSocket);
1601
- this.windowManager = inject(WindowManager);
1657
+ constructor(router, socket, windowManager) {
1658
+ this.router = router;
1659
+ this.socket = socket;
1660
+ this.windowManager = windowManager;
1602
1661
  // -------------------------------------------------------------------------
1603
1662
  // IPC
1604
1663
  // -------------------------------------------------------------------------
1605
1664
  this.onRendererMessage = /* @__PURE__ */ __name(async (event) => {
1606
- const { senderId, requestId, path: path2, method, body } = event.data;
1665
+ const { senderId, requestId, path: path2, method, body, query } = event.data;
1607
1666
  const channels = this.socket.get(senderId);
1608
1667
  if (!channels) {
1609
1668
  Logger.error(`No message channel found for sender ID: ${senderId}`);
1610
1669
  return;
1611
1670
  }
1612
1671
  try {
1613
- const request = new Request(event, senderId, requestId, method, path2, body);
1672
+ const request = new Request(event, senderId, requestId, method, path2, body, query);
1614
1673
  const response = await this.router.handle(request);
1615
1674
  channels.request.port1.postMessage(response);
1616
1675
  } catch (err) {
@@ -1661,7 +1720,7 @@ var NoxApp = class {
1661
1720
  async load(importFns) {
1662
1721
  InjectorExplorer.beginAccumulate();
1663
1722
  await Promise.all(importFns.map((fn) => fn()));
1664
- InjectorExplorer.flushAccumulated();
1723
+ await InjectorExplorer.flushAccumulated();
1665
1724
  return this;
1666
1725
  }
1667
1726
  /**
@@ -1739,18 +1798,34 @@ NoxApp = __decorateClass([
1739
1798
  var import_main3 = require("electron/main");
1740
1799
  init_app_injector();
1741
1800
  init_injector_explorer();
1801
+ init_logger();
1742
1802
  async function bootstrapApplication(config = {}) {
1743
1803
  await import_main3.app.whenReady();
1804
+ if (config.logLevel !== void 0) {
1805
+ if (config.logLevel === "none") {
1806
+ Logger.setLogLevel([]);
1807
+ } else if (Array.isArray(config.logLevel)) {
1808
+ Logger.setLogLevel(config.logLevel);
1809
+ } else {
1810
+ Logger.setLogLevel(config.logLevel);
1811
+ }
1812
+ }
1744
1813
  const overrides = /* @__PURE__ */ new Map();
1745
1814
  for (const { token: token2, useValue } of config.singletons ?? []) {
1746
1815
  overrides.set(token2, useValue);
1747
1816
  RootInjector.singletons.set(token2, useValue);
1748
1817
  }
1818
+ InjectorExplorer.setControllerRegistrar((controllerClass, pathPrefix, routeGuards, routeMiddlewares) => {
1819
+ const router = inject(Router);
1820
+ router.registerController(controllerClass, pathPrefix, routeGuards, routeMiddlewares);
1821
+ });
1749
1822
  InjectorExplorer.processPending(overrides);
1750
1823
  const noxApp = inject(NoxApp);
1751
1824
  if (config.routes?.length) {
1752
1825
  for (const route of config.routes) {
1753
- noxApp.lazy(route.path, route.load, route.guards, route.middlewares);
1826
+ if (route.load) {
1827
+ noxApp.lazy(route.path, route.load, route.guards, route.middlewares);
1828
+ }
1754
1829
  }
1755
1830
  }
1756
1831
  if (config.eagerLoad?.length) {
@@ -1762,29 +1837,53 @@ async function bootstrapApplication(config = {}) {
1762
1837
  __name(bootstrapApplication, "bootstrapApplication");
1763
1838
 
1764
1839
  // src/main.ts
1765
- init_exceptions();
1766
- init_controller_decorator();
1767
- init_injectable_decorator();
1768
- init_method_decorator();
1769
1840
  init_logger();
1770
1841
  init_forward_ref();
1771
- init_request();
1772
1842
 
1773
1843
  // src/internal/routes.ts
1774
1844
  function defineRoutes(routes) {
1775
- const paths = routes.map((r) => r.path.replace(/^\/+|\/+$/g, ""));
1845
+ const flat = flattenRoutes(routes);
1846
+ const paths = flat.map((r) => r.path);
1776
1847
  const duplicates = paths.filter((p, i) => paths.indexOf(p) !== i);
1777
1848
  if (duplicates.length > 0) {
1778
1849
  throw new Error(
1779
1850
  `[Noxus] Duplicate route prefixes detected: ${[...new Set(duplicates)].map((d) => `"${d}"`).join(", ")}`
1780
1851
  );
1781
1852
  }
1782
- return routes.map((r) => ({
1783
- ...r,
1784
- path: r.path.replace(/^\/+|\/+$/g, "")
1785
- }));
1853
+ const sorted = [...paths].sort();
1854
+ for (let i = 0; i < sorted.length - 1; i++) {
1855
+ const a = sorted[i];
1856
+ const b = sorted[i + 1];
1857
+ if (b.startsWith(a + "/")) {
1858
+ throw new Error(
1859
+ `[Noxus] Overlapping route prefixes detected: "${a}" and "${b}". Use nested children under "${a}" instead of declaring both as top-level routes.`
1860
+ );
1861
+ }
1862
+ }
1863
+ return flat;
1786
1864
  }
1787
1865
  __name(defineRoutes, "defineRoutes");
1866
+ function flattenRoutes(routes, parentPath = "", parentGuards = [], parentMiddlewares = []) {
1867
+ const result = [];
1868
+ for (const route of routes) {
1869
+ const path2 = [parentPath, route.path.replace(/^\/+|\/+$/g, "")].filter(Boolean).join("/");
1870
+ const guards = [.../* @__PURE__ */ new Set([...parentGuards, ...route.guards ?? []])];
1871
+ const middlewares = [.../* @__PURE__ */ new Set([...parentMiddlewares, ...route.middlewares ?? []])];
1872
+ if (route.load) {
1873
+ result.push({ ...route, path: path2, guards, middlewares });
1874
+ }
1875
+ if (route.children?.length) {
1876
+ result.push(...flattenRoutes(route.children, path2, guards, middlewares));
1877
+ }
1878
+ if (!route.load && !route.children?.length) {
1879
+ throw new Error(
1880
+ `[Noxus] Route "${path2}" has neither a load function nor children. It must have at least one of them.`
1881
+ );
1882
+ }
1883
+ }
1884
+ return result;
1885
+ }
1886
+ __name(flattenRoutes, "flattenRoutes");
1788
1887
  // Annotate the CommonJS export names for ESM import in node:
1789
1888
  0 && (module.exports = {
1790
1889
  AppInjector,
@@ -1838,6 +1937,7 @@ __name(defineRoutes, "defineRoutes");
1838
1937
  inject,
1839
1938
  isAtomicHttpMethod,
1840
1939
  isRendererEventMessage,
1940
+ resetRootInjector,
1841
1941
  token
1842
1942
  });
1843
1943
  /**