@noxfly/noxus 1.0.4 → 1.1.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.
package/dist/noxus.mjs CHANGED
@@ -1,3 +1,8 @@
1
+ /**
2
+ * @copyright 2025 NoxFly
3
+ * @license MIT
4
+ * @author NoxFly
5
+ */
1
6
  var __defProp = Object.defineProperty;
2
7
  var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
3
8
  var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
@@ -8,8 +13,18 @@ import "reflect-metadata";
8
13
 
9
14
  // src/exceptions.ts
10
15
  var _ResponseException = class _ResponseException extends Error {
11
- constructor(message = "") {
12
- super(message);
16
+ constructor(statusOrMessage, message) {
17
+ let statusCode;
18
+ if (typeof statusOrMessage === "number") {
19
+ statusCode = statusOrMessage;
20
+ } else if (typeof statusOrMessage === "string") {
21
+ message = statusOrMessage;
22
+ }
23
+ super(message ?? "");
24
+ __publicField(this, "status", 0);
25
+ if (statusCode !== void 0) {
26
+ this.status = statusCode;
27
+ }
13
28
  this.name = this.constructor.name.replace(/([A-Z])/g, " $1");
14
29
  }
15
30
  };
@@ -31,6 +46,14 @@ var _UnauthorizedException = class _UnauthorizedException extends ResponseExcept
31
46
  };
32
47
  __name(_UnauthorizedException, "UnauthorizedException");
33
48
  var UnauthorizedException = _UnauthorizedException;
