61 lines
1.6 KiB
TypeScript
61 lines
1.6 KiB
TypeScript
/**
|
|
* IPC server — binds a Unix socket and accepts incoming client connections.
|
|
* Mirrors `apps/infrastructure/src/ipc/server.rs`.
|
|
*/
|
|
import * as net from "node:net";
|
|
import * as fs from "node:fs";
|
|
import { Connection } from "./conn.ts";
|
|
|
|
/** A Unix-socket IPC server. */
|
|
export class IpcServer {
|
|
private server: net.Server;
|
|
private path: string;
|
|
|
|
private constructor(path: string, server: net.Server) {
|
|
this.path = path;
|
|
this.server = server;
|
|
}
|
|
|
|
/** Bind a Unix-socket server at `path`, removing any stale socket file. */
|
|
static bindUnix(path: string): Promise<IpcServer> {
|
|
return new Promise((resolve, reject) => {
|
|
if (fs.existsSync(path)) {
|
|
fs.unlinkSync(path);
|
|
}
|
|
const server = net.createServer();
|
|
server.once("error", reject);
|
|
server.listen(path, () => {
|
|
resolve(new IpcServer(path, server));
|
|
});
|
|
});
|
|
}
|
|
|
|
/** Accept the next incoming connection as a `Connection`. */
|
|
accept(): Promise<Connection> {
|
|
return new Promise((resolve) => {
|
|
const onConnection = (socket: net.Socket) => {
|
|
serverCleanup();
|
|
resolve(new Connection(socket));
|
|
};
|
|
const serverCleanup = () => {
|
|
this.server.removeListener("connection", onConnection);
|
|
};
|
|
this.server.once("connection", onConnection);
|
|
});
|
|
}
|
|
|
|
/** Close the server and remove the socket file. */
|
|
close(): Promise<void> {
|
|
return new Promise((resolve) => {
|
|
this.server.close(() => {
|
|
try {
|
|
fs.unlinkSync(this.path);
|
|
} catch {
|
|
/* ignore */
|
|
}
|
|
resolve();
|
|
});
|
|
});
|
|
}
|
|
}
|