@noxfly/noxus 2.5.0 → 3.0.0-dev.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (48) hide show
  1. package/README.md +403 -341
  2. package/dist/app-injector-Bz3Upc0y.d.mts +125 -0
  3. package/dist/app-injector-Bz3Upc0y.d.ts +125 -0
  4. package/dist/child.d.mts +48 -22
  5. package/dist/child.d.ts +48 -22
  6. package/dist/child.js +1111 -1341
  7. package/dist/child.mjs +1087 -1295
  8. package/dist/main.d.mts +301 -309
  9. package/dist/main.d.ts +301 -309
  10. package/dist/main.js +1471 -1650
  11. package/dist/main.mjs +1420 -1570
  12. package/dist/renderer.d.mts +3 -3
  13. package/dist/renderer.d.ts +3 -3
  14. package/dist/renderer.js +109 -135
  15. package/dist/renderer.mjs +109 -135
  16. package/dist/request-BlTtiHbi.d.ts +112 -0
  17. package/dist/request-qJ9EiDZc.d.mts +112 -0
  18. package/package.json +7 -7
  19. package/src/DI/app-injector.ts +95 -106
  20. package/src/DI/injector-explorer.ts +93 -119
  21. package/src/DI/token.ts +53 -0
  22. package/src/app.ts +141 -168
  23. package/src/bootstrap.ts +78 -54
  24. package/src/decorators/controller.decorator.ts +38 -27
  25. package/src/decorators/guards.decorator.ts +5 -64
  26. package/src/decorators/injectable.decorator.ts +68 -15
  27. package/src/decorators/method.decorator.ts +40 -81
  28. package/src/decorators/middleware.decorator.ts +5 -72
  29. package/src/index.ts +2 -0
  30. package/src/main.ts +4 -8
  31. package/src/non-electron-process.ts +0 -1
  32. package/src/preload-bridge.ts +1 -1
  33. package/src/renderer-client.ts +2 -2
  34. package/src/renderer-events.ts +1 -1
  35. package/src/request.ts +3 -3
  36. package/src/router.ts +190 -431
  37. package/src/routes.ts +78 -0
  38. package/src/socket.ts +4 -4
  39. package/src/window/window-manager.ts +255 -0
  40. package/tsconfig.json +5 -10
  41. package/tsup.config.ts +2 -2
  42. package/dist/app-injector-B3MvgV3k.d.mts +0 -95
  43. package/dist/app-injector-B3MvgV3k.d.ts +0 -95
  44. package/dist/request-CdpZ9qZL.d.ts +0 -167
  45. package/dist/request-Dx_5Prte.d.mts +0 -167
  46. package/src/decorators/inject.decorator.ts +0 -24
  47. package/src/decorators/injectable.metadata.ts +0 -15
  48. package/src/decorators/module.decorator.ts +0 -75
package/dist/main.js CHANGED
@@ -10,8 +10,10 @@ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
10
10
  var __getOwnPropNames = Object.getOwnPropertyNames;
11
11
  var __getProtoOf = Object.getPrototypeOf;
12
12
  var __hasOwnProp = Object.prototype.hasOwnProperty;
13
- var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
14
13
  var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
14
+ var __esm = (fn, res) => function __init() {
15
+ return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
16
+ };
15
17
  var __export = (target, all) => {
16
18
  for (var name in all)
17
19
  __defProp(target, name, { get: all[name], enumerable: true });
@@ -33,533 +35,169 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
33
35
  mod
34
36
  ));
