@noxfly/noxus 3.0.0-dev.10 → 3.0.0-dev.12

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/renderer.js CHANGED
@@ -8,6 +8,7 @@ var __defProp = Object.defineProperty;
8
8
  var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
9
9
  var __getOwnPropNames = Object.getOwnPropertyNames;
10
10
  var __hasOwnProp = Object.prototype.hasOwnProperty;
11
+ var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
11
12
  var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
12
13
  var __esm = (fn, res) => function __init() {
13
14
  return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
@@ -25,6 +26,7 @@ var __copyProps = (to, from, except, desc) => {
25
26
  return to;
26
27
  };
27
28
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
29
+ var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
28
30
 
29
31
  // src/utils/forward-ref.ts
30
32
  var _ForwardReference, ForwardReference;
@@ -49,6 +51,7 @@ var init_token = __esm({
49
51
  _Token = class _Token {
50
52
  constructor(target) {
51
53
  this.target = target;
54
+ __publicField(this, "description");
52
55
  this.description = typeof target === "string" ? target : target.name;
53
56
  }
54
57
  toString() {
@@ -74,9 +77,9 @@ var init_app_injector = __esm({
74
77
  _AppInjector = class _AppInjector {
75
78
  constructor(name = null) {
76
79
  this.name = name;
77
- this.bindings = /* @__PURE__ */ new Map();
78
- this.singletons = /* @__PURE__ */ new Map();
79
- this.scoped = /* @__PURE__ */ new Map();
80
+ __publicField(this, "bindings", /* @__PURE__ */ new Map());
81
+ __publicField(this, "singletons", /* @__PURE__ */ new Map());
82
+ __publicField(this, "scoped", /* @__PURE__ */ new Map());
80
83
  }
81
84
  /**
82
85
  * Creates a child scope for per-request lifetime resolution.
@@ -187,8 +190,9 @@ var _Request = class _Request {
187
190
  this.method = method;
188
191
  this.path = path;
189
192
  this.body = body;
190
- this.context = RootInjector.createScope();
191
- this.params = {};
193
+ __publicField(this, "context", RootInjector.createScope());
194
+ __publicField(this, "params", {});
195
+ __publicField(this, "query");
192
196
  this.path = path.replace(/^\/|\/$/g, "");
193
197
  this.query = query ?? {};
194
198
  }
@@ -216,7 +220,7 @@ __name(isRendererEventMessage, "isRendererEventMessage");
216
220
  // src/internal/renderer-events.ts
217
221
  var _RendererEventRegistry = class _RendererEventRegistry {
218
222
  constructor() {
219
- this.listeners = /* @__PURE__ */ new Map();
223
+ __publicField(this, "listeners", /* @__PURE__ */ new Map());
220
224
  }
221
225
  /**
222
226
  *
@@ -342,10 +346,22 @@ function resolveBridgeFromWindow(windowRef, preferred) {
342
346
  __name(resolveBridgeFromWindow, "resolveBridgeFromWindow");
343
347
  var _NoxRendererClient = class _NoxRendererClient {
344
348
  constructor(options = {}) {
345
- this.events = new RendererEventRegistry();
346
- this.pendingRequests = /* @__PURE__ */ new Map();
347
- this.isReady = false;
348
- this.onWindowMessage = /* @__PURE__ */ __name((event) => {
349
+ __publicField(this, "events", new RendererEventRegistry());
350
+ __publicField(this, "pendingRequests", /* @__PURE__ */ new Map());
351
+ __publicField(this, "requestPort");
352
+ __publicField(this, "socketPort");
353
+ __publicField(this, "senderId");
354
+ __publicField(this, "bridge");
355
+ __publicField(this, "initMessageType");
356
+ __publicField(this, "windowRef");
357
+ __publicField(this, "generateRequestId");
358
+ __publicField(this, "requestTimeout");
359
+ __publicField(this, "isReady", false);
360
+ __publicField(this, "setupPromise");
361
+ __publicField(this, "setupResolve");
362
+ __publicField(this, "setupReject");
363
+ __publicField(this, "enableLogging");
364
+ __publicField(this, "onWindowMessage", /* @__PURE__ */ __name((event) => {
349
365
  if (event.data?.type !== this.initMessageType) {
350
366
  return;
351
367
  }
@@ -372,14 +388,14 @@ var _NoxRendererClient = class _NoxRendererClient {
372
388
  this.isReady = true;
373
389
  this.setupResolve?.();
374
390
  this.resetSetupState(true);
375
- }, "onWindowMessage");
376
- this.onSocketMessage = /* @__PURE__ */ __name((event) => {
391
+ }, "onWindowMessage"));
392
+ __publicField(this, "onSocketMessage", /* @__PURE__ */ __name((event) => {
377
393
  if (this.events.tryDispatchFromMessageEvent(event)) {
378
394
  return;
379
395
  }
380
396
  console.warn("[Noxus] Received a socket message that is not a renderer event payload.", event.data);
381
- }, "onSocketMessage");
382
- this.onRequestMessage = /* @__PURE__ */ __name((event) => {
397
+ }, "onSocketMessage"));
398
+ __publicField(this, "onRequestMessage", /* @__PURE__ */ __name((event) => {
383
399
  if (this.events.tryDispatchFromMessageEvent(event)) {
384
400
  return;
385
401
  }
@@ -403,7 +419,7 @@ var _NoxRendererClient = class _NoxRendererClient {
403
419
  return;
404
420
  }
405
421
  pending.resolve(response.body);
406
- }, "onRequestMessage");
422
+ }, "onRequestMessage"));
407
423
  this.windowRef = options.windowRef ?? window;
408
424
  const resolvedBridge = options.bridge ?? resolveBridgeFromWindow(this.windowRef, options.bridgeName);
409
425
  this.bridge = resolvedBridge ?? null;
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/utils/forward-ref.ts","../src/DI/token.ts","../src/DI/app-injector.ts","../src/renderer.ts","../src/internal/request.ts","../src/internal/renderer-events.ts","../src/internal/renderer-client.ts"],"sourcesContent":["/**\r\n * @copyright 2025 NoxFly\r\n * @license MIT\r\n * @author NoxFly\r\n */\r\n\r\nimport { Type } from \"./types\";\r\n\r\n/**\r\n * A function that returns a type.\r\n * Used for forward references to types that are not yet defined.\r\n */\r\nexport interface ForwardRefFn<T = any> {\r\n (): Type<T>;\r\n}\r\n\r\n/**\r\n * A wrapper class for forward referenced types.\r\n */\r\nexport class ForwardReference<T = any> {\r\n constructor(public readonly forwardRefFn: ForwardRefFn<T>) {}\r\n}\r\n\r\n/**\r\n * Creates a forward reference to a type.\r\n * @param fn A function that returns the type.\r\n * @returns A ForwardReference instance.\r\n */\r\nexport function forwardRef<T = any>(fn: ForwardRefFn<T>): ForwardReference<T> {\r\n return new ForwardReference(fn);\r\n}\r\n","/**\r\n * @copyright 2025 NoxFly\r\n * @license MIT\r\n * @author NoxFly\r\n */\r\n\r\nimport { Type } from '../utils/types';\r\n\r\n/**\r\n * A DI token uniquely identifies a dependency.\r\n * It can wrap a class (Type<T>) or be a named symbol token.\r\n *\r\n * Using tokens instead of reflect-metadata means dependencies are\r\n * declared explicitly — no magic type inference, no emitDecoratorMetadata.\r\n *\r\n * @example\r\n * // Class token (most common)\r\n * const MY_SERVICE = token(MyService);\r\n *\r\n * // Named symbol token (for interfaces or non-class values)\r\n * const DB_URL = token<string>('DB_URL');\r\n */\r\nexport class Token<T> {\r\n public readonly description: string;\r\n\r\n constructor(\r\n public readonly target: Type<T> | string,\r\n ) {\r\n this.description = typeof target === 'string' ? target : target.name;\r\n }\r\n\r\n public toString(): string {\r\n return `Token(${this.description})`;\r\n }\r\n}\r\n\r\n/**\r\n * Creates a DI token for a class type or a named value.\r\n *\r\n * @example\r\n * export const MY_SERVICE = token(MyService);\r\n * export const DB_URL = token<string>('DB_URL');\r\n */\r\nexport function token<T>(target: Type<T> | string): Token<T> {\r\n return new Token<T>(target);\r\n}\r\n\r\n/**\r\n * The key used to look up a class token in the registry.\r\n * For class tokens, the key is the class constructor itself.\r\n * For named tokens, the key is the Token instance.\r\n */\r\nexport type TokenKey<T = unknown> = Type<T> | Token<T>;\r\n","/**\r\n * @copyright 2025 NoxFly\r\n * @license MIT\r\n * @author NoxFly\r\n */\r\n\r\nimport { ForwardReference } from '../utils/forward-ref';\r\nimport { Type } from '../utils/types';\r\nimport { Token, TokenKey } from './token';\r\n\r\n/**\r\n * Lifetime of a binding in the DI container.\r\n * - singleton: created once, shared for the lifetime of the app.\r\n * - scope: created once per request scope.\r\n * - transient: new instance every time it is resolved.\r\n */\r\nexport type Lifetime = 'singleton' | 'scope' | 'transient';\r\n\r\n/**\r\n * Internal representation of a registered binding.\r\n */\r\nexport interface IBinding<T = unknown> {\r\n lifetime: Lifetime;\r\n implementation: Type<T>;\r\n /** Explicit constructor dependencies, declared by the class itself. */\r\n deps: ReadonlyArray<TokenKey>;\r\n instance?: T;\r\n}\r\n\r\nfunction keyOf<T>(k: TokenKey<T>): Type<T> | Token<T> {\r\n return k;\r\n}\r\n\r\n/**\r\n * AppInjector is the core DI container.\r\n * It no longer uses reflect-metadata — all dependency information\r\n * comes from explicitly declared `deps` arrays on each binding.\r\n */\r\nexport class AppInjector {\r\n public readonly bindings = new Map<Type<unknown> | Token<unknown>, IBinding<unknown>>();\r\n public readonly singletons = new Map<Type<unknown> | Token<unknown>, unknown>();\r\n public readonly scoped = new Map<Type<unknown> | Token<unknown>, unknown>();\r\n\r\n constructor(public readonly name: string | null = null) {}\r\n\r\n /**\r\n * Creates a child scope for per-request lifetime resolution.\r\n */\r\n public createScope(): AppInjector {\r\n const scope = new AppInjector();\r\n (scope as any).bindings = this.bindings;\r\n (scope as any).singletons = this.singletons;\r\n return scope;\r\n }\r\n\r\n /**\r\n * Registers a binding explicitly.\r\n */\r\n public register<T>(\r\n key: TokenKey<T>,\r\n implementation: Type<T>,\r\n lifetime: Lifetime,\r\n deps: ReadonlyArray<TokenKey> = [],\r\n ): void {\r\n const k = keyOf(key) as TokenKey<unknown>;\r\n if (!this.bindings.has(k)) {\r\n this.bindings.set(k, { lifetime, implementation: implementation as Type<unknown>, deps });\r\n }\r\n }\r\n\r\n /**\r\n * Resolves a dependency by token or class reference.\r\n */\r\n public resolve<T>(target: TokenKey<T> | ForwardReference<T>): T {\r\n if (target instanceof ForwardReference) {\r\n return this._resolveForwardRef(target);\r\n }\r\n\r\n const k = keyOf(target) as TokenKey<unknown>;\r\n\r\n if (this.singletons.has(k)) {\r\n return this.singletons.get(k) as T;\r\n }\r\n\r\n const binding = this.bindings.get(k);\r\n\r\n if (!binding) {\r\n const name = target instanceof Token\r\n ? target.description\r\n : (target as Type<unknown>).name\r\n ?? 'unknown';\r\n\r\n throw new Error(\r\n `[Noxus DI] No binding found for \"${name}\".\\n`\r\n + `Did you forget to declare it in @Injectable({ deps }) or in bootstrapApplication({ singletons })?`,\r\n );\r\n }\r\n\r\n switch (binding.lifetime) {\r\n case 'transient':\r\n return this._instantiate(binding) as T;\r\n\r\n case 'scope': {\r\n if (this.scoped.has(k)) return this.scoped.get(k) as T;\r\n const inst = this._instantiate(binding);\r\n this.scoped.set(k, inst);\r\n return inst as T;\r\n }\r\n\r\n case 'singleton': {\r\n if (this.singletons.has(k)) return this.singletons.get(k) as T;\r\n const inst = this._instantiate(binding);\r\n this.singletons.set(k, inst);\r\n if (binding.instance === undefined) {\r\n (binding as IBinding<unknown>).instance = inst as unknown;\r\n }\r\n return inst as T;\r\n }\r\n }\r\n }\r\n\r\n // -------------------------------------------------------------------------\r\n\r\n private _resolveForwardRef<T>(ref: ForwardReference<T>): T {\r\n let resolved: T | undefined;\r\n return new Proxy({} as object, {\r\n get: (_obj, prop, receiver) => {\r\n resolved ??= this.resolve(ref.forwardRefFn()) as T;\r\n const value = Reflect.get(resolved as object, prop, receiver);\r\n return typeof value === 'function' ? (value as Function).bind(resolved) : value;\r\n },\r\n set: (_obj, prop, value, receiver) => {\r\n resolved ??= this.resolve(ref.forwardRefFn()) as T;\r\n return Reflect.set(resolved as object, prop, value, receiver);\r\n },\r\n getPrototypeOf: () => {\r\n resolved ??= this.resolve(ref.forwardRefFn()) as T;\r\n return Object.getPrototypeOf(resolved);\r\n },\r\n }) as T;\r\n }\r\n\r\n private _instantiate<T>(binding: IBinding<T>): T {\r\n const resolvedDeps = binding.deps.map((dep) => this.resolve(dep));\r\n return new binding.implementation(...resolvedDeps) as T;\r\n }\r\n}\r\n\r\n/**\r\n * The global root injector. All singletons live here.\r\n */\r\nexport const RootInjector = new AppInjector('root');\r\n\r\n/**\r\n * Resets the root injector to a clean state.\r\n * **Intended for testing only** — clears all bindings, singletons, and scoped instances\r\n * so that each test can start from a fresh DI container without restarting the process.\r\n */\r\nexport function resetRootInjector(): void {\r\n RootInjector.bindings.clear();\r\n RootInjector.singletons.clear();\r\n RootInjector.scoped.clear();\r\n // Lazy import to avoid circular dependency (InjectorExplorer → app-injector → InjectorExplorer)\r\n const { InjectorExplorer } = require('./injector-explorer') as typeof import('./injector-explorer');\r\n InjectorExplorer.reset();\r\n}\r\n\r\n/**\r\n * Convenience function: resolve a token from the root injector.\r\n */\r\nexport function inject<T>(t: TokenKey<T> | ForwardReference<T>): T {\r\n return RootInjector.resolve(t);\r\n}\r\n","/**\r\n * @copyright 2025 NoxFly\r\n * @license MIT\r\n * @author NoxFly\r\n *\r\n * Entry point for renderer web consumers (Angular, React, Vue, Vanilla...).\r\n * No Electron imports — safe to bundle with any web bundler.\r\n */\r\n\r\nexport * from './internal/renderer-client';\r\nexport * from './internal/renderer-events';\r\nexport * from './internal/request';\r\nexport type { HttpMethod, AtomicHttpMethod } from './decorators/method.decorator';\r\n","/**\r\n * @copyright 2025 NoxFly\r\n * @license MIT\r\n * @author NoxFly\r\n */\r\n\r\n\r\nimport { AtomicHttpMethod, HttpMethod } from '../decorators/method.decorator';\r\nimport { AppInjector, RootInjector } from '../DI/app-injector';\r\n\r\n/**\r\n * The Request class represents an HTTP request in the Noxus framework.\r\n * It encapsulates the request data, including the event, ID, method, path, and body.\r\n * It also provides a context for dependency injection through the AppInjector.\r\n */\r\nexport class Request {\r\n public readonly context: AppInjector = RootInjector.createScope();\r\n\r\n public readonly params: Record<string, string> = {};\r\n public readonly query: Record<string, unknown>;\r\n\r\n constructor(\r\n public readonly event: Electron.MessageEvent,\r\n public readonly senderId: number,\r\n public readonly id: string,\r\n public readonly method: HttpMethod,\r\n public readonly path: string,\r\n public readonly body: unknown,\r\n query?: Record<string, unknown>,\r\n ) {\r\n this.path = path.replace(/^\\/|\\/$/g, '');\r\n this.query = query ?? {};\r\n }\r\n}\r\n\r\n/**\r\n * The IRequest interface defines the structure of a request object.\r\n * It includes properties for the sender ID, request ID, path, method, and an optional body.\r\n * This interface is used to standardize the request data across the application.\r\n */\r\nexport interface IRequest<TBody = unknown> {\r\n senderId: number;\r\n requestId: string;\r\n path: string;\r\n method: HttpMethod;\r\n body?: TBody;\r\n query?: Record<string, unknown>;\r\n}\r\n\r\nexport interface IBatchRequestItem<TBody = unknown> {\r\n requestId?: string;\r\n path: string;\r\n method: AtomicHttpMethod;\r\n body?: TBody;\r\n query?: Record<string, unknown>;\r\n}\r\n\r\nexport interface IBatchRequestPayload {\r\n requests: IBatchRequestItem[];\r\n}\r\n\r\n/**\r\n * Creates a Request object from the IPC event data.\r\n * This function extracts the necessary information from the IPC event and constructs a Request instance.\r\n */\r\nexport interface IResponse<TBody = unknown> {\r\n requestId: string;\r\n status: number;\r\n body?: TBody;\r\n error?: string;\r\n stack?: string;\r\n}\r\n\r\nexport interface IBatchResponsePayload {\r\n responses: IResponse[];\r\n}\r\n\r\nexport const RENDERER_EVENT_TYPE = 'noxus:event';\r\n\r\nexport interface IRendererEventMessage<TPayload = unknown> {\r\n type: typeof RENDERER_EVENT_TYPE;\r\n event: string;\r\n payload?: TPayload;\r\n}\r\n\r\nexport function createRendererEventMessage<TPayload = unknown>(event: string, payload?: TPayload): IRendererEventMessage<TPayload> {\r\n return {\r\n type: RENDERER_EVENT_TYPE,\r\n event,\r\n payload,\r\n };\r\n}\r\n\r\nexport function isRendererEventMessage(value: unknown): value is IRendererEventMessage {\r\n if(value === null || typeof value !== 'object') {\r\n return false;\r\n }\r\n\r\n const possibleMessage = value as Partial<IRendererEventMessage>;\r\n\r\n return possibleMessage.type === RENDERER_EVENT_TYPE && typeof possibleMessage.event === 'string';\r\n}\r\n","/**\r\n * @copyright 2025 NoxFly\r\n * @license MIT\r\n * @author NoxFly\r\n */\r\n\r\n/**\r\n * Lightweight event registry to help renderer processes subscribe to\r\n * push messages sent by the main process through Noxus.\r\n */\r\nimport { IRendererEventMessage, isRendererEventMessage } from './request';\r\n\r\nexport type RendererEventHandler<TPayload = unknown> = (payload: TPayload) => void;\r\n\r\nexport interface RendererEventSubscription {\r\n unsubscribe(): void;\r\n}\r\n\r\nexport class RendererEventRegistry {\r\n private readonly listeners = new Map<string, Set<RendererEventHandler>>();\r\n\r\n /**\r\n *\r\n */\r\n public subscribe<TPayload>(eventName: string, handler: RendererEventHandler<TPayload>): RendererEventSubscription {\r\n const normalizedEventName = eventName.trim();\r\n\r\n if(normalizedEventName.length === 0) {\r\n throw new Error('Renderer event name must be a non-empty string.');\r\n }\r\n\r\n const handlers = this.listeners.get(normalizedEventName) ?? new Set<RendererEventHandler>();\r\n\r\n handlers.add(handler as RendererEventHandler);\r\n this.listeners.set(normalizedEventName, handlers);\r\n\r\n return {\r\n unsubscribe: () => this.unsubscribe(normalizedEventName, handler as RendererEventHandler),\r\n };\r\n }\r\n\r\n /**\r\n *\r\n */\r\n public unsubscribe<TPayload>(eventName: string, handler: RendererEventHandler<TPayload>): void {\r\n const handlers = this.listeners.get(eventName);\r\n\r\n if(!handlers) {\r\n return;\r\n }\r\n\r\n handlers.delete(handler as RendererEventHandler);\r\n\r\n if(handlers.size === 0) {\r\n this.listeners.delete(eventName);\r\n }\r\n }\r\n\r\n /**\r\n *\r\n */\r\n public clear(eventName?: string): void {\r\n if(eventName) {\r\n this.listeners.delete(eventName);\r\n return;\r\n }\r\n\r\n this.listeners.clear();\r\n }\r\n\r\n /**\r\n *\r\n */\r\n public dispatch<TPayload>(message: IRendererEventMessage<TPayload>): void {\r\n const handlers = this.listeners.get(message.event);\r\n\r\n if(!handlers || handlers.size === 0) {\r\n return;\r\n }\r\n\r\n handlers.forEach((handler) => {\r\n try {\r\n handler(message.payload as TPayload);\r\n }\r\n catch(error) {\r\n console.error(`[Noxus] Renderer event handler for \"${message.event}\" threw an error.`, error);\r\n }\r\n });\r\n }\r\n\r\n /**\r\n *\r\n */\r\n public tryDispatchFromMessageEvent(event: MessageEvent): boolean {\r\n if(!isRendererEventMessage(event.data)) {\r\n return false;\r\n }\r\n\r\n this.dispatch(event.data);\r\n return true;\r\n }\r\n\r\n /**\r\n *\r\n */\r\n public hasHandlers(eventName: string): boolean {\r\n const handlers = this.listeners.get(eventName);\r\n return !!handlers && handlers.size > 0;\r\n }\r\n}\r\n","/**\r\n * @copyright 2025 NoxFly\r\n * @license MIT\r\n * @author NoxFly\r\n */\r\n\r\nimport { IBatchRequestItem, IBatchResponsePayload, IRequest, IResponse } from './request';\r\nimport { RendererEventRegistry } from './renderer-events';\r\n\r\nexport interface IPortRequester {\r\n requestPort(): void;\r\n}\r\n\r\n/**\r\n * Per-request options that can override global client defaults.\r\n */\r\nexport interface RequestOptions {\r\n /**\r\n * Timeout in milliseconds for this specific request.\r\n * Overrides the global `requestTimeout` set on the client.\r\n * Set to 0 to disable timeout for this request.\r\n */\r\n timeout?: number;\r\n}\r\n\r\nexport interface RendererClientOptions {\r\n bridge?: IPortRequester | null;\r\n bridgeName?: string | string[];\r\n initMessageType?: string;\r\n windowRef?: Window;\r\n generateRequestId?: () => string;\r\n /**\r\n * Timeout in milliseconds for IPC requests.\r\n * If the main process does not respond within this duration,\r\n * the request Promise is rejected and the pending entry cleaned up.\r\n * Defaults to 10 000 ms. Set to 0 to disable.\r\n */\r\n requestTimeout?: number;\r\n /** @default true */\r\n enableLogging?: boolean;\r\n}\r\n\r\ninterface PendingRequest<T = unknown> {\r\n resolve: (value: T) => void;\r\n reject: (reason: IResponse<T>) => void;\r\n request: IRequest;\r\n submittedAt: number;\r\n timer?: ReturnType<typeof setTimeout>;\r\n}\r\n\r\nconst DEFAULT_INIT_EVENT = 'init-port';\r\nconst DEFAULT_BRIDGE_NAMES = ['noxus', 'ipcRenderer'];\r\n\r\nfunction defaultRequestId(): string {\r\n if(typeof crypto !== 'undefined' && typeof crypto.randomUUID === 'function') {\r\n return crypto.randomUUID();\r\n }\r\n\r\n return `${Date.now().toString(16)}-${Math.floor(Math.random() * 1e8).toString(16)}`;\r\n}\r\n\r\nfunction normalizeBridgeNames(preferred?: string | string[]): string[] {\r\n const names: string[] = [];\r\n\r\n const add = (name: string | undefined): void => {\r\n if(!name)\r\n return;\r\n\r\n if(!names.includes(name)) {\r\n names.push(name);\r\n }\r\n };\r\n\r\n if(Array.isArray(preferred)) {\r\n for(const name of preferred) {\r\n add(name);\r\n }\r\n }\r\n else {\r\n add(preferred);\r\n }\r\n\r\n for(const fallback of DEFAULT_BRIDGE_NAMES) {\r\n add(fallback);\r\n }\r\n\r\n return names;\r\n}\r\n\r\nfunction resolveBridgeFromWindow(windowRef: Window, preferred?: string | string[]): IPortRequester | null {\r\n const names = normalizeBridgeNames(preferred);\r\n const globalRef = windowRef as unknown as Record<string, unknown> | null | undefined;\r\n\r\n if(!globalRef) {\r\n return null;\r\n }\r\n\r\n for(const name of names) {\r\n const candidate = globalRef[name];\r\n\r\n if(candidate && typeof (candidate as IPortRequester).requestPort === 'function') {\r\n return candidate as IPortRequester;\r\n }\r\n }\r\n\r\n return null;\r\n}\r\n\r\nexport class NoxRendererClient {\r\n public readonly events = new RendererEventRegistry();\r\n\r\n protected readonly pendingRequests = new Map<string, PendingRequest>();\r\n\r\n protected requestPort: MessagePort | undefined;\r\n protected socketPort: MessagePort | undefined;\r\n protected senderId: number | undefined;\r\n\r\n private readonly bridge: IPortRequester | null;\r\n private readonly initMessageType: string;\r\n private readonly windowRef: Window;\r\n private readonly generateRequestId: () => string;\r\n private readonly requestTimeout: number;\r\n\r\n private isReady = false;\r\n private setupPromise: Promise<void> | undefined;\r\n private setupResolve: (() => void) | undefined;\r\n private setupReject: ((reason: Error) => void) | undefined;\r\n\r\n private enableLogging: boolean;\r\n\r\n constructor(options: RendererClientOptions = {}) {\r\n this.windowRef = options.windowRef ?? window;\r\n const resolvedBridge = options.bridge ?? resolveBridgeFromWindow(this.windowRef, options.bridgeName);\r\n this.bridge = resolvedBridge ?? null;\r\n this.initMessageType = options.initMessageType ?? DEFAULT_INIT_EVENT;\r\n this.generateRequestId = options.generateRequestId ?? defaultRequestId;\r\n this.requestTimeout = options.requestTimeout ?? 10_000;\r\n this.enableLogging = options.enableLogging ?? true;\r\n }\r\n\r\n public async setup(): Promise<void> {\r\n if(this.isReady) {\r\n return Promise.resolve();\r\n }\r\n\r\n if(this.setupPromise) {\r\n return this.setupPromise;\r\n }\r\n\r\n if(!this.bridge || typeof this.bridge.requestPort !== 'function') {\r\n throw new Error('[Noxus] Renderer bridge is missing requestPort().');\r\n }\r\n\r\n this.setupPromise = new Promise<void>((resolve, reject) => {\r\n this.setupResolve = resolve;\r\n this.setupReject = reject;\r\n });\r\n\r\n this.windowRef.addEventListener('message', this.onWindowMessage);\r\n this.bridge.requestPort();\r\n\r\n return this.setupPromise;\r\n }\r\n\r\n public dispose(): void {\r\n this.windowRef.removeEventListener('message', this.onWindowMessage);\r\n\r\n this.requestPort?.close();\r\n this.socketPort?.close();\r\n\r\n this.requestPort = undefined;\r\n this.socketPort = undefined;\r\n this.senderId = undefined;\r\n this.isReady = false;\r\n\r\n for(const pending of this.pendingRequests.values()) {\r\n if(pending.timer !== undefined) {\r\n clearTimeout(pending.timer);\r\n }\r\n }\r\n\r\n this.pendingRequests.clear();\r\n }\r\n\r\n public async request<TResponse, TBody = unknown>(\r\n request: Omit<IRequest<TBody>, 'requestId' | 'senderId'>,\r\n options?: RequestOptions,\r\n ): Promise<TResponse> {\r\n const senderId = this.senderId;\r\n const requestId = this.generateRequestId();\r\n\r\n if(senderId === undefined) {\r\n return Promise.reject(this.createErrorResponse(requestId, 'MessagePort is not available'));\r\n }\r\n\r\n const readinessError = this.validateReady(requestId);\r\n\r\n if(readinessError) {\r\n return Promise.reject(readinessError as IResponse<TResponse>);\r\n }\r\n\r\n const message: IRequest<TBody> = {\r\n requestId,\r\n senderId,\r\n ...request,\r\n };\r\n\r\n const effectiveTimeout = options?.timeout ?? this.requestTimeout;\r\n\r\n return new Promise<TResponse>((resolve, reject) => {\r\n const pending: PendingRequest<TResponse> = {\r\n resolve,\r\n reject: (response: IResponse<TResponse>) => reject(response),\r\n request: message,\r\n submittedAt: Date.now(),\r\n };\r\n\r\n if(effectiveTimeout > 0) {\r\n pending.timer = setTimeout(() => {\r\n this.pendingRequests.delete(message.requestId);\r\n reject(this.createErrorResponse<TResponse>(message.requestId, `Request timed out after ${effectiveTimeout}ms`) as IResponse<TResponse>);\r\n }, effectiveTimeout);\r\n }\r\n\r\n this.pendingRequests.set(message.requestId, pending as PendingRequest);\r\n\r\n this.requestPort!.postMessage(message);\r\n });\r\n }\r\n\r\n public async batch(requests: Omit<IBatchRequestItem<unknown>, 'requestId'>[]): Promise<IBatchResponsePayload> {\r\n return this.request<IBatchResponsePayload>({\r\n method: 'BATCH',\r\n path: '',\r\n body: {\r\n requests,\r\n },\r\n });\r\n }\r\n\r\n public getSenderId(): number | undefined {\r\n return this.senderId;\r\n }\r\n\r\n private readonly onWindowMessage = (event: MessageEvent): void => {\r\n if(event.data?.type !== this.initMessageType) {\r\n return;\r\n }\r\n\r\n if(!Array.isArray(event.ports) || event.ports.length < 2) {\r\n const error = new Error('[Noxus] Renderer expected two MessagePorts (request + socket).');\r\n\r\n console.error(error);\r\n this.setupReject?.(error);\r\n this.resetSetupState();\r\n return;\r\n }\r\n\r\n this.windowRef.removeEventListener('message', this.onWindowMessage);\r\n\r\n this.requestPort = event.ports[0];\r\n this.socketPort = event.ports[1];\r\n this.senderId = event.data.senderId;\r\n\r\n if(this.requestPort === undefined || this.socketPort === undefined) {\r\n const error = new Error('[Noxus] Renderer failed to receive valid MessagePorts.');\r\n console.error(error);\r\n this.setupReject?.(error);\r\n this.resetSetupState();\r\n return;\r\n }\r\n\r\n this.attachRequestPort(this.requestPort);\r\n this.attachSocketPort(this.socketPort);\r\n\r\n this.isReady = true;\r\n this.setupResolve?.();\r\n this.resetSetupState(true);\r\n };\r\n\r\n private readonly onSocketMessage = (event: MessageEvent): void => {\r\n if(this.events.tryDispatchFromMessageEvent(event)) {\r\n return;\r\n }\r\n\r\n console.warn('[Noxus] Received a socket message that is not a renderer event payload.', event.data);\r\n };\r\n\r\n private readonly onRequestMessage = (event: MessageEvent): void => {\r\n if(this.events.tryDispatchFromMessageEvent(event)) {\r\n return;\r\n }\r\n\r\n const response: IResponse = event.data;\r\n\r\n if(!response || typeof response.requestId !== 'string') {\r\n console.error('[Noxus] Renderer received an invalid response payload.', response);\r\n return;\r\n }\r\n\r\n const pending = this.pendingRequests.get(response.requestId);\r\n\r\n if(!pending) {\r\n console.error(`[Noxus] No pending handler found for request ${response.requestId}.`);\r\n return;\r\n }\r\n\r\n if(pending.timer !== undefined) {\r\n clearTimeout(pending.timer);\r\n }\r\n\r\n this.pendingRequests.delete(response.requestId);\r\n\r\n this.onRequestCompleted(pending, response);\r\n\r\n if(response.status >= 400) {\r\n pending.reject(response as IResponse<any>);\r\n return;\r\n }\r\n\r\n pending.resolve(response.body as unknown);\r\n };\r\n\r\n protected onRequestCompleted(pending: PendingRequest, response: IResponse): void {\r\n if(!this.enableLogging) {\r\n return;\r\n }\r\n\r\n if(typeof console.groupCollapsed === 'function') {\r\n console.groupCollapsed(`${response.status} ${pending.request.method} /${pending.request.path}`);\r\n }\r\n\r\n if(response.error) {\r\n console.error('error message:', response.error);\r\n }\r\n\r\n if(response.body !== undefined) {\r\n console.info('response:', response.body);\r\n }\r\n\r\n console.info('request:', pending.request);\r\n console.info(`Request duration: ${Date.now() - pending.submittedAt} ms`);\r\n\r\n if(typeof console.groupCollapsed === 'function') {\r\n console.groupEnd();\r\n }\r\n }\r\n\r\n private attachRequestPort(port: MessagePort): void {\r\n port.onmessage = this.onRequestMessage;\r\n port.start();\r\n }\r\n\r\n private attachSocketPort(port: MessagePort): void {\r\n port.onmessage = this.onSocketMessage;\r\n port.start();\r\n }\r\n\r\n private validateReady(requestId: string): IResponse | undefined {\r\n if(!this.isElectronEnvironment()) {\r\n return this.createErrorResponse(requestId, 'Not running in Electron environment');\r\n }\r\n\r\n if(!this.requestPort) {\r\n return this.createErrorResponse(requestId, 'MessagePort is not available');\r\n }\r\n\r\n return undefined;\r\n }\r\n\r\n private createErrorResponse<T>(requestId: string, message: string): IResponse<T> {\r\n return {\r\n status: 500,\r\n requestId,\r\n error: message,\r\n };\r\n }\r\n\r\n private resetSetupState(success = false): void {\r\n if(!success) {\r\n this.setupPromise = undefined;\r\n }\r\n\r\n this.setupResolve = undefined;\r\n this.setupReject = undefined;\r\n }\r\n\r\n public isElectronEnvironment(): boolean {\r\n return typeof window !== 'undefined' && /Electron/.test(window.navigator.userAgent);\r\n }\r\n}\r\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../src/utils/forward-ref.ts","../src/DI/token.ts","../src/DI/app-injector.ts","../src/renderer.ts","../src/internal/request.ts","../src/internal/renderer-events.ts","../src/internal/renderer-client.ts"],"sourcesContent":["/**\r\n * @copyright 2025 NoxFly\r\n * @license MIT\r\n * @author NoxFly\r\n */\r\n\r\nimport { Type } from \"./types\";\r\n\r\n/**\r\n * A function that returns a type.\r\n * Used for forward references to types that are not yet defined.\r\n */\r\nexport interface ForwardRefFn<T = any> {\r\n (): Type<T>;\r\n}\r\n\r\n/**\r\n * A wrapper class for forward referenced types.\r\n */\r\nexport class ForwardReference<T = any> {\r\n constructor(public readonly forwardRefFn: ForwardRefFn<T>) {}\r\n}\r\n\r\n/**\r\n * Creates a forward reference to a type.\r\n * @param fn A function that returns the type.\r\n * @returns A ForwardReference instance.\r\n */\r\nexport function forwardRef<T = any>(fn: ForwardRefFn<T>): ForwardReference<T> {\r\n return new ForwardReference(fn);\r\n}\r\n","/**\r\n * @copyright 2025 NoxFly\r\n * @license MIT\r\n * @author NoxFly\r\n */\r\n\r\nimport { Type } from '../utils/types';\r\n\r\n/**\r\n * A DI token uniquely identifies a dependency.\r\n * It can wrap a class (Type<T>) or be a named symbol token.\r\n *\r\n * Using tokens instead of reflect-metadata means dependencies are\r\n * declared explicitly — no magic type inference, no emitDecoratorMetadata.\r\n *\r\n * @example\r\n * // Class token (most common)\r\n * const MY_SERVICE = token(MyService);\r\n *\r\n * // Named symbol token (for interfaces or non-class values)\r\n * const DB_URL = token<string>('DB_URL');\r\n */\r\nexport class Token<T> {\r\n public readonly description: string;\r\n\r\n constructor(\r\n public readonly target: Type<T> | string,\r\n ) {\r\n this.description = typeof target === 'string' ? target : target.name;\r\n }\r\n\r\n public toString(): string {\r\n return `Token(${this.description})`;\r\n }\r\n}\r\n\r\n/**\r\n * Creates a DI token for a class type or a named value.\r\n *\r\n * @example\r\n * export const MY_SERVICE = token(MyService);\r\n * export const DB_URL = token<string>('DB_URL');\r\n */\r\nexport function token<T>(target: Type<T> | string): Token<T> {\r\n return new Token<T>(target);\r\n}\r\n\r\n/**\r\n * The key used to look up a class token in the registry.\r\n * For class tokens, the key is the class constructor itself.\r\n * For named tokens, the key is the Token instance.\r\n */\r\nexport type TokenKey<T = unknown> = Type<T> | Token<T>;\r\n","/**\r\n * @copyright 2025 NoxFly\r\n * @license MIT\r\n * @author NoxFly\r\n */\r\n\r\nimport { ForwardReference } from '../utils/forward-ref';\r\nimport { Type } from '../utils/types';\r\nimport { Token, TokenKey } from './token';\r\n\r\n/**\r\n * Lifetime of a binding in the DI container.\r\n * - singleton: created once, shared for the lifetime of the app.\r\n * - scope: created once per request scope.\r\n * - transient: new instance every time it is resolved.\r\n */\r\nexport type Lifetime = 'singleton' | 'scope' | 'transient';\r\n\r\n/**\r\n * Internal representation of a registered binding.\r\n */\r\nexport interface IBinding<T = unknown> {\r\n lifetime: Lifetime;\r\n implementation: Type<T>;\r\n /** Explicit constructor dependencies, declared by the class itself. */\r\n deps: ReadonlyArray<TokenKey>;\r\n instance?: T;\r\n}\r\n\r\nfunction keyOf<T>(k: TokenKey<T>): Type<T> | Token<T> {\r\n return k;\r\n}\r\n\r\n/**\r\n * AppInjector is the core DI container.\r\n * It no longer uses reflect-metadata — all dependency information\r\n * comes from explicitly declared `deps` arrays on each binding.\r\n */\r\nexport class AppInjector {\r\n public readonly bindings = new Map<Type<unknown> | Token<unknown>, IBinding<unknown>>();\r\n public readonly singletons = new Map<Type<unknown> | Token<unknown>, unknown>();\r\n public readonly scoped = new Map<Type<unknown> | Token<unknown>, unknown>();\r\n\r\n constructor(public readonly name: string | null = null) {}\r\n\r\n /**\r\n * Creates a child scope for per-request lifetime resolution.\r\n */\r\n public createScope(): AppInjector {\r\n const scope = new AppInjector();\r\n (scope as any).bindings = this.bindings;\r\n (scope as any).singletons = this.singletons;\r\n return scope;\r\n }\r\n\r\n /**\r\n * Registers a binding explicitly.\r\n */\r\n public register<T>(\r\n key: TokenKey<T>,\r\n implementation: Type<T>,\r\n lifetime: Lifetime,\r\n deps: ReadonlyArray<TokenKey> = [],\r\n ): void {\r\n const k = keyOf(key) as TokenKey<unknown>;\r\n if (!this.bindings.has(k)) {\r\n this.bindings.set(k, { lifetime, implementation: implementation as Type<unknown>, deps });\r\n }\r\n }\r\n\r\n /**\r\n * Resolves a dependency by token or class reference.\r\n */\r\n public resolve<T>(target: TokenKey<T> | ForwardReference<T>): T {\r\n if (target instanceof ForwardReference) {\r\n return this._resolveForwardRef(target);\r\n }\r\n\r\n const k = keyOf(target) as TokenKey<unknown>;\r\n\r\n if (this.singletons.has(k)) {\r\n return this.singletons.get(k) as T;\r\n }\r\n\r\n const binding = this.bindings.get(k);\r\n\r\n if (!binding) {\r\n const name = target instanceof Token\r\n ? target.description\r\n : (target as Type<unknown>).name\r\n ?? 'unknown';\r\n\r\n throw new Error(\r\n `[Noxus DI] No binding found for \"${name}\".\\n`\r\n + `Did you forget to declare it in @Injectable({ deps }) or in bootstrapApplication({ singletons })?`,\r\n );\r\n }\r\n\r\n switch (binding.lifetime) {\r\n case 'transient':\r\n return this._instantiate(binding) as T;\r\n\r\n case 'scope': {\r\n if (this.scoped.has(k)) return this.scoped.get(k) as T;\r\n const inst = this._instantiate(binding);\r\n this.scoped.set(k, inst);\r\n return inst as T;\r\n }\r\n\r\n case 'singleton': {\r\n if (this.singletons.has(k)) return this.singletons.get(k) as T;\r\n const inst = this._instantiate(binding);\r\n this.singletons.set(k, inst);\r\n if (binding.instance === undefined) {\r\n (binding as IBinding<unknown>).instance = inst as unknown;\r\n }\r\n return inst as T;\r\n }\r\n }\r\n }\r\n\r\n // -------------------------------------------------------------------------\r\n\r\n private _resolveForwardRef<T>(ref: ForwardReference<T>): T {\r\n let resolved: T | undefined;\r\n return new Proxy({} as object, {\r\n get: (_obj, prop, receiver) => {\r\n resolved ??= this.resolve(ref.forwardRefFn()) as T;\r\n const value = Reflect.get(resolved as object, prop, receiver);\r\n return typeof value === 'function' ? (value as Function).bind(resolved) : value;\r\n },\r\n set: (_obj, prop, value, receiver) => {\r\n resolved ??= this.resolve(ref.forwardRefFn()) as T;\r\n return Reflect.set(resolved as object, prop, value, receiver);\r\n },\r\n getPrototypeOf: () => {\r\n resolved ??= this.resolve(ref.forwardRefFn()) as T;\r\n return Object.getPrototypeOf(resolved);\r\n },\r\n }) as T;\r\n }\r\n\r\n private _instantiate<T>(binding: IBinding<T>): T {\r\n const resolvedDeps = binding.deps.map((dep) => this.resolve(dep));\r\n return new binding.implementation(...resolvedDeps) as T;\r\n }\r\n}\r\n\r\n/**\r\n * The global root injector. All singletons live here.\r\n */\r\nexport const RootInjector = new AppInjector('root');\r\n\r\n/**\r\n * Resets the root injector to a clean state.\r\n * **Intended for testing only** — clears all bindings, singletons, and scoped instances\r\n * so that each test can start from a fresh DI container without restarting the process.\r\n */\r\nexport function resetRootInjector(): void {\r\n RootInjector.bindings.clear();\r\n RootInjector.singletons.clear();\r\n RootInjector.scoped.clear();\r\n // Lazy import to avoid circular dependency (InjectorExplorer → app-injector → InjectorExplorer)\r\n const { InjectorExplorer } = require('./injector-explorer') as typeof import('./injector-explorer');\r\n InjectorExplorer.reset();\r\n}\r\n\r\n/**\r\n * Convenience function: resolve a token from the root injector.\r\n */\r\nexport function inject<T>(t: TokenKey<T> | ForwardReference<T>): T {\r\n return RootInjector.resolve(t);\r\n}\r\n","/**\r\n * @copyright 2025 NoxFly\r\n * @license MIT\r\n * @author NoxFly\r\n *\r\n * Entry point for renderer web consumers (Angular, React, Vue, Vanilla...).\r\n * No Electron imports — safe to bundle with any web bundler.\r\n */\r\n\r\nexport * from './internal/renderer-client';\r\nexport * from './internal/renderer-events';\r\nexport * from './internal/request';\r\nexport type { HttpMethod, AtomicHttpMethod } from './decorators/method.decorator';\r\n","/**\r\n * @copyright 2025 NoxFly\r\n * @license MIT\r\n * @author NoxFly\r\n */\r\n\r\n\r\nimport { AtomicHttpMethod, HttpMethod } from '../decorators/method.decorator';\r\nimport { AppInjector, RootInjector } from '../DI/app-injector';\r\n\r\n/**\r\n * The Request class represents an HTTP request in the Noxus framework.\r\n * It encapsulates the request data, including the event, ID, method, path, and body.\r\n * It also provides a context for dependency injection through the AppInjector.\r\n */\r\nexport class Request {\r\n public readonly context: AppInjector = RootInjector.createScope();\r\n\r\n public readonly params: Record<string, string> = {};\r\n public readonly query: Record<string, unknown>;\r\n\r\n constructor(\r\n public readonly event: Electron.MessageEvent,\r\n public readonly senderId: number,\r\n public readonly id: string,\r\n public readonly method: HttpMethod,\r\n public readonly path: string,\r\n public readonly body: unknown,\r\n query?: Record<string, unknown>,\r\n ) {\r\n this.path = path.replace(/^\\/|\\/$/g, '');\r\n this.query = query ?? {};\r\n }\r\n}\r\n\r\n/**\r\n * The IRequest interface defines the structure of a request object.\r\n * It includes properties for the sender ID, request ID, path, method, and an optional body.\r\n * This interface is used to standardize the request data across the application.\r\n */\r\nexport interface IRequest<TBody = unknown> {\r\n senderId: number;\r\n requestId: string;\r\n path: string;\r\n method: HttpMethod;\r\n body?: TBody;\r\n query?: Record<string, unknown>;\r\n}\r\n\r\nexport interface IBatchRequestItem<TBody = unknown> {\r\n requestId?: string;\r\n path: string;\r\n method: AtomicHttpMethod;\r\n body?: TBody;\r\n query?: Record<string, unknown>;\r\n}\r\n\r\nexport interface IBatchRequestPayload {\r\n requests: IBatchRequestItem[];\r\n}\r\n\r\n/**\r\n * Creates a Request object from the IPC event data.\r\n * This function extracts the necessary information from the IPC event and constructs a Request instance.\r\n */\r\nexport interface IResponse<TBody = unknown> {\r\n requestId: string;\r\n status: number;\r\n body?: TBody;\r\n error?: string;\r\n stack?: string;\r\n}\r\n\r\nexport interface IBatchResponsePayload {\r\n responses: IResponse[];\r\n}\r\n\r\nexport const RENDERER_EVENT_TYPE = 'noxus:event';\r\n\r\nexport interface IRendererEventMessage<TPayload = unknown> {\r\n type: typeof RENDERER_EVENT_TYPE;\r\n event: string;\r\n payload?: TPayload;\r\n}\r\n\r\nexport function createRendererEventMessage<TPayload = unknown>(event: string, payload?: TPayload): IRendererEventMessage<TPayload> {\r\n return {\r\n type: RENDERER_EVENT_TYPE,\r\n event,\r\n payload,\r\n };\r\n}\r\n\r\nexport function isRendererEventMessage(value: unknown): value is IRendererEventMessage {\r\n if(value === null || typeof value !== 'object') {\r\n return false;\r\n }\r\n\r\n const possibleMessage = value as Partial<IRendererEventMessage>;\r\n\r\n return possibleMessage.type === RENDERER_EVENT_TYPE && typeof possibleMessage.event === 'string';\r\n}\r\n","/**\r\n * @copyright 2025 NoxFly\r\n * @license MIT\r\n * @author NoxFly\r\n */\r\n\r\n/**\r\n * Lightweight event registry to help renderer processes subscribe to\r\n * push messages sent by the main process through Noxus.\r\n */\r\nimport { IRendererEventMessage, isRendererEventMessage } from './request';\r\n\r\nexport type RendererEventHandler<TPayload = unknown> = (payload: TPayload) => void;\r\n\r\nexport interface RendererEventSubscription {\r\n unsubscribe(): void;\r\n}\r\n\r\nexport class RendererEventRegistry {\r\n private readonly listeners = new Map<string, Set<RendererEventHandler>>();\r\n\r\n /**\r\n *\r\n */\r\n public subscribe<TPayload>(eventName: string, handler: RendererEventHandler<TPayload>): RendererEventSubscription {\r\n const normalizedEventName = eventName.trim();\r\n\r\n if(normalizedEventName.length === 0) {\r\n throw new Error('Renderer event name must be a non-empty string.');\r\n }\r\n\r\n const handlers = this.listeners.get(normalizedEventName) ?? new Set<RendererEventHandler>();\r\n\r\n handlers.add(handler as RendererEventHandler);\r\n this.listeners.set(normalizedEventName, handlers);\r\n\r\n return {\r\n unsubscribe: () => this.unsubscribe(normalizedEventName, handler as RendererEventHandler),\r\n };\r\n }\r\n\r\n /**\r\n *\r\n */\r\n public unsubscribe<TPayload>(eventName: string, handler: RendererEventHandler<TPayload>): void {\r\n const handlers = this.listeners.get(eventName);\r\n\r\n if(!handlers) {\r\n return;\r\n }\r\n\r\n handlers.delete(handler as RendererEventHandler);\r\n\r\n if(handlers.size === 0) {\r\n this.listeners.delete(eventName);\r\n }\r\n }\r\n\r\n /**\r\n *\r\n */\r\n public clear(eventName?: string): void {\r\n if(eventName) {\r\n this.listeners.delete(eventName);\r\n return;\r\n }\r\n\r\n this.listeners.clear();\r\n }\r\n\r\n /**\r\n *\r\n */\r\n public dispatch<TPayload>(message: IRendererEventMessage<TPayload>): void {\r\n const handlers = this.listeners.get(message.event);\r\n\r\n if(!handlers || handlers.size === 0) {\r\n return;\r\n }\r\n\r\n handlers.forEach((handler) => {\r\n try {\r\n handler(message.payload as TPayload);\r\n }\r\n catch(error) {\r\n console.error(`[Noxus] Renderer event handler for \"${message.event}\" threw an error.`, error);\r\n }\r\n });\r\n }\r\n\r\n /**\r\n *\r\n */\r\n public tryDispatchFromMessageEvent(event: MessageEvent): boolean {\r\n if(!isRendererEventMessage(event.data)) {\r\n return false;\r\n }\r\n\r\n this.dispatch(event.data);\r\n return true;\r\n }\r\n\r\n /**\r\n *\r\n */\r\n public hasHandlers(eventName: string): boolean {\r\n const handlers = this.listeners.get(eventName);\r\n return !!handlers && handlers.size > 0;\r\n }\r\n}\r\n","/**\r\n * @copyright 2025 NoxFly\r\n * @license MIT\r\n * @author NoxFly\r\n */\r\n\r\nimport { IBatchRequestItem, IBatchResponsePayload, IRequest, IResponse } from './request';\r\nimport { RendererEventRegistry } from './renderer-events';\r\n\r\nexport interface IPortRequester {\r\n requestPort(): void;\r\n}\r\n\r\n/**\r\n * Per-request options that can override global client defaults.\r\n */\r\nexport interface RequestOptions {\r\n /**\r\n * Timeout in milliseconds for this specific request.\r\n * Overrides the global `requestTimeout` set on the client.\r\n * Set to 0 to disable timeout for this request.\r\n */\r\n timeout?: number;\r\n}\r\n\r\nexport interface RendererClientOptions {\r\n bridge?: IPortRequester | null;\r\n bridgeName?: string | string[];\r\n initMessageType?: string;\r\n windowRef?: Window;\r\n generateRequestId?: () => string;\r\n /**\r\n * Timeout in milliseconds for IPC requests.\r\n * If the main process does not respond within this duration,\r\n * the request Promise is rejected and the pending entry cleaned up.\r\n * Defaults to 10 000 ms. Set to 0 to disable.\r\n */\r\n requestTimeout?: number;\r\n /** @default true */\r\n enableLogging?: boolean;\r\n}\r\n\r\ninterface PendingRequest<T = unknown> {\r\n resolve: (value: T) => void;\r\n reject: (reason: IResponse<T>) => void;\r\n request: IRequest;\r\n submittedAt: number;\r\n timer?: ReturnType<typeof setTimeout>;\r\n}\r\n\r\nconst DEFAULT_INIT_EVENT = 'init-port';\r\nconst DEFAULT_BRIDGE_NAMES = ['noxus', 'ipcRenderer'];\r\n\r\nfunction defaultRequestId(): string {\r\n if(typeof crypto !== 'undefined' && typeof crypto.randomUUID === 'function') {\r\n return crypto.randomUUID();\r\n }\r\n\r\n return `${Date.now().toString(16)}-${Math.floor(Math.random() * 1e8).toString(16)}`;\r\n}\r\n\r\nfunction normalizeBridgeNames(preferred?: string | string[]): string[] {\r\n const names: string[] = [];\r\n\r\n const add = (name: string | undefined): void => {\r\n if(!name)\r\n return;\r\n\r\n if(!names.includes(name)) {\r\n names.push(name);\r\n }\r\n };\r\n\r\n if(Array.isArray(preferred)) {\r\n for(const name of preferred) {\r\n add(name);\r\n }\r\n }\r\n else {\r\n add(preferred);\r\n }\r\n\r\n for(const fallback of DEFAULT_BRIDGE_NAMES) {\r\n add(fallback);\r\n }\r\n\r\n return names;\r\n}\r\n\r\nfunction resolveBridgeFromWindow(windowRef: Window, preferred?: string | string[]): IPortRequester | null {\r\n const names = normalizeBridgeNames(preferred);\r\n const globalRef = windowRef as unknown as Record<string, unknown> | null | undefined;\r\n\r\n if(!globalRef) {\r\n return null;\r\n }\r\n\r\n for(const name of names) {\r\n const candidate = globalRef[name];\r\n\r\n if(candidate && typeof (candidate as IPortRequester).requestPort === 'function') {\r\n return candidate as IPortRequester;\r\n }\r\n }\r\n\r\n return null;\r\n}\r\n\r\nexport class NoxRendererClient {\r\n public readonly events = new RendererEventRegistry();\r\n\r\n protected readonly pendingRequests = new Map<string, PendingRequest>();\r\n\r\n protected requestPort: MessagePort | undefined;\r\n protected socketPort: MessagePort | undefined;\r\n protected senderId: number | undefined;\r\n\r\n private readonly bridge: IPortRequester | null;\r\n private readonly initMessageType: string;\r\n private readonly windowRef: Window;\r\n private readonly generateRequestId: () => string;\r\n private readonly requestTimeout: number;\r\n\r\n private isReady = false;\r\n private setupPromise: Promise<void> | undefined;\r\n private setupResolve: (() => void) | undefined;\r\n private setupReject: ((reason: Error) => void) | undefined;\r\n\r\n private enableLogging: boolean;\r\n\r\n constructor(options: RendererClientOptions = {}) {\r\n this.windowRef = options.windowRef ?? window;\r\n const resolvedBridge = options.bridge ?? resolveBridgeFromWindow(this.windowRef, options.bridgeName);\r\n this.bridge = resolvedBridge ?? null;\r\n this.initMessageType = options.initMessageType ?? DEFAULT_INIT_EVENT;\r\n this.generateRequestId = options.generateRequestId ?? defaultRequestId;\r\n this.requestTimeout = options.requestTimeout ?? 10_000;\r\n this.enableLogging = options.enableLogging ?? true;\r\n }\r\n\r\n public async setup(): Promise<void> {\r\n if(this.isReady) {\r\n return Promise.resolve();\r\n }\r\n\r\n if(this.setupPromise) {\r\n return this.setupPromise;\r\n }\r\n\r\n if(!this.bridge || typeof this.bridge.requestPort !== 'function') {\r\n throw new Error('[Noxus] Renderer bridge is missing requestPort().');\r\n }\r\n\r\n this.setupPromise = new Promise<void>((resolve, reject) => {\r\n this.setupResolve = resolve;\r\n this.setupReject = reject;\r\n });\r\n\r\n this.windowRef.addEventListener('message', this.onWindowMessage);\r\n this.bridge.requestPort();\r\n\r\n return this.setupPromise;\r\n }\r\n\r\n public dispose(): void {\r\n this.windowRef.removeEventListener('message', this.onWindowMessage);\r\n\r\n this.requestPort?.close();\r\n this.socketPort?.close();\r\n\r\n this.requestPort = undefined;\r\n this.socketPort = undefined;\r\n this.senderId = undefined;\r\n this.isReady = false;\r\n\r\n for(const pending of this.pendingRequests.values()) {\r\n if(pending.timer !== undefined) {\r\n clearTimeout(pending.timer);\r\n }\r\n }\r\n\r\n this.pendingRequests.clear();\r\n }\r\n\r\n public async request<TResponse, TBody = unknown>(\r\n request: Omit<IRequest<TBody>, 'requestId' | 'senderId'>,\r\n options?: RequestOptions,\r\n ): Promise<TResponse> {\r\n const senderId = this.senderId;\r\n const requestId = this.generateRequestId();\r\n\r\n if(senderId === undefined) {\r\n return Promise.reject(this.createErrorResponse(requestId, 'MessagePort is not available'));\r\n }\r\n\r\n const readinessError = this.validateReady(requestId);\r\n\r\n if(readinessError) {\r\n return Promise.reject(readinessError as IResponse<TResponse>);\r\n }\r\n\r\n const message: IRequest<TBody> = {\r\n requestId,\r\n senderId,\r\n ...request,\r\n };\r\n\r\n const effectiveTimeout = options?.timeout ?? this.requestTimeout;\r\n\r\n return new Promise<TResponse>((resolve, reject) => {\r\n const pending: PendingRequest<TResponse> = {\r\n resolve,\r\n reject: (response: IResponse<TResponse>) => reject(response),\r\n request: message,\r\n submittedAt: Date.now(),\r\n };\r\n\r\n if(effectiveTimeout > 0) {\r\n pending.timer = setTimeout(() => {\r\n this.pendingRequests.delete(message.requestId);\r\n reject(this.createErrorResponse<TResponse>(message.requestId, `Request timed out after ${effectiveTimeout}ms`) as IResponse<TResponse>);\r\n }, effectiveTimeout);\r\n }\r\n\r\n this.pendingRequests.set(message.requestId, pending as PendingRequest);\r\n\r\n this.requestPort!.postMessage(message);\r\n });\r\n }\r\n\r\n public async batch(requests: Omit<IBatchRequestItem<unknown>, 'requestId'>[]): Promise<IBatchResponsePayload> {\r\n return this.request<IBatchResponsePayload>({\r\n method: 'BATCH',\r\n path: '',\r\n body: {\r\n requests,\r\n },\r\n });\r\n }\r\n\r\n public getSenderId(): number | undefined {\r\n return this.senderId;\r\n }\r\n\r\n private readonly onWindowMessage = (event: MessageEvent): void => {\r\n if(event.data?.type !== this.initMessageType) {\r\n return;\r\n }\r\n\r\n if(!Array.isArray(event.ports) || event.ports.length < 2) {\r\n const error = new Error('[Noxus] Renderer expected two MessagePorts (request + socket).');\r\n\r\n console.error(error);\r\n this.setupReject?.(error);\r\n this.resetSetupState();\r\n return;\r\n }\r\n\r\n this.windowRef.removeEventListener('message', this.onWindowMessage);\r\n\r\n this.requestPort = event.ports[0];\r\n this.socketPort = event.ports[1];\r\n this.senderId = event.data.senderId;\r\n\r\n if(this.requestPort === undefined || this.socketPort === undefined) {\r\n const error = new Error('[Noxus] Renderer failed to receive valid MessagePorts.');\r\n console.error(error);\r\n this.setupReject?.(error);\r\n this.resetSetupState();\r\n return;\r\n }\r\n\r\n this.attachRequestPort(this.requestPort);\r\n this.attachSocketPort(this.socketPort);\r\n\r\n this.isReady = true;\r\n this.setupResolve?.();\r\n this.resetSetupState(true);\r\n };\r\n\r\n private readonly onSocketMessage = (event: MessageEvent): void => {\r\n if(this.events.tryDispatchFromMessageEvent(event)) {\r\n return;\r\n }\r\n\r\n console.warn('[Noxus] Received a socket message that is not a renderer event payload.', event.data);\r\n };\r\n\r\n private readonly onRequestMessage = (event: MessageEvent): void => {\r\n if(this.events.tryDispatchFromMessageEvent(event)) {\r\n return;\r\n }\r\n\r\n const response: IResponse = event.data;\r\n\r\n if(!response || typeof response.requestId !== 'string') {\r\n console.error('[Noxus] Renderer received an invalid response payload.', response);\r\n return;\r\n }\r\n\r\n const pending = this.pendingRequests.get(response.requestId);\r\n\r\n if(!pending) {\r\n console.error(`[Noxus] No pending handler found for request ${response.requestId}.`);\r\n return;\r\n }\r\n\r\n if(pending.timer !== undefined) {\r\n clearTimeout(pending.timer);\r\n }\r\n\r\n this.pendingRequests.delete(response.requestId);\r\n\r\n this.onRequestCompleted(pending, response);\r\n\r\n if(response.status >= 400) {\r\n pending.reject(response as IResponse<any>);\r\n return;\r\n }\r\n\r\n pending.resolve(response.body as unknown);\r\n };\r\n\r\n protected onRequestCompleted(pending: PendingRequest, response: IResponse): void {\r\n if(!this.enableLogging) {\r\n return;\r\n }\r\n\r\n if(typeof console.groupCollapsed === 'function') {\r\n console.groupCollapsed(`${response.status} ${pending.request.method} /${pending.request.path}`);\r\n }\r\n\r\n if(response.error) {\r\n console.error('error message:', response.error);\r\n }\r\n\r\n if(response.body !== undefined) {\r\n console.info('response:', response.body);\r\n }\r\n\r\n console.info('request:', pending.request);\r\n console.info(`Request duration: ${Date.now() - pending.submittedAt} ms`);\r\n\r\n if(typeof console.groupCollapsed === 'function') {\r\n console.groupEnd();\r\n }\r\n }\r\n\r\n private attachRequestPort(port: MessagePort): void {\r\n port.onmessage = this.onRequestMessage;\r\n port.start();\r\n }\r\n\r\n private attachSocketPort(port: MessagePort): void {\r\n port.onmessage = this.onSocketMessage;\r\n port.start();\r\n }\r\n\r\n private validateReady(requestId: string): IResponse | undefined {\r\n if(!this.isElectronEnvironment()) {\r\n return this.createErrorResponse(requestId, 'Not running in Electron environment');\r\n }\r\n\r\n if(!this.requestPort) {\r\n return this.createErrorResponse(requestId, 'MessagePort is not available');\r\n }\r\n\r\n return undefined;\r\n }\r\n\r\n private createErrorResponse<T>(requestId: string, message: string): IResponse<T> {\r\n return {\r\n status: 500,\r\n requestId,\r\n error: message,\r\n };\r\n }\r\n\r\n private resetSetupState(success = false): void {\r\n if(!success) {\r\n this.setupPromise = undefined;\r\n }\r\n\r\n this.setupResolve = undefined;\r\n this.setupReject = undefined;\r\n }\r\n\r\n public isElectronEnvironment(): boolean {\r\n return typeof window !== 'undefined' && /Electron/.test(window.navigator.userAgent);\r\n }\r\n}\r\n"],"mappings":"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","names":[]}
package/dist/renderer.mjs CHANGED
@@ -5,10 +5,12 @@
5
5
  */
6
6
  var __defProp = Object.defineProperty;
7
7
  var __getOwnPropNames = Object.getOwnPropertyNames;
8
+ var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
8
9
  var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
9
10
  var __esm = (fn, res) => function __init() {
10
11
  return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
11
12
  };
13
+ var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
12
14
 
13
15
  // src/utils/forward-ref.ts
14
16
  var _ForwardReference, ForwardReference;
@@ -33,6 +35,7 @@ var init_token = __esm({
33
35
  _Token = class _Token {
34
36
  constructor(target) {
35
37
  this.target = target;
38
+ __publicField(this, "description");
36
39
  this.description = typeof target === "string" ? target : target.name;
37
40
  }
38
41
  toString() {
@@ -58,9 +61,9 @@ var init_app_injector = __esm({
58
61
  _AppInjector = class _AppInjector {
59
62
  constructor(name = null) {
60
63
  this.name = name;
61
- this.bindings = /* @__PURE__ */ new Map();
62
- this.singletons = /* @__PURE__ */ new Map();
63
- this.scoped = /* @__PURE__ */ new Map();
64
+ __publicField(this, "bindings", /* @__PURE__ */ new Map());
65
+ __publicField(this, "singletons", /* @__PURE__ */ new Map());
66
+ __publicField(this, "scoped", /* @__PURE__ */ new Map());
64
67
  }
65
68
  /**
66
69
  * Creates a child scope for per-request lifetime resolution.
@@ -159,8 +162,9 @@ var _Request = class _Request {
159
162
  this.method = method;
160
163
  this.path = path;
161
164
  this.body = body;
162
- this.context = RootInjector.createScope();
163
- this.params = {};
165
+ __publicField(this, "context", RootInjector.createScope());
166
+ __publicField(this, "params", {});
167
+ __publicField(this, "query");
164
168
  this.path = path.replace(/^\/|\/$/g, "");
165
169
  this.query = query ?? {};
166
170
  }
@@ -188,7 +192,7 @@ __name(isRendererEventMessage, "isRendererEventMessage");
188
192
  // src/internal/renderer-events.ts
189
193
  var _RendererEventRegistry = class _RendererEventRegistry {
190
194
  constructor() {
191
- this.listeners = /* @__PURE__ */ new Map();
195
+ __publicField(this, "listeners", /* @__PURE__ */ new Map());
192
196
  }
193
197
  /**
194
198
  *
@@ -314,10 +318,22 @@ function resolveBridgeFromWindow(windowRef, preferred) {
314
318
  __name(resolveBridgeFromWindow, "resolveBridgeFromWindow");
315
319
  var _NoxRendererClient = class _NoxRendererClient {
316
320
  constructor(options = {}) {
317
- this.events = new RendererEventRegistry();
318
- this.pendingRequests = /* @__PURE__ */ new Map();
319
- this.isReady = false;
320
- this.onWindowMessage = /* @__PURE__ */ __name((event) => {
321
+ __publicField(this, "events", new RendererEventRegistry());
322
+ __publicField(this, "pendingRequests", /* @__PURE__ */ new Map());
323
+ __publicField(this, "requestPort");
324
+ __publicField(this, "socketPort");
325
+ __publicField(this, "senderId");
326
+ __publicField(this, "bridge");
327
+ __publicField(this, "initMessageType");
328
+ __publicField(this, "windowRef");
329
+ __publicField(this, "generateRequestId");
330
+ __publicField(this, "requestTimeout");
331
+ __publicField(this, "isReady", false);
332
+ __publicField(this, "setupPromise");
333
+ __publicField(this, "setupResolve");
334
+ __publicField(this, "setupReject");
335
+ __publicField(this, "enableLogging");
336
+ __publicField(this, "onWindowMessage", /* @__PURE__ */ __name((event) => {
321
337
  if (event.data?.type !== this.initMessageType) {
322
338
  return;
323
339
  }
@@ -344,14 +360,14 @@ var _NoxRendererClient = class _NoxRendererClient {
344
360
  this.isReady = true;
345
361
  this.setupResolve?.();
346
362
  this.resetSetupState(true);
347
- }, "onWindowMessage");
348
- this.onSocketMessage = /* @__PURE__ */ __name((event) => {
363
+ }, "onWindowMessage"));
364
+ __publicField(this, "onSocketMessage", /* @__PURE__ */ __name((event) => {
349
365
  if (this.events.tryDispatchFromMessageEvent(event)) {
350
366
  return;
351
367
  }
352
368
  console.warn("[Noxus] Received a socket message that is not a renderer event payload.", event.data);
353
- }, "onSocketMessage");
354
- this.onRequestMessage = /* @__PURE__ */ __name((event) => {
369
+ }, "onSocketMessage"));
370
+ __publicField(this, "onRequestMessage", /* @__PURE__ */ __name((event) => {
355
371
  if (this.events.tryDispatchFromMessageEvent(event)) {
356
372
  return;
357
373
  }
@@ -375,7 +391,7 @@ var _NoxRendererClient = class _NoxRendererClient {
375
391
  return;
376
392
  }
377
393
  pending.resolve(response.body);
378
- }, "onRequestMessage");
394
+ }, "onRequestMessage"));
379
395
  this.windowRef = options.windowRef ?? window;
380
396
  const resolvedBridge = options.bridge ?? resolveBridgeFromWindow(this.windowRef, options.bridgeName);
381
397
  this.bridge = resolvedBridge ?? null;
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/utils/forward-ref.ts","../src/DI/token.ts","../src/DI/app-injector.ts","../src/internal/request.ts","../src/internal/renderer-events.ts","../src/internal/renderer-client.ts"],"sourcesContent":["/**\r\n * @copyright 2025 NoxFly\r\n * @license MIT\r\n * @author NoxFly\r\n */\r\n\r\nimport { Type } from \"./types\";\r\n\r\n/**\r\n * A function that returns a type.\r\n * Used for forward references to types that are not yet defined.\r\n */\r\nexport interface ForwardRefFn<T = any> {\r\n (): Type<T>;\r\n}\r\n\r\n/**\r\n * A wrapper class for forward referenced types.\r\n */\r\nexport class ForwardReference<T = any> {\r\n constructor(public readonly forwardRefFn: ForwardRefFn<T>) {}\r\n}\r\n\r\n/**\r\n * Creates a forward reference to a type.\r\n * @param fn A function that returns the type.\r\n * @returns A ForwardReference instance.\r\n */\r\nexport function forwardRef<T = any>(fn: ForwardRefFn<T>): ForwardReference<T> {\r\n return new ForwardReference(fn);\r\n}\r\n","/**\r\n * @copyright 2025 NoxFly\r\n * @license MIT\r\n * @author NoxFly\r\n */\r\n\r\nimport { Type } from '../utils/types';\r\n\r\n/**\r\n * A DI token uniquely identifies a dependency.\r\n * It can wrap a class (Type<T>) or be a named symbol token.\r\n *\r\n * Using tokens instead of reflect-metadata means dependencies are\r\n * declared explicitly — no magic type inference, no emitDecoratorMetadata.\r\n *\r\n * @example\r\n * // Class token (most common)\r\n * const MY_SERVICE = token(MyService);\r\n *\r\n * // Named symbol token (for interfaces or non-class values)\r\n * const DB_URL = token<string>('DB_URL');\r\n */\r\nexport class Token<T> {\r\n public readonly description: string;\r\n\r\n constructor(\r\n public readonly target: Type<T> | string,\r\n ) {\r\n this.description = typeof target === 'string' ? target : target.name;\r\n }\r\n\r\n public toString(): string {\r\n return `Token(${this.description})`;\r\n }\r\n}\r\n\r\n/**\r\n * Creates a DI token for a class type or a named value.\r\n *\r\n * @example\r\n * export const MY_SERVICE = token(MyService);\r\n * export const DB_URL = token<string>('DB_URL');\r\n */\r\nexport function token<T>(target: Type<T> | string): Token<T> {\r\n return new Token<T>(target);\r\n}\r\n\r\n/**\r\n * The key used to look up a class token in the registry.\r\n * For class tokens, the key is the class constructor itself.\r\n * For named tokens, the key is the Token instance.\r\n */\r\nexport type TokenKey<T = unknown> = Type<T> | Token<T>;\r\n","/**\r\n * @copyright 2025 NoxFly\r\n * @license MIT\r\n * @author NoxFly\r\n */\r\n\r\nimport { ForwardReference } from '../utils/forward-ref';\r\nimport { Type } from '../utils/types';\r\nimport { Token, TokenKey } from './token';\r\n\r\n/**\r\n * Lifetime of a binding in the DI container.\r\n * - singleton: created once, shared for the lifetime of the app.\r\n * - scope: created once per request scope.\r\n * - transient: new instance every time it is resolved.\r\n */\r\nexport type Lifetime = 'singleton' | 'scope' | 'transient';\r\n\r\n/**\r\n * Internal representation of a registered binding.\r\n */\r\nexport interface IBinding<T = unknown> {\r\n lifetime: Lifetime;\r\n implementation: Type<T>;\r\n /** Explicit constructor dependencies, declared by the class itself. */\r\n deps: ReadonlyArray<TokenKey>;\r\n instance?: T;\r\n}\r\n\r\nfunction keyOf<T>(k: TokenKey<T>): Type<T> | Token<T> {\r\n return k;\r\n}\r\n\r\n/**\r\n * AppInjector is the core DI container.\r\n * It no longer uses reflect-metadata — all dependency information\r\n * comes from explicitly declared `deps` arrays on each binding.\r\n */\r\nexport class AppInjector {\r\n public readonly bindings = new Map<Type<unknown> | Token<unknown>, IBinding<unknown>>();\r\n public readonly singletons = new Map<Type<unknown> | Token<unknown>, unknown>();\r\n public readonly scoped = new Map<Type<unknown> | Token<unknown>, unknown>();\r\n\r\n constructor(public readonly name: string | null = null) {}\r\n\r\n /**\r\n * Creates a child scope for per-request lifetime resolution.\r\n */\r\n public createScope(): AppInjector {\r\n const scope = new AppInjector();\r\n (scope as any).bindings = this.bindings;\r\n (scope as any).singletons = this.singletons;\r\n return scope;\r\n }\r\n\r\n /**\r\n * Registers a binding explicitly.\r\n */\r\n public register<T>(\r\n key: TokenKey<T>,\r\n implementation: Type<T>,\r\n lifetime: Lifetime,\r\n deps: ReadonlyArray<TokenKey> = [],\r\n ): void {\r\n const k = keyOf(key) as TokenKey<unknown>;\r\n if (!this.bindings.has(k)) {\r\n this.bindings.set(k, { lifetime, implementation: implementation as Type<unknown>, deps });\r\n }\r\n }\r\n\r\n /**\r\n * Resolves a dependency by token or class reference.\r\n */\r\n public resolve<T>(target: TokenKey<T> | ForwardReference<T>): T {\r\n if (target instanceof ForwardReference) {\r\n return this._resolveForwardRef(target);\r\n }\r\n\r\n const k = keyOf(target) as TokenKey<unknown>;\r\n\r\n if (this.singletons.has(k)) {\r\n return this.singletons.get(k) as T;\r\n }\r\n\r\n const binding = this.bindings.get(k);\r\n\r\n if (!binding) {\r\n const name = target instanceof Token\r\n ? target.description\r\n : (target as Type<unknown>).name\r\n ?? 'unknown';\r\n\r\n throw new Error(\r\n `[Noxus DI] No binding found for \"${name}\".\\n`\r\n + `Did you forget to declare it in @Injectable({ deps }) or in bootstrapApplication({ singletons })?`,\r\n );\r\n }\r\n\r\n switch (binding.lifetime) {\r\n case 'transient':\r\n return this._instantiate(binding) as T;\r\n\r\n case 'scope': {\r\n if (this.scoped.has(k)) return this.scoped.get(k) as T;\r\n const inst = this._instantiate(binding);\r\n this.scoped.set(k, inst);\r\n return inst as T;\r\n }\r\n\r\n case 'singleton': {\r\n if (this.singletons.has(k)) return this.singletons.get(k) as T;\r\n const inst = this._instantiate(binding);\r\n this.singletons.set(k, inst);\r\n if (binding.instance === undefined) {\r\n (binding as IBinding<unknown>).instance = inst as unknown;\r\n }\r\n return inst as T;\r\n }\r\n }\r\n }\r\n\r\n // -------------------------------------------------------------------------\r\n\r\n private _resolveForwardRef<T>(ref: ForwardReference<T>): T {\r\n let resolved: T | undefined;\r\n return new Proxy({} as object, {\r\n get: (_obj, prop, receiver) => {\r\n resolved ??= this.resolve(ref.forwardRefFn()) as T;\r\n const value = Reflect.get(resolved as object, prop, receiver);\r\n return typeof value === 'function' ? (value as Function).bind(resolved) : value;\r\n },\r\n set: (_obj, prop, value, receiver) => {\r\n resolved ??= this.resolve(ref.forwardRefFn()) as T;\r\n return Reflect.set(resolved as object, prop, value, receiver);\r\n },\r\n getPrototypeOf: () => {\r\n resolved ??= this.resolve(ref.forwardRefFn()) as T;\r\n return Object.getPrototypeOf(resolved);\r\n },\r\n }) as T;\r\n }\r\n\r\n private _instantiate<T>(binding: IBinding<T>): T {\r\n const resolvedDeps = binding.deps.map((dep) => this.resolve(dep));\r\n return new binding.implementation(...resolvedDeps) as T;\r\n }\r\n}\r\n\r\n/**\r\n * The global root injector. All singletons live here.\r\n */\r\nexport const RootInjector = new AppInjector('root');\r\n\r\n/**\r\n * Resets the root injector to a clean state.\r\n * **Intended for testing only** — clears all bindings, singletons, and scoped instances\r\n * so that each test can start from a fresh DI container without restarting the process.\r\n */\r\nexport function resetRootInjector(): void {\r\n RootInjector.bindings.clear();\r\n RootInjector.singletons.clear();\r\n RootInjector.scoped.clear();\r\n // Lazy import to avoid circular dependency (InjectorExplorer → app-injector → InjectorExplorer)\r\n const { InjectorExplorer } = require('./injector-explorer') as typeof import('./injector-explorer');\r\n InjectorExplorer.reset();\r\n}\r\n\r\n/**\r\n * Convenience function: resolve a token from the root injector.\r\n */\r\nexport function inject<T>(t: TokenKey<T> | ForwardReference<T>): T {\r\n return RootInjector.resolve(t);\r\n}\r\n","/**\r\n * @copyright 2025 NoxFly\r\n * @license MIT\r\n * @author NoxFly\r\n */\r\n\r\n\r\nimport { AtomicHttpMethod, HttpMethod } from '../decorators/method.decorator';\r\nimport { AppInjector, RootInjector } from '../DI/app-injector';\r\n\r\n/**\r\n * The Request class represents an HTTP request in the Noxus framework.\r\n * It encapsulates the request data, including the event, ID, method, path, and body.\r\n * It also provides a context for dependency injection through the AppInjector.\r\n */\r\nexport class Request {\r\n public readonly context: AppInjector = RootInjector.createScope();\r\n\r\n public readonly params: Record<string, string> = {};\r\n public readonly query: Record<string, unknown>;\r\n\r\n constructor(\r\n public readonly event: Electron.MessageEvent,\r\n public readonly senderId: number,\r\n public readonly id: string,\r\n public readonly method: HttpMethod,\r\n public readonly path: string,\r\n public readonly body: unknown,\r\n query?: Record<string, unknown>,\r\n ) {\r\n this.path = path.replace(/^\\/|\\/$/g, '');\r\n this.query = query ?? {};\r\n }\r\n}\r\n\r\n/**\r\n * The IRequest interface defines the structure of a request object.\r\n * It includes properties for the sender ID, request ID, path, method, and an optional body.\r\n * This interface is used to standardize the request data across the application.\r\n */\r\nexport interface IRequest<TBody = unknown> {\r\n senderId: number;\r\n requestId: string;\r\n path: string;\r\n method: HttpMethod;\r\n body?: TBody;\r\n query?: Record<string, unknown>;\r\n}\r\n\r\nexport interface IBatchRequestItem<TBody = unknown> {\r\n requestId?: string;\r\n path: string;\r\n method: AtomicHttpMethod;\r\n body?: TBody;\r\n query?: Record<string, unknown>;\r\n}\r\n\r\nexport interface IBatchRequestPayload {\r\n requests: IBatchRequestItem[];\r\n}\r\n\r\n/**\r\n * Creates a Request object from the IPC event data.\r\n * This function extracts the necessary information from the IPC event and constructs a Request instance.\r\n */\r\nexport interface IResponse<TBody = unknown> {\r\n requestId: string;\r\n status: number;\r\n body?: TBody;\r\n error?: string;\r\n stack?: string;\r\n}\r\n\r\nexport interface IBatchResponsePayload {\r\n responses: IResponse[];\r\n}\r\n\r\nexport const RENDERER_EVENT_TYPE = 'noxus:event';\r\n\r\nexport interface IRendererEventMessage<TPayload = unknown> {\r\n type: typeof RENDERER_EVENT_TYPE;\r\n event: string;\r\n payload?: TPayload;\r\n}\r\n\r\nexport function createRendererEventMessage<TPayload = unknown>(event: string, payload?: TPayload): IRendererEventMessage<TPayload> {\r\n return {\r\n type: RENDERER_EVENT_TYPE,\r\n event,\r\n payload,\r\n };\r\n}\r\n\r\nexport function isRendererEventMessage(value: unknown): value is IRendererEventMessage {\r\n if(value === null || typeof value !== 'object') {\r\n return false;\r\n }\r\n\r\n const possibleMessage = value as Partial<IRendererEventMessage>;\r\n\r\n return possibleMessage.type === RENDERER_EVENT_TYPE && typeof possibleMessage.event === 'string';\r\n}\r\n","/**\r\n * @copyright 2025 NoxFly\r\n * @license MIT\r\n * @author NoxFly\r\n */\r\n\r\n/**\r\n * Lightweight event registry to help renderer processes subscribe to\r\n * push messages sent by the main process through Noxus.\r\n */\r\nimport { IRendererEventMessage, isRendererEventMessage } from './request';\r\n\r\nexport type RendererEventHandler<TPayload = unknown> = (payload: TPayload) => void;\r\n\r\nexport interface RendererEventSubscription {\r\n unsubscribe(): void;\r\n}\r\n\r\nexport class RendererEventRegistry {\r\n private readonly listeners = new Map<string, Set<RendererEventHandler>>();\r\n\r\n /**\r\n *\r\n */\r\n public subscribe<TPayload>(eventName: string, handler: RendererEventHandler<TPayload>): RendererEventSubscription {\r\n const normalizedEventName = eventName.trim();\r\n\r\n if(normalizedEventName.length === 0) {\r\n throw new Error('Renderer event name must be a non-empty string.');\r\n }\r\n\r\n const handlers = this.listeners.get(normalizedEventName) ?? new Set<RendererEventHandler>();\r\n\r\n handlers.add(handler as RendererEventHandler);\r\n this.listeners.set(normalizedEventName, handlers);\r\n\r\n return {\r\n unsubscribe: () => this.unsubscribe(normalizedEventName, handler as RendererEventHandler),\r\n };\r\n }\r\n\r\n /**\r\n *\r\n */\r\n public unsubscribe<TPayload>(eventName: string, handler: RendererEventHandler<TPayload>): void {\r\n const handlers = this.listeners.get(eventName);\r\n\r\n if(!handlers) {\r\n return;\r\n }\r\n\r\n handlers.delete(handler as RendererEventHandler);\r\n\r\n if(handlers.size === 0) {\r\n this.listeners.delete(eventName);\r\n }\r\n }\r\n\r\n /**\r\n *\r\n */\r\n public clear(eventName?: string): void {\r\n if(eventName) {\r\n this.listeners.delete(eventName);\r\n return;\r\n }\r\n\r\n this.listeners.clear();\r\n }\r\n\r\n /**\r\n *\r\n */\r\n public dispatch<TPayload>(message: IRendererEventMessage<TPayload>): void {\r\n const handlers = this.listeners.get(message.event);\r\n\r\n if(!handlers || handlers.size === 0) {\r\n return;\r\n }\r\n\r\n handlers.forEach((handler) => {\r\n try {\r\n handler(message.payload as TPayload);\r\n }\r\n catch(error) {\r\n console.error(`[Noxus] Renderer event handler for \"${message.event}\" threw an error.`, error);\r\n }\r\n });\r\n }\r\n\r\n /**\r\n *\r\n */\r\n public tryDispatchFromMessageEvent(event: MessageEvent): boolean {\r\n if(!isRendererEventMessage(event.data)) {\r\n return false;\r\n }\r\n\r\n this.dispatch(event.data);\r\n return true;\r\n }\r\n\r\n /**\r\n *\r\n */\r\n public hasHandlers(eventName: string): boolean {\r\n const handlers = this.listeners.get(eventName);\r\n return !!handlers && handlers.size > 0;\r\n }\r\n}\r\n","/**\r\n * @copyright 2025 NoxFly\r\n * @license MIT\r\n * @author NoxFly\r\n */\r\n\r\nimport { IBatchRequestItem, IBatchResponsePayload, IRequest, IResponse } from './request';\r\nimport { RendererEventRegistry } from './renderer-events';\r\n\r\nexport interface IPortRequester {\r\n requestPort(): void;\r\n}\r\n\r\n/**\r\n * Per-request options that can override global client defaults.\r\n */\r\nexport interface RequestOptions {\r\n /**\r\n * Timeout in milliseconds for this specific request.\r\n * Overrides the global `requestTimeout` set on the client.\r\n * Set to 0 to disable timeout for this request.\r\n */\r\n timeout?: number;\r\n}\r\n\r\nexport interface RendererClientOptions {\r\n bridge?: IPortRequester | null;\r\n bridgeName?: string | string[];\r\n initMessageType?: string;\r\n windowRef?: Window;\r\n generateRequestId?: () => string;\r\n /**\r\n * Timeout in milliseconds for IPC requests.\r\n * If the main process does not respond within this duration,\r\n * the request Promise is rejected and the pending entry cleaned up.\r\n * Defaults to 10 000 ms. Set to 0 to disable.\r\n */\r\n requestTimeout?: number;\r\n /** @default true */\r\n enableLogging?: boolean;\r\n}\r\n\r\ninterface PendingRequest<T = unknown> {\r\n resolve: (value: T) => void;\r\n reject: (reason: IResponse<T>) => void;\r\n request: IRequest;\r\n submittedAt: number;\r\n timer?: ReturnType<typeof setTimeout>;\r\n}\r\n\r\nconst DEFAULT_INIT_EVENT = 'init-port';\r\nconst DEFAULT_BRIDGE_NAMES = ['noxus', 'ipcRenderer'];\r\n\r\nfunction defaultRequestId(): string {\r\n if(typeof crypto !== 'undefined' && typeof crypto.randomUUID === 'function') {\r\n return crypto.randomUUID();\r\n }\r\n\r\n return `${Date.now().toString(16)}-${Math.floor(Math.random() * 1e8).toString(16)}`;\r\n}\r\n\r\nfunction normalizeBridgeNames(preferred?: string | string[]): string[] {\r\n const names: string[] = [];\r\n\r\n const add = (name: string | undefined): void => {\r\n if(!name)\r\n return;\r\n\r\n if(!names.includes(name)) {\r\n names.push(name);\r\n }\r\n };\r\n\r\n if(Array.isArray(preferred)) {\r\n for(const name of preferred) {\r\n add(name);\r\n }\r\n }\r\n else {\r\n add(preferred);\r\n }\r\n\r\n for(const fallback of DEFAULT_BRIDGE_NAMES) {\r\n add(fallback);\r\n }\r\n\r\n return names;\r\n}\r\n\r\nfunction resolveBridgeFromWindow(windowRef: Window, preferred?: string | string[]): IPortRequester | null {\r\n const names = normalizeBridgeNames(preferred);\r\n const globalRef = windowRef as unknown as Record<string, unknown> | null | undefined;\r\n\r\n if(!globalRef) {\r\n return null;\r\n }\r\n\r\n for(const name of names) {\r\n const candidate = globalRef[name];\r\n\r\n if(candidate && typeof (candidate as IPortRequester).requestPort === 'function') {\r\n return candidate as IPortRequester;\r\n }\r\n }\r\n\r\n return null;\r\n}\r\n\r\nexport class NoxRendererClient {\r\n public readonly events = new RendererEventRegistry();\r\n\r\n protected readonly pendingRequests = new Map<string, PendingRequest>();\r\n\r\n protected requestPort: MessagePort | undefined;\r\n protected socketPort: MessagePort | undefined;\r\n protected senderId: number | undefined;\r\n\r\n private readonly bridge: IPortRequester | null;\r\n private readonly initMessageType: string;\r\n private readonly windowRef: Window;\r\n private readonly generateRequestId: () => string;\r\n private readonly requestTimeout: number;\r\n\r\n private isReady = false;\r\n private setupPromise: Promise<void> | undefined;\r\n private setupResolve: (() => void) | undefined;\r\n private setupReject: ((reason: Error) => void) | undefined;\r\n\r\n private enableLogging: boolean;\r\n\r\n constructor(options: RendererClientOptions = {}) {\r\n this.windowRef = options.windowRef ?? window;\r\n const resolvedBridge = options.bridge ?? resolveBridgeFromWindow(this.windowRef, options.bridgeName);\r\n this.bridge = resolvedBridge ?? null;\r\n this.initMessageType = options.initMessageType ?? DEFAULT_INIT_EVENT;\r\n this.generateRequestId = options.generateRequestId ?? defaultRequestId;\r\n this.requestTimeout = options.requestTimeout ?? 10_000;\r\n this.enableLogging = options.enableLogging ?? true;\r\n }\r\n\r\n public async setup(): Promise<void> {\r\n if(this.isReady) {\r\n return Promise.resolve();\r\n }\r\n\r\n if(this.setupPromise) {\r\n return this.setupPromise;\r\n }\r\n\r\n if(!this.bridge || typeof this.bridge.requestPort !== 'function') {\r\n throw new Error('[Noxus] Renderer bridge is missing requestPort().');\r\n }\r\n\r\n this.setupPromise = new Promise<void>((resolve, reject) => {\r\n this.setupResolve = resolve;\r\n this.setupReject = reject;\r\n });\r\n\r\n this.windowRef.addEventListener('message', this.onWindowMessage);\r\n this.bridge.requestPort();\r\n\r\n return this.setupPromise;\r\n }\r\n\r\n public dispose(): void {\r\n this.windowRef.removeEventListener('message', this.onWindowMessage);\r\n\r\n this.requestPort?.close();\r\n this.socketPort?.close();\r\n\r\n this.requestPort = undefined;\r\n this.socketPort = undefined;\r\n this.senderId = undefined;\r\n this.isReady = false;\r\n\r\n for(const pending of this.pendingRequests.values()) {\r\n if(pending.timer !== undefined) {\r\n clearTimeout(pending.timer);\r\n }\r\n }\r\n\r\n this.pendingRequests.clear();\r\n }\r\n\r\n public async request<TResponse, TBody = unknown>(\r\n request: Omit<IRequest<TBody>, 'requestId' | 'senderId'>,\r\n options?: RequestOptions,\r\n ): Promise<TResponse> {\r\n const senderId = this.senderId;\r\n const requestId = this.generateRequestId();\r\n\r\n if(senderId === undefined) {\r\n return Promise.reject(this.createErrorResponse(requestId, 'MessagePort is not available'));\r\n }\r\n\r\n const readinessError = this.validateReady(requestId);\r\n\r\n if(readinessError) {\r\n return Promise.reject(readinessError as IResponse<TResponse>);\r\n }\r\n\r\n const message: IRequest<TBody> = {\r\n requestId,\r\n senderId,\r\n ...request,\r\n };\r\n\r\n const effectiveTimeout = options?.timeout ?? this.requestTimeout;\r\n\r\n return new Promise<TResponse>((resolve, reject) => {\r\n const pending: PendingRequest<TResponse> = {\r\n resolve,\r\n reject: (response: IResponse<TResponse>) => reject(response),\r\n request: message,\r\n submittedAt: Date.now(),\r\n };\r\n\r\n if(effectiveTimeout > 0) {\r\n pending.timer = setTimeout(() => {\r\n this.pendingRequests.delete(message.requestId);\r\n reject(this.createErrorResponse<TResponse>(message.requestId, `Request timed out after ${effectiveTimeout}ms`) as IResponse<TResponse>);\r\n }, effectiveTimeout);\r\n }\r\n\r\n this.pendingRequests.set(message.requestId, pending as PendingRequest);\r\n\r\n this.requestPort!.postMessage(message);\r\n });\r\n }\r\n\r\n public async batch(requests: Omit<IBatchRequestItem<unknown>, 'requestId'>[]): Promise<IBatchResponsePayload> {\r\n return this.request<IBatchResponsePayload>({\r\n method: 'BATCH',\r\n path: '',\r\n body: {\r\n requests,\r\n },\r\n });\r\n }\r\n\r\n public getSenderId(): number | undefined {\r\n return this.senderId;\r\n }\r\n\r\n private readonly onWindowMessage = (event: MessageEvent): void => {\r\n if(event.data?.type !== this.initMessageType) {\r\n return;\r\n }\r\n\r\n if(!Array.isArray(event.ports) || event.ports.length < 2) {\r\n const error = new Error('[Noxus] Renderer expected two MessagePorts (request + socket).');\r\n\r\n console.error(error);\r\n this.setupReject?.(error);\r\n this.resetSetupState();\r\n return;\r\n }\r\n\r\n this.windowRef.removeEventListener('message', this.onWindowMessage);\r\n\r\n this.requestPort = event.ports[0];\r\n this.socketPort = event.ports[1];\r\n this.senderId = event.data.senderId;\r\n\r\n if(this.requestPort === undefined || this.socketPort === undefined) {\r\n const error = new Error('[Noxus] Renderer failed to receive valid MessagePorts.');\r\n console.error(error);\r\n this.setupReject?.(error);\r\n this.resetSetupState();\r\n return;\r\n }\r\n\r\n this.attachRequestPort(this.requestPort);\r\n this.attachSocketPort(this.socketPort);\r\n\r\n this.isReady = true;\r\n this.setupResolve?.();\r\n this.resetSetupState(true);\r\n };\r\n\r\n private readonly onSocketMessage = (event: MessageEvent): void => {\r\n if(this.events.tryDispatchFromMessageEvent(event)) {\r\n return;\r\n }\r\n\r\n console.warn('[Noxus] Received a socket message that is not a renderer event payload.', event.data);\r\n };\r\n\r\n private readonly onRequestMessage = (event: MessageEvent): void => {\r\n if(this.events.tryDispatchFromMessageEvent(event)) {\r\n return;\r\n }\r\n\r\n const response: IResponse = event.data;\r\n\r\n if(!response || typeof response.requestId !== 'string') {\r\n console.error('[Noxus] Renderer received an invalid response payload.', response);\r\n return;\r\n }\r\n\r\n const pending = this.pendingRequests.get(response.requestId);\r\n\r\n if(!pending) {\r\n console.error(`[Noxus] No pending handler found for request ${response.requestId}.`);\r\n return;\r\n }\r\n\r\n if(pending.timer !== undefined) {\r\n clearTimeout(pending.timer);\r\n }\r\n\r\n this.pendingRequests.delete(response.requestId);\r\n\r\n this.onRequestCompleted(pending, response);\r\n\r\n if(response.status >= 400) {\r\n pending.reject(response as IResponse<any>);\r\n return;\r\n }\r\n\r\n pending.resolve(response.body as unknown);\r\n };\r\n\r\n protected onRequestCompleted(pending: PendingRequest, response: IResponse): void {\r\n if(!this.enableLogging) {\r\n return;\r\n }\r\n\r\n if(typeof console.groupCollapsed === 'function') {\r\n console.groupCollapsed(`${response.status} ${pending.request.method} /${pending.request.path}`);\r\n }\r\n\r\n if(response.error) {\r\n console.error('error message:', response.error);\r\n }\r\n\r\n if(response.body !== undefined) {\r\n console.info('response:', response.body);\r\n }\r\n\r\n console.info('request:', pending.request);\r\n console.info(`Request duration: ${Date.now() - pending.submittedAt} ms`);\r\n\r\n if(typeof console.groupCollapsed === 'function') {\r\n console.groupEnd();\r\n }\r\n }\r\n\r\n private attachRequestPort(port: MessagePort): void {\r\n port.onmessage = this.onRequestMessage;\r\n port.start();\r\n }\r\n\r\n private attachSocketPort(port: MessagePort): void {\r\n port.onmessage = this.onSocketMessage;\r\n port.start();\r\n }\r\n\r\n private validateReady(requestId: string): IResponse | undefined {\r\n if(!this.isElectronEnvironment()) {\r\n return this.createErrorResponse(requestId, 'Not running in Electron environment');\r\n }\r\n\r\n if(!this.requestPort) {\r\n return this.createErrorResponse(requestId, 'MessagePort is not available');\r\n }\r\n\r\n return undefined;\r\n }\r\n\r\n private createErrorResponse<T>(requestId: string, message: string): IResponse<T> {\r\n return {\r\n status: 500,\r\n requestId,\r\n error: message,\r\n };\r\n }\r\n\r\n private resetSetupState(success = false): void {\r\n if(!success) {\r\n this.setupPromise = undefined;\r\n }\r\n\r\n this.setupResolve = undefined;\r\n this.setupReject = undefined;\r\n }\r\n\r\n public isElectronEnvironment(): boolean {\r\n return typeof window !== 'undefined' && /Electron/.test(window.navigator.userAgent);\r\n }\r\n}\r\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../src/utils/forward-ref.ts","../src/DI/token.ts","../src/DI/app-injector.ts","../src/internal/request.ts","../src/internal/renderer-events.ts","../src/internal/renderer-client.ts"],"sourcesContent":["/**\r\n * @copyright 2025 NoxFly\r\n * @license MIT\r\n * @author NoxFly\r\n */\r\n\r\nimport { Type } from \"./types\";\r\n\r\n/**\r\n * A function that returns a type.\r\n * Used for forward references to types that are not yet defined.\r\n */\r\nexport interface ForwardRefFn<T = any> {\r\n (): Type<T>;\r\n}\r\n\r\n/**\r\n * A wrapper class for forward referenced types.\r\n */\r\nexport class ForwardReference<T = any> {\r\n constructor(public readonly forwardRefFn: ForwardRefFn<T>) {}\r\n}\r\n\r\n/**\r\n * Creates a forward reference to a type.\r\n * @param fn A function that returns the type.\r\n * @returns A ForwardReference instance.\r\n */\r\nexport function forwardRef<T = any>(fn: ForwardRefFn<T>): ForwardReference<T> {\r\n return new ForwardReference(fn);\r\n}\r\n","/**\r\n * @copyright 2025 NoxFly\r\n * @license MIT\r\n * @author NoxFly\r\n */\r\n\r\nimport { Type } from '../utils/types';\r\n\r\n/**\r\n * A DI token uniquely identifies a dependency.\r\n * It can wrap a class (Type<T>) or be a named symbol token.\r\n *\r\n * Using tokens instead of reflect-metadata means dependencies are\r\n * declared explicitly — no magic type inference, no emitDecoratorMetadata.\r\n *\r\n * @example\r\n * // Class token (most common)\r\n * const MY_SERVICE = token(MyService);\r\n *\r\n * // Named symbol token (for interfaces or non-class values)\r\n * const DB_URL = token<string>('DB_URL');\r\n */\r\nexport class Token<T> {\r\n public readonly description: string;\r\n\r\n constructor(\r\n public readonly target: Type<T> | string,\r\n ) {\r\n this.description = typeof target === 'string' ? target : target.name;\r\n }\r\n\r\n public toString(): string {\r\n return `Token(${this.description})`;\r\n }\r\n}\r\n\r\n/**\r\n * Creates a DI token for a class type or a named value.\r\n *\r\n * @example\r\n * export const MY_SERVICE = token(MyService);\r\n * export const DB_URL = token<string>('DB_URL');\r\n */\r\nexport function token<T>(target: Type<T> | string): Token<T> {\r\n return new Token<T>(target);\r\n}\r\n\r\n/**\r\n * The key used to look up a class token in the registry.\r\n * For class tokens, the key is the class constructor itself.\r\n * For named tokens, the key is the Token instance.\r\n */\r\nexport type TokenKey<T = unknown> = Type<T> | Token<T>;\r\n","/**\r\n * @copyright 2025 NoxFly\r\n * @license MIT\r\n * @author NoxFly\r\n */\r\n\r\nimport { ForwardReference } from '../utils/forward-ref';\r\nimport { Type } from '../utils/types';\r\nimport { Token, TokenKey } from './token';\r\n\r\n/**\r\n * Lifetime of a binding in the DI container.\r\n * - singleton: created once, shared for the lifetime of the app.\r\n * - scope: created once per request scope.\r\n * - transient: new instance every time it is resolved.\r\n */\r\nexport type Lifetime = 'singleton' | 'scope' | 'transient';\r\n\r\n/**\r\n * Internal representation of a registered binding.\r\n */\r\nexport interface IBinding<T = unknown> {\r\n lifetime: Lifetime;\r\n implementation: Type<T>;\r\n /** Explicit constructor dependencies, declared by the class itself. */\r\n deps: ReadonlyArray<TokenKey>;\r\n instance?: T;\r\n}\r\n\r\nfunction keyOf<T>(k: TokenKey<T>): Type<T> | Token<T> {\r\n return k;\r\n}\r\n\r\n/**\r\n * AppInjector is the core DI container.\r\n * It no longer uses reflect-metadata — all dependency information\r\n * comes from explicitly declared `deps` arrays on each binding.\r\n */\r\nexport class AppInjector {\r\n public readonly bindings = new Map<Type<unknown> | Token<unknown>, IBinding<unknown>>();\r\n public readonly singletons = new Map<Type<unknown> | Token<unknown>, unknown>();\r\n public readonly scoped = new Map<Type<unknown> | Token<unknown>, unknown>();\r\n\r\n constructor(public readonly name: string | null = null) {}\r\n\r\n /**\r\n * Creates a child scope for per-request lifetime resolution.\r\n */\r\n public createScope(): AppInjector {\r\n const scope = new AppInjector();\r\n (scope as any).bindings = this.bindings;\r\n (scope as any).singletons = this.singletons;\r\n return scope;\r\n }\r\n\r\n /**\r\n * Registers a binding explicitly.\r\n */\r\n public register<T>(\r\n key: TokenKey<T>,\r\n implementation: Type<T>,\r\n lifetime: Lifetime,\r\n deps: ReadonlyArray<TokenKey> = [],\r\n ): void {\r\n const k = keyOf(key) as TokenKey<unknown>;\r\n if (!this.bindings.has(k)) {\r\n this.bindings.set(k, { lifetime, implementation: implementation as Type<unknown>, deps });\r\n }\r\n }\r\n\r\n /**\r\n * Resolves a dependency by token or class reference.\r\n */\r\n public resolve<T>(target: TokenKey<T> | ForwardReference<T>): T {\r\n if (target instanceof ForwardReference) {\r\n return this._resolveForwardRef(target);\r\n }\r\n\r\n const k = keyOf(target) as TokenKey<unknown>;\r\n\r\n if (this.singletons.has(k)) {\r\n return this.singletons.get(k) as T;\r\n }\r\n\r\n const binding = this.bindings.get(k);\r\n\r\n if (!binding) {\r\n const name = target instanceof Token\r\n ? target.description\r\n : (target as Type<unknown>).name\r\n ?? 'unknown';\r\n\r\n throw new Error(\r\n `[Noxus DI] No binding found for \"${name}\".\\n`\r\n + `Did you forget to declare it in @Injectable({ deps }) or in bootstrapApplication({ singletons })?`,\r\n );\r\n }\r\n\r\n switch (binding.lifetime) {\r\n case 'transient':\r\n return this._instantiate(binding) as T;\r\n\r\n case 'scope': {\r\n if (this.scoped.has(k)) return this.scoped.get(k) as T;\r\n const inst = this._instantiate(binding);\r\n this.scoped.set(k, inst);\r\n return inst as T;\r\n }\r\n\r\n case 'singleton': {\r\n if (this.singletons.has(k)) return this.singletons.get(k) as T;\r\n const inst = this._instantiate(binding);\r\n this.singletons.set(k, inst);\r\n if (binding.instance === undefined) {\r\n (binding as IBinding<unknown>).instance = inst as unknown;\r\n }\r\n return inst as T;\r\n }\r\n }\r\n }\r\n\r\n // -------------------------------------------------------------------------\r\n\r\n private _resolveForwardRef<T>(ref: ForwardReference<T>): T {\r\n let resolved: T | undefined;\r\n return new Proxy({} as object, {\r\n get: (_obj, prop, receiver) => {\r\n resolved ??= this.resolve(ref.forwardRefFn()) as T;\r\n const value = Reflect.get(resolved as object, prop, receiver);\r\n return typeof value === 'function' ? (value as Function).bind(resolved) : value;\r\n },\r\n set: (_obj, prop, value, receiver) => {\r\n resolved ??= this.resolve(ref.forwardRefFn()) as T;\r\n return Reflect.set(resolved as object, prop, value, receiver);\r\n },\r\n getPrototypeOf: () => {\r\n resolved ??= this.resolve(ref.forwardRefFn()) as T;\r\n return Object.getPrototypeOf(resolved);\r\n },\r\n }) as T;\r\n }\r\n\r\n private _instantiate<T>(binding: IBinding<T>): T {\r\n const resolvedDeps = binding.deps.map((dep) => this.resolve(dep));\r\n return new binding.implementation(...resolvedDeps) as T;\r\n }\r\n}\r\n\r\n/**\r\n * The global root injector. All singletons live here.\r\n */\r\nexport const RootInjector = new AppInjector('root');\r\n\r\n/**\r\n * Resets the root injector to a clean state.\r\n * **Intended for testing only** — clears all bindings, singletons, and scoped instances\r\n * so that each test can start from a fresh DI container without restarting the process.\r\n */\r\nexport function resetRootInjector(): void {\r\n RootInjector.bindings.clear();\r\n RootInjector.singletons.clear();\r\n RootInjector.scoped.clear();\r\n // Lazy import to avoid circular dependency (InjectorExplorer → app-injector → InjectorExplorer)\r\n const { InjectorExplorer } = require('./injector-explorer') as typeof import('./injector-explorer');\r\n InjectorExplorer.reset();\r\n}\r\n\r\n/**\r\n * Convenience function: resolve a token from the root injector.\r\n */\r\nexport function inject<T>(t: TokenKey<T> | ForwardReference<T>): T {\r\n return RootInjector.resolve(t);\r\n}\r\n","/**\r\n * @copyright 2025 NoxFly\r\n * @license MIT\r\n * @author NoxFly\r\n */\r\n\r\n\r\nimport { AtomicHttpMethod, HttpMethod } from '../decorators/method.decorator';\r\nimport { AppInjector, RootInjector } from '../DI/app-injector';\r\n\r\n/**\r\n * The Request class represents an HTTP request in the Noxus framework.\r\n * It encapsulates the request data, including the event, ID, method, path, and body.\r\n * It also provides a context for dependency injection through the AppInjector.\r\n */\r\nexport class Request {\r\n public readonly context: AppInjector = RootInjector.createScope();\r\n\r\n public readonly params: Record<string, string> = {};\r\n public readonly query: Record<string, unknown>;\r\n\r\n constructor(\r\n public readonly event: Electron.MessageEvent,\r\n public readonly senderId: number,\r\n public readonly id: string,\r\n public readonly method: HttpMethod,\r\n public readonly path: string,\r\n public readonly body: unknown,\r\n query?: Record<string, unknown>,\r\n ) {\r\n this.path = path.replace(/^\\/|\\/$/g, '');\r\n this.query = query ?? {};\r\n }\r\n}\r\n\r\n/**\r\n * The IRequest interface defines the structure of a request object.\r\n * It includes properties for the sender ID, request ID, path, method, and an optional body.\r\n * This interface is used to standardize the request data across the application.\r\n */\r\nexport interface IRequest<TBody = unknown> {\r\n senderId: number;\r\n requestId: string;\r\n path: string;\r\n method: HttpMethod;\r\n body?: TBody;\r\n query?: Record<string, unknown>;\r\n}\r\n\r\nexport interface IBatchRequestItem<TBody = unknown> {\r\n requestId?: string;\r\n path: string;\r\n method: AtomicHttpMethod;\r\n body?: TBody;\r\n query?: Record<string, unknown>;\r\n}\r\n\r\nexport interface IBatchRequestPayload {\r\n requests: IBatchRequestItem[];\r\n}\r\n\r\n/**\r\n * Creates a Request object from the IPC event data.\r\n * This function extracts the necessary information from the IPC event and constructs a Request instance.\r\n */\r\nexport interface IResponse<TBody = unknown> {\r\n requestId: string;\r\n status: number;\r\n body?: TBody;\r\n error?: string;\r\n stack?: string;\r\n}\r\n\r\nexport interface IBatchResponsePayload {\r\n responses: IResponse[];\r\n}\r\n\r\nexport const RENDERER_EVENT_TYPE = 'noxus:event';\r\n\r\nexport interface IRendererEventMessage<TPayload = unknown> {\r\n type: typeof RENDERER_EVENT_TYPE;\r\n event: string;\r\n payload?: TPayload;\r\n}\r\n\r\nexport function createRendererEventMessage<TPayload = unknown>(event: string, payload?: TPayload): IRendererEventMessage<TPayload> {\r\n return {\r\n type: RENDERER_EVENT_TYPE,\r\n event,\r\n payload,\r\n };\r\n}\r\n\r\nexport function isRendererEventMessage(value: unknown): value is IRendererEventMessage {\r\n if(value === null || typeof value !== 'object') {\r\n return false;\r\n }\r\n\r\n const possibleMessage = value as Partial<IRendererEventMessage>;\r\n\r\n return possibleMessage.type === RENDERER_EVENT_TYPE && typeof possibleMessage.event === 'string';\r\n}\r\n","/**\r\n * @copyright 2025 NoxFly\r\n * @license MIT\r\n * @author NoxFly\r\n */\r\n\r\n/**\r\n * Lightweight event registry to help renderer processes subscribe to\r\n * push messages sent by the main process through Noxus.\r\n */\r\nimport { IRendererEventMessage, isRendererEventMessage } from './request';\r\n\r\nexport type RendererEventHandler<TPayload = unknown> = (payload: TPayload) => void;\r\n\r\nexport interface RendererEventSubscription {\r\n unsubscribe(): void;\r\n}\r\n\r\nexport class RendererEventRegistry {\r\n private readonly listeners = new Map<string, Set<RendererEventHandler>>();\r\n\r\n /**\r\n *\r\n */\r\n public subscribe<TPayload>(eventName: string, handler: RendererEventHandler<TPayload>): RendererEventSubscription {\r\n const normalizedEventName = eventName.trim();\r\n\r\n if(normalizedEventName.length === 0) {\r\n throw new Error('Renderer event name must be a non-empty string.');\r\n }\r\n\r\n const handlers = this.listeners.get(normalizedEventName) ?? new Set<RendererEventHandler>();\r\n\r\n handlers.add(handler as RendererEventHandler);\r\n this.listeners.set(normalizedEventName, handlers);\r\n\r\n return {\r\n unsubscribe: () => this.unsubscribe(normalizedEventName, handler as RendererEventHandler),\r\n };\r\n }\r\n\r\n /**\r\n *\r\n */\r\n public unsubscribe<TPayload>(eventName: string, handler: RendererEventHandler<TPayload>): void {\r\n const handlers = this.listeners.get(eventName);\r\n\r\n if(!handlers) {\r\n return;\r\n }\r\n\r\n handlers.delete(handler as RendererEventHandler);\r\n\r\n if(handlers.size === 0) {\r\n this.listeners.delete(eventName);\r\n }\r\n }\r\n\r\n /**\r\n *\r\n */\r\n public clear(eventName?: string): void {\r\n if(eventName) {\r\n this.listeners.delete(eventName);\r\n return;\r\n }\r\n\r\n this.listeners.clear();\r\n }\r\n\r\n /**\r\n *\r\n */\r\n public dispatch<TPayload>(message: IRendererEventMessage<TPayload>): void {\r\n const handlers = this.listeners.get(message.event);\r\n\r\n if(!handlers || handlers.size === 0) {\r\n return;\r\n }\r\n\r\n handlers.forEach((handler) => {\r\n try {\r\n handler(message.payload as TPayload);\r\n }\r\n catch(error) {\r\n console.error(`[Noxus] Renderer event handler for \"${message.event}\" threw an error.`, error);\r\n }\r\n });\r\n }\r\n\r\n /**\r\n *\r\n */\r\n public tryDispatchFromMessageEvent(event: MessageEvent): boolean {\r\n if(!isRendererEventMessage(event.data)) {\r\n return false;\r\n }\r\n\r\n this.dispatch(event.data);\r\n return true;\r\n }\r\n\r\n /**\r\n *\r\n */\r\n public hasHandlers(eventName: string): boolean {\r\n const handlers = this.listeners.get(eventName);\r\n return !!handlers && handlers.size > 0;\r\n }\r\n}\r\n","/**\r\n * @copyright 2025 NoxFly\r\n * @license MIT\r\n * @author NoxFly\r\n */\r\n\r\nimport { IBatchRequestItem, IBatchResponsePayload, IRequest, IResponse } from './request';\r\nimport { RendererEventRegistry } from './renderer-events';\r\n\r\nexport interface IPortRequester {\r\n requestPort(): void;\r\n}\r\n\r\n/**\r\n * Per-request options that can override global client defaults.\r\n */\r\nexport interface RequestOptions {\r\n /**\r\n * Timeout in milliseconds for this specific request.\r\n * Overrides the global `requestTimeout` set on the client.\r\n * Set to 0 to disable timeout for this request.\r\n */\r\n timeout?: number;\r\n}\r\n\r\nexport interface RendererClientOptions {\r\n bridge?: IPortRequester | null;\r\n bridgeName?: string | string[];\r\n initMessageType?: string;\r\n windowRef?: Window;\r\n generateRequestId?: () => string;\r\n /**\r\n * Timeout in milliseconds for IPC requests.\r\n * If the main process does not respond within this duration,\r\n * the request Promise is rejected and the pending entry cleaned up.\r\n * Defaults to 10 000 ms. Set to 0 to disable.\r\n */\r\n requestTimeout?: number;\r\n /** @default true */\r\n enableLogging?: boolean;\r\n}\r\n\r\ninterface PendingRequest<T = unknown> {\r\n resolve: (value: T) => void;\r\n reject: (reason: IResponse<T>) => void;\r\n request: IRequest;\r\n submittedAt: number;\r\n timer?: ReturnType<typeof setTimeout>;\r\n}\r\n\r\nconst DEFAULT_INIT_EVENT = 'init-port';\r\nconst DEFAULT_BRIDGE_NAMES = ['noxus', 'ipcRenderer'];\r\n\r\nfunction defaultRequestId(): string {\r\n if(typeof crypto !== 'undefined' && typeof crypto.randomUUID === 'function') {\r\n return crypto.randomUUID();\r\n }\r\n\r\n return `${Date.now().toString(16)}-${Math.floor(Math.random() * 1e8).toString(16)}`;\r\n}\r\n\r\nfunction normalizeBridgeNames(preferred?: string | string[]): string[] {\r\n const names: string[] = [];\r\n\r\n const add = (name: string | undefined): void => {\r\n if(!name)\r\n return;\r\n\r\n if(!names.includes(name)) {\r\n names.push(name);\r\n }\r\n };\r\n\r\n if(Array.isArray(preferred)) {\r\n for(const name of preferred) {\r\n add(name);\r\n }\r\n }\r\n else {\r\n add(preferred);\r\n }\r\n\r\n for(const fallback of DEFAULT_BRIDGE_NAMES) {\r\n add(fallback);\r\n }\r\n\r\n return names;\r\n}\r\n\r\nfunction resolveBridgeFromWindow(windowRef: Window, preferred?: string | string[]): IPortRequester | null {\r\n const names = normalizeBridgeNames(preferred);\r\n const globalRef = windowRef as unknown as Record<string, unknown> | null | undefined;\r\n\r\n if(!globalRef) {\r\n return null;\r\n }\r\n\r\n for(const name of names) {\r\n const candidate = globalRef[name];\r\n\r\n if(candidate && typeof (candidate as IPortRequester).requestPort === 'function') {\r\n return candidate as IPortRequester;\r\n }\r\n }\r\n\r\n return null;\r\n}\r\n\r\nexport class NoxRendererClient {\r\n public readonly events = new RendererEventRegistry();\r\n\r\n protected readonly pendingRequests = new Map<string, PendingRequest>();\r\n\r\n protected requestPort: MessagePort | undefined;\r\n protected socketPort: MessagePort | undefined;\r\n protected senderId: number | undefined;\r\n\r\n private readonly bridge: IPortRequester | null;\r\n private readonly initMessageType: string;\r\n private readonly windowRef: Window;\r\n private readonly generateRequestId: () => string;\r\n private readonly requestTimeout: number;\r\n\r\n private isReady = false;\r\n private setupPromise: Promise<void> | undefined;\r\n private setupResolve: (() => void) | undefined;\r\n private setupReject: ((reason: Error) => void) | undefined;\r\n\r\n private enableLogging: boolean;\r\n\r\n constructor(options: RendererClientOptions = {}) {\r\n this.windowRef = options.windowRef ?? window;\r\n const resolvedBridge = options.bridge ?? resolveBridgeFromWindow(this.windowRef, options.bridgeName);\r\n this.bridge = resolvedBridge ?? null;\r\n this.initMessageType = options.initMessageType ?? DEFAULT_INIT_EVENT;\r\n this.generateRequestId = options.generateRequestId ?? defaultRequestId;\r\n this.requestTimeout = options.requestTimeout ?? 10_000;\r\n this.enableLogging = options.enableLogging ?? true;\r\n }\r\n\r\n public async setup(): Promise<void> {\r\n if(this.isReady) {\r\n return Promise.resolve();\r\n }\r\n\r\n if(this.setupPromise) {\r\n return this.setupPromise;\r\n }\r\n\r\n if(!this.bridge || typeof this.bridge.requestPort !== 'function') {\r\n throw new Error('[Noxus] Renderer bridge is missing requestPort().');\r\n }\r\n\r\n this.setupPromise = new Promise<void>((resolve, reject) => {\r\n this.setupResolve = resolve;\r\n this.setupReject = reject;\r\n });\r\n\r\n this.windowRef.addEventListener('message', this.onWindowMessage);\r\n this.bridge.requestPort();\r\n\r\n return this.setupPromise;\r\n }\r\n\r\n public dispose(): void {\r\n this.windowRef.removeEventListener('message', this.onWindowMessage);\r\n\r\n this.requestPort?.close();\r\n this.socketPort?.close();\r\n\r\n this.requestPort = undefined;\r\n this.socketPort = undefined;\r\n this.senderId = undefined;\r\n this.isReady = false;\r\n\r\n for(const pending of this.pendingRequests.values()) {\r\n if(pending.timer !== undefined) {\r\n clearTimeout(pending.timer);\r\n }\r\n }\r\n\r\n this.pendingRequests.clear();\r\n }\r\n\r\n public async request<TResponse, TBody = unknown>(\r\n request: Omit<IRequest<TBody>, 'requestId' | 'senderId'>,\r\n options?: RequestOptions,\r\n ): Promise<TResponse> {\r\n const senderId = this.senderId;\r\n const requestId = this.generateRequestId();\r\n\r\n if(senderId === undefined) {\r\n return Promise.reject(this.createErrorResponse(requestId, 'MessagePort is not available'));\r\n }\r\n\r\n const readinessError = this.validateReady(requestId);\r\n\r\n if(readinessError) {\r\n return Promise.reject(readinessError as IResponse<TResponse>);\r\n }\r\n\r\n const message: IRequest<TBody> = {\r\n requestId,\r\n senderId,\r\n ...request,\r\n };\r\n\r\n const effectiveTimeout = options?.timeout ?? this.requestTimeout;\r\n\r\n return new Promise<TResponse>((resolve, reject) => {\r\n const pending: PendingRequest<TResponse> = {\r\n resolve,\r\n reject: (response: IResponse<TResponse>) => reject(response),\r\n request: message,\r\n submittedAt: Date.now(),\r\n };\r\n\r\n if(effectiveTimeout > 0) {\r\n pending.timer = setTimeout(() => {\r\n this.pendingRequests.delete(message.requestId);\r\n reject(this.createErrorResponse<TResponse>(message.requestId, `Request timed out after ${effectiveTimeout}ms`) as IResponse<TResponse>);\r\n }, effectiveTimeout);\r\n }\r\n\r\n this.pendingRequests.set(message.requestId, pending as PendingRequest);\r\n\r\n this.requestPort!.postMessage(message);\r\n });\r\n }\r\n\r\n public async batch(requests: Omit<IBatchRequestItem<unknown>, 'requestId'>[]): Promise<IBatchResponsePayload> {\r\n return this.request<IBatchResponsePayload>({\r\n method: 'BATCH',\r\n path: '',\r\n body: {\r\n requests,\r\n },\r\n });\r\n }\r\n\r\n public getSenderId(): number | undefined {\r\n return this.senderId;\r\n }\r\n\r\n private readonly onWindowMessage = (event: MessageEvent): void => {\r\n if(event.data?.type !== this.initMessageType) {\r\n return;\r\n }\r\n\r\n if(!Array.isArray(event.ports) || event.ports.length < 2) {\r\n const error = new Error('[Noxus] Renderer expected two MessagePorts (request + socket).');\r\n\r\n console.error(error);\r\n this.setupReject?.(error);\r\n this.resetSetupState();\r\n return;\r\n }\r\n\r\n this.windowRef.removeEventListener('message', this.onWindowMessage);\r\n\r\n this.requestPort = event.ports[0];\r\n this.socketPort = event.ports[1];\r\n this.senderId = event.data.senderId;\r\n\r\n if(this.requestPort === undefined || this.socketPort === undefined) {\r\n const error = new Error('[Noxus] Renderer failed to receive valid MessagePorts.');\r\n console.error(error);\r\n this.setupReject?.(error);\r\n this.resetSetupState();\r\n return;\r\n }\r\n\r\n this.attachRequestPort(this.requestPort);\r\n this.attachSocketPort(this.socketPort);\r\n\r\n this.isReady = true;\r\n this.setupResolve?.();\r\n this.resetSetupState(true);\r\n };\r\n\r\n private readonly onSocketMessage = (event: MessageEvent): void => {\r\n if(this.events.tryDispatchFromMessageEvent(event)) {\r\n return;\r\n }\r\n\r\n console.warn('[Noxus] Received a socket message that is not a renderer event payload.', event.data);\r\n };\r\n\r\n private readonly onRequestMessage = (event: MessageEvent): void => {\r\n if(this.events.tryDispatchFromMessageEvent(event)) {\r\n return;\r\n }\r\n\r\n const response: IResponse = event.data;\r\n\r\n if(!response || typeof response.requestId !== 'string') {\r\n console.error('[Noxus] Renderer received an invalid response payload.', response);\r\n return;\r\n }\r\n\r\n const pending = this.pendingRequests.get(response.requestId);\r\n\r\n if(!pending) {\r\n console.error(`[Noxus] No pending handler found for request ${response.requestId}.`);\r\n return;\r\n }\r\n\r\n if(pending.timer !== undefined) {\r\n clearTimeout(pending.timer);\r\n }\r\n\r\n this.pendingRequests.delete(response.requestId);\r\n\r\n this.onRequestCompleted(pending, response);\r\n\r\n if(response.status >= 400) {\r\n pending.reject(response as IResponse<any>);\r\n return;\r\n }\r\n\r\n pending.resolve(response.body as unknown);\r\n };\r\n\r\n protected onRequestCompleted(pending: PendingRequest, response: IResponse): void {\r\n if(!this.enableLogging) {\r\n return;\r\n }\r\n\r\n if(typeof console.groupCollapsed === 'function') {\r\n console.groupCollapsed(`${response.status} ${pending.request.method} /${pending.request.path}`);\r\n }\r\n\r\n if(response.error) {\r\n console.error('error message:', response.error);\r\n }\r\n\r\n if(response.body !== undefined) {\r\n console.info('response:', response.body);\r\n }\r\n\r\n console.info('request:', pending.request);\r\n console.info(`Request duration: ${Date.now() - pending.submittedAt} ms`);\r\n\r\n if(typeof console.groupCollapsed === 'function') {\r\n console.groupEnd();\r\n }\r\n }\r\n\r\n private attachRequestPort(port: MessagePort): void {\r\n port.onmessage = this.onRequestMessage;\r\n port.start();\r\n }\r\n\r\n private attachSocketPort(port: MessagePort): void {\r\n port.onmessage = this.onSocketMessage;\r\n port.start();\r\n }\r\n\r\n private validateReady(requestId: string): IResponse | undefined {\r\n if(!this.isElectronEnvironment()) {\r\n return this.createErrorResponse(requestId, 'Not running in Electron environment');\r\n }\r\n\r\n if(!this.requestPort) {\r\n return this.createErrorResponse(requestId, 'MessagePort is not available');\r\n }\r\n\r\n return undefined;\r\n }\r\n\r\n private createErrorResponse<T>(requestId: string, message: string): IResponse<T> {\r\n return {\r\n status: 500,\r\n requestId,\r\n error: message,\r\n };\r\n }\r\n\r\n private resetSetupState(success = false): void {\r\n if(!success) {\r\n this.setupPromise = undefined;\r\n }\r\n\r\n this.setupResolve = undefined;\r\n this.setupReject = undefined;\r\n }\r\n\r\n public isElectronEnvironment(): boolean {\r\n return typeof window !== 'undefined' && /Electron/.test(window.navigator.userAgent);\r\n }\r\n}\r\n"],"mappings":"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","names":[]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@noxfly/noxus",
3
- "version": "3.0.0-dev.10",
3
+ "version": "3.0.0-dev.12",
4
4
  "author": "NoxFly",
5
5
  "license": "MIT",
6
6
  "description": "Lightweight HTTP-like IPC framework for Electron with standalone controllers, explicit DI, and lazy route loading. No reflect-metadata required.",