@noxfly/noxus
Version:
Simulate lightweight HTTP-like requests between renderer and main process in Electron applications with MessagePort, with structured and modular design.
74 lines (58 loc) • 2.43 kB
text/typescript
/**
* @copyright 2025 NoxFly
* @license MIT
* @author NoxFly
*/
/**
* Centralizes MessagePort storage for renderer communication and handles
* push-event delivery back to renderer processes.
*/
import { Injectable } from 'src/decorators/injectable.decorator';
import { createRendererEventMessage } from 'src/request';
import { Logger } from 'src/utils/logger';
interface RendererChannels {
request: Electron.MessageChannelMain;
socket: Electron.MessageChannelMain;
}
('singleton')
export class NoxSocket {
private readonly channels = new Map<number, RendererChannels>();
public register(senderId: number, requestChannel: Electron.MessageChannelMain, socketChannel: Electron.MessageChannelMain): void {
this.channels.set(senderId, { request: requestChannel, socket: socketChannel });
}
public get(senderId: number): RendererChannels | undefined {
return this.channels.get(senderId);
}
public unregister(senderId: number): void {
this.channels.delete(senderId);
}
public getSenderIds(): number[] {
return [...this.channels.keys()];
}
public emit<TPayload = unknown>(eventName: string, payload?: TPayload, targetSenderIds?: number[]): number {
const normalizedEvent = eventName.trim();
if(normalizedEvent.length === 0) {
throw new Error('Renderer event name must be a non-empty string.');
}
const recipients = targetSenderIds ?? this.getSenderIds();
let delivered = 0;
for(const senderId of recipients) {
const channel = this.channels.get(senderId);
if(!channel) {
Logger.warn(`No message channel found for sender ID: ${senderId} while emitting "${normalizedEvent}".`);
continue;
}
try {
channel.socket.port1.postMessage(createRendererEventMessage(normalizedEvent, payload));
delivered++;
}
catch(error) {
Logger.error(`[Noxus] Failed to emit "${normalizedEvent}" to sender ${senderId}.`, error);
}
}
return delivered;
}
public emitToRenderer<TPayload = unknown>(senderId: number, eventName: string, payload?: TPayload): boolean {
return this.emit(eventName, payload, [senderId]) > 0;
}
}