You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

69 lines
1.7 KiB

import fs from "node:fs";
import readline from "node:readline";
import { stdin as input, stdout as output } from "node:process";
const POLL_MS = 400;
function sleep(ms: number): Promise<void> {
return new Promise((resolve) => setTimeout(resolve, ms));
}
function consumeTrigger(triggerPath: string): void {
if (fs.existsSync(triggerPath)) {
fs.rmSync(triggerPath, { force: true });
}
}
async function waitForTriggerFile(
triggerPath: string,
label: string,
): Promise<void> {
consumeTrigger(triggerPath);
const rel = triggerPath.replace(/\\/g, "/");
console.log(`
[录证] ${label} — 文件触发
PowerShell: New-Item -ItemType File -Force -Path "${rel}"
或 CMD: type nul > "${rel}"
`);
while (!fs.existsSync(triggerPath)) {
await sleep(POLL_MS);
}
consumeTrigger(triggerPath);
console.log(`[录证] ${label} 已触发`);
}
export async function waitForHumanCheckpoint(options: {
label: string;
message: string;
triggerPath: string;
rl?: readline.Interface | null;
}): Promise<void> {
const useFileTrigger =
process.env.HUMAN_RECORD_FILE_TRIGGER === "1" || !process.stdin.isTTY;
console.log(`\n[录证] ── ${options.label} ──`);
console.log(options.message);
if (useFileTrigger) {
await waitForTriggerFile(options.triggerPath, options.label);
return;
}
const rl =
options.rl ??
readline.createInterface({ input, output, terminal: true });
await new Promise<void>((resolve) => {
rl.question("\n操作完成后按 Enter 继续… ", () => resolve());
});
if (!options.rl) {
rl.close();
}
}
export function createSharedReadline(): readline.Interface {
return readline.createInterface({ input, output, terminal: true });
}