import * as fs from "fs"; import * as os from "os"; import * as path from "path"; import * as rimraf from "rimraf"; import * as util from "util"; import { IDisposable } from "@coder/disposable"; import { Emitter } from "@coder/events"; import { Client } from "../src/browser/client"; import { Server, ServerOptions } from "../src/node/server"; // So we only make the directory once when running multiple tests. let mkdirPromise: Promise | undefined; export class Helper { private i = 0; public coderDir: string; private baseDir = path.join(os.tmpdir(), "coder"); public constructor(directoryName: string) { if (!directoryName.trim()) { throw new Error("no directory name"); } this.coderDir = path.join(this.baseDir, directoryName); } public tmpFile(): string { return path.join(this.coderDir, `${this.i++}`); } public async createTmpFile(): Promise { const tf = this.tmpFile(); await util.promisify(fs.writeFile)(tf, ""); return tf; } public async prepare(): Promise { if (!mkdirPromise) { mkdirPromise = util.promisify(fs.mkdir)(this.baseDir).catch((error) => { if (error.code !== "EEXIST" && error.code !== "EISDIR") { throw error; } }); } await mkdirPromise; await util.promisify(rimraf)(this.coderDir); await util.promisify(fs.mkdir)(this.coderDir); } } export const createClient = (serverOptions?: ServerOptions): Client => { const s2c = new Emitter(); const c2s = new Emitter(); const closeCallbacks = void>>[]; // tslint:disable-next-line no-unused-expression new Server({ close: (): void => closeCallbacks.forEach((cb) => cb()), onDown: (_cb: () => void): void => undefined, onUp: (_cb: () => void): void => undefined, onClose: (cb: () => void): number => closeCallbacks.push(cb), onMessage: (cb): IDisposable => c2s.event((d) => cb(d)), send: (data): NodeJS.Timer => setTimeout(() => s2c.emit(data), 0), }, serverOptions); const client = new Client({ close: (): void => closeCallbacks.forEach((cb) => cb()), onDown: (_cb: () => void): void => undefined, onUp: (_cb: () => void): void => undefined, onClose: (cb: () => void): number => closeCallbacks.push(cb), onMessage: (cb): IDisposable => s2c.event((d) => cb(d)), send: (data): NodeJS.Timer => setTimeout(() => c2s.emit(data), 0), }); return client; };