36 lines
1.5 KiB
JavaScript
36 lines
1.5 KiB
JavaScript
import net from 'node:net';
|
|
import fs from 'node:fs';
|
|
import path from 'node:path';
|
|
import { mkdir, rm } from 'node:fs/promises';
|
|
|
|
const MAX_LINE = 64 * 1024;
|
|
|
|
export async function createEventSocket({ socketPath, onMessage }) {
|
|
await mkdir(path.dirname(socketPath), { recursive: true });
|
|
try { await rm(socketPath, { force: true }); } catch {}
|
|
const server = net.createServer((socket) => {
|
|
let buffer = '';
|
|
socket.setEncoding('utf8');
|
|
socket.on('data', (chunk) => {
|
|
buffer += chunk;
|
|
if (buffer.length > MAX_LINE * 2) { socket.destroy(new Error('IPC buffer too large')); return; }
|
|
let index;
|
|
while ((index = buffer.indexOf('\n')) >= 0) {
|
|
const line = buffer.slice(0, index); buffer = buffer.slice(index + 1);
|
|
if (line.length > MAX_LINE) { socket.destroy(new Error('IPC message too large')); return; }
|
|
try { onMessage?.(JSON.parse(line), socket); } catch { socket.write(JSON.stringify({ error: 'invalid IPC message' }) + '\n'); }
|
|
}
|
|
});
|
|
});
|
|
await new Promise((resolve, reject) => { server.once('error', reject); server.listen(socketPath, resolve); });
|
|
return { server, socketPath, close: () => new Promise((resolve) => server.close(() => fs.unlink(socketPath, () => resolve()))) };
|
|
}
|
|
|
|
export function sendEvent(socket, event, payload = {}) {
|
|
const message = JSON.stringify({ event, ...payload });
|
|
if (Buffer.byteLength(message) > MAX_LINE) throw new Error('IPC event too large; use a file path for bulk data');
|
|
socket.write(`${message}\n`);
|
|
}
|
|
|
|
export { MAX_LINE };
|