@noxfly/noxus 1.1.10 → 2.0.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.
@@ -25,9 +25,9 @@ var __copyProps = (to, from, except, desc) => {
25
25
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
26
26
  var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
27
27
 
28
- // src/index.ts
29
- var src_exports = {};
30
- __export(src_exports, {
28
+ // src/main.ts
29
+ var main_exports = {};
30
+ __export(main_exports, {
31
31
  AppInjector: () => AppInjector,
32
32
  Authorize: () => Authorize,
33
33
  BadGatewayException: () => BadGatewayException,
@@ -56,11 +56,15 @@ __export(src_exports, {
56
56
  NotFoundException: () => NotFoundException,
57
57
  NotImplementedException: () => NotImplementedException,
58
58
  NoxApp: () => NoxApp,
59
+ NoxRendererClient: () => NoxRendererClient,
60
+ NoxSocket: () => NoxSocket,
59
61
  Patch: () => Patch,
60
62
  PaymentRequiredException: () => PaymentRequiredException,
61
63
  Post: () => Post,
62
64
  Put: () => Put,
65
+ RENDERER_EVENT_TYPE: () => RENDERER_EVENT_TYPE,
63
66
  ROUTE_METADATA_KEY: () => ROUTE_METADATA_KEY,
67
+ RendererEventRegistry: () => RendererEventRegistry,
64
68
  Request: () => Request,
65
69
  RequestTimeoutException: () => RequestTimeoutException,
66
70
  ResponseException: () => ResponseException,
@@ -73,6 +77,8 @@ __export(src_exports, {
73
77
  UseMiddlewares: () => UseMiddlewares,
74
78
  VariantAlsoNegotiatesException: () => VariantAlsoNegotiatesException,
75
79
  bootstrapApplication: () => bootstrapApplication,
80
+ createRendererEventMessage: () => createRendererEventMessage,
81
+ exposeNoxusBridge: () => exposeNoxusBridge,
76
82
  getControllerMetadata: () => getControllerMetadata,
77
83
  getGuardForController: () => getGuardForController,
78
84
  getGuardForControllerAction: () => getGuardForControllerAction,
@@ -81,9 +87,11 @@ __export(src_exports, {
81
87
  getMiddlewaresForControllerAction: () => getMiddlewaresForControllerAction,
82
88
  getModuleMetadata: () => getModuleMetadata,
83
89
  getRouteMetadata: () => getRouteMetadata,
84
- inject: () => inject
90
+ hasInjectableMetadata: () => hasInjectableMetadata,
91
+ inject: () => inject,
92
+ isRendererEventMessage: () => isRendererEventMessage
85
93
  });
86
- module.exports = __toCommonJS(src_exports);
94
+ module.exports = __toCommonJS(main_exports);
87
95
 
88
96
  // src/DI/app-injector.ts
89
97
  var import_reflect_metadata = require("reflect-metadata");
@@ -392,6 +400,21 @@ function getGuardForControllerAction(controllerName, actionName) {
392
400
  __name(getGuardForControllerAction, "getGuardForControllerAction");
393
401
  var authorizations = /* @__PURE__ */ new Map();
394
402
 
403
+ // src/decorators/injectable.metadata.ts
404
+ var INJECTABLE_METADATA_KEY = Symbol("INJECTABLE_METADATA_KEY");
405
+ function defineInjectableMetadata(target, lifetime) {
406
+ Reflect.defineMetadata(INJECTABLE_METADATA_KEY, lifetime, target);
407
+ }
408
+ __name(defineInjectableMetadata, "defineInjectableMetadata");
409
+ function getInjectableMetadata(target) {
410
+ return Reflect.getMetadata(INJECTABLE_METADATA_KEY, target);
411
+ }
412
+ __name(getInjectableMetadata, "getInjectableMetadata");
413
+ function hasInjectableMetadata(target) {
414
+ return Reflect.hasMetadata(INJECTABLE_METADATA_KEY, target);
415
+ }
416
+ __name(hasInjectableMetadata, "hasInjectableMetadata");
417
+
395
418
  // src/decorators/method.decorator.ts
396
419
  function createRouteDecorator(verb) {
397
420
  return (path) => {
@@ -639,16 +662,11 @@ function Injectable(lifetime = "scope") {
639
662
  if (typeof target !== "function" || !target.prototype) {
640
663
  throw new Error(`@Injectable can only be used on classes, not on ${typeof target}`);
641
664
  }
642
- Reflect.defineMetadata(INJECTABLE_METADATA_KEY, lifetime, target);
665
+ defineInjectableMetadata(target, lifetime);
643
666
  InjectorExplorer.register(target, lifetime);
644
667
  };
645
668
  }
646
669
  __name(Injectable, "Injectable");
647
- function getInjectableMetadata(target) {
648
- return Reflect.getMetadata(INJECTABLE_METADATA_KEY, target);
649
- }
650
- __name(getInjectableMetadata, "getInjectableMetadata");
651
- var INJECTABLE_METADATA_KEY = Symbol("INJECTABLE_METADATA_KEY");
652
670
 
653
671
  // src/decorators/controller.decorator.ts
654
672
  function Controller(path) {
@@ -702,8 +720,9 @@ var middlewares = /* @__PURE__ */ new Map();
702
720
  // src/request.ts
703
721
  var import_reflect_metadata2 = require("reflect-metadata");
704
722
  var _Request = class _Request {
705
- constructor(event, id, method, path, body) {
723
+ constructor(event, senderId, id, method, path, body) {
706
724
  __publicField(this, "event");
725
+ __publicField(this, "senderId");
707
726
  __publicField(this, "id");
708
727
  __publicField(this, "method");
709
728
  __publicField(this, "path");
@@ -711,6 +730,7 @@ var _Request = class _Request {
711
730
  __publicField(this, "context", RootInjector.createScope());
712
731
  __publicField(this, "params", {});
713
732
  this.event = event;
733
+ this.senderId = senderId;
714
734
  this.id = id;
715
735
  this.method = method;
716
736
  this.path = path;
@@ -720,6 +740,23 @@ var _Request = class _Request {
720
740
  };
721
741
  __name(_Request, "Request");
722
742
  var Request = _Request;
743
+ var RENDERER_EVENT_TYPE = "noxus:event";
744
+ function createRendererEventMessage(event, payload) {
745
+ return {
746
+ type: RENDERER_EVENT_TYPE,
747
+ event,
748
+ payload
749
+ };
750
+ }
751
+ __name(createRendererEventMessage, "createRendererEventMessage");
752
+ function isRendererEventMessage(value) {
753
+ if (value === null || typeof value !== "object") {
754
+ return false;
755
+ }
756
+ const possibleMessage = value;
757
+ return possibleMessage.type === RENDERER_EVENT_TYPE && typeof possibleMessage.event === "string";
758
+ }
759
+ __name(isRendererEventMessage, "isRendererEventMessage");
723
760
 
724
761
  // src/utils/radix-tree.ts
725
762
  var _a;
@@ -1029,7 +1066,7 @@ var _Router = class _Router {
1029
1066
  const batchResponses = [];
1030
1067
  for (const [index, item] of payload.requests.entries()) {
1031
1068
  const subRequestId = item.requestId ?? `${request.id}:${index}`;
1032
- const atomicRequest = new Request(request.event, subRequestId, item.method, item.path, item.body);
1069
+ const atomicRequest = new Request(request.event, request.senderId, subRequestId, item.method, item.path, item.body);
1033
1070
  batchResponses.push(await this.handleAtomic(atomicRequest));
1034
1071
  }
1035
1072
  response.body.responses = batchResponses;
@@ -1238,6 +1275,8 @@ Router = _ts_decorate([
1238
1275
 
1239
1276
  // src/app.ts
1240
1277
  var import_main = require("electron/main");
1278
+
1279
+ // src/socket.ts
1241
1280
  function _ts_decorate2(decorators, target, key, desc) {
1242
1281
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
1243
1282
  if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
@@ -1245,16 +1284,104 @@ function _ts_decorate2(decorators, target, key, desc) {
1245
1284
  return c > 3 && r && Object.defineProperty(target, key, r), r;
1246
1285
  }
1247
1286
  __name(_ts_decorate2, "_ts_decorate");
1287
+ var _NoxSocket = class _NoxSocket {
1288
+ constructor() {
1289
+ __publicField(this, "channels", /* @__PURE__ */ new Map());
1290
+ }
1291
+ register(senderId, requestChannel, socketChannel) {
1292
+ this.channels.set(senderId, {
1293
+ request: requestChannel,
1294
+ socket: socketChannel
1295
+ });
1296
+ }
1297
+ get(senderId) {
1298
+ return this.channels.get(senderId);
1299
+ }
1300
+ unregister(senderId) {
1301
+ this.channels.delete(senderId);
1302
+ }
1303
+ getSenderIds() {
1304
+ return [
1305
+ ...this.channels.keys()
1306
+ ];
1307
+ }
1308
+ emit(eventName, payload, targetSenderIds) {
1309
+ const normalizedEvent = eventName.trim();
1310
+ if (normalizedEvent.length === 0) {
1311
+ throw new Error("Renderer event name must be a non-empty string.");
1312
+ }
1313
+ const recipients = targetSenderIds ?? this.getSenderIds();
1314
+ let delivered = 0;
1315
+ for (const senderId of recipients) {
1316
+ const channel = this.channels.get(senderId);
1317
+ if (!channel) {
1318
+ Logger.warn(`No message channel found for sender ID: ${senderId} while emitting "${normalizedEvent}".`);
1319
+ continue;
1320
+ }
1321
+ try {
1322
+ channel.socket.port1.postMessage(createRendererEventMessage(normalizedEvent, payload));
1323
+ delivered++;
1324
+ } catch (error) {
1325
+ Logger.error(`[Noxus] Failed to emit "${normalizedEvent}" to sender ${senderId}.`, error);
1326
+ }
1327
+ }
1328
+ return delivered;
1329
+ }
1330
+ emitToRenderer(senderId, eventName, payload) {
1331
+ return this.emit(eventName, payload, [
1332
+ senderId
1333
+ ]) > 0;
1334
+ }
1335
+ };
1336
+ __name(_NoxSocket, "NoxSocket");
1337
+ var NoxSocket = _NoxSocket;
1338
+ NoxSocket = _ts_decorate2([
1339
+ Injectable("singleton")
1340
+ ], NoxSocket);
1341
+
1342
+ // src/app.ts
1343
+ function _ts_decorate3(decorators, target, key, desc) {
1344
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
1345
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
1346
+ 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;
1347
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
1348
+ }
1349
+ __name(_ts_decorate3, "_ts_decorate");
1248
1350
  function _ts_metadata(k, v) {
1249
1351
  if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
1250
1352
  }
1251
1353
  __name(_ts_metadata, "_ts_metadata");
1252
1354
  var _NoxApp = class _NoxApp {
1253
- constructor(router) {
1355
+ constructor(router, socket) {
1254
1356
  __publicField(this, "router");
1255
- __publicField(this, "messagePorts", /* @__PURE__ */ new Map());
1357
+ __publicField(this, "socket");
1256
1358
  __publicField(this, "app");
1359
+ /**
1360
+ *
1361
+ */
1362
+ __publicField(this, "onRendererMessage", /* @__PURE__ */ __name(async (event) => {
1363
+ const { senderId, requestId, path, method, body } = event.data;
1364
+ const channels = this.socket.get(senderId);
1365
+ if (!channels) {
1366
+ Logger.error(`No message channel found for sender ID: ${senderId}`);
1367
+ return;
1368
+ }
1369
+ try {
1370
+ const request = new Request(event, senderId, requestId, method, path, body);
1371
+ const response = await this.router.handle(request);
1372
+ channels.request.port1.postMessage(response);
1373
+ } catch (err) {
1374
+ const response = {
1375
+ requestId,
1376
+ status: 500,
1377
+ body: null,
1378
+ error: err.message || "Internal Server Error"
1379
+ };
1380
+ channels.request.port1.postMessage(response);
1381
+ }
1382
+ }, "onRendererMessage"));
1257
1383
  this.router = router;
1384
+ this.socket = socket;
1258
1385
  }
1259
1386
  /**
1260
1387
  * Initializes the NoxApp instance.
@@ -1276,44 +1403,22 @@ var _NoxApp = class _NoxApp {
1276
1403
  */
1277
1404
  giveTheRendererAPort(event) {
1278
1405
  const senderId = event.sender.id;
1279
- if (this.messagePorts.has(senderId)) {
1406
+ if (this.socket.get(senderId)) {
1280
1407
  this.shutdownChannel(senderId);
1281
1408
  }
1282
- const channel = new import_main.MessageChannelMain();
1283
- this.messagePorts.set(senderId, channel);
1284
- channel.port1.on("message", this.onRendererMessage.bind(this));
1285
- channel.port1.start();
1409
+ const requestChannel = new import_main.MessageChannelMain();
1410
+ const socketChannel = new import_main.MessageChannelMain();
1411
+ requestChannel.port1.on("message", this.onRendererMessage);
1412
+ requestChannel.port1.start();
1413
+ socketChannel.port1.start();
1414
+ this.socket.register(senderId, requestChannel, socketChannel);
1286
1415
  event.sender.postMessage("port", {
1287
1416
  senderId
1288
1417
  }, [
1289
- channel.port2
1418
+ requestChannel.port2,
1419
+ socketChannel.port2
1290
1420
  ]);
1291
1421
  }
1292
- /**
1293
- * Electron specific message handling.
1294
- * Replaces HTTP calls by using Electron's IPC mechanism.
1295
- */
1296
- async onRendererMessage(event) {
1297
- const { senderId, requestId, path, method, body } = event.data;
1298
- const channel = this.messagePorts.get(senderId);
1299
- if (!channel) {
1300
- Logger.error(`No message channel found for sender ID: ${senderId}`);
1301
- return;
1302
- }
1303
- try {
1304
- const request = new Request(event, requestId, method, path, body);
1305
- const response = await this.router.handle(request);
1306
- channel.port1.postMessage(response);
1307
- } catch (err) {
1308
- const response = {
1309
- requestId,
1310
- status: 500,
1311
- body: null,
1312
- error: err.message || "Internal Server Error"
1313
- };
1314
- channel.port1.postMessage(response);
1315
- }
1316
- }
1317
1422
  /**
1318
1423
  * MacOS specific behavior.
1319
1424
  */
@@ -1330,25 +1435,26 @@ var _NoxApp = class _NoxApp {
1330
1435
  * @param remove - Whether to remove the channel from the messagePorts map.
1331
1436
  */
1332
1437
  shutdownChannel(channelSenderId) {
1333
- const channel = this.messagePorts.get(channelSenderId);
1334
- if (!channel) {
1438
+ const channels = this.socket.get(channelSenderId);
1439
+ if (!channels) {
1335
1440
  Logger.warn(`No message channel found for sender ID: ${channelSenderId}`);
1336
1441
  return;
1337
1442
  }
1338
- channel.port1.off("message", this.onRendererMessage.bind(this));
1339
- channel.port1.close();
1340
- channel.port2.close();
1341
- this.messagePorts.delete(channelSenderId);
1443
+ channels.request.port1.off("message", this.onRendererMessage);
1444
+ channels.request.port1.close();
1445
+ channels.request.port2.close();
1446
+ channels.socket.port1.close();
1447
+ channels.socket.port2.close();
1448
+ this.socket.unregister(channelSenderId);
1342
1449
  }
1343
1450
  /**
1344
1451
  * Handles the application shutdown process.
1345
1452
  * This method is called when all windows are closed, and it cleans up the message channels
1346
1453
  */
1347
1454
  async onAllWindowsClosed() {
1348
- this.messagePorts.forEach((channel, senderId) => {
1455
+ for (const senderId of this.socket.getSenderIds()) {
1349
1456
  this.shutdownChannel(senderId);
1350
- });
1351
- this.messagePorts.clear();
1457
+ }
1352
1458
  Logger.info("All windows closed, shutting down application...");
1353
1459
  await this.app?.dispose();
1354
1460
  if (process.platform !== "darwin") {
@@ -1387,11 +1493,12 @@ var _NoxApp = class _NoxApp {
1387
1493
  };
1388
1494
  __name(_NoxApp, "NoxApp");
1389
1495
  var NoxApp = _NoxApp;
1390
- NoxApp = _ts_decorate2([
1496
+ NoxApp = _ts_decorate3([
1391
1497
  Injectable("singleton"),
1392
1498
  _ts_metadata("design:type", Function),
1393
1499
  _ts_metadata("design:paramtypes", [
1394
- typeof Router === "undefined" ? Object : Router
1500
+ typeof Router === "undefined" ? Object : Router,
1501
+ typeof NoxSocket === "undefined" ? Object : NoxSocket
1395
1502
  ])
1396
1503
  ], NoxApp);
1397
1504
 
@@ -1407,6 +1514,368 @@ async function bootstrapApplication(rootModule) {
1407
1514
  return noxApp;
1408
1515
  }
1409
1516
  __name(bootstrapApplication, "bootstrapApplication");
1517
+
1518
+ // src/preload-bridge.ts
1519
+ var import_renderer = require("electron/renderer");
1520
+ var DEFAULT_EXPOSE_NAME = "noxus";
1521
+ var DEFAULT_INIT_EVENT = "init-port";
1522
+ var DEFAULT_REQUEST_CHANNEL = "gimme-my-port";
1523
+ var DEFAULT_RESPONSE_CHANNEL = "port";
1524
+ function exposeNoxusBridge(options = {}) {
1525
+ const { exposeAs = DEFAULT_EXPOSE_NAME, initMessageType = DEFAULT_INIT_EVENT, requestChannel = DEFAULT_REQUEST_CHANNEL, responseChannel = DEFAULT_RESPONSE_CHANNEL, targetWindow = window } = options;
1526
+ const api = {
1527
+ requestPort: /* @__PURE__ */ __name(() => {
1528
+ import_renderer.ipcRenderer.send(requestChannel);
1529
+ import_renderer.ipcRenderer.once(responseChannel, (event, message) => {
1530
+ const ports = (event.ports ?? []).filter((port) => port !== void 0);
1531
+ if (ports.length === 0) {
1532
+ console.error("[Noxus] No MessagePort received from main process.");
1533
+ return;
1534
+ }
1535
+ for (const port of ports) {
1536
+ try {
1537
+ port.start();
1538
+ } catch (error) {
1539
+ console.error("[Noxus] Failed to start MessagePort.", error);
1540
+ }
1541
+ }
1542
+ targetWindow.postMessage({
1543
+ type: initMessageType,
1544
+ senderId: message?.senderId
1545
+ }, "*", ports);
1546
+ });
1547
+ }, "requestPort")
1548
+ };
1549
+ import_renderer.contextBridge.exposeInMainWorld(exposeAs, api);
1550
+ return api;
1551
+ }
1552
+ __name(exposeNoxusBridge, "exposeNoxusBridge");
1553
+
1554
+ // src/renderer-events.ts
1555
+ var _RendererEventRegistry = class _RendererEventRegistry {
1556
+ constructor() {
1557
+ __publicField(this, "listeners", /* @__PURE__ */ new Map());
1558
+ }
1559
+ /**
1560
+ *
1561
+ */
1562
+ subscribe(eventName, handler) {
1563
+ const normalizedEventName = eventName.trim();
1564
+ if (normalizedEventName.length === 0) {
1565
+ throw new Error("Renderer event name must be a non-empty string.");
1566
+ }
1567
+ const handlers = this.listeners.get(normalizedEventName) ?? /* @__PURE__ */ new Set();
1568
+ handlers.add(handler);
1569
+ this.listeners.set(normalizedEventName, handlers);
1570
+ return {
1571
+ unsubscribe: /* @__PURE__ */ __name(() => this.unsubscribe(normalizedEventName, handler), "unsubscribe")
1572
+ };
1573
+ }
1574
+ /**
1575
+ *
1576
+ */
1577
+ unsubscribe(eventName, handler) {
1578
+ const handlers = this.listeners.get(eventName);
1579
+ if (!handlers) {
1580
+ return;
1581
+ }
1582
+ handlers.delete(handler);
1583
+ if (handlers.size === 0) {
1584
+ this.listeners.delete(eventName);
1585
+ }
1586
+ }
1587
+ /**
1588
+ *
1589
+ */
1590
+ clear(eventName) {
1591
+ if (eventName) {
1592
+ this.listeners.delete(eventName);
1593
+ return;
1594
+ }
1595
+ this.listeners.clear();
1596
+ }
1597
+ /**
1598
+ *
1599
+ */
1600
+ dispatch(message) {
1601
+ const handlers = this.listeners.get(message.event);
1602
+ if (!handlers || handlers.size === 0) {
1603
+ return;
1604
+ }
1605
+ handlers.forEach((handler) => {
1606
+ try {
1607
+ handler(message.payload);
1608
+ } catch (error) {
1609
+ console.error(`[Noxus] Renderer event handler for "${message.event}" threw an error.`, error);
1610
+ }
1611
+ });
1612
+ }
1613
+ /**
1614
+ *
1615
+ */
1616
+ tryDispatchFromMessageEvent(event) {
1617
+ if (!isRendererEventMessage(event.data)) {
1618
+ return false;
1619
+ }
1620
+ this.dispatch(event.data);
1621
+ return true;
1622
+ }
1623
+ /**
1624
+ *
1625
+ */
1626
+ hasHandlers(eventName) {
1627
+ const handlers = this.listeners.get(eventName);
1628
+ return !!handlers && handlers.size > 0;
1629
+ }
1630
+ };
1631
+ __name(_RendererEventRegistry, "RendererEventRegistry");
1632
+ var RendererEventRegistry = _RendererEventRegistry;
1633
+
1634
+ // src/renderer-client.ts
1635
+ var DEFAULT_INIT_EVENT2 = "init-port";
1636
+ var DEFAULT_BRIDGE_NAMES = [
1637
+ "noxus",
1638
+ "ipcRenderer"
1639
+ ];
1640
+ function defaultRequestId() {
1641
+ if (typeof crypto !== "undefined" && typeof crypto.randomUUID === "function") {
1642
+ return crypto.randomUUID();
1643
+ }
1644
+ return `${Date.now().toString(16)}-${Math.floor(Math.random() * 1e8).toString(16)}`;
1645
+ }
1646
+ __name(defaultRequestId, "defaultRequestId");
1647
+ function normalizeBridgeNames(preferred) {
1648
+ const names = [];
1649
+ const add = /* @__PURE__ */ __name((name) => {
1650
+ if (!name) return;
1651
+ if (!names.includes(name)) {
1652
+ names.push(name);
1653
+ }
1654
+ }, "add");
1655
+ if (Array.isArray(preferred)) {
1656
+ for (const name of preferred) {
1657
+ add(name);
1658
+ }
1659
+ } else {
1660
+ add(preferred);
1661
+ }
1662
+ for (const fallback of DEFAULT_BRIDGE_NAMES) {
1663
+ add(fallback);
1664
+ }
1665
+ return names;
1666
+ }
1667
+ __name(normalizeBridgeNames, "normalizeBridgeNames");
1668
+ function resolveBridgeFromWindow(windowRef, preferred) {
1669
+ const names = normalizeBridgeNames(preferred);
1670
+ const globalRef = windowRef;
1671
+ if (!globalRef) {
1672
+ return null;
1673
+ }
1674
+ for (const name of names) {
1675
+ const candidate = globalRef[name];
1676
+ if (candidate && typeof candidate.requestPort === "function") {
1677
+ return candidate;
1678
+ }
1679
+ }
1680
+ return null;
1681
+ }
1682
+ __name(resolveBridgeFromWindow, "resolveBridgeFromWindow");
1683
+ var _NoxRendererClient = class _NoxRendererClient {
1684
+ constructor(options = {}) {
1685
+ __publicField(this, "events", new RendererEventRegistry());
1686
+ __publicField(this, "pendingRequests", /* @__PURE__ */ new Map());
1687
+ __publicField(this, "requestPort");
1688
+ __publicField(this, "socketPort");
1689
+ __publicField(this, "senderId");
1690
+ __publicField(this, "bridge");
1691
+ __publicField(this, "initMessageType");
1692
+ __publicField(this, "windowRef");
1693
+ __publicField(this, "generateRequestId");
1694
+ __publicField(this, "isReady", false);
1695
+ __publicField(this, "setupPromise");
1696
+ __publicField(this, "setupResolve");
1697
+ __publicField(this, "setupReject");
1698
+ __publicField(this, "onWindowMessage", /* @__PURE__ */ __name((event) => {
1699
+ if (event.data?.type !== this.initMessageType) {
1700
+ return;
1701
+ }
1702
+ if (!Array.isArray(event.ports) || event.ports.length < 2) {
1703
+ const error = new Error("[Noxus] Renderer expected two MessagePorts (request + socket).");
1704
+ console.error(error);
1705
+ this.setupReject?.(error);
1706
+ this.resetSetupState();
1707
+ return;
1708
+ }
1709
+ this.windowRef.removeEventListener("message", this.onWindowMessage);
1710
+ this.requestPort = event.ports[0];
1711
+ this.socketPort = event.ports[1];
1712
+ this.senderId = event.data.senderId;
1713
+ if (this.requestPort === void 0 || this.socketPort === void 0) {
1714
+ const error = new Error("[Noxus] Renderer failed to receive valid MessagePorts.");
1715
+ console.error(error);
1716
+ this.setupReject?.(error);
1717
+ this.resetSetupState();
1718
+ return;
1719
+ }
1720
+ this.attachRequestPort(this.requestPort);
1721
+ this.attachSocketPort(this.socketPort);
1722
+ this.isReady = true;
1723
+ this.setupResolve?.();
1724
+ this.resetSetupState(true);
1725
+ }, "onWindowMessage"));
1726
+ __publicField(this, "onSocketMessage", /* @__PURE__ */ __name((event) => {
1727
+ if (this.events.tryDispatchFromMessageEvent(event)) {
1728
+ return;
1729
+ }
1730
+ console.warn("[Noxus] Received a socket message that is not a renderer event payload.", event.data);
1731
+ }, "onSocketMessage"));
1732
+ __publicField(this, "onRequestMessage", /* @__PURE__ */ __name((event) => {
1733
+ if (this.events.tryDispatchFromMessageEvent(event)) {
1734
+ return;
1735
+ }
1736
+ const response = event.data;
1737
+ if (!response || typeof response.requestId !== "string") {
1738
+ console.error("[Noxus] Renderer received an invalid response payload.", response);
1739
+ return;
1740
+ }
1741
+ const pending = this.pendingRequests.get(response.requestId);
1742
+ if (!pending) {
1743
+ console.error(`[Noxus] No pending handler found for request ${response.requestId}.`);
1744
+ return;
1745
+ }
1746
+ this.pendingRequests.delete(response.requestId);
1747
+ this.onRequestCompleted(pending, response);
1748
+ if (response.status >= 400) {
1749
+ pending.reject(response);
1750
+ return;
1751
+ }
1752
+ pending.resolve(response.body);
1753
+ }, "onRequestMessage"));
1754
+ this.windowRef = options.windowRef ?? window;
1755
+ const resolvedBridge = options.bridge ?? resolveBridgeFromWindow(this.windowRef, options.bridgeName);
1756
+ this.bridge = resolvedBridge ?? null;
1757
+ this.initMessageType = options.initMessageType ?? DEFAULT_INIT_EVENT2;
1758
+ this.generateRequestId = options.generateRequestId ?? defaultRequestId;
1759
+ }
1760
+ async setup() {
1761
+ if (this.isReady) {
1762
+ return Promise.resolve();
1763
+ }
1764
+ if (this.setupPromise) {
1765
+ return this.setupPromise;
1766
+ }
1767
+ if (!this.bridge || typeof this.bridge.requestPort !== "function") {
1768
+ throw new Error("[Noxus] Renderer bridge is missing requestPort().");
1769
+ }
1770
+ this.setupPromise = new Promise((resolve, reject) => {
1771
+ this.setupResolve = resolve;
1772
+ this.setupReject = reject;
1773
+ });
1774
+ this.windowRef.addEventListener("message", this.onWindowMessage);
1775
+ this.bridge.requestPort();
1776
+ return this.setupPromise;
1777
+ }
1778
+ dispose() {
1779
+ this.windowRef.removeEventListener("message", this.onWindowMessage);
1780
+ this.requestPort?.close();
1781
+ this.socketPort?.close();
1782
+ this.requestPort = void 0;
1783
+ this.socketPort = void 0;
1784
+ this.senderId = void 0;
1785
+ this.isReady = false;
1786
+ this.pendingRequests.clear();
1787
+ }
1788
+ async request(request) {
1789
+ const senderId = this.senderId;
1790
+ const requestId = this.generateRequestId();
1791
+ if (senderId === void 0) {
1792
+ return Promise.reject(this.createErrorResponse(requestId, "MessagePort is not available"));
1793
+ }
1794
+ const readinessError = this.validateReady(requestId);
1795
+ if (readinessError) {
1796
+ return Promise.reject(readinessError);
1797
+ }
1798
+ const message = {
1799
+ requestId,
1800
+ senderId,
1801
+ ...request
1802
+ };
1803
+ return new Promise((resolve, reject) => {
1804
+ const pending = {
1805
+ resolve,
1806
+ reject: /* @__PURE__ */ __name((response) => reject(response), "reject"),
1807
+ request: message,
1808
+ submittedAt: Date.now()
1809
+ };
1810
+ this.pendingRequests.set(message.requestId, pending);
1811
+ this.requestPort.postMessage(message);
1812
+ });
1813
+ }
1814
+ async batch(requests) {
1815
+ return this.request({
1816
+ method: "BATCH",
1817
+ path: "",
1818
+ body: {
1819
+ requests
1820
+ }
1821
+ });
1822
+ }
1823
+ getSenderId() {
1824
+ return this.senderId;
1825
+ }
1826
+ onRequestCompleted(pending, response) {
1827
+ if (typeof console.groupCollapsed === "function") {
1828
+ console.groupCollapsed(`${response.status} ${pending.request.method} /${pending.request.path}`);
1829
+ }
1830
+ if (response.error) {
1831
+ console.error("error message:", response.error);
1832
+ }
1833
+ if (response.body !== void 0) {
1834
+ console.info("response:", response.body);
1835
+ }
1836
+ console.info("request:", pending.request);
1837
+ console.info(`Request duration: ${Date.now() - pending.submittedAt} ms`);
1838
+ if (typeof console.groupCollapsed === "function") {
1839
+ console.groupEnd();
1840
+ }
1841
+ }
1842
+ attachRequestPort(port) {
1843
+ port.onmessage = this.onRequestMessage;
1844
+ port.start();
1845
+ }
1846
+ attachSocketPort(port) {
1847
+ port.onmessage = this.onSocketMessage;
1848
+ port.start();
1849
+ }
1850
+ validateReady(requestId) {
1851
+ if (!this.isElectronEnvironment()) {
1852
+ return this.createErrorResponse(requestId, "Not running in Electron environment");
1853
+ }
1854
+ if (!this.requestPort) {
1855
+ return this.createErrorResponse(requestId, "MessagePort is not available");
1856
+ }
1857
+ return void 0;
1858
+ }
1859
+ createErrorResponse(requestId, message) {
1860
+ return {
1861
+ status: 500,
1862
+ requestId,
1863
+ error: message
1864
+ };
1865
+ }
1866
+ resetSetupState(success = false) {
1867
+ if (!success) {
1868
+ this.setupPromise = void 0;
1869
+ }
1870
+ this.setupResolve = void 0;
1871
+ this.setupReject = void 0;
1872
+ }
1873
+ isElectronEnvironment() {
1874
+ return typeof window !== "undefined" && /Electron/.test(window.navigator.userAgent);
1875
+ }
1876
+ };
1877
+ __name(_NoxRendererClient, "NoxRendererClient");
1878
+ var NoxRendererClient = _NoxRendererClient;
1410
1879
  // Annotate the CommonJS export names for ESM import in node:
1411
1880
  0 && (module.exports = {
1412
1881
  AppInjector,
@@ -1437,11 +1906,15 @@ __name(bootstrapApplication, "bootstrapApplication");
1437
1906
  NotFoundException,
1438
1907
  NotImplementedException,
1439
1908
  NoxApp,
1909
+ NoxRendererClient,
1910
+ NoxSocket,
1440
1911
  Patch,
1441
1912
  PaymentRequiredException,
1442
1913
  Post,
1443
1914
  Put,
1915
+ RENDERER_EVENT_TYPE,
1444
1916
  ROUTE_METADATA_KEY,
1917
+ RendererEventRegistry,
1445
1918
  Request,
1446
1919
  RequestTimeoutException,
1447
1920
  ResponseException,
@@ -1454,6 +1927,8 @@ __name(bootstrapApplication, "bootstrapApplication");
1454
1927
  UseMiddlewares,
1455
1928
  VariantAlsoNegotiatesException,
1456
1929
  bootstrapApplication,
1930
+ createRendererEventMessage,
1931
+ exposeNoxusBridge,
1457
1932
  getControllerMetadata,
1458
1933
  getGuardForController,
1459
1934
  getGuardForControllerAction,
@@ -1462,11 +1937,13 @@ __name(bootstrapApplication, "bootstrapApplication");
1462
1937
  getMiddlewaresForControllerAction,
1463
1938
  getModuleMetadata,
1464
1939
  getRouteMetadata,
1465
- inject
1940
+ hasInjectableMetadata,
1941
+ inject,
1942
+ isRendererEventMessage
1466
1943
  });
1467
1944
  /**
1468
1945
  * @copyright 2025 NoxFly
1469
1946
  * @license MIT
1470
1947
  * @author NoxFly
1471
1948
  */
1472
- //# sourceMappingURL=noxus.js.map
1949
+ //# sourceMappingURL=main.js.map