UNPKG

@nodedaemon/core

Version:

Production-ready Node.js process manager with zero external dependencies

173 lines 5.9 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.IPCClient = void 0; const net_1 = require("net"); const helpers_1 = require("../utils/helpers"); const constants_1 = require("../utils/constants"); class IPCClient { socket = null; pendingRequests = new Map(); connected = false; connectionTimeout = 5000; requestTimeout = 30000; async connect() { if (this.connected) { return; } return new Promise((resolve, reject) => { this.socket = new net_1.Socket(); const connectionTimer = setTimeout(() => { this.socket?.destroy(); reject(new Error('Connection timeout')); }, this.connectionTimeout); this.socket.connect(constants_1.IPC_SOCKET_PATH, () => { clearTimeout(connectionTimer); this.connected = true; this.setupSocketHandlers(); resolve(); }); this.socket.on('error', (error) => { clearTimeout(connectionTimer); if (error.message.includes('ENOENT') || error.message.includes('ECONNREFUSED')) { reject(new Error('NodeDaemon is not running. Start it with: nodedaemon daemon')); } else { reject(new Error(`Connection failed: ${error.message}`)); } }); }); } setupSocketHandlers() { if (!this.socket) return; let buffer = ''; this.socket.on('data', (data) => { buffer += data.toString(); // Process complete JSON messages (separated by newlines) const messages = buffer.split('\n'); buffer = messages.pop() || ''; // Keep incomplete message in buffer messages.forEach(messageStr => { if (messageStr.trim()) { try { const response = JSON.parse(messageStr); this.handleResponse(response); } catch (error) { console.error('Failed to parse response:', error); } } }); }); this.socket.on('error', (error) => { console.error('Socket error:', error.message); this.handleDisconnection(); }); this.socket.on('close', () => { this.handleDisconnection(); }); this.socket.on('end', () => { this.handleDisconnection(); }); } handleResponse(response) { const request = this.pendingRequests.get(response.id); if (request) { clearTimeout(request.timeout); this.pendingRequests.delete(response.id); if (response.success) { request.resolve(response); } else { const error = response.data?.error || 'Unknown error'; request.reject(new Error(error)); } } } handleDisconnection() { this.connected = false; this.socket = null; // Reject all pending requests this.pendingRequests.forEach((request) => { clearTimeout(request.timeout); request.reject(new Error('Connection lost')); }); this.pendingRequests.clear(); } async sendMessage(type, data) { if (!this.connected || !this.socket) { await this.connect(); } return new Promise((resolve, reject) => { const id = (0, helpers_1.generateId)(); const message = { id, type, data, timestamp: Date.now() }; const timeout = setTimeout(() => { this.pendingRequests.delete(id); reject(new Error(`Request timeout for ${type}`)); }, this.requestTimeout); this.pendingRequests.set(id, { resolve: (response) => resolve(response.data), reject, timeout }); const messageData = JSON.stringify(message) + '\n'; this.socket.write(messageData, (error) => { if (error) { clearTimeout(timeout); this.pendingRequests.delete(id); reject(new Error(`Failed to send message: ${error.message}`)); } }); }); } async ping() { return this.sendMessage('ping'); } async start(config) { return this.sendMessage('start', config); } async stop(options) { return this.sendMessage('stop', options); } async restart(options) { return this.sendMessage('restart', options); } async list() { return this.sendMessage('list'); } async status(options) { return this.sendMessage('status', options); } async logs(options) { return this.sendMessage('logs', options); } async shutdown() { return this.sendMessage('shutdown'); } disconnect() { if (this.socket) { this.socket.end(); this.socket = null; } this.connected = false; // Clear pending requests this.pendingRequests.forEach((request) => { clearTimeout(request.timeout); request.reject(new Error('Client disconnected')); }); this.pendingRequests.clear(); } isConnected() { return this.connected; } setTimeout(connectionTimeout, requestTimeout) { this.connectionTimeout = Math.max(1000, connectionTimeout); this.requestTimeout = Math.max(5000, requestTimeout); } } exports.IPCClient = IPCClient; //# sourceMappingURL=IPCClient.js.map