@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.
@@ -315,6 +315,21 @@ function getGuardForControllerAction(controllerName, actionName) {
315
315
  __name(getGuardForControllerAction, "getGuardForControllerAction");
316
316
  var authorizations = /* @__PURE__ */ new Map();
317
317
 
318
+ // src/decorators/injectable.metadata.ts
319
+ var INJECTABLE_METADATA_KEY = Symbol("INJECTABLE_METADATA_KEY");
320
+ function defineInjectableMetadata(target, lifetime) {
321
+ Reflect.defineMetadata(INJECTABLE_METADATA_KEY, lifetime, target);
322
+ }
323
+ __name(defineInjectableMetadata, "defineInjectableMetadata");
324
+ function getInjectableMetadata(target) {
325
+ return Reflect.getMetadata(INJECTABLE_METADATA_KEY, target);
326
+ }
327
+ __name(getInjectableMetadata, "getInjectableMetadata");
328
+ function hasInjectableMetadata(target) {
329
+ return Reflect.hasMetadata(INJECTABLE_METADATA_KEY, target);
330
+ }
331
+ __name(hasInjectableMetadata, "hasInjectableMetadata");
332
+
318
333
  // src/decorators/method.decorator.ts
319
334
  function createRouteDecorator(verb) {
320
335
  return (path) => {
@@ -562,16 +577,11 @@ function Injectable(lifetime = "scope") {
562
577
  if (typeof target !== "function" || !target.prototype) {
563
578
  throw new Error(`@Injectable can only be used on classes, not on ${typeof target}`);
564
579
  }
565
- Reflect.defineMetadata(INJECTABLE_METADATA_KEY, lifetime, target);
580
+ defineInjectableMetadata(target, lifetime);
566
581
  InjectorExplorer.register(target, lifetime);
567
582
  };
568
583
  }
569
584
  __name(Injectable, "Injectable");
570
- function getInjectableMetadata(target) {
571
- return Reflect.getMetadata(INJECTABLE_METADATA_KEY, target);
572
- }
573
- __name(getInjectableMetadata, "getInjectableMetadata");
574
- var INJECTABLE_METADATA_KEY = Symbol("INJECTABLE_METADATA_KEY");
575
585
 
576
586
  // src/decorators/controller.decorator.ts
577
587
  function Controller(path) {
@@ -625,8 +635,9 @@ var middlewares = /* @__PURE__ */ new Map();
625
635
  // src/request.ts
626
636
  import "reflect-metadata";
627
637
  var _Request = class _Request {
628
- constructor(event, id, method, path, body) {
638
+ constructor(event, senderId, id, method, path, body) {
629
639
  __publicField(this, "event");
640
+ __publicField(this, "senderId");
630
641
  __publicField(this, "id");
631
642
  __publicField(this, "method");
632
643
  __publicField(this, "path");
@@ -634,6 +645,7 @@ var _Request = class _Request {
634
645
  __publicField(this, "context", RootInjector.createScope());
635
646
  __publicField(this, "params", {});
636
647
  this.event = event;
648
+ this.senderId = senderId;
637
649
  this.id = id;
638
650
  this.method = method;
639
651
  this.path = path;
@@ -643,6 +655,23 @@ var _Request = class _Request {
643
655
  };
644
656
  __name(_Request, "Request");
645
657
  var Request = _Request;
658
+ var RENDERER_EVENT_TYPE = "noxus:event";
659
+ function createRendererEventMessage(event, payload) {
660
+ return {
661
+ type: RENDERER_EVENT_TYPE,
662
+ event,
663
+ payload
664
+ };
665
+ }
666
+ __name(createRendererEventMessage, "createRendererEventMessage");
667
+ function isRendererEventMessage(value) {
668
+ if (value === null || typeof value !== "object") {
669
+ return false;
670
+ }
671
+ const possibleMessage = value;
672
+ return possibleMessage.type === RENDERER_EVENT_TYPE && typeof possibleMessage.event === "string";
673
+ }
674
+ __name(isRendererEventMessage, "isRendererEventMessage");
646
675
 
647
676
  // src/utils/radix-tree.ts
648
677
  var _a;
@@ -952,7 +981,7 @@ var _Router = class _Router {
952
981
  const batchResponses = [];
953
982
  for (const [index, item] of payload.requests.entries()) {
954
983
  const subRequestId = item.requestId ?? `${request.id}:${index}`;
955
- const atomicRequest = new Request(request.event, subRequestId, item.method, item.path, item.body);
984
+ const atomicRequest = new Request(request.event, request.senderId, subRequestId, item.method, item.path, item.body);
956
985
  batchResponses.push(await this.handleAtomic(atomicRequest));
957
986
  }
958
987
  response.body.responses = batchResponses;
@@ -1161,6 +1190,8 @@ Router = _ts_decorate([
1161
1190
 
1162
1191
  // src/app.ts
1163
1192
  import { app, BrowserWindow, ipcMain, MessageChannelMain } from "electron/main";
1193
+
1194
+ // src/socket.ts
1164
1195
  function _ts_decorate2(decorators, target, key, desc) {
1165
1196
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
1166
1197
  if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
@@ -1168,16 +1199,104 @@ function _ts_decorate2(decorators, target, key, desc) {
1168
1199
  return c > 3 && r && Object.defineProperty(target, key, r), r;
1169
1200
  }
1170
1201
  __name(_ts_decorate2, "_ts_decorate");
1202
+ var _NoxSocket = class _NoxSocket {
1203
+ constructor() {
1204
+ __publicField(this, "channels", /* @__PURE__ */ new Map());
1205
+ }
1206
+ register(senderId, requestChannel, socketChannel) {
1207
+ this.channels.set(senderId, {
1208
+ request: requestChannel,
1209
+ socket: socketChannel
1210
+ });
1211
+ }
1212
+ get(senderId) {
1213
+ return this.channels.get(senderId);
1214
+ }
1215
+ unregister(senderId) {
1216
+ this.channels.delete(senderId);
1217
+ }
1218
+ getSenderIds() {
1219
+ return [
1220
+ ...this.channels.keys()
1221
+ ];
1222
+ }
1223
+ emit(eventName, payload, targetSenderIds) {
1224
+ const normalizedEvent = eventName.trim();
1225
+ if (normalizedEvent.length === 0) {
1226
+ throw new Error("Renderer event name must be a non-empty string.");
1227
+ }
1228
+ const recipients = targetSenderIds ?? this.getSenderIds();
1229
+ let delivered = 0;
1230
+ for (const senderId of recipients) {
1231
+ const channel = this.channels.get(senderId);
1232
+ if (!channel) {
1233
+ Logger.warn(`No message channel found for sender ID: ${senderId} while emitting "${normalizedEvent}".`);
1234
+ continue;
1235
+ }
1236
+ try {
1237
+ channel.socket.port1.postMessage(createRendererEventMessage(normalizedEvent, payload));
1238
+ delivered++;
1239
+ } catch (error) {
1240
+ Logger.error(`[Noxus] Failed to emit "${normalizedEvent}" to sender ${senderId}.`, error);
1241
+ }
1242
+ }
1243
+ return delivered;
1244
+ }
1245
+ emitToRenderer(senderId, eventName, payload) {
1246
+ return this.emit(eventName, payload, [
1247
+ senderId
1248
+ ]) > 0;
1249
+ }
1250
+ };
1251
+ __name(_NoxSocket, "NoxSocket");
1252
+ var NoxSocket = _NoxSocket;
1253
+ NoxSocket = _ts_decorate2([
1254
+ Injectable("singleton")
1255
+ ], NoxSocket);
1256
+
1257
+ // src/app.ts
1258
+ function _ts_decorate3(decorators, target, key, desc) {
1259
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
1260
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
1261
+ 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;
1262
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
1263
+ }
1264
+ __name(_ts_decorate3, "_ts_decorate");
1171
1265
  function _ts_metadata(k, v) {
1172
1266
  if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
1173
1267
  }
1174
1268
  __name(_ts_metadata, "_ts_metadata");
1175
1269
  var _NoxApp = class _NoxApp {
1176
- constructor(router) {
1270
+ constructor(router, socket) {
1177
1271
  __publicField(this, "router");
1178
- __publicField(this, "messagePorts", /* @__PURE__ */ new Map());
1272
+ __publicField(this, "socket");
1179
1273
  __publicField(this, "app");
1274
+ /**
1275
+ *
1276
+ */
1277
+ __publicField(this, "onRendererMessage", /* @__PURE__ */ __name(async (event) => {
1278
+ const { senderId, requestId, path, method, body } = event.data;
1279
+ const channels = this.socket.get(senderId);
1280
+ if (!channels) {
1281
+ Logger.error(`No message channel found for sender ID: ${senderId}`);
1282
+ return;
1283
+ }
1284
+ try {
1285
+ const request = new Request(event, senderId, requestId, method, path, body);
1286
+ const response = await this.router.handle(request);
1287
+ channels.request.port1.postMessage(response);
1288
+ } catch (err) {
1289
+ const response = {
1290
+ requestId,
1291
+ status: 500,
1292
+ body: null,
1293
+ error: err.message || "Internal Server Error"
1294
+ };
1295
+ channels.request.port1.postMessage(response);
1296
+ }
1297
+ }, "onRendererMessage"));
1180
1298
  this.router = router;
1299
+ this.socket = socket;
1181
1300
  }
1182
1301
  /**
1183
1302
  * Initializes the NoxApp instance.
@@ -1199,44 +1318,22 @@ var _NoxApp = class _NoxApp {
1199
1318
  */
1200
1319
  giveTheRendererAPort(event) {
1201
1320
  const senderId = event.sender.id;
1202
- if (this.messagePorts.has(senderId)) {
1321
+ if (this.socket.get(senderId)) {
1203
1322
  this.shutdownChannel(senderId);
1204
1323
  }
1205
- const channel = new MessageChannelMain();
1206
- this.messagePorts.set(senderId, channel);
1207
- channel.port1.on("message", this.onRendererMessage.bind(this));
1208
- channel.port1.start();
1324
+ const requestChannel = new MessageChannelMain();
1325
+ const socketChannel = new MessageChannelMain();
1326
+ requestChannel.port1.on("message", this.onRendererMessage);
1327
+ requestChannel.port1.start();
1328
+ socketChannel.port1.start();
1329
+ this.socket.register(senderId, requestChannel, socketChannel);
1209
1330
  event.sender.postMessage("port", {
1210
1331
  senderId
1211
1332
  }, [
1212
- channel.port2
1333
+ requestChannel.port2,
1334
+ socketChannel.port2
1213
1335
  ]);
1214
1336
  }
1215
- /**
1216
- * Electron specific message handling.
1217
- * Replaces HTTP calls by using Electron's IPC mechanism.
1218
- */
1219
- async onRendererMessage(event) {
1220
- const { senderId, requestId, path, method, body } = event.data;
1221
- const channel = this.messagePorts.get(senderId);
1222
- if (!channel) {
1223
- Logger.error(`No message channel found for sender ID: ${senderId}`);
1224
- return;
1225
- }
1226
- try {
1227
- const request = new Request(event, requestId, method, path, body);
1228
- const response = await this.router.handle(request);
1229
- channel.port1.postMessage(response);
1230
- } catch (err) {
1231
- const response = {
1232
- requestId,
1233
- status: 500,
1234
- body: null,
1235
- error: err.message || "Internal Server Error"
1236
- };
1237
- channel.port1.postMessage(response);
1238
- }
1239
- }
1240
1337
  /**
1241
1338
  * MacOS specific behavior.
1242
1339
  */
@@ -1253,25 +1350,26 @@ var _NoxApp = class _NoxApp {
1253
1350
  * @param remove - Whether to remove the channel from the messagePorts map.
1254
1351
  */
1255
1352
  shutdownChannel(channelSenderId) {
1256
- const channel = this.messagePorts.get(channelSenderId);
1257
- if (!channel) {
1353
+ const channels = this.socket.get(channelSenderId);
1354
+ if (!channels) {
1258
1355
  Logger.warn(`No message channel found for sender ID: ${channelSenderId}`);
1259
1356
  return;
1260
1357
  }
1261
- channel.port1.off("message", this.onRendererMessage.bind(this));
1262
- channel.port1.close();
1263
- channel.port2.close();
1264
- this.messagePorts.delete(channelSenderId);
1358
+ channels.request.port1.off("message", this.onRendererMessage);
1359
+ channels.request.port1.close();
1360
+ channels.request.port2.close();
1361
+ channels.socket.port1.close();
1362
+ channels.socket.port2.close();
1363
+ this.socket.unregister(channelSenderId);
1265
1364
  }
1266
1365
  /**
1267
1366
  * Handles the application shutdown process.
1268
1367
  * This method is called when all windows are closed, and it cleans up the message channels
1269
1368
  */
1270
1369
  async onAllWindowsClosed() {
1271
- this.messagePorts.forEach((channel, senderId) => {
1370
+ for (const senderId of this.socket.getSenderIds()) {
1272
1371
  this.shutdownChannel(senderId);
1273
- });
1274
- this.messagePorts.clear();
1372
+ }
1275
1373
  Logger.info("All windows closed, shutting down application...");
1276
1374
  await this.app?.dispose();
1277
1375
  if (process.platform !== "darwin") {
@@ -1310,11 +1408,12 @@ var _NoxApp = class _NoxApp {
1310
1408
  };
1311
1409
  __name(_NoxApp, "NoxApp");
1312
1410
  var NoxApp = _NoxApp;
1313
- NoxApp = _ts_decorate2([
1411
+ NoxApp = _ts_decorate3([
1314
1412
  Injectable("singleton"),
1315
1413
  _ts_metadata("design:type", Function),
1316
1414
  _ts_metadata("design:paramtypes", [
1317
- typeof Router === "undefined" ? Object : Router
1415
+ typeof Router === "undefined" ? Object : Router,
1416
+ typeof NoxSocket === "undefined" ? Object : NoxSocket
1318
1417
  ])
1319
1418
  ], NoxApp);
1320
1419
 
@@ -1330,6 +1429,368 @@ async function bootstrapApplication(rootModule) {
1330
1429
  return noxApp;
1331
1430
  }
1332
1431
  __name(bootstrapApplication, "bootstrapApplication");
1432
+
1433
+ // src/preload-bridge.ts
1434
+ import { contextBridge, ipcRenderer } from "electron/renderer";
1435
+ var DEFAULT_EXPOSE_NAME = "noxus";
1436
+ var DEFAULT_INIT_EVENT = "init-port";
1437
+ var DEFAULT_REQUEST_CHANNEL = "gimme-my-port";
1438
+ var DEFAULT_RESPONSE_CHANNEL = "port";
1439
+ function exposeNoxusBridge(options = {}) {
1440
+ const { exposeAs = DEFAULT_EXPOSE_NAME, initMessageType = DEFAULT_INIT_EVENT, requestChannel = DEFAULT_REQUEST_CHANNEL, responseChannel = DEFAULT_RESPONSE_CHANNEL, targetWindow = window } = options;
1441
+ const api = {
1442
+ requestPort: /* @__PURE__ */ __name(() => {
1443
+ ipcRenderer.send(requestChannel);
1444
+ ipcRenderer.once(responseChannel, (event, message) => {
1445
+ const ports = (event.ports ?? []).filter((port) => port !== void 0);
1446
+ if (ports.length === 0) {
1447
+ console.error("[Noxus] No MessagePort received from main process.");
1448
+ return;
1449
+ }
1450
+ for (const port of ports) {
1451
+ try {
1452
+ port.start();
1453
+ } catch (error) {
1454
+ console.error("[Noxus] Failed to start MessagePort.", error);
1455
+ }
1456
+ }
1457
+ targetWindow.postMessage({
1458
+ type: initMessageType,
1459
+ senderId: message?.senderId
1460
+ }, "*", ports);
1461
+ });
1462
+ }, "requestPort")
1463
+ };
1464
+ contextBridge.exposeInMainWorld(exposeAs, api);
1465
+ return api;
1466
+ }
1467
+ __name(exposeNoxusBridge, "exposeNoxusBridge");
1468
+
1469
+ // src/renderer-events.ts
1470
+ var _RendererEventRegistry = class _RendererEventRegistry {
1471
+ constructor() {
1472
+ __publicField(this, "listeners", /* @__PURE__ */ new Map());
1473
+ }
1474
+ /**
1475
+ *
1476
+ */
1477
+ subscribe(eventName, handler) {
1478
+ const normalizedEventName = eventName.trim();
1479
+ if (normalizedEventName.length === 0) {
1480
+ throw new Error("Renderer event name must be a non-empty string.");
1481
+ }
1482
+ const handlers = this.listeners.get(normalizedEventName) ?? /* @__PURE__ */ new Set();
1483
+ handlers.add(handler);
1484
+ this.listeners.set(normalizedEventName, handlers);
1485
+ return {
1486
+ unsubscribe: /* @__PURE__ */ __name(() => this.unsubscribe(normalizedEventName, handler), "unsubscribe")
1487
+ };
1488
+ }
1489
+ /**
1490
+ *
1491
+ */
1492
+ unsubscribe(eventName, handler) {
1493
+ const handlers = this.listeners.get(eventName);
1494
+ if (!handlers) {
1495
+ return;
1496
+ }
1497
+ handlers.delete(handler);
1498
+ if (handlers.size === 0) {
1499
+ this.listeners.delete(eventName);
1500
+ }
1501
+ }
1502
+ /**
1503
+ *
1504
+ */
1505
+ clear(eventName) {
1506
+ if (eventName) {
1507
+ this.listeners.delete(eventName);
1508
+ return;
1509
+ }
1510
+ this.listeners.clear();
1511
+ }
1512
+ /**
1513
+ *
1514
+ */
1515
+ dispatch(message) {
1516
+ const handlers = this.listeners.get(message.event);
1517
+ if (!handlers || handlers.size === 0) {
1518
+ return;
1519
+ }
1520
+ handlers.forEach((handler) => {
1521
+ try {
1522
+ handler(message.payload);
1523
+ } catch (error) {
1524
+ console.error(`[Noxus] Renderer event handler for "${message.event}" threw an error.`, error);
1525
+ }
1526
+ });
1527
+ }
1528
+ /**
1529
+ *
1530
+ */
1531
+ tryDispatchFromMessageEvent(event) {
1532
+ if (!isRendererEventMessage(event.data)) {
1533
+ return false;
1534
+ }
1535
+ this.dispatch(event.data);
1536
+ return true;
1537
+ }
1538
+ /**
1539
+ *
1540
+ */
1541
+ hasHandlers(eventName) {
1542
+ const handlers = this.listeners.get(eventName);
1543
+ return !!handlers && handlers.size > 0;
1544
+ }
1545
+ };
1546
+ __name(_RendererEventRegistry, "RendererEventRegistry");
1547
+ var RendererEventRegistry = _RendererEventRegistry;
1548
+
1549
+ // src/renderer-client.ts
1550
+ var DEFAULT_INIT_EVENT2 = "init-port";
1551
+ var DEFAULT_BRIDGE_NAMES = [
1552
+ "noxus",
1553
+ "ipcRenderer"
1554
+ ];
1555
+ function defaultRequestId() {
1556
+ if (typeof crypto !== "undefined" && typeof crypto.randomUUID === "function") {
1557
+ return crypto.randomUUID();
1558
+ }
1559
+ return `${Date.now().toString(16)}-${Math.floor(Math.random() * 1e8).toString(16)}`;
1560
+ }
1561
+ __name(defaultRequestId, "defaultRequestId");
1562
+ function normalizeBridgeNames(preferred) {
1563
+ const names = [];
1564
+ const add = /* @__PURE__ */ __name((name) => {
1565
+ if (!name) return;
1566
+ if (!names.includes(name)) {
1567
+ names.push(name);
1568
+ }
1569
+ }, "add");
1570
+ if (Array.isArray(preferred)) {
1571
+ for (const name of preferred) {
1572
+ add(name);
1573
+ }
1574
+ } else {
1575
+ add(preferred);
1576
+ }
1577
+ for (const fallback of DEFAULT_BRIDGE_NAMES) {
1578
+ add(fallback);
1579
+ }
1580
+ return names;
1581
+ }
1582
+ __name(normalizeBridgeNames, "normalizeBridgeNames");
1583
+ function resolveBridgeFromWindow(windowRef, preferred) {
1584
+ const names = normalizeBridgeNames(preferred);
1585
+ const globalRef = windowRef;
1586
+ if (!globalRef) {
1587
+ return null;
1588
+ }
1589
+ for (const name of names) {
1590
+ const candidate = globalRef[name];
1591
+ if (candidate && typeof candidate.requestPort === "function") {
1592
+ return candidate;
1593
+ }
1594
+ }
1595
+ return null;
1596
+ }
1597
+ __name(resolveBridgeFromWindow, "resolveBridgeFromWindow");
1598
+ var _NoxRendererClient = class _NoxRendererClient {
1599
+ constructor(options = {}) {
1600
+ __publicField(this, "events", new RendererEventRegistry());
1601
+ __publicField(this, "pendingRequests", /* @__PURE__ */ new Map());
1602
+ __publicField(this, "requestPort");
1603
+ __publicField(this, "socketPort");
1604
+ __publicField(this, "senderId");
1605
+ __publicField(this, "bridge");
1606
+ __publicField(this, "initMessageType");
1607
+ __publicField(this, "windowRef");
1608
+ __publicField(this, "generateRequestId");
1609
+ __publicField(this, "isReady", false);
1610
+ __publicField(this, "setupPromise");
1611
+ __publicField(this, "setupResolve");
1612
+ __publicField(this, "setupReject");
1613
+ __publicField(this, "onWindowMessage", /* @__PURE__ */ __name((event) => {
1614
+ if (event.data?.type !== this.initMessageType) {
1615
+ return;
1616
+ }
1617
+ if (!Array.isArray(event.ports) || event.ports.length < 2) {
1618
+ const error = new Error("[Noxus] Renderer expected two MessagePorts (request + socket).");
1619
+ console.error(error);
1620
+ this.setupReject?.(error);
1621
+ this.resetSetupState();
1622
+ return;
1623
+ }
1624
+ this.windowRef.removeEventListener("message", this.onWindowMessage);
1625
+ this.requestPort = event.ports[0];
1626
+ this.socketPort = event.ports[1];
1627
+ this.senderId = event.data.senderId;
1628
+ if (this.requestPort === void 0 || this.socketPort === void 0) {
1629
+ const error = new Error("[Noxus] Renderer failed to receive valid MessagePorts.");
1630
+ console.error(error);
1631
+ this.setupReject?.(error);
1632
+ this.resetSetupState();
1633
+ return;
1634
+ }
1635
+ this.attachRequestPort(this.requestPort);
1636
+ this.attachSocketPort(this.socketPort);
1637
+ this.isReady = true;
1638
+ this.setupResolve?.();
1639
+ this.resetSetupState(true);
1640
+ }, "onWindowMessage"));
1641
+ __publicField(this, "onSocketMessage", /* @__PURE__ */ __name((event) => {
1642
+ if (this.events.tryDispatchFromMessageEvent(event)) {
1643
+ return;
1644
+ }
1645
+ console.warn("[Noxus] Received a socket message that is not a renderer event payload.", event.data);
1646
+ }, "onSocketMessage"));
1647
+ __publicField(this, "onRequestMessage", /* @__PURE__ */ __name((event) => {
1648
+ if (this.events.tryDispatchFromMessageEvent(event)) {
1649
+ return;
1650
+ }
1651
+ const response = event.data;
1652
+ if (!response || typeof response.requestId !== "string") {
1653
+ console.error("[Noxus] Renderer received an invalid response payload.", response);
1654
+ return;
1655
+ }
1656
+ const pending = this.pendingRequests.get(response.requestId);
1657
+ if (!pending) {
1658
+ console.error(`[Noxus] No pending handler found for request ${response.requestId}.`);
1659
+ return;
1660
+ }
1661
+ this.pendingRequests.delete(response.requestId);
1662
+ this.onRequestCompleted(pending, response);
1663
+ if (response.status >= 400) {
1664
+ pending.reject(response);
1665
+ return;
1666
+ }
1667
+ pending.resolve(response.body);
1668
+ }, "onRequestMessage"));
1669
+ this.windowRef = options.windowRef ?? window;
1670
+ const resolvedBridge = options.bridge ?? resolveBridgeFromWindow(this.windowRef, options.bridgeName);
1671
+ this.bridge = resolvedBridge ?? null;
1672
+ this.initMessageType = options.initMessageType ?? DEFAULT_INIT_EVENT2;
1673
+ this.generateRequestId = options.generateRequestId ?? defaultRequestId;
1674
+ }
1675
+ async setup() {
1676
+ if (this.isReady) {
1677
+ return Promise.resolve();
1678
+ }
1679
+ if (this.setupPromise) {
1680
+ return this.setupPromise;
1681
+ }
1682
+ if (!this.bridge || typeof this.bridge.requestPort !== "function") {
1683
+ throw new Error("[Noxus] Renderer bridge is missing requestPort().");
1684
+ }
1685
+ this.setupPromise = new Promise((resolve, reject) => {
1686
+ this.setupResolve = resolve;
1687
+ this.setupReject = reject;
1688
+ });
1689
+ this.windowRef.addEventListener("message", this.onWindowMessage);
1690
+ this.bridge.requestPort();
1691
+ return this.setupPromise;
1692
+ }
1693
+ dispose() {
1694
+ this.windowRef.removeEventListener("message", this.onWindowMessage);
1695
+ this.requestPort?.close();
1696
+ this.socketPort?.close();
1697
+ this.requestPort = void 0;
1698
+ this.socketPort = void 0;
1699
+ this.senderId = void 0;
1700
+ this.isReady = false;
1701
+ this.pendingRequests.clear();
1702
+ }
1703
+ async request(request) {
1704
+ const senderId = this.senderId;
1705
+ const requestId = this.generateRequestId();
1706
+ if (senderId === void 0) {
1707
+ return Promise.reject(this.createErrorResponse(requestId, "MessagePort is not available"));
1708
+ }
1709
+ const readinessError = this.validateReady(requestId);
1710
+ if (readinessError) {
1711
+ return Promise.reject(readinessError);
1712
+ }
1713
+ const message = {
1714
+ requestId,
1715
+ senderId,
1716
+ ...request
1717
+ };
1718
+ return new Promise((resolve, reject) => {
1719
+ const pending = {
1720
+ resolve,
1721
+ reject: /* @__PURE__ */ __name((response) => reject(response), "reject"),
1722
+ request: message,
1723
+ submittedAt: Date.now()
1724
+ };
1725
+ this.pendingRequests.set(message.requestId, pending);
1726
+ this.requestPort.postMessage(message);
1727
+ });
1728
+ }
1729
+ async batch(requests) {
1730
+ return this.request({
1731
+ method: "BATCH",
1732
+ path: "",
1733
+ body: {
1734
+ requests
1735
+ }
1736
+ });
1737
+ }
1738
+ getSenderId() {
1739
+ return this.senderId;
1740
+ }
1741
+ onRequestCompleted(pending, response) {
1742
+ if (typeof console.groupCollapsed === "function") {
1743
+ console.groupCollapsed(`${response.status} ${pending.request.method} /${pending.request.path}`);
1744
+ }
1745
+ if (response.error) {
1746
+ console.error("error message:", response.error);
1747
+ }
1748
+ if (response.body !== void 0) {
1749
+ console.info("response:", response.body);
1750
+ }
1751
+ console.info("request:", pending.request);
1752
+ console.info(`Request duration: ${Date.now() - pending.submittedAt} ms`);
1753
+ if (typeof console.groupCollapsed === "function") {
1754
+ console.groupEnd();
1755
+ }
1756
+ }
1757
+ attachRequestPort(port) {
1758
+ port.onmessage = this.onRequestMessage;
1759
+ port.start();
1760
+ }
1761
+ attachSocketPort(port) {
1762
+ port.onmessage = this.onSocketMessage;
1763
+ port.start();
1764
+ }
1765
+ validateReady(requestId) {
1766
+ if (!this.isElectronEnvironment()) {
1767
+ return this.createErrorResponse(requestId, "Not running in Electron environment");
1768
+ }
1769
+ if (!this.requestPort) {
1770
+ return this.createErrorResponse(requestId, "MessagePort is not available");
1771
+ }
1772
+ return void 0;
1773
+ }
1774
+ createErrorResponse(requestId, message) {
1775
+ return {
1776
+ status: 500,
1777
+ requestId,
1778
+ error: message
1779
+ };
1780
+ }
1781
+ resetSetupState(success = false) {
1782
+ if (!success) {
1783
+ this.setupPromise = void 0;
1784
+ }
1785
+ this.setupResolve = void 0;
1786
+ this.setupReject = void 0;
1787
+ }
1788
+ isElectronEnvironment() {
1789
+ return typeof window !== "undefined" && /Electron/.test(window.navigator.userAgent);
1790
+ }
1791
+ };
1792
+ __name(_NoxRendererClient, "NoxRendererClient");
1793
+ var NoxRendererClient = _NoxRendererClient;
1333
1794
  export {
1334
1795
  AppInjector,
1335
1796
  Authorize,
@@ -1359,11 +1820,15 @@ export {
1359
1820
  NotFoundException,
1360
1821
  NotImplementedException,
1361
1822
  NoxApp,
1823
+ NoxRendererClient,
1824
+ NoxSocket,
1362
1825
  Patch,
1363
1826
  PaymentRequiredException,
1364
1827
  Post,
1365
1828
  Put,
1829
+ RENDERER_EVENT_TYPE,
1366
1830
  ROUTE_METADATA_KEY,
1831
+ RendererEventRegistry,
1367
1832
  Request,
1368
1833
  RequestTimeoutException,
1369
1834
  ResponseException,
@@ -1376,6 +1841,8 @@ export {
1376
1841
  UseMiddlewares,
1377
1842
  VariantAlsoNegotiatesException,
1378
1843
  bootstrapApplication,
1844
+ createRendererEventMessage,
1845
+ exposeNoxusBridge,
1379
1846
  getControllerMetadata,
1380
1847
  getGuardForController,
1381
1848
  getGuardForControllerAction,
@@ -1384,11 +1851,13 @@ export {
1384
1851
  getMiddlewaresForControllerAction,
1385
1852
  getModuleMetadata,
1386
1853
  getRouteMetadata,
1387
- inject
1854
+ hasInjectableMetadata,
1855
+ inject,
1856
+ isRendererEventMessage
1388
1857
  };
1389
1858
  /**
1390
1859
  * @copyright 2025 NoxFly
1391
1860
  * @license MIT
1392
1861
  * @author NoxFly
1393
1862
  */
1394
- //# sourceMappingURL=noxus.mjs.map
1863
+ //# sourceMappingURL=main.mjs.map