35
37
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
36
- var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
37
-
38
- // src/main.ts
39
- var main_exports = {};
40
- __export(main_exports, {
41
- AppInjector: () => AppInjector,
42
- Authorize: () => Authorize,
43
- BadGatewayException: () => BadGatewayException,
44
- BadRequestException: () => BadRequestException,
45
- CONTROLLER_METADATA_KEY: () => CONTROLLER_METADATA_KEY,
46
- ConflictException: () => ConflictException,
47
- Controller: () => Controller,
48
- Delete: () => Delete,
49
- ForbiddenException: () => ForbiddenException,
50
- ForwardReference: () => ForwardReference,
51
- GatewayTimeoutException: () => GatewayTimeoutException,
52
- Get: () => Get,
53
- HttpVersionNotSupportedException: () => HttpVersionNotSupportedException,
54
- INJECTABLE_METADATA_KEY: () => INJECTABLE_METADATA_KEY,
55
- INJECT_METADATA_KEY: () => INJECT_METADATA_KEY,
56
- Inject: () => Inject,
57
- Injectable: () => Injectable,
58
- InsufficientStorageException: () => InsufficientStorageException,
59
- InternalServerException: () => InternalServerException,
60
- Logger: () => Logger,
61
- LoopDetectedException: () => LoopDetectedException,
62
- MODULE_METADATA_KEY: () => MODULE_METADATA_KEY,
63
- MethodNotAllowedException: () => MethodNotAllowedException,
64
- Module: () => Module,
65
- NetworkAuthenticationRequiredException: () => NetworkAuthenticationRequiredException,
66
- NetworkConnectTimeoutException: () => NetworkConnectTimeoutException,
67
- NotAcceptableException: () => NotAcceptableException,
68
- NotExtendedException: () => NotExtendedException,
69
- NotFoundException: () => NotFoundException,
70
- NotImplementedException: () => NotImplementedException,
71
- NoxApp: () => NoxApp,
72
- NoxSocket: () => NoxSocket,
73
- Patch: () => Patch,
74
- PaymentRequiredException: () => PaymentRequiredException,
75
- Post: () => Post,
76
- Put: () => Put,
77
- RENDERER_EVENT_TYPE: () => RENDERER_EVENT_TYPE,
78
- ROUTE_METADATA_KEY: () => ROUTE_METADATA_KEY,
79
- Request: () => Request,
80
- RequestTimeoutException: () => RequestTimeoutException,
81
- ResponseException: () => ResponseException,
82
- RootInjector: () => RootInjector,
83
- Router: () => Router,
84
- ServiceUnavailableException: () => ServiceUnavailableException,
85
- TooManyRequestsException: () => TooManyRequestsException,
86
- UnauthorizedException: () => UnauthorizedException,
87
- UpgradeRequiredException: () => UpgradeRequiredException,
88
- UseMiddlewares: () => UseMiddlewares,
89
- VariantAlsoNegotiatesException: () => VariantAlsoNegotiatesException,
90
- bootstrapApplication: () => bootstrapApplication,
91
- createRendererEventMessage: () => createRendererEventMessage,
92
- forwardRef: () => forwardRef,
93
- getControllerMetadata: () => getControllerMetadata,
94
- getGuardForController: () => getGuardForController,
95
- getGuardForControllerAction: () => getGuardForControllerAction,
96
- getInjectableMetadata: () => getInjectableMetadata,
97
- getMiddlewaresForController: () => getMiddlewaresForController,
98
- getMiddlewaresForControllerAction: () => getMiddlewaresForControllerAction,
99
- getModuleMetadata: () => getModuleMetadata,
100
- getRouteMetadata: () => getRouteMetadata,
101
- hasInjectableMetadata: () => hasInjectableMetadata,
102
- inject: () => inject,
103
- isRendererEventMessage: () => isRendererEventMessage
104
- });
105
- module.exports = __toCommonJS(main_exports);
106
-
107
- // src/DI/app-injector.ts
108
- var import_reflect_metadata2 = require("reflect-metadata");
109
-
110
- // src/decorators/inject.decorator.ts
111
- var import_reflect_metadata = require("reflect-metadata");
112
- var INJECT_METADATA_KEY = "custom:inject";
113
- function Inject(token) {
114
- return (target, propertyKey, parameterIndex) => {
115
- const existingParameters = Reflect.getOwnMetadata(INJECT_METADATA_KEY, target) || [];
116
- existingParameters[parameterIndex] = token;
117
- Reflect.defineMetadata(INJECT_METADATA_KEY, existingParameters, target);
118
- };
119
- }
120
- __name(Inject, "Inject");
121
-
122
- // src/exceptions.ts
123
- var _ResponseException = class _ResponseException extends Error {
124
- constructor(statusOrMessage, message) {
125
- let statusCode;
126
- if (typeof statusOrMessage === "number") {
127
- statusCode = statusOrMessage;
128
- } else if (typeof statusOrMessage === "string") {
129
- message = statusOrMessage;
130
- }
131
- super(message ?? "");
132
- __publicField(this, "status", 0);
133
- if (statusCode !== void 0) {
134
- this.status = statusCode;
135
- }
136
- this.name = this.constructor.name.replace(/([A-Z])/g, " $1");
137
- }
138
- };
139
- __name(_ResponseException, "ResponseException");
140
- var ResponseException = _ResponseException;
141
- var _BadRequestException = class _BadRequestException extends ResponseException {
142
- constructor() {
143
- super(...arguments);
144
- __publicField(this, "status", 400);
145
- }
146
- };
147
- __name(_BadRequestException, "BadRequestException");
148
- var BadRequestException = _BadRequestException;
149
- var _UnauthorizedException = class _UnauthorizedException extends ResponseException {
150
- constructor() {
151
- super(...arguments);
152
- __publicField(this, "status", 401);
153
- }
154
- };
155
- __name(_UnauthorizedException, "UnauthorizedException");
156
- var UnauthorizedException = _UnauthorizedException;
157
- var _PaymentRequiredException = class _PaymentRequiredException extends ResponseException {
158
- constructor() {
159
- super(...arguments);
160
- __publicField(this, "status", 402);
161
- }
162
- };
163
- __name(_PaymentRequiredException, "PaymentRequiredException");
164
- var PaymentRequiredException = _PaymentRequiredException;
165
- var _ForbiddenException = class _ForbiddenException extends ResponseException {
166
- constructor() {
167
- super(...arguments);
168
- __publicField(this, "status", 403);
169
- }
170
- };
171
- __name(_ForbiddenException, "ForbiddenException");
172
- var ForbiddenException = _ForbiddenException;
173
- var _NotFoundException = class _NotFoundException extends ResponseException {
174
- constructor() {
175
- super(...arguments);
176
- __publicField(this, "status", 404);
177
- }
178
- };
179
- __name(_NotFoundException, "NotFoundException");
180
- var NotFoundException = _NotFoundException;
181
- var _MethodNotAllowedException = class _MethodNotAllowedException extends ResponseException {
182
- constructor() {
183
- super(...arguments);
184
- __publicField(this, "status", 405);
185
- }
186
- };
187
- __name(_MethodNotAllowedException, "MethodNotAllowedException");
188
- var MethodNotAllowedException = _MethodNotAllowedException;
189
- var _NotAcceptableException = class _NotAcceptableException extends ResponseException {
190
- constructor() {
191
- super(...arguments);
192
- __publicField(this, "status", 406);
193
- }
194
- };
195
- __name(_NotAcceptableException, "NotAcceptableException");
196
- var NotAcceptableException = _NotAcceptableException;
197
- var _RequestTimeoutException = class _RequestTimeoutException extends ResponseException {
198
- constructor() {
199
- super(...arguments);
200
- __publicField(this, "status", 408);
201
- }
202
- };
203
- __name(_RequestTimeoutException, "RequestTimeoutException");
204
- var RequestTimeoutException = _RequestTimeoutException;
205
- var _ConflictException = class _ConflictException extends ResponseException {
206
- constructor() {
207
- super(...arguments);
208
- __publicField(this, "status", 409);
209
- }
210
- };
211
- __name(_ConflictException, "ConflictException");
212
- var ConflictException = _ConflictException;
213
- var _UpgradeRequiredException = class _UpgradeRequiredException extends ResponseException {
214
- constructor() {
215
- super(...arguments);
216
- __publicField(this, "status", 426);
217
- }
218
- };
219
- __name(_UpgradeRequiredException, "UpgradeRequiredException");
220
- var UpgradeRequiredException = _UpgradeRequiredException;
221
- var _TooManyRequestsException = class _TooManyRequestsException extends ResponseException {
222
- constructor() {
223
- super(...arguments);
224
- __publicField(this, "status", 429);
225
- }
226
- };
227
- __name(_TooManyRequestsException, "TooManyRequestsException");
228
- var TooManyRequestsException = _TooManyRequestsException;
229
- var _InternalServerException = class _InternalServerException extends ResponseException {
230
- constructor() {
231
- super(...arguments);
232
- __publicField(this, "status", 500);
233
- }
234
- };
235
- __name(_InternalServerException, "InternalServerException");
236
- var InternalServerException = _InternalServerException;
237
- var _NotImplementedException = class _NotImplementedException extends ResponseException {
238
- constructor() {
239
- super(...arguments);
240
- __publicField(this, "status", 501);
241
- }
242
- };
243
- __name(_NotImplementedException, "NotImplementedException");
244
- var NotImplementedException = _NotImplementedException;
245
- var _BadGatewayException = class _BadGatewayException extends ResponseException {
246
- constructor() {
247
- super(...arguments);
248
- __publicField(this, "status", 502);
249
- }
250
- };
251
- __name(_BadGatewayException, "BadGatewayException");
252
- var BadGatewayException = _BadGatewayException;
253
- var _ServiceUnavailableException = class _ServiceUnavailableException extends ResponseException {
254
- constructor() {
255
- super(...arguments);
256
- __publicField(this, "status", 503);
257
- }
258
- };
259
- __name(_ServiceUnavailableException, "ServiceUnavailableException");
260
- var ServiceUnavailableException = _ServiceUnavailableException;
261
- var _GatewayTimeoutException = class _GatewayTimeoutException extends ResponseException {
262
- constructor() {
263
- super(...arguments);
264
- __publicField(this, "status", 504);
265
- }
266
- };
267
- __name(_GatewayTimeoutException, "GatewayTimeoutException");
268
- var GatewayTimeoutException = _GatewayTimeoutException;
269
- var _HttpVersionNotSupportedException = class _HttpVersionNotSupportedException extends ResponseException {
270
- constructor() {
271
- super(...arguments);
272
- __publicField(this, "status", 505);
273
- }
38
+ var __decorateClass = (decorators, target, key, kind) => {
39
+ var result = kind > 1 ? void 0 : kind ? __getOwnPropDesc(target, key) : target;
40
+ for (var i = decorators.length - 1, decorator; i >= 0; i--)
41
+ if (decorator = decorators[i])
42
+ result = (kind ? decorator(target, key, result) : decorator(result)) || result;
43
+ if (kind && result) __defProp(target, key, result);
44
+ return result;
274
45
  };
275
- __name(_HttpVersionNotSupportedException, "HttpVersionNotSupportedException");
276
- var HttpVersionNotSupportedException = _HttpVersionNotSupportedException;
277
- var _VariantAlsoNegotiatesException = class _VariantAlsoNegotiatesException extends ResponseException {
278
- constructor() {
279
- super(...arguments);
280
- __publicField(this, "status", 506);
281
- }
282
- };
283
- __name(_VariantAlsoNegotiatesException, "VariantAlsoNegotiatesException");
284
- var VariantAlsoNegotiatesException = _VariantAlsoNegotiatesException;
285
- var _InsufficientStorageException = class _InsufficientStorageException extends ResponseException {
286
- constructor() {
287
- super(...arguments);
288
- __publicField(this, "status", 507);
289
- }
290
- };
291
- __name(_InsufficientStorageException, "InsufficientStorageException");
292
- var InsufficientStorageException = _InsufficientStorageException;
293
- var _LoopDetectedException = class _LoopDetectedException extends ResponseException {
294
- constructor() {
295
- super(...arguments);
296
- __publicField(this, "status", 508);
297
- }
298
- };
299
- __name(_LoopDetectedException, "LoopDetectedException");
300
- var LoopDetectedException = _LoopDetectedException;
301
- var _NotExtendedException = class _NotExtendedException extends ResponseException {
302
- constructor() {
303
- super(...arguments);
304
- __publicField(this, "status", 510);
305
- }
306
- };
307
- __name(_NotExtendedException, "NotExtendedException");
308
- var NotExtendedException = _NotExtendedException;
309
- var _NetworkAuthenticationRequiredException = class _NetworkAuthenticationRequiredException extends ResponseException {
310
- constructor() {
311
- super(...arguments);
312
- __publicField(this, "status", 511);
313
- }
314
- };
315
- __name(_NetworkAuthenticationRequiredException, "NetworkAuthenticationRequiredException");
316
- var NetworkAuthenticationRequiredException = _NetworkAuthenticationRequiredException;
317
- var _NetworkConnectTimeoutException = class _NetworkConnectTimeoutException extends ResponseException {
318
- constructor() {
319
- super(...arguments);
320
- __publicField(this, "status", 599);
321
- }
322
- };
323
- __name(_NetworkConnectTimeoutException, "NetworkConnectTimeoutException");
324
- var NetworkConnectTimeoutException = _NetworkConnectTimeoutException;
325
46
 
326
47
  // src/utils/forward-ref.ts
327
- var _ForwardReference = class _ForwardReference {
328
- constructor(forwardRefFn) {
329
- __publicField(this, "forwardRefFn");
330
- this.forwardRefFn = forwardRefFn;
331
- }
332
- };
333
- __name(_ForwardReference, "ForwardReference");
334
- var ForwardReference = _ForwardReference;
335
48
  function forwardRef(fn) {
336
49
  return new ForwardReference(fn);
337
50
  }
338
- __name(forwardRef, "forwardRef");
339
-
340
- // src/DI/app-injector.ts
341
- var _AppInjector = class _AppInjector {
342
- constructor(name = null) {
343
- __publicField(this, "name");
344
- __publicField(this, "bindings", /* @__PURE__ */ new Map());
345
- __publicField(this, "singletons", /* @__PURE__ */ new Map());
346
- __publicField(this, "scoped", /* @__PURE__ */ new Map());
347
- this.name = name;
348
- }
349
- /**
350
- * Typically used to create a dependency injection scope
351
- * at the "scope" level (i.e., per-request lifetime).
352
- *
353
- * SHOULD NOT BE USED by anything else than the framework itself.
354
- */
355
- createScope() {
356
- const scope = new _AppInjector();
357
- scope.bindings = this.bindings;
358
- scope.singletons = this.singletons;
359
- return scope;
360
- }
361
- /**
362
- * Called when resolving a dependency,
363
- * i.e., retrieving the instance of a given class.
364
- */
365
- resolve(target) {
366
- if (target instanceof ForwardReference) {
367
- return new Proxy({}, {
368
- get: /* @__PURE__ */ __name((obj, prop, receiver) => {
369
- const realType = target.forwardRefFn();
370
- const instance = this.resolve(realType);
371
- const value = Reflect.get(instance, prop, receiver);
372
- return typeof value === "function" ? value.bind(instance) : value;
373
- }, "get"),
374
- set: /* @__PURE__ */ __name((obj, prop, value, receiver) => {
375
- const realType = target.forwardRefFn();
376
- const instance = this.resolve(realType);
377
- return Reflect.set(instance, prop, value, receiver);
378
- }, "set"),
379
- getPrototypeOf: /* @__PURE__ */ __name(() => {
380
- const realType = target.forwardRefFn();
381
- return realType.prototype;
382
- }, "getPrototypeOf")
383
- });
384
- }
385
- const binding = this.bindings.get(target);
386
- if (!binding) {
387
- if (target === void 0) {
388
- throw new InternalServerException("Failed to resolve a dependency injection : Undefined target type.\nThis might be caused by a circular dependency.");
389
- }
390
- const name = target.name || "unknown";
391
- throw new InternalServerException(`Failed to resolve a dependency injection : No binding for type ${name}.
392
- Did you forget to use @Injectable() decorator ?`);
393
- }
394
- switch (binding.lifetime) {
395
- case "transient":
396
- return this.instantiate(binding.implementation);
397
- case "scope": {
398
- if (this.scoped.has(target)) {
399
- return this.scoped.get(target);
400
- }
401
- const instance = this.instantiate(binding.implementation);
402
- this.scoped.set(target, instance);
403
- return instance;
404
- }
405
- case "singleton": {
406
- if (binding.instance === void 0 && this.name === "root") {
407
- binding.instance = this.instantiate(binding.implementation);
408
- this.singletons.set(target, binding.instance);
409
- }
410
- return binding.instance;
51
+ var _ForwardReference, ForwardReference;
52
+ var init_forward_ref = __esm({
53
+ "src/utils/forward-ref.ts"() {
54
+ "use strict";
55
+ _ForwardReference = class _ForwardReference {
56
+ constructor(forwardRefFn) {
57
+ this.forwardRefFn = forwardRefFn;
411
58
  }
412
- }
413
- }
414
- /**
415
- * Instantiates a class, resolving its dependencies.
416
- */
417
- instantiate(target) {
418
- const paramTypes = Reflect.getMetadata("design:paramtypes", target) || [];
419
- const injectParams = Reflect.getMetadata(INJECT_METADATA_KEY, target) || [];
420
- const params = paramTypes.map((paramType, index) => {
421
- const overrideToken = injectParams[index];
422
- const actualToken = overrideToken !== void 0 ? overrideToken : paramType;
423
- return this.resolve(actualToken);
424
- });
425
- return new target(...params);
59
+ };
60
+ __name(_ForwardReference, "ForwardReference");
61
+ ForwardReference = _ForwardReference;
62
+ __name(forwardRef, "forwardRef");
426
63
  }
427
- };
428
- __name(_AppInjector, "AppInjector");
429
- var AppInjector = _AppInjector;
430
- function inject(t) {
431
- return RootInjector.resolve(t);
432
- }
433
- __name(inject, "inject");
434
- var RootInjector = new AppInjector("root");
435
-
436
- // src/router.ts
437
- var import_reflect_metadata4 = require("reflect-metadata");
438
-
439
- // src/decorators/guards.decorator.ts
440
- function Authorize(...guardClasses) {
441
- return (target, propertyKey) => {
442
- let key;
443
- if (propertyKey) {
444
- const ctrlName = target.constructor.name;
445
- const actionName = propertyKey;
446
- key = `${ctrlName}.${actionName}`;
447
- } else {
448
- const ctrlName = target.name;
449
- key = `${ctrlName}`;
450
- }
451
- if (authorizations.has(key)) {
452
- throw new Error(`Guard(s) already registered for ${key}`);
453
- }
454
- authorizations.set(key, guardClasses);
455
- };
456
- }
457
- __name(Authorize, "Authorize");
458
- function getGuardForController(controllerName) {
459
- const key = `${controllerName}`;
460
- return authorizations.get(key) ?? [];
461
- }
462
- __name(getGuardForController, "getGuardForController");
463
- function getGuardForControllerAction(controllerName, actionName) {
464
- const key = `${controllerName}.${actionName}`;
465
- return authorizations.get(key) ?? [];
466
- }
467
- __name(getGuardForControllerAction, "getGuardForControllerAction");
468
- var authorizations = /* @__PURE__ */ new Map();
64
+ });
469
65
 
470
- // src/decorators/injectable.metadata.ts
471
- var INJECTABLE_METADATA_KEY = Symbol("INJECTABLE_METADATA_KEY");
472
- function defineInjectableMetadata(target, lifetime) {
473
- Reflect.defineMetadata(INJECTABLE_METADATA_KEY, lifetime, target);
474
- }
475
- __name(defineInjectableMetadata, "defineInjectableMetadata");
476
- function getInjectableMetadata(target) {
477
- return Reflect.getMetadata(INJECTABLE_METADATA_KEY, target);
478
- }
479
- __name(getInjectableMetadata, "getInjectableMetadata");
480
- function hasInjectableMetadata(target) {
481
- return Reflect.hasMetadata(INJECTABLE_METADATA_KEY, target);
66
+ // src/DI/token.ts
67
+ function token(target) {
68
+ return new Token(target);
482
69
  }
483
- __name(hasInjectableMetadata, "hasInjectableMetadata");
484
-
485
- // src/decorators/method.decorator.ts
486
- function createRouteDecorator(verb) {
487
- return (path2) => {
488
- return (target, propertyKey) => {
489
- const existingRoutes = Reflect.getMetadata(ROUTE_METADATA_KEY, target.constructor) || [];
490
- const metadata = {
491
- method: verb,
492
- path: path2.trim().replace(/^\/|\/$/g, ""),
493
- handler: propertyKey,
494
- guards: getGuardForControllerAction(target.constructor.__controllerName, propertyKey)
495
- };
496
- existingRoutes.push(metadata);
497
- Reflect.defineMetadata(ROUTE_METADATA_KEY, existingRoutes, target.constructor);
70
+ var _Token, Token;
71
+ var init_token = __esm({
72
+ "src/DI/token.ts"() {
73
+ "use strict";
74
+ _Token = class _Token {
75
+ constructor(target) {
76
+ this.target = target;
77
+ this.description = typeof target === "string" ? target : target.name;
78
+ }
79
+ toString() {
80
+ return `Token(${this.description})`;
81
+ }
498
82
  };
499
- };
83
+ __name(_Token, "Token");
84
+ Token = _Token;
85
+ __name(token, "token");
86
+ }
87
+ });
88
+
89
+ // src/DI/app-injector.ts
90
+ function keyOf(k) {
91
+ return k;
500
92
  }
501
- __name(createRouteDecorator, "createRouteDecorator");
502
- function getRouteMetadata(target) {
503
- return Reflect.getMetadata(ROUTE_METADATA_KEY, target) || [];
93
+ function inject(t) {
94
+ return RootInjector.resolve(t);
504
95
  }
505
- __name(getRouteMetadata, "getRouteMetadata");
506
- var Get = createRouteDecorator("GET");
507
- var Post = createRouteDecorator("POST");
508
- var Put = createRouteDecorator("PUT");
509
- var Patch = createRouteDecorator("PATCH");
510
- var Delete = createRouteDecorator("DELETE");
511
- var ROUTE_METADATA_KEY = Symbol("ROUTE_METADATA_KEY");
512
-
513
- // src/decorators/module.decorator.ts
514
- function Module(metadata) {
515
- return (target) => {
516
- const checkModule = /* @__PURE__ */ __name((arr, arrName) => {
517
- if (!arr) return;
518
- for (const clazz of arr) {
519
- if (!Reflect.getMetadata(MODULE_METADATA_KEY, clazz)) {
520
- throw new Error(`Class ${clazz.name} in ${arrName} must be decorated with @Module`);
521
- }
96
+ var _AppInjector, AppInjector, RootInjector;
97
+ var init_app_injector = __esm({
98
+ "src/DI/app-injector.ts"() {
99
+ "use strict";
100
+ init_forward_ref();
101
+ init_token();
102
+ __name(keyOf, "keyOf");
103
+ _AppInjector = class _AppInjector {
104
+ constructor(name = null) {
105
+ this.name = name;
106
+ this.bindings = /* @__PURE__ */ new Map();
107
+ this.singletons = /* @__PURE__ */ new Map();
108
+ this.scoped = /* @__PURE__ */ new Map();
109
+ }
110
+ /**
111
+ * Creates a child scope for per-request lifetime resolution.
112
+ */
113
+ createScope() {
114
+ const scope = new _AppInjector();
115
+ scope.bindings = this.bindings;
116
+ scope.singletons = this.singletons;
117
+ return scope;
522
118
  }
523
- }, "checkModule");
524
- const checkInjectable = /* @__PURE__ */ __name((arr) => {
525
- if (!arr) return;
526
- for (const clazz of arr) {
527
- if (!Reflect.getMetadata(INJECTABLE_METADATA_KEY, clazz)) {
528
- throw new Error(`Class ${clazz.name} in providers must be decorated with @Injectable`);
119
+ /**
120
+ * Registers a binding explicitly.
121
+ */
122
+ register(key, implementation, lifetime, deps = []) {
123
+ const k = keyOf(key);
124
+ if (!this.bindings.has(k)) {
125
+ this.bindings.set(k, { lifetime, implementation, deps });
529
126
  }
530
127
  }
531
- }, "checkInjectable");
532
- const checkController = /* @__PURE__ */ __name((arr) => {
533
- if (!arr) return;
534
- for (const clazz of arr) {
535
- if (!Reflect.getMetadata(CONTROLLER_METADATA_KEY, clazz)) {
536
- throw new Error(`Class ${clazz.name} in controllers must be decorated with @Controller`);
128
+ /**
129
+ * Resolves a dependency by token or class reference.
130
+ */
131
+ resolve(target) {
132
+ if (target instanceof ForwardReference) {
133
+ return this._resolveForwardRef(target);
134
+ }
135
+ const k = keyOf(target);
136
+ const binding = this.bindings.get(k);
137
+ if (!binding) {
138
+ const name = target instanceof Token ? target.description : target.name ?? "unknown";
139
+ throw new Error(
140
+ `[Noxus DI] No binding found for "${name}".
141
+ Did you forget to declare it in @Injectable({ deps }) or in bootstrapApplication({ singletons })?`
142
+ );
143
+ }
144
+ switch (binding.lifetime) {
145
+ case "transient":
146
+ return this._instantiate(binding);
147
+ case "scope": {
148
+ if (this.scoped.has(k)) return this.scoped.get(k);
149
+ const inst = this._instantiate(binding);
150
+ this.scoped.set(k, inst);
151
+ return inst;
152
+ }
153
+ case "singleton": {
154
+ if (this.singletons.has(k)) return this.singletons.get(k);
155
+ const inst = this._instantiate(binding);
156
+ this.singletons.set(k, inst);
157
+ if (binding.instance === void 0) {
158
+ binding.instance = inst;
159
+ }
160
+ return inst;
161
+ }
537
162
  }
538
163
  }
539
- }, "checkController");
540
- checkModule(metadata.imports, "imports");
541
- checkModule(metadata.exports, "exports");
542
- checkInjectable(metadata.providers);
543
- checkController(metadata.controllers);
544
- Reflect.defineMetadata(MODULE_METADATA_KEY, metadata, target);
545
- Injectable("singleton")(target);
546
- };
547
- }
548
- __name(Module, "Module");
549
- function getModuleMetadata(target) {
550
- return Reflect.getMetadata(MODULE_METADATA_KEY, target);
551
- }
552
- __name(getModuleMetadata, "getModuleMetadata");
553
- var MODULE_METADATA_KEY = Symbol("MODULE_METADATA_KEY");
164
+ // -------------------------------------------------------------------------
165
+ _resolveForwardRef(ref) {
166
+ return new Proxy({}, {
167
+ get: /* @__PURE__ */ __name((_obj, prop, receiver) => {
168
+ const realType = ref.forwardRefFn();
169
+ const instance = this.resolve(realType);
170
+ const value = Reflect.get(instance, prop, receiver);
171
+ return typeof value === "function" ? value.bind(instance) : value;
172
+ }, "get"),
173
+ set: /* @__PURE__ */ __name((_obj, prop, value, receiver) => {
174
+ const realType = ref.forwardRefFn();
175
+ const instance = this.resolve(realType);
176
+ return Reflect.set(instance, prop, value, receiver);
177
+ }, "set"),
178
+ getPrototypeOf: /* @__PURE__ */ __name(() => {
179
+ const realType = ref.forwardRefFn();
180
+ return realType.prototype;
181
+ }, "getPrototypeOf")
182
+ });
183
+ }
184
+ _instantiate(binding) {
185
+ const resolvedDeps = binding.deps.map((dep) => this.resolve(dep));
186
+ return new binding.implementation(...resolvedDeps);
187
+ }
188
+ };
189
+ __name(_AppInjector, "AppInjector");
190
+ AppInjector = _AppInjector;
191
+ RootInjector = new AppInjector("root");
192
+ __name(inject, "inject");
193
+ }
194
+ });
554
195
 
555
196
  // src/utils/logger.ts
556
- var fs = __toESM(require("fs"));
557
- var path = __toESM(require("path"));
558
197
  function getPrettyTimestamp() {
559
198
  const now = /* @__PURE__ */ new Date();
560
199
  return `${now.getDate().toString().padStart(2, "0")}/${(now.getMonth() + 1).toString().padStart(2, "0")}/${now.getFullYear()} ${now.getHours().toString().padStart(2, "0")}:${now.getMinutes().toString().padStart(2, "0")}:${now.getSeconds().toString().padStart(2, "0")}`;
561
200
  }
562
- __name(getPrettyTimestamp, "getPrettyTimestamp");
563
201
  function getLogPrefix(callee, messageType, color) {
564
202
  const timestamp = getPrettyTimestamp();
565
203
  const spaces = " ".repeat(10 - messageType.length);
@@ -572,7 +210,6 @@ function getLogPrefix(callee, messageType, color) {
572
210
  }
573
211
  return `${color}[APP] ${process.pid} - ${colReset}${timestamp}${spaces}${color}${messageType.toUpperCase()}${colReset} ${colCallee}[${callee}]${colReset}`;
574
212
  }
575
- __name(getLogPrefix, "getLogPrefix");
576
213
  function formatObject(prefix, arg, enableColor = true) {
577
214
  const json = JSON.stringify(arg, null, 2);
578
215
  let colStart = "";
@@ -586,7 +223,6 @@ function formatObject(prefix, arg, enableColor = true) {
586
223
  const prefixedJson = json.split("\n").map((line, idx) => idx === 0 ? `${colStart}${line}` : `${prefix} ${colLine}${line}`).join("\n") + colReset;
587
224
  return prefixedJson;
588
225
  }
589
- __name(formatObject, "formatObject");
590
226
  function formattedArgs(prefix, args, color) {
591
227
  let colReset = Logger.colors.initial;
592
228
  if (color === void 0) {
@@ -602,17 +238,14 @@ function formattedArgs(prefix, args, color) {
602
238
  return arg;
603
239
  });
604
240
  }
605
- __name(formattedArgs, "formattedArgs");
606
241
  function getCallee() {
607
242
  const stack = new Error().stack?.split("\n") ?? [];
608
243
  const caller = stack[3]?.trim().match(/at (.+?)(?:\..+)? .+$/)?.[1]?.replace("Object", "").replace(/^_/, "") || "App";
609
244
  return caller;
610
245
  }
611
- __name(getCallee, "getCallee");
612
246
  function canLog(level) {
613
247
  return logLevels.has(level);
614
248
  }
615
- __name(canLog, "canLog");
616
249
  function processLogQueue(filepath) {
617
250
  const state = fileStates.get(filepath);
618
251
  if (!state || state.isWriting || state.queue.length === 0) {
@@ -622,17 +255,13 @@ function processLogQueue(filepath) {
622
255
  const messagesToWrite = state.queue.join("\n") + "\n";
623
256
  state.queue = [];
624
257
  const dir = path.dirname(filepath);
625
- fs.mkdir(dir, {
626
- recursive: true
627
- }, (err) => {
258
+ fs.mkdir(dir, { recursive: true }, (err) => {
628
259
  if (err) {
629
260
  console.error(`[Logger] Failed to create directory ${dir}`, err);
630
261
  state.isWriting = false;
631
262
  return;
632
263
  }
633
- fs.appendFile(filepath, messagesToWrite, {
634
- encoding: "utf-8"
635
- }, (err2) => {
264
+ fs.appendFile(filepath, messagesToWrite, { encoding: "utf-8" }, (err2) => {
636
265
  state.isWriting = false;
637
266
  if (err2) {
638
267
  console.error(`[Logger] Failed to write log to ${filepath}`, err2);
@@ -643,19 +272,14 @@ function processLogQueue(filepath) {
643
272
  });
644
273
  });
645
274
  }
646
- __name(processLogQueue, "processLogQueue");
647
275
  function enqueue(filepath, message) {
648
276
  if (!fileStates.has(filepath)) {
649
- fileStates.set(filepath, {
650
- queue: [],
651
- isWriting: false
652
- });
277
+ fileStates.set(filepath, { queue: [], isWriting: false });
653
278
  }
654
279
  const state = fileStates.get(filepath);
655
280
  state.queue.push(message);
656
281
  processLogQueue(filepath);
657
282
  }
658
- __name(enqueue, "enqueue");
659
283
  function output(level, args) {
660
284
  if (!canLog(level)) {
661
285
  return;
@@ -676,363 +300,550 @@ function output(level, args) {
676
300
  }
677
301
  }
678
302
  }
679
- __name(output, "output");
680
- (function(Logger2) {
681
- function setLogLevel(level) {
682
- logLevels.clear();
683
- if (Array.isArray(level)) {
684
- for (const lvl of level) {
685
- logLevels.add(lvl);
686
- }
687
- } else {
688
- const targetRank = logLevelRank[level];
689
- for (const [lvl, rank] of Object.entries(logLevelRank)) {
690
- if (rank >= targetRank) {
691
- logLevels.add(lvl);
303
+ var fs, path, Logger, fileSettings, fileStates, logLevels, logLevelRank, logLevelColors, logLevelChannel;
304
+ var init_logger = __esm({
305
+ "src/utils/logger.ts"() {
306
+ "use strict";
307
+ fs = __toESM(require("fs"));
308
+ path = __toESM(require("path"));
309
+ __name(getPrettyTimestamp, "getPrettyTimestamp");
310
+ __name(getLogPrefix, "getLogPrefix");
311
+ __name(formatObject, "formatObject");
312
+ __name(formattedArgs, "formattedArgs");
313
+ __name(getCallee, "getCallee");
314
+ __name(canLog, "canLog");
315
+ __name(processLogQueue, "processLogQueue");
316
+ __name(enqueue, "enqueue");
317
+ __name(output, "output");
318
+ ((Logger2) => {
319
+ function setLogLevel(level) {
320
+ logLevels.clear();
321
+ if (Array.isArray(level)) {
322
+ for (const lvl of level) {
323
+ logLevels.add(lvl);
324
+ }
325
+ } else {
326
+ const targetRank = logLevelRank[level];
327
+ for (const [lvl, rank] of Object.entries(logLevelRank)) {
328
+ if (rank >= targetRank) {
329
+ logLevels.add(lvl);
330
+ }
331
+ }
692
332
  }
693
333
  }
694
- }
695
- }
696
- __name(setLogLevel, "setLogLevel");
697
- Logger2.setLogLevel = setLogLevel;
698
- function log(...args) {
699
- output("log", args);
700
- }
701
- __name(log, "log");
702
- Logger2.log = log;
703
- function info(...args) {
704
- output("info", args);
705
- }
706
- __name(info, "info");
707
- Logger2.info = info;
708
- function warn(...args) {
709
- output("warn", args);
710
- }
711
- __name(warn, "warn");
712
- Logger2.warn = warn;
713
- function error(...args) {
714
- output("error", args);
715
- }
716
- __name(error, "error");
717
- Logger2.error = error;
718
- function errorStack(...args) {
719
- output("error", args);
720
- }
721
- __name(errorStack, "errorStack");
722
- Logger2.errorStack = errorStack;
723
- function debug(...args) {
724
- output("debug", args);
725
- }
726
- __name(debug, "debug");
727
- Logger2.debug = debug;
728
- function comment(...args) {
729
- output("comment", args);
730
- }
731
- __name(comment, "comment");
732
- Logger2.comment = comment;
733
- function critical(...args) {
734
- output("critical", args);
735
- }
736
- __name(critical, "critical");
737
- Logger2.critical = critical;
738
- function enableFileLogging(filepath, levels = [
739
- "debug",
740
- "comment",
741
- "log",
742
- "info",
743
- "warn",
744
- "error",
745
- "critical"
746
- ]) {
747
- for (const level of levels) {
748
- fileSettings.set(level, {
749
- filepath
750
- });
751
- }
752
- }
753
- __name(enableFileLogging, "enableFileLogging");
754
- Logger2.enableFileLogging = enableFileLogging;
755
- function disableFileLogging(levels = [
756
- "debug",
757
- "comment",
758
- "log",
759
- "info",
760
- "warn",
761
- "error",
762
- "critical"
763
- ]) {
764
- for (const level of levels) {
765
- fileSettings.delete(level);
766
- }
334
+ Logger2.setLogLevel = setLogLevel;
335
+ __name(setLogLevel, "setLogLevel");
336
+ function log(...args) {
337
+ output("log", args);
338
+ }
339
+ Logger2.log = log;
340
+ __name(log, "log");
341
+ function info(...args) {
342
+ output("info", args);
343
+ }
344
+ Logger2.info = info;
345
+ __name(info, "info");
346
+ function warn(...args) {
347
+ output("warn", args);
348
+ }
349
+ Logger2.warn = warn;
350
+ __name(warn, "warn");
351
+ function error(...args) {
352
+ output("error", args);
353
+ }
354
+ Logger2.error = error;
355
+ __name(error, "error");
356
+ function errorStack(...args) {
357
+ output("error", args);
358
+ }
359
+ Logger2.errorStack = errorStack;
360
+ __name(errorStack, "errorStack");
361
+ function debug(...args) {
362
+ output("debug", args);
363
+ }
364
+ Logger2.debug = debug;
365
+ __name(debug, "debug");
366
+ function comment(...args) {
367
+ output("comment", args);
368
+ }
369
+ Logger2.comment = comment;
370
+ __name(comment, "comment");
371
+ function critical(...args) {
372
+ output("critical", args);
373
+ }
374
+ Logger2.critical = critical;
375
+ __name(critical, "critical");
376
+ function enableFileLogging(filepath, levels = ["debug", "comment", "log", "info", "warn", "error", "critical"]) {
377
+ for (const level of levels) {
378
+ fileSettings.set(level, { filepath });
379
+ }
380
+ }
381
+ Logger2.enableFileLogging = enableFileLogging;
382
+ __name(enableFileLogging, "enableFileLogging");
383
+ function disableFileLogging(levels = ["debug", "comment", "log", "info", "warn", "error", "critical"]) {
384
+ for (const level of levels) {
385
+ fileSettings.delete(level);
386
+ }
387
+ }
388
+ Logger2.disableFileLogging = disableFileLogging;
389
+ __name(disableFileLogging, "disableFileLogging");
390
+ Logger2.colors = {
391
+ black: "\x1B[0;30m",
392
+ grey: "\x1B[0;37m",
393
+ red: "\x1B[0;31m",
394
+ green: "\x1B[0;32m",
395
+ brown: "\x1B[0;33m",
396
+ blue: "\x1B[0;34m",
397
+ purple: "\x1B[0;35m",
398
+ darkGrey: "\x1B[1;30m",
399
+ lightRed: "\x1B[1;31m",
400
+ lightGreen: "\x1B[1;32m",
401
+ yellow: "\x1B[1;33m",
402
+ lightBlue: "\x1B[1;34m",
403
+ magenta: "\x1B[1;35m",
404
+ cyan: "\x1B[1;36m",
405
+ white: "\x1B[1;37m",
406
+ initial: "\x1B[0m"
407
+ };
408
+ })(Logger || (Logger = {}));
409
+ fileSettings = /* @__PURE__ */ new Map();
410
+ fileStates = /* @__PURE__ */ new Map();
411
+ logLevels = /* @__PURE__ */ new Set();
412
+ logLevelRank = {
413
+ debug: 0,
414
+ comment: 1,
415
+ log: 2,
416
+ info: 3,
417
+ warn: 4,
418
+ error: 5,
419
+ critical: 6
420
+ };
421
+ logLevelColors = {
422
+ debug: Logger.colors.purple,
423
+ comment: Logger.colors.grey,
424
+ log: Logger.colors.green,
425
+ info: Logger.colors.blue,
426
+ warn: Logger.colors.brown,
427
+ error: Logger.colors.red,
428
+ critical: Logger.colors.lightRed
429
+ };
430
+ logLevelChannel = {
431
+ debug: console.debug,
432
+ comment: console.debug,
433
+ log: console.log,
434
+ info: console.info,
435
+ warn: console.warn,
436
+ error: console.error,
437
+ critical: console.error
438
+ };
439
+ Logger.setLogLevel("debug");
767
440
  }
768
- __name(disableFileLogging, "disableFileLogging");
769
- Logger2.disableFileLogging = disableFileLogging;
770
- Logger2.colors = {
771
- black: "\x1B[0;30m",
772
- grey: "\x1B[0;37m",
773
- red: "\x1B[0;31m",
774
- green: "\x1B[0;32m",
775
- brown: "\x1B[0;33m",
776
- blue: "\x1B[0;34m",
777
- purple: "\x1B[0;35m",
778
- darkGrey: "\x1B[1;30m",
779
- lightRed: "\x1B[1;31m",
780
- lightGreen: "\x1B[1;32m",
781
- yellow: "\x1B[1;33m",
782
- lightBlue: "\x1B[1;34m",
783
- magenta: "\x1B[1;35m",
784
- cyan: "\x1B[1;36m",
785
- white: "\x1B[1;37m",
786
- initial: "\x1B[0m"
787
- };
788
- })(Logger || (Logger = {}));
789
- var fileSettings = /* @__PURE__ */ new Map();
790
- var fileStates = /* @__PURE__ */ new Map();
791
- var logLevels = /* @__PURE__ */ new Set();
792
- var logLevelRank = {
793
- debug: 0,
794
- comment: 1,
795
- log: 2,
796
- info: 3,
797
- warn: 4,
798
- error: 5,
799
- critical: 6
800
- };
801
- var logLevelColors = {
802
- debug: Logger.colors.purple,
803
- comment: Logger.colors.grey,
804
- log: Logger.colors.green,
805
- info: Logger.colors.blue,
806
- warn: Logger.colors.brown,
807
- error: Logger.colors.red,
808
- critical: Logger.colors.lightRed
809
- };
810
- var logLevelChannel = {
811
- debug: console.debug,
812
- comment: console.debug,
813
- log: console.log,
814
- info: console.info,
815
- warn: console.warn,
816
- error: console.error,
817
- critical: console.error
818
- };
819
- Logger.setLogLevel("debug");
820
- var Logger;
441
+ });
821
442
 
822
443
  // src/DI/injector-explorer.ts
823
- var _InjectorExplorer = class _InjectorExplorer {
824
- /**
825
- * Enqueues a class for deferred registration.
826
- * Called by the @Injectable decorator at import time.
827
- *
828
- * If {@link processPending} has already been called (i.e. after bootstrap)
829
- * and accumulation mode is not active, the class is registered immediately
830
- * so that late dynamic imports (e.g. middlewares loaded after bootstrap)
831
- * work correctly.
832
- *
833
- * When accumulation mode is active (between {@link beginAccumulate} and
834
- * {@link flushAccumulated}), classes are queued instead — preserving the
835
- * two-phase binding/resolution guarantee for lazy-loaded modules.
836
- */
837
- static enqueue(target, lifetime) {
838
- if (_InjectorExplorer.processed && !_InjectorExplorer.accumulating) {
839
- _InjectorExplorer.registerImmediate(target, lifetime);
840
- return;
841
- }
842
- _InjectorExplorer.pending.push({
843
- target,
844
- lifetime
845
- });
846
- }
847
- /**
848
- * Enters accumulation mode. While active, all decorated classes discovered
849
- * via dynamic imports are queued in {@link pending} rather than registered
850
- * immediately. Call {@link flushAccumulated} to process them with the
851
- * full two-phase (bind-then-resolve) guarantee.
852
- */
853
- static beginAccumulate() {
854
- _InjectorExplorer.accumulating = true;
855
- }
856
- /**
857
- * Exits accumulation mode and processes every class queued since
858
- * {@link beginAccumulate} was called. Uses the same two-phase strategy
859
- * as {@link processPending} (register all bindings first, then resolve
860
- * singletons / controllers) so import ordering within a lazy batch
861
- * does not cause resolution failures.
862
- */
863
- static flushAccumulated() {
864
- _InjectorExplorer.accumulating = false;
865
- const queue = [
866
- ..._InjectorExplorer.pending
867
- ];
868
- _InjectorExplorer.pending.length = 0;
869
- for (const { target, lifetime } of queue) {
870
- if (!RootInjector.bindings.has(target)) {
871
- RootInjector.bindings.set(target, {
872
- implementation: target,
873
- lifetime
874
- });
444
+ var _InjectorExplorer, InjectorExplorer;
445
+ var init_injector_explorer = __esm({
446
+ "src/DI/injector-explorer.ts"() {
447
+ "use strict";
448
+ init_app_injector();
449
+ init_logger();
450
+ _InjectorExplorer = class _InjectorExplorer {
451
+ // -------------------------------------------------------------------------
452
+ // Public API
453
+ // -------------------------------------------------------------------------
454
+ static enqueue(reg) {
455
+ if (_InjectorExplorer.processed && !_InjectorExplorer.accumulating) {
456
+ _InjectorExplorer._registerImmediate(reg);
457
+ return;
458
+ }
459
+ _InjectorExplorer.pending.push(reg);
875
460
  }
876
- }
877
- for (const { target, lifetime } of queue) {
878
- _InjectorExplorer.processRegistration(target, lifetime);
879
- }
880
- }
881
- /**
882
- * Processes all pending registrations in two phases:
883
- * 1. Register all bindings (no instantiation) so every dependency is known.
884
- * 2. Resolve singletons, register controllers and log module readiness.
885
- *
886
- * This two-phase approach makes the system resilient to import ordering:
887
- * all bindings exist before any singleton is instantiated.
888
- */
889
- static processPending() {
890
- const queue = _InjectorExplorer.pending;
891
- for (const { target, lifetime } of queue) {
892
- if (!RootInjector.bindings.has(target)) {
893
- RootInjector.bindings.set(target, {
894
- implementation: target,
895
- lifetime
896
- });
461
+ /**
462
+ * Two-phase flush of all pending registrations collected at startup.
463
+ * Called by bootstrapApplication after app.whenReady().
464
+ */
465
+ static processPending(singletonOverrides) {
466
+ const queue = [..._InjectorExplorer.pending];
467
+ _InjectorExplorer.pending.length = 0;
468
+ _InjectorExplorer._phaseOne(queue);
469
+ _InjectorExplorer._phaseTwo(queue, singletonOverrides);
470
+ _InjectorExplorer.processed = true;
897
471
  }
898
- }
899
- for (const { target, lifetime } of queue) {
900
- _InjectorExplorer.processRegistration(target, lifetime);
901
- }
902
- queue.length = 0;
903
- _InjectorExplorer.processed = true;
472
+ /** Enters accumulation mode for lazy-loaded batches. */
473
+ static beginAccumulate() {
474
+ _InjectorExplorer.accumulating = true;
475
+ }
476
+ /**
477
+ * Exits accumulation mode and flushes queued registrations
478
+ * with the same two-phase guarantee as processPending.
479
+ */
480
+ static flushAccumulated(routeGuards = [], routeMiddlewares = [], pathPrefix = "") {
481
+ _InjectorExplorer.accumulating = false;
482
+ const queue = [..._InjectorExplorer.pending];
483
+ _InjectorExplorer.pending.length = 0;
484
+ _InjectorExplorer._phaseOne(queue);
485
+ for (const reg of queue) {
486
+ if (reg.isController) reg.pathPrefix = pathPrefix;
487
+ }
488
+ _InjectorExplorer._phaseTwo(queue, void 0, routeGuards, routeMiddlewares);
489
+ }
490
+ // -------------------------------------------------------------------------
491
+ // Private helpers
492
+ // -------------------------------------------------------------------------
493
+ /** Phase 1: register all bindings without instantiating anything. */
494
+ static _phaseOne(queue) {
495
+ for (const reg of queue) {
496
+ RootInjector.register(reg.key, reg.implementation, reg.lifetime, reg.deps);
497
+ }
498
+ }
499
+ /** Phase 2: resolve singletons and register controllers in the router. */
500
+ static _phaseTwo(queue, overrides, routeGuards = [], routeMiddlewares = []) {
501
+ for (const reg of queue) {
502
+ if (overrides?.has(reg.key)) {
503
+ const override = overrides.get(reg.key);
504
+ RootInjector.singletons.set(reg.key, override);
505
+ Logger.log(`Registered ${reg.implementation.name} as singleton (overridden)`);
506
+ continue;
507
+ }
508
+ if (reg.lifetime === "singleton") {
509
+ RootInjector.resolve(reg.key);
510
+ }
511
+ if (reg.isController) {
512
+ const { Router: Router2 } = (init_router(), __toCommonJS(router_exports));
513
+ const router = RootInjector.resolve(Router2);
514
+ router.registerController(reg.implementation, reg.pathPrefix ?? "", routeGuards, routeMiddlewares);
515
+ } else if (reg.lifetime !== "singleton") {
516
+ Logger.log(`Registered ${reg.implementation.name} as ${reg.lifetime}`);
517
+ }
518
+ }
519
+ }
520
+ static _registerImmediate(reg) {
521
+ RootInjector.register(reg.key, reg.implementation, reg.lifetime, reg.deps);
522
+ if (reg.lifetime === "singleton") {
523
+ RootInjector.resolve(reg.key);
524
+ }
525
+ if (reg.isController) {
526
+ const { Router: Router2 } = (init_router(), __toCommonJS(router_exports));
527
+ const router = RootInjector.resolve(Router2);
528
+ router.registerController(reg.implementation);
529
+ }
530
+ }
531
+ };
532
+ __name(_InjectorExplorer, "InjectorExplorer");
533
+ _InjectorExplorer.pending = [];
534
+ _InjectorExplorer.processed = false;
535
+ _InjectorExplorer.accumulating = false;
536
+ InjectorExplorer = _InjectorExplorer;
904
537
  }
905
- /**
906
- * Registers a single class immediately (post-bootstrap path).
907
- * Used for classes discovered via late dynamic imports.
908
- */
909
- static registerImmediate(target, lifetime) {
910
- if (RootInjector.bindings.has(target)) {
911
- return;
912
- }
913
- RootInjector.bindings.set(target, {
538
+ });
539
+
540
+ // src/decorators/controller.decorator.ts
541
+ function Controller(options = {}) {
542
+ return (target) => {
543
+ const meta = {
544
+ deps: options.deps ?? []
545
+ };
546
+ controllerMetaMap.set(target, meta);
547
+ InjectorExplorer.enqueue({
548
+ key: target,
914
549
  implementation: target,
915
- lifetime
550
+ lifetime: "scope",
551
+ deps: options.deps ?? [],
552
+ isController: true
916
553
  });
917
- _InjectorExplorer.processRegistration(target, lifetime);
918
- }
919
- /**
920
- * Performs phase-2 work for a single registration: resolve singletons,
921
- * register controllers, and log module readiness.
922
- */
923
- static processRegistration(target, lifetime) {
924
- if (lifetime === "singleton") {
925
- RootInjector.resolve(target);
926
- }
927
- if (getModuleMetadata(target)) {
928
- Logger.log(`${target.name} dependencies initialized`);
929
- return;
930
- }
931
- const controllerMeta = getControllerMetadata(target);
932
- if (controllerMeta) {
933
- const router = RootInjector.resolve(Router);
934
- router?.registerController(target);
935
- return;
936
- }
937
- if (getRouteMetadata(target).length > 0) {
938
- return;
939
- }
940
- if (getInjectableMetadata(target)) {
941
- Logger.log(`Registered ${target.name} as ${lifetime}`);
942
- }
554
+ };
555
+ }
556
+ function getControllerMetadata(target) {
557
+ return controllerMetaMap.get(target);
558
+ }
559
+ var controllerMetaMap;
560
+ var init_controller_decorator = __esm({
561
+ "src/decorators/controller.decorator.ts"() {
562
+ "use strict";
563
+ init_injector_explorer();
564
+ controllerMetaMap = /* @__PURE__ */ new WeakMap();
565
+ __name(Controller, "Controller");
566
+ __name(getControllerMetadata, "getControllerMetadata");
943
567
  }
944
- };
945
- __name(_InjectorExplorer, "InjectorExplorer");
946
- __publicField(_InjectorExplorer, "pending", []);
947
- __publicField(_InjectorExplorer, "processed", false);
948
- __publicField(_InjectorExplorer, "accumulating", false);
949
- var InjectorExplorer = _InjectorExplorer;
568
+ });
950
569
 
951
570
  // src/decorators/injectable.decorator.ts
952
- function Injectable(lifetime = "scope") {
571
+ function Injectable(options = {}) {
572
+ const { lifetime = "scope", deps = [] } = options;
953
573
  return (target) => {
954
574
  if (typeof target !== "function" || !target.prototype) {
955
- throw new Error(`@Injectable can only be used on classes, not on ${typeof target}`);
575
+ throw new Error(`@Injectable can only be applied to classes, not ${typeof target}`);
956
576
  }
957
- defineInjectableMetadata(target, lifetime);
958
- InjectorExplorer.enqueue(target, lifetime);
577
+ const key = target;
578
+ InjectorExplorer.enqueue({
579
+ key,
580
+ implementation: key,
581
+ lifetime,
582
+ deps,
583
+ isController: false
584
+ });
959
585
  };
960
586
  }
961
- __name(Injectable, "Injectable");
587
+ var init_injectable_decorator = __esm({
588
+ "src/decorators/injectable.decorator.ts"() {
589
+ "use strict";
590
+ init_injector_explorer();
591
+ init_token();
592
+ __name(Injectable, "Injectable");
593
+ }
594
+ });
962
595
 
963
- // src/decorators/controller.decorator.ts
964
- function Controller(path2) {
965
- return (target) => {
966
- const data = {
967
- path: path2,
968
- guards: getGuardForController(target.name)
596
+ // src/decorators/method.decorator.ts
597
+ function isAtomicHttpMethod(m) {
598
+ return typeof m === "string" && ATOMIC_METHODS.has(m);
599
+ }
600
+ function createRouteDecorator(verb) {
601
+ return (path2, options = {}) => {
602
+ return (target, propertyKey) => {
603
+ const ctor = target.constructor;
604
+ const existing = routeMetaMap.get(ctor) ?? [];
605
+ existing.push({
606
+ method: verb,
607
+ path: (path2 ?? "").trim().replace(/^\/|\/$/g, ""),
608
+ handler: propertyKey,
609
+ guards: options.guards ?? [],
610
+ middlewares: options.middlewares ?? []
611
+ });
612
+ routeMetaMap.set(ctor, existing);
969
613
  };
970
- Reflect.defineMetadata(CONTROLLER_METADATA_KEY, data, target);
971
- Injectable("scope")(target);
972
614
  };
973
615
  }
974
- __name(Controller, "Controller");
975
- function getControllerMetadata(target) {
976
- return Reflect.getMetadata(CONTROLLER_METADATA_KEY, target);
616
+ function getRouteMetadata(target) {
617
+ return routeMetaMap.get(target) ?? [];
977
618
  }
978
- __name(getControllerMetadata, "getControllerMetadata");
979
- var CONTROLLER_METADATA_KEY = Symbol("CONTROLLER_METADATA_KEY");
619
+ var ATOMIC_METHODS, routeMetaMap, Get, Post, Put, Patch, Delete;
620
+ var init_method_decorator = __esm({
621
+ "src/decorators/method.decorator.ts"() {
622
+ "use strict";
623
+ ATOMIC_METHODS = /* @__PURE__ */ new Set(["GET", "POST", "PUT", "PATCH", "DELETE"]);
624
+ __name(isAtomicHttpMethod, "isAtomicHttpMethod");
625
+ routeMetaMap = /* @__PURE__ */ new WeakMap();
626
+ __name(createRouteDecorator, "createRouteDecorator");
627
+ __name(getRouteMetadata, "getRouteMetadata");
628
+ Get = createRouteDecorator("GET");
629
+ Post = createRouteDecorator("POST");
630
+ Put = createRouteDecorator("PUT");
631
+ Patch = createRouteDecorator("PATCH");
632
+ Delete = createRouteDecorator("DELETE");
633
+ }
634
+ });
980
635
 
981
- // src/decorators/middleware.decorator.ts
982
- function UseMiddlewares(mdlw) {
983
- return (target, propertyKey) => {
984
- let key;
985
- if (propertyKey) {
986
- const ctrlName = target.constructor.name;
987
- const actionName = propertyKey;
988
- key = `${ctrlName}.${actionName}`;
989
- } else {
990
- const ctrlName = target.name;
991
- key = `${ctrlName}`;
992
- }
993
- if (middlewares.has(key)) {
994
- throw new Error(`Middlewares(s) already registered for ${key}`);
995
- }
996
- middlewares.set(key, mdlw);
997
- };
998
- }
999
- __name(UseMiddlewares, "UseMiddlewares");
1000
- function getMiddlewaresForController(controllerName) {
1001
- const key = `${controllerName}`;
1002
- return middlewares.get(key) ?? [];
1003
- }
1004
- __name(getMiddlewaresForController, "getMiddlewaresForController");
1005
- function getMiddlewaresForControllerAction(controllerName, actionName) {
1006
- const key = `${controllerName}.${actionName}`;
1007
- return middlewares.get(key) ?? [];
1008
- }
1009
- __name(getMiddlewaresForControllerAction, "getMiddlewaresForControllerAction");
1010
- var middlewares = /* @__PURE__ */ new Map();
636
+ // src/exceptions.ts
637
+ var _ResponseException, ResponseException, _BadRequestException, BadRequestException, _UnauthorizedException, UnauthorizedException, _PaymentRequiredException, PaymentRequiredException, _ForbiddenException, ForbiddenException, _NotFoundException, NotFoundException, _MethodNotAllowedException, MethodNotAllowedException, _NotAcceptableException, NotAcceptableException, _RequestTimeoutException, RequestTimeoutException, _ConflictException, ConflictException, _UpgradeRequiredException, UpgradeRequiredException, _TooManyRequestsException, TooManyRequestsException, _InternalServerException, InternalServerException, _NotImplementedException, NotImplementedException, _BadGatewayException, BadGatewayException, _ServiceUnavailableException, ServiceUnavailableException, _GatewayTimeoutException, GatewayTimeoutException, _HttpVersionNotSupportedException, HttpVersionNotSupportedException, _VariantAlsoNegotiatesException, VariantAlsoNegotiatesException, _InsufficientStorageException, InsufficientStorageException, _LoopDetectedException, LoopDetectedException, _NotExtendedException, NotExtendedException, _NetworkAuthenticationRequiredException, NetworkAuthenticationRequiredException, _NetworkConnectTimeoutException, NetworkConnectTimeoutException;
638
+ var init_exceptions = __esm({
639
+ "src/exceptions.ts"() {
640
+ "use strict";
641
+ _ResponseException = class _ResponseException extends Error {
642
+ constructor(statusOrMessage, message) {
643
+ let statusCode;
644
+ if (typeof statusOrMessage === "number") {
645
+ statusCode = statusOrMessage;
646
+ } else if (typeof statusOrMessage === "string") {
647
+ message = statusOrMessage;
648
+ }
649
+ super(message ?? "");
650
+ this.status = 0;
651
+ if (statusCode !== void 0) {
652
+ this.status = statusCode;
653
+ }
654
+ this.name = this.constructor.name.replace(/([A-Z])/g, " $1");
655
+ }
656
+ };
657
+ __name(_ResponseException, "ResponseException");
658
+ ResponseException = _ResponseException;
659
+ _BadRequestException = class _BadRequestException extends ResponseException {
660
+ constructor() {
661
+ super(...arguments);
662
+ this.status = 400;
663
+ }
664
+ };
665
+ __name(_BadRequestException, "BadRequestException");
666
+ BadRequestException = _BadRequestException;
667
+ _UnauthorizedException = class _UnauthorizedException extends ResponseException {
668
+ constructor() {
669
+ super(...arguments);
670
+ this.status = 401;
671
+ }
672
+ };
673
+ __name(_UnauthorizedException, "UnauthorizedException");
674
+ UnauthorizedException = _UnauthorizedException;
675
+ _PaymentRequiredException = class _PaymentRequiredException extends ResponseException {
676
+ constructor() {
677
+ super(...arguments);
678
+ this.status = 402;
679
+ }
680
+ };
681
+ __name(_PaymentRequiredException, "PaymentRequiredException");
682
+ PaymentRequiredException = _PaymentRequiredException;
683
+ _ForbiddenException = class _ForbiddenException extends ResponseException {
684
+ constructor() {
685
+ super(...arguments);
686
+ this.status = 403;
687
+ }
688
+ };
689
+ __name(_ForbiddenException, "ForbiddenException");
690
+ ForbiddenException = _ForbiddenException;
691
+ _NotFoundException = class _NotFoundException extends ResponseException {
692
+ constructor() {
693
+ super(...arguments);
694
+ this.status = 404;
695
+ }
696
+ };
697
+ __name(_NotFoundException, "NotFoundException");
698
+ NotFoundException = _NotFoundException;
699
+ _MethodNotAllowedException = class _MethodNotAllowedException extends ResponseException {
700
+ constructor() {
701
+ super(...arguments);
702
+ this.status = 405;
703
+ }
704
+ };
705
+ __name(_MethodNotAllowedException, "MethodNotAllowedException");
706
+ MethodNotAllowedException = _MethodNotAllowedException;
707
+ _NotAcceptableException = class _NotAcceptableException extends ResponseException {
708
+ constructor() {
709
+ super(...arguments);
710
+ this.status = 406;
711
+ }
712
+ };
713
+ __name(_NotAcceptableException, "NotAcceptableException");
714
+ NotAcceptableException = _NotAcceptableException;
715
+ _RequestTimeoutException = class _RequestTimeoutException extends ResponseException {
716
+ constructor() {
717
+ super(...arguments);
718
+ this.status = 408;
719
+ }
720
+ };
721
+ __name(_RequestTimeoutException, "RequestTimeoutException");
722
+ RequestTimeoutException = _RequestTimeoutException;
723
+ _ConflictException = class _ConflictException extends ResponseException {
724
+ constructor() {
725
+ super(...arguments);
726
+ this.status = 409;
727
+ }
728
+ };
729
+ __name(_ConflictException, "ConflictException");
730
+ ConflictException = _ConflictException;
731
+ _UpgradeRequiredException = class _UpgradeRequiredException extends ResponseException {
732
+ constructor() {
733
+ super(...arguments);
734
+ this.status = 426;
735
+ }
736
+ };
737
+ __name(_UpgradeRequiredException, "UpgradeRequiredException");
738
+ UpgradeRequiredException = _UpgradeRequiredException;
739
+ _TooManyRequestsException = class _TooManyRequestsException extends ResponseException {
740
+ constructor() {
741
+ super(...arguments);
742
+ this.status = 429;
743
+ }
744
+ };
745
+ __name(_TooManyRequestsException, "TooManyRequestsException");
746
+ TooManyRequestsException = _TooManyRequestsException;
747
+ _InternalServerException = class _InternalServerException extends ResponseException {
748
+ constructor() {
749
+ super(...arguments);
750
+ this.status = 500;
751
+ }
752
+ };
753
+ __name(_InternalServerException, "InternalServerException");
754
+ InternalServerException = _InternalServerException;
755
+ _NotImplementedException = class _NotImplementedException extends ResponseException {
756
+ constructor() {
757
+ super(...arguments);
758
+ this.status = 501;
759
+ }
760
+ };
761
+ __name(_NotImplementedException, "NotImplementedException");
762
+ NotImplementedException = _NotImplementedException;
763
+ _BadGatewayException = class _BadGatewayException extends ResponseException {
764
+ constructor() {
765
+ super(...arguments);
766
+ this.status = 502;
767
+ }
768
+ };
769
+ __name(_BadGatewayException, "BadGatewayException");
770
+ BadGatewayException = _BadGatewayException;
771
+ _ServiceUnavailableException = class _ServiceUnavailableException extends ResponseException {
772
+ constructor() {
773
+ super(...arguments);
774
+ this.status = 503;
775
+ }
776
+ };
777
+ __name(_ServiceUnavailableException, "ServiceUnavailableException");
778
+ ServiceUnavailableException = _ServiceUnavailableException;
779
+ _GatewayTimeoutException = class _GatewayTimeoutException extends ResponseException {
780
+ constructor() {
781
+ super(...arguments);
782
+ this.status = 504;
783
+ }
784
+ };
785
+ __name(_GatewayTimeoutException, "GatewayTimeoutException");
786
+ GatewayTimeoutException = _GatewayTimeoutException;
787
+ _HttpVersionNotSupportedException = class _HttpVersionNotSupportedException extends ResponseException {
788
+ constructor() {
789
+ super(...arguments);
790
+ this.status = 505;
791
+ }
792
+ };
793
+ __name(_HttpVersionNotSupportedException, "HttpVersionNotSupportedException");
794
+ HttpVersionNotSupportedException = _HttpVersionNotSupportedException;
795
+ _VariantAlsoNegotiatesException = class _VariantAlsoNegotiatesException extends ResponseException {
796
+ constructor() {
797
+ super(...arguments);
798
+ this.status = 506;
799
+ }
800
+ };
801
+ __name(_VariantAlsoNegotiatesException, "VariantAlsoNegotiatesException");
802
+ VariantAlsoNegotiatesException = _VariantAlsoNegotiatesException;
803
+ _InsufficientStorageException = class _InsufficientStorageException extends ResponseException {
804
+ constructor() {
805
+ super(...arguments);
806
+ this.status = 507;
807
+ }
808
+ };
809
+ __name(_InsufficientStorageException, "InsufficientStorageException");
810
+ InsufficientStorageException = _InsufficientStorageException;
811
+ _LoopDetectedException = class _LoopDetectedException extends ResponseException {
812
+ constructor() {
813
+ super(...arguments);
814
+ this.status = 508;
815
+ }
816
+ };
817
+ __name(_LoopDetectedException, "LoopDetectedException");
818
+ LoopDetectedException = _LoopDetectedException;
819
+ _NotExtendedException = class _NotExtendedException extends ResponseException {
820
+ constructor() {
821
+ super(...arguments);
822
+ this.status = 510;
823
+ }
824
+ };
825
+ __name(_NotExtendedException, "NotExtendedException");
826
+ NotExtendedException = _NotExtendedException;
827
+ _NetworkAuthenticationRequiredException = class _NetworkAuthenticationRequiredException extends ResponseException {
828
+ constructor() {
829
+ super(...arguments);
830
+ this.status = 511;
831
+ }
832
+ };
833
+ __name(_NetworkAuthenticationRequiredException, "NetworkAuthenticationRequiredException");
834
+ NetworkAuthenticationRequiredException = _NetworkAuthenticationRequiredException;
835
+ _NetworkConnectTimeoutException = class _NetworkConnectTimeoutException extends ResponseException {
836
+ constructor() {
837
+ super(...arguments);
838
+ this.status = 599;
839
+ }
840
+ };
841
+ __name(_NetworkConnectTimeoutException, "NetworkConnectTimeoutException");
842
+ NetworkConnectTimeoutException = _NetworkConnectTimeoutException;
843
+ }
844
+ });
1011
845
 
1012
846
  // src/request.ts
1013
- var import_reflect_metadata3 = require("reflect-metadata");
1014
- var _Request = class _Request {
1015
- constructor(event, senderId, id, method, path2, body) {
1016
- __publicField(this, "event");
1017
- __publicField(this, "senderId");
1018
- __publicField(this, "id");
1019
- __publicField(this, "method");
1020
- __publicField(this, "path");
1021
- __publicField(this, "body");
1022
- __publicField(this, "context", RootInjector.createScope());
1023
- __publicField(this, "params", {});
1024
- this.event = event;
1025
- this.senderId = senderId;
1026
- this.id = id;
1027
- this.method = method;
1028
- this.path = path2;
1029
- this.body = body;
1030
- this.path = path2.replace(/^\/|\/$/g, "");
1031
- }
1032
- };
1033
- __name(_Request, "Request");
1034
- var Request = _Request;
1035
- var RENDERER_EVENT_TYPE = "noxus:event";
1036
847
  function createRendererEventMessage(event, payload) {
1037
848
  return {
1038
849
  type: RENDERER_EVENT_TYPE,
@@ -1040,7 +851,6 @@ function createRendererEventMessage(event, payload) {
1040
851
  payload
1041
852
  };
1042
853
  }
1043
- __name(createRendererEventMessage, "createRendererEventMessage");
1044
854
  function isRendererEventMessage(value) {
1045
855
  if (value === null || typeof value !== "object") {
1046
856
  return false;
@@ -1048,637 +858,528 @@ function isRendererEventMessage(value) {
1048
858
  const possibleMessage = value;
1049
859
  return possibleMessage.type === RENDERER_EVENT_TYPE && typeof possibleMessage.event === "string";
1050
860
  }
1051
- __name(isRendererEventMessage, "isRendererEventMessage");
861
+ var _Request, Request, RENDERER_EVENT_TYPE;
862
+ var init_request = __esm({
863
+ "src/request.ts"() {
864
+ "use strict";
865
+ init_app_injector();
866
+ _Request = class _Request {
867
+ constructor(event, senderId, id, method, path2, body) {
868
+ this.event = event;
869
+ this.senderId = senderId;
870
+ this.id = id;
871
+ this.method = method;
872
+ this.path = path2;
873
+ this.body = body;
874
+ this.context = RootInjector.createScope();
875
+ this.params = {};
876
+ this.path = path2.replace(/^\/|\/$/g, "");
877
+ }
878
+ };
879
+ __name(_Request, "Request");
880
+ Request = _Request;
881
+ RENDERER_EVENT_TYPE = "noxus:event";
882
+ __name(createRendererEventMessage, "createRendererEventMessage");
883
+ __name(isRendererEventMessage, "isRendererEventMessage");
884
+ }
885
+ });
1052
886
 
1053
887
  // src/utils/radix-tree.ts
1054
- var _a;
1055
- var RadixNode = (_a = class {
1056
- /**
1057
- * Creates a new RadixNode.
1058
- * @param segment - The segment of the path this node represents.
1059
- */
1060
- constructor(segment) {
1061
- __publicField(this, "segment");
1062
- __publicField(this, "children", []);
1063
- __publicField(this, "value");
1064
- __publicField(this, "isParam");
1065
- __publicField(this, "paramName");
1066
- this.segment = segment;
1067
- this.isParam = segment.startsWith(":");
1068
- if (this.isParam) {
1069
- this.paramName = segment.slice(1);
1070
- }
1071
- }
1072
- /**
1073
- * Matches a child node against a given segment.
1074
- * This method checks if the segment matches any of the children nodes.
1075
- * @param segment - The segment to match against the children of this node.
1076
- * @returns A child node that matches the segment, or undefined if no match is found.
1077
- */
1078
- matchChild(segment) {
1079
- for (const child of this.children) {
1080
- if (child.isParam || segment.startsWith(child.segment)) return child;
1081
- }
1082
- return void 0;
1083
- }
1084
- /**
1085
- * Finds a child node that matches the segment exactly.
1086
- * This method checks if there is a child node that matches the segment exactly.
1087
- * @param segment - The segment to find an exact match for among the children of this node.
1088
- * @returns A child node that matches the segment exactly, or undefined if no match is found.
1089
- */
1090
- findExactChild(segment) {
1091
- return this.children.find((c) => c.segment === segment);
1092
- }
1093
- /**
1094
- * Adds a child node to this node's children.
1095
- * This method adds a new child node to the list of children for this node.
1096
- * @param node - The child node to add to this node's children.
1097
- */
1098
- addChild(node) {
1099
- this.children.push(node);
1100
- }
1101
- }, __name(_a, "RadixNode"), _a);
1102
- var _RadixTree = class _RadixTree {
1103
- constructor() {
1104
- __publicField(this, "root", new RadixNode(""));
1105
- }
1106
- /**
1107
- * Inserts a path and its associated value into the Radix Tree.
1108
- * This method normalizes the path and inserts it into the tree, associating it with
1109
- * @param path - The path to insert into the tree.
1110
- * @param value - The value to associate with the path.
1111
- */
1112
- insert(path2, value) {
1113
- const segments = this.normalize(path2);
1114
- this.insertRecursive(this.root, segments, value);
1115
- }
1116
- /**
1117
- * Recursively inserts a path into the Radix Tree.
1118
- * This method traverses the tree and inserts the segments of the path, creating new nodes
1119
- * @param node - The node to start inserting from.
1120
- * @param segments - The segments of the path to insert.
1121
- * @param value - The value to associate with the path.
1122
- */
1123
- insertRecursive(node, segments, value) {
1124
- if (segments.length === 0) {
1125
- node.value = value;
1126
- return;
1127
- }
1128
- const segment = segments[0] ?? "";
1129
- let child = node.children.find((c) => c.isParam === segment.startsWith(":") && (c.isParam || c.segment === segment));
1130
- if (!child) {
1131
- child = new RadixNode(segment);
1132
- node.addChild(child);
1133
- }
1134
- this.insertRecursive(child, segments.slice(1), value);
1135
- }
1136
- /**
1137
- * Searches for a path in the Radix Tree.
1138
- * This method normalizes the path and searches for it in the tree, returning the node
1139
- * @param path - The path to search for in the Radix Tree.
1140
- * @returns An ISearchResult containing the node and parameters if a match is found, otherwise undefined.
1141
- */
1142
- search(path2) {
1143
- const segments = this.normalize(path2);
1144
- return this.searchRecursive(this.root, segments, {});
1145
- }
1146
- /**
1147
- * Recursively searches for a path in the Radix Tree.
1148
- * This method traverses the tree and searches for the segments of the path, collecting parameters
1149
- * @param node - The node to start searching from.
1150
- * @param segments - The segments of the path to search for.
1151
- * @param params - The parameters collected during the search.
1152
- * @returns An ISearchResult containing the node and parameters if a match is found, otherwise undefined.
1153
- */
1154
- searchRecursive(node, segments, params) {
1155
- if (segments.length === 0) {
1156
- if (node.value !== void 0) {
1157
- return {
1158
- node,
1159
- params
1160
- };
888
+ var _RadixNode, RadixNode, _RadixTree, RadixTree;
889
+ var init_radix_tree = __esm({
890
+ "src/utils/radix-tree.ts"() {
891
+ "use strict";
892
+ _RadixNode = class _RadixNode {
893
+ /**
894
+ * Creates a new RadixNode.
895
+ * @param segment - The segment of the path this node represents.
896
+ */
897
+ constructor(segment) {
898
+ this.children = [];
899
+ this.segment = segment;
900
+ this.isParam = segment.startsWith(":");
901
+ if (this.isParam) {
902
+ this.paramName = segment.slice(1);
903
+ }
1161
904
  }
1162
- return void 0;
1163
- }
1164
- const [segment, ...rest] = segments;
1165
- for (const child of node.children) {
1166
- if (child.isParam) {
1167
- const paramName = child.paramName;
1168
- const childParams = {
1169
- ...params,
1170
- [paramName]: segment ?? ""
1171
- };
1172
- if (rest.length === 0) {
1173
- return {
1174
- node: child,
1175
- params: childParams
1176
- };
905
+ /**
906
+ * Matches a child node against a given segment.
907
+ * This method checks if the segment matches any of the children nodes.
908
+ * @param segment - The segment to match against the children of this node.
909
+ * @returns A child node that matches the segment, or undefined if no match is found.
910
+ */
911
+ matchChild(segment) {
912
+ for (const child of this.children) {
913
+ if (child.isParam || segment.startsWith(child.segment))
914
+ return child;
1177
915
  }
1178
- const result = this.searchRecursive(child, rest, childParams);
1179
- if (result) return result;
1180
- } else if (segment === child.segment) {
1181
- if (rest.length === 0) {
1182
- return {
1183
- node: child,
1184
- params
1185
- };
916
+ return void 0;
917
+ }
918
+ /**
919
+ * Finds a child node that matches the segment exactly.
920
+ * This method checks if there is a child node that matches the segment exactly.
921
+ * @param segment - The segment to find an exact match for among the children of this node.
922
+ * @returns A child node that matches the segment exactly, or undefined if no match is found.
923
+ */
924
+ findExactChild(segment) {
925
+ return this.children.find((c) => c.segment === segment);
926
+ }
927
+ /**
928
+ * Adds a child node to this node's children.
929
+ * This method adds a new child node to the list of children for this node.
930
+ * @param node - The child node to add to this node's children.
931
+ */
932
+ addChild(node) {
933
+ this.children.push(node);
934
+ }
935
+ };
936
+ __name(_RadixNode, "RadixNode");
937
+ RadixNode = _RadixNode;
938
+ _RadixTree = class _RadixTree {
939
+ constructor() {
940
+ this.root = new RadixNode("");
941
+ }
942
+ /**
943
+ * Inserts a path and its associated value into the Radix Tree.
944
+ * This method normalizes the path and inserts it into the tree, associating it with
945
+ * @param path - The path to insert into the tree.
946
+ * @param value - The value to associate with the path.
947
+ */
948
+ insert(path2, value) {
949
+ const segments = this.normalize(path2);
950
+ this.insertRecursive(this.root, segments, value);
951
+ }
952
+ /**
953
+ * Recursively inserts a path into the Radix Tree.
954
+ * This method traverses the tree and inserts the segments of the path, creating new nodes
955
+ * @param node - The node to start inserting from.
956
+ * @param segments - The segments of the path to insert.
957
+ * @param value - The value to associate with the path.
958
+ */
959
+ insertRecursive(node, segments, value) {
960
+ if (segments.length === 0) {
961
+ node.value = value;
962
+ return;
1186
963
  }
1187
- const result = this.searchRecursive(child, rest, params);
1188
- if (result) return result;
964
+ const segment = segments[0] ?? "";
965
+ let child = node.children.find(
966
+ (c) => c.isParam === segment.startsWith(":") && (c.isParam || c.segment === segment)
967
+ );
968
+ if (!child) {
969
+ child = new RadixNode(segment);
970
+ node.addChild(child);
971
+ }
972
+ this.insertRecursive(child, segments.slice(1), value);
1189
973
  }
1190
- }
1191
- return void 0;
1192
- }
1193
- /**
1194
- * Normalizes a path into an array of segments.
1195
- * This method removes leading and trailing slashes, splits the path by slashes, and
1196
- * @param path - The path to normalize.
1197
- * @returns An array of normalized path segments.
1198
- */
1199
- normalize(path2) {
1200
- const segments = path2.replace(/^\/+|\/+$/g, "").split("/").filter(Boolean);
1201
- return [
1202
- "",
1203
- ...segments
1204
- ];
974
+ /**
975
+ * Searches for a path in the Radix Tree.
976
+ * This method normalizes the path and searches for it in the tree, returning the node
977
+ * @param path - The path to search for in the Radix Tree.
978
+ * @returns An ISearchResult containing the node and parameters if a match is found, otherwise undefined.
979
+ */
980
+ search(path2) {
981
+ const segments = this.normalize(path2);
982
+ return this.searchRecursive(this.root, segments, {});
983
+ }
984
+ /**
985
+ * Recursively searches for a path in the Radix Tree.
986
+ * This method traverses the tree and searches for the segments of the path, collecting parameters
987
+ * @param node - The node to start searching from.
988
+ * @param segments - The segments of the path to search for.
989
+ * @param params - The parameters collected during the search.
990
+ * @returns An ISearchResult containing the node and parameters if a match is found, otherwise undefined.
991
+ */
992
+ searchRecursive(node, segments, params) {
993
+ if (segments.length === 0) {
994
+ if (node.value !== void 0) {
995
+ return {
996
+ node,
997
+ params
998
+ };
999
+ }
1000
+ return void 0;
1001
+ }
1002
+ const [segment, ...rest] = segments;
1003
+ for (const child of node.children) {
1004
+ if (child.isParam) {
1005
+ const paramName = child.paramName;
1006
+ const childParams = {
1007
+ ...params,
1008
+ [paramName]: segment ?? ""
1009
+ };
1010
+ if (rest.length === 0) {
1011
+ return {
1012
+ node: child,
1013
+ params: childParams
1014
+ };
1015
+ }
1016
+ const result = this.searchRecursive(child, rest, childParams);
1017
+ if (result)
1018
+ return result;
1019
+ } else if (segment === child.segment) {
1020
+ if (rest.length === 0) {
1021
+ return {
1022
+ node: child,
1023
+ params
1024
+ };
1025
+ }
1026
+ const result = this.searchRecursive(child, rest, params);
1027
+ if (result)
1028
+ return result;
1029
+ }
1030
+ }
1031
+ return void 0;
1032
+ }
1033
+ /**
1034
+ * Normalizes a path into an array of segments.
1035
+ * This method removes leading and trailing slashes, splits the path by slashes, and
1036
+ * @param path - The path to normalize.
1037
+ * @returns An array of normalized path segments.
1038
+ */
1039
+ normalize(path2) {
1040
+ const segments = path2.replace(/^\/+|\/+$/g, "").split("/").filter(Boolean);
1041
+ return ["", ...segments];
1042
+ }
1043
+ };
1044
+ __name(_RadixTree, "RadixTree");
1045
+ RadixTree = _RadixTree;
1205
1046
  }
1206
- };
1207
- __name(_RadixTree, "RadixTree");
1208
- var RadixTree = _RadixTree;
1047
+ });
1209
1048
 
1210
1049
  // src/router.ts
1211
- function _ts_decorate(decorators, target, key, desc) {
1212
- var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
1213
- if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
1214
- else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
1215
- return c > 3 && r && Object.defineProperty(target, key, r), r;
1216
- }
1217
- __name(_ts_decorate, "_ts_decorate");
1218
- var ATOMIC_HTTP_METHODS = /* @__PURE__ */ new Set([
1219
- "GET",
1220
- "POST",
1221
- "PUT",
1222
- "PATCH",
1223
- "DELETE"
1224
- ]);
1225
- function isAtomicHttpMethod(method) {
1226
- return typeof method === "string" && ATOMIC_HTTP_METHODS.has(method);
1227
- }
1228
- __name(isAtomicHttpMethod, "isAtomicHttpMethod");
1229
- var _Router = class _Router {
1230
- constructor() {
1231
- __publicField(this, "routes", new RadixTree());
1232
- __publicField(this, "rootMiddlewares", []);
1233
- __publicField(this, "lazyRoutes", /* @__PURE__ */ new Map());
1234
- }
1235
- /**
1236
- * Registers a controller class with the router.
1237
- * This method extracts the route metadata from the controller class and registers it in the routing tree.
1238
- * It also handles the guards and middlewares associated with the controller.
1239
- * @param controllerClass - The controller class to register.
1240
- */
1241
- registerController(controllerClass) {
1242
- const controllerMeta = getControllerMetadata(controllerClass);
1243
- const controllerGuards = getGuardForController(controllerClass.name);
1244
- const controllerMiddlewares = getMiddlewaresForController(controllerClass.name);
1245
- if (!controllerMeta) throw new Error(`Missing @Controller decorator on ${controllerClass.name}`);
1246
- const routeMetadata = getRouteMetadata(controllerClass);
1247
- for (const def of routeMetadata) {
1248
- const fullPath = `${controllerMeta.path}/${def.path}`.replace(/\/+/g, "/");
1249
- const routeGuards = getGuardForControllerAction(controllerClass.name, def.handler);
1250
- const routeMiddlewares = getMiddlewaresForControllerAction(controllerClass.name, def.handler);
1251
- const guards = /* @__PURE__ */ new Set([
1252
- ...controllerGuards,
1253
- ...routeGuards
1254
- ]);
1255
- const middlewares2 = /* @__PURE__ */ new Set([
1256
- ...controllerMiddlewares,
1257
- ...routeMiddlewares
1258
- ]);
1259
- const routeDef = {
1260
- method: def.method,
1261
- path: fullPath,
1262
- controller: controllerClass,
1263
- handler: def.handler,
1264
- guards: [
1265
- ...guards
1266
- ],
1267
- middlewares: [
1268
- ...middlewares2
1269
- ]
1270
- };
1271
- this.routes.insert(fullPath + "/" + def.method, routeDef);
1272
- const hasActionGuards = routeDef.guards.length > 0;
1273
- const actionGuardsInfo = hasActionGuards ? "<" + routeDef.guards.map((g) => g.name).join("|") + ">" : "";
1274
- Logger.log(`Mapped {${routeDef.method} /${fullPath}}${actionGuardsInfo} route`);
1275
- }
1276
- const hasCtrlGuards = controllerMeta.guards.length > 0;
1277
- const controllerGuardsInfo = hasCtrlGuards ? "<" + controllerMeta.guards.map((g) => g.name).join("|") + ">" : "";
1278
- Logger.log(`Mapped ${controllerClass.name}${controllerGuardsInfo} controller's routes`);
1279
- return this;
1280
- }
1281
- /**
1282
- * Registers a lazy route. The module behind this route prefix will only
1283
- * be imported (and its controllers/services registered in DI) the first
1284
- * time a request targets this prefix.
1285
- *
1286
- * @param pathPrefix - Route prefix (e.g. "auth"). Matched against the first segment of the request path.
1287
- * @param loadModule - A function that returns a dynamic import promise.
1288
- */
1289
- registerLazyRoute(pathPrefix, loadModule) {
1290
- const normalized = pathPrefix.replace(/^\/+|\/+$/g, "");
1291
- this.lazyRoutes.set(normalized, {
1292
- loadModule,
1293
- loading: null,
1294
- loaded: false
1295
- });
1296
- Logger.log(`Registered lazy route prefix {${normalized}}`);
1297
- return this;
1298
- }
1299
- /**
1300
- * Defines a middleware for the root of the application.
1301
- * This method allows you to register a middleware that will be applied to all requests
1302
- * to the application, regardless of the controller or action.
1303
- * @param middleware - The middleware class to register.
1304
- */
1305
- defineRootMiddleware(middleware) {
1306
- this.rootMiddlewares.push(middleware);
1307
- return this;
1308
- }
1309
- /**
1310
- * Shuts down the message channel for a specific sender ID.
1311
- * This method closes the IPC channel for the specified sender ID and
1312
- * removes it from the messagePorts map.
1313
- * @param channelSenderId - The ID of the sender channel to shut down.
1314
- */
1315
- async handle(request) {
1316
- if (request.method === "BATCH") {
1317
- return this.handleBatch(request);
1318
- }
1319
- return this.handleAtomic(request);
1320
- }
1321
- async handleAtomic(request) {
1322
- Logger.comment(`> ${request.method} /${request.path}`);
1323
- const t0 = performance.now();
1324
- const response = {
1325
- requestId: request.id,
1326
- status: 200,
1327
- body: null
1328
- };
1329
- let isCritical = false;
1330
- try {
1331
- const routeDef = await this.findRoute(request);
1332
- await this.resolveController(request, response, routeDef);
1333
- if (response.status > 400) {
1334
- throw new ResponseException(response.status, response.error);
1335
- }
1336
- } catch (error) {
1337
- response.body = void 0;
1338
- if (error instanceof ResponseException) {
1339
- response.status = error.status;
1340
- response.error = error.message;
1341
- response.stack = error.stack;
1342
- } else if (error instanceof Error) {
1343
- isCritical = true;
1344
- response.status = 500;
1345
- response.error = error.message || "Internal Server Error";
1346
- response.stack = error.stack || "No stack trace available";
1347
- } else {
1348
- isCritical = true;
1349
- response.status = 500;
1350
- response.error = "Unknown error occurred";
1351
- response.stack = "No stack trace available";
1352
- }
1353
- } finally {
1354
- const t1 = performance.now();
1355
- const message = `< ${response.status} ${request.method} /${request.path} ${Logger.colors.yellow}${Math.round(t1 - t0)}ms${Logger.colors.initial}`;
1356
- if (response.status < 400) {
1357
- Logger.log(message);
1358
- } else if (response.status < 500) {
1359
- Logger.warn(message);
1360
- } else {
1361
- if (isCritical) {
1362
- Logger.critical(message);
1363
- } else {
1364
- Logger.error(message);
1365
- }
1050
+ var router_exports = {};
1051
+ __export(router_exports, {
1052
+ Router: () => Router
1053
+ });
1054
+ var Router;
1055
+ var init_router = __esm({
1056
+ "src/router.ts"() {
1057
+ "use strict";
1058
+ init_controller_decorator();
1059
+ init_injectable_decorator();
1060
+ init_method_decorator();
1061
+ init_injector_explorer();
1062
+ init_exceptions();
1063
+ init_request();
1064
+ init_logger();
1065
+ init_radix_tree();
1066
+ Router = class {
1067
+ constructor() {
1068
+ this.routes = new RadixTree();
1069
+ this.rootMiddlewares = [];
1070
+ this.lazyRoutes = /* @__PURE__ */ new Map();
1366
1071
  }
1367
- if (response.error !== void 0) {
1368
- if (isCritical) {
1369
- Logger.critical(response.error);
1370
- } else {
1371
- Logger.error(response.error);
1072
+ // -------------------------------------------------------------------------
1073
+ // Registration
1074
+ // -------------------------------------------------------------------------
1075
+ registerController(controllerClass, pathPrefix, routeGuards = [], routeMiddlewares = []) {
1076
+ const meta = getControllerMetadata(controllerClass);
1077
+ if (!meta) {
1078
+ throw new Error(`[Noxus] Missing @Controller decorator on ${controllerClass.name}`);
1372
1079
  }
1373
- if (response.stack !== void 0) {
1374
- Logger.errorStack(response.stack);
1080
+ const routeMeta = getRouteMetadata(controllerClass);
1081
+ for (const def of routeMeta) {
1082
+ const fullPath = `${pathPrefix}/${def.path}`.replace(/\/+/g, "/").replace(/\/$/, "") || "/";
1083
+ const guards = [.../* @__PURE__ */ new Set([...routeGuards, ...def.guards])];
1084
+ const middlewares = [.../* @__PURE__ */ new Set([...routeMiddlewares, ...def.middlewares])];
1085
+ const routeDef = {
1086
+ method: def.method,
1087
+ path: fullPath,
1088
+ controller: controllerClass,
1089
+ handler: def.handler,
1090
+ guards,
1091
+ middlewares
1092
+ };
1093
+ this.routes.insert(fullPath + "/" + def.method, routeDef);
1094
+ const guardInfo = guards.length ? `<${guards.map((g) => g.name).join("|")}>` : "";
1095
+ Logger.log(`Mapped {${def.method} /${fullPath}}${guardInfo} route`);
1375
1096
  }
1097
+ const ctrlGuardInfo = routeGuards.length ? `<${routeGuards.map((g) => g.name).join("|")}>` : "";
1098
+ Logger.log(`Mapped ${controllerClass.name}${ctrlGuardInfo} controller's routes`);
1099
+ return this;
1376
1100
  }
1377
- return response;
1378
- }
1379
- }
1380
- async handleBatch(request) {
1381
- Logger.comment(`> ${request.method} /${request.path}`);
1382
- const t0 = performance.now();
1383
- const response = {
1384
- requestId: request.id,
1385
- status: 200,
1386
- body: {
1387
- responses: []
1101
+ registerLazyRoute(pathPrefix, load, guards = [], middlewares = []) {
1102
+ const normalized = pathPrefix.replace(/^\/+|\/+$/g, "");
1103
+ this.lazyRoutes.set(normalized, { load, guards, middlewares, loading: null, loaded: false });
1104
+ Logger.log(`Registered lazy route prefix {${normalized}}`);
1105
+ return this;
1388
1106
  }
1389
- };
1390
- let isCritical = false;
1391
- try {
1392
- const payload = this.normalizeBatchPayload(request.body);
1393
- const batchPromises = payload.requests.map((item, index) => {
1394
- const subRequestId = item.requestId ?? `${request.id}:${index}`;
1395
- const atomicRequest = new Request(request.event, request.senderId, subRequestId, item.method, item.path, item.body);
1396
- return this.handleAtomic(atomicRequest);
1397
- });
1398
- response.body.responses = await Promise.all(batchPromises);
1399
- } catch (error) {
1400
- response.body = void 0;
1401
- if (error instanceof ResponseException) {
1402
- response.status = error.status;
1403
- response.error = error.message;
1404
- response.stack = error.stack;
1405
- } else if (error instanceof Error) {
1406
- isCritical = true;
1407
- response.status = 500;
1408
- response.error = error.message || "Internal Server Error";
1409
- response.stack = error.stack || "No stack trace available";
1410
- } else {
1411
- isCritical = true;
1412
- response.status = 500;
1413
- response.error = "Unknown error occurred";
1414
- response.stack = "No stack trace available";
1415
- }
1416
- } finally {
1417
- const t1 = performance.now();
1418
- const message = `< ${response.status} ${request.method} /${request.path} ${Logger.colors.yellow}${Math.round(t1 - t0)}ms${Logger.colors.initial}`;
1419
- if (response.status < 400) {
1420
- Logger.log(message);
1421
- } else if (response.status < 500) {
1422
- Logger.warn(message);
1423
- } else {
1424
- if (isCritical) {
1425
- Logger.critical(message);
1426
- } else {
1427
- Logger.error(message);
1107
+ defineRootMiddleware(middleware) {
1108
+ this.rootMiddlewares.push(middleware);
1109
+ return this;
1110
+ }
1111
+ // -------------------------------------------------------------------------
1112
+ // Request handling
1113
+ // -------------------------------------------------------------------------
1114
+ async handle(request) {
1115
+ return request.method === "BATCH" ? this.handleBatch(request) : this.handleAtomic(request);
1116
+ }
1117
+ async handleAtomic(request) {
1118
+ Logger.comment(`> ${request.method} /${request.path}`);
1119
+ const t0 = performance.now();
1120
+ const response = { requestId: request.id, status: 200, body: null };
1121
+ let isCritical = false;
1122
+ try {
1123
+ const routeDef = await this.findRoute(request);
1124
+ await this.resolveController(request, response, routeDef);
1125
+ if (response.status >= 400) throw new ResponseException(response.status, response.error);
1126
+ } catch (error) {
1127
+ this.fillErrorResponse(response, error, (c) => {
1128
+ isCritical = c;
1129
+ });
1130
+ } finally {
1131
+ this.logResponse(request, response, performance.now() - t0, isCritical);
1132
+ return response;
1428
1133
  }
1429
1134
  }
1430
- if (response.error !== void 0) {
1431
- if (isCritical) {
1432
- Logger.critical(response.error);
1433
- } else {
1434
- Logger.error(response.error);
1135
+ async handleBatch(request) {
1136
+ Logger.comment(`> ${request.method} /${request.path}`);
1137
+ const t0 = performance.now();
1138
+ const response = {
1139
+ requestId: request.id,
1140
+ status: 200,
1141
+ body: { responses: [] }
1142
+ };
1143
+ let isCritical = false;
1144
+ try {
1145
+ const payload = this.normalizeBatchPayload(request.body);
1146
+ response.body.responses = await Promise.all(
1147
+ payload.requests.map((item, i) => {
1148
+ const id = item.requestId ?? `${request.id}:${i}`;
1149
+ return this.handleAtomic(new Request(request.event, request.senderId, id, item.method, item.path, item.body));
1150
+ })
1151
+ );
1152
+ } catch (error) {
1153
+ this.fillErrorResponse(response, error, (c) => {
1154
+ isCritical = c;
1155
+ });
1156
+ } finally {
1157
+ this.logResponse(request, response, performance.now() - t0, isCritical);
1158
+ return response;
1435
1159
  }
1436
- if (response.stack !== void 0) {
1437
- Logger.errorStack(response.stack);
1160
+ }
1161
+ // -------------------------------------------------------------------------
1162
+ // Route resolution
1163
+ // -------------------------------------------------------------------------
1164
+ tryFindRoute(request) {
1165
+ const matched = this.routes.search(request.path);
1166
+ if (!matched?.node || matched.node.children.length === 0) return void 0;
1167
+ return matched.node.findExactChild(request.method)?.value;
1168
+ }
1169
+ async findRoute(request) {
1170
+ const direct = this.tryFindRoute(request);
1171
+ if (direct) return direct;
1172
+ await this.tryLoadLazyRoute(request.path);
1173
+ const afterLazy = this.tryFindRoute(request);
1174
+ if (afterLazy) return afterLazy;
1175
+ throw new NotFoundException(`No route matches ${request.method} ${request.path}`);
1176
+ }
1177
+ async tryLoadLazyRoute(requestPath) {
1178
+ const firstSegment = requestPath.replace(/^\/+/, "").split("/")[0] ?? "";
1179
+ for (const [prefix, entry] of this.lazyRoutes) {
1180
+ if (entry.loaded) continue;
1181
+ const normalized = requestPath.replace(/^\/+/, "");
1182
+ if (normalized === prefix || normalized.startsWith(prefix + "/") || firstSegment === prefix) {
1183
+ if (!entry.loading) entry.loading = this.loadLazyModule(prefix, entry);
1184
+ await entry.loading;
1185
+ return;
1186
+ }
1438
1187
  }
1439
1188
  }
1440
- return response;
1441
- }
1442
- }
1443
- normalizeBatchPayload(body) {
1444
- if (body === null || typeof body !== "object") {
1445
- throw new BadRequestException("Batch payload must be an object containing a requests array.");
1446
- }
1447
- const possiblePayload = body;
1448
- const { requests } = possiblePayload;
1449
- if (!Array.isArray(requests)) {
1450
- throw new BadRequestException("Batch payload must define a requests array.");
1451
- }
1452
- const normalizedRequests = requests.map((entry, index) => this.normalizeBatchItem(entry, index));
1453
- return {
1454
- requests: normalizedRequests
1455
- };
1456
- }
1457
- normalizeBatchItem(entry, index) {
1458
- if (entry === null || typeof entry !== "object") {
1459
- throw new BadRequestException(`Batch request at index ${index} must be an object.`);
1460
- }
1461
- const { requestId, path: path2, method, body } = entry;
1462
- if (requestId !== void 0 && typeof requestId !== "string") {
1463
- throw new BadRequestException(`Batch request at index ${index} has an invalid requestId.`);
1464
- }
1465
- if (typeof path2 !== "string" || path2.length === 0) {
1466
- throw new BadRequestException(`Batch request at index ${index} must define a non-empty path.`);
1467
- }
1468
- if (typeof method !== "string") {
1469
- throw new BadRequestException(`Batch request at index ${index} must define an HTTP method.`);
1470
- }
1471
- const normalizedMethod = method.toUpperCase();
1472
- if (!isAtomicHttpMethod(normalizedMethod)) {
1473
- throw new BadRequestException(`Batch request at index ${index} uses the unsupported method ${method}.`);
1474
- }
1475
- return {
1476
- requestId,
1477
- path: path2,
1478
- method: normalizedMethod,
1479
- body
1480
- };
1481
- }
1482
- /**
1483
- * Finds the route definition for a given request.
1484
- * This method searches the routing tree for a matching route based on the request's path and method.
1485
- * If no matching route is found, it throws a NotFoundException.
1486
- * @param request - The Request object containing the method and path to search for.
1487
- * @returns The IRouteDefinition for the matched route.
1488
- */
1489
- /**
1490
- * Attempts to find a route definition for the given request.
1491
- * Returns undefined instead of throwing when the route is not found,
1492
- * so the caller can try lazy-loading first.
1493
- */
1494
- tryFindRoute(request) {
1495
- const matchedRoutes = this.routes.search(request.path);
1496
- if (matchedRoutes?.node === void 0 || matchedRoutes.node.children.length === 0) {
1497
- return void 0;
1498
- }
1499
- const routeDef = matchedRoutes.node.findExactChild(request.method);
1500
- return routeDef?.value;
1501
- }
1502
- /**
1503
- * Finds the route definition for a given request.
1504
- * If no eagerly-registered route matches, attempts to load a lazy module
1505
- * whose prefix matches the request path, then retries.
1506
- */
1507
- async findRoute(request) {
1508
- const direct = this.tryFindRoute(request);
1509
- if (direct) return direct;
1510
- await this.tryLoadLazyRoute(request.path);
1511
- const afterLazy = this.tryFindRoute(request);
1512
- if (afterLazy) return afterLazy;
1513
- throw new NotFoundException(`No route matches ${request.method} ${request.path}`);
1514
- }
1515
- /**
1516
- * Given a request path, checks whether a lazy route prefix matches
1517
- * and triggers the dynamic import if it hasn't been loaded yet.
1518
- */
1519
- async tryLoadLazyRoute(requestPath) {
1520
- const firstSegment = requestPath.replace(/^\/+/, "").split("/")[0] ?? "";
1521
- for (const [prefix, entry] of this.lazyRoutes) {
1522
- if (entry.loaded) continue;
1523
- const normalizedPath = requestPath.replace(/^\/+/, "");
1524
- if (normalizedPath === prefix || normalizedPath.startsWith(prefix + "/") || firstSegment === prefix) {
1525
- if (!entry.loading) {
1526
- entry.loading = this.loadLazyModule(prefix, entry);
1189
+ async loadLazyModule(prefix, entry) {
1190
+ const t0 = performance.now();
1191
+ InjectorExplorer.beginAccumulate();
1192
+ await entry.load?.();
1193
+ entry.loading = null;
1194
+ entry.load = null;
1195
+ InjectorExplorer.flushAccumulated(entry.guards, entry.middlewares, prefix);
1196
+ entry.loaded = true;
1197
+ Logger.info(`Lazy-loaded module for prefix {${prefix}} in ${Math.round(performance.now() - t0)}ms`);
1198
+ }
1199
+ // -------------------------------------------------------------------------
1200
+ // Pipeline
1201
+ // -------------------------------------------------------------------------
1202
+ async resolveController(request, response, routeDef) {
1203
+ const instance = request.context.resolve(routeDef.controller);
1204
+ Object.assign(request.params, this.extractParams(request.path, routeDef.path));
1205
+ await this.runPipeline(request, response, routeDef, instance);
1206
+ }
1207
+ async runPipeline(request, response, routeDef, controllerInstance) {
1208
+ const middlewares = [.../* @__PURE__ */ new Set([...this.rootMiddlewares, ...routeDef.middlewares])];
1209
+ const mwMax = middlewares.length - 1;
1210
+ const guardMax = mwMax + routeDef.guards.length;
1211
+ let index = -1;
1212
+ const dispatch = /* @__PURE__ */ __name(async (i) => {
1213
+ if (i <= index) throw new Error("next() called multiple times");
1214
+ index = i;
1215
+ if (i <= mwMax) {
1216
+ await this.runMiddleware(request, response, dispatch.bind(null, i + 1), middlewares[i]);
1217
+ if (response.status >= 400) throw new ResponseException(response.status, response.error);
1218
+ return;
1219
+ }
1220
+ if (i <= guardMax) {
1221
+ await this.runGuard(request, routeDef.guards[i - middlewares.length]);
1222
+ await dispatch(i + 1);
1223
+ return;
1224
+ }
1225
+ const action = controllerInstance[routeDef.handler];
1226
+ response.body = await action.call(controllerInstance, request, response);
1227
+ if (response.body === void 0) response.body = {};
1228
+ }, "dispatch");
1229
+ await dispatch(0);
1230
+ }
1231
+ async runMiddleware(request, response, next, middleware) {
1232
+ await middleware(request, response, next);
1233
+ }
1234
+ async runGuard(request, guard) {
1235
+ if (!await guard(request)) {
1236
+ throw new UnauthorizedException(`Unauthorized for ${request.method} ${request.path}`);
1527
1237
  }
1528
- await entry.loading;
1529
- return;
1530
1238
  }
1531
- }
1532
- }
1533
- /**
1534
- * Dynamically imports a lazy module and registers its decorated classes
1535
- * (controllers, services) in the DI container using the two-phase strategy.
1536
- */
1537
- async loadLazyModule(prefix, entry) {
1538
- const t0 = performance.now();
1539
- InjectorExplorer.beginAccumulate();
1540
- await entry.loadModule();
1541
- InjectorExplorer.flushAccumulated();
1542
- entry.loaded = true;
1543
- const t1 = performance.now();
1544
- Logger.info(`Lazy-loaded module for prefix {${prefix}} in ${Math.round(t1 - t0)}ms`);
1545
- }
1546
- /**
1547
- * Resolves the controller for a given route definition.
1548
- * This method creates an instance of the controller class and prepares the request parameters.
1549
- * It also runs the request pipeline, which includes executing middlewares and guards.
1550
- * @param request - The Request object containing the request data.
1551
- * @param response - The IResponse object to populate with the response data.
1552
- * @param routeDef - The IRouteDefinition for the matched route.
1553
- * @return A Promise that resolves when the controller action has been executed.
1554
- * @throws UnauthorizedException if the request is not authorized by the guards.
1555
- */
1556
- async resolveController(request, response, routeDef) {
1557
- const controllerInstance = request.context.resolve(routeDef.controller);
1558
- Object.assign(request.params, this.extractParams(request.path, routeDef.path));
1559
- await this.runRequestPipeline(request, response, routeDef, controllerInstance);
1560
- }
1561
- /**
1562
- * Runs the request pipeline for a given request.
1563
- * This method executes the middlewares and guards associated with the route,
1564
- * and finally calls the controller action.
1565
- * @param request - The Request object containing the request data.
1566
- * @param response - The IResponse object to populate with the response data.
1567
- * @param routeDef - The IRouteDefinition for the matched route.
1568
- * @param controllerInstance - The instance of the controller class.
1569
- * @return A Promise that resolves when the request pipeline has been executed.
1570
- * @throws ResponseException if the response status is not successful.
1571
- */
1572
- async runRequestPipeline(request, response, routeDef, controllerInstance) {
1573
- const middlewares2 = [
1574
- .../* @__PURE__ */ new Set([
1575
- ...this.rootMiddlewares,
1576
- ...routeDef.middlewares
1577
- ])
1578
- ];
1579
- const middlewareMaxIndex = middlewares2.length - 1;
1580
- const guardsMaxIndex = middlewareMaxIndex + routeDef.guards.length;
1581
- let index = -1;
1582
- const dispatch = /* @__PURE__ */ __name(async (i) => {
1583
- if (i <= index) throw new Error("next() called multiple times");
1584
- index = i;
1585
- if (i <= middlewareMaxIndex) {
1586
- const nextFn = dispatch.bind(null, i + 1);
1587
- await this.runMiddleware(request, response, nextFn, middlewares2[i]);
1588
- if (response.status >= 400) {
1589
- throw new ResponseException(response.status, response.error);
1239
+ // -------------------------------------------------------------------------
1240
+ // Utilities
1241
+ // -------------------------------------------------------------------------
1242
+ extractParams(actual, template) {
1243
+ const aParts = actual.split("/");
1244
+ const tParts = template.split("/");
1245
+ const params = {};
1246
+ tParts.forEach((part, i) => {
1247
+ if (part.startsWith(":")) params[part.slice(1)] = aParts[i] ?? "";
1248
+ });
1249
+ return params;
1250
+ }
1251
+ normalizeBatchPayload(body) {
1252
+ if (body === null || typeof body !== "object") {
1253
+ throw new BadRequestException("Batch payload must be an object containing a requests array.");
1590
1254
  }
1591
- return;
1255
+ const { requests } = body;
1256
+ if (!Array.isArray(requests)) throw new BadRequestException("Batch payload must define a requests array.");
1257
+ return { requests: requests.map((e, i) => this.normalizeBatchItem(e, i)) };
1592
1258
  }
1593
- if (i <= guardsMaxIndex) {
1594
- const guardIndex = i - middlewares2.length;
1595
- const guardType = routeDef.guards[guardIndex];
1596
- await this.runGuard(request, guardType);
1597
- await dispatch(i + 1);
1598
- return;
1259
+ normalizeBatchItem(entry, index) {
1260
+ if (entry === null || typeof entry !== "object") throw new BadRequestException(`Batch request at index ${index} must be an object.`);
1261
+ const { requestId, path: path2, method, body } = entry;
1262
+ if (requestId !== void 0 && typeof requestId !== "string") throw new BadRequestException(`Batch request at index ${index} has an invalid requestId.`);
1263
+ if (typeof path2 !== "string" || !path2.length) throw new BadRequestException(`Batch request at index ${index} must define a non-empty path.`);
1264
+ if (typeof method !== "string") throw new BadRequestException(`Batch request at index ${index} must define an HTTP method.`);
1265
+ const normalized = method.toUpperCase();
1266
+ if (!isAtomicHttpMethod(normalized)) throw new BadRequestException(`Batch request at index ${index} uses unsupported method ${method}.`);
1267
+ return { requestId, path: path2, method: normalized, body };
1599
1268
  }
1600
- const action = controllerInstance[routeDef.handler];
1601
- response.body = await action.call(controllerInstance, request, response);
1602
- if (response.body === void 0) {
1603
- response.body = {};
1269
+ fillErrorResponse(response, error, setCritical) {
1270
+ response.body = void 0;
1271
+ if (error instanceof ResponseException) {
1272
+ response.status = error.status;
1273
+ response.error = error.message;
1274
+ response.stack = error.stack;
1275
+ } else if (error instanceof Error) {
1276
+ setCritical(true);
1277
+ response.status = 500;
1278
+ response.error = error.message || "Internal Server Error";
1279
+ response.stack = error.stack;
1280
+ } else {
1281
+ setCritical(true);
1282
+ response.status = 500;
1283
+ response.error = "Unknown error occurred";
1284
+ }
1604
1285
  }
1605
- }, "dispatch");
1606
- await dispatch(0);
1607
- }
1608
- /**
1609
- * Runs a middleware function in the request pipeline.
1610
- * This method creates an instance of the middleware and invokes its `invoke` method,
1611
- * passing the request, response, and next function.
1612
- * @param request - The Request object containing the request data.
1613
- * @param response - The IResponse object to populate with the response data.
1614
- * @param next - The NextFunction to call to continue the middleware chain.
1615
- * @param middlewareType - The type of the middleware to run.
1616
- * @return A Promise that resolves when the middleware has been executed.
1617
- */
1618
- async runMiddleware(request, response, next, middlewareType) {
1619
- const middleware = request.context.resolve(middlewareType);
1620
- await middleware.invoke(request, response, next);
1621
- }
1622
- /**
1623
- * Runs a guard to check if the request is authorized.
1624
- * This method creates an instance of the guard and calls its `canActivate` method.
1625
- * If the guard returns false, it throws an UnauthorizedException.
1626
- * @param request - The Request object containing the request data.
1627
- * @param guardType - The type of the guard to run.
1628
- * @return A Promise that resolves if the guard allows the request, or throws an UnauthorizedException if not.
1629
- * @throws UnauthorizedException if the guard denies access to the request.
1630
- */
1631
- async runGuard(request, guardType) {
1632
- const guard = request.context.resolve(guardType);
1633
- const allowed = await guard.canActivate(request);
1634
- if (!allowed) throw new UnauthorizedException(`Unauthorized for ${request.method} ${request.path}`);
1635
- }
1636
- /**
1637
- * Extracts parameters from the actual request path based on the template path.
1638
- * This method splits the actual path and the template path into segments,
1639
- * then maps the segments to parameters based on the template.
1640
- * @param actual - The actual request path.
1641
- * @param template - The template path to extract parameters from.
1642
- * @returns An object containing the extracted parameters.
1643
- */
1644
- extractParams(actual, template) {
1645
- const aParts = actual.split("/");
1646
- const tParts = template.split("/");
1647
- const params = {};
1648
- tParts.forEach((part, i) => {
1649
- if (part.startsWith(":")) {
1650
- params[part.slice(1)] = aParts[i] ?? "";
1286
+ logResponse(request, response, ms, isCritical) {
1287
+ const msg = `< ${response.status} ${request.method} /${request.path} ${Logger.colors.yellow}${Math.round(ms)}ms${Logger.colors.initial}`;
1288
+ if (response.status < 400) Logger.log(msg);
1289
+ else if (response.status < 500) Logger.warn(msg);
1290
+ else isCritical ? Logger.critical(msg) : Logger.error(msg);
1291
+ if (response.error) {
1292
+ isCritical ? Logger.critical(response.error) : Logger.error(response.error);
1293
+ if (response.stack) Logger.errorStack(response.stack);
1294
+ }
1651
1295
  }
1652
- });
1653
- return params;
1296
+ };
1297
+ __name(Router, "Router");
1298
+ Router = __decorateClass([
1299
+ Injectable({ lifetime: "singleton" })
1300
+ ], Router);
1654
1301
  }
1655
- };
1656
- __name(_Router, "Router");
1657
- var Router = _Router;
1658
- Router = _ts_decorate([
1659
- Injectable("singleton")
1660
- ], Router);
1302
+ });
1303
+
1304
+ // src/main.ts
1305
+ var main_exports = {};
1306
+ __export(main_exports, {
1307
+ AppInjector: () => AppInjector,
1308
+ BadGatewayException: () => BadGatewayException,
1309
+ BadRequestException: () => BadRequestException,
1310
+ ConflictException: () => ConflictException,
1311
+ Controller: () => Controller,
1312
+ Delete: () => Delete,
1313
+ ForbiddenException: () => ForbiddenException,
1314
+ ForwardReference: () => ForwardReference,
1315
+ GatewayTimeoutException: () => GatewayTimeoutException,
1316
+ Get: () => Get,
1317
+ HttpVersionNotSupportedException: () => HttpVersionNotSupportedException,
1318
+ Injectable: () => Injectable,
1319
+ InsufficientStorageException: () => InsufficientStorageException,
1320
+ InternalServerException: () => InternalServerException,
1321
+ Logger: () => Logger,
1322
+ LoopDetectedException: () => LoopDetectedException,
1323
+ MethodNotAllowedException: () => MethodNotAllowedException,
1324
+ NetworkAuthenticationRequiredException: () => NetworkAuthenticationRequiredException,
1325
+ NetworkConnectTimeoutException: () => NetworkConnectTimeoutException,
1326
+ NotAcceptableException: () => NotAcceptableException,
1327
+ NotExtendedException: () => NotExtendedException,
1328
+ NotFoundException: () => NotFoundException,
1329
+ NotImplementedException: () => NotImplementedException,
1330
+ NoxApp: () => NoxApp,
1331
+ NoxSocket: () => NoxSocket,
1332
+ Patch: () => Patch,
1333
+ PaymentRequiredException: () => PaymentRequiredException,
1334
+ Post: () => Post,
1335
+ Put: () => Put,
1336
+ RENDERER_EVENT_TYPE: () => RENDERER_EVENT_TYPE,
1337
+ Request: () => Request,
1338
+ RequestTimeoutException: () => RequestTimeoutException,
1339
+ ResponseException: () => ResponseException,
1340
+ RootInjector: () => RootInjector,
1341
+ Router: () => Router,
1342
+ ServiceUnavailableException: () => ServiceUnavailableException,
1343
+ Token: () => Token,
1344
+ TooManyRequestsException: () => TooManyRequestsException,
1345
+ UnauthorizedException: () => UnauthorizedException,
1346
+ UpgradeRequiredException: () => UpgradeRequiredException,
1347
+ VariantAlsoNegotiatesException: () => VariantAlsoNegotiatesException,
1348
+ WindowManager: () => WindowManager,
1349
+ bootstrapApplication: () => bootstrapApplication,
1350
+ createRendererEventMessage: () => createRendererEventMessage,
1351
+ defineRoutes: () => defineRoutes,
1352
+ forwardRef: () => forwardRef,
1353
+ getControllerMetadata: () => getControllerMetadata,
1354
+ getRouteMetadata: () => getRouteMetadata,
1355
+ inject: () => inject,
1356
+ isAtomicHttpMethod: () => isAtomicHttpMethod,
1357
+ isRendererEventMessage: () => isRendererEventMessage,
1358
+ token: () => token
1359
+ });
1360
+ module.exports = __toCommonJS(main_exports);
1361
+ init_app_injector();
1362
+ init_token();
1363
+ init_router();
1661
1364
 
1662
1365
  // src/app.ts
1663
- var import_main = require("electron/main");
1366
+ var import_main2 = require("electron/main");
1367
+ init_injectable_decorator();
1368
+ init_app_injector();
1369
+ init_injector_explorer();
1370
+ init_request();
1371
+ init_router();
1664
1372
 
1665
1373
  // src/socket.ts
1666
- function _ts_decorate2(decorators, target, key, desc) {
1667
- var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
1668
- if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
1669
- else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
1670
- return c > 3 && r && Object.defineProperty(target, key, r), r;
1671
- }
1672
- __name(_ts_decorate2, "_ts_decorate");
1673
- var _NoxSocket = class _NoxSocket {
1374
+ init_injectable_decorator();
1375
+ init_request();
1376
+ init_logger();
1377
+ var NoxSocket = class {
1674
1378
  constructor() {
1675
- __publicField(this, "channels", /* @__PURE__ */ new Map());
1379
+ this.channels = /* @__PURE__ */ new Map();
1676
1380
  }
1677
1381
  register(senderId, requestChannel, socketChannel) {
1678
- this.channels.set(senderId, {
1679
- request: requestChannel,
1680
- socket: socketChannel
1681
- });
1382
+ this.channels.set(senderId, { request: requestChannel, socket: socketChannel });
1682
1383
  }
1683
1384
  get(senderId) {
1684
1385
  return this.channels.get(senderId);
@@ -1687,9 +1388,7 @@ var _NoxSocket = class _NoxSocket {
1687
1388
  this.channels.delete(senderId);
1688
1389
  }
1689
1390
  getSenderIds() {
1690
- return [
1691
- ...this.channels.keys()
1692
- ];
1391
+ return [...this.channels.keys()];
1693
1392
  }
1694
1393
  emit(eventName, payload, targetSenderIds) {
1695
1394
  const normalizedEvent = eventName.trim();
@@ -1714,39 +1413,196 @@ var _NoxSocket = class _NoxSocket {
1714
1413
  return delivered;
1715
1414
  }
1716
1415
  emitToRenderer(senderId, eventName, payload) {
1717
- return this.emit(eventName, payload, [
1718
- senderId
1719
- ]) > 0;
1416
+ return this.emit(eventName, payload, [senderId]) > 0;
1720
1417
  }
1721
1418
  };
1722
- __name(_NoxSocket, "NoxSocket");
1723
- var NoxSocket = _NoxSocket;
1724
- NoxSocket = _ts_decorate2([
1725
- Injectable("singleton")
1419
+ __name(NoxSocket, "NoxSocket");
1420
+ NoxSocket = __decorateClass([
1421
+ Injectable({ lifetime: "singleton" })
1726
1422
  ], NoxSocket);
1727
1423
 
1728
1424
  // src/app.ts
1729
- function _ts_decorate3(decorators, target, key, desc) {
1730
- var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
1731
- if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
1732
- else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
1733
- return c > 3 && r && Object.defineProperty(target, key, r), r;
1734
- }
1735
- __name(_ts_decorate3, "_ts_decorate");
1736
- function _ts_metadata(k, v) {
1737
- if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
1738
- }
1739
- __name(_ts_metadata, "_ts_metadata");
1740
- var _NoxApp = class _NoxApp {
1741
- constructor(router, socket) {
1742
- __publicField(this, "router");
1743
- __publicField(this, "socket");
1744
- __publicField(this, "app");
1745
- __publicField(this, "mainWindow");
1746
- /**
1747
- *
1748
- */
1749
- __publicField(this, "onRendererMessage", /* @__PURE__ */ __name(async (event) => {
1425
+ init_logger();
1426
+
1427
+ // src/window/window-manager.ts
1428
+ var import_main = require("electron/main");
1429
+ init_injectable_decorator();
1430
+ init_logger();
1431
+ var WindowManager = class {
1432
+ constructor() {
1433
+ this._windows = /* @__PURE__ */ new Map();
1434
+ }
1435
+ // -------------------------------------------------------------------------
1436
+ // Creation
1437
+ // -------------------------------------------------------------------------
1438
+ /**
1439
+ * Creates a BrowserWindow, optionally performs an animated expand to the
1440
+ * work area, and registers it in the manager.
1441
+ *
1442
+ * If expandToWorkArea is true:
1443
+ * 1. The window is created at the given initial size (defaults to 600×600, centered).
1444
+ * 2. An animated setBounds expands it to the full work area.
1445
+ * 3. The returned promise resolves only after the animation, so callers
1446
+ * can safely call win.loadFile() without the viewbox freeze.
1447
+ *
1448
+ * @param config Window configuration.
1449
+ * @param isMain Mark this window as the main window (accessible via getMain()).
1450
+ */
1451
+ async create(config, isMain = false) {
1452
+ const {
1453
+ expandToWorkArea = false,
1454
+ expandAnimationDuration = 600,
1455
+ ...bwOptions
1456
+ } = config;
1457
+ const win = new import_main.BrowserWindow({ show: false, ...bwOptions });
1458
+ this._register(win, isMain);
1459
+ if (expandToWorkArea) {
1460
+ await this._expandToWorkArea(win, expandAnimationDuration);
1461
+ }
1462
+ win.once("ready-to-show", () => win.show());
1463
+ Logger.log(`[WindowManager] Created window #${win.id}${isMain ? " (main)" : ""}`);
1464
+ return win;
1465
+ }
1466
+ /**
1467
+ * Creates the initial "splash" window that is shown immediately after
1468
+ * app.whenReady(). It is displayed instantly (show: true, no preload
1469
+ * loading) and then expanded to the work area with animation.
1470
+ *
1471
+ * After the animation completes you can call win.loadFile() without
1472
+ * experiencing the viewbox freeze.
1473
+ *
1474
+ * This is the recommended way to get pixels on screen as fast as possible.
1475
+ *
1476
+ * @example
1477
+ * const win = await wm.createSplash({
1478
+ * webPreferences: { preload: path.join(__dirname, 'preload.js') }
1479
+ * });
1480
+ * win.loadFile('index.html');
1481
+ */
1482
+ async createSplash(options = {}) {
1483
+ const { animationDuration = 600, ...bwOptions } = options;
1484
+ const win = new import_main.BrowserWindow({
1485
+ width: 600,
1486
+ height: 600,
1487
+ center: true,
1488
+ frame: false,
1489
+ show: true,
1490
+ ...bwOptions
1491
+ });
1492
+ this._register(win, true);
1493
+ Logger.log(`[WindowManager] Splash window #${win.id} created`);
1494
+ await this._expandToWorkArea(win, animationDuration);
1495
+ return win;
1496
+ }
1497
+ // -------------------------------------------------------------------------
1498
+ // Accessors
1499
+ // -------------------------------------------------------------------------
1500
+ /** Returns all currently open windows. */
1501
+ getAll() {
1502
+ return [...this._windows.values()];
1503
+ }
1504
+ /** Returns the window designated as main, or undefined. */
1505
+ getMain() {
1506
+ return this._mainWindowId !== void 0 ? this._windows.get(this._mainWindowId) : void 0;
1507
+ }
1508
+ /** Returns a window by its Electron id, or undefined. */
1509
+ getById(id) {
1510
+ return this._windows.get(id);
1511
+ }
1512
+ /** Returns the number of open windows. */
1513
+ get count() {
1514
+ return this._windows.size;
1515
+ }
1516
+ // -------------------------------------------------------------------------
1517
+ // Actions
1518
+ // -------------------------------------------------------------------------
1519
+ /** Closes and destroys a window by id. */
1520
+ close(id) {
1521
+ const win = this._windows.get(id);
1522
+ if (!win) {
1523
+ Logger.warn(`[WindowManager] Window #${id} not found`);
1524
+ return;
1525
+ }
1526
+ win.destroy();
1527
+ }
1528
+ /** Closes all windows. */
1529
+ closeAll() {
1530
+ for (const win of this._windows.values()) {
1531
+ win.destroy();
1532
+ }
1533
+ }
1534
+ /**
1535
+ * Sends a message to a specific window via webContents.send.
1536
+ * @param id Target window id.
1537
+ * @param channel IPC channel name.
1538
+ * @param args Payload.
1539
+ */
1540
+ send(id, channel, ...args) {
1541
+ const win = this._windows.get(id);
1542
+ if (!win || win.isDestroyed()) {
1543
+ Logger.warn(`[WindowManager] Cannot send to window #${id}: not found or destroyed`);
1544
+ return;
1545
+ }
1546
+ win.webContents.send(channel, ...args);
1547
+ }
1548
+ /**
1549
+ * Broadcasts a message to all open windows.
1550
+ */
1551
+ broadcast(channel, ...args) {
1552
+ for (const win of this._windows.values()) {
1553
+ if (!win.isDestroyed()) win.webContents.send(channel, ...args);
1554
+ }
1555
+ }
1556
+ // -------------------------------------------------------------------------
1557
+ // Private
1558
+ // -------------------------------------------------------------------------
1559
+ _register(win, isMain) {
1560
+ this._windows.set(win.id, win);
1561
+ if (isMain && this._mainWindowId === void 0) {
1562
+ this._mainWindowId = win.id;
1563
+ }
1564
+ win.once("closed", () => {
1565
+ this._windows.delete(win.id);
1566
+ if (this._mainWindowId === win.id) this._mainWindowId = void 0;
1567
+ Logger.log(`[WindowManager] Window #${win.id} closed`);
1568
+ });
1569
+ }
1570
+ /**
1571
+ * Animates the window to the full work area of the primary display.
1572
+ * Resolves only after the animation is complete, so that content loaded
1573
+ * afterward gets the correct surface size (no viewbox freeze).
1574
+ */
1575
+ _expandToWorkArea(win, animationDuration) {
1576
+ return new Promise((resolve) => {
1577
+ const { x, y, width, height } = import_main.screen.getPrimaryDisplay().workArea;
1578
+ win.setBounds({ x, y, width, height }, true);
1579
+ let resolved = false;
1580
+ const done = /* @__PURE__ */ __name(() => {
1581
+ if (resolved) return;
1582
+ resolved = true;
1583
+ win.removeListener("resize", done);
1584
+ resolve();
1585
+ }, "done");
1586
+ win.once("resize", done);
1587
+ setTimeout(done, animationDuration + 100);
1588
+ });
1589
+ }
1590
+ };
1591
+ __name(WindowManager, "WindowManager");
1592
+ WindowManager = __decorateClass([
1593
+ Injectable({ lifetime: "singleton" })
1594
+ ], WindowManager);
1595
+
1596
+ // src/app.ts
1597
+ var NoxApp = class {
1598
+ constructor() {
1599
+ this.router = inject(Router);
1600
+ this.socket = inject(NoxSocket);
1601
+ this.windowManager = inject(WindowManager);
1602
+ // -------------------------------------------------------------------------
1603
+ // IPC
1604
+ // -------------------------------------------------------------------------
1605
+ this.onRendererMessage = /* @__PURE__ */ __name(async (event) => {
1750
1606
  const { senderId, requestId, path: path2, method, body } = event.data;
1751
1607
  const channels = this.socket.get(senderId);
1752
1608
  if (!channels) {
@@ -1762,69 +1618,108 @@ var _NoxApp = class _NoxApp {
1762
1618
  requestId,
1763
1619
  status: 500,
1764
1620
  body: null,
1765
- error: err.message || "Internal Server Error"
1621
+ error: err instanceof Error ? err.message : "Internal Server Error"
1766
1622
  };
1767
1623
  channels.request.port1.postMessage(response);
1768
1624
  }
1769
- }, "onRendererMessage"));
1770
- this.router = router;
1771
- this.socket = socket;
1625
+ }, "onRendererMessage");
1772
1626
  }
1773
- /**
1774
- * Initializes the NoxApp instance.
1775
- * This method sets up the IPC communication, registers event listeners,
1776
- * and prepares the application for use.
1777
- */
1627
+ // -------------------------------------------------------------------------
1628
+ // Initialisation
1629
+ // -------------------------------------------------------------------------
1778
1630
  async init() {
1779
- import_main.ipcMain.on("gimme-my-port", this.giveTheRendererAPort.bind(this));
1780
- import_main.app.once("activate", this.onAppActivated.bind(this));
1781
- import_main.app.once("window-all-closed", this.onAllWindowsClosed.bind(this));
1631
+ import_main2.ipcMain.on("gimme-my-port", this.giveTheRendererAPort.bind(this));
1632
+ import_main2.app.once("activate", this.onAppActivated.bind(this));
1633
+ import_main2.app.once("window-all-closed", this.onAllWindowsClosed.bind(this));
1782
1634
  console.log("");
1783
1635
  return this;
1784
1636
  }
1637
+ // -------------------------------------------------------------------------
1638
+ // Public API
1639
+ // -------------------------------------------------------------------------
1640
+ /**
1641
+ * Registers a lazy route. The file behind this prefix is dynamically
1642
+ * imported on the first IPC request that targets it.
1643
+ *
1644
+ * The import function should NOT statically reference heavy modules —
1645
+ * the whole point is to defer their loading.
1646
+ *
1647
+ * @example
1648
+ * noxApp.lazy('auth', () => import('./modules/auth/auth.controller.js'));
1649
+ * noxApp.lazy('reporting', () => import('./modules/reporting/index.js'));
1650
+ */
1651
+ lazy(pathPrefix, load, guards = [], middlewares = []) {
1652
+ this.router.registerLazyRoute(pathPrefix, load, guards, middlewares);
1653
+ return this;
1654
+ }
1655
+ /**
1656
+ * Eagerly loads a set of modules (controllers + services) before start().
1657
+ * Use this for modules that provide services needed by your IApp.onReady().
1658
+ *
1659
+ * All imports run in parallel; DI is flushed with the two-phase guarantee.
1660
+ */
1661
+ async load(importFns) {
1662
+ InjectorExplorer.beginAccumulate();
1663
+ await Promise.all(importFns.map((fn) => fn()));
1664
+ InjectorExplorer.flushAccumulated();
1665
+ return this;
1666
+ }
1667
+ /**
1668
+ * Registers a global middleware applied to every route.
1669
+ */
1670
+ use(middleware) {
1671
+ this.router.defineRootMiddleware(middleware);
1672
+ return this;
1673
+ }
1674
+ /**
1675
+ * Sets the application service (implements IApp) that receives lifecycle events.
1676
+ * @param appClass - Class decorated with @Injectable that implements IApp.
1677
+ */
1678
+ configure(appClass) {
1679
+ this.appService = inject(appClass);
1680
+ return this;
1681
+ }
1785
1682
  /**
1786
- * Handles the request from the renderer process.
1787
- * This method creates a Request object from the IPC event data,
1788
- * processes it through the Router, and sends the response back
1789
- * to the renderer process using the MessageChannel.
1683
+ * Calls IApp.onReady(). Should be called after configure() and any lazy()
1684
+ * registrations are set up.
1790
1685
  */
1686
+ start() {
1687
+ this.appService?.onReady();
1688
+ return this;
1689
+ }
1791
1690
  giveTheRendererAPort(event) {
1792
1691
  const senderId = event.sender.id;
1793
1692
  if (this.socket.get(senderId)) {
1794
1693
  this.shutdownChannel(senderId);
1795
1694
  }
1796
- const requestChannel = new import_main.MessageChannelMain();
1797
- const socketChannel = new import_main.MessageChannelMain();
1695
+ const requestChannel = new import_main2.MessageChannelMain();
1696
+ const socketChannel = new import_main2.MessageChannelMain();
1798
1697
  requestChannel.port1.on("message", this.onRendererMessage);
1799
1698
  requestChannel.port1.start();
1800
1699
  socketChannel.port1.start();
1700
+ event.sender.once("destroyed", () => this.shutdownChannel(senderId));
1801
1701
  this.socket.register(senderId, requestChannel, socketChannel);
1802
- event.sender.postMessage("port", {
1803
- senderId
1804
- }, [
1805
- requestChannel.port2,
1806
- socketChannel.port2
1807
- ]);
1702
+ event.sender.postMessage("port", { senderId }, [requestChannel.port2, socketChannel.port2]);
1808
1703
  }
1809
- /**
1810
- * MacOS specific behavior.
1811
- */
1704
+ // -------------------------------------------------------------------------
1705
+ // Lifecycle
1706
+ // -------------------------------------------------------------------------
1812
1707
  onAppActivated() {
1813
- if (process.platform === "darwin" && import_main.BrowserWindow.getAllWindows().length === 0) {
1814
- this.app?.onActivated();
1708
+ if (process.platform === "darwin" && import_main2.BrowserWindow.getAllWindows().length === 0) {
1709
+ this.appService?.onActivated();
1815
1710
  }
1816
1711
  }
1817
- /**
1818
- * Shuts down the message channel for a specific sender ID.
1819
- * This method closes the IPC channel for the specified sender ID and
1820
- * removes it from the messagePorts map.
1821
- * @param channelSenderId - The ID of the sender channel to shut down.
1822
- * @param remove - Whether to remove the channel from the messagePorts map.
1823
- */
1712
+ async onAllWindowsClosed() {
1713
+ for (const senderId of this.socket.getSenderIds()) {
1714
+ this.shutdownChannel(senderId);
1715
+ }
1716
+ Logger.info("All windows closed, shutting down application...");
1717
+ await this.appService?.dispose();
1718
+ if (process.platform !== "darwin") import_main2.app.quit();
1719
+ }
1824
1720
  shutdownChannel(channelSenderId) {
1825
1721
  const channels = this.socket.get(channelSenderId);
1826
1722
  if (!channels) {
1827
- Logger.warn(`No message channel found for sender ID: ${channelSenderId}`);
1828
1723
  return;
1829
1724
  }
1830
1725
  channels.request.port1.off("message", this.onRendererMessage);
@@ -1834,139 +1729,67 @@ var _NoxApp = class _NoxApp {
1834
1729
  channels.socket.port2.close();
1835
1730
  this.socket.unregister(channelSenderId);
1836
1731
  }
1837
- /**
1838
- * Handles the application shutdown process.
1839
- * This method is called when all windows are closed, and it cleans up the message channels
1840
- */
1841
- async onAllWindowsClosed() {
1842
- for (const senderId of this.socket.getSenderIds()) {
1843
- this.shutdownChannel(senderId);
1844
- }
1845
- Logger.info("All windows closed, shutting down application...");
1846
- await this.app?.dispose();
1847
- if (process.platform !== "darwin") {
1848
- import_main.app.quit();
1849
- }
1850
- }
1851
- // ---
1852
- /**
1853
- * Sets the main BrowserWindow that was created early by bootstrapApplication.
1854
- * This window will be passed to IApp.onReady when start() is called.
1855
- * @param window - The BrowserWindow created during bootstrap.
1856
- */
1857
- setMainWindow(window) {
1858
- this.mainWindow = window;
1859
- }
1860
- /**
1861
- * Registers a lazy-loaded route. The module behind this path prefix
1862
- * will only be dynamically imported when the first IPC request
1863
- * targets this prefix — like Angular's loadChildren.
1864
- *
1865
- * @example
1866
- * ```ts
1867
- * noxApp.lazy("auth", () => import("./modules/auth/auth.module.js"));
1868
- * noxApp.lazy("printing", () => import("./modules/printing/printing.module.js"));
1869
- * ```
1870
- *
1871
- * @param pathPrefix - The route prefix (e.g. "auth", "cash-register").
1872
- * @param loadModule - A function returning a dynamic import promise.
1873
- * @returns NoxApp instance for method chaining.
1874
- */
1875
- lazy(pathPrefix, loadModule) {
1876
- this.router.registerLazyRoute(pathPrefix, loadModule);
1877
- return this;
1878
- }
1879
- /**
1880
- * Eagerly loads one or more modules with a two-phase DI guarantee.
1881
- * Use this when a service needed at startup lives inside a module
1882
- * (e.g. the Application service depends on LoaderService).
1883
- *
1884
- * All dynamic imports run in parallel; bindings are registered first,
1885
- * then singletons are resolved — safe regardless of import ordering.
1886
- *
1887
- * @param importFns - Functions returning dynamic import promises.
1888
- */
1889
- async loadModules(importFns) {
1890
- InjectorExplorer.beginAccumulate();
1891
- await Promise.all(importFns.map((fn) => fn()));
1892
- InjectorExplorer.flushAccumulated();
1893
- }
1894
- /**
1895
- * Configures the NoxApp instance with the provided application class.
1896
- * This method allows you to set the application class that will handle lifecycle events.
1897
- * @param app - The application class to configure.
1898
- * @returns NoxApp instance for method chaining.
1899
- */
1900
- configure(app3) {
1901
- this.app = inject(app3);
1902
- return this;
1903
- }
1904
- /**
1905
- * Registers a middleware for the root of the application.
1906
- * This method allows you to define a middleware that will be applied to all requests
1907
- * @param middleware - The middleware class to register.
1908
- * @returns NoxApp instance for method chaining.
1909
- */
1910
- use(middleware) {
1911
- this.router.defineRootMiddleware(middleware);
1912
- return this;
1913
- }
1914
- /**
1915
- * Should be called after the bootstrapApplication function is called.
1916
- * Passes the early-created BrowserWindow (if any) to the configured IApp service.
1917
- * @returns NoxApp instance for method chaining.
1918
- */
1919
- start() {
1920
- this.app?.onReady(this.mainWindow);
1921
- return this;
1922
- }
1923
1732
  };
1924
- __name(_NoxApp, "NoxApp");
1925
- var NoxApp = _NoxApp;
1926
- NoxApp = _ts_decorate3([
1927
- Injectable("singleton"),
1928
- _ts_metadata("design:type", Function),
1929
- _ts_metadata("design:paramtypes", [
1930
- typeof Router === "undefined" ? Object : Router,
1931
- typeof NoxSocket === "undefined" ? Object : NoxSocket
1932
- ])
1733
+ __name(NoxApp, "NoxApp");
1734
+ NoxApp = __decorateClass([
1735
+ Injectable({ lifetime: "singleton", deps: [Router, NoxSocket, WindowManager] })
1933
1736
  ], NoxApp);
1934
1737
 
1935
1738
  // src/bootstrap.ts
1936
- var import_main2 = require("electron/main");
1937
- async function bootstrapApplication(rootModule, options) {
1938
- if (rootModule && !getModuleMetadata(rootModule)) {
1939
- throw new Error(`Root module must be decorated with @Module`);
1940
- }
1941
- await import_main2.app.whenReady();
1942
- let mainWindow;
1943
- if (options?.window) {
1944
- mainWindow = new import_main2.BrowserWindow(options.window);
1945
- mainWindow.once("ready-to-show", () => {
1946
- mainWindow?.show();
1947
- });
1948
- const primaryDisplay = import_main2.screen.getPrimaryDisplay();
1949
- const { width, height } = primaryDisplay.workAreaSize;
1950
- if (options.window.minWidth && options.window.minHeight) {
1951
- mainWindow.setSize(Math.min(width, options.window.minWidth), Math.min(height, options.window.minHeight), true);
1739
+ var import_main3 = require("electron/main");
1740
+ init_app_injector();
1741
+ init_injector_explorer();
1742
+ async function bootstrapApplication(config = {}) {
1743
+ await import_main3.app.whenReady();
1744
+ const overrides = /* @__PURE__ */ new Map();
1745
+ for (const { token: token2, useValue } of config.singletons ?? []) {
1746
+ overrides.set(token2, useValue);
1747
+ RootInjector.singletons.set(token2, useValue);
1748
+ }
1749
+ InjectorExplorer.processPending(overrides);
1750
+ const noxApp = inject(NoxApp);
1751
+ if (config.routes?.length) {
1752
+ for (const route of config.routes) {
1753
+ noxApp.lazy(route.path, route.load, route.guards, route.middlewares);
1952
1754
  }
1953
1755
  }
1954
- InjectorExplorer.processPending();
1955
- const noxApp = inject(NoxApp);
1956
- if (mainWindow) {
1957
- noxApp.setMainWindow(mainWindow);
1756
+ if (config.eagerLoad?.length) {
1757
+ await noxApp.load(config.eagerLoad);
1958
1758
  }
1959
1759
  await noxApp.init();
1960
1760
  return noxApp;
1961
1761
  }
1962
1762
  __name(bootstrapApplication, "bootstrapApplication");
1763
+
1764
+ // src/main.ts
1765
+ init_exceptions();
1766
+ init_controller_decorator();
1767
+ init_injectable_decorator();
1768
+ init_method_decorator();
1769
+ init_logger();
1770
+ init_forward_ref();
1771
+ init_request();
1772
+
1773
+ // src/routes.ts
1774
+ function defineRoutes(routes) {
1775
+ const paths = routes.map((r) => r.path.replace(/^\/+|\/+$/g, ""));
1776
+ const duplicates = paths.filter((p, i) => paths.indexOf(p) !== i);
1777
+ if (duplicates.length > 0) {
1778
+ throw new Error(
1779
+ `[Noxus] Duplicate route prefixes detected: ${[...new Set(duplicates)].map((d) => `"${d}"`).join(", ")}`
1780
+ );
1781
+ }
1782
+ return routes.map((r) => ({
1783
+ ...r,
1784
+ path: r.path.replace(/^\/+|\/+$/g, "")
1785
+ }));
1786
+ }
1787
+ __name(defineRoutes, "defineRoutes");
1963
1788
  // Annotate the CommonJS export names for ESM import in node:
1964
1789
  0 && (module.exports = {
1965
1790
  AppInjector,
1966
- Authorize,
1967
1791
  BadGatewayException,
1968
1792
  BadRequestException,
1969
- CONTROLLER_METADATA_KEY,
1970
1793
  ConflictException,
1971
1794
  Controller,
1972
1795
  Delete,
@@ -1975,17 +1798,12 @@ __name(bootstrapApplication, "bootstrapApplication");
1975
1798
  GatewayTimeoutException,
1976
1799
  Get,
1977
1800
  HttpVersionNotSupportedException,
1978
- INJECTABLE_METADATA_KEY,
1979
- INJECT_METADATA_KEY,
1980
- Inject,
1981
1801
  Injectable,
1982
1802
  InsufficientStorageException,
1983
1803
  InternalServerException,
1984
1804
  Logger,
1985
1805
  LoopDetectedException,
1986
- MODULE_METADATA_KEY,
1987
1806
  MethodNotAllowedException,
1988
- Module,
1989
1807
  NetworkAuthenticationRequiredException,
1990
1808
  NetworkConnectTimeoutException,
1991
1809
  NotAcceptableException,
@@ -1999,36 +1817,39 @@ __name(bootstrapApplication, "bootstrapApplication");
1999
1817
  Post,
2000
1818
  Put,
2001
1819
  RENDERER_EVENT_TYPE,
2002
- ROUTE_METADATA_KEY,
2003
1820
  Request,
2004
1821
  RequestTimeoutException,
2005
1822
  ResponseException,
2006
1823
  RootInjector,
2007
1824
  Router,
2008
1825
  ServiceUnavailableException,
1826
+ Token,
2009
1827
  TooManyRequestsException,
2010
1828
  UnauthorizedException,
2011
1829
  UpgradeRequiredException,
2012
- UseMiddlewares,
2013
1830
  VariantAlsoNegotiatesException,
1831
+ WindowManager,
2014
1832
  bootstrapApplication,
2015
1833
  createRendererEventMessage,
1834
+ defineRoutes,
2016
1835
  forwardRef,
2017
1836
  getControllerMetadata,
2018
- getGuardForController,
2019
- getGuardForControllerAction,
2020
- getInjectableMetadata,
2021
- getMiddlewaresForController,
2022
- getMiddlewaresForControllerAction,
2023
- getModuleMetadata,
2024
1837
  getRouteMetadata,
2025
- hasInjectableMetadata,
2026
1838
  inject,
2027
- isRendererEventMessage
1839
+ isAtomicHttpMethod,
1840
+ isRendererEventMessage,
1841
+ token
2028
1842
  });
2029
1843
  /**
2030
1844
  * @copyright 2025 NoxFly
2031
1845
  * @license MIT
2032
1846
  * @author NoxFly
2033
1847
  */
1848
+ /**
1849
+ * @copyright 2025 NoxFly
1850
+ * @license MIT
1851
+ * @author NoxFly
1852
+ *
1853
+ * Entry point for Electron main-process consumers.
1854
+ */
2034
1855
  //# sourceMappingURL=main.js.map