@noxfly/noxus 1.0.5 → 1.1.1

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
@@ -13,8 +13,18 @@ import "reflect-metadata";
13
13
 
14
14
  // src/exceptions.ts
15
15
  var _ResponseException = class _ResponseException extends Error {
16
- constructor(message = "") {
17
- 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
+ }
18
28
  this.name = this.constructor.name.replace(/([A-Z])/g, " $1");
19
29
  }
20
30
  };
@@ -206,8 +216,7 @@ __name(_NetworkConnectTimeoutException, "NetworkConnectTimeoutException");
206
216
  var NetworkConnectTimeoutException = _NetworkConnectTimeoutException;
207
217
 
208
218
  // src/DI/app-injector.ts
209
- var _a;
210
- var AppInjector = (_a = class {
219
+ var _AppInjector = class _AppInjector {
211
220
  constructor(name = null) {
212
221
  __publicField(this, "name");
213
222
  __publicField(this, "bindings", /* @__PURE__ */ new Map());
@@ -220,7 +229,7 @@ var AppInjector = (_a = class {
220
229
  * au niveau "scope" (donc durée de vie d'une requête)
221
230
  */
222
231
  createScope() {
223
- const scope = new _a();
232
+ const scope = new _AppInjector();
224
233
  scope.bindings = this.bindings;
225
234
  scope.singletons = this.singletons;
226
235
  return scope;
@@ -231,7 +240,8 @@ var AppInjector = (_a = class {
231
240
  */
232
241
  resolve(target) {
233
242
  const binding = this.bindings.get(target);
234
- 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 ?`);
235
245
  switch (binding.lifetime) {
236
246
  case "transient":
237
247
  return this.instantiate(binding.implementation);
@@ -260,7 +270,9 @@ var AppInjector = (_a = class {
260
270
  const params = paramTypes.map((p) => this.resolve(p));
261
271
  return new target(...params);
262
272
  }
263
- }, __name(_a, "AppInjector"), _a);
273
+ };
274
+ __name(_AppInjector, "AppInjector");
275
+ var AppInjector = _AppInjector;
264
276
  var RootInjector = new AppInjector("root");
265
277
  function inject(t) {
266
278
  return RootInjector.resolve(t);
@@ -400,7 +412,7 @@ function Authorize(...guardClasses) {
400
412
  if (authorizations.has(key)) {
401
413
  throw new Error(`Guard(s) already registered for ${key}`);
402
414
  }
403
- 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(", ")}`);
404
416
  authorizations.set(key, guardClasses);
405
417
  };
406
418
  }
@@ -563,9 +575,41 @@ function getControllerMetadata(target) {
563
575
  }
564
576
  __name(getControllerMetadata, "getControllerMetadata");
565
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
+
566
610
  // src/utils/radix-tree.ts
567
- var _a2;
568
- var RadixNode = (_a2 = class {
611
+ var _a;
612
+ var RadixNode = (_a = class {
569
613
  constructor(segment) {
570
614
  __publicField(this, "segment");
571
615
  __publicField(this, "children", []);
@@ -590,7 +634,7 @@ var RadixNode = (_a2 = class {
590
634
  addChild(node) {
591
635
  this.children.push(node);
592
636
  }
593
- }, __name(_a2, "RadixNode"), _a2);
637
+ }, __name(_a, "RadixNode"), _a);
594
638
  var _RadixTree = class _RadixTree {
595
639
  constructor() {
596
640
  __publicField(this, "root", new RadixNode(""));
@@ -677,19 +721,29 @@ __name(_ts_decorate, "_ts_decorate");
677
721
  var _Router = class _Router {
678
722
  constructor() {
679
723
  __publicField(this, "routes", new RadixTree());
724
+ __publicField(this, "rootMiddlewares", []);
680
725
  }
726
+ /**
727
+ *
728
+ */
681
729
  registerController(controllerClass) {
682
730
  const controllerMeta = getControllerMetadata(controllerClass);
683
731
  const controllerGuards = getGuardForController(controllerClass.name);
732
+ const controllerMiddlewares = getMiddlewaresForController(controllerClass.name);
684
733
  if (!controllerMeta) throw new Error(`Missing @Controller decorator on ${controllerClass.name}`);
685
734
  const routeMetadata = getRouteMetadata(controllerClass);
686
735
  for (const def of routeMetadata) {
687
736
  const fullPath = `${controllerMeta.path}/${def.path}`.replace(/\/+/g, "/");
688
737
  const routeGuards = getGuardForControllerAction(controllerClass.name, def.handler);
738
+ const routeMiddlewares = getMiddlewaresForControllerAction(controllerClass.name, def.handler);
689
739
  const guards = /* @__PURE__ */ new Set([
690
740
  ...controllerGuards,
691
741
  ...routeGuards
692
742
  ]);
743
+ const middlewares2 = /* @__PURE__ */ new Set([
744
+ ...controllerMiddlewares,
745
+ ...routeMiddlewares
746
+ ]);
693
747
  const routeDef = {
694
748
  method: def.method,
695
749
  path: fullPath,
@@ -697,6 +751,9 @@ var _Router = class _Router {
697
751
  handler: def.handler,
698
752
  guards: [
699
753
  ...guards
754
+ ],
755
+ middlewares: [
756
+ ...middlewares2
700
757
  ]
701
758
  };
702
759
  this.routes.insert(fullPath + "/" + def.method, routeDef);
@@ -709,6 +766,17 @@ var _Router = class _Router {
709
766
  Logger.log(`Mapped ${controllerClass.name}${controllerGuardsInfo} controller's routes`);
710
767
  return this;
711
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
+ */
712
780
  async handle(request) {
713
781
  Logger.log(`> Received request: {${request.method} /${request.path}}`);
714
782
  const t0 = performance.now();
@@ -720,10 +788,10 @@ var _Router = class _Router {
720
788
  };
721
789
  try {
722
790
  const routeDef = this.findRoute(request);
723
- const controllerInstance = await this.resolveController(request, routeDef);
724
- const action = controllerInstance[routeDef.handler];
725
- this.verifyRequestBody(request, action);
726
- 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
+ }
727
795
  } catch (error) {
728
796
  if (error instanceof ResponseException) {
729
797
  response.status = error.status;
@@ -747,6 +815,9 @@ var _Router = class _Router {
747
815
  return response;
748
816
  }
749
817
  }
818
+ /**
819
+ *
820
+ */
750
821
  findRoute(request) {
751
822
  const matchedRoutes = this.routes.search(request.path);
752
823
  if (matchedRoutes?.node === void 0 || matchedRoutes.node.children.length === 0) {
@@ -758,21 +829,68 @@ var _Router = class _Router {
758
829
  }
759
830
  return routeDef.value;
760
831
  }
761
- async resolveController(request, routeDef) {
832
+ /**
833
+ *
834
+ */
835
+ async resolveController(request, response, routeDef) {
762
836
  const controllerInstance = request.context.resolve(routeDef.controller);
763
837
  Object.assign(request.params, this.extractParams(request.path, routeDef.path));
764
- if (routeDef.guards.length > 0) {
765
- for (const guardType of routeDef.guards) {
766
- const guard = request.context.resolve(guardType);
767
- const allowed = await guard.canActivate(request);
768
- 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;
769
863
  }
770
- }
771
- 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);
772
875
  }
773
- verifyRequestBody(request, action) {
774
- const requiredParams = Reflect.getMetadata("design:paramtypes", action) || [];
876
+ /**
877
+ *
878
+ */
879
+ async runMiddleware(request, response, next, middlewareType) {
880
+ const middleware = request.context.resolve(middlewareType);
881
+ await middleware.invoke(request, response, next);
882
+ }
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}`);
775
890
  }
891
+ /**
892
+ *
893
+ */
776
894
  extractParams(actual, template) {
777
895
  const aParts = actual.split("/");
778
896
  const tParts = template.split("/");
@@ -836,7 +954,7 @@ var _NoxApp = class _NoxApp {
836
954
  this.router = router;
837
955
  }
838
956
  /**
839
- *
957
+ *
840
958
  */
841
959
  async init() {
842
960
  ipcMain.on("gimme-my-port", this.giveTheRendererAPort.bind(this));
@@ -846,7 +964,7 @@ var _NoxApp = class _NoxApp {
846
964
  return this;
847
965
  }
848
966
  /**
849
- *
967
+ *
850
968
  */
851
969
  giveTheRendererAPort(event) {
852
970
  const senderId = event.sender.id;
@@ -908,7 +1026,7 @@ var _NoxApp = class _NoxApp {
908
1026
  this.messagePorts.delete(channelSenderId);
909
1027
  }
910
1028
  /**
911
- *
1029
+ *
912
1030
  */
913
1031
  async onAllWindowsClosed() {
914
1032
  this.messagePorts.forEach((channel, senderId) => {
@@ -925,6 +1043,10 @@ var _NoxApp = class _NoxApp {
925
1043
  this.app = inject(app3);
926
1044
  return this;
927
1045
  }
1046
+ use(middleware) {
1047
+ this.router.defineRootMiddleware(middleware);
1048
+ return this;
1049
+ }
928
1050
  /**
929
1051
  * Should be called after the bootstrapApplication function is called.
930
1052
  */
@@ -956,6 +1078,7 @@ async function bootstrapApplication(rootModule) {
956
1078
  }
957
1079
  __name(bootstrapApplication, "bootstrapApplication");
958
1080
  export {
1081
+ AppInjector,
959
1082
  Authorize,
960
1083
  BadGatewayException,
961
1084
  BadRequestException,
@@ -997,12 +1120,15 @@ export {
997
1120
  TooManyRequestsException,
998
1121
  UnauthorizedException,
999
1122
  UpgradeRequiredException,
1123
+ UseMiddlewares,
1000
1124
  VariantAlsoNegotiatesException,
1001
1125
  bootstrapApplication,
1002
1126
  getControllerMetadata,
1003
1127
  getGuardForController,
1004
1128
  getGuardForControllerAction,
1005
1129
  getInjectableMetadata,
1130
+ getMiddlewaresForController,
1131
+ getMiddlewaresForControllerAction,
1006
1132
  getModuleMetadata,
1007
1133
  getRouteMetadata,
1008
1134
  inject