@noxfly/noxus 2.4.0 → 2.5.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/child.js +115 -10
- package/dist/child.mjs +115 -10
- package/dist/main.d.mts +72 -21
- package/dist/main.d.ts +72 -21
- package/dist/main.js +160 -381
- package/dist/main.mjs +161 -379
- package/dist/renderer.d.mts +112 -1
- package/dist/renderer.d.ts +112 -1
- package/dist/renderer.js +40 -2
- package/dist/renderer.mjs +39 -2
- package/dist/{index-BxWQVi6C.d.ts → request-CdpZ9qZL.d.ts} +1 -87
- package/dist/{index-DQBQQfMw.d.mts → request-Dx_5Prte.d.mts} +1 -87
- package/package.json +1 -1
- package/src/DI/injector-explorer.ts +49 -4
- package/src/app.ts +37 -0
- package/src/bootstrap.ts +18 -3
- package/src/index.ts +1 -0
- package/src/main.ts +0 -3
- package/src/router.ts +99 -6
package/dist/main.js
CHANGED
|
@@ -69,7 +69,6 @@ __export(main_exports, {
|
|
|
69
69
|
NotFoundException: () => NotFoundException,
|
|
70
70
|
NotImplementedException: () => NotImplementedException,
|
|
71
71
|
NoxApp: () => NoxApp,
|
|
72
|
-
NoxRendererClient: () => NoxRendererClient,
|
|
73
72
|
NoxSocket: () => NoxSocket,
|
|
74
73
|
Patch: () => Patch,
|
|
75
74
|
PaymentRequiredException: () => PaymentRequiredException,
|
|
@@ -77,7 +76,6 @@ __export(main_exports, {
|
|
|
77
76
|
Put: () => Put,
|
|
78
77
|
RENDERER_EVENT_TYPE: () => RENDERER_EVENT_TYPE,
|
|
79
78
|
ROUTE_METADATA_KEY: () => ROUTE_METADATA_KEY,
|
|
80
|
-
RendererEventRegistry: () => RendererEventRegistry,
|
|
81
79
|
Request: () => Request,
|
|
82
80
|
RequestTimeoutException: () => RequestTimeoutException,
|
|
83
81
|
ResponseException: () => ResponseException,
|
|
@@ -91,7 +89,6 @@ __export(main_exports, {
|
|
|
91
89
|
VariantAlsoNegotiatesException: () => VariantAlsoNegotiatesException,
|
|
92
90
|
bootstrapApplication: () => bootstrapApplication,
|
|
93
91
|
createRendererEventMessage: () => createRendererEventMessage,
|
|
94
|
-
exposeNoxusBridge: () => exposeNoxusBridge,
|
|
95
92
|
forwardRef: () => forwardRef,
|
|
96
93
|
getControllerMetadata: () => getControllerMetadata,
|
|
97
94
|
getGuardForController: () => getGuardForController,
|
|
@@ -828,12 +825,17 @@ var _InjectorExplorer = class _InjectorExplorer {
|
|
|
828
825
|
* Enqueues a class for deferred registration.
|
|
829
826
|
* Called by the @Injectable decorator at import time.
|
|
830
827
|
*
|
|
831
|
-
* If {@link processPending} has already been called (i.e. after bootstrap)
|
|
832
|
-
*
|
|
833
|
-
* (e.g. middlewares loaded after bootstrap)
|
|
828
|
+
* If {@link processPending} has already been called (i.e. after bootstrap)
|
|
829
|
+
* and accumulation mode is not active, the class is registered immediately
|
|
830
|
+
* so that late dynamic imports (e.g. middlewares loaded after bootstrap)
|
|
831
|
+
* work correctly.
|
|
832
|
+
*
|
|
833
|
+
* When accumulation mode is active (between {@link beginAccumulate} and
|
|
834
|
+
* {@link flushAccumulated}), classes are queued instead — preserving the
|
|
835
|
+
* two-phase binding/resolution guarantee for lazy-loaded modules.
|
|
834
836
|
*/
|
|
835
837
|
static enqueue(target, lifetime) {
|
|
836
|
-
if (_InjectorExplorer.processed) {
|
|
838
|
+
if (_InjectorExplorer.processed && !_InjectorExplorer.accumulating) {
|
|
837
839
|
_InjectorExplorer.registerImmediate(target, lifetime);
|
|
838
840
|
return;
|
|
839
841
|
}
|
|
@@ -842,6 +844,40 @@ var _InjectorExplorer = class _InjectorExplorer {
|
|
|
842
844
|
lifetime
|
|
843
845
|
});
|
|
844
846
|
}
|
|
847
|
+
/**
|
|
848
|
+
* Enters accumulation mode. While active, all decorated classes discovered
|
|
849
|
+
* via dynamic imports are queued in {@link pending} rather than registered
|
|
850
|
+
* immediately. Call {@link flushAccumulated} to process them with the
|
|
851
|
+
* full two-phase (bind-then-resolve) guarantee.
|
|
852
|
+
*/
|
|
853
|
+
static beginAccumulate() {
|
|
854
|
+
_InjectorExplorer.accumulating = true;
|
|
855
|
+
}
|
|
856
|
+
/**
|
|
857
|
+
* Exits accumulation mode and processes every class queued since
|
|
858
|
+
* {@link beginAccumulate} was called. Uses the same two-phase strategy
|
|
859
|
+
* as {@link processPending} (register all bindings first, then resolve
|
|
860
|
+
* singletons / controllers) so import ordering within a lazy batch
|
|
861
|
+
* does not cause resolution failures.
|
|
862
|
+
*/
|
|
863
|
+
static flushAccumulated() {
|
|
864
|
+
_InjectorExplorer.accumulating = false;
|
|
865
|
+
const queue = [
|
|
866
|
+
..._InjectorExplorer.pending
|
|
867
|
+
];
|
|
868
|
+
_InjectorExplorer.pending.length = 0;
|
|
869
|
+
for (const { target, lifetime } of queue) {
|
|
870
|
+
if (!RootInjector.bindings.has(target)) {
|
|
871
|
+
RootInjector.bindings.set(target, {
|
|
872
|
+
implementation: target,
|
|
873
|
+
lifetime
|
|
874
|
+
});
|
|
875
|
+
}
|
|
876
|
+
}
|
|
877
|
+
for (const { target, lifetime } of queue) {
|
|
878
|
+
_InjectorExplorer.processRegistration(target, lifetime);
|
|
879
|
+
}
|
|
880
|
+
}
|
|
845
881
|
/**
|
|
846
882
|
* Processes all pending registrations in two phases:
|
|
847
883
|
* 1. Register all bindings (no instantiation) so every dependency is known.
|
|
@@ -909,6 +945,7 @@ var _InjectorExplorer = class _InjectorExplorer {
|
|
|
909
945
|
__name(_InjectorExplorer, "InjectorExplorer");
|
|
910
946
|
__publicField(_InjectorExplorer, "pending", []);
|
|
911
947
|
__publicField(_InjectorExplorer, "processed", false);
|
|
948
|
+
__publicField(_InjectorExplorer, "accumulating", false);
|
|
912
949
|
var InjectorExplorer = _InjectorExplorer;
|
|
913
950
|
|
|
914
951
|
// src/decorators/injectable.decorator.ts
|
|
@@ -1193,6 +1230,7 @@ var _Router = class _Router {
|
|
|
1193
1230
|
constructor() {
|
|
1194
1231
|
__publicField(this, "routes", new RadixTree());
|
|
1195
1232
|
__publicField(this, "rootMiddlewares", []);
|
|
1233
|
+
__publicField(this, "lazyRoutes", /* @__PURE__ */ new Map());
|
|
1196
1234
|
}
|
|
1197
1235
|
/**
|
|
1198
1236
|
* Registers a controller class with the router.
|
|
@@ -1240,6 +1278,24 @@ var _Router = class _Router {
|
|
|
1240
1278
|
Logger.log(`Mapped ${controllerClass.name}${controllerGuardsInfo} controller's routes`);
|
|
1241
1279
|
return this;
|
|
1242
1280
|
}
|
|
1281
|
+
/**
|
|
1282
|
+
* Registers a lazy route. The module behind this route prefix will only
|
|
1283
|
+
* be imported (and its controllers/services registered in DI) the first
|
|
1284
|
+
* time a request targets this prefix.
|
|
1285
|
+
*
|
|
1286
|
+
* @param pathPrefix - Route prefix (e.g. "auth"). Matched against the first segment of the request path.
|
|
1287
|
+
* @param loadModule - A function that returns a dynamic import promise.
|
|
1288
|
+
*/
|
|
1289
|
+
registerLazyRoute(pathPrefix, loadModule) {
|
|
1290
|
+
const normalized = pathPrefix.replace(/^\/+|\/+$/g, "");
|
|
1291
|
+
this.lazyRoutes.set(normalized, {
|
|
1292
|
+
loadModule,
|
|
1293
|
+
loading: null,
|
|
1294
|
+
loaded: false
|
|
1295
|
+
});
|
|
1296
|
+
Logger.log(`Registered lazy route prefix {${normalized}}`);
|
|
1297
|
+
return this;
|
|
1298
|
+
}
|
|
1243
1299
|
/**
|
|
1244
1300
|
* Defines a middleware for the root of the application.
|
|
1245
1301
|
* This method allows you to register a middleware that will be applied to all requests
|
|
@@ -1272,7 +1328,7 @@ var _Router = class _Router {
|
|
|
1272
1328
|
};
|
|
1273
1329
|
let isCritical = false;
|
|
1274
1330
|
try {
|
|
1275
|
-
const routeDef = this.findRoute(request);
|
|
1331
|
+
const routeDef = await this.findRoute(request);
|
|
1276
1332
|
await this.resolveController(request, response, routeDef);
|
|
1277
1333
|
if (response.status > 400) {
|
|
1278
1334
|
throw new ResponseException(response.status, response.error);
|
|
@@ -1430,16 +1486,62 @@ var _Router = class _Router {
|
|
|
1430
1486
|
* @param request - The Request object containing the method and path to search for.
|
|
1431
1487
|
* @returns The IRouteDefinition for the matched route.
|
|
1432
1488
|
*/
|
|
1433
|
-
|
|
1489
|
+
/**
|
|
1490
|
+
* Attempts to find a route definition for the given request.
|
|
1491
|
+
* Returns undefined instead of throwing when the route is not found,
|
|
1492
|
+
* so the caller can try lazy-loading first.
|
|
1493
|
+
*/
|
|
1494
|
+
tryFindRoute(request) {
|
|
1434
1495
|
const matchedRoutes = this.routes.search(request.path);
|
|
1435
1496
|
if (matchedRoutes?.node === void 0 || matchedRoutes.node.children.length === 0) {
|
|
1436
|
-
|
|
1497
|
+
return void 0;
|
|
1437
1498
|
}
|
|
1438
1499
|
const routeDef = matchedRoutes.node.findExactChild(request.method);
|
|
1439
|
-
|
|
1440
|
-
|
|
1500
|
+
return routeDef?.value;
|
|
1501
|
+
}
|
|
1502
|
+
/**
|
|
1503
|
+
* Finds the route definition for a given request.
|
|
1504
|
+
* If no eagerly-registered route matches, attempts to load a lazy module
|
|
1505
|
+
* whose prefix matches the request path, then retries.
|
|
1506
|
+
*/
|
|
1507
|
+
async findRoute(request) {
|
|
1508
|
+
const direct = this.tryFindRoute(request);
|
|
1509
|
+
if (direct) return direct;
|
|
1510
|
+
await this.tryLoadLazyRoute(request.path);
|
|
1511
|
+
const afterLazy = this.tryFindRoute(request);
|
|
1512
|
+
if (afterLazy) return afterLazy;
|
|
1513
|
+
throw new NotFoundException(`No route matches ${request.method} ${request.path}`);
|
|
1514
|
+
}
|
|
1515
|
+
/**
|
|
1516
|
+
* Given a request path, checks whether a lazy route prefix matches
|
|
1517
|
+
* and triggers the dynamic import if it hasn't been loaded yet.
|
|
1518
|
+
*/
|
|
1519
|
+
async tryLoadLazyRoute(requestPath) {
|
|
1520
|
+
const firstSegment = requestPath.replace(/^\/+/, "").split("/")[0] ?? "";
|
|
1521
|
+
for (const [prefix, entry] of this.lazyRoutes) {
|
|
1522
|
+
if (entry.loaded) continue;
|
|
1523
|
+
const normalizedPath = requestPath.replace(/^\/+/, "");
|
|
1524
|
+
if (normalizedPath === prefix || normalizedPath.startsWith(prefix + "/") || firstSegment === prefix) {
|
|
1525
|
+
if (!entry.loading) {
|
|
1526
|
+
entry.loading = this.loadLazyModule(prefix, entry);
|
|
1527
|
+
}
|
|
1528
|
+
await entry.loading;
|
|
1529
|
+
return;
|
|
1530
|
+
}
|
|
1441
1531
|
}
|
|
1442
|
-
|
|
1532
|
+
}
|
|
1533
|
+
/**
|
|
1534
|
+
* Dynamically imports a lazy module and registers its decorated classes
|
|
1535
|
+
* (controllers, services) in the DI container using the two-phase strategy.
|
|
1536
|
+
*/
|
|
1537
|
+
async loadLazyModule(prefix, entry) {
|
|
1538
|
+
const t0 = performance.now();
|
|
1539
|
+
InjectorExplorer.beginAccumulate();
|
|
1540
|
+
await entry.loadModule();
|
|
1541
|
+
InjectorExplorer.flushAccumulated();
|
|
1542
|
+
entry.loaded = true;
|
|
1543
|
+
const t1 = performance.now();
|
|
1544
|
+
Logger.info(`Lazy-loaded module for prefix {${prefix}} in ${Math.round(t1 - t0)}ms`);
|
|
1443
1545
|
}
|
|
1444
1546
|
/**
|
|
1445
1547
|
* Resolves the controller for a given route definition.
|
|
@@ -1752,8 +1854,42 @@ var _NoxApp = class _NoxApp {
|
|
|
1752
1854
|
* This window will be passed to IApp.onReady when start() is called.
|
|
1753
1855
|
* @param window - The BrowserWindow created during bootstrap.
|
|
1754
1856
|
*/
|
|
1755
|
-
setMainWindow(
|
|
1756
|
-
this.mainWindow =
|
|
1857
|
+
setMainWindow(window) {
|
|
1858
|
+
this.mainWindow = window;
|
|
1859
|
+
}
|
|
1860
|
+
/**
|
|
1861
|
+
* Registers a lazy-loaded route. The module behind this path prefix
|
|
1862
|
+
* will only be dynamically imported when the first IPC request
|
|
1863
|
+
* targets this prefix — like Angular's loadChildren.
|
|
1864
|
+
*
|
|
1865
|
+
* @example
|
|
1866
|
+
* ```ts
|
|
1867
|
+
* noxApp.lazy("auth", () => import("./modules/auth/auth.module.js"));
|
|
1868
|
+
* noxApp.lazy("printing", () => import("./modules/printing/printing.module.js"));
|
|
1869
|
+
* ```
|
|
1870
|
+
*
|
|
1871
|
+
* @param pathPrefix - The route prefix (e.g. "auth", "cash-register").
|
|
1872
|
+
* @param loadModule - A function returning a dynamic import promise.
|
|
1873
|
+
* @returns NoxApp instance for method chaining.
|
|
1874
|
+
*/
|
|
1875
|
+
lazy(pathPrefix, loadModule) {
|
|
1876
|
+
this.router.registerLazyRoute(pathPrefix, loadModule);
|
|
1877
|
+
return this;
|
|
1878
|
+
}
|
|
1879
|
+
/**
|
|
1880
|
+
* Eagerly loads one or more modules with a two-phase DI guarantee.
|
|
1881
|
+
* Use this when a service needed at startup lives inside a module
|
|
1882
|
+
* (e.g. the Application service depends on LoaderService).
|
|
1883
|
+
*
|
|
1884
|
+
* All dynamic imports run in parallel; bindings are registered first,
|
|
1885
|
+
* then singletons are resolved — safe regardless of import ordering.
|
|
1886
|
+
*
|
|
1887
|
+
* @param importFns - Functions returning dynamic import promises.
|
|
1888
|
+
*/
|
|
1889
|
+
async loadModules(importFns) {
|
|
1890
|
+
InjectorExplorer.beginAccumulate();
|
|
1891
|
+
await Promise.all(importFns.map((fn) => fn()));
|
|
1892
|
+
InjectorExplorer.flushAccumulated();
|
|
1757
1893
|
}
|
|
1758
1894
|
/**
|
|
1759
1895
|
* Configures the NoxApp instance with the provided application class.
|
|
@@ -1799,13 +1935,21 @@ NoxApp = _ts_decorate3([
|
|
|
1799
1935
|
// src/bootstrap.ts
|
|
1800
1936
|
var import_main2 = require("electron/main");
|
|
1801
1937
|
async function bootstrapApplication(rootModule, options) {
|
|
1802
|
-
if (!getModuleMetadata(rootModule)) {
|
|
1938
|
+
if (rootModule && !getModuleMetadata(rootModule)) {
|
|
1803
1939
|
throw new Error(`Root module must be decorated with @Module`);
|
|
1804
1940
|
}
|
|
1805
1941
|
await import_main2.app.whenReady();
|
|
1806
1942
|
let mainWindow;
|
|
1807
1943
|
if (options?.window) {
|
|
1808
1944
|
mainWindow = new import_main2.BrowserWindow(options.window);
|
|
1945
|
+
mainWindow.once("ready-to-show", () => {
|
|
1946
|
+
mainWindow?.show();
|
|
1947
|
+
});
|
|
1948
|
+
const primaryDisplay = import_main2.screen.getPrimaryDisplay();
|
|
1949
|
+
const { width, height } = primaryDisplay.workAreaSize;
|
|
1950
|
+
if (options.window.minWidth && options.window.minHeight) {
|
|
1951
|
+
mainWindow.setSize(Math.min(width, options.window.minWidth), Math.min(height, options.window.minHeight), true);
|
|
1952
|
+
}
|
|
1809
1953
|
}
|
|
1810
1954
|
InjectorExplorer.processPending();
|
|
1811
1955
|
const noxApp = inject(NoxApp);
|
|
@@ -1816,368 +1960,6 @@ async function bootstrapApplication(rootModule, options) {
|
|
|
1816
1960
|
return noxApp;
|
|
1817
1961
|
}
|
|
1818
1962
|
__name(bootstrapApplication, "bootstrapApplication");
|
|
1819
|
-
|
|
1820
|
-
// src/preload-bridge.ts
|
|
1821
|
-
var import_renderer = require("electron/renderer");
|
|
1822
|
-
var DEFAULT_EXPOSE_NAME = "noxus";
|
|
1823
|
-
var DEFAULT_INIT_EVENT = "init-port";
|
|
1824
|
-
var DEFAULT_REQUEST_CHANNEL = "gimme-my-port";
|
|
1825
|
-
var DEFAULT_RESPONSE_CHANNEL = "port";
|
|
1826
|
-
function exposeNoxusBridge(options = {}) {
|
|
1827
|
-
const { exposeAs = DEFAULT_EXPOSE_NAME, initMessageType = DEFAULT_INIT_EVENT, requestChannel = DEFAULT_REQUEST_CHANNEL, responseChannel = DEFAULT_RESPONSE_CHANNEL, targetWindow = window } = options;
|
|
1828
|
-
const api = {
|
|
1829
|
-
requestPort: /* @__PURE__ */ __name(() => {
|
|
1830
|
-
import_renderer.ipcRenderer.send(requestChannel);
|
|
1831
|
-
import_renderer.ipcRenderer.once(responseChannel, (event, message) => {
|
|
1832
|
-
const ports = (event.ports ?? []).filter((port) => port !== void 0);
|
|
1833
|
-
if (ports.length === 0) {
|
|
1834
|
-
console.error("[Noxus] No MessagePort received from main process.");
|
|
1835
|
-
return;
|
|
1836
|
-
}
|
|
1837
|
-
for (const port of ports) {
|
|
1838
|
-
try {
|
|
1839
|
-
port.start();
|
|
1840
|
-
} catch (error) {
|
|
1841
|
-
console.error("[Noxus] Failed to start MessagePort.", error);
|
|
1842
|
-
}
|
|
1843
|
-
}
|
|
1844
|
-
targetWindow.postMessage({
|
|
1845
|
-
type: initMessageType,
|
|
1846
|
-
senderId: message?.senderId
|
|
1847
|
-
}, "*", ports);
|
|
1848
|
-
});
|
|
1849
|
-
}, "requestPort")
|
|
1850
|
-
};
|
|
1851
|
-
import_renderer.contextBridge.exposeInMainWorld(exposeAs, api);
|
|
1852
|
-
return api;
|
|
1853
|
-
}
|
|
1854
|
-
__name(exposeNoxusBridge, "exposeNoxusBridge");
|
|
1855
|
-
|
|
1856
|
-
// src/renderer-events.ts
|
|
1857
|
-
var _RendererEventRegistry = class _RendererEventRegistry {
|
|
1858
|
-
constructor() {
|
|
1859
|
-
__publicField(this, "listeners", /* @__PURE__ */ new Map());
|
|
1860
|
-
}
|
|
1861
|
-
/**
|
|
1862
|
-
*
|
|
1863
|
-
*/
|
|
1864
|
-
subscribe(eventName, handler) {
|
|
1865
|
-
const normalizedEventName = eventName.trim();
|
|
1866
|
-
if (normalizedEventName.length === 0) {
|
|
1867
|
-
throw new Error("Renderer event name must be a non-empty string.");
|
|
1868
|
-
}
|
|
1869
|
-
const handlers = this.listeners.get(normalizedEventName) ?? /* @__PURE__ */ new Set();
|
|
1870
|
-
handlers.add(handler);
|
|
1871
|
-
this.listeners.set(normalizedEventName, handlers);
|
|
1872
|
-
return {
|
|
1873
|
-
unsubscribe: /* @__PURE__ */ __name(() => this.unsubscribe(normalizedEventName, handler), "unsubscribe")
|
|
1874
|
-
};
|
|
1875
|
-
}
|
|
1876
|
-
/**
|
|
1877
|
-
*
|
|
1878
|
-
*/
|
|
1879
|
-
unsubscribe(eventName, handler) {
|
|
1880
|
-
const handlers = this.listeners.get(eventName);
|
|
1881
|
-
if (!handlers) {
|
|
1882
|
-
return;
|
|
1883
|
-
}
|
|
1884
|
-
handlers.delete(handler);
|
|
1885
|
-
if (handlers.size === 0) {
|
|
1886
|
-
this.listeners.delete(eventName);
|
|
1887
|
-
}
|
|
1888
|
-
}
|
|
1889
|
-
/**
|
|
1890
|
-
*
|
|
1891
|
-
*/
|
|
1892
|
-
clear(eventName) {
|
|
1893
|
-
if (eventName) {
|
|
1894
|
-
this.listeners.delete(eventName);
|
|
1895
|
-
return;
|
|
1896
|
-
}
|
|
1897
|
-
this.listeners.clear();
|
|
1898
|
-
}
|
|
1899
|
-
/**
|
|
1900
|
-
*
|
|
1901
|
-
*/
|
|
1902
|
-
dispatch(message) {
|
|
1903
|
-
const handlers = this.listeners.get(message.event);
|
|
1904
|
-
if (!handlers || handlers.size === 0) {
|
|
1905
|
-
return;
|
|
1906
|
-
}
|
|
1907
|
-
handlers.forEach((handler) => {
|
|
1908
|
-
try {
|
|
1909
|
-
handler(message.payload);
|
|
1910
|
-
} catch (error) {
|
|
1911
|
-
console.error(`[Noxus] Renderer event handler for "${message.event}" threw an error.`, error);
|
|
1912
|
-
}
|
|
1913
|
-
});
|
|
1914
|
-
}
|
|
1915
|
-
/**
|
|
1916
|
-
*
|
|
1917
|
-
*/
|
|
1918
|
-
tryDispatchFromMessageEvent(event) {
|
|
1919
|
-
if (!isRendererEventMessage(event.data)) {
|
|
1920
|
-
return false;
|
|
1921
|
-
}
|
|
1922
|
-
this.dispatch(event.data);
|
|
1923
|
-
return true;
|
|
1924
|
-
}
|
|
1925
|
-
/**
|
|
1926
|
-
*
|
|
1927
|
-
*/
|
|
1928
|
-
hasHandlers(eventName) {
|
|
1929
|
-
const handlers = this.listeners.get(eventName);
|
|
1930
|
-
return !!handlers && handlers.size > 0;
|
|
1931
|
-
}
|
|
1932
|
-
};
|
|
1933
|
-
__name(_RendererEventRegistry, "RendererEventRegistry");
|
|
1934
|
-
var RendererEventRegistry = _RendererEventRegistry;
|
|
1935
|
-
|
|
1936
|
-
// src/renderer-client.ts
|
|
1937
|
-
var DEFAULT_INIT_EVENT2 = "init-port";
|
|
1938
|
-
var DEFAULT_BRIDGE_NAMES = [
|
|
1939
|
-
"noxus",
|
|
1940
|
-
"ipcRenderer"
|
|
1941
|
-
];
|
|
1942
|
-
function defaultRequestId() {
|
|
1943
|
-
if (typeof crypto !== "undefined" && typeof crypto.randomUUID === "function") {
|
|
1944
|
-
return crypto.randomUUID();
|
|
1945
|
-
}
|
|
1946
|
-
return `${Date.now().toString(16)}-${Math.floor(Math.random() * 1e8).toString(16)}`;
|
|
1947
|
-
}
|
|
1948
|
-
__name(defaultRequestId, "defaultRequestId");
|
|
1949
|
-
function normalizeBridgeNames(preferred) {
|
|
1950
|
-
const names = [];
|
|
1951
|
-
const add = /* @__PURE__ */ __name((name) => {
|
|
1952
|
-
if (!name) return;
|
|
1953
|
-
if (!names.includes(name)) {
|
|
1954
|
-
names.push(name);
|
|
1955
|
-
}
|
|
1956
|
-
}, "add");
|
|
1957
|
-
if (Array.isArray(preferred)) {
|
|
1958
|
-
for (const name of preferred) {
|
|
1959
|
-
add(name);
|
|
1960
|
-
}
|
|
1961
|
-
} else {
|
|
1962
|
-
add(preferred);
|
|
1963
|
-
}
|
|
1964
|
-
for (const fallback of DEFAULT_BRIDGE_NAMES) {
|
|
1965
|
-
add(fallback);
|
|
1966
|
-
}
|
|
1967
|
-
return names;
|
|
1968
|
-
}
|
|
1969
|
-
__name(normalizeBridgeNames, "normalizeBridgeNames");
|
|
1970
|
-
function resolveBridgeFromWindow(windowRef, preferred) {
|
|
1971
|
-
const names = normalizeBridgeNames(preferred);
|
|
1972
|
-
const globalRef = windowRef;
|
|
1973
|
-
if (!globalRef) {
|
|
1974
|
-
return null;
|
|
1975
|
-
}
|
|
1976
|
-
for (const name of names) {
|
|
1977
|
-
const candidate = globalRef[name];
|
|
1978
|
-
if (candidate && typeof candidate.requestPort === "function") {
|
|
1979
|
-
return candidate;
|
|
1980
|
-
}
|
|
1981
|
-
}
|
|
1982
|
-
return null;
|
|
1983
|
-
}
|
|
1984
|
-
__name(resolveBridgeFromWindow, "resolveBridgeFromWindow");
|
|
1985
|
-
var _NoxRendererClient = class _NoxRendererClient {
|
|
1986
|
-
constructor(options = {}) {
|
|
1987
|
-
__publicField(this, "events", new RendererEventRegistry());
|
|
1988
|
-
__publicField(this, "pendingRequests", /* @__PURE__ */ new Map());
|
|
1989
|
-
__publicField(this, "requestPort");
|
|
1990
|
-
__publicField(this, "socketPort");
|
|
1991
|
-
__publicField(this, "senderId");
|
|
1992
|
-
__publicField(this, "bridge");
|
|
1993
|
-
__publicField(this, "initMessageType");
|
|
1994
|
-
__publicField(this, "windowRef");
|
|
1995
|
-
__publicField(this, "generateRequestId");
|
|
1996
|
-
__publicField(this, "isReady", false);
|
|
1997
|
-
__publicField(this, "setupPromise");
|
|
1998
|
-
__publicField(this, "setupResolve");
|
|
1999
|
-
__publicField(this, "setupReject");
|
|
2000
|
-
__publicField(this, "onWindowMessage", /* @__PURE__ */ __name((event) => {
|
|
2001
|
-
if (event.data?.type !== this.initMessageType) {
|
|
2002
|
-
return;
|
|
2003
|
-
}
|
|
2004
|
-
if (!Array.isArray(event.ports) || event.ports.length < 2) {
|
|
2005
|
-
const error = new Error("[Noxus] Renderer expected two MessagePorts (request + socket).");
|
|
2006
|
-
console.error(error);
|
|
2007
|
-
this.setupReject?.(error);
|
|
2008
|
-
this.resetSetupState();
|
|
2009
|
-
return;
|
|
2010
|
-
}
|
|
2011
|
-
this.windowRef.removeEventListener("message", this.onWindowMessage);
|
|
2012
|
-
this.requestPort = event.ports[0];
|
|
2013
|
-
this.socketPort = event.ports[1];
|
|
2014
|
-
this.senderId = event.data.senderId;
|
|
2015
|
-
if (this.requestPort === void 0 || this.socketPort === void 0) {
|
|
2016
|
-
const error = new Error("[Noxus] Renderer failed to receive valid MessagePorts.");
|
|
2017
|
-
console.error(error);
|
|
2018
|
-
this.setupReject?.(error);
|
|
2019
|
-
this.resetSetupState();
|
|
2020
|
-
return;
|
|
2021
|
-
}
|
|
2022
|
-
this.attachRequestPort(this.requestPort);
|
|
2023
|
-
this.attachSocketPort(this.socketPort);
|
|
2024
|
-
this.isReady = true;
|
|
2025
|
-
this.setupResolve?.();
|
|
2026
|
-
this.resetSetupState(true);
|
|
2027
|
-
}, "onWindowMessage"));
|
|
2028
|
-
__publicField(this, "onSocketMessage", /* @__PURE__ */ __name((event) => {
|
|
2029
|
-
if (this.events.tryDispatchFromMessageEvent(event)) {
|
|
2030
|
-
return;
|
|
2031
|
-
}
|
|
2032
|
-
console.warn("[Noxus] Received a socket message that is not a renderer event payload.", event.data);
|
|
2033
|
-
}, "onSocketMessage"));
|
|
2034
|
-
__publicField(this, "onRequestMessage", /* @__PURE__ */ __name((event) => {
|
|
2035
|
-
if (this.events.tryDispatchFromMessageEvent(event)) {
|
|
2036
|
-
return;
|
|
2037
|
-
}
|
|
2038
|
-
const response = event.data;
|
|
2039
|
-
if (!response || typeof response.requestId !== "string") {
|
|
2040
|
-
console.error("[Noxus] Renderer received an invalid response payload.", response);
|
|
2041
|
-
return;
|
|
2042
|
-
}
|
|
2043
|
-
const pending = this.pendingRequests.get(response.requestId);
|
|
2044
|
-
if (!pending) {
|
|
2045
|
-
console.error(`[Noxus] No pending handler found for request ${response.requestId}.`);
|
|
2046
|
-
return;
|
|
2047
|
-
}
|
|
2048
|
-
this.pendingRequests.delete(response.requestId);
|
|
2049
|
-
this.onRequestCompleted(pending, response);
|
|
2050
|
-
if (response.status >= 400) {
|
|
2051
|
-
pending.reject(response);
|
|
2052
|
-
return;
|
|
2053
|
-
}
|
|
2054
|
-
pending.resolve(response.body);
|
|
2055
|
-
}, "onRequestMessage"));
|
|
2056
|
-
this.windowRef = options.windowRef ?? window;
|
|
2057
|
-
const resolvedBridge = options.bridge ?? resolveBridgeFromWindow(this.windowRef, options.bridgeName);
|
|
2058
|
-
this.bridge = resolvedBridge ?? null;
|
|
2059
|
-
this.initMessageType = options.initMessageType ?? DEFAULT_INIT_EVENT2;
|
|
2060
|
-
this.generateRequestId = options.generateRequestId ?? defaultRequestId;
|
|
2061
|
-
}
|
|
2062
|
-
async setup() {
|
|
2063
|
-
if (this.isReady) {
|
|
2064
|
-
return Promise.resolve();
|
|
2065
|
-
}
|
|
2066
|
-
if (this.setupPromise) {
|
|
2067
|
-
return this.setupPromise;
|
|
2068
|
-
}
|
|
2069
|
-
if (!this.bridge || typeof this.bridge.requestPort !== "function") {
|
|
2070
|
-
throw new Error("[Noxus] Renderer bridge is missing requestPort().");
|
|
2071
|
-
}
|
|
2072
|
-
this.setupPromise = new Promise((resolve, reject) => {
|
|
2073
|
-
this.setupResolve = resolve;
|
|
2074
|
-
this.setupReject = reject;
|
|
2075
|
-
});
|
|
2076
|
-
this.windowRef.addEventListener("message", this.onWindowMessage);
|
|
2077
|
-
this.bridge.requestPort();
|
|
2078
|
-
return this.setupPromise;
|
|
2079
|
-
}
|
|
2080
|
-
dispose() {
|
|
2081
|
-
this.windowRef.removeEventListener("message", this.onWindowMessage);
|
|
2082
|
-
this.requestPort?.close();
|
|
2083
|
-
this.socketPort?.close();
|
|
2084
|
-
this.requestPort = void 0;
|
|
2085
|
-
this.socketPort = void 0;
|
|
2086
|
-
this.senderId = void 0;
|
|
2087
|
-
this.isReady = false;
|
|
2088
|
-
this.pendingRequests.clear();
|
|
2089
|
-
}
|
|
2090
|
-
async request(request) {
|
|
2091
|
-
const senderId = this.senderId;
|
|
2092
|
-
const requestId = this.generateRequestId();
|
|
2093
|
-
if (senderId === void 0) {
|
|
2094
|
-
return Promise.reject(this.createErrorResponse(requestId, "MessagePort is not available"));
|
|
2095
|
-
}
|
|
2096
|
-
const readinessError = this.validateReady(requestId);
|
|
2097
|
-
if (readinessError) {
|
|
2098
|
-
return Promise.reject(readinessError);
|
|
2099
|
-
}
|
|
2100
|
-
const message = {
|
|
2101
|
-
requestId,
|
|
2102
|
-
senderId,
|
|
2103
|
-
...request
|
|
2104
|
-
};
|
|
2105
|
-
return new Promise((resolve, reject) => {
|
|
2106
|
-
const pending = {
|
|
2107
|
-
resolve,
|
|
2108
|
-
reject: /* @__PURE__ */ __name((response) => reject(response), "reject"),
|
|
2109
|
-
request: message,
|
|
2110
|
-
submittedAt: Date.now()
|
|
2111
|
-
};
|
|
2112
|
-
this.pendingRequests.set(message.requestId, pending);
|
|
2113
|
-
this.requestPort.postMessage(message);
|
|
2114
|
-
});
|
|
2115
|
-
}
|
|
2116
|
-
async batch(requests) {
|
|
2117
|
-
return this.request({
|
|
2118
|
-
method: "BATCH",
|
|
2119
|
-
path: "",
|
|
2120
|
-
body: {
|
|
2121
|
-
requests
|
|
2122
|
-
}
|
|
2123
|
-
});
|
|
2124
|
-
}
|
|
2125
|
-
getSenderId() {
|
|
2126
|
-
return this.senderId;
|
|
2127
|
-
}
|
|
2128
|
-
onRequestCompleted(pending, response) {
|
|
2129
|
-
if (typeof console.groupCollapsed === "function") {
|
|
2130
|
-
console.groupCollapsed(`${response.status} ${pending.request.method} /${pending.request.path}`);
|
|
2131
|
-
}
|
|
2132
|
-
if (response.error) {
|
|
2133
|
-
console.error("error message:", response.error);
|
|
2134
|
-
}
|
|
2135
|
-
if (response.body !== void 0) {
|
|
2136
|
-
console.info("response:", response.body);
|
|
2137
|
-
}
|
|
2138
|
-
console.info("request:", pending.request);
|
|
2139
|
-
console.info(`Request duration: ${Date.now() - pending.submittedAt} ms`);
|
|
2140
|
-
if (typeof console.groupCollapsed === "function") {
|
|
2141
|
-
console.groupEnd();
|
|
2142
|
-
}
|
|
2143
|
-
}
|
|
2144
|
-
attachRequestPort(port) {
|
|
2145
|
-
port.onmessage = this.onRequestMessage;
|
|
2146
|
-
port.start();
|
|
2147
|
-
}
|
|
2148
|
-
attachSocketPort(port) {
|
|
2149
|
-
port.onmessage = this.onSocketMessage;
|
|
2150
|
-
port.start();
|
|
2151
|
-
}
|
|
2152
|
-
validateReady(requestId) {
|
|
2153
|
-
if (!this.isElectronEnvironment()) {
|
|
2154
|
-
return this.createErrorResponse(requestId, "Not running in Electron environment");
|
|
2155
|
-
}
|
|
2156
|
-
if (!this.requestPort) {
|
|
2157
|
-
return this.createErrorResponse(requestId, "MessagePort is not available");
|
|
2158
|
-
}
|
|
2159
|
-
return void 0;
|
|
2160
|
-
}
|
|
2161
|
-
createErrorResponse(requestId, message) {
|
|
2162
|
-
return {
|
|
2163
|
-
status: 500,
|
|
2164
|
-
requestId,
|
|
2165
|
-
error: message
|
|
2166
|
-
};
|
|
2167
|
-
}
|
|
2168
|
-
resetSetupState(success = false) {
|
|
2169
|
-
if (!success) {
|
|
2170
|
-
this.setupPromise = void 0;
|
|
2171
|
-
}
|
|
2172
|
-
this.setupResolve = void 0;
|
|
2173
|
-
this.setupReject = void 0;
|
|
2174
|
-
}
|
|
2175
|
-
isElectronEnvironment() {
|
|
2176
|
-
return typeof window !== "undefined" && /Electron/.test(window.navigator.userAgent);
|
|
2177
|
-
}
|
|
2178
|
-
};
|
|
2179
|
-
__name(_NoxRendererClient, "NoxRendererClient");
|
|
2180
|
-
var NoxRendererClient = _NoxRendererClient;
|
|
2181
1963
|
// Annotate the CommonJS export names for ESM import in node:
|
|
2182
1964
|
0 && (module.exports = {
|
|
2183
1965
|
AppInjector,
|
|
@@ -2211,7 +1993,6 @@ var NoxRendererClient = _NoxRendererClient;
|
|
|
2211
1993
|
NotFoundException,
|
|
2212
1994
|
NotImplementedException,
|
|
2213
1995
|
NoxApp,
|
|
2214
|
-
NoxRendererClient,
|
|
2215
1996
|
NoxSocket,
|
|
2216
1997
|
Patch,
|
|
2217
1998
|
PaymentRequiredException,
|
|
@@ -2219,7 +2000,6 @@ var NoxRendererClient = _NoxRendererClient;
|
|
|
2219
2000
|
Put,
|
|
2220
2001
|
RENDERER_EVENT_TYPE,
|
|
2221
2002
|
ROUTE_METADATA_KEY,
|
|
2222
|
-
RendererEventRegistry,
|
|
2223
2003
|
Request,
|
|
2224
2004
|
RequestTimeoutException,
|
|
2225
2005
|
ResponseException,
|
|
@@ -2233,7 +2013,6 @@ var NoxRendererClient = _NoxRendererClient;
|
|
|
2233
2013
|
VariantAlsoNegotiatesException,
|
|
2234
2014
|
bootstrapApplication,
|
|
2235
2015
|
createRendererEventMessage,
|
|
2236
|
-
exposeNoxusBridge,
|
|
2237
2016
|
forwardRef,
|
|
2238
2017
|
getControllerMetadata,
|
|
2239
2018
|
getGuardForController,
|