@noxfly/noxus 3.0.0-dev.4 → 3.0.0-dev.6
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.map +1 -0
- package/dist/child.mjs.map +1 -0
- package/dist/main.d.mts +4 -4
- package/dist/main.d.ts +4 -4
- package/dist/main.js.map +1 -0
- package/dist/main.mjs.map +1 -0
- package/dist/preload.js.map +1 -0
- package/dist/preload.mjs.map +1 -0
- package/dist/renderer.d.mts +4 -4
- package/dist/renderer.d.ts +4 -4
- package/dist/renderer.js.map +1 -0
- package/dist/renderer.mjs.map +1 -0
- package/package.json +10 -9
- package/.editorconfig +0 -16
- package/.github/copilot-instructions.md +0 -128
- package/.vscode/settings.json +0 -3
- package/AGENTS.md +0 -5
- package/eslint.config.js +0 -109
- package/scripts/postbuild.js +0 -31
- package/src/DI/app-injector.ts +0 -173
- package/src/DI/injector-explorer.ts +0 -201
- package/src/DI/token.ts +0 -53
- package/src/decorators/controller.decorator.ts +0 -58
- package/src/decorators/guards.decorator.ts +0 -15
- package/src/decorators/injectable.decorator.ts +0 -81
- package/src/decorators/method.decorator.ts +0 -66
- package/src/decorators/middleware.decorator.ts +0 -15
- package/src/index.ts +0 -10
- package/src/internal/app.ts +0 -219
- package/src/internal/bootstrap.ts +0 -141
- package/src/internal/exceptions.ts +0 -57
- package/src/internal/preload-bridge.ts +0 -75
- package/src/internal/renderer-client.ts +0 -374
- package/src/internal/renderer-events.ts +0 -110
- package/src/internal/request.ts +0 -102
- package/src/internal/router.ts +0 -365
- package/src/internal/routes.ts +0 -142
- package/src/internal/socket.ts +0 -75
- package/src/main.ts +0 -26
- package/src/non-electron-process.ts +0 -22
- package/src/preload.ts +0 -10
- package/src/renderer.ts +0 -13
- package/src/utils/forward-ref.ts +0 -31
- package/src/utils/logger.ts +0 -430
- package/src/utils/radix-tree.ts +0 -243
- package/src/utils/types.ts +0 -21
- package/src/window/window-manager.ts +0 -302
- package/tsconfig.json +0 -29
- package/tsup.config.ts +0 -50
package/src/internal/app.ts
DELETED
|
@@ -1,219 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @copyright 2025 NoxFly
|
|
3
|
-
* @license MIT
|
|
4
|
-
* @author NoxFly
|
|
5
|
-
*/
|
|
6
|
-
|
|
7
|
-
import { app, BrowserWindow, ipcMain, MessageChannelMain } from 'electron/main';
|
|
8
|
-
import { Guard } from "../decorators/guards.decorator";
|
|
9
|
-
import { Injectable } from '../decorators/injectable.decorator';
|
|
10
|
-
import { Middleware } from '../decorators/middleware.decorator';
|
|
11
|
-
import { inject } from '../DI/app-injector';
|
|
12
|
-
import { InjectorExplorer } from '../DI/injector-explorer';
|
|
13
|
-
import { Logger } from '../utils/logger';
|
|
14
|
-
import { Type } from '../utils/types';
|
|
15
|
-
import { WindowManager } from '../window/window-manager';
|
|
16
|
-
import { IResponse, Request } from './request';
|
|
17
|
-
import { Router } from './router';
|
|
18
|
-
import { NoxSocket } from './socket';
|
|
19
|
-
|
|
20
|
-
/**
|
|
21
|
-
* Your application service should implement IApp.
|
|
22
|
-
* Noxus calls these lifecycle methods at the appropriate time.
|
|
23
|
-
*
|
|
24
|
-
* Unlike v2, IApp no longer receives a BrowserWindow in onReady.
|
|
25
|
-
* Use the injected WindowManager instead — it is more flexible and
|
|
26
|
-
* does not couple the lifecycle to a single pre-created window.
|
|
27
|
-
*
|
|
28
|
-
* @example
|
|
29
|
-
* @Injectable({ lifetime: 'singleton', deps: [WindowManager, MyService] })
|
|
30
|
-
* class AppService implements IApp {
|
|
31
|
-
* constructor(private wm: WindowManager, private svc: MyService) {}
|
|
32
|
-
*
|
|
33
|
-
* async onReady() {
|
|
34
|
-
* const win = await this.wm.createSplash({ webPreferences: { preload: ... } });
|
|
35
|
-
* win.loadFile('index.html');
|
|
36
|
-
* }
|
|
37
|
-
*
|
|
38
|
-
* async onActivated() { ... }
|
|
39
|
-
* async dispose() { ... }
|
|
40
|
-
* }
|
|
41
|
-
*/
|
|
42
|
-
export interface IApp {
|
|
43
|
-
dispose(): Promise<void>;
|
|
44
|
-
onReady(): Promise<void>;
|
|
45
|
-
onActivated(): Promise<void>;
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
@Injectable({ lifetime: 'singleton', deps: [Router, NoxSocket, WindowManager] })
|
|
49
|
-
export class NoxApp {
|
|
50
|
-
private appService: IApp | undefined;
|
|
51
|
-
|
|
52
|
-
constructor(
|
|
53
|
-
private readonly router: Router,
|
|
54
|
-
private readonly socket: NoxSocket,
|
|
55
|
-
public readonly windowManager: WindowManager,
|
|
56
|
-
) {}
|
|
57
|
-
|
|
58
|
-
// -------------------------------------------------------------------------
|
|
59
|
-
// Initialisation
|
|
60
|
-
// -------------------------------------------------------------------------
|
|
61
|
-
|
|
62
|
-
public async init(): Promise<this> {
|
|
63
|
-
ipcMain.on('gimme-my-port', this.giveTheRendererAPort.bind(this));
|
|
64
|
-
app.once('activate', this.onAppActivated.bind(this));
|
|
65
|
-
app.once('window-all-closed', this.onAllWindowsClosed.bind(this));
|
|
66
|
-
console.log('');
|
|
67
|
-
return this;
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
// -------------------------------------------------------------------------
|
|
71
|
-
// Public API
|
|
72
|
-
// -------------------------------------------------------------------------
|
|
73
|
-
|
|
74
|
-
/**
|
|
75
|
-
* Registers a lazy route. The file behind this prefix is dynamically
|
|
76
|
-
* imported on the first IPC request that targets it.
|
|
77
|
-
*
|
|
78
|
-
* The import function should NOT statically reference heavy modules —
|
|
79
|
-
* the whole point is to defer their loading.
|
|
80
|
-
*
|
|
81
|
-
* @example
|
|
82
|
-
* noxApp.lazy('auth', () => import('./modules/auth/auth.controller.js'));
|
|
83
|
-
* noxApp.lazy('reporting', () => import('./modules/reporting/index.js'));
|
|
84
|
-
*/
|
|
85
|
-
public lazy(
|
|
86
|
-
pathPrefix: string,
|
|
87
|
-
load: () => Promise<unknown>,
|
|
88
|
-
guards: Guard[] = [],
|
|
89
|
-
middlewares: Middleware[] = [],
|
|
90
|
-
): this {
|
|
91
|
-
this.router.registerLazyRoute(pathPrefix, load, guards, middlewares);
|
|
92
|
-
return this;
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
/**
|
|
96
|
-
* Eagerly loads a set of modules (controllers + services) before start().
|
|
97
|
-
* Use this for modules that provide services needed by your IApp.onReady().
|
|
98
|
-
*
|
|
99
|
-
* All imports run in parallel; DI is flushed with the two-phase guarantee.
|
|
100
|
-
*/
|
|
101
|
-
public async load(importFns: Array<() => Promise<unknown>>): Promise<this> {
|
|
102
|
-
InjectorExplorer.beginAccumulate();
|
|
103
|
-
await Promise.all(importFns.map((fn) => fn()));
|
|
104
|
-
await InjectorExplorer.flushAccumulated();
|
|
105
|
-
return this;
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
/**
|
|
109
|
-
* Registers a global middleware applied to every route.
|
|
110
|
-
*/
|
|
111
|
-
public use(middleware: Middleware): this {
|
|
112
|
-
this.router.defineRootMiddleware(middleware);
|
|
113
|
-
return this;
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
/**
|
|
117
|
-
* Sets the application service (implements IApp) that receives lifecycle events.
|
|
118
|
-
* @param appClass - Class decorated with @Injectable that implements IApp.
|
|
119
|
-
*/
|
|
120
|
-
public configure(appClass: Type<IApp>): this {
|
|
121
|
-
this.appService = inject(appClass);
|
|
122
|
-
return this;
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
/**
|
|
126
|
-
* Calls IApp.onReady(). Should be called after configure() and any lazy()
|
|
127
|
-
* registrations are set up.
|
|
128
|
-
*/
|
|
129
|
-
public start(): this {
|
|
130
|
-
this.appService?.onReady();
|
|
131
|
-
return this;
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
// -------------------------------------------------------------------------
|
|
135
|
-
// IPC
|
|
136
|
-
// -------------------------------------------------------------------------
|
|
137
|
-
|
|
138
|
-
private readonly onRendererMessage = async (event: Electron.MessageEvent): Promise<void> => {
|
|
139
|
-
const { senderId, requestId, path, method, body, query }: import('./request').IRequest = event.data;
|
|
140
|
-
const channels = this.socket.get(senderId);
|
|
141
|
-
|
|
142
|
-
if (!channels) {
|
|
143
|
-
Logger.error(`No message channel found for sender ID: ${senderId}`);
|
|
144
|
-
return;
|
|
145
|
-
}
|
|
146
|
-
|
|
147
|
-
try {
|
|
148
|
-
const request = new Request(event, senderId, requestId, method, path, body, query);
|
|
149
|
-
const response = await this.router.handle(request);
|
|
150
|
-
channels.request.port1.postMessage(response);
|
|
151
|
-
}
|
|
152
|
-
catch (err: unknown) {
|
|
153
|
-
const response: IResponse = {
|
|
154
|
-
requestId,
|
|
155
|
-
status: 500,
|
|
156
|
-
body: null,
|
|
157
|
-
error: err instanceof Error ? err.message : 'Internal Server Error',
|
|
158
|
-
};
|
|
159
|
-
channels.request.port1.postMessage(response);
|
|
160
|
-
}
|
|
161
|
-
};
|
|
162
|
-
|
|
163
|
-
private giveTheRendererAPort(event: Electron.IpcMainInvokeEvent): void {
|
|
164
|
-
const senderId = event.sender.id;
|
|
165
|
-
|
|
166
|
-
if (this.socket.get(senderId)) {
|
|
167
|
-
this.shutdownChannel(senderId);
|
|
168
|
-
}
|
|
169
|
-
|
|
170
|
-
const requestChannel = new MessageChannelMain();
|
|
171
|
-
const socketChannel = new MessageChannelMain();
|
|
172
|
-
|
|
173
|
-
requestChannel.port1.on('message', this.onRendererMessage);
|
|
174
|
-
requestChannel.port1.start();
|
|
175
|
-
socketChannel.port1.start();
|
|
176
|
-
|
|
177
|
-
event.sender.once('destroyed', () => this.shutdownChannel(senderId));
|
|
178
|
-
|
|
179
|
-
this.socket.register(senderId, requestChannel, socketChannel);
|
|
180
|
-
event.sender.postMessage('port', { senderId }, [requestChannel.port2, socketChannel.port2]);
|
|
181
|
-
}
|
|
182
|
-
|
|
183
|
-
// -------------------------------------------------------------------------
|
|
184
|
-
// Lifecycle
|
|
185
|
-
// -------------------------------------------------------------------------
|
|
186
|
-
|
|
187
|
-
private onAppActivated(): void {
|
|
188
|
-
if (process.platform === 'darwin' && BrowserWindow.getAllWindows().length === 0) {
|
|
189
|
-
this.appService?.onActivated();
|
|
190
|
-
}
|
|
191
|
-
}
|
|
192
|
-
|
|
193
|
-
private async onAllWindowsClosed(): Promise<void> {
|
|
194
|
-
for (const senderId of this.socket.getSenderIds()) {
|
|
195
|
-
this.shutdownChannel(senderId);
|
|
196
|
-
}
|
|
197
|
-
|
|
198
|
-
Logger.info('All windows closed, shutting down application...');
|
|
199
|
-
await this.appService?.dispose();
|
|
200
|
-
|
|
201
|
-
if (process.platform !== 'darwin') app.quit();
|
|
202
|
-
}
|
|
203
|
-
|
|
204
|
-
private shutdownChannel(channelSenderId: number): void {
|
|
205
|
-
const channels = this.socket.get(channelSenderId);
|
|
206
|
-
|
|
207
|
-
if (!channels) {
|
|
208
|
-
return;
|
|
209
|
-
}
|
|
210
|
-
|
|
211
|
-
channels.request.port1.off('message', this.onRendererMessage);
|
|
212
|
-
channels.request.port1.close();
|
|
213
|
-
channels.request.port2.close();
|
|
214
|
-
channels.socket.port1.close();
|
|
215
|
-
channels.socket.port2.close();
|
|
216
|
-
|
|
217
|
-
this.socket.unregister(channelSenderId);
|
|
218
|
-
}
|
|
219
|
-
}
|
|
@@ -1,141 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @copyright 2025 NoxFly
|
|
3
|
-
* @license MIT
|
|
4
|
-
* @author NoxFly
|
|
5
|
-
*/
|
|
6
|
-
|
|
7
|
-
import { app } from 'electron/main';
|
|
8
|
-
import { inject, RootInjector } from '../DI/app-injector';
|
|
9
|
-
import { InjectorExplorer } from '../DI/injector-explorer';
|
|
10
|
-
import { TokenKey } from '../DI/token';
|
|
11
|
-
import { Logger } from '../utils/logger';
|
|
12
|
-
import { NoxApp } from './app';
|
|
13
|
-
import { RouteDefinition } from "./routes";
|
|
14
|
-
import { Router } from './router';
|
|
15
|
-
|
|
16
|
-
/**
|
|
17
|
-
* A singleton value override: provides an already-constructed instance
|
|
18
|
-
* for a given token, bypassing the DI factory.
|
|
19
|
-
*
|
|
20
|
-
* Useful for injecting external singletons (e.g. a database connection,
|
|
21
|
-
* a logger already configured, a third-party SDK wrapper) that cannot
|
|
22
|
-
* or should not be constructed by the DI container.
|
|
23
|
-
*
|
|
24
|
-
* @example
|
|
25
|
-
* { token: MikroORM, useValue: await MikroORM.init(config) }
|
|
26
|
-
* { token: DB_URL, useValue: process.env.DATABASE_URL }
|
|
27
|
-
*/
|
|
28
|
-
export interface SingletonOverride<T = unknown> {
|
|
29
|
-
token: TokenKey<T>;
|
|
30
|
-
useValue: T;
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
/**
|
|
34
|
-
* Configuration object for bootstrapApplication.
|
|
35
|
-
*/
|
|
36
|
-
export interface BootstrapConfig {
|
|
37
|
-
/**
|
|
38
|
-
* Application routing table, produced by defineRoutes().
|
|
39
|
-
* All lazy routes are registered before the app starts.
|
|
40
|
-
*/
|
|
41
|
-
routes?: RouteDefinition[];
|
|
42
|
-
|
|
43
|
-
/**
|
|
44
|
-
* Pre-built singleton instances to inject into the DI container
|
|
45
|
-
* before the application starts.
|
|
46
|
-
*
|
|
47
|
-
* This replaces the v2 module/provider declaration pattern for
|
|
48
|
-
* external singletons.
|
|
49
|
-
*
|
|
50
|
-
* @example
|
|
51
|
-
* singletons: [
|
|
52
|
-
* { token: MikroORM, useValue: await MikroORM.init(ormConfig) },
|
|
53
|
-
* { token: DB_URL, useValue: process.env.DATABASE_URL! },
|
|
54
|
-
* ]
|
|
55
|
-
*/
|
|
56
|
-
singletons?: SingletonOverride[];
|
|
57
|
-
|
|
58
|
-
/**
|
|
59
|
-
* Controllers and services to eagerly load before NoxApp.start() is called.
|
|
60
|
-
* Each entry is a dynamic import function — files are imported in parallel.
|
|
61
|
-
*
|
|
62
|
-
* Use this only for things needed at startup (e.g. if your IApp service
|
|
63
|
-
* depends on a service in an otherwise lazy module).
|
|
64
|
-
*
|
|
65
|
-
* Everything else should be registered via noxApp.lazy().
|
|
66
|
-
*
|
|
67
|
-
* @example
|
|
68
|
-
* eagerLoad: [
|
|
69
|
-
* () => import('./modules/auth/auth.controller.js'),
|
|
70
|
-
* ]
|
|
71
|
-
*/
|
|
72
|
-
eagerLoad?: Array<() => Promise<unknown>>;
|
|
73
|
-
|
|
74
|
-
/**
|
|
75
|
-
* Controls framework log verbosity.
|
|
76
|
-
* - `'debug'`: all messages (default during development).
|
|
77
|
-
* - `'info'`: info, warn, error, critical only.
|
|
78
|
-
* - `'none'`: completely silent — no framework logs.
|
|
79
|
-
*
|
|
80
|
-
* You can also pass an array of specific log levels to enable.
|
|
81
|
-
*/
|
|
82
|
-
logLevel?: 'debug' | 'info' | 'none' | import('../utils/logger').LogLevel[];
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
/**
|
|
86
|
-
* Bootstraps the Noxus application.
|
|
87
|
-
*/
|
|
88
|
-
export async function bootstrapApplication(config: BootstrapConfig = {}): Promise<NoxApp> {
|
|
89
|
-
await app.whenReady();
|
|
90
|
-
|
|
91
|
-
// Apply log level configuration
|
|
92
|
-
if (config.logLevel !== undefined) {
|
|
93
|
-
if (config.logLevel === 'none') {
|
|
94
|
-
Logger.setLogLevel([]);
|
|
95
|
-
} else if (Array.isArray(config.logLevel)) {
|
|
96
|
-
Logger.setLogLevel(config.logLevel);
|
|
97
|
-
} else {
|
|
98
|
-
Logger.setLogLevel(config.logLevel);
|
|
99
|
-
}
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
// Build override map for the DI flush phase
|
|
103
|
-
const overrides = new Map<TokenKey, unknown>();
|
|
104
|
-
|
|
105
|
-
for (const { token, useValue } of config.singletons ?? []) {
|
|
106
|
-
overrides.set(token, useValue);
|
|
107
|
-
// Pre-register the binding so the injector knows the token exists
|
|
108
|
-
RootInjector.singletons.set(token as any, useValue);
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
// Flush all classes enqueued by decorators at import time (two-phase)
|
|
112
|
-
// Wire the controller registrar so InjectorExplorer can register controllers
|
|
113
|
-
// without directly importing Router (avoids circular dependency).
|
|
114
|
-
InjectorExplorer.setControllerRegistrar((controllerClass, pathPrefix, routeGuards, routeMiddlewares) => {
|
|
115
|
-
const router = inject(Router);
|
|
116
|
-
router.registerController(controllerClass, pathPrefix, routeGuards, routeMiddlewares);
|
|
117
|
-
});
|
|
118
|
-
|
|
119
|
-
InjectorExplorer.processPending(overrides);
|
|
120
|
-
|
|
121
|
-
// Resolve core framework singletons
|
|
122
|
-
const noxApp = inject(NoxApp);
|
|
123
|
-
|
|
124
|
-
// Register routes from the routing table
|
|
125
|
-
if (config.routes?.length) {
|
|
126
|
-
for (const route of config.routes) {
|
|
127
|
-
if (route.load) {
|
|
128
|
-
noxApp.lazy(route.path, route.load, route.guards, route.middlewares);
|
|
129
|
-
}
|
|
130
|
-
}
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
// Eagerly load optional modules
|
|
134
|
-
if (config.eagerLoad?.length) {
|
|
135
|
-
await noxApp.load(config.eagerLoad);
|
|
136
|
-
}
|
|
137
|
-
|
|
138
|
-
await noxApp.init();
|
|
139
|
-
|
|
140
|
-
return noxApp;
|
|
141
|
-
}
|
|
@@ -1,57 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @copyright 2025 NoxFly
|
|
3
|
-
* @license MIT
|
|
4
|
-
* @author NoxFly
|
|
5
|
-
*/
|
|
6
|
-
|
|
7
|
-
export class ResponseException extends Error {
|
|
8
|
-
public readonly status: number = 0;
|
|
9
|
-
|
|
10
|
-
constructor(message?: string);
|
|
11
|
-
constructor(statusCode?: number, message?: string);
|
|
12
|
-
constructor(statusOrMessage?: number | string, message?: string) {
|
|
13
|
-
let statusCode: number | undefined;
|
|
14
|
-
|
|
15
|
-
if(typeof statusOrMessage === 'number') {
|
|
16
|
-
statusCode = statusOrMessage;
|
|
17
|
-
}
|
|
18
|
-
else if(typeof statusOrMessage === 'string') {
|
|
19
|
-
message = statusOrMessage;
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
super(message ?? "");
|
|
23
|
-
|
|
24
|
-
if(statusCode !== undefined) {
|
|
25
|
-
this.status = statusCode;
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
this.name = this.constructor.name
|
|
29
|
-
.replace(/([A-Z])/g, ' $1');
|
|
30
|
-
}
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
// 4XX
|
|
34
|
-
export class BadRequestException extends ResponseException { public override readonly status = 400; }
|
|
35
|
-
export class UnauthorizedException extends ResponseException { public override readonly status = 401; }
|
|
36
|
-
export class PaymentRequiredException extends ResponseException { public override readonly status = 402; }
|
|
37
|
-
export class ForbiddenException extends ResponseException { public override readonly status = 403; }
|
|
38
|
-
export class NotFoundException extends ResponseException { public override readonly status = 404; }
|
|
39
|
-
export class MethodNotAllowedException extends ResponseException { public override readonly status = 405; }
|
|
40
|
-
export class NotAcceptableException extends ResponseException { public override readonly status = 406; }
|
|
41
|
-
export class RequestTimeoutException extends ResponseException { public override readonly status = 408; }
|
|
42
|
-
export class ConflictException extends ResponseException { public override readonly status = 409; }
|
|
43
|
-
export class UpgradeRequiredException extends ResponseException { public override readonly status = 426; }
|
|
44
|
-
export class TooManyRequestsException extends ResponseException { public override readonly status = 429; }
|
|
45
|
-
// 5XX
|
|
46
|
-
export class InternalServerException extends ResponseException { public override readonly status = 500; }
|
|
47
|
-
export class NotImplementedException extends ResponseException { public override readonly status = 501; }
|
|
48
|
-
export class BadGatewayException extends ResponseException { public override readonly status = 502; }
|
|
49
|
-
export class ServiceUnavailableException extends ResponseException { public override readonly status = 503; }
|
|
50
|
-
export class GatewayTimeoutException extends ResponseException { public override readonly status = 504; }
|
|
51
|
-
export class HttpVersionNotSupportedException extends ResponseException { public override readonly status = 505; }
|
|
52
|
-
export class VariantAlsoNegotiatesException extends ResponseException { public override readonly status = 506; }
|
|
53
|
-
export class InsufficientStorageException extends ResponseException { public override readonly status = 507; }
|
|
54
|
-
export class LoopDetectedException extends ResponseException { public override readonly status = 508; }
|
|
55
|
-
export class NotExtendedException extends ResponseException { public override readonly status = 510; }
|
|
56
|
-
export class NetworkAuthenticationRequiredException extends ResponseException { public override readonly status = 511; }
|
|
57
|
-
export class NetworkConnectTimeoutException extends ResponseException { public override readonly status = 599; }
|
|
@@ -1,75 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @copyright 2025 NoxFly
|
|
3
|
-
* @license MIT
|
|
4
|
-
* @author NoxFly
|
|
5
|
-
*/
|
|
6
|
-
|
|
7
|
-
import { contextBridge, ipcRenderer } from 'electron/renderer';
|
|
8
|
-
import type { IPortRequester } from './renderer-client';
|
|
9
|
-
|
|
10
|
-
export interface NoxusPreloadAPI extends IPortRequester {}
|
|
11
|
-
|
|
12
|
-
export interface NoxusPreloadOptions {
|
|
13
|
-
exposeAs?: string;
|
|
14
|
-
initMessageType?: string;
|
|
15
|
-
requestChannel?: string;
|
|
16
|
-
responseChannel?: string;
|
|
17
|
-
targetWindow?: Window;
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
const DEFAULT_EXPOSE_NAME = 'noxus';
|
|
21
|
-
const DEFAULT_INIT_EVENT = 'init-port';
|
|
22
|
-
const DEFAULT_REQUEST_CHANNEL = 'gimme-my-port';
|
|
23
|
-
const DEFAULT_RESPONSE_CHANNEL = 'port';
|
|
24
|
-
|
|
25
|
-
/**
|
|
26
|
-
* Exposes a minimal bridge in the isolated preload context so renderer processes
|
|
27
|
-
* can request the two MessagePorts required by Noxus. The bridge forwards both
|
|
28
|
-
* request/response and socket ports to the renderer via window.postMessage.
|
|
29
|
-
*/
|
|
30
|
-
export function exposeNoxusBridge(options: NoxusPreloadOptions = {}): NoxusPreloadAPI {
|
|
31
|
-
const {
|
|
32
|
-
exposeAs = DEFAULT_EXPOSE_NAME,
|
|
33
|
-
initMessageType = DEFAULT_INIT_EVENT,
|
|
34
|
-
requestChannel = DEFAULT_REQUEST_CHANNEL,
|
|
35
|
-
responseChannel = DEFAULT_RESPONSE_CHANNEL,
|
|
36
|
-
targetWindow = window,
|
|
37
|
-
} = options;
|
|
38
|
-
|
|
39
|
-
const api: NoxusPreloadAPI = {
|
|
40
|
-
requestPort: () => {
|
|
41
|
-
ipcRenderer.send(requestChannel);
|
|
42
|
-
|
|
43
|
-
ipcRenderer.once(responseChannel, (event, message: { senderId: number }) => {
|
|
44
|
-
const ports = (event.ports ?? []).filter((port): port is MessagePort => port !== undefined);
|
|
45
|
-
|
|
46
|
-
if(ports.length === 0) {
|
|
47
|
-
console.error('[Noxus] No MessagePort received from main process.');
|
|
48
|
-
return;
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
for(const port of ports) {
|
|
52
|
-
try {
|
|
53
|
-
port.start();
|
|
54
|
-
}
|
|
55
|
-
catch(error) {
|
|
56
|
-
console.error('[Noxus] Failed to start MessagePort.', error);
|
|
57
|
-
}
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
targetWindow.postMessage(
|
|
61
|
-
{
|
|
62
|
-
type: initMessageType,
|
|
63
|
-
senderId: message?.senderId,
|
|
64
|
-
},
|
|
65
|
-
'*',
|
|
66
|
-
ports,
|
|
67
|
-
);
|
|
68
|
-
});
|
|
69
|
-
},
|
|
70
|
-
};
|
|
71
|
-
|
|
72
|
-
contextBridge.exposeInMainWorld(exposeAs, api);
|
|
73
|
-
|
|
74
|
-
return api;
|
|
75
|
-
}
|