2025-08-24 16:39:09 +00:00
|
|
|
export * from './classes.transports.js';
|
|
|
|
export * from './classes.ipcchannel.js';
|
|
|
|
export * from './classes.ipcserver.js';
|
|
|
|
export * from './classes.ipcclient.js';
|
|
|
|
|
|
|
|
import { IpcServer } from './classes.ipcserver.js';
|
|
|
|
import { IpcClient } from './classes.ipcclient.js';
|
|
|
|
import { IpcChannel } from './classes.ipcchannel.js';
|
|
|
|
import type { IIpcServerOptions } from './classes.ipcserver.js';
|
2025-08-25 13:37:31 +00:00
|
|
|
import type { IIpcClientOptions, IConnectRetryConfig } from './classes.ipcclient.js';
|
2025-08-24 16:39:09 +00:00
|
|
|
import type { IIpcChannelOptions } from './classes.ipcchannel.js';
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Main SmartIpc class - Factory for creating IPC servers, clients, and channels
|
|
|
|
*/
|
2019-04-08 19:42:23 +02:00
|
|
|
export class SmartIpc {
|
|
|
|
/**
|
2025-08-24 16:39:09 +00:00
|
|
|
* Create an IPC server
|
2019-04-08 19:42:23 +02:00
|
|
|
*/
|
2025-08-25 13:37:31 +00:00
|
|
|
/**
|
|
|
|
* Wait for a server to become ready at the given socket path
|
|
|
|
*/
|
|
|
|
public static async waitForServer(options: {
|
|
|
|
socketPath: string;
|
|
|
|
timeoutMs?: number;
|
|
|
|
}): Promise<void> {
|
|
|
|
const timeout = options.timeoutMs || 10000;
|
|
|
|
const startTime = Date.now();
|
|
|
|
|
|
|
|
while (Date.now() - startTime < timeout) {
|
|
|
|
try {
|
2025-08-26 12:32:28 +00:00
|
|
|
// Create a temporary client with proper options
|
|
|
|
const testClient = SmartIpc.createClient({
|
|
|
|
id: 'test-probe',
|
2025-08-25 13:37:31 +00:00
|
|
|
socketPath: options.socketPath,
|
2025-08-26 12:32:28 +00:00
|
|
|
clientId: `probe-${process.pid}-${Date.now()}`,
|
|
|
|
heartbeat: false,
|
2025-08-29 08:48:38 +00:00
|
|
|
clientOnly: true,
|
2025-08-26 12:32:28 +00:00
|
|
|
connectRetry: {
|
|
|
|
enabled: false // Don't retry, we're handling retries here
|
|
|
|
},
|
|
|
|
registerTimeoutMs: 2000 // Short timeout for quick probing
|
2025-08-25 13:37:31 +00:00
|
|
|
});
|
|
|
|
|
2025-08-26 12:32:28 +00:00
|
|
|
// Try to connect and register with the server
|
2025-08-25 13:37:31 +00:00
|
|
|
await testClient.connect();
|
2025-08-26 12:32:28 +00:00
|
|
|
|
|
|
|
// Success! Clean up and return
|
2025-08-25 13:37:31 +00:00
|
|
|
await testClient.disconnect();
|
2025-08-26 12:32:28 +00:00
|
|
|
return;
|
2025-08-25 13:37:31 +00:00
|
|
|
} catch (error) {
|
|
|
|
// Server not ready yet, wait and retry
|
2025-08-26 12:32:28 +00:00
|
|
|
await new Promise(resolve => setTimeout(resolve, 200));
|
2025-08-25 13:37:31 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
throw new Error(`Server not ready at ${options.socketPath} after ${timeout}ms`);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Helper to spawn a server process and connect a client
|
|
|
|
*/
|
|
|
|
public static async spawnAndConnect(options: {
|
|
|
|
serverScript: string;
|
|
|
|
socketPath: string;
|
|
|
|
clientId?: string;
|
|
|
|
spawnOptions?: any;
|
|
|
|
connectRetry?: IConnectRetryConfig;
|
|
|
|
timeoutMs?: number;
|
|
|
|
}): Promise<{
|
|
|
|
client: IpcClient;
|
|
|
|
serverProcess: any;
|
|
|
|
}> {
|
|
|
|
const { spawn } = await import('child_process');
|
|
|
|
|
|
|
|
// Spawn the server process
|
|
|
|
const serverProcess = spawn('node', [options.serverScript], {
|
|
|
|
detached: true,
|
|
|
|
stdio: 'pipe',
|
|
|
|
...options.spawnOptions
|
|
|
|
});
|
|
|
|
|
|
|
|
// Handle server process errors
|
|
|
|
serverProcess.on('error', (error: Error) => {
|
|
|
|
console.error('Server process error:', error);
|
|
|
|
});
|
|
|
|
|
|
|
|
// Wait for server to be ready
|
|
|
|
await SmartIpc.waitForServer({
|
|
|
|
socketPath: options.socketPath,
|
|
|
|
timeoutMs: options.timeoutMs || 10000
|
|
|
|
});
|
|
|
|
|
|
|
|
// Create and connect client
|
|
|
|
const client = new IpcClient({
|
|
|
|
id: options.clientId || 'test-client',
|
|
|
|
socketPath: options.socketPath,
|
|
|
|
connectRetry: options.connectRetry || {
|
|
|
|
enabled: true,
|
|
|
|
maxAttempts: 10,
|
|
|
|
initialDelay: 100,
|
|
|
|
maxDelay: 1000
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
await client.connect({ waitForReady: true });
|
|
|
|
|
|
|
|
return { client, serverProcess };
|
|
|
|
}
|
|
|
|
|
2025-08-24 16:39:09 +00:00
|
|
|
public static createServer(options: IIpcServerOptions): IpcServer {
|
|
|
|
return new IpcServer(options);
|
2019-04-08 19:42:23 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2025-08-24 16:39:09 +00:00
|
|
|
* Create an IPC client
|
2019-04-08 19:42:23 +02:00
|
|
|
*/
|
2025-08-24 16:39:09 +00:00
|
|
|
public static createClient(options: IIpcClientOptions): IpcClient {
|
|
|
|
return new IpcClient(options);
|
2019-04-08 19:42:23 +02:00
|
|
|
}
|
2019-04-08 19:56:21 +02:00
|
|
|
|
2019-04-09 12:30:12 +02:00
|
|
|
/**
|
2025-08-24 16:39:09 +00:00
|
|
|
* Create a raw IPC channel (for advanced use cases)
|
2019-04-09 12:30:12 +02:00
|
|
|
*/
|
2025-08-24 16:39:09 +00:00
|
|
|
public static createChannel(options: IIpcChannelOptions): IpcChannel {
|
|
|
|
return new IpcChannel(options);
|
2019-04-08 19:56:21 +02:00
|
|
|
}
|
2019-04-08 19:42:23 +02:00
|
|
|
}
|
2025-08-24 16:39:09 +00:00
|
|
|
|
|
|
|
// Export the main class as default
|
2025-08-29 08:48:38 +00:00
|
|
|
export default SmartIpc;
|