@noxfly/noxus 1.2.0 → 2.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/main.js CHANGED
@@ -4,9 +4,11 @@
4
4
  * @author NoxFly
5
5
  */
6
6
  "use strict";
7
+ var __create = Object.create;
7
8
  var __defProp = Object.defineProperty;
8
9
  var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
9
10
  var __getOwnPropNames = Object.getOwnPropertyNames;
11
+ var __getProtoOf = Object.getPrototypeOf;
10
12
  var __hasOwnProp = Object.prototype.hasOwnProperty;
11
13
  var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
12
14
  var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
@@ -22,6 +24,14 @@ var __copyProps = (to, from, except, desc) => {
22
24
  }
23
25
  return to;
24
26
  };
27
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
28
+ // If the importer is in node compatibility mode or this is not an ESM
29
+ // file that has been converted to a CommonJS file using a Babel-
30
+ // compatible transform (i.e. "__esModule" has not been set), then set
31
+ // "default" to the CommonJS "module.exports" for node compatibility.
32
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
33
+ mod
34
+ ));
25
35
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
26
36
  var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
27
37
 
@@ -56,6 +66,7 @@ __export(main_exports, {
56
66
  NotFoundException: () => NotFoundException,
57
67
  NotImplementedException: () => NotImplementedException,
58
68
  NoxApp: () => NoxApp,
69
+ NoxRendererClient: () => NoxRendererClient,
59
70
  NoxSocket: () => NoxSocket,
60
71
  Patch: () => Patch,
61
72
  PaymentRequiredException: () => PaymentRequiredException,
@@ -77,6 +88,7 @@ __export(main_exports, {
77
88
  VariantAlsoNegotiatesException: () => VariantAlsoNegotiatesException,
78
89
  bootstrapApplication: () => bootstrapApplication,
79
90
  createRendererEventMessage: () => createRendererEventMessage,
91
+ exposeNoxusBridge: () => exposeNoxusBridge,
80
92
  getControllerMetadata: () => getControllerMetadata,
81
93
  getGuardForController: () => getGuardForController,
82
94
  getGuardForControllerAction: () => getGuardForControllerAction,
@@ -85,6 +97,7 @@ __export(main_exports, {
85
97
  getMiddlewaresForControllerAction: () => getMiddlewaresForControllerAction,
86
98
  getModuleMetadata: () => getModuleMetadata,
87
99
  getRouteMetadata: () => getRouteMetadata,
100
+ hasInjectableMetadata: () => hasInjectableMetadata,
88
101
  inject: () => inject,
89
102
  isRendererEventMessage: () => isRendererEventMessage
90
103
  });
@@ -397,14 +410,29 @@ function getGuardForControllerAction(controllerName, actionName) {
397
410
  __name(getGuardForControllerAction, "getGuardForControllerAction");
398
411
  var authorizations = /* @__PURE__ */ new Map();
399
412
 
413
+ // src/decorators/injectable.metadata.ts
414
+ var INJECTABLE_METADATA_KEY = Symbol("INJECTABLE_METADATA_KEY");
415
+ function defineInjectableMetadata(target, lifetime) {
416
+ Reflect.defineMetadata(INJECTABLE_METADATA_KEY, lifetime, target);
417
+ }
418
+ __name(defineInjectableMetadata, "defineInjectableMetadata");
419
+ function getInjectableMetadata(target) {
420
+ return Reflect.getMetadata(INJECTABLE_METADATA_KEY, target);
421
+ }
422
+ __name(getInjectableMetadata, "getInjectableMetadata");
423
+ function hasInjectableMetadata(target) {
424
+ return Reflect.hasMetadata(INJECTABLE_METADATA_KEY, target);
425
+ }
426
+ __name(hasInjectableMetadata, "hasInjectableMetadata");
427
+
400
428
  // src/decorators/method.decorator.ts
401
429
  function createRouteDecorator(verb) {
402
- return (path) => {
430
+ return (path2) => {
403
431
  return (target, propertyKey) => {
404
432
  const existingRoutes = Reflect.getMetadata(ROUTE_METADATA_KEY, target.constructor) || [];
405
433
  const metadata = {
406
434
  method: verb,
407
- path: path.trim().replace(/^\/|\/$/g, ""),
435
+ path: path2.trim().replace(/^\/|\/$/g, ""),
408
436
  handler: propertyKey,
409
437
  guards: getGuardForControllerAction(target.constructor.__controllerName, propertyKey)
410
438
  };
@@ -468,6 +496,8 @@ __name(getModuleMetadata, "getModuleMetadata");
468
496
  var MODULE_METADATA_KEY = Symbol("MODULE_METADATA_KEY");
469
497
 
470
498
  // src/utils/logger.ts
499
+ var fs = __toESM(require("fs"));
500
+ var path = __toESM(require("path"));
471
501
  function getPrettyTimestamp() {
472
502
  const now = /* @__PURE__ */ new Date();
473
503
  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")}`;
@@ -476,21 +506,41 @@ __name(getPrettyTimestamp, "getPrettyTimestamp");
476
506
  function getLogPrefix(callee, messageType, color) {
477
507
  const timestamp = getPrettyTimestamp();
478
508
  const spaces = " ".repeat(10 - messageType.length);
479
- return `${color}[APP] ${process.pid} - ${Logger.colors.initial}${timestamp}${spaces}${color}${messageType.toUpperCase()}${Logger.colors.initial} ${Logger.colors.yellow}[${callee}]${Logger.colors.initial}`;
509
+ let colReset = Logger.colors.initial;
510
+ let colCallee = Logger.colors.yellow;
511
+ if (color === void 0) {
512
+ color = "";
513
+ colReset = "";
514
+ colCallee = "";
515
+ }
516
+ return `${color}[APP] ${process.pid} - ${colReset}${timestamp}${spaces}${color}${messageType.toUpperCase()}${colReset} ${colCallee}[${callee}]${colReset}`;
480
517
  }
481
518
  __name(getLogPrefix, "getLogPrefix");
482
- function formatObject(prefix, arg) {
519
+ function formatObject(prefix, arg, enableColor = true) {
483
520
  const json = JSON.stringify(arg, null, 2);
484
- const prefixedJson = json.split("\n").map((line, idx) => idx === 0 ? `${Logger.colors.darkGrey}${line}` : `${prefix} ${Logger.colors.grey}${line}`).join("\n") + Logger.colors.initial;
521
+ let colStart = "";
522
+ let colLine = "";
523
+ let colReset = "";
524
+ if (enableColor) {
525
+ colStart = Logger.colors.darkGrey;
526
+ colLine = Logger.colors.grey;
527
+ colReset = Logger.colors.initial;
528
+ }
529
+ const prefixedJson = json.split("\n").map((line, idx) => idx === 0 ? `${colStart}${line}` : `${prefix} ${colLine}${line}`).join("\n") + colReset;
485
530
  return prefixedJson;
486
531
  }
487
532
  __name(formatObject, "formatObject");
488
533
  function formattedArgs(prefix, args, color) {
534
+ let colReset = Logger.colors.initial;
535
+ if (color === void 0) {
536
+ color = "";
537
+ colReset = "";
538
+ }
489
539
  return args.map((arg) => {
490
540
  if (typeof arg === "string") {
491
- return `${color}${arg}${Logger.colors.initial}`;
541
+ return `${color}${arg}${colReset}`;
492
542
  } else if (typeof arg === "object") {
493
- return formatObject(prefix, arg);
543
+ return formatObject(prefix, arg, color === "");
494
544
  }
495
545
  return arg;
496
546
  });
@@ -503,80 +553,163 @@ function getCallee() {
503
553
  }
504
554
  __name(getCallee, "getCallee");
505
555
  function canLog(level) {
506
- return logLevelRank[level] >= logLevelRank[logLevel];
556
+ return logLevels.has(level);
507
557
  }
508
558
  __name(canLog, "canLog");
509
- var logLevel = "debug";
510
- var logLevelRank = {
511
- debug: 0,
512
- comment: 1,
513
- log: 2,
514
- info: 3,
515
- warn: 4,
516
- error: 5
517
- };
559
+ function processLogQueue(filepath) {
560
+ const state = fileStates.get(filepath);
561
+ if (!state || state.isWriting || state.queue.length === 0) {
562
+ return;
563
+ }
564
+ state.isWriting = true;
565
+ const messagesToWrite = state.queue.join("\n") + "\n";
566
+ state.queue = [];
567
+ const dir = path.dirname(filepath);
568
+ fs.mkdir(dir, {
569
+ recursive: true
570
+ }, (err) => {
571
+ if (err) {
572
+ console.error(`[Logger] Failed to create directory ${dir}`, err);
573
+ state.isWriting = false;
574
+ return;
575
+ }
576
+ fs.appendFile(filepath, messagesToWrite, {
577
+ encoding: "utf-8"
578
+ }, (err2) => {
579
+ state.isWriting = false;
580
+ if (err2) {
581
+ console.error(`[Logger] Failed to write log to ${filepath}`, err2);
582
+ }
583
+ if (state.queue.length > 0) {
584
+ processLogQueue(filepath);
585
+ }
586
+ });
587
+ });
588
+ }
589
+ __name(processLogQueue, "processLogQueue");
590
+ function enqueue(filepath, message) {
591
+ if (!fileStates.has(filepath)) {
592
+ fileStates.set(filepath, {
593
+ queue: [],
594
+ isWriting: false
595
+ });
596
+ }
597
+ const state = fileStates.get(filepath);
598
+ state.queue.push(message);
599
+ processLogQueue(filepath);
600
+ }
601
+ __name(enqueue, "enqueue");
602
+ function output(level, args) {
603
+ if (!canLog(level)) {
604
+ return;
605
+ }
606
+ const callee = getCallee();
607
+ {
608
+ const prefix = getLogPrefix(callee, level, logLevelColors[level]);
609
+ const data = formattedArgs(prefix, args, logLevelColors[level]);
610
+ logLevelChannel[level](prefix, ...data);
611
+ }
612
+ {
613
+ const prefix = getLogPrefix(callee, level);
614
+ const data = formattedArgs(prefix, args);
615
+ const filepath = fileSettings.get(level)?.filepath;
616
+ if (filepath) {
617
+ const message = prefix + " " + data.join(" ");
618
+ enqueue(filepath, message);
619
+ }
620
+ }
621
+ }
622
+ __name(output, "output");
518
623
  (function(Logger2) {
519
624
  function setLogLevel(level) {
520
- logLevel = level;
625
+ logLevels.clear();
626
+ if (Array.isArray(level)) {
627
+ for (const lvl of level) {
628
+ logLevels.add(lvl);
629
+ }
630
+ } else {
631
+ const targetRank = logLevelRank[level];
632
+ for (const [lvl, rank] of Object.entries(logLevelRank)) {
633
+ if (rank >= targetRank) {
634
+ logLevels.add(lvl);
635
+ }
636
+ }
637
+ }
521
638
  }
522
639
  __name(setLogLevel, "setLogLevel");
523
640
  Logger2.setLogLevel = setLogLevel;
524
641
  function log(...args) {
525
- if (!canLog("log")) return;
526
- const callee = getCallee();
527
- const prefix = getLogPrefix(callee, "log", Logger2.colors.green);
528
- console.log(prefix, ...formattedArgs(prefix, args, Logger2.colors.green));
642
+ output("log", args);
529
643
  }
530
644
  __name(log, "log");
531
645
  Logger2.log = log;
532
646
  function info(...args) {
533
- if (!canLog("info")) return;
534
- const callee = getCallee();
535
- const prefix = getLogPrefix(callee, "info", Logger2.colors.blue);
536
- console.info(prefix, ...formattedArgs(prefix, args, Logger2.colors.blue));
647
+ output("info", args);
537
648
  }
538
649
  __name(info, "info");
539
650
  Logger2.info = info;
540
651
  function warn(...args) {
541
- if (!canLog("warn")) return;
542
- const callee = getCallee();
543
- const prefix = getLogPrefix(callee, "warn", Logger2.colors.brown);
544
- console.warn(prefix, ...formattedArgs(prefix, args, Logger2.colors.brown));
652
+ output("warn", args);
545
653
  }
546
654
  __name(warn, "warn");
547
655
  Logger2.warn = warn;
548
656
  function error(...args) {
549
- if (!canLog("error")) return;
550
- const callee = getCallee();
551
- const prefix = getLogPrefix(callee, "error", Logger2.colors.red);
552
- console.error(prefix, ...formattedArgs(prefix, args, Logger2.colors.red));
657
+ output("error", args);
553
658
  }
554
659
  __name(error, "error");
555
660
  Logger2.error = error;
556
661
  function errorStack(...args) {
557
- if (!canLog("error")) return;
558
- const callee = getCallee();
559
- const prefix = getLogPrefix(callee, "error", Logger2.colors.grey);
560
- console.error(prefix, ...formattedArgs(prefix, args, Logger2.colors.grey));
662
+ output("error", args);
561
663
  }
562
664
  __name(errorStack, "errorStack");
563
665
  Logger2.errorStack = errorStack;
564
666
  function debug(...args) {
565
- if (!canLog("debug")) return;
566
- const callee = getCallee();
567
- const prefix = getLogPrefix(callee, "debug", Logger2.colors.purple);
568
- console.debug(prefix, ...formattedArgs(prefix, args, Logger2.colors.purple));
667
+ output("debug", args);
569
668
  }
570
669
  __name(debug, "debug");
571
670
  Logger2.debug = debug;
572
671
  function comment(...args) {
573
- if (!canLog("comment")) return;
574
- const callee = getCallee();
575
- const prefix = getLogPrefix(callee, "comment", Logger2.colors.grey);
576
- console.debug(prefix, ...formattedArgs(prefix, args, Logger2.colors.grey));
672
+ output("comment", args);
577
673
  }
578
674
  __name(comment, "comment");
579
675
  Logger2.comment = comment;
676
+ function critical(...args) {
677
+ output("critical", args);
678
+ }
679
+ __name(critical, "critical");
680
+ Logger2.critical = critical;
681
+ function enableFileLogging(filepath, levels = [
682
+ "debug",
683
+ "comment",
684
+ "log",
685
+ "info",
686
+ "warn",
687
+ "error",
688
+ "critical"
689
+ ]) {
690
+ for (const level of levels) {
691
+ fileSettings.set(level, {
692
+ filepath
693
+ });
694
+ }
695
+ }
696
+ __name(enableFileLogging, "enableFileLogging");
697
+ Logger2.enableFileLogging = enableFileLogging;
698
+ function disableFileLogging(levels = [
699
+ "debug",
700
+ "comment",
701
+ "log",
702
+ "info",
703
+ "warn",
704
+ "error",
705
+ "critical"
706
+ ]) {
707
+ for (const level of levels) {
708
+ fileSettings.delete(level);
709
+ }
710
+ }
711
+ __name(disableFileLogging, "disableFileLogging");
712
+ Logger2.disableFileLogging = disableFileLogging;
580
713
  Logger2.colors = {
581
714
  black: "\x1B[0;30m",
582
715
  grey: "\x1B[0;37m",
@@ -596,6 +729,37 @@ var logLevelRank = {
596
729
  initial: "\x1B[0m"
597
730
  };
598
731
  })(Logger || (Logger = {}));
732
+ var fileSettings = /* @__PURE__ */ new Map();
733
+ var fileStates = /* @__PURE__ */ new Map();
734
+ var logLevels = /* @__PURE__ */ new Set();
735
+ var logLevelRank = {
736
+ debug: 0,
737
+ comment: 1,
738
+ log: 2,
739
+ info: 3,
740
+ warn: 4,
741
+ error: 5,
742
+ critical: 6
743
+ };
744
+ var logLevelColors = {
745
+ debug: Logger.colors.purple,
746
+ comment: Logger.colors.grey,
747
+ log: Logger.colors.green,
748
+ info: Logger.colors.blue,
749
+ warn: Logger.colors.brown,
750
+ error: Logger.colors.red,
751
+ critical: Logger.colors.lightRed
752
+ };
753
+ var logLevelChannel = {
754
+ debug: console.debug,
755
+ comment: console.debug,
756
+ log: console.log,
757
+ info: console.info,
758
+ warn: console.warn,
759
+ error: console.error,
760
+ critical: console.error
761
+ };
762
+ Logger.setLogLevel("debug");
599
763
  var Logger;
600
764
 
601
765
  // src/DI/injector-explorer.ts
@@ -644,22 +808,17 @@ function Injectable(lifetime = "scope") {
644
808
  if (typeof target !== "function" || !target.prototype) {
645
809
  throw new Error(`@Injectable can only be used on classes, not on ${typeof target}`);
646
810
  }
647
- Reflect.defineMetadata(INJECTABLE_METADATA_KEY, lifetime, target);
811
+ defineInjectableMetadata(target, lifetime);
648
812
  InjectorExplorer.register(target, lifetime);
649
813
  };
650
814
  }
651
815
  __name(Injectable, "Injectable");
652
- function getInjectableMetadata(target) {
653
- return Reflect.getMetadata(INJECTABLE_METADATA_KEY, target);
654
- }
655
- __name(getInjectableMetadata, "getInjectableMetadata");
656
- var INJECTABLE_METADATA_KEY = Symbol("INJECTABLE_METADATA_KEY");
657
816
 
658
817
  // src/decorators/controller.decorator.ts
659
- function Controller(path) {
818
+ function Controller(path2) {
660
819
  return (target) => {
661
820
  const data = {
662
- path,
821
+ path: path2,
663
822
  guards: getGuardForController(target.name)
664
823
  };
665
824
  Reflect.defineMetadata(CONTROLLER_METADATA_KEY, data, target);
@@ -707,8 +866,9 @@ var middlewares = /* @__PURE__ */ new Map();
707
866
  // src/request.ts
708
867
  var import_reflect_metadata2 = require("reflect-metadata");
709
868
  var _Request = class _Request {
710
- constructor(event, id, method, path, body) {
869
+ constructor(event, senderId, id, method, path2, body) {
711
870
  __publicField(this, "event");
871
+ __publicField(this, "senderId");
712
872
  __publicField(this, "id");
713
873
  __publicField(this, "method");
714
874
  __publicField(this, "path");
@@ -716,11 +876,12 @@ var _Request = class _Request {
716
876
  __publicField(this, "context", RootInjector.createScope());
717
877
  __publicField(this, "params", {});
718
878
  this.event = event;
879
+ this.senderId = senderId;
719
880
  this.id = id;
720
881
  this.method = method;
721
- this.path = path;
882
+ this.path = path2;
722
883
  this.body = body;
723
- this.path = path.replace(/^\/|\/$/g, "");
884
+ this.path = path2.replace(/^\/|\/$/g, "");
724
885
  }
725
886
  };
726
887
  __name(_Request, "Request");
@@ -802,8 +963,8 @@ var _RadixTree = class _RadixTree {
802
963
  * @param path - The path to insert into the tree.
803
964
  * @param value - The value to associate with the path.
804
965
  */
805
- insert(path, value) {
806
- const segments = this.normalize(path);
966
+ insert(path2, value) {
967
+ const segments = this.normalize(path2);
807
968
  this.insertRecursive(this.root, segments, value);
808
969
  }
809
970
  /**
@@ -832,8 +993,8 @@ var _RadixTree = class _RadixTree {
832
993
  * @param path - The path to search for in the Radix Tree.
833
994
  * @returns An ISearchResult containing the node and parameters if a match is found, otherwise undefined.
834
995
  */
835
- search(path) {
836
- const segments = this.normalize(path);
996
+ search(path2) {
997
+ const segments = this.normalize(path2);
837
998
  return this.searchRecursive(this.root, segments, {});
838
999
  }
839
1000
  /**
@@ -889,8 +1050,8 @@ var _RadixTree = class _RadixTree {
889
1050
  * @param path - The path to normalize.
890
1051
  * @returns An array of normalized path segments.
891
1052
  */
892
- normalize(path) {
893
- const segments = path.replace(/^\/+|\/+$/g, "").split("/").filter(Boolean);
1053
+ normalize(path2) {
1054
+ const segments = path2.replace(/^\/+|\/+$/g, "").split("/").filter(Boolean);
894
1055
  return [
895
1056
  "",
896
1057
  ...segments
@@ -1000,6 +1161,7 @@ var _Router = class _Router {
1000
1161
  status: 200,
1001
1162
  body: null
1002
1163
  };
1164
+ let isCritical = false;
1003
1165
  try {
1004
1166
  const routeDef = this.findRoute(request);
1005
1167
  await this.resolveController(request, response, routeDef);
@@ -1013,10 +1175,12 @@ var _Router = class _Router {
1013
1175
  response.error = error.message;
1014
1176
  response.stack = error.stack;
1015
1177
  } else if (error instanceof Error) {
1178
+ isCritical = true;
1016
1179
  response.status = 500;
1017
1180
  response.error = error.message || "Internal Server Error";
1018
1181
  response.stack = error.stack || "No stack trace available";
1019
1182
  } else {
1183
+ isCritical = true;
1020
1184
  response.status = 500;
1021
1185
  response.error = "Unknown error occurred";
1022
1186
  response.stack = "No stack trace available";
@@ -1024,11 +1188,23 @@ var _Router = class _Router {
1024
1188
  } finally {
1025
1189
  const t1 = performance.now();
1026
1190
  const message = `< ${response.status} ${request.method} /${request.path} ${Logger.colors.yellow}${Math.round(t1 - t0)}ms${Logger.colors.initial}`;
1027
- if (response.status < 400) Logger.log(message);
1028
- else if (response.status < 500) Logger.warn(message);
1029
- else Logger.error(message);
1191
+ if (response.status < 400) {
1192
+ Logger.log(message);
1193
+ } else if (response.status < 500) {
1194
+ Logger.warn(message);
1195
+ } else {
1196
+ if (isCritical) {
1197
+ Logger.critical(message);
1198
+ } else {
1199
+ Logger.error(message);
1200
+ }
1201
+ }
1030
1202
  if (response.error !== void 0) {
1031
- Logger.error(response.error);
1203
+ if (isCritical) {
1204
+ Logger.critical(response.error);
1205
+ } else {
1206
+ Logger.error(response.error);
1207
+ }
1032
1208
  if (response.stack !== void 0) {
1033
1209
  Logger.errorStack(response.stack);
1034
1210
  }
@@ -1046,12 +1222,13 @@ var _Router = class _Router {
1046
1222
  responses: []
1047
1223
  }
1048
1224
  };
1225
+ let isCritical = false;
1049
1226
  try {
1050
1227
  const payload = this.normalizeBatchPayload(request.body);
1051
1228
  const batchResponses = [];
1052
1229
  for (const [index, item] of payload.requests.entries()) {
1053
1230
  const subRequestId = item.requestId ?? `${request.id}:${index}`;
1054
- const atomicRequest = new Request(request.event, subRequestId, item.method, item.path, item.body);
1231
+ const atomicRequest = new Request(request.event, request.senderId, subRequestId, item.method, item.path, item.body);
1055
1232
  batchResponses.push(await this.handleAtomic(atomicRequest));
1056
1233
  }
1057
1234
  response.body.responses = batchResponses;
@@ -1062,10 +1239,12 @@ var _Router = class _Router {
1062
1239
  response.error = error.message;
1063
1240
  response.stack = error.stack;
1064
1241
  } else if (error instanceof Error) {
1242
+ isCritical = true;
1065
1243
  response.status = 500;
1066
1244
  response.error = error.message || "Internal Server Error";
1067
1245
  response.stack = error.stack || "No stack trace available";
1068
1246
  } else {
1247
+ isCritical = true;
1069
1248
  response.status = 500;
1070
1249
  response.error = "Unknown error occurred";
1071
1250
  response.stack = "No stack trace available";
@@ -1073,11 +1252,23 @@ var _Router = class _Router {
1073
1252
  } finally {
1074
1253
  const t1 = performance.now();
1075
1254
  const message = `< ${response.status} ${request.method} /${request.path} ${Logger.colors.yellow}${Math.round(t1 - t0)}ms${Logger.colors.initial}`;
1076
- if (response.status < 400) Logger.log(message);
1077
- else if (response.status < 500) Logger.warn(message);
1078
- else Logger.error(message);
1255
+ if (response.status < 400) {
1256
+ Logger.log(message);
1257
+ } else if (response.status < 500) {
1258
+ Logger.warn(message);
1259
+ } else {
1260
+ if (isCritical) {
1261
+ Logger.critical(message);
1262
+ } else {
1263
+ Logger.error(message);
1264
+ }
1265
+ }
1079
1266
  if (response.error !== void 0) {
1080
- Logger.error(response.error);
1267
+ if (isCritical) {
1268
+ Logger.critical(response.error);
1269
+ } else {
1270
+ Logger.error(response.error);
1271
+ }
1081
1272
  if (response.stack !== void 0) {
1082
1273
  Logger.errorStack(response.stack);
1083
1274
  }
@@ -1103,11 +1294,11 @@ var _Router = class _Router {
1103
1294
  if (entry === null || typeof entry !== "object") {
1104
1295
  throw new BadRequestException(`Batch request at index ${index} must be an object.`);
1105
1296
  }
1106
- const { requestId, path, method, body } = entry;
1297
+ const { requestId, path: path2, method, body } = entry;
1107
1298
  if (requestId !== void 0 && typeof requestId !== "string") {
1108
1299
  throw new BadRequestException(`Batch request at index ${index} has an invalid requestId.`);
1109
1300
  }
1110
- if (typeof path !== "string" || path.length === 0) {
1301
+ if (typeof path2 !== "string" || path2.length === 0) {
1111
1302
  throw new BadRequestException(`Batch request at index ${index} must define a non-empty path.`);
1112
1303
  }
1113
1304
  if (typeof method !== "string") {
@@ -1119,7 +1310,7 @@ var _Router = class _Router {
1119
1310
  }
1120
1311
  return {
1121
1312
  requestId,
1122
- path,
1313
+ path: path2,
1123
1314
  method: normalizedMethod,
1124
1315
  body
1125
1316
  };
@@ -1271,20 +1462,23 @@ function _ts_decorate2(decorators, target, key, desc) {
1271
1462
  __name(_ts_decorate2, "_ts_decorate");
1272
1463
  var _NoxSocket = class _NoxSocket {
1273
1464
  constructor() {
1274
- __publicField(this, "messagePorts", /* @__PURE__ */ new Map());
1465
+ __publicField(this, "channels", /* @__PURE__ */ new Map());
1275
1466
  }
1276
- register(senderId, channel) {
1277
- this.messagePorts.set(senderId, channel);
1467
+ register(senderId, requestChannel, socketChannel) {
1468
+ this.channels.set(senderId, {
1469
+ request: requestChannel,
1470
+ socket: socketChannel
1471
+ });
1278
1472
  }
1279
1473
  get(senderId) {
1280
- return this.messagePorts.get(senderId);
1474
+ return this.channels.get(senderId);
1281
1475
  }
1282
1476
  unregister(senderId) {
1283
- this.messagePorts.delete(senderId);
1477
+ this.channels.delete(senderId);
1284
1478
  }
1285
1479
  getSenderIds() {
1286
1480
  return [
1287
- ...this.messagePorts.keys()
1481
+ ...this.channels.keys()
1288
1482
  ];
1289
1483
  }
1290
1484
  emit(eventName, payload, targetSenderIds) {
@@ -1295,13 +1489,13 @@ var _NoxSocket = class _NoxSocket {
1295
1489
  const recipients = targetSenderIds ?? this.getSenderIds();
1296
1490
  let delivered = 0;
1297
1491
  for (const senderId of recipients) {
1298
- const channel = this.messagePorts.get(senderId);
1492
+ const channel = this.channels.get(senderId);
1299
1493
  if (!channel) {
1300
1494
  Logger.warn(`No message channel found for sender ID: ${senderId} while emitting "${normalizedEvent}".`);
1301
1495
  continue;
1302
1496
  }
1303
1497
  try {
1304
- channel.port1.postMessage(createRendererEventMessage(normalizedEvent, payload));
1498
+ channel.socket.port1.postMessage(createRendererEventMessage(normalizedEvent, payload));
1305
1499
  delivered++;
1306
1500
  } catch (error) {
1307
1501
  Logger.error(`[Noxus] Failed to emit "${normalizedEvent}" to sender ${senderId}.`, error);
@@ -1338,17 +1532,20 @@ var _NoxApp = class _NoxApp {
1338
1532
  __publicField(this, "router");
1339
1533
  __publicField(this, "socket");
1340
1534
  __publicField(this, "app");
1535
+ /**
1536
+ *
1537
+ */
1341
1538
  __publicField(this, "onRendererMessage", /* @__PURE__ */ __name(async (event) => {
1342
- const { senderId, requestId, path, method, body } = event.data;
1343
- const channel = this.socket.get(senderId);
1344
- if (!channel) {
1539
+ const { senderId, requestId, path: path2, method, body } = event.data;
1540
+ const channels = this.socket.get(senderId);
1541
+ if (!channels) {
1345
1542
  Logger.error(`No message channel found for sender ID: ${senderId}`);
1346
1543
  return;
1347
1544
  }
1348
1545
  try {
1349
- const request = new Request(event, requestId, method, path, body);
1546
+ const request = new Request(event, senderId, requestId, method, path2, body);
1350
1547
  const response = await this.router.handle(request);
1351
- channel.port1.postMessage(response);
1548
+ channels.request.port1.postMessage(response);
1352
1549
  } catch (err) {
1353
1550
  const response = {
1354
1551
  requestId,
@@ -1356,7 +1553,7 @@ var _NoxApp = class _NoxApp {
1356
1553
  body: null,
1357
1554
  error: err.message || "Internal Server Error"
1358
1555
  };
1359
- channel.port1.postMessage(response);
1556
+ channels.request.port1.postMessage(response);
1360
1557
  }
1361
1558
  }, "onRendererMessage"));
1362
1559
  this.router = router;
@@ -1385,14 +1582,17 @@ var _NoxApp = class _NoxApp {
1385
1582
  if (this.socket.get(senderId)) {
1386
1583
  this.shutdownChannel(senderId);
1387
1584
  }
1388
- const channel = new import_main.MessageChannelMain();
1389
- channel.port1.on("message", this.onRendererMessage);
1390
- channel.port1.start();
1391
- this.socket.register(senderId, channel);
1585
+ const requestChannel = new import_main.MessageChannelMain();
1586
+ const socketChannel = new import_main.MessageChannelMain();
1587
+ requestChannel.port1.on("message", this.onRendererMessage);
1588
+ requestChannel.port1.start();
1589
+ socketChannel.port1.start();
1590
+ this.socket.register(senderId, requestChannel, socketChannel);
1392
1591
  event.sender.postMessage("port", {
1393
1592
  senderId
1394
1593
  }, [
1395
- channel.port2
1594
+ requestChannel.port2,
1595
+ socketChannel.port2
1396
1596
  ]);
1397
1597
  }
1398
1598
  /**
@@ -1411,14 +1611,16 @@ var _NoxApp = class _NoxApp {
1411
1611
  * @param remove - Whether to remove the channel from the messagePorts map.
1412
1612
  */
1413
1613
  shutdownChannel(channelSenderId) {
1414
- const channel = this.socket.get(channelSenderId);
1415
- if (!channel) {
1614
+ const channels = this.socket.get(channelSenderId);
1615
+ if (!channels) {
1416
1616
  Logger.warn(`No message channel found for sender ID: ${channelSenderId}`);
1417
1617
  return;
1418
1618
  }
1419
- channel.port1.off("message", this.onRendererMessage);
1420
- channel.port1.close();
1421
- channel.port2.close();
1619
+ channels.request.port1.off("message", this.onRendererMessage);
1620
+ channels.request.port1.close();
1621
+ channels.request.port2.close();
1622
+ channels.socket.port1.close();
1623
+ channels.socket.port2.close();
1422
1624
  this.socket.unregister(channelSenderId);
1423
1625
  }
1424
1626
  /**
@@ -1489,6 +1691,42 @@ async function bootstrapApplication(rootModule) {
1489
1691
  }
1490
1692
  __name(bootstrapApplication, "bootstrapApplication");
1491
1693
 
1694
+ // src/preload-bridge.ts
1695
+ var import_renderer = require("electron/renderer");
1696
+ var DEFAULT_EXPOSE_NAME = "noxus";
1697
+ var DEFAULT_INIT_EVENT = "init-port";
1698
+ var DEFAULT_REQUEST_CHANNEL = "gimme-my-port";
1699
+ var DEFAULT_RESPONSE_CHANNEL = "port";
1700
+ function exposeNoxusBridge(options = {}) {
1701
+ const { exposeAs = DEFAULT_EXPOSE_NAME, initMessageType = DEFAULT_INIT_EVENT, requestChannel = DEFAULT_REQUEST_CHANNEL, responseChannel = DEFAULT_RESPONSE_CHANNEL, targetWindow = window } = options;
1702
+ const api = {
1703
+ requestPort: /* @__PURE__ */ __name(() => {
1704
+ import_renderer.ipcRenderer.send(requestChannel);
1705
+ import_renderer.ipcRenderer.once(responseChannel, (event, message) => {
1706
+ const ports = (event.ports ?? []).filter((port) => port !== void 0);
1707
+ if (ports.length === 0) {
1708
+ console.error("[Noxus] No MessagePort received from main process.");
1709
+ return;
1710
+ }
1711
+ for (const port of ports) {
1712
+ try {
1713
+ port.start();
1714
+ } catch (error) {
1715
+ console.error("[Noxus] Failed to start MessagePort.", error);
1716
+ }
1717
+ }
1718
+ targetWindow.postMessage({
1719
+ type: initMessageType,
1720
+ senderId: message?.senderId
1721
+ }, "*", ports);
1722
+ });
1723
+ }, "requestPort")
1724
+ };
1725
+ import_renderer.contextBridge.exposeInMainWorld(exposeAs, api);
1726
+ return api;
1727
+ }
1728
+ __name(exposeNoxusBridge, "exposeNoxusBridge");
1729
+
1492
1730
  // src/renderer-events.ts
1493
1731
  var _RendererEventRegistry = class _RendererEventRegistry {
1494
1732
  constructor() {
@@ -1568,6 +1806,252 @@ var _RendererEventRegistry = class _RendererEventRegistry {
1568
1806
  };
1569
1807
  __name(_RendererEventRegistry, "RendererEventRegistry");
1570
1808
  var RendererEventRegistry = _RendererEventRegistry;
1809
+
1810
+ // src/renderer-client.ts
1811
+ var DEFAULT_INIT_EVENT2 = "init-port";
1812
+ var DEFAULT_BRIDGE_NAMES = [
1813
+ "noxus",
1814
+ "ipcRenderer"
1815
+ ];
1816
+ function defaultRequestId() {
1817
+ if (typeof crypto !== "undefined" && typeof crypto.randomUUID === "function") {
1818
+ return crypto.randomUUID();
1819
+ }
1820
+ return `${Date.now().toString(16)}-${Math.floor(Math.random() * 1e8).toString(16)}`;
1821
+ }
1822
+ __name(defaultRequestId, "defaultRequestId");
1823
+ function normalizeBridgeNames(preferred) {
1824
+ const names = [];
1825
+ const add = /* @__PURE__ */ __name((name) => {
1826
+ if (!name) return;
1827
+ if (!names.includes(name)) {
1828
+ names.push(name);
1829
+ }
1830
+ }, "add");
1831
+ if (Array.isArray(preferred)) {
1832
+ for (const name of preferred) {
1833
+ add(name);
1834
+ }
1835
+ } else {
1836
+ add(preferred);
1837
+ }
1838
+ for (const fallback of DEFAULT_BRIDGE_NAMES) {
1839
+ add(fallback);
1840
+ }
1841
+ return names;
1842
+ }
1843
+ __name(normalizeBridgeNames, "normalizeBridgeNames");
1844
+ function resolveBridgeFromWindow(windowRef, preferred) {
1845
+ const names = normalizeBridgeNames(preferred);
1846
+ const globalRef = windowRef;
1847
+ if (!globalRef) {
1848
+ return null;
1849
+ }
1850
+ for (const name of names) {
1851
+ const candidate = globalRef[name];
1852
+ if (candidate && typeof candidate.requestPort === "function") {
1853
+ return candidate;
1854
+ }
1855
+ }
1856
+ return null;
1857
+ }
1858
+ __name(resolveBridgeFromWindow, "resolveBridgeFromWindow");
1859
+ var _NoxRendererClient = class _NoxRendererClient {
1860
+ constructor(options = {}) {
1861
+ __publicField(this, "events", new RendererEventRegistry());
1862
+ __publicField(this, "pendingRequests", /* @__PURE__ */ new Map());
1863
+ __publicField(this, "requestPort");
1864
+ __publicField(this, "socketPort");
1865
+ __publicField(this, "senderId");
1866
+ __publicField(this, "bridge");
1867
+ __publicField(this, "initMessageType");
1868
+ __publicField(this, "windowRef");
1869
+ __publicField(this, "generateRequestId");
1870
+ __publicField(this, "isReady", false);
1871
+ __publicField(this, "setupPromise");
1872
+ __publicField(this, "setupResolve");
1873
+ __publicField(this, "setupReject");
1874
+ __publicField(this, "onWindowMessage", /* @__PURE__ */ __name((event) => {
1875
+ if (event.data?.type !== this.initMessageType) {
1876
+ return;
1877
+ }
1878
+ if (!Array.isArray(event.ports) || event.ports.length < 2) {
1879
+ const error = new Error("[Noxus] Renderer expected two MessagePorts (request + socket).");
1880
+ console.error(error);
1881
+ this.setupReject?.(error);
1882
+ this.resetSetupState();
1883
+ return;
1884
+ }
1885
+ this.windowRef.removeEventListener("message", this.onWindowMessage);
1886
+ this.requestPort = event.ports[0];
1887
+ this.socketPort = event.ports[1];
1888
+ this.senderId = event.data.senderId;
1889
+ if (this.requestPort === void 0 || this.socketPort === void 0) {
1890
+ const error = new Error("[Noxus] Renderer failed to receive valid MessagePorts.");
1891
+ console.error(error);
1892
+ this.setupReject?.(error);
1893
+ this.resetSetupState();
1894
+ return;
1895
+ }
1896
+ this.attachRequestPort(this.requestPort);
1897
+ this.attachSocketPort(this.socketPort);
1898
+ this.isReady = true;
1899
+ this.setupResolve?.();
1900
+ this.resetSetupState(true);
1901
+ }, "onWindowMessage"));
1902
+ __publicField(this, "onSocketMessage", /* @__PURE__ */ __name((event) => {
1903
+ if (this.events.tryDispatchFromMessageEvent(event)) {
1904
+ return;
1905
+ }
1906
+ console.warn("[Noxus] Received a socket message that is not a renderer event payload.", event.data);
1907
+ }, "onSocketMessage"));
1908
+ __publicField(this, "onRequestMessage", /* @__PURE__ */ __name((event) => {
1909
+ if (this.events.tryDispatchFromMessageEvent(event)) {
1910
+ return;
1911
+ }
1912
+ const response = event.data;
1913
+ if (!response || typeof response.requestId !== "string") {
1914
+ console.error("[Noxus] Renderer received an invalid response payload.", response);
1915
+ return;
1916
+ }
1917
+ const pending = this.pendingRequests.get(response.requestId);
1918
+ if (!pending) {
1919
+ console.error(`[Noxus] No pending handler found for request ${response.requestId}.`);
1920
+ return;
1921
+ }
1922
+ this.pendingRequests.delete(response.requestId);
1923
+ this.onRequestCompleted(pending, response);
1924
+ if (response.status >= 400) {
1925
+ pending.reject(response);
1926
+ return;
1927
+ }
1928
+ pending.resolve(response.body);
1929
+ }, "onRequestMessage"));
1930
+ this.windowRef = options.windowRef ?? window;
1931
+ const resolvedBridge = options.bridge ?? resolveBridgeFromWindow(this.windowRef, options.bridgeName);
1932
+ this.bridge = resolvedBridge ?? null;
1933
+ this.initMessageType = options.initMessageType ?? DEFAULT_INIT_EVENT2;
1934
+ this.generateRequestId = options.generateRequestId ?? defaultRequestId;
1935
+ }
1936
+ async setup() {
1937
+ if (this.isReady) {
1938
+ return Promise.resolve();
1939
+ }
1940
+ if (this.setupPromise) {
1941
+ return this.setupPromise;
1942
+ }
1943
+ if (!this.bridge || typeof this.bridge.requestPort !== "function") {
1944
+ throw new Error("[Noxus] Renderer bridge is missing requestPort().");
1945
+ }
1946
+ this.setupPromise = new Promise((resolve, reject) => {
1947
+ this.setupResolve = resolve;
1948
+ this.setupReject = reject;
1949
+ });
1950
+ this.windowRef.addEventListener("message", this.onWindowMessage);
1951
+ this.bridge.requestPort();
1952
+ return this.setupPromise;
1953
+ }
1954
+ dispose() {
1955
+ this.windowRef.removeEventListener("message", this.onWindowMessage);
1956
+ this.requestPort?.close();
1957
+ this.socketPort?.close();
1958
+ this.requestPort = void 0;
1959
+ this.socketPort = void 0;
1960
+ this.senderId = void 0;
1961
+ this.isReady = false;
1962
+ this.pendingRequests.clear();
1963
+ }
1964
+ async request(request) {
1965
+ const senderId = this.senderId;
1966
+ const requestId = this.generateRequestId();
1967
+ if (senderId === void 0) {
1968
+ return Promise.reject(this.createErrorResponse(requestId, "MessagePort is not available"));
1969
+ }
1970
+ const readinessError = this.validateReady(requestId);
1971
+ if (readinessError) {
1972
+ return Promise.reject(readinessError);
1973
+ }
1974
+ const message = {
1975
+ requestId,
1976
+ senderId,
1977
+ ...request
1978
+ };
1979
+ return new Promise((resolve, reject) => {
1980
+ const pending = {
1981
+ resolve,
1982
+ reject: /* @__PURE__ */ __name((response) => reject(response), "reject"),
1983
+ request: message,
1984
+ submittedAt: Date.now()
1985
+ };
1986
+ this.pendingRequests.set(message.requestId, pending);
1987
+ this.requestPort.postMessage(message);
1988
+ });
1989
+ }
1990
+ async batch(requests) {
1991
+ return this.request({
1992
+ method: "BATCH",
1993
+ path: "",
1994
+ body: {
1995
+ requests
1996
+ }
1997
+ });
1998
+ }
1999
+ getSenderId() {
2000
+ return this.senderId;
2001
+ }
2002
+ onRequestCompleted(pending, response) {
2003
+ if (typeof console.groupCollapsed === "function") {
2004
+ console.groupCollapsed(`${response.status} ${pending.request.method} /${pending.request.path}`);
2005
+ }
2006
+ if (response.error) {
2007
+ console.error("error message:", response.error);
2008
+ }
2009
+ if (response.body !== void 0) {
2010
+ console.info("response:", response.body);
2011
+ }
2012
+ console.info("request:", pending.request);
2013
+ console.info(`Request duration: ${Date.now() - pending.submittedAt} ms`);
2014
+ if (typeof console.groupCollapsed === "function") {
2015
+ console.groupEnd();
2016
+ }
2017
+ }
2018
+ attachRequestPort(port) {
2019
+ port.onmessage = this.onRequestMessage;
2020
+ port.start();
2021
+ }
2022
+ attachSocketPort(port) {
2023
+ port.onmessage = this.onSocketMessage;
2024
+ port.start();
2025
+ }
2026
+ validateReady(requestId) {
2027
+ if (!this.isElectronEnvironment()) {
2028
+ return this.createErrorResponse(requestId, "Not running in Electron environment");
2029
+ }
2030
+ if (!this.requestPort) {
2031
+ return this.createErrorResponse(requestId, "MessagePort is not available");
2032
+ }
2033
+ return void 0;
2034
+ }
2035
+ createErrorResponse(requestId, message) {
2036
+ return {
2037
+ status: 500,
2038
+ requestId,
2039
+ error: message
2040
+ };
2041
+ }
2042
+ resetSetupState(success = false) {
2043
+ if (!success) {
2044
+ this.setupPromise = void 0;
2045
+ }
2046
+ this.setupResolve = void 0;
2047
+ this.setupReject = void 0;
2048
+ }
2049
+ isElectronEnvironment() {
2050
+ return typeof window !== "undefined" && /Electron/.test(window.navigator.userAgent);
2051
+ }
2052
+ };
2053
+ __name(_NoxRendererClient, "NoxRendererClient");
2054
+ var NoxRendererClient = _NoxRendererClient;
1571
2055
  // Annotate the CommonJS export names for ESM import in node:
1572
2056
  0 && (module.exports = {
1573
2057
  AppInjector,
@@ -1598,6 +2082,7 @@ var RendererEventRegistry = _RendererEventRegistry;
1598
2082
  NotFoundException,
1599
2083
  NotImplementedException,
1600
2084
  NoxApp,
2085
+ NoxRendererClient,
1601
2086
  NoxSocket,
1602
2087
  Patch,
1603
2088
  PaymentRequiredException,
@@ -1619,6 +2104,7 @@ var RendererEventRegistry = _RendererEventRegistry;
1619
2104
  VariantAlsoNegotiatesException,
1620
2105
  bootstrapApplication,
1621
2106
  createRendererEventMessage,
2107
+ exposeNoxusBridge,
1622
2108
  getControllerMetadata,
1623
2109
  getGuardForController,
1624
2110
  getGuardForControllerAction,
@@ -1627,6 +2113,7 @@ var RendererEventRegistry = _RendererEventRegistry;
1627
2113
  getMiddlewaresForControllerAction,
1628
2114
  getModuleMetadata,
1629
2115
  getRouteMetadata,
2116
+ hasInjectableMetadata,
1630
2117
  inject,
1631
2118
  isRendererEventMessage
1632
2119
  });