@noxfly/noxus 3.0.0-dev.2 → 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 +172 -125
- package/dist/main.d.ts +172 -125
- package/dist/main.js +985 -893
- package/dist/main.mjs +934 -843
- 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 +59 -12
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
|
-
|
|
1337
|
+
import { BrowserWindow } from "electron/main";
|
|
1310
1338
|
init_logger();
|
|
1311
|
-
import { BrowserWindow, screen } from "electron/main";
|
|
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
|
|
@@ -1361,18 +1389,24 @@ var WindowManager = class {
|
|
|
1361
1389
|
* win.loadFile('index.html');
|
|
1362
1390
|
*/
|
|
1363
1391
|
async createSplash(options = {}) {
|
|
1364
|
-
const {
|
|
1392
|
+
const {
|
|
1393
|
+
animationDuration = 10,
|
|
1394
|
+
expandToWorkArea = true,
|
|
1395
|
+
...bwOptions
|
|
1396
|
+
} = options;
|
|
1365
1397
|
const win = new BrowserWindow({
|
|
1366
1398
|
width: 600,
|
|
1367
1399
|
height: 600,
|
|
1368
1400
|
center: true,
|
|
1369
|
-
frame: false,
|
|
1370
1401
|
show: true,
|
|
1371
1402
|
...bwOptions
|
|
1372
1403
|
});
|
|
1373
1404
|
this._register(win, true);
|
|
1374
1405
|
Logger.log(`[WindowManager] Splash window #${win.id} created`);
|
|
1375
|
-
|
|
1406
|
+
if (expandToWorkArea) {
|
|
1407
|
+
await (() => new Promise((r) => setTimeout(r, 500)))();
|
|
1408
|
+
await this._expandToWorkArea(win, animationDuration);
|
|
1409
|
+
}
|
|
1376
1410
|
return win;
|
|
1377
1411
|
}
|
|
1378
1412
|
// -------------------------------------------------------------------------
|
|
@@ -1431,10 +1465,24 @@ var WindowManager = class {
|
|
|
1431
1465
|
*/
|
|
1432
1466
|
broadcast(channel, ...args) {
|
|
1433
1467
|
for (const win of this._windows.values()) {
|
|
1434
|
-
if (!win.isDestroyed())
|
|
1468
|
+
if (!win.isDestroyed()) {
|
|
1469
|
+
win.webContents.send(channel, ...args);
|
|
1470
|
+
}
|
|
1435
1471
|
}
|
|
1436
1472
|
}
|
|
1437
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
|
+
// -------------------------------------------------------------------------
|
|
1438
1486
|
// Private
|
|
1439
1487
|
// -------------------------------------------------------------------------
|
|
1440
1488
|
_register(win, isMain) {
|
|
@@ -1442,10 +1490,16 @@ var WindowManager = class {
|
|
|
1442
1490
|
if (isMain && this._mainWindowId === void 0) {
|
|
1443
1491
|
this._mainWindowId = win.id;
|
|
1444
1492
|
}
|
|
1493
|
+
this._emit("created", win);
|
|
1494
|
+
win.on("focus", () => this._emit("focused", win));
|
|
1495
|
+
win.on("blur", () => this._emit("blurred", win));
|
|
1445
1496
|
win.once("closed", () => {
|
|
1446
1497
|
this._windows.delete(win.id);
|
|
1447
|
-
if (this._mainWindowId === win.id)
|
|
1498
|
+
if (this._mainWindowId === win.id) {
|
|
1499
|
+
this._mainWindowId = void 0;
|
|
1500
|
+
}
|
|
1448
1501
|
Logger.log(`[WindowManager] Window #${win.id} closed`);
|
|
1502
|
+
this._emit("closed", win);
|
|
1449
1503
|
});
|
|
1450
1504
|
}
|
|
1451
1505
|
/**
|
|
@@ -1455,17 +1509,18 @@ var WindowManager = class {
|
|
|
1455
1509
|
*/
|
|
1456
1510
|
_expandToWorkArea(win, animationDuration) {
|
|
1457
1511
|
return new Promise((resolve) => {
|
|
1458
|
-
|
|
1459
|
-
win.setBounds({ x, y, width, height }, true);
|
|
1512
|
+
win.maximize();
|
|
1460
1513
|
let resolved = false;
|
|
1461
1514
|
const done = /* @__PURE__ */ __name(() => {
|
|
1462
|
-
if (resolved)
|
|
1515
|
+
if (resolved) {
|
|
1516
|
+
return;
|
|
1517
|
+
}
|
|
1463
1518
|
resolved = true;
|
|
1464
1519
|
win.removeListener("resize", done);
|
|
1465
1520
|
resolve();
|
|
1466
1521
|
}, "done");
|
|
1467
1522
|
win.once("resize", done);
|
|
1468
|
-
setTimeout(done, animationDuration
|
|
1523
|
+
setTimeout(done, animationDuration);
|
|
1469
1524
|
});
|
|
1470
1525
|
}
|
|
1471
1526
|
};
|
|
@@ -1474,14 +1529,8 @@ WindowManager = __decorateClass([
|
|
|
1474
1529
|
Injectable({ lifetime: "singleton" })
|
|
1475
1530
|
], WindowManager);
|
|
1476
1531
|
|
|
1477
|
-
// src/internal/app.ts
|
|
1478
|
-
init_request();
|
|
1479
|
-
init_router();
|
|
1480
|
-
|
|
1481
1532
|
// src/internal/socket.ts
|
|
1482
|
-
init_injectable_decorator();
|
|
1483
1533
|
init_logger();
|
|
1484
|
-
init_request();
|
|
1485
1534
|
var NoxSocket = class {
|
|
1486
1535
|
constructor() {
|
|
1487
1536
|
this.channels = /* @__PURE__ */ new Map();
|
|
@@ -1504,7 +1553,6 @@ var NoxSocket = class {
|
|
|
1504
1553
|
throw new Error("Renderer event name must be a non-empty string.");
|
|
1505
1554
|
}
|
|
1506
1555
|
const recipients = targetSenderIds ?? this.getSenderIds();
|
|
1507
|
-
let delivered = 0;
|
|
1508
1556
|
for (const senderId of recipients) {
|
|
1509
1557
|
const channel = this.channels.get(senderId);
|
|
1510
1558
|
if (!channel) {
|
|
@@ -1513,15 +1561,17 @@ var NoxSocket = class {
|
|
|
1513
1561
|
}
|
|
1514
1562
|
try {
|
|
1515
1563
|
channel.socket.port1.postMessage(createRendererEventMessage(normalizedEvent, payload));
|
|
1516
|
-
delivered++;
|
|
1517
1564
|
} catch (error) {
|
|
1518
1565
|
Logger.error(`[Noxus] Failed to emit "${normalizedEvent}" to sender ${senderId}.`, error);
|
|
1519
1566
|
}
|
|
1520
1567
|
}
|
|
1521
|
-
return delivered;
|
|
1522
1568
|
}
|
|
1523
1569
|
emitToRenderer(senderId, eventName, payload) {
|
|
1524
|
-
|
|
1570
|
+
if (!this.channels.has(senderId)) {
|
|
1571
|
+
return false;
|
|
1572
|
+
}
|
|
1573
|
+
this.emit(eventName, payload, [senderId]);
|
|
1574
|
+
return true;
|
|
1525
1575
|
}
|
|
1526
1576
|
};
|
|
1527
1577
|
__name(NoxSocket, "NoxSocket");
|
|
@@ -1531,22 +1581,22 @@ NoxSocket = __decorateClass([
|
|
|
1531
1581
|
|
|
1532
1582
|
// src/internal/app.ts
|
|
1533
1583
|
var NoxApp = class {
|
|
1534
|
-
constructor() {
|
|
1535
|
-
this.router =
|
|
1536
|
-
this.socket =
|
|
1537
|
-
this.windowManager =
|
|
1584
|
+
constructor(router, socket, windowManager) {
|
|
1585
|
+
this.router = router;
|
|
1586
|
+
this.socket = socket;
|
|
1587
|
+
this.windowManager = windowManager;
|
|
1538
1588
|
// -------------------------------------------------------------------------
|
|
1539
1589
|
// IPC
|
|
1540
1590
|
// -------------------------------------------------------------------------
|
|
1541
1591
|
this.onRendererMessage = /* @__PURE__ */ __name(async (event) => {
|
|
1542
|
-
const { senderId, requestId, path: path2, method, body } = event.data;
|
|
1592
|
+
const { senderId, requestId, path: path2, method, body, query } = event.data;
|
|
1543
1593
|
const channels = this.socket.get(senderId);
|
|
1544
1594
|
if (!channels) {
|
|
1545
1595
|
Logger.error(`No message channel found for sender ID: ${senderId}`);
|
|
1546
1596
|
return;
|
|
1547
1597
|
}
|
|
1548
1598
|
try {
|
|
1549
|
-
const request = new Request(event, senderId, requestId, method, path2, body);
|
|
1599
|
+
const request = new Request(event, senderId, requestId, method, path2, body, query);
|
|
1550
1600
|
const response = await this.router.handle(request);
|
|
1551
1601
|
channels.request.port1.postMessage(response);
|
|
1552
1602
|
} catch (err) {
|
|
@@ -1597,7 +1647,7 @@ var NoxApp = class {
|
|
|
1597
1647
|
async load(importFns) {
|
|
1598
1648
|
InjectorExplorer.beginAccumulate();
|
|
1599
1649
|
await Promise.all(importFns.map((fn) => fn()));
|
|
1600
|
-
InjectorExplorer.flushAccumulated();
|
|
1650
|
+
await InjectorExplorer.flushAccumulated();
|
|
1601
1651
|
return this;
|
|
1602
1652
|
}
|
|
1603
1653
|
/**
|
|
@@ -1674,19 +1724,35 @@ NoxApp = __decorateClass([
|
|
|
1674
1724
|
// src/internal/bootstrap.ts
|
|
1675
1725
|
init_app_injector();
|
|
1676
1726
|
init_injector_explorer();
|
|
1727
|
+
init_logger();
|
|
1677
1728
|
import { app as app2 } from "electron/main";
|
|
1678
1729
|
async function bootstrapApplication(config = {}) {
|
|
1679
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
|
+
}
|
|
1680
1740
|
const overrides = /* @__PURE__ */ new Map();
|
|
1681
1741
|
for (const { token: token2, useValue } of config.singletons ?? []) {
|
|
1682
1742
|
overrides.set(token2, useValue);
|
|
1683
1743
|
RootInjector.singletons.set(token2, useValue);
|
|
1684
1744
|
}
|
|
1745
|
+
InjectorExplorer.setControllerRegistrar((controllerClass, pathPrefix, routeGuards, routeMiddlewares) => {
|
|
1746
|
+
const router = inject(Router);
|
|
1747
|
+
router.registerController(controllerClass, pathPrefix, routeGuards, routeMiddlewares);
|
|
1748
|
+
});
|
|
1685
1749
|
InjectorExplorer.processPending(overrides);
|
|
1686
1750
|
const noxApp = inject(NoxApp);
|
|
1687
1751
|
if (config.routes?.length) {
|
|
1688
1752
|
for (const route of config.routes) {
|
|
1689
|
-
|
|
1753
|
+
if (route.load) {
|
|
1754
|
+
noxApp.lazy(route.path, route.load, route.guards, route.middlewares);
|
|
1755
|
+
}
|
|
1690
1756
|
}
|
|
1691
1757
|
}
|
|
1692
1758
|
if (config.eagerLoad?.length) {
|
|
@@ -1698,29 +1764,53 @@ async function bootstrapApplication(config = {}) {
|
|
|
1698
1764
|
__name(bootstrapApplication, "bootstrapApplication");
|
|
1699
1765
|
|
|
1700
1766
|
// src/main.ts
|
|
1701
|
-
init_exceptions();
|
|
1702
|
-
init_controller_decorator();
|
|
1703
|
-
init_injectable_decorator();
|
|
1704
|
-
init_method_decorator();
|
|
1705
1767
|
init_logger();
|
|
1706
1768
|
init_forward_ref();
|
|
1707
|
-
init_request();
|
|
1708
1769
|
|
|
1709
1770
|
// src/internal/routes.ts
|
|
1710
1771
|
function defineRoutes(routes) {
|
|
1711
|
-
const
|
|
1772
|
+
const flat = flattenRoutes(routes);
|
|
1773
|
+
const paths = flat.map((r) => r.path);
|
|
1712
1774
|
const duplicates = paths.filter((p, i) => paths.indexOf(p) !== i);
|
|
1713
1775
|
if (duplicates.length > 0) {
|
|
1714
1776
|
throw new Error(
|
|
1715
1777
|
`[Noxus] Duplicate route prefixes detected: ${[...new Set(duplicates)].map((d) => `"${d}"`).join(", ")}`
|
|
1716
1778
|
);
|
|
1717
1779
|
}
|
|
1718
|
-
|
|
1719
|
-
|
|
1720
|
-
|
|
1721
|
-
|
|
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;
|
|
1722
1791
|
}
|
|
1723
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");
|
|
1724
1814
|
export {
|
|
1725
1815
|
AppInjector,
|
|
1726
1816
|
BadGatewayException,
|
|
@@ -1773,6 +1863,7 @@ export {
|
|
|
1773
1863
|
inject,
|
|
1774
1864
|
isAtomicHttpMethod,
|
|
1775
1865
|
isRendererEventMessage,
|
|
1866
|
+
resetRootInjector,
|
|
1776
1867
|
token
|
|
1777
1868
|
};
|
|
1778
1869
|
/**
|