Files
openclaw/scripts/e2e/lib/temp-state-dir.ts
2026-06-02 01:30:10 +02:00

60 lines
1.7 KiB
TypeScript

import { rmSync } from "node:fs";
import fs from "node:fs/promises";
import os from "node:os";
import path from "node:path";
const cleanupSignals = ["SIGINT", "SIGTERM", "SIGHUP"] as const;
type CleanupSignal = (typeof cleanupSignals)[number];
export type E2eStateDir = {
stateDir: string;
created: boolean;
cleanup: () => void;
registerExitCleanup: () => void;
};
export async function createE2eStateDir(prefix: string, env = process.env): Promise<E2eStateDir> {
const configuredStateDir = env.OPENCLAW_STATE_DIR?.trim();
const created = !configuredStateDir;
const stateDir = configuredStateDir || (await fs.mkdtemp(path.join(os.tmpdir(), prefix)));
const signalHandlers = new Map<CleanupSignal, () => void>();
let cleaned = false;
let cleanupRegistered = false;
const cleanup = () => {
if (created && !cleaned) {
cleaned = true;
rmSync(stateDir, { force: true, recursive: true });
}
};
const unregisterSignalCleanup = () => {
for (const [signal, handler] of signalHandlers) {
process.removeListener(signal, handler);
}
signalHandlers.clear();
};
const registerExitCleanup = () => {
if (!created || cleanupRegistered) {
return;
}
cleanupRegistered = true;
process.once("exit", cleanup);
for (const signal of cleanupSignals) {
const handleSignal = () => {
cleanup();
unregisterSignalCleanup();
if (process.listenerCount(signal) === 0) {
process.kill(process.pid, signal);
}
};
signalHandlers.set(signal, handleSignal);
process.once(signal, handleSignal);
}
};
return { stateDir, created, cleanup, registerExitCleanup };
}