49
+ var _PaymentRequiredException = class _PaymentRequiredException extends ResponseException {
50
+ constructor() {
51
+ super(...arguments);
52
+ __publicField(this, "status", 402);
53
+ }
54
+ };
55
+ __name(_PaymentRequiredException, "PaymentRequiredException");
56
+ var PaymentRequiredException = _PaymentRequiredException;
34
57
  var _ForbiddenException = class _ForbiddenException extends ResponseException {
35
58
  constructor() {
36
59
  super(...arguments);
@@ -193,8 +216,7 @@ __name(_NetworkConnectTimeoutException, "NetworkConnectTimeoutException");
193
216
  var NetworkConnectTimeoutException = _NetworkConnectTimeoutException;
194
217
 
195
218
  // src/DI/app-injector.ts
196
- var _a;
197
- var AppInjector = (_a = class {
219
+ var _AppInjector = class _AppInjector {
198
220
  constructor(name = null) {
199
221
  __publicField(this, "name");
200
222
  __publicField(this, "bindings", /* @__PURE__ */ new Map());
@@ -207,7 +229,7 @@ var AppInjector = (_a = class {
207
229
  * au niveau "scope" (donc durée de vie d'une requête)
208
230
  */
209
231
  createScope() {
210
- const scope = new _a();
232
+ const scope = new _AppInjector();
211
233
  scope.bindings = this.bindings;
212
234
  scope.singletons = this.singletons;
213
235
  return scope;
@@ -218,7 +240,8 @@ var AppInjector = (_a = class {
218
240
  */
219
241
  resolve(target) {
220
242
  const binding = this.bindings.get(target);
221
- if (!binding) throw new InternalServerException(`Failed to resolve a dependency injection : No binding for type ${target.name}`);
243
+ if (!binding) throw new InternalServerException(`Failed to resolve a dependency injection : No binding for type ${target.name}.
244
+ Did you forget to use @Injectable() decorator ?`);
222
245
  switch (binding.lifetime) {
223
246
  case "transient":
224
247
  return this.instantiate(binding.implementation);
@@ -247,8 +270,14 @@ var AppInjector = (_a = class {
247
270
  const params = paramTypes.map((p) => this.resolve(p));
248
271
  return new target(...params);
249
272
  }
250
- }, __name(_a, "AppInjector"), _a);
273
+ };
274
+ __name(_AppInjector, "AppInjector");
275
+ var AppInjector = _AppInjector;
251
276
  var RootInjector = new AppInjector("root");
277
+ function inject(t) {
278
+ return RootInjector.resolve(t);
279
+ }
280
+ __name(inject, "inject");
252
281
 
253
282
  // src/router.ts
254
283
  import "reflect-metadata";
@@ -383,7 +412,7 @@ function Authorize(...guardClasses) {
383
412
  if (authorizations.has(key)) {
384
413
  throw new Error(`Guard(s) already registered for ${key}`);
385
414
  }
386
- Logger.debug(`Registering guards for ${key}: ${guardClasses.map((c) => c.name).join(", ")}`);
415
+ Logger.debug(`Registering guard(s) for ${key}: ${guardClasses.map((c) => c.name).join(", ")}`);
387
416
  authorizations.set(key, guardClasses);
388
417
  };
389
418
  }
@@ -546,9 +575,41 @@ function getControllerMetadata(target) {
546
575
  }
547
576
  __name(getControllerMetadata, "getControllerMetadata");
548
577
 
578
+ // src/decorators/middleware.decorator.ts
579
+ var middlewares = /* @__PURE__ */ new Map();
580
+ function UseMiddlewares(mdlw) {
581
+ return (target, propertyKey) => {
582
+ let key;
583
+ if (propertyKey) {
584
+ const ctrlName = target.constructor.name;
585
+ const actionName = propertyKey;
586
+ key = `${ctrlName}.${actionName}`;
587
+ } else {
588
+ const ctrlName = target.name;
589
+ key = `${ctrlName}`;
590
+ }
591
+ if (middlewares.has(key)) {
592
+ throw new Error(`Middlewares(s) already registered for ${key}`);
593
+ }
594
+ Logger.debug(`Registering middleware(s) for ${key}: ${mdlw.map((c) => c.name).join(", ")}`);
595
+ middlewares.set(key, mdlw);
596
+ };
597
+ }
598
+ __name(UseMiddlewares, "UseMiddlewares");
599
+ function getMiddlewaresForController(controllerName) {
600
+ const key = `${controllerName}`;
601
+ return middlewares.get(key) ?? [];
602
+ }
603
+ __name(getMiddlewaresForController, "getMiddlewaresForController");
604
+ function getMiddlewaresForControllerAction(controllerName, actionName) {
605
+ const key = `${controllerName}.${actionName}`;
606
+ return middlewares.get(key) ?? [];
607
+ }
608
+ __name(getMiddlewaresForControllerAction, "getMiddlewaresForControllerAction");
609
+
549
610
  // src/utils/radix-tree.ts
550
- var _a2;
551
- var RadixNode = (_a2 = class {
611
+ var _a;
612
+ var RadixNode = (_a = class {
552
613
  constructor(segment) {
553
614
  __publicField(this, "segment");
554
615
  __publicField(this, "children", []);
@@ -573,7 +634,7 @@ var RadixNode = (_a2 = class {
573
634
  addChild(node) {
574
635
  this.children.push(node);
575
636
  }
576
- }, __name(_a2, "RadixNode"), _a2);
637
+ }, __name(_a, "RadixNode"), _a);
577
638
  var _RadixTree = class _RadixTree {
578
639
  constructor() {
579
640
  __publicField(this, "root", new RadixNode(""));
@@ -660,19 +721,29 @@ __name(_ts_decorate, "_ts_decorate");
660
721
  var _Router = class _Router {
661
722
  constructor() {
662
723
  __publicField(this, "routes", new RadixTree());
724
+ __publicField(this, "rootMiddlewares", []);
663
725
  }
726
+ /**
727
+ *
728
+ */
664
729
  registerController(controllerClass) {
665
730
  const controllerMeta = getControllerMetadata(controllerClass);
666
731
  const controllerGuards = getGuardForController(controllerClass.name);
732
+ const controllerMiddlewares = getMiddlewaresForController(controllerClass.name);
667
733
  if (!controllerMeta) throw new Error(`Missing @Controller decorator on ${controllerClass.name}`);
668
734
  const routeMetadata = getRouteMetadata(controllerClass);
669
735
  for (const def of routeMetadata) {
670
736
  const fullPath = `${controllerMeta.path}/${def.path}`.replace(/\/+/g, "/");
671
737
  const routeGuards = getGuardForControllerAction(controllerClass.name, def.handler);
738
+ const routeMiddlewares = getMiddlewaresForControllerAction(controllerClass.name, def.handler);
672
739
  const guards = /* @__PURE__ */ new Set([
673
740
  ...controllerGuards,
674
741
  ...routeGuards
675
742
  ]);
743
+ const middlewares2 = /* @__PURE__ */ new Set([
744
+ ...controllerMiddlewares,
745
+ ...routeMiddlewares
746
+ ]);
676
747
  const routeDef = {
677
748
  method: def.method,
678
749
  path: fullPath,
@@ -680,6 +751,9 @@ var _Router = class _Router {
680
751
  handler: def.handler,
681
752
  guards: [
682
753
  ...guards
754
+ ],
755
+ middlewares: [
756
+ ...middlewares2
683
757
  ]
684
758
  };
685
759
  this.routes.insert(fullPath + "/" + def.method, routeDef);
@@ -692,6 +766,17 @@ var _Router = class _Router {
692
766
  Logger.log(`Mapped ${controllerClass.name}${controllerGuardsInfo} controller's routes`);
693
767
  return this;
694
768
  }
769
+ /**
770
+ *
771
+ */
772
+ defineRootMiddleware(middleware) {
773
+ Logger.debug(`Registering root middleware: ${middleware.name}`);
774
+ this.rootMiddlewares.push(middleware);
775
+ return this;
776
+ }
777
+ /**
778
+ *
779
+ */
695
780
  async handle(request) {
696
781
  Logger.log(`> Received request: {${request.method} /${request.path}}`);
697
782
  const t0 = performance.now();
@@ -703,10 +788,10 @@ var _Router = class _Router {
703
788
  };
704
789
  try {
705
790
  const routeDef = this.findRoute(request);
706
- const controllerInstance = await this.resolveController(request, routeDef);
707
- const action = controllerInstance[routeDef.handler];
708
- this.verifyRequestBody(request, action);
709
- response.body = await action.call(controllerInstance, request, response);
791
+ await this.resolveController(request, response, routeDef);
792
+ if (response.status > 400) {
793
+ throw new ResponseException(response.status, response.error);
794
+ }
710
795
  } catch (error) {
711
796
  if (error instanceof ResponseException) {
712
797
  response.status = error.status;
@@ -730,6 +815,9 @@ var _Router = class _Router {
730
815
  return response;
731
816
  }
732
817
  }
818
+ /**
819
+ *
820
+ */
733
821
  findRoute(request) {
734
822
  const matchedRoutes = this.routes.search(request.path);
735
823
  if (matchedRoutes?.node === void 0 || matchedRoutes.node.children.length === 0) {
@@ -741,21 +829,68 @@ var _Router = class _Router {
741
829
  }
742
830
  return routeDef.value;
743
831
  }
744
- async resolveController(request, routeDef) {
832
+ /**
833
+ *
834
+ */
835
+ async resolveController(request, response, routeDef) {
745
836
  const controllerInstance = request.context.resolve(routeDef.controller);
746
837
  Object.assign(request.params, this.extractParams(request.path, routeDef.path));
747
- if (routeDef.guards.length > 0) {
748
- for (const guardType of routeDef.guards) {
749
- const guard = request.context.resolve(guardType);
750
- const allowed = await guard.canActivate(request);
751
- if (!allowed) throw new UnauthorizedException(`Unauthorized for ${request.method} ${request.path}`);
838
+ await this.runRequestPipeline(request, response, routeDef, controllerInstance);
839
+ }
840
+ /**
841
+ *
842
+ */
843
+ async runRequestPipeline(request, response, routeDef, controllerInstance) {
844
+ const middlewares2 = [
845
+ .../* @__PURE__ */ new Set([
846
+ ...this.rootMiddlewares,
847
+ ...routeDef.middlewares
848
+ ])
849
+ ];
850
+ const middlewareMaxIndex = middlewares2.length - 1;
851
+ const guardsMaxIndex = middlewareMaxIndex + routeDef.guards.length;
852
+ let index = -1;
853
+ const dispatch = /* @__PURE__ */ __name(async (i) => {
854
+ if (i <= index) throw new Error("next() called multiple times");
855
+ index = i;
856
+ if (i <= middlewareMaxIndex) {
857
+ const nextFn = dispatch.bind(null, i + 1);
858
+ await this.runMiddleware(request, response, nextFn, middlewares2[i]);
859
+ if (response.status >= 400) {
860
+ throw new ResponseException(response.status, response.error);
861
+ }
862
+ return;
752
863
  }
753
- }
754
- return controllerInstance;
864
+ if (i <= guardsMaxIndex) {
865
+ const guardIndex = i - middlewares2.length;
866
+ const guardType = routeDef.guards[guardIndex];
867
+ await this.runGuard(request, guardType);
868
+ dispatch(i + 1);
869
+ return;
870
+ }
871
+ const action = controllerInstance[routeDef.handler];
872
+ response.body = await action.call(controllerInstance, request, response);
873
+ }, "dispatch");
874
+ await dispatch(0);
875
+ }
876
+ /**
877
+ *
878
+ */
879
+ async runMiddleware(request, response, next, middlewareType) {
880
+ const middleware = request.context.resolve(middlewareType);
881
+ await middleware.invoke(request, response, next);
755
882
  }
756
- verifyRequestBody(request, action) {
757
- const requiredParams = Reflect.getMetadata("design:paramtypes", action) || [];
883
+ /**
884
+ *
885
+ */
886
+ async runGuard(request, guardType) {
887
+ const guard = request.context.resolve(guardType);
888
+ const allowed = await guard.canActivate(request);
889
+ if (!allowed) throw new UnauthorizedException(`Unauthorized for ${request.method} ${request.path}`);
758
890
  }
891
+ /**
892
+ *
893
+ */
759
894
  extractParams(actual, template) {
760
895
  const aParts = actual.split("/");
761
896
  const tParts = template.split("/");
@@ -774,15 +909,13 @@ Router = _ts_decorate([
774
909
  Injectable("singleton")
775
910
  ], Router);
776
911
 
777
- // src/bootstrap.ts
778
- import { ipcMain } from "electron";
779
- import { app, BrowserWindow, MessageChannelMain } from "electron/main";
912
+ // src/app.ts
913
+ import { app, BrowserWindow, ipcMain, MessageChannelMain } from "electron/main";
780
914
 
781
915
  // src/request.ts
782
916
  import "reflect-metadata";
783
917
  var _Request = class _Request {
784
- constructor(app2, event, id, method, path, body) {
785
- __publicField(this, "app");
918
+ constructor(event, id, method, path, body) {
786
919
  __publicField(this, "event");
787
920
  __publicField(this, "id");
788
921
  __publicField(this, "method");
@@ -790,7 +923,6 @@ var _Request = class _Request {
790
923
  __publicField(this, "body");
791
924
  __publicField(this, "context", RootInjector.createScope());
792
925
  __publicField(this, "params", {});
793
- this.app = app2;
794
926
  this.event = event;
795
927
  this.id = id;
796
928
  this.method = method;
@@ -802,69 +934,68 @@ var _Request = class _Request {
802
934
  __name(_Request, "Request");
803
935
  var Request = _Request;
804
936
 
805
- // src/bootstrap.ts
806
- async function bootstrapApplication(root, rootModule) {
807
- if (!getModuleMetadata(rootModule)) {
808
- throw new Error(`Root module must be decorated with @Module`);
809
- }
810
- if (!getInjectableMetadata(root)) {
811
- throw new Error(`Root application must be decorated with @Injectable`);
812
- }
813
- await app.whenReady();
814
- RootInjector.resolve(Router);
815
- const noxEngine = new Nox(root, rootModule);
816
- const application = await noxEngine.init();
817
- return application;
937
+ // src/app.ts
938
+ function _ts_decorate2(decorators, target, key, desc) {
939
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
940
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
941
+ 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;
942
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
818
943
  }
819
- __name(bootstrapApplication, "bootstrapApplication");
820
- var _a3;
821
- var Nox = (_a3 = class {
822
- constructor(root, rootModule) {
823
- __publicField(this, "root");
824
- __publicField(this, "rootModule");
825
- __publicField(this, "messagePort");
826
- this.root = root;
827
- this.rootModule = rootModule;
944
+ __name(_ts_decorate2, "_ts_decorate");
945
+ function _ts_metadata(k, v) {
946
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
947
+ }
948
+ __name(_ts_metadata, "_ts_metadata");
949
+ var _NoxApp = class _NoxApp {
950
+ constructor(router) {
951
+ __publicField(this, "router");
952
+ __publicField(this, "messagePorts", /* @__PURE__ */ new Map());
953
+ __publicField(this, "app");
954
+ this.router = router;
828
955
  }
829
956
  /**
830
957
  *
831
958
  */
832
959
  async init() {
833
- const application = RootInjector.resolve(this.root);
834
- ipcMain.on("gimme-my-port", this.giveTheClientAPort.bind(this, application));
835
- app.once("activate", this.onAppActivated.bind(this, application));
836
- app.once("window-all-closed", this.onAllWindowsClosed.bind(this, application));
837
- await application.onReady();
960
+ ipcMain.on("gimme-my-port", this.giveTheRendererAPort.bind(this));
961
+ app.once("activate", this.onAppActivated.bind(this));
962
+ app.once("window-all-closed", this.onAllWindowsClosed.bind(this));
838
963
  console.log("");
839
- return application;
964
+ return this;
840
965
  }
841
966
  /**
842
967
  *
843
968
  */
844
- giveTheClientAPort(application, event) {
845
- if (this.messagePort) {
846
- this.messagePort.port1.close();
847
- this.messagePort.port2.close();
848
- this.messagePort = void 0;
969
+ giveTheRendererAPort(event) {
970
+ const senderId = event.sender.id;
971
+ if (this.messagePorts.has(senderId)) {
972
+ this.shutdownChannel(senderId);
849
973
  }
850
- this.messagePort = new MessageChannelMain();
851
- this.messagePort.port1.on("message", (event2) => this.onClientMessage(application, event2));
852
- this.messagePort.port1.start();
853
- event.sender.postMessage("port", null, [
854
- this.messagePort.port2
974
+ const channel = new MessageChannelMain();
975
+ this.messagePorts.set(senderId, channel);
976
+ channel.port1.on("message", this.onRendererMessage.bind(this));
977
+ channel.port1.start();
978
+ event.sender.postMessage("port", {
979
+ senderId
980
+ }, [
981
+ channel.port2
855
982
  ]);
856
983
  }
857
984
  /**
858
985
  * Electron specific message handling.
859
986
  * Replaces HTTP calls by using Electron's IPC mechanism.
860
987
  */
861
- async onClientMessage(application, event) {
862
- const { requestId, path, method, body } = event.data;
988
+ async onRendererMessage(event) {
989
+ const { senderId, requestId, path, method, body } = event.data;
990
+ const channel = this.messagePorts.get(senderId);
991
+ if (!channel) {
992
+ Logger.error(`No message channel found for sender ID: ${senderId}`);
993
+ return;
994
+ }
863
995
  try {
864
- const request = new Request(application, event, requestId, method, path, body);
865
- const router = RootInjector.resolve(Router);
866
- const response = await router.handle(request);
867
- this.messagePort?.port1.postMessage(response);
996
+ const request = new Request(event, requestId, method, path, body);
997
+ const response = await this.router.handle(request);
998
+ channel.port1.postMessage(response);
868
999
  } catch (err) {
869
1000
  const response = {
870
1001
  requestId,
@@ -872,29 +1003,82 @@ var Nox = (_a3 = class {
872
1003
  body: null,
873
1004
  error: err.message || "Internal Server Error"
874
1005
  };
875
- this.messagePort?.port1.postMessage(response);
1006
+ channel.port1.postMessage(response);
876
1007
  }
877
1008
  }
878
1009
  /**
879
- *
1010
+ * MacOS specific behavior.
880
1011
  */
881
- onAppActivated(application) {
882
- if (BrowserWindow.getAllWindows().length === 0) {
883
- application.onReady();
1012
+ onAppActivated() {
1013
+ if (process.platform === "darwin" && BrowserWindow.getAllWindows().length === 0) {
1014
+ this.app?.onActivated();
884
1015
  }
885
1016
  }
1017
+ shutdownChannel(channelSenderId, remove = true) {
1018
+ const channel = this.messagePorts.get(channelSenderId);
1019
+ if (!channel) {
1020
+ Logger.warn(`No message channel found for sender ID: ${channelSenderId}`);
1021
+ return;
1022
+ }
1023
+ channel.port1.off("message", this.onRendererMessage.bind(this));
1024
+ channel.port1.close();
1025
+ channel.port2.close();
1026
+ this.messagePorts.delete(channelSenderId);
1027
+ }
886
1028
  /**
887
1029
  *
888
1030
  */
889
- async onAllWindowsClosed(application) {
890
- this.messagePort?.port1.close();
891
- await application.dispose();
1031
+ async onAllWindowsClosed() {
1032
+ this.messagePorts.forEach((channel, senderId) => {
1033
+ this.shutdownChannel(senderId, false);
1034
+ });
1035
+ this.messagePorts.clear();
1036
+ this.app?.dispose();
892
1037
  if (process.platform !== "darwin") {
893
1038
  app.quit();
894
1039
  }
895
1040
  }
896
- }, __name(_a3, "Nox"), _a3);
1041
+ // ---
1042
+ configure(app3) {
1043
+ this.app = inject(app3);
1044
+ return this;
1045
+ }
1046
+ use(middleware) {
1047
+ this.router.defineRootMiddleware(middleware);
1048
+ return this;
1049
+ }
1050
+ /**
1051
+ * Should be called after the bootstrapApplication function is called.
1052
+ */
1053
+ start() {
1054
+ this.app?.onReady();
1055
+ return this;
1056
+ }
1057
+ };
1058
+ __name(_NoxApp, "NoxApp");
1059
+ var NoxApp = _NoxApp;
1060
+ NoxApp = _ts_decorate2([
1061
+ Injectable("singleton"),
1062
+ _ts_metadata("design:type", Function),
1063
+ _ts_metadata("design:paramtypes", [
1064
+ typeof Router === "undefined" ? Object : Router
1065
+ ])
1066
+ ], NoxApp);
1067
+
1068
+ // src/bootstrap.ts
1069
+ import { app as app2 } from "electron/main";
1070
+ async function bootstrapApplication(rootModule) {
1071
+ if (!getModuleMetadata(rootModule)) {
1072
+ throw new Error(`Root module must be decorated with @Module`);
1073
+ }
1074
+ await app2.whenReady();
1075
+ const noxApp = inject(NoxApp);
1076
+ await noxApp.init();
1077
+ return noxApp;
1078
+ }
1079
+ __name(bootstrapApplication, "bootstrapApplication");
897
1080
  export {
1081
+ AppInjector,
898
1082
  Authorize,
899
1083
  BadGatewayException,
900
1084
  BadRequestException,
@@ -921,7 +1105,9 @@ export {
921
1105
  NotExtendedException,
922
1106
  NotFoundException,
923
1107
  NotImplementedException,
1108
+ NoxApp,
924
1109
  Patch,
1110
+ PaymentRequiredException,
925
1111
  Post,
926
1112
  Put,
927
1113
  ROUTE_METADATA_KEY,
@@ -934,13 +1120,22 @@ export {
934
1120
  TooManyRequestsException,
935
1121
  UnauthorizedException,
936
1122
  UpgradeRequiredException,
1123
+ UseMiddlewares,
937
1124
  VariantAlsoNegotiatesException,
938
1125
  bootstrapApplication,
939
1126
  getControllerMetadata,
940
1127
  getGuardForController,
941
1128
  getGuardForControllerAction,
942
1129
  getInjectableMetadata,
1130
+ getMiddlewaresForController,
1131
+ getMiddlewaresForControllerAction,
943
1132
  getModuleMetadata,
944
- getRouteMetadata
1133
+ getRouteMetadata,
1134
+ inject
945
1135
  };
1136
+ /**
1137
+ * @copyright 2025 NoxFly
1138
+ * @license MIT
1139
+ * @author NoxFly
1140
+ */
946
1141
  //# sourceMappingURL=noxus.mjs.map