@noxfly/noxus 3.0.0-dev.3 → 3.0.0-dev.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.github/copilot-instructions.md +110 -14
- package/AGENTS.md +5 -0
- package/README.md +114 -7
- package/dist/child.d.mts +7 -1
- package/dist/child.d.ts +7 -1
- package/dist/child.js +402 -862
- package/dist/child.mjs +389 -850
- package/dist/main.d.mts +171 -125
- package/dist/main.d.ts +171 -125
- package/dist/main.js +967 -886
- package/dist/main.mjs +914 -834
- package/dist/renderer.d.mts +17 -2
- package/dist/renderer.d.ts +17 -2
- package/dist/renderer.js +161 -118
- package/dist/renderer.mjs +150 -106
- package/package.json +1 -1
- package/src/DI/app-injector.ts +22 -9
- package/src/DI/injector-explorer.ts +78 -20
- package/src/internal/app.ts +9 -7
- package/src/internal/bootstrap.ts +33 -1
- package/src/internal/renderer-client.ts +36 -0
- package/src/internal/request.ts +6 -1
- package/src/internal/router.ts +14 -2
- package/src/internal/routes.ts +75 -11
- package/src/internal/socket.ts +8 -6
- package/src/utils/radix-tree.ts +58 -25
- package/src/window/window-manager.ts +34 -0
package/dist/main.mjs
CHANGED
|
@@ -75,116 +75,6 @@ var init_token = __esm({
|
|
|
75
75
|
}
|
|
76
76
|
});
|
|
77
77
|
|
|
78
|
-
// src/DI/app-injector.ts
|
|
79
|
-
function keyOf(k) {
|
|
80
|
-
return k;
|
|
81
|
-
}
|
|
82
|
-
function inject(t) {
|
|
83
|
-
return RootInjector.resolve(t);
|
|
84
|
-
}
|
|
85
|
-
var _AppInjector, AppInjector, RootInjector;
|
|
86
|
-
var init_app_injector = __esm({
|
|
87
|
-
"src/DI/app-injector.ts"() {
|
|
88
|
-
"use strict";
|
|
89
|
-
init_forward_ref();
|
|
90
|
-
init_token();
|
|
91
|
-
__name(keyOf, "keyOf");
|
|
92
|
-
_AppInjector = class _AppInjector {
|
|
93
|
-
constructor(name = null) {
|
|
94
|
-
this.name = name;
|
|
95
|
-
this.bindings = /* @__PURE__ */ new Map();
|
|
96
|
-
this.singletons = /* @__PURE__ */ new Map();
|
|
97
|
-
this.scoped = /* @__PURE__ */ new Map();
|
|
98
|
-
}
|
|
99
|
-
/**
|
|
100
|
-
* Creates a child scope for per-request lifetime resolution.
|
|
101
|
-
*/
|
|
102
|
-
createScope() {
|
|
103
|
-
const scope = new _AppInjector();
|
|
104
|
-
scope.bindings = this.bindings;
|
|
105
|
-
scope.singletons = this.singletons;
|
|
106
|
-
return scope;
|
|
107
|
-
}
|
|
108
|
-
/**
|
|
109
|
-
* Registers a binding explicitly.
|
|
110
|
-
*/
|
|
111
|
-
register(key, implementation, lifetime, deps = []) {
|
|
112
|
-
const k = keyOf(key);
|
|
113
|
-
if (!this.bindings.has(k)) {
|
|
114
|
-
this.bindings.set(k, { lifetime, implementation, deps });
|
|
115
|
-
}
|
|
116
|
-
}
|
|
117
|
-
/**
|
|
118
|
-
* Resolves a dependency by token or class reference.
|
|
119
|
-
*/
|
|
120
|
-
resolve(target) {
|
|
121
|
-
if (target instanceof ForwardReference) {
|
|
122
|
-
return this._resolveForwardRef(target);
|
|
123
|
-
}
|
|
124
|
-
const k = keyOf(target);
|
|
125
|
-
if (this.singletons.has(k)) {
|
|
126
|
-
return this.singletons.get(k);
|
|
127
|
-
}
|
|
128
|
-
const binding = this.bindings.get(k);
|
|
129
|
-
if (!binding) {
|
|
130
|
-
const name = target instanceof Token ? target.description : target.name ?? "unknown";
|
|
131
|
-
throw new Error(
|
|
132
|
-
`[Noxus DI] No binding found for "${name}".
|
|
133
|
-
Did you forget to declare it in @Injectable({ deps }) or in bootstrapApplication({ singletons })?`
|
|
134
|
-
);
|
|
135
|
-
}
|
|
136
|
-
switch (binding.lifetime) {
|
|
137
|
-
case "transient":
|
|
138
|
-
return this._instantiate(binding);
|
|
139
|
-
case "scope": {
|
|
140
|
-
if (this.scoped.has(k)) return this.scoped.get(k);
|
|
141
|
-
const inst = this._instantiate(binding);
|
|
142
|
-
this.scoped.set(k, inst);
|
|
143
|
-
return inst;
|
|
144
|
-
}
|
|
145
|
-
case "singleton": {
|
|
146
|
-
if (this.singletons.has(k)) return this.singletons.get(k);
|
|
147
|
-
const inst = this._instantiate(binding);
|
|
148
|
-
this.singletons.set(k, inst);
|
|
149
|
-
if (binding.instance === void 0) {
|
|
150
|
-
binding.instance = inst;
|
|
151
|
-
}
|
|
152
|
-
return inst;
|
|
153
|
-
}
|
|
154
|
-
}
|
|
155
|
-
}
|
|
156
|
-
// -------------------------------------------------------------------------
|
|
157
|
-
_resolveForwardRef(ref) {
|
|
158
|
-
return new Proxy({}, {
|
|
159
|
-
get: /* @__PURE__ */ __name((_obj, prop, receiver) => {
|
|
160
|
-
const realType = ref.forwardRefFn();
|
|
161
|
-
const instance = this.resolve(realType);
|
|
162
|
-
const value = Reflect.get(instance, prop, receiver);
|
|
163
|
-
return typeof value === "function" ? value.bind(instance) : value;
|
|
164
|
-
}, "get"),
|
|
165
|
-
set: /* @__PURE__ */ __name((_obj, prop, value, receiver) => {
|
|
166
|
-
const realType = ref.forwardRefFn();
|
|
167
|
-
const instance = this.resolve(realType);
|
|
168
|
-
return Reflect.set(instance, prop, value, receiver);
|
|
169
|
-
}, "set"),
|
|
170
|
-
getPrototypeOf: /* @__PURE__ */ __name(() => {
|
|
171
|
-
const realType = ref.forwardRefFn();
|
|
172
|
-
return realType.prototype;
|
|
173
|
-
}, "getPrototypeOf")
|
|
174
|
-
});
|
|
175
|
-
}
|
|
176
|
-
_instantiate(binding) {
|
|
177
|
-
const resolvedDeps = binding.deps.map((dep) => this.resolve(dep));
|
|
178
|
-
return new binding.implementation(...resolvedDeps);
|
|
179
|
-
}
|
|
180
|
-
};
|
|
181
|
-
__name(_AppInjector, "AppInjector");
|
|
182
|
-
AppInjector = _AppInjector;
|
|
183
|
-
RootInjector = new AppInjector("root");
|
|
184
|
-
__name(inject, "inject");
|
|
185
|
-
}
|
|
186
|
-
});
|
|
187
|
-
|
|
188
78
|
// src/utils/logger.ts
|
|
189
79
|
import * as fs from "fs";
|
|
190
80
|
import * as path from "path";
|
|
@@ -433,6 +323,10 @@ var init_logger = __esm({
|
|
|
433
323
|
});
|
|
434
324
|
|
|
435
325
|
// src/DI/injector-explorer.ts
|
|
326
|
+
var injector_explorer_exports = {};
|
|
327
|
+
__export(injector_explorer_exports, {
|
|
328
|
+
InjectorExplorer: () => InjectorExplorer
|
|
329
|
+
});
|
|
436
330
|
var _InjectorExplorer, InjectorExplorer;
|
|
437
331
|
var init_injector_explorer = __esm({
|
|
438
332
|
"src/DI/injector-explorer.ts"() {
|
|
@@ -443,6 +337,13 @@ var init_injector_explorer = __esm({
|
|
|
443
337
|
// -------------------------------------------------------------------------
|
|
444
338
|
// Public API
|
|
445
339
|
// -------------------------------------------------------------------------
|
|
340
|
+
/**
|
|
341
|
+
* Sets the callback used to register controllers.
|
|
342
|
+
* Must be called once before processPending (typically by bootstrapApplication).
|
|
343
|
+
*/
|
|
344
|
+
static setControllerRegistrar(registrar) {
|
|
345
|
+
_InjectorExplorer.controllerRegistrar = registrar;
|
|
346
|
+
}
|
|
446
347
|
static enqueue(reg) {
|
|
447
348
|
if (_InjectorExplorer.processed && !_InjectorExplorer.accumulating) {
|
|
448
349
|
_InjectorExplorer._registerImmediate(reg);
|
|
@@ -468,16 +369,37 @@ var init_injector_explorer = __esm({
|
|
|
468
369
|
/**
|
|
469
370
|
* Exits accumulation mode and flushes queued registrations
|
|
470
371
|
* with the same two-phase guarantee as processPending.
|
|
372
|
+
* Serialised through a lock to prevent concurrent lazy loads from corrupting the queue.
|
|
471
373
|
*/
|
|
472
374
|
static flushAccumulated(routeGuards = [], routeMiddlewares = [], pathPrefix = "") {
|
|
473
|
-
_InjectorExplorer.
|
|
474
|
-
|
|
375
|
+
_InjectorExplorer.loadingLock = _InjectorExplorer.loadingLock.then(() => {
|
|
376
|
+
_InjectorExplorer.accumulating = false;
|
|
377
|
+
const queue = [..._InjectorExplorer.pending];
|
|
378
|
+
_InjectorExplorer.pending.length = 0;
|
|
379
|
+
_InjectorExplorer._phaseOne(queue);
|
|
380
|
+
for (const reg of queue) {
|
|
381
|
+
if (reg.isController) reg.pathPrefix = pathPrefix;
|
|
382
|
+
}
|
|
383
|
+
_InjectorExplorer._phaseTwo(queue, void 0, routeGuards, routeMiddlewares);
|
|
384
|
+
});
|
|
385
|
+
return _InjectorExplorer.loadingLock;
|
|
386
|
+
}
|
|
387
|
+
/**
|
|
388
|
+
* Returns a Promise that resolves once all pending flushAccumulated calls
|
|
389
|
+
* have completed. Useful for awaiting lazy-load serialisation.
|
|
390
|
+
*/
|
|
391
|
+
static waitForFlush() {
|
|
392
|
+
return _InjectorExplorer.loadingLock;
|
|
393
|
+
}
|
|
394
|
+
/**
|
|
395
|
+
* Resets the explorer state. Intended for tests only.
|
|
396
|
+
*/
|
|
397
|
+
static reset() {
|
|
475
398
|
_InjectorExplorer.pending.length = 0;
|
|
476
|
-
_InjectorExplorer.
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
_InjectorExplorer._phaseTwo(queue, void 0, routeGuards, routeMiddlewares);
|
|
399
|
+
_InjectorExplorer.processed = false;
|
|
400
|
+
_InjectorExplorer.accumulating = false;
|
|
401
|
+
_InjectorExplorer.loadingLock = Promise.resolve();
|
|
402
|
+
_InjectorExplorer.controllerRegistrar = null;
|
|
481
403
|
}
|
|
482
404
|
// -------------------------------------------------------------------------
|
|
483
405
|
// Private helpers
|
|
@@ -488,8 +410,15 @@ var init_injector_explorer = __esm({
|
|
|
488
410
|
RootInjector.register(reg.key, reg.implementation, reg.lifetime, reg.deps);
|
|
489
411
|
}
|
|
490
412
|
}
|
|
491
|
-
/** Phase 2: resolve singletons and register controllers
|
|
413
|
+
/** Phase 2: validate deps, resolve singletons and register controllers via the registrar callback. */
|
|
492
414
|
static _phaseTwo(queue, overrides, routeGuards = [], routeMiddlewares = []) {
|
|
415
|
+
for (const reg of queue) {
|
|
416
|
+
for (const dep of reg.deps) {
|
|
417
|
+
if (!RootInjector.bindings.has(dep) && !RootInjector.singletons.has(dep)) {
|
|
418
|
+
Logger.warn(`[Noxus DI] "${reg.implementation.name}" declares dep "${dep.name ?? dep}" which has no binding`);
|
|
419
|
+
}
|
|
420
|
+
}
|
|
421
|
+
}
|
|
493
422
|
for (const reg of queue) {
|
|
494
423
|
if (overrides?.has(reg.key)) {
|
|
495
424
|
const override = overrides.get(reg.key);
|
|
@@ -501,9 +430,15 @@ var init_injector_explorer = __esm({
|
|
|
501
430
|
RootInjector.resolve(reg.key);
|
|
502
431
|
}
|
|
503
432
|
if (reg.isController) {
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
433
|
+
if (!_InjectorExplorer.controllerRegistrar) {
|
|
434
|
+
throw new Error("[Noxus DI] No controller registrar set. Call InjectorExplorer.setControllerRegistrar() before processing.");
|
|
435
|
+
}
|
|
436
|
+
_InjectorExplorer.controllerRegistrar(
|
|
437
|
+
reg.implementation,
|
|
438
|
+
reg.pathPrefix ?? "",
|
|
439
|
+
routeGuards,
|
|
440
|
+
routeMiddlewares
|
|
441
|
+
);
|
|
507
442
|
} else if (reg.lifetime !== "singleton") {
|
|
508
443
|
Logger.log(`Registered ${reg.implementation.name} as ${reg.lifetime}`);
|
|
509
444
|
}
|
|
@@ -514,10 +449,8 @@ var init_injector_explorer = __esm({
|
|
|
514
449
|
if (reg.lifetime === "singleton") {
|
|
515
450
|
RootInjector.resolve(reg.key);
|
|
516
451
|
}
|
|
517
|
-
if (reg.isController) {
|
|
518
|
-
|
|
519
|
-
const router = RootInjector.resolve(Router2);
|
|
520
|
-
router.registerController(reg.implementation);
|
|
452
|
+
if (reg.isController && _InjectorExplorer.controllerRegistrar) {
|
|
453
|
+
_InjectorExplorer.controllerRegistrar(reg.implementation, "", [], []);
|
|
521
454
|
}
|
|
522
455
|
}
|
|
523
456
|
};
|
|
@@ -525,11 +458,136 @@ var init_injector_explorer = __esm({
|
|
|
525
458
|
_InjectorExplorer.pending = [];
|
|
526
459
|
_InjectorExplorer.processed = false;
|
|
527
460
|
_InjectorExplorer.accumulating = false;
|
|
461
|
+
_InjectorExplorer.loadingLock = Promise.resolve();
|
|
462
|
+
_InjectorExplorer.controllerRegistrar = null;
|
|
528
463
|
InjectorExplorer = _InjectorExplorer;
|
|
529
464
|
}
|
|
530
465
|
});
|
|
531
466
|
|
|
467
|
+
// src/DI/app-injector.ts
|
|
468
|
+
function keyOf(k) {
|
|
469
|
+
return k;
|
|
470
|
+
}
|
|
471
|
+
function resetRootInjector() {
|
|
472
|
+
RootInjector.bindings.clear();
|
|
473
|
+
RootInjector.singletons.clear();
|
|
474
|
+
RootInjector.scoped.clear();
|
|
475
|
+
const { InjectorExplorer: InjectorExplorer2 } = (init_injector_explorer(), __toCommonJS(injector_explorer_exports));
|
|
476
|
+
InjectorExplorer2.reset();
|
|
477
|
+
}
|
|
478
|
+
function inject(t) {
|
|
479
|
+
return RootInjector.resolve(t);
|
|
480
|
+
}
|
|
481
|
+
var _AppInjector, AppInjector, RootInjector;
|
|
482
|
+
var init_app_injector = __esm({
|
|
483
|
+
"src/DI/app-injector.ts"() {
|
|
484
|
+
"use strict";
|
|
485
|
+
init_forward_ref();
|
|
486
|
+
init_token();
|
|
487
|
+
__name(keyOf, "keyOf");
|
|
488
|
+
_AppInjector = class _AppInjector {
|
|
489
|
+
constructor(name = null) {
|
|
490
|
+
this.name = name;
|
|
491
|
+
this.bindings = /* @__PURE__ */ new Map();
|
|
492
|
+
this.singletons = /* @__PURE__ */ new Map();
|
|
493
|
+
this.scoped = /* @__PURE__ */ new Map();
|
|
494
|
+
}
|
|
495
|
+
/**
|
|
496
|
+
* Creates a child scope for per-request lifetime resolution.
|
|
497
|
+
*/
|
|
498
|
+
createScope() {
|
|
499
|
+
const scope = new _AppInjector();
|
|
500
|
+
scope.bindings = this.bindings;
|
|
501
|
+
scope.singletons = this.singletons;
|
|
502
|
+
return scope;
|
|
503
|
+
}
|
|
504
|
+
/**
|
|
505
|
+
* Registers a binding explicitly.
|
|
506
|
+
*/
|
|
507
|
+
register(key, implementation, lifetime, deps = []) {
|
|
508
|
+
const k = keyOf(key);
|
|
509
|
+
if (!this.bindings.has(k)) {
|
|
510
|
+
this.bindings.set(k, { lifetime, implementation, deps });
|
|
511
|
+
}
|
|
512
|
+
}
|
|
513
|
+
/**
|
|
514
|
+
* Resolves a dependency by token or class reference.
|
|
515
|
+
*/
|
|
516
|
+
resolve(target) {
|
|
517
|
+
if (target instanceof ForwardReference) {
|
|
518
|
+
return this._resolveForwardRef(target);
|
|
519
|
+
}
|
|
520
|
+
const k = keyOf(target);
|
|
521
|
+
if (this.singletons.has(k)) {
|
|
522
|
+
return this.singletons.get(k);
|
|
523
|
+
}
|
|
524
|
+
const binding = this.bindings.get(k);
|
|
525
|
+
if (!binding) {
|
|
526
|
+
const name = target instanceof Token ? target.description : target.name ?? "unknown";
|
|
527
|
+
throw new Error(
|
|
528
|
+
`[Noxus DI] No binding found for "${name}".
|
|
529
|
+
Did you forget to declare it in @Injectable({ deps }) or in bootstrapApplication({ singletons })?`
|
|
530
|
+
);
|
|
531
|
+
}
|
|
532
|
+
switch (binding.lifetime) {
|
|
533
|
+
case "transient":
|
|
534
|
+
return this._instantiate(binding);
|
|
535
|
+
case "scope": {
|
|
536
|
+
if (this.scoped.has(k)) return this.scoped.get(k);
|
|
537
|
+
const inst = this._instantiate(binding);
|
|
538
|
+
this.scoped.set(k, inst);
|
|
539
|
+
return inst;
|
|
540
|
+
}
|
|
541
|
+
case "singleton": {
|
|
542
|
+
if (this.singletons.has(k)) return this.singletons.get(k);
|
|
543
|
+
const inst = this._instantiate(binding);
|
|
544
|
+
this.singletons.set(k, inst);
|
|
545
|
+
if (binding.instance === void 0) {
|
|
546
|
+
binding.instance = inst;
|
|
547
|
+
}
|
|
548
|
+
return inst;
|
|
549
|
+
}
|
|
550
|
+
}
|
|
551
|
+
}
|
|
552
|
+
// -------------------------------------------------------------------------
|
|
553
|
+
_resolveForwardRef(ref) {
|
|
554
|
+
let resolved;
|
|
555
|
+
return new Proxy({}, {
|
|
556
|
+
get: /* @__PURE__ */ __name((_obj, prop, receiver) => {
|
|
557
|
+
resolved ?? (resolved = this.resolve(ref.forwardRefFn()));
|
|
558
|
+
const value = Reflect.get(resolved, prop, receiver);
|
|
559
|
+
return typeof value === "function" ? value.bind(resolved) : value;
|
|
560
|
+
}, "get"),
|
|
561
|
+
set: /* @__PURE__ */ __name((_obj, prop, value, receiver) => {
|
|
562
|
+
resolved ?? (resolved = this.resolve(ref.forwardRefFn()));
|
|
563
|
+
return Reflect.set(resolved, prop, value, receiver);
|
|
564
|
+
}, "set"),
|
|
565
|
+
getPrototypeOf: /* @__PURE__ */ __name(() => {
|
|
566
|
+
resolved ?? (resolved = this.resolve(ref.forwardRefFn()));
|
|
567
|
+
return Object.getPrototypeOf(resolved);
|
|
568
|
+
}, "getPrototypeOf")
|
|
569
|
+
});
|
|
570
|
+
}
|
|
571
|
+
_instantiate(binding) {
|
|
572
|
+
const resolvedDeps = binding.deps.map((dep) => this.resolve(dep));
|
|
573
|
+
return new binding.implementation(...resolvedDeps);
|
|
574
|
+
}
|
|
575
|
+
};
|
|
576
|
+
__name(_AppInjector, "AppInjector");
|
|
577
|
+
AppInjector = _AppInjector;
|
|
578
|
+
RootInjector = new AppInjector("root");
|
|
579
|
+
__name(resetRootInjector, "resetRootInjector");
|
|
580
|
+
__name(inject, "inject");
|
|
581
|
+
}
|
|
582
|
+
});
|
|
583
|
+
|
|
584
|
+
// src/main.ts
|
|
585
|
+
init_app_injector();
|
|
586
|
+
init_token();
|
|
587
|
+
|
|
532
588
|
// src/decorators/controller.decorator.ts
|
|
589
|
+
init_injector_explorer();
|
|
590
|
+
var controllerMetaMap = /* @__PURE__ */ new WeakMap();
|
|
533
591
|
function Controller(options = {}) {
|
|
534
592
|
return (target) => {
|
|
535
593
|
const meta = {
|
|
@@ -545,21 +603,15 @@ function Controller(options = {}) {
|
|
|
545
603
|
});
|
|
546
604
|
};
|
|
547
605
|
}
|
|
606
|
+
__name(Controller, "Controller");
|
|
548
607
|
function getControllerMetadata(target) {
|
|
549
608
|
return controllerMetaMap.get(target);
|
|
550
609
|
}
|
|
551
|
-
|
|
552
|
-
var init_controller_decorator = __esm({
|
|
553
|
-
"src/decorators/controller.decorator.ts"() {
|
|
554
|
-
"use strict";
|
|
555
|
-
init_injector_explorer();
|
|
556
|
-
controllerMetaMap = /* @__PURE__ */ new WeakMap();
|
|
557
|
-
__name(Controller, "Controller");
|
|
558
|
-
__name(getControllerMetadata, "getControllerMetadata");
|
|
559
|
-
}
|
|
560
|
-
});
|
|
610
|
+
__name(getControllerMetadata, "getControllerMetadata");
|
|
561
611
|
|
|
562
612
|
// src/decorators/injectable.decorator.ts
|
|
613
|
+
init_injector_explorer();
|
|
614
|
+
init_token();
|
|
563
615
|
function Injectable(options = {}) {
|
|
564
616
|
const { lifetime = "scope", deps = [] } = options;
|
|
565
617
|
return (target) => {
|
|
@@ -576,19 +628,15 @@ function Injectable(options = {}) {
|
|
|
576
628
|
});
|
|
577
629
|
};
|
|
578
630
|
}
|
|
579
|
-
|
|
580
|
-
"src/decorators/injectable.decorator.ts"() {
|
|
581
|
-
"use strict";
|
|
582
|
-
init_injector_explorer();
|
|
583
|
-
init_token();
|
|
584
|
-
__name(Injectable, "Injectable");
|
|
585
|
-
}
|
|
586
|
-
});
|
|
631
|
+
__name(Injectable, "Injectable");
|
|
587
632
|
|
|
588
633
|
// src/decorators/method.decorator.ts
|
|
634
|
+
var ATOMIC_METHODS = /* @__PURE__ */ new Set(["GET", "POST", "PUT", "PATCH", "DELETE"]);
|
|
589
635
|
function isAtomicHttpMethod(m) {
|
|
590
636
|
return typeof m === "string" && ATOMIC_METHODS.has(m);
|
|
591
637
|
}
|
|
638
|
+
__name(isAtomicHttpMethod, "isAtomicHttpMethod");
|
|
639
|
+
var routeMetaMap = /* @__PURE__ */ new WeakMap();
|
|
592
640
|
function createRouteDecorator(verb) {
|
|
593
641
|
return (path2, options = {}) => {
|
|
594
642
|
return (target, propertyKey) => {
|
|
@@ -605,399 +653,416 @@ function createRouteDecorator(verb) {
|
|
|
605
653
|
};
|
|
606
654
|
};
|
|
607
655
|
}
|
|
656
|
+
__name(createRouteDecorator, "createRouteDecorator");
|
|
608
657
|
function getRouteMetadata(target) {
|
|
609
658
|
return routeMetaMap.get(target) ?? [];
|
|
610
659
|
}
|
|
611
|
-
|
|
612
|
-
var
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
Post = createRouteDecorator("POST");
|
|
622
|
-
Put = createRouteDecorator("PUT");
|
|
623
|
-
Patch = createRouteDecorator("PATCH");
|
|
624
|
-
Delete = createRouteDecorator("DELETE");
|
|
625
|
-
}
|
|
626
|
-
});
|
|
660
|
+
__name(getRouteMetadata, "getRouteMetadata");
|
|
661
|
+
var Get = createRouteDecorator("GET");
|
|
662
|
+
var Post = createRouteDecorator("POST");
|
|
663
|
+
var Put = createRouteDecorator("PUT");
|
|
664
|
+
var Patch = createRouteDecorator("PATCH");
|
|
665
|
+
var Delete = createRouteDecorator("DELETE");
|
|
666
|
+
|
|
667
|
+
// src/internal/router.ts
|
|
668
|
+
init_injector_explorer();
|
|
669
|
+
init_logger();
|
|
627
670
|
|
|
628
671
|
// src/utils/radix-tree.ts
|
|
629
|
-
var _RadixNode
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
this.isParam = segment.startsWith(":");
|
|
642
|
-
if (this.isParam) {
|
|
643
|
-
this.paramName = segment.slice(1);
|
|
644
|
-
}
|
|
645
|
-
}
|
|
646
|
-
/**
|
|
647
|
-
* Matches a child node against a given segment.
|
|
648
|
-
* This method checks if the segment matches any of the children nodes.
|
|
649
|
-
* @param segment - The segment to match against the children of this node.
|
|
650
|
-
* @returns A child node that matches the segment, or undefined if no match is found.
|
|
651
|
-
*/
|
|
652
|
-
matchChild(segment) {
|
|
653
|
-
for (const child of this.children) {
|
|
654
|
-
if (child.isParam || segment.startsWith(child.segment))
|
|
655
|
-
return child;
|
|
656
|
-
}
|
|
657
|
-
return void 0;
|
|
658
|
-
}
|
|
659
|
-
/**
|
|
660
|
-
* Finds a child node that matches the segment exactly.
|
|
661
|
-
* This method checks if there is a child node that matches the segment exactly.
|
|
662
|
-
* @param segment - The segment to find an exact match for among the children of this node.
|
|
663
|
-
* @returns A child node that matches the segment exactly, or undefined if no match is found.
|
|
664
|
-
*/
|
|
665
|
-
findExactChild(segment) {
|
|
666
|
-
return this.children.find((c) => c.segment === segment);
|
|
667
|
-
}
|
|
668
|
-
/**
|
|
669
|
-
* Adds a child node to this node's children.
|
|
670
|
-
* This method adds a new child node to the list of children for this node.
|
|
671
|
-
* @param node - The child node to add to this node's children.
|
|
672
|
-
*/
|
|
673
|
-
addChild(node) {
|
|
674
|
-
this.children.push(node);
|
|
675
|
-
}
|
|
676
|
-
};
|
|
677
|
-
__name(_RadixNode, "RadixNode");
|
|
678
|
-
RadixNode = _RadixNode;
|
|
679
|
-
_RadixTree = class _RadixTree {
|
|
680
|
-
constructor() {
|
|
681
|
-
this.root = new RadixNode("");
|
|
682
|
-
}
|
|
683
|
-
/**
|
|
684
|
-
* Inserts a path and its associated value into the Radix Tree.
|
|
685
|
-
* This method normalizes the path and inserts it into the tree, associating it with
|
|
686
|
-
* @param path - The path to insert into the tree.
|
|
687
|
-
* @param value - The value to associate with the path.
|
|
688
|
-
*/
|
|
689
|
-
insert(path2, value) {
|
|
690
|
-
const segments = this.normalize(path2);
|
|
691
|
-
this.insertRecursive(this.root, segments, value);
|
|
692
|
-
}
|
|
693
|
-
/**
|
|
694
|
-
* Recursively inserts a path into the Radix Tree.
|
|
695
|
-
* This method traverses the tree and inserts the segments of the path, creating new nodes
|
|
696
|
-
* @param node - The node to start inserting from.
|
|
697
|
-
* @param segments - The segments of the path to insert.
|
|
698
|
-
* @param value - The value to associate with the path.
|
|
699
|
-
*/
|
|
700
|
-
insertRecursive(node, segments, value) {
|
|
701
|
-
if (segments.length === 0) {
|
|
702
|
-
node.value = value;
|
|
703
|
-
return;
|
|
704
|
-
}
|
|
705
|
-
const segment = segments[0] ?? "";
|
|
706
|
-
let child = node.children.find(
|
|
707
|
-
(c) => c.isParam === segment.startsWith(":") && (c.isParam || c.segment === segment)
|
|
708
|
-
);
|
|
709
|
-
if (!child) {
|
|
710
|
-
child = new RadixNode(segment);
|
|
711
|
-
node.addChild(child);
|
|
712
|
-
}
|
|
713
|
-
this.insertRecursive(child, segments.slice(1), value);
|
|
714
|
-
}
|
|
715
|
-
/**
|
|
716
|
-
* Searches for a path in the Radix Tree.
|
|
717
|
-
* This method normalizes the path and searches for it in the tree, returning the node
|
|
718
|
-
* @param path - The path to search for in the Radix Tree.
|
|
719
|
-
* @returns An ISearchResult containing the node and parameters if a match is found, otherwise undefined.
|
|
720
|
-
*/
|
|
721
|
-
search(path2) {
|
|
722
|
-
const segments = this.normalize(path2);
|
|
723
|
-
return this.searchRecursive(this.root, segments, {});
|
|
724
|
-
}
|
|
725
|
-
/**
|
|
726
|
-
* Recursively searches for a path in the Radix Tree.
|
|
727
|
-
* This method traverses the tree and searches for the segments of the path, collecting parameters
|
|
728
|
-
* @param node - The node to start searching from.
|
|
729
|
-
* @param segments - The segments of the path to search for.
|
|
730
|
-
* @param params - The parameters collected during the search.
|
|
731
|
-
* @returns An ISearchResult containing the node and parameters if a match is found, otherwise undefined.
|
|
732
|
-
*/
|
|
733
|
-
searchRecursive(node, segments, params) {
|
|
734
|
-
if (segments.length === 0) {
|
|
735
|
-
if (node.value !== void 0) {
|
|
736
|
-
return {
|
|
737
|
-
node,
|
|
738
|
-
params
|
|
739
|
-
};
|
|
740
|
-
}
|
|
741
|
-
return void 0;
|
|
742
|
-
}
|
|
743
|
-
const [segment, ...rest] = segments;
|
|
744
|
-
for (const child of node.children) {
|
|
745
|
-
if (child.isParam) {
|
|
746
|
-
const paramName = child.paramName;
|
|
747
|
-
const childParams = {
|
|
748
|
-
...params,
|
|
749
|
-
[paramName]: segment ?? ""
|
|
750
|
-
};
|
|
751
|
-
if (rest.length === 0) {
|
|
752
|
-
return {
|
|
753
|
-
node: child,
|
|
754
|
-
params: childParams
|
|
755
|
-
};
|
|
756
|
-
}
|
|
757
|
-
const result = this.searchRecursive(child, rest, childParams);
|
|
758
|
-
if (result)
|
|
759
|
-
return result;
|
|
760
|
-
} else if (segment === child.segment) {
|
|
761
|
-
if (rest.length === 0) {
|
|
762
|
-
return {
|
|
763
|
-
node: child,
|
|
764
|
-
params
|
|
765
|
-
};
|
|
766
|
-
}
|
|
767
|
-
const result = this.searchRecursive(child, rest, params);
|
|
768
|
-
if (result)
|
|
769
|
-
return result;
|
|
770
|
-
}
|
|
771
|
-
}
|
|
772
|
-
return void 0;
|
|
773
|
-
}
|
|
774
|
-
/**
|
|
775
|
-
* Normalizes a path into an array of segments.
|
|
776
|
-
* This method removes leading and trailing slashes, splits the path by slashes, and
|
|
777
|
-
* @param path - The path to normalize.
|
|
778
|
-
* @returns An array of normalized path segments.
|
|
779
|
-
*/
|
|
780
|
-
normalize(path2) {
|
|
781
|
-
const segments = path2.replace(/^\/+|\/+$/g, "").split("/").filter(Boolean);
|
|
782
|
-
return ["", ...segments];
|
|
783
|
-
}
|
|
784
|
-
};
|
|
785
|
-
__name(_RadixTree, "RadixTree");
|
|
786
|
-
RadixTree = _RadixTree;
|
|
672
|
+
var _RadixNode = class _RadixNode {
|
|
673
|
+
/**
|
|
674
|
+
* Creates a new RadixNode.
|
|
675
|
+
* @param segment - The segment of the path this node represents.
|
|
676
|
+
*/
|
|
677
|
+
constructor(segment) {
|
|
678
|
+
this.children = [];
|
|
679
|
+
this.segment = segment;
|
|
680
|
+
this.isParam = segment.startsWith(":");
|
|
681
|
+
if (this.isParam) {
|
|
682
|
+
this.paramName = segment.slice(1);
|
|
683
|
+
}
|
|
787
684
|
}
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
constructor() {
|
|
895
|
-
super(...arguments);
|
|
896
|
-
this.status = 429;
|
|
897
|
-
}
|
|
898
|
-
};
|
|
899
|
-
__name(_TooManyRequestsException, "TooManyRequestsException");
|
|
900
|
-
TooManyRequestsException = _TooManyRequestsException;
|
|
901
|
-
_InternalServerException = class _InternalServerException extends ResponseException {
|
|
902
|
-
constructor() {
|
|
903
|
-
super(...arguments);
|
|
904
|
-
this.status = 500;
|
|
905
|
-
}
|
|
906
|
-
};
|
|
907
|
-
__name(_InternalServerException, "InternalServerException");
|
|
908
|
-
InternalServerException = _InternalServerException;
|
|
909
|
-
_NotImplementedException = class _NotImplementedException extends ResponseException {
|
|
910
|
-
constructor() {
|
|
911
|
-
super(...arguments);
|
|
912
|
-
this.status = 501;
|
|
913
|
-
}
|
|
914
|
-
};
|
|
915
|
-
__name(_NotImplementedException, "NotImplementedException");
|
|
916
|
-
NotImplementedException = _NotImplementedException;
|
|
917
|
-
_BadGatewayException = class _BadGatewayException extends ResponseException {
|
|
918
|
-
constructor() {
|
|
919
|
-
super(...arguments);
|
|
920
|
-
this.status = 502;
|
|
921
|
-
}
|
|
922
|
-
};
|
|
923
|
-
__name(_BadGatewayException, "BadGatewayException");
|
|
924
|
-
BadGatewayException = _BadGatewayException;
|
|
925
|
-
_ServiceUnavailableException = class _ServiceUnavailableException extends ResponseException {
|
|
926
|
-
constructor() {
|
|
927
|
-
super(...arguments);
|
|
928
|
-
this.status = 503;
|
|
929
|
-
}
|
|
930
|
-
};
|
|
931
|
-
__name(_ServiceUnavailableException, "ServiceUnavailableException");
|
|
932
|
-
ServiceUnavailableException = _ServiceUnavailableException;
|
|
933
|
-
_GatewayTimeoutException = class _GatewayTimeoutException extends ResponseException {
|
|
934
|
-
constructor() {
|
|
935
|
-
super(...arguments);
|
|
936
|
-
this.status = 504;
|
|
937
|
-
}
|
|
938
|
-
};
|
|
939
|
-
__name(_GatewayTimeoutException, "GatewayTimeoutException");
|
|
940
|
-
GatewayTimeoutException = _GatewayTimeoutException;
|
|
941
|
-
_HttpVersionNotSupportedException = class _HttpVersionNotSupportedException extends ResponseException {
|
|
942
|
-
constructor() {
|
|
943
|
-
super(...arguments);
|
|
944
|
-
this.status = 505;
|
|
945
|
-
}
|
|
946
|
-
};
|
|
947
|
-
__name(_HttpVersionNotSupportedException, "HttpVersionNotSupportedException");
|
|
948
|
-
HttpVersionNotSupportedException = _HttpVersionNotSupportedException;
|
|
949
|
-
_VariantAlsoNegotiatesException = class _VariantAlsoNegotiatesException extends ResponseException {
|
|
950
|
-
constructor() {
|
|
951
|
-
super(...arguments);
|
|
952
|
-
this.status = 506;
|
|
953
|
-
}
|
|
954
|
-
};
|
|
955
|
-
__name(_VariantAlsoNegotiatesException, "VariantAlsoNegotiatesException");
|
|
956
|
-
VariantAlsoNegotiatesException = _VariantAlsoNegotiatesException;
|
|
957
|
-
_InsufficientStorageException = class _InsufficientStorageException extends ResponseException {
|
|
958
|
-
constructor() {
|
|
959
|
-
super(...arguments);
|
|
960
|
-
this.status = 507;
|
|
961
|
-
}
|
|
962
|
-
};
|
|
963
|
-
__name(_InsufficientStorageException, "InsufficientStorageException");
|
|
964
|
-
InsufficientStorageException = _InsufficientStorageException;
|
|
965
|
-
_LoopDetectedException = class _LoopDetectedException extends ResponseException {
|
|
966
|
-
constructor() {
|
|
967
|
-
super(...arguments);
|
|
968
|
-
this.status = 508;
|
|
685
|
+
/**
|
|
686
|
+
* Matches a child node against a given segment.
|
|
687
|
+
* This method checks if the segment matches any of the children nodes.
|
|
688
|
+
* @param segment - The segment to match against the children of this node.
|
|
689
|
+
* @returns A child node that matches the segment, or undefined if no match is found.
|
|
690
|
+
*/
|
|
691
|
+
matchChild(segment) {
|
|
692
|
+
for (const child of this.children) {
|
|
693
|
+
if (child.isParam || segment.startsWith(child.segment))
|
|
694
|
+
return child;
|
|
695
|
+
}
|
|
696
|
+
return void 0;
|
|
697
|
+
}
|
|
698
|
+
/**
|
|
699
|
+
* Finds a child node that matches the segment exactly.
|
|
700
|
+
* This method checks if there is a child node that matches the segment exactly.
|
|
701
|
+
* @param segment - The segment to find an exact match for among the children of this node.
|
|
702
|
+
* @returns A child node that matches the segment exactly, or undefined if no match is found.
|
|
703
|
+
*/
|
|
704
|
+
findExactChild(segment) {
|
|
705
|
+
return this.children.find((c) => c.segment === segment);
|
|
706
|
+
}
|
|
707
|
+
/**
|
|
708
|
+
* Adds a child node to this node's children.
|
|
709
|
+
* This method adds a new child node to the list of children for this node.
|
|
710
|
+
* @param node - The child node to add to this node's children.
|
|
711
|
+
*/
|
|
712
|
+
addChild(node) {
|
|
713
|
+
this.children.push(node);
|
|
714
|
+
}
|
|
715
|
+
};
|
|
716
|
+
__name(_RadixNode, "RadixNode");
|
|
717
|
+
var RadixNode = _RadixNode;
|
|
718
|
+
var _RadixTree = class _RadixTree {
|
|
719
|
+
constructor() {
|
|
720
|
+
this.root = new RadixNode("");
|
|
721
|
+
}
|
|
722
|
+
/**
|
|
723
|
+
* Inserts a path and its associated value into the Radix Tree.
|
|
724
|
+
* This method normalizes the path and inserts it into the tree, associating it with
|
|
725
|
+
* @param path - The path to insert into the tree.
|
|
726
|
+
* @param value - The value to associate with the path.
|
|
727
|
+
*/
|
|
728
|
+
insert(path2, value) {
|
|
729
|
+
const segments = this.normalize(path2);
|
|
730
|
+
this.insertRecursive(this.root, segments, value);
|
|
731
|
+
}
|
|
732
|
+
/**
|
|
733
|
+
* Recursively inserts a path into the Radix Tree.
|
|
734
|
+
* This method traverses the tree and inserts the segments of the path, creating new nodes
|
|
735
|
+
* @param node - The node to start inserting from.
|
|
736
|
+
* @param segments - The segments of the path to insert.
|
|
737
|
+
* @param value - The value to associate with the path.
|
|
738
|
+
*/
|
|
739
|
+
insertRecursive(node, segments, value) {
|
|
740
|
+
if (segments.length === 0) {
|
|
741
|
+
node.value = value;
|
|
742
|
+
return;
|
|
743
|
+
}
|
|
744
|
+
const segment = segments[0] ?? "";
|
|
745
|
+
let child = node.children.find(
|
|
746
|
+
(c) => c.isParam === segment.startsWith(":") && (c.isParam || c.segment === segment)
|
|
747
|
+
);
|
|
748
|
+
if (!child) {
|
|
749
|
+
child = new RadixNode(segment);
|
|
750
|
+
node.addChild(child);
|
|
751
|
+
}
|
|
752
|
+
this.insertRecursive(child, segments.slice(1), value);
|
|
753
|
+
}
|
|
754
|
+
/**
|
|
755
|
+
* Searches for a path in the Radix Tree.
|
|
756
|
+
* This method normalizes the path and searches for it in the tree, returning the node
|
|
757
|
+
* @param path - The path to search for in the Radix Tree.
|
|
758
|
+
* @returns An ISearchResult containing the node and parameters if a match is found, otherwise undefined.
|
|
759
|
+
*/
|
|
760
|
+
search(path2) {
|
|
761
|
+
const segments = this.normalize(path2);
|
|
762
|
+
return this.searchRecursive(this.root, segments, {});
|
|
763
|
+
}
|
|
764
|
+
collectValues(node, values = []) {
|
|
765
|
+
if (!node) {
|
|
766
|
+
node = this.root;
|
|
767
|
+
}
|
|
768
|
+
if (node.value !== void 0) {
|
|
769
|
+
values.push(node.value);
|
|
770
|
+
}
|
|
771
|
+
for (const child of node.children) {
|
|
772
|
+
this.collectValues(child, values);
|
|
773
|
+
}
|
|
774
|
+
return values;
|
|
775
|
+
}
|
|
776
|
+
/**
|
|
777
|
+
* Recursively searches for a path in the Radix Tree.
|
|
778
|
+
* This method traverses the tree and searches for the segments of the path, collecting parameters
|
|
779
|
+
* @param node - The node to start searching from.
|
|
780
|
+
* @param segments - The segments of the path to search for.
|
|
781
|
+
* @param params - The parameters collected during the search.
|
|
782
|
+
* @returns An ISearchResult containing the node and parameters if a match is found, otherwise undefined.
|
|
783
|
+
*/
|
|
784
|
+
searchRecursive(node, segments, params) {
|
|
785
|
+
if (segments.length === 0) {
|
|
786
|
+
if (node.value !== void 0) {
|
|
787
|
+
return {
|
|
788
|
+
node,
|
|
789
|
+
params
|
|
790
|
+
};
|
|
969
791
|
}
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
|
|
973
|
-
|
|
974
|
-
|
|
975
|
-
|
|
976
|
-
|
|
792
|
+
return void 0;
|
|
793
|
+
}
|
|
794
|
+
const [segment, ...rest] = segments;
|
|
795
|
+
const staticChildren = [];
|
|
796
|
+
const paramChildren = [];
|
|
797
|
+
for (const child of node.children) {
|
|
798
|
+
if (child.isParam) {
|
|
799
|
+
paramChildren.push(child);
|
|
800
|
+
} else if (segment === child.segment) {
|
|
801
|
+
staticChildren.push(child);
|
|
977
802
|
}
|
|
978
|
-
}
|
|
979
|
-
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
|
|
983
|
-
|
|
984
|
-
this.status = 511;
|
|
803
|
+
}
|
|
804
|
+
for (const child of staticChildren) {
|
|
805
|
+
if (rest.length === 0) {
|
|
806
|
+
if (child.value !== void 0 || child.children.length > 0) {
|
|
807
|
+
return { node: child, params };
|
|
808
|
+
}
|
|
985
809
|
}
|
|
986
|
-
|
|
987
|
-
|
|
988
|
-
|
|
989
|
-
|
|
990
|
-
|
|
991
|
-
|
|
992
|
-
|
|
810
|
+
const result = this.searchRecursive(child, rest, params);
|
|
811
|
+
if (result) return result;
|
|
812
|
+
}
|
|
813
|
+
for (const child of paramChildren) {
|
|
814
|
+
const paramName = child.paramName;
|
|
815
|
+
const childParams = {
|
|
816
|
+
...params,
|
|
817
|
+
[paramName]: segment ?? ""
|
|
818
|
+
};
|
|
819
|
+
if (rest.length === 0) {
|
|
820
|
+
if (child.value !== void 0 || child.children.length > 0) {
|
|
821
|
+
return { node: child, params: childParams };
|
|
822
|
+
}
|
|
993
823
|
}
|
|
994
|
-
|
|
995
|
-
|
|
996
|
-
|
|
824
|
+
const result = this.searchRecursive(child, rest, childParams);
|
|
825
|
+
if (result) return result;
|
|
826
|
+
}
|
|
827
|
+
return void 0;
|
|
997
828
|
}
|
|
998
|
-
|
|
829
|
+
/**
|
|
830
|
+
* Normalizes a path into an array of segments.
|
|
831
|
+
* This method removes leading and trailing slashes, splits the path by slashes, and
|
|
832
|
+
* @param path - The path to normalize.
|
|
833
|
+
* @returns An array of normalized path segments.
|
|
834
|
+
*/
|
|
835
|
+
normalize(path2) {
|
|
836
|
+
const segments = path2.replace(/^\/+|\/+$/g, "").split("/").filter(Boolean);
|
|
837
|
+
return ["", ...segments];
|
|
838
|
+
}
|
|
839
|
+
};
|
|
840
|
+
__name(_RadixTree, "RadixTree");
|
|
841
|
+
var RadixTree = _RadixTree;
|
|
842
|
+
|
|
843
|
+
// src/internal/exceptions.ts
|
|
844
|
+
var _ResponseException = class _ResponseException extends Error {
|
|
845
|
+
constructor(statusOrMessage, message) {
|
|
846
|
+
let statusCode;
|
|
847
|
+
if (typeof statusOrMessage === "number") {
|
|
848
|
+
statusCode = statusOrMessage;
|
|
849
|
+
} else if (typeof statusOrMessage === "string") {
|
|
850
|
+
message = statusOrMessage;
|
|
851
|
+
}
|
|
852
|
+
super(message ?? "");
|
|
853
|
+
this.status = 0;
|
|
854
|
+
if (statusCode !== void 0) {
|
|
855
|
+
this.status = statusCode;
|
|
856
|
+
}
|
|
857
|
+
this.name = this.constructor.name.replace(/([A-Z])/g, " $1");
|
|
858
|
+
}
|
|
859
|
+
};
|
|
860
|
+
__name(_ResponseException, "ResponseException");
|
|
861
|
+
var ResponseException = _ResponseException;
|
|
862
|
+
var _BadRequestException = class _BadRequestException extends ResponseException {
|
|
863
|
+
constructor() {
|
|
864
|
+
super(...arguments);
|
|
865
|
+
this.status = 400;
|
|
866
|
+
}
|
|
867
|
+
};
|
|
868
|
+
__name(_BadRequestException, "BadRequestException");
|
|
869
|
+
var BadRequestException = _BadRequestException;
|
|
870
|
+
var _UnauthorizedException = class _UnauthorizedException extends ResponseException {
|
|
871
|
+
constructor() {
|
|
872
|
+
super(...arguments);
|
|
873
|
+
this.status = 401;
|
|
874
|
+
}
|
|
875
|
+
};
|
|
876
|
+
__name(_UnauthorizedException, "UnauthorizedException");
|
|
877
|
+
var UnauthorizedException = _UnauthorizedException;
|
|
878
|
+
var _PaymentRequiredException = class _PaymentRequiredException extends ResponseException {
|
|
879
|
+
constructor() {
|
|
880
|
+
super(...arguments);
|
|
881
|
+
this.status = 402;
|
|
882
|
+
}
|
|
883
|
+
};
|
|
884
|
+
__name(_PaymentRequiredException, "PaymentRequiredException");
|
|
885
|
+
var PaymentRequiredException = _PaymentRequiredException;
|
|
886
|
+
var _ForbiddenException = class _ForbiddenException extends ResponseException {
|
|
887
|
+
constructor() {
|
|
888
|
+
super(...arguments);
|
|
889
|
+
this.status = 403;
|
|
890
|
+
}
|
|
891
|
+
};
|
|
892
|
+
__name(_ForbiddenException, "ForbiddenException");
|
|
893
|
+
var ForbiddenException = _ForbiddenException;
|
|
894
|
+
var _NotFoundException = class _NotFoundException extends ResponseException {
|
|
895
|
+
constructor() {
|
|
896
|
+
super(...arguments);
|
|
897
|
+
this.status = 404;
|
|
898
|
+
}
|
|
899
|
+
};
|
|
900
|
+
__name(_NotFoundException, "NotFoundException");
|
|
901
|
+
var NotFoundException = _NotFoundException;
|
|
902
|
+
var _MethodNotAllowedException = class _MethodNotAllowedException extends ResponseException {
|
|
903
|
+
constructor() {
|
|
904
|
+
super(...arguments);
|
|
905
|
+
this.status = 405;
|
|
906
|
+
}
|
|
907
|
+
};
|
|
908
|
+
__name(_MethodNotAllowedException, "MethodNotAllowedException");
|
|
909
|
+
var MethodNotAllowedException = _MethodNotAllowedException;
|
|
910
|
+
var _NotAcceptableException = class _NotAcceptableException extends ResponseException {
|
|
911
|
+
constructor() {
|
|
912
|
+
super(...arguments);
|
|
913
|
+
this.status = 406;
|
|
914
|
+
}
|
|
915
|
+
};
|
|
916
|
+
__name(_NotAcceptableException, "NotAcceptableException");
|
|
917
|
+
var NotAcceptableException = _NotAcceptableException;
|
|
918
|
+
var _RequestTimeoutException = class _RequestTimeoutException extends ResponseException {
|
|
919
|
+
constructor() {
|
|
920
|
+
super(...arguments);
|
|
921
|
+
this.status = 408;
|
|
922
|
+
}
|
|
923
|
+
};
|
|
924
|
+
__name(_RequestTimeoutException, "RequestTimeoutException");
|
|
925
|
+
var RequestTimeoutException = _RequestTimeoutException;
|
|
926
|
+
var _ConflictException = class _ConflictException extends ResponseException {
|
|
927
|
+
constructor() {
|
|
928
|
+
super(...arguments);
|
|
929
|
+
this.status = 409;
|
|
930
|
+
}
|
|
931
|
+
};
|
|
932
|
+
__name(_ConflictException, "ConflictException");
|
|
933
|
+
var ConflictException = _ConflictException;
|
|
934
|
+
var _UpgradeRequiredException = class _UpgradeRequiredException extends ResponseException {
|
|
935
|
+
constructor() {
|
|
936
|
+
super(...arguments);
|
|
937
|
+
this.status = 426;
|
|
938
|
+
}
|
|
939
|
+
};
|
|
940
|
+
__name(_UpgradeRequiredException, "UpgradeRequiredException");
|
|
941
|
+
var UpgradeRequiredException = _UpgradeRequiredException;
|
|
942
|
+
var _TooManyRequestsException = class _TooManyRequestsException extends ResponseException {
|
|
943
|
+
constructor() {
|
|
944
|
+
super(...arguments);
|
|
945
|
+
this.status = 429;
|
|
946
|
+
}
|
|
947
|
+
};
|
|
948
|
+
__name(_TooManyRequestsException, "TooManyRequestsException");
|
|
949
|
+
var TooManyRequestsException = _TooManyRequestsException;
|
|
950
|
+
var _InternalServerException = class _InternalServerException extends ResponseException {
|
|
951
|
+
constructor() {
|
|
952
|
+
super(...arguments);
|
|
953
|
+
this.status = 500;
|
|
954
|
+
}
|
|
955
|
+
};
|
|
956
|
+
__name(_InternalServerException, "InternalServerException");
|
|
957
|
+
var InternalServerException = _InternalServerException;
|
|
958
|
+
var _NotImplementedException = class _NotImplementedException extends ResponseException {
|
|
959
|
+
constructor() {
|
|
960
|
+
super(...arguments);
|
|
961
|
+
this.status = 501;
|
|
962
|
+
}
|
|
963
|
+
};
|
|
964
|
+
__name(_NotImplementedException, "NotImplementedException");
|
|
965
|
+
var NotImplementedException = _NotImplementedException;
|
|
966
|
+
var _BadGatewayException = class _BadGatewayException extends ResponseException {
|
|
967
|
+
constructor() {
|
|
968
|
+
super(...arguments);
|
|
969
|
+
this.status = 502;
|
|
970
|
+
}
|
|
971
|
+
};
|
|
972
|
+
__name(_BadGatewayException, "BadGatewayException");
|
|
973
|
+
var BadGatewayException = _BadGatewayException;
|
|
974
|
+
var _ServiceUnavailableException = class _ServiceUnavailableException extends ResponseException {
|
|
975
|
+
constructor() {
|
|
976
|
+
super(...arguments);
|
|
977
|
+
this.status = 503;
|
|
978
|
+
}
|
|
979
|
+
};
|
|
980
|
+
__name(_ServiceUnavailableException, "ServiceUnavailableException");
|
|
981
|
+
var ServiceUnavailableException = _ServiceUnavailableException;
|
|
982
|
+
var _GatewayTimeoutException = class _GatewayTimeoutException extends ResponseException {
|
|
983
|
+
constructor() {
|
|
984
|
+
super(...arguments);
|
|
985
|
+
this.status = 504;
|
|
986
|
+
}
|
|
987
|
+
};
|
|
988
|
+
__name(_GatewayTimeoutException, "GatewayTimeoutException");
|
|
989
|
+
var GatewayTimeoutException = _GatewayTimeoutException;
|
|
990
|
+
var _HttpVersionNotSupportedException = class _HttpVersionNotSupportedException extends ResponseException {
|
|
991
|
+
constructor() {
|
|
992
|
+
super(...arguments);
|
|
993
|
+
this.status = 505;
|
|
994
|
+
}
|
|
995
|
+
};
|
|
996
|
+
__name(_HttpVersionNotSupportedException, "HttpVersionNotSupportedException");
|
|
997
|
+
var HttpVersionNotSupportedException = _HttpVersionNotSupportedException;
|
|
998
|
+
var _VariantAlsoNegotiatesException = class _VariantAlsoNegotiatesException extends ResponseException {
|
|
999
|
+
constructor() {
|
|
1000
|
+
super(...arguments);
|
|
1001
|
+
this.status = 506;
|
|
1002
|
+
}
|
|
1003
|
+
};
|
|
1004
|
+
__name(_VariantAlsoNegotiatesException, "VariantAlsoNegotiatesException");
|
|
1005
|
+
var VariantAlsoNegotiatesException = _VariantAlsoNegotiatesException;
|
|
1006
|
+
var _InsufficientStorageException = class _InsufficientStorageException extends ResponseException {
|
|
1007
|
+
constructor() {
|
|
1008
|
+
super(...arguments);
|
|
1009
|
+
this.status = 507;
|
|
1010
|
+
}
|
|
1011
|
+
};
|
|
1012
|
+
__name(_InsufficientStorageException, "InsufficientStorageException");
|
|
1013
|
+
var InsufficientStorageException = _InsufficientStorageException;
|
|
1014
|
+
var _LoopDetectedException = class _LoopDetectedException extends ResponseException {
|
|
1015
|
+
constructor() {
|
|
1016
|
+
super(...arguments);
|
|
1017
|
+
this.status = 508;
|
|
1018
|
+
}
|
|
1019
|
+
};
|
|
1020
|
+
__name(_LoopDetectedException, "LoopDetectedException");
|
|
1021
|
+
var LoopDetectedException = _LoopDetectedException;
|
|
1022
|
+
var _NotExtendedException = class _NotExtendedException extends ResponseException {
|
|
1023
|
+
constructor() {
|
|
1024
|
+
super(...arguments);
|
|
1025
|
+
this.status = 510;
|
|
1026
|
+
}
|
|
1027
|
+
};
|
|
1028
|
+
__name(_NotExtendedException, "NotExtendedException");
|
|
1029
|
+
var NotExtendedException = _NotExtendedException;
|
|
1030
|
+
var _NetworkAuthenticationRequiredException = class _NetworkAuthenticationRequiredException extends ResponseException {
|
|
1031
|
+
constructor() {
|
|
1032
|
+
super(...arguments);
|
|
1033
|
+
this.status = 511;
|
|
1034
|
+
}
|
|
1035
|
+
};
|
|
1036
|
+
__name(_NetworkAuthenticationRequiredException, "NetworkAuthenticationRequiredException");
|
|
1037
|
+
var NetworkAuthenticationRequiredException = _NetworkAuthenticationRequiredException;
|
|
1038
|
+
var _NetworkConnectTimeoutException = class _NetworkConnectTimeoutException extends ResponseException {
|
|
1039
|
+
constructor() {
|
|
1040
|
+
super(...arguments);
|
|
1041
|
+
this.status = 599;
|
|
1042
|
+
}
|
|
1043
|
+
};
|
|
1044
|
+
__name(_NetworkConnectTimeoutException, "NetworkConnectTimeoutException");
|
|
1045
|
+
var NetworkConnectTimeoutException = _NetworkConnectTimeoutException;
|
|
999
1046
|
|
|
1000
1047
|
// src/internal/request.ts
|
|
1048
|
+
init_app_injector();
|
|
1049
|
+
var _Request = class _Request {
|
|
1050
|
+
constructor(event, senderId, id, method, path2, body, query) {
|
|
1051
|
+
this.event = event;
|
|
1052
|
+
this.senderId = senderId;
|
|
1053
|
+
this.id = id;
|
|
1054
|
+
this.method = method;
|
|
1055
|
+
this.path = path2;
|
|
1056
|
+
this.body = body;
|
|
1057
|
+
this.context = RootInjector.createScope();
|
|
1058
|
+
this.params = {};
|
|
1059
|
+
this.path = path2.replace(/^\/|\/$/g, "");
|
|
1060
|
+
this.query = query ?? {};
|
|
1061
|
+
}
|
|
1062
|
+
};
|
|
1063
|
+
__name(_Request, "Request");
|
|
1064
|
+
var Request = _Request;
|
|
1065
|
+
var RENDERER_EVENT_TYPE = "noxus:event";
|
|
1001
1066
|
function createRendererEventMessage(event, payload) {
|
|
1002
1067
|
return {
|
|
1003
1068
|
type: RENDERER_EVENT_TYPE,
|
|
@@ -1005,6 +1070,7 @@ function createRendererEventMessage(event, payload) {
|
|
|
1005
1070
|
payload
|
|
1006
1071
|
};
|
|
1007
1072
|
}
|
|
1073
|
+
__name(createRendererEventMessage, "createRendererEventMessage");
|
|
1008
1074
|
function isRendererEventMessage(value) {
|
|
1009
1075
|
if (value === null || typeof value !== "object") {
|
|
1010
1076
|
return false;
|
|
@@ -1012,306 +1078,268 @@ function isRendererEventMessage(value) {
|
|
|
1012
1078
|
const possibleMessage = value;
|
|
1013
1079
|
return possibleMessage.type === RENDERER_EVENT_TYPE && typeof possibleMessage.event === "string";
|
|
1014
1080
|
}
|
|
1015
|
-
|
|
1016
|
-
var init_request = __esm({
|
|
1017
|
-
"src/internal/request.ts"() {
|
|
1018
|
-
"use strict";
|
|
1019
|
-
init_app_injector();
|
|
1020
|
-
_Request = class _Request {
|
|
1021
|
-
constructor(event, senderId, id, method, path2, body) {
|
|
1022
|
-
this.event = event;
|
|
1023
|
-
this.senderId = senderId;
|
|
1024
|
-
this.id = id;
|
|
1025
|
-
this.method = method;
|
|
1026
|
-
this.path = path2;
|
|
1027
|
-
this.body = body;
|
|
1028
|
-
this.context = RootInjector.createScope();
|
|
1029
|
-
this.params = {};
|
|
1030
|
-
this.path = path2.replace(/^\/|\/$/g, "");
|
|
1031
|
-
}
|
|
1032
|
-
};
|
|
1033
|
-
__name(_Request, "Request");
|
|
1034
|
-
Request = _Request;
|
|
1035
|
-
RENDERER_EVENT_TYPE = "noxus:event";
|
|
1036
|
-
__name(createRendererEventMessage, "createRendererEventMessage");
|
|
1037
|
-
__name(isRendererEventMessage, "isRendererEventMessage");
|
|
1038
|
-
}
|
|
1039
|
-
});
|
|
1081
|
+
__name(isRendererEventMessage, "isRendererEventMessage");
|
|
1040
1082
|
|
|
1041
1083
|
// src/internal/router.ts
|
|
1042
|
-
var
|
|
1043
|
-
|
|
1044
|
-
|
|
1045
|
-
|
|
1046
|
-
|
|
1047
|
-
|
|
1048
|
-
|
|
1049
|
-
|
|
1050
|
-
|
|
1051
|
-
|
|
1052
|
-
|
|
1053
|
-
|
|
1054
|
-
|
|
1055
|
-
|
|
1056
|
-
|
|
1057
|
-
|
|
1058
|
-
|
|
1059
|
-
|
|
1060
|
-
|
|
1061
|
-
|
|
1062
|
-
|
|
1063
|
-
|
|
1064
|
-
|
|
1065
|
-
|
|
1066
|
-
|
|
1067
|
-
|
|
1068
|
-
|
|
1069
|
-
|
|
1070
|
-
|
|
1071
|
-
|
|
1072
|
-
|
|
1073
|
-
|
|
1074
|
-
|
|
1075
|
-
|
|
1076
|
-
|
|
1077
|
-
|
|
1078
|
-
|
|
1079
|
-
|
|
1080
|
-
|
|
1081
|
-
|
|
1082
|
-
|
|
1083
|
-
|
|
1084
|
-
|
|
1085
|
-
|
|
1086
|
-
|
|
1087
|
-
|
|
1088
|
-
|
|
1089
|
-
|
|
1090
|
-
|
|
1091
|
-
|
|
1092
|
-
|
|
1093
|
-
|
|
1094
|
-
|
|
1095
|
-
|
|
1096
|
-
|
|
1097
|
-
|
|
1098
|
-
|
|
1099
|
-
|
|
1100
|
-
|
|
1101
|
-
|
|
1102
|
-
|
|
1103
|
-
|
|
1104
|
-
|
|
1105
|
-
|
|
1106
|
-
|
|
1107
|
-
|
|
1108
|
-
|
|
1109
|
-
|
|
1110
|
-
|
|
1111
|
-
|
|
1112
|
-
|
|
1113
|
-
|
|
1114
|
-
|
|
1115
|
-
|
|
1116
|
-
|
|
1117
|
-
|
|
1118
|
-
|
|
1119
|
-
|
|
1120
|
-
|
|
1121
|
-
|
|
1122
|
-
|
|
1123
|
-
|
|
1124
|
-
|
|
1125
|
-
|
|
1126
|
-
|
|
1127
|
-
|
|
1128
|
-
|
|
1129
|
-
|
|
1130
|
-
|
|
1131
|
-
|
|
1132
|
-
|
|
1133
|
-
|
|
1134
|
-
|
|
1135
|
-
|
|
1136
|
-
|
|
1137
|
-
|
|
1138
|
-
|
|
1139
|
-
|
|
1140
|
-
|
|
1141
|
-
|
|
1142
|
-
|
|
1143
|
-
|
|
1144
|
-
|
|
1145
|
-
|
|
1146
|
-
|
|
1147
|
-
|
|
1148
|
-
|
|
1149
|
-
|
|
1150
|
-
|
|
1151
|
-
|
|
1152
|
-
|
|
1153
|
-
|
|
1154
|
-
|
|
1155
|
-
|
|
1156
|
-
|
|
1157
|
-
|
|
1158
|
-
|
|
1159
|
-
|
|
1160
|
-
|
|
1161
|
-
|
|
1162
|
-
|
|
1163
|
-
|
|
1164
|
-
|
|
1165
|
-
|
|
1166
|
-
|
|
1167
|
-
|
|
1168
|
-
|
|
1169
|
-
|
|
1170
|
-
|
|
1171
|
-
|
|
1172
|
-
if (entry.loaded) continue;
|
|
1173
|
-
const normalized = requestPath.replace(/^\/+/, "");
|
|
1174
|
-
if (normalized === prefix || normalized.startsWith(prefix + "/") || firstSegment === prefix) {
|
|
1175
|
-
if (!entry.loading) entry.loading = this.loadLazyModule(prefix, entry);
|
|
1176
|
-
await entry.loading;
|
|
1177
|
-
return;
|
|
1178
|
-
}
|
|
1179
|
-
}
|
|
1180
|
-
}
|
|
1181
|
-
async loadLazyModule(prefix, entry) {
|
|
1182
|
-
const t0 = performance.now();
|
|
1183
|
-
InjectorExplorer.beginAccumulate();
|
|
1184
|
-
await entry.load?.();
|
|
1185
|
-
entry.loading = null;
|
|
1186
|
-
entry.load = null;
|
|
1187
|
-
InjectorExplorer.flushAccumulated(entry.guards, entry.middlewares, prefix);
|
|
1188
|
-
entry.loaded = true;
|
|
1189
|
-
Logger.info(`Lazy-loaded module for prefix {${prefix}} in ${Math.round(performance.now() - t0)}ms`);
|
|
1190
|
-
}
|
|
1191
|
-
// -------------------------------------------------------------------------
|
|
1192
|
-
// Pipeline
|
|
1193
|
-
// -------------------------------------------------------------------------
|
|
1194
|
-
async resolveController(request, response, routeDef) {
|
|
1195
|
-
const instance = request.context.resolve(routeDef.controller);
|
|
1196
|
-
Object.assign(request.params, this.extractParams(request.path, routeDef.path));
|
|
1197
|
-
await this.runPipeline(request, response, routeDef, instance);
|
|
1198
|
-
}
|
|
1199
|
-
async runPipeline(request, response, routeDef, controllerInstance) {
|
|
1200
|
-
const middlewares = [.../* @__PURE__ */ new Set([...this.rootMiddlewares, ...routeDef.middlewares])];
|
|
1201
|
-
const mwMax = middlewares.length - 1;
|
|
1202
|
-
const guardMax = mwMax + routeDef.guards.length;
|
|
1203
|
-
let index = -1;
|
|
1204
|
-
const dispatch = /* @__PURE__ */ __name(async (i) => {
|
|
1205
|
-
if (i <= index) throw new Error("next() called multiple times");
|
|
1206
|
-
index = i;
|
|
1207
|
-
if (i <= mwMax) {
|
|
1208
|
-
await this.runMiddleware(request, response, dispatch.bind(null, i + 1), middlewares[i]);
|
|
1209
|
-
if (response.status >= 400) throw new ResponseException(response.status, response.error);
|
|
1210
|
-
return;
|
|
1211
|
-
}
|
|
1212
|
-
if (i <= guardMax) {
|
|
1213
|
-
await this.runGuard(request, routeDef.guards[i - middlewares.length]);
|
|
1214
|
-
await dispatch(i + 1);
|
|
1215
|
-
return;
|
|
1216
|
-
}
|
|
1217
|
-
const action = controllerInstance[routeDef.handler];
|
|
1218
|
-
response.body = await action.call(controllerInstance, request, response);
|
|
1219
|
-
if (response.body === void 0) response.body = {};
|
|
1220
|
-
}, "dispatch");
|
|
1221
|
-
await dispatch(0);
|
|
1222
|
-
}
|
|
1223
|
-
async runMiddleware(request, response, next, middleware) {
|
|
1224
|
-
await middleware(request, response, next);
|
|
1225
|
-
}
|
|
1226
|
-
async runGuard(request, guard) {
|
|
1227
|
-
if (!await guard(request)) {
|
|
1228
|
-
throw new UnauthorizedException(`Unauthorized for ${request.method} ${request.path}`);
|
|
1229
|
-
}
|
|
1230
|
-
}
|
|
1231
|
-
// -------------------------------------------------------------------------
|
|
1232
|
-
// Utilities
|
|
1233
|
-
// -------------------------------------------------------------------------
|
|
1234
|
-
extractParams(actual, template) {
|
|
1235
|
-
const aParts = actual.split("/");
|
|
1236
|
-
const tParts = template.split("/");
|
|
1237
|
-
const params = {};
|
|
1238
|
-
tParts.forEach((part, i) => {
|
|
1239
|
-
if (part.startsWith(":")) params[part.slice(1)] = aParts[i] ?? "";
|
|
1240
|
-
});
|
|
1241
|
-
return params;
|
|
1242
|
-
}
|
|
1243
|
-
normalizeBatchPayload(body) {
|
|
1244
|
-
if (body === null || typeof body !== "object") {
|
|
1245
|
-
throw new BadRequestException("Batch payload must be an object containing a requests array.");
|
|
1246
|
-
}
|
|
1247
|
-
const { requests } = body;
|
|
1248
|
-
if (!Array.isArray(requests)) throw new BadRequestException("Batch payload must define a requests array.");
|
|
1249
|
-
return { requests: requests.map((e, i) => this.normalizeBatchItem(e, i)) };
|
|
1250
|
-
}
|
|
1251
|
-
normalizeBatchItem(entry, index) {
|
|
1252
|
-
if (entry === null || typeof entry !== "object") throw new BadRequestException(`Batch request at index ${index} must be an object.`);
|
|
1253
|
-
const { requestId, path: path2, method, body } = entry;
|
|
1254
|
-
if (requestId !== void 0 && typeof requestId !== "string") throw new BadRequestException(`Batch request at index ${index} has an invalid requestId.`);
|
|
1255
|
-
if (typeof path2 !== "string" || !path2.length) throw new BadRequestException(`Batch request at index ${index} must define a non-empty path.`);
|
|
1256
|
-
if (typeof method !== "string") throw new BadRequestException(`Batch request at index ${index} must define an HTTP method.`);
|
|
1257
|
-
const normalized = method.toUpperCase();
|
|
1258
|
-
if (!isAtomicHttpMethod(normalized)) throw new BadRequestException(`Batch request at index ${index} uses unsupported method ${method}.`);
|
|
1259
|
-
return { requestId, path: path2, method: normalized, body };
|
|
1084
|
+
var Router = class {
|
|
1085
|
+
constructor() {
|
|
1086
|
+
this.routes = new RadixTree();
|
|
1087
|
+
this.rootMiddlewares = [];
|
|
1088
|
+
this.lazyRoutes = /* @__PURE__ */ new Map();
|
|
1089
|
+
}
|
|
1090
|
+
// -------------------------------------------------------------------------
|
|
1091
|
+
// Registration
|
|
1092
|
+
// -------------------------------------------------------------------------
|
|
1093
|
+
registerController(controllerClass, pathPrefix, routeGuards = [], routeMiddlewares = []) {
|
|
1094
|
+
const meta = getControllerMetadata(controllerClass);
|
|
1095
|
+
if (!meta) {
|
|
1096
|
+
throw new Error(`[Noxus] Missing @Controller decorator on ${controllerClass.name}`);
|
|
1097
|
+
}
|
|
1098
|
+
const routeMeta = getRouteMetadata(controllerClass);
|
|
1099
|
+
for (const def of routeMeta) {
|
|
1100
|
+
const fullPath = `${pathPrefix}/${def.path}`.replace(/\/+/g, "/").replace(/\/$/, "") || "/";
|
|
1101
|
+
const guards = [.../* @__PURE__ */ new Set([...routeGuards, ...def.guards])];
|
|
1102
|
+
const middlewares = [.../* @__PURE__ */ new Set([...routeMiddlewares, ...def.middlewares])];
|
|
1103
|
+
const routeDef = {
|
|
1104
|
+
method: def.method,
|
|
1105
|
+
path: fullPath,
|
|
1106
|
+
controller: controllerClass,
|
|
1107
|
+
handler: def.handler,
|
|
1108
|
+
guards,
|
|
1109
|
+
middlewares
|
|
1110
|
+
};
|
|
1111
|
+
this.routes.insert(fullPath + "/" + def.method, routeDef);
|
|
1112
|
+
const guardInfo = guards.length ? `<${guards.map((g) => g.name).join("|")}>` : "";
|
|
1113
|
+
Logger.log(`Mapped {${def.method} /${fullPath}}${guardInfo} route`);
|
|
1114
|
+
}
|
|
1115
|
+
const ctrlGuardInfo = routeGuards.length ? `<${routeGuards.map((g) => g.name).join("|")}>` : "";
|
|
1116
|
+
Logger.log(`Mapped ${controllerClass.name}${ctrlGuardInfo} controller's routes`);
|
|
1117
|
+
return this;
|
|
1118
|
+
}
|
|
1119
|
+
registerLazyRoute(pathPrefix, load, guards = [], middlewares = []) {
|
|
1120
|
+
const normalized = pathPrefix.replace(/^\/+|\/+$/g, "");
|
|
1121
|
+
this.lazyRoutes.set(normalized, { load, guards, middlewares, loading: null, loaded: false });
|
|
1122
|
+
Logger.log(`Registered lazy route prefix {${normalized}}`);
|
|
1123
|
+
return this;
|
|
1124
|
+
}
|
|
1125
|
+
defineRootMiddleware(middleware) {
|
|
1126
|
+
this.rootMiddlewares.push(middleware);
|
|
1127
|
+
return this;
|
|
1128
|
+
}
|
|
1129
|
+
getRegisteredRoutes() {
|
|
1130
|
+
const allRoutes = this.routes.collectValues();
|
|
1131
|
+
return allRoutes.map((r) => ({ method: r.method, path: r.path }));
|
|
1132
|
+
}
|
|
1133
|
+
getLazyRoutes() {
|
|
1134
|
+
return [...this.lazyRoutes.entries()].map(([prefix, entry]) => ({
|
|
1135
|
+
prefix,
|
|
1136
|
+
loaded: entry.loaded
|
|
1137
|
+
}));
|
|
1138
|
+
}
|
|
1139
|
+
// -------------------------------------------------------------------------
|
|
1140
|
+
// Request handling
|
|
1141
|
+
// -------------------------------------------------------------------------
|
|
1142
|
+
async handle(request) {
|
|
1143
|
+
return request.method === "BATCH" ? this.handleBatch(request) : this.handleAtomic(request);
|
|
1144
|
+
}
|
|
1145
|
+
async handleAtomic(request) {
|
|
1146
|
+
Logger.comment(`> ${request.method} /${request.path}`);
|
|
1147
|
+
const t0 = performance.now();
|
|
1148
|
+
const response = { requestId: request.id, status: 200, body: null };
|
|
1149
|
+
let isCritical = false;
|
|
1150
|
+
try {
|
|
1151
|
+
const routeDef = await this.findRoute(request);
|
|
1152
|
+
await this.resolveController(request, response, routeDef);
|
|
1153
|
+
if (response.status >= 400) throw new ResponseException(response.status, response.error);
|
|
1154
|
+
} catch (error) {
|
|
1155
|
+
this.fillErrorResponse(response, error, (c) => {
|
|
1156
|
+
isCritical = c;
|
|
1157
|
+
});
|
|
1158
|
+
} finally {
|
|
1159
|
+
this.logResponse(request, response, performance.now() - t0, isCritical);
|
|
1160
|
+
return response;
|
|
1161
|
+
}
|
|
1162
|
+
}
|
|
1163
|
+
async handleBatch(request) {
|
|
1164
|
+
Logger.comment(`> ${request.method} /${request.path}`);
|
|
1165
|
+
const t0 = performance.now();
|
|
1166
|
+
const response = {
|
|
1167
|
+
requestId: request.id,
|
|
1168
|
+
status: 200,
|
|
1169
|
+
body: { responses: [] }
|
|
1170
|
+
};
|
|
1171
|
+
let isCritical = false;
|
|
1172
|
+
try {
|
|
1173
|
+
const payload = this.normalizeBatchPayload(request.body);
|
|
1174
|
+
response.body.responses = await Promise.all(
|
|
1175
|
+
payload.requests.map((item, i) => {
|
|
1176
|
+
const id = item.requestId ?? `${request.id}:${i}`;
|
|
1177
|
+
return this.handleAtomic(new Request(request.event, request.senderId, id, item.method, item.path, item.body, item.query));
|
|
1178
|
+
})
|
|
1179
|
+
);
|
|
1180
|
+
} catch (error) {
|
|
1181
|
+
this.fillErrorResponse(response, error, (c) => {
|
|
1182
|
+
isCritical = c;
|
|
1183
|
+
});
|
|
1184
|
+
} finally {
|
|
1185
|
+
this.logResponse(request, response, performance.now() - t0, isCritical);
|
|
1186
|
+
return response;
|
|
1187
|
+
}
|
|
1188
|
+
}
|
|
1189
|
+
// -------------------------------------------------------------------------
|
|
1190
|
+
// Route resolution
|
|
1191
|
+
// -------------------------------------------------------------------------
|
|
1192
|
+
tryFindRoute(request) {
|
|
1193
|
+
const matched = this.routes.search(request.path);
|
|
1194
|
+
if (!matched?.node || matched.node.children.length === 0) return void 0;
|
|
1195
|
+
return matched.node.findExactChild(request.method)?.value;
|
|
1196
|
+
}
|
|
1197
|
+
async findRoute(request) {
|
|
1198
|
+
const direct = this.tryFindRoute(request);
|
|
1199
|
+
if (direct) return direct;
|
|
1200
|
+
await this.tryLoadLazyRoute(request.path);
|
|
1201
|
+
const afterLazy = this.tryFindRoute(request);
|
|
1202
|
+
if (afterLazy) return afterLazy;
|
|
1203
|
+
throw new NotFoundException(`No route matches ${request.method} ${request.path}`);
|
|
1204
|
+
}
|
|
1205
|
+
async tryLoadLazyRoute(requestPath) {
|
|
1206
|
+
const firstSegment = requestPath.replace(/^\/+/, "").split("/")[0] ?? "";
|
|
1207
|
+
for (const [prefix, entry] of this.lazyRoutes) {
|
|
1208
|
+
if (entry.loaded) continue;
|
|
1209
|
+
const normalized = requestPath.replace(/^\/+/, "");
|
|
1210
|
+
if (normalized === prefix || normalized.startsWith(prefix + "/") || firstSegment === prefix) {
|
|
1211
|
+
if (!entry.loading) entry.loading = this.loadLazyModule(prefix, entry);
|
|
1212
|
+
await entry.loading;
|
|
1213
|
+
return;
|
|
1260
1214
|
}
|
|
1261
|
-
|
|
1262
|
-
|
|
1263
|
-
|
|
1264
|
-
|
|
1265
|
-
|
|
1266
|
-
|
|
1267
|
-
|
|
1268
|
-
|
|
1269
|
-
|
|
1270
|
-
|
|
1271
|
-
|
|
1272
|
-
|
|
1273
|
-
|
|
1274
|
-
|
|
1275
|
-
|
|
1276
|
-
|
|
1215
|
+
}
|
|
1216
|
+
}
|
|
1217
|
+
async loadLazyModule(prefix, entry) {
|
|
1218
|
+
const t0 = performance.now();
|
|
1219
|
+
InjectorExplorer.beginAccumulate();
|
|
1220
|
+
await entry.load?.();
|
|
1221
|
+
entry.loading = null;
|
|
1222
|
+
entry.load = null;
|
|
1223
|
+
await InjectorExplorer.flushAccumulated(entry.guards, entry.middlewares, prefix);
|
|
1224
|
+
entry.loaded = true;
|
|
1225
|
+
Logger.info(`Lazy-loaded module for prefix {${prefix}} in ${Math.round(performance.now() - t0)}ms`);
|
|
1226
|
+
}
|
|
1227
|
+
// -------------------------------------------------------------------------
|
|
1228
|
+
// Pipeline
|
|
1229
|
+
// -------------------------------------------------------------------------
|
|
1230
|
+
async resolveController(request, response, routeDef) {
|
|
1231
|
+
const instance = request.context.resolve(routeDef.controller);
|
|
1232
|
+
Object.assign(request.params, this.extractParams(request.path, routeDef.path));
|
|
1233
|
+
await this.runPipeline(request, response, routeDef, instance);
|
|
1234
|
+
}
|
|
1235
|
+
async runPipeline(request, response, routeDef, controllerInstance) {
|
|
1236
|
+
const middlewares = [.../* @__PURE__ */ new Set([...this.rootMiddlewares, ...routeDef.middlewares])];
|
|
1237
|
+
const mwMax = middlewares.length - 1;
|
|
1238
|
+
const guardMax = mwMax + routeDef.guards.length;
|
|
1239
|
+
let index = -1;
|
|
1240
|
+
const dispatch = /* @__PURE__ */ __name(async (i) => {
|
|
1241
|
+
if (i <= index) throw new Error("next() called multiple times");
|
|
1242
|
+
index = i;
|
|
1243
|
+
if (i <= mwMax) {
|
|
1244
|
+
await this.runMiddleware(request, response, dispatch.bind(null, i + 1), middlewares[i]);
|
|
1245
|
+
if (response.status >= 400) throw new ResponseException(response.status, response.error);
|
|
1246
|
+
return;
|
|
1277
1247
|
}
|
|
1278
|
-
|
|
1279
|
-
|
|
1280
|
-
|
|
1281
|
-
|
|
1282
|
-
else isCritical ? Logger.critical(msg) : Logger.error(msg);
|
|
1283
|
-
if (response.error) {
|
|
1284
|
-
isCritical ? Logger.critical(response.error) : Logger.error(response.error);
|
|
1285
|
-
if (response.stack) Logger.errorStack(response.stack);
|
|
1286
|
-
}
|
|
1248
|
+
if (i <= guardMax) {
|
|
1249
|
+
await this.runGuard(request, routeDef.guards[i - middlewares.length]);
|
|
1250
|
+
await dispatch(i + 1);
|
|
1251
|
+
return;
|
|
1287
1252
|
}
|
|
1288
|
-
|
|
1289
|
-
|
|
1290
|
-
|
|
1291
|
-
|
|
1292
|
-
|
|
1253
|
+
const action = controllerInstance[routeDef.handler];
|
|
1254
|
+
response.body = await action.call(controllerInstance, request, response);
|
|
1255
|
+
if (response.body === void 0) response.body = {};
|
|
1256
|
+
}, "dispatch");
|
|
1257
|
+
await dispatch(0);
|
|
1293
1258
|
}
|
|
1294
|
-
|
|
1295
|
-
|
|
1296
|
-
|
|
1297
|
-
|
|
1298
|
-
|
|
1299
|
-
|
|
1259
|
+
async runMiddleware(request, response, next, middleware) {
|
|
1260
|
+
await middleware(request, response, next);
|
|
1261
|
+
}
|
|
1262
|
+
async runGuard(request, guard) {
|
|
1263
|
+
if (!await guard(request)) {
|
|
1264
|
+
throw new UnauthorizedException(`Unauthorized for ${request.method} ${request.path}`);
|
|
1265
|
+
}
|
|
1266
|
+
}
|
|
1267
|
+
// -------------------------------------------------------------------------
|
|
1268
|
+
// Utilities
|
|
1269
|
+
// -------------------------------------------------------------------------
|
|
1270
|
+
extractParams(actual, template) {
|
|
1271
|
+
const aParts = actual.split("/");
|
|
1272
|
+
const tParts = template.split("/");
|
|
1273
|
+
const params = {};
|
|
1274
|
+
tParts.forEach((part, i) => {
|
|
1275
|
+
if (part.startsWith(":")) params[part.slice(1)] = aParts[i] ?? "";
|
|
1276
|
+
});
|
|
1277
|
+
return params;
|
|
1278
|
+
}
|
|
1279
|
+
normalizeBatchPayload(body) {
|
|
1280
|
+
if (body === null || typeof body !== "object") {
|
|
1281
|
+
throw new BadRequestException("Batch payload must be an object containing a requests array.");
|
|
1282
|
+
}
|
|
1283
|
+
const { requests } = body;
|
|
1284
|
+
if (!Array.isArray(requests)) throw new BadRequestException("Batch payload must define a requests array.");
|
|
1285
|
+
return { requests: requests.map((e, i) => this.normalizeBatchItem(e, i)) };
|
|
1286
|
+
}
|
|
1287
|
+
normalizeBatchItem(entry, index) {
|
|
1288
|
+
if (entry === null || typeof entry !== "object") throw new BadRequestException(`Batch request at index ${index} must be an object.`);
|
|
1289
|
+
const { requestId, path: path2, method, body } = entry;
|
|
1290
|
+
if (requestId !== void 0 && typeof requestId !== "string") throw new BadRequestException(`Batch request at index ${index} has an invalid requestId.`);
|
|
1291
|
+
if (typeof path2 !== "string" || !path2.length) throw new BadRequestException(`Batch request at index ${index} must define a non-empty path.`);
|
|
1292
|
+
if (typeof method !== "string") throw new BadRequestException(`Batch request at index ${index} must define an HTTP method.`);
|
|
1293
|
+
const normalized = method.toUpperCase();
|
|
1294
|
+
if (!isAtomicHttpMethod(normalized)) throw new BadRequestException(`Batch request at index ${index} uses unsupported method ${method}.`);
|
|
1295
|
+
return { requestId, path: path2, method: normalized, body };
|
|
1296
|
+
}
|
|
1297
|
+
fillErrorResponse(response, error, setCritical) {
|
|
1298
|
+
response.body = void 0;
|
|
1299
|
+
if (error instanceof ResponseException) {
|
|
1300
|
+
response.status = error.status;
|
|
1301
|
+
response.error = error.message;
|
|
1302
|
+
response.stack = error.stack;
|
|
1303
|
+
} else if (error instanceof Error) {
|
|
1304
|
+
setCritical(true);
|
|
1305
|
+
response.status = 500;
|
|
1306
|
+
response.error = error.message || "Internal Server Error";
|
|
1307
|
+
response.stack = error.stack;
|
|
1308
|
+
} else {
|
|
1309
|
+
setCritical(true);
|
|
1310
|
+
response.status = 500;
|
|
1311
|
+
response.error = "Unknown error occurred";
|
|
1312
|
+
}
|
|
1313
|
+
}
|
|
1314
|
+
logResponse(request, response, ms, isCritical) {
|
|
1315
|
+
const msg = `< ${response.status} ${request.method} /${request.path} ${Logger.colors.yellow}${Math.round(ms)}ms${Logger.colors.initial}`;
|
|
1316
|
+
if (response.status < 400) Logger.log(msg);
|
|
1317
|
+
else if (response.status < 500) Logger.warn(msg);
|
|
1318
|
+
else isCritical ? Logger.critical(msg) : Logger.error(msg);
|
|
1319
|
+
if (response.error) {
|
|
1320
|
+
isCritical ? Logger.critical(response.error) : Logger.error(response.error);
|
|
1321
|
+
if (response.stack) Logger.errorStack(response.stack);
|
|
1322
|
+
}
|
|
1323
|
+
}
|
|
1324
|
+
};
|
|
1325
|
+
__name(Router, "Router");
|
|
1326
|
+
Router = __decorateClass([
|
|
1327
|
+
Injectable({ lifetime: "singleton" })
|
|
1328
|
+
], Router);
|
|
1300
1329
|
|
|
1301
1330
|
// src/internal/app.ts
|
|
1302
|
-
|
|
1331
|
+
import { app, BrowserWindow as BrowserWindow2, ipcMain, MessageChannelMain } from "electron/main";
|
|
1303
1332
|
init_app_injector();
|
|
1304
1333
|
init_injector_explorer();
|
|
1305
1334
|
init_logger();
|
|
1306
|
-
import { app, BrowserWindow as BrowserWindow2, ipcMain, MessageChannelMain } from "electron/main";
|
|
1307
1335
|
|
|
1308
1336
|
// src/window/window-manager.ts
|
|
1309
|
-
init_injectable_decorator();
|
|
1310
|
-
init_logger();
|
|
1311
1337
|
import { BrowserWindow } from "electron/main";
|
|
1338
|
+
init_logger();
|
|
1312
1339
|
var WindowManager = class {
|
|
1313
1340
|
constructor() {
|
|
1314
1341
|
this._windows = /* @__PURE__ */ new Map();
|
|
1342
|
+
this.listeners = /* @__PURE__ */ new Map();
|
|
1315
1343
|
}
|
|
1316
1344
|
// -------------------------------------------------------------------------
|
|
1317
1345
|
// Creation
|
|
@@ -1443,6 +1471,18 @@ var WindowManager = class {
|
|
|
1443
1471
|
}
|
|
1444
1472
|
}
|
|
1445
1473
|
// -------------------------------------------------------------------------
|
|
1474
|
+
// Events
|
|
1475
|
+
// -------------------------------------------------------------------------
|
|
1476
|
+
on(event, handler) {
|
|
1477
|
+
const set = this.listeners.get(event) ?? /* @__PURE__ */ new Set();
|
|
1478
|
+
set.add(handler);
|
|
1479
|
+
this.listeners.set(event, set);
|
|
1480
|
+
return () => set.delete(handler);
|
|
1481
|
+
}
|
|
1482
|
+
_emit(event, win) {
|
|
1483
|
+
this.listeners.get(event)?.forEach((h) => h(win));
|
|
1484
|
+
}
|
|
1485
|
+
// -------------------------------------------------------------------------
|
|
1446
1486
|
// Private
|
|
1447
1487
|
// -------------------------------------------------------------------------
|
|
1448
1488
|
_register(win, isMain) {
|
|
@@ -1450,12 +1490,16 @@ var WindowManager = class {
|
|
|
1450
1490
|
if (isMain && this._mainWindowId === void 0) {
|
|
1451
1491
|
this._mainWindowId = win.id;
|
|
1452
1492
|
}
|
|
1493
|
+
this._emit("created", win);
|
|
1494
|
+
win.on("focus", () => this._emit("focused", win));
|
|
1495
|
+
win.on("blur", () => this._emit("blurred", win));
|
|
1453
1496
|
win.once("closed", () => {
|
|
1454
1497
|
this._windows.delete(win.id);
|
|
1455
1498
|
if (this._mainWindowId === win.id) {
|
|
1456
1499
|
this._mainWindowId = void 0;
|
|
1457
1500
|
}
|
|
1458
1501
|
Logger.log(`[WindowManager] Window #${win.id} closed`);
|
|
1502
|
+
this._emit("closed", win);
|
|
1459
1503
|
});
|
|
1460
1504
|
}
|
|
1461
1505
|
/**
|
|
@@ -1485,14 +1529,8 @@ WindowManager = __decorateClass([
|
|
|
1485
1529
|
Injectable({ lifetime: "singleton" })
|
|
1486
1530
|
], WindowManager);
|
|
1487
1531
|
|
|
1488
|
-
// src/internal/app.ts
|
|
1489
|
-
init_request();
|
|
1490
|
-
init_router();
|
|
1491
|
-
|
|
1492
1532
|
// src/internal/socket.ts
|
|
1493
|
-
init_injectable_decorator();
|
|
1494
1533
|
init_logger();
|
|
1495
|
-
init_request();
|
|
1496
1534
|
var NoxSocket = class {
|
|
1497
1535
|
constructor() {
|
|
1498
1536
|
this.channels = /* @__PURE__ */ new Map();
|
|
@@ -1515,7 +1553,6 @@ var NoxSocket = class {
|
|
|
1515
1553
|
throw new Error("Renderer event name must be a non-empty string.");
|
|
1516
1554
|
}
|
|
1517
1555
|
const recipients = targetSenderIds ?? this.getSenderIds();
|
|
1518
|
-
let delivered = 0;
|
|
1519
1556
|
for (const senderId of recipients) {
|
|
1520
1557
|
const channel = this.channels.get(senderId);
|
|
1521
1558
|
if (!channel) {
|
|
@@ -1524,15 +1561,17 @@ var NoxSocket = class {
|
|
|
1524
1561
|
}
|
|
1525
1562
|
try {
|
|
1526
1563
|
channel.socket.port1.postMessage(createRendererEventMessage(normalizedEvent, payload));
|
|
1527
|
-
delivered++;
|
|
1528
1564
|
} catch (error) {
|
|
1529
1565
|
Logger.error(`[Noxus] Failed to emit "${normalizedEvent}" to sender ${senderId}.`, error);
|
|
1530
1566
|
}
|
|
1531
1567
|
}
|
|
1532
|
-
return delivered;
|
|
1533
1568
|
}
|
|
1534
1569
|
emitToRenderer(senderId, eventName, payload) {
|
|
1535
|
-
|
|
1570
|
+
if (!this.channels.has(senderId)) {
|
|
1571
|
+
return false;
|
|
1572
|
+
}
|
|
1573
|
+
this.emit(eventName, payload, [senderId]);
|
|
1574
|
+
return true;
|
|
1536
1575
|
}
|
|
1537
1576
|
};
|
|
1538
1577
|
__name(NoxSocket, "NoxSocket");
|
|
@@ -1542,22 +1581,22 @@ NoxSocket = __decorateClass([
|
|
|
1542
1581
|
|
|
1543
1582
|
// src/internal/app.ts
|
|
1544
1583
|
var NoxApp = class {
|
|
1545
|
-
constructor() {
|
|
1546
|
-
this.router =
|
|
1547
|
-
this.socket =
|
|
1548
|
-
this.windowManager =
|
|
1584
|
+
constructor(router, socket, windowManager) {
|
|
1585
|
+
this.router = router;
|
|
1586
|
+
this.socket = socket;
|
|
1587
|
+
this.windowManager = windowManager;
|
|
1549
1588
|
// -------------------------------------------------------------------------
|
|
1550
1589
|
// IPC
|
|
1551
1590
|
// -------------------------------------------------------------------------
|
|
1552
1591
|
this.onRendererMessage = /* @__PURE__ */ __name(async (event) => {
|
|
1553
|
-
const { senderId, requestId, path: path2, method, body } = event.data;
|
|
1592
|
+
const { senderId, requestId, path: path2, method, body, query } = event.data;
|
|
1554
1593
|
const channels = this.socket.get(senderId);
|
|
1555
1594
|
if (!channels) {
|
|
1556
1595
|
Logger.error(`No message channel found for sender ID: ${senderId}`);
|
|
1557
1596
|
return;
|
|
1558
1597
|
}
|
|
1559
1598
|
try {
|
|
1560
|
-
const request = new Request(event, senderId, requestId, method, path2, body);
|
|
1599
|
+
const request = new Request(event, senderId, requestId, method, path2, body, query);
|
|
1561
1600
|
const response = await this.router.handle(request);
|
|
1562
1601
|
channels.request.port1.postMessage(response);
|
|
1563
1602
|
} catch (err) {
|
|
@@ -1608,7 +1647,7 @@ var NoxApp = class {
|
|
|
1608
1647
|
async load(importFns) {
|
|
1609
1648
|
InjectorExplorer.beginAccumulate();
|
|
1610
1649
|
await Promise.all(importFns.map((fn) => fn()));
|
|
1611
|
-
InjectorExplorer.flushAccumulated();
|
|
1650
|
+
await InjectorExplorer.flushAccumulated();
|
|
1612
1651
|
return this;
|
|
1613
1652
|
}
|
|
1614
1653
|
/**
|
|
@@ -1685,19 +1724,35 @@ NoxApp = __decorateClass([
|
|
|
1685
1724
|
// src/internal/bootstrap.ts
|
|
1686
1725
|
init_app_injector();
|
|
1687
1726
|
init_injector_explorer();
|
|
1727
|
+
init_logger();
|
|
1688
1728
|
import { app as app2 } from "electron/main";
|
|
1689
1729
|
async function bootstrapApplication(config = {}) {
|
|
1690
1730
|
await app2.whenReady();
|
|
1731
|
+
if (config.logLevel !== void 0) {
|
|
1732
|
+
if (config.logLevel === "none") {
|
|
1733
|
+
Logger.setLogLevel([]);
|
|
1734
|
+
} else if (Array.isArray(config.logLevel)) {
|
|
1735
|
+
Logger.setLogLevel(config.logLevel);
|
|
1736
|
+
} else {
|
|
1737
|
+
Logger.setLogLevel(config.logLevel);
|
|
1738
|
+
}
|
|
1739
|
+
}
|
|
1691
1740
|
const overrides = /* @__PURE__ */ new Map();
|
|
1692
1741
|
for (const { token: token2, useValue } of config.singletons ?? []) {
|
|
1693
1742
|
overrides.set(token2, useValue);
|
|
1694
1743
|
RootInjector.singletons.set(token2, useValue);
|
|
1695
1744
|
}
|
|
1745
|
+
InjectorExplorer.setControllerRegistrar((controllerClass, pathPrefix, routeGuards, routeMiddlewares) => {
|
|
1746
|
+
const router = inject(Router);
|
|
1747
|
+
router.registerController(controllerClass, pathPrefix, routeGuards, routeMiddlewares);
|
|
1748
|
+
});
|
|
1696
1749
|
InjectorExplorer.processPending(overrides);
|
|
1697
1750
|
const noxApp = inject(NoxApp);
|
|
1698
1751
|
if (config.routes?.length) {
|
|
1699
1752
|
for (const route of config.routes) {
|
|
1700
|
-
|
|
1753
|
+
if (route.load) {
|
|
1754
|
+
noxApp.lazy(route.path, route.load, route.guards, route.middlewares);
|
|
1755
|
+
}
|
|
1701
1756
|
}
|
|
1702
1757
|
}
|
|
1703
1758
|
if (config.eagerLoad?.length) {
|
|
@@ -1709,29 +1764,53 @@ async function bootstrapApplication(config = {}) {
|
|
|
1709
1764
|
__name(bootstrapApplication, "bootstrapApplication");
|
|
1710
1765
|
|
|
1711
1766
|
// src/main.ts
|
|
1712
|
-
init_exceptions();
|
|
1713
|
-
init_controller_decorator();
|
|
1714
|
-
init_injectable_decorator();
|
|
1715
|
-
init_method_decorator();
|
|
1716
1767
|
init_logger();
|
|
1717
1768
|
init_forward_ref();
|
|
1718
|
-
init_request();
|
|
1719
1769
|
|
|
1720
1770
|
// src/internal/routes.ts
|
|
1721
1771
|
function defineRoutes(routes) {
|
|
1722
|
-
const
|
|
1772
|
+
const flat = flattenRoutes(routes);
|
|
1773
|
+
const paths = flat.map((r) => r.path);
|
|
1723
1774
|
const duplicates = paths.filter((p, i) => paths.indexOf(p) !== i);
|
|
1724
1775
|
if (duplicates.length > 0) {
|
|
1725
1776
|
throw new Error(
|
|
1726
1777
|
`[Noxus] Duplicate route prefixes detected: ${[...new Set(duplicates)].map((d) => `"${d}"`).join(", ")}`
|
|
1727
1778
|
);
|
|
1728
1779
|
}
|
|
1729
|
-
|
|
1730
|
-
|
|
1731
|
-
|
|
1732
|
-
|
|
1780
|
+
const sorted = [...paths].sort();
|
|
1781
|
+
for (let i = 0; i < sorted.length - 1; i++) {
|
|
1782
|
+
const a = sorted[i];
|
|
1783
|
+
const b = sorted[i + 1];
|
|
1784
|
+
if (b.startsWith(a + "/")) {
|
|
1785
|
+
throw new Error(
|
|
1786
|
+
`[Noxus] Overlapping route prefixes detected: "${a}" and "${b}". Use nested children under "${a}" instead of declaring both as top-level routes.`
|
|
1787
|
+
);
|
|
1788
|
+
}
|
|
1789
|
+
}
|
|
1790
|
+
return flat;
|
|
1733
1791
|
}
|
|
1734
1792
|
__name(defineRoutes, "defineRoutes");
|
|
1793
|
+
function flattenRoutes(routes, parentPath = "", parentGuards = [], parentMiddlewares = []) {
|
|
1794
|
+
const result = [];
|
|
1795
|
+
for (const route of routes) {
|
|
1796
|
+
const path2 = [parentPath, route.path.replace(/^\/+|\/+$/g, "")].filter(Boolean).join("/");
|
|
1797
|
+
const guards = [.../* @__PURE__ */ new Set([...parentGuards, ...route.guards ?? []])];
|
|
1798
|
+
const middlewares = [.../* @__PURE__ */ new Set([...parentMiddlewares, ...route.middlewares ?? []])];
|
|
1799
|
+
if (route.load) {
|
|
1800
|
+
result.push({ ...route, path: path2, guards, middlewares });
|
|
1801
|
+
}
|
|
1802
|
+
if (route.children?.length) {
|
|
1803
|
+
result.push(...flattenRoutes(route.children, path2, guards, middlewares));
|
|
1804
|
+
}
|
|
1805
|
+
if (!route.load && !route.children?.length) {
|
|
1806
|
+
throw new Error(
|
|
1807
|
+
`[Noxus] Route "${path2}" has neither a load function nor children. It must have at least one of them.`
|
|
1808
|
+
);
|
|
1809
|
+
}
|
|
1810
|
+
}
|
|
1811
|
+
return result;
|
|
1812
|
+
}
|
|
1813
|
+
__name(flattenRoutes, "flattenRoutes");
|
|
1735
1814
|
export {
|
|
1736
1815
|
AppInjector,
|
|
1737
1816
|
BadGatewayException,
|
|
@@ -1784,6 +1863,7 @@ export {
|
|
|
1784
1863
|
inject,
|
|
1785
1864
|
isAtomicHttpMethod,
|
|
1786
1865
|
isRendererEventMessage,
|
|
1866
|
+
resetRootInjector,
|
|
1787
1867
|
token
|
|
1788
1868
|
};
|
|
1789
1869
|
/**
|