SPB Git

Repository Public MIT

io.ts 1.8 KB 55 lines typescript

1import { createInterface } from "node:readline";2import { homedir } from "node:os";34/** Everything the CLI touches from the outside world, injectable so tests can run it in-process. */5export interface IO {6  stdout: (s: string) => void;7  stderr: (s: string) => void;8  /** Read all of stdin (used for --token-stdin and piped input). */9  stdin: () => Promise<string>;10  isTTY: boolean;11  prompt: (question: string, opts?: { hidden?: boolean }) => Promise<string>;12  env: Record<string, string | undefined>;13  cwd: string;14  home: string;15  platform: NodeJS.Platform;16  fetch?: typeof fetch;17}1819function ttyPrompt(question: string, hidden: boolean): Promise<string> {20  return new Promise((resolve) => {21    const rl = createInterface({ input: process.stdin, output: process.stderr, terminal: true });22    if (hidden) {23      // Print the question once, then swallow every echo of typed characters.24      (rl as unknown as { _writeToOutput: (s: string) => void })._writeToOutput = (s: string) => {25        if (s.includes(question)) process.stderr.write(question);26      };27    }28    rl.question(question, (answer) => {29      rl.close();30      if (hidden) process.stderr.write("\n");31      resolve(answer);32    });33  });34}3536async function readAllStdin(): Promise<string> {37  const chunks: Buffer[] = [];38  for await (const c of process.stdin) chunks.push(Buffer.from(c as Buffer));39  return Buffer.concat(chunks).toString("utf8");40}4142export function defaultIO(): IO {43  return {44    stdout: (s) => void process.stdout.write(s),45    stderr: (s) => void process.stderr.write(s),46    stdin: readAllStdin,47    isTTY: !!process.stdin.isTTY && !!process.stderr.isTTY,48    prompt: (q, o) => ttyPrompt(q, !!o?.hidden),49    env: process.env,50    cwd: process.cwd(),51    home: homedir(),52    platform: process.platform,53  };54}55
Files main
Menu

Theme