// Destructive hub changes ask the operator first. The web asks in the page; // the CLI asks in the terminal, or accepts --yes. export interface ConfirmPrompt { readonly isTTY?: boolean; readonly ask?: (question: string) => Promise; } const terminalQuestion = async (question: string): Promise => { const { createInterface } = await import("node:readline/promises"); const prompt = createInterface({ input: process.stdin, output: process.stdout }); try { return await prompt.question(question); } finally { prompt.close(); } }; /** * Ask one yes/no question. --yes answers it. Without a terminal, this throws * instead of running the change. */ export const confirmed = async ( question: string, yes: boolean, nonInteractiveError: string, prompt: ConfirmPrompt = {}, ): Promise => { if (yes) return true; const isTTY = prompt.isTTY ?? Boolean(process.stdin.isTTY && process.stdout.isTTY); if (!isTTY) throw new Error(nonInteractiveError); const answer = (await (prompt.ask ?? terminalQuestion)(`${question} [y/N] `)) .trim() .toLowerCase(); return answer === "y" || answer === "yes"; };