/// import { EventEmitter } from "events"; import * as pty from "node-pty"; import { ServerProxy } from "../../common/proxy"; import { preserveEnv } from "../../common/util"; // tslint:disable completed-docs /** * Server-side IPty proxy. */ export class NodePtyProcessProxy implements ServerProxy { private readonly emitter = new EventEmitter(); public constructor(private readonly process: pty.IPty) { let name = process.process; setTimeout(() => { // Need to wait for the caller to listen to the event. this.emitter.emit("process", name); }, 1); const timer = setInterval(() => { if (process.process !== name) { name = process.process; this.emitter.emit("process", name); } }, 200); this.process.on("exit", () => clearInterval(timer)); } public async getPid(): Promise { return this.process.pid; } public async getProcess(): Promise { return this.process.process; } public async kill(signal?: string): Promise { this.process.kill(signal); } public async resize(columns: number, rows: number): Promise { this.process.resize(columns, rows); } public async write(data: string): Promise { this.process.write(data); } public async onDone(cb: () => void): Promise { this.process.on("exit", cb); } public async dispose(): Promise { this.process.kill(); setTimeout(() => this.process.kill("SIGKILL"), 5000); // Double tap. this.emitter.removeAllListeners(); } // tslint:disable-next-line no-any public async onEvent(cb: (event: string, ...args: any[]) => void): Promise { this.emitter.on("process", (process) => cb("process", process)); this.process.on("data", (data) => cb("data", data)); this.process.on("exit", (exitCode, signal) => cb("exit", exitCode, signal)); } } /** * Server-side node-pty proxy. */ export class NodePtyModuleProxy { public async spawn(file: string, args: string[] | string, options: pty.IPtyForkOptions): Promise { preserveEnv(options); return new NodePtyProcessProxy(require("node-pty").spawn(file, args, options)); } }