Files
openclaw/src/test-utils/tracked-temp-dirs.ts
2026-04-07 06:20:53 +01:00

70 lines
2.0 KiB
TypeScript

import fs from "node:fs/promises";
import os from "node:os";
import path from "node:path";
export function createTrackedTempDirs() {
const prefixRoots = new Map<string, { root: string; nextIndex: number }>();
const pendingPrefixRoots = new Map<string, Promise<{ root: string; nextIndex: number }>>();
const cleanupRoots = new Set<string>();
let globalDirIndex = 0;
const ensurePrefixRoot = async (prefix: string) => {
const cached = prefixRoots.get(prefix);
if (cached) {
return cached;
}
const pending = pendingPrefixRoots.get(prefix);
if (pending) {
return await pending;
}
const create = (async () => {
const root = await fs.mkdtemp(path.join(os.tmpdir(), prefix));
const state = { root, nextIndex: 0 };
prefixRoots.set(prefix, state);
cleanupRoots.add(root);
return state;
})();
pendingPrefixRoots.set(prefix, create);
try {
return await create;
} finally {
pendingPrefixRoots.delete(prefix);
}
};
return {
async make(prefix: string): Promise<string> {
const state = await ensurePrefixRoot(prefix);
const dir = path.join(state.root, `dir-${String(globalDirIndex)}`);
state.nextIndex += 1;
globalDirIndex += 1;
await fs.mkdir(dir, { recursive: true });
return dir;
},
async cleanup(): Promise<void> {
const roots = [...cleanupRoots];
pendingPrefixRoots.clear();
await Promise.all(
roots.map(async (dir) => {
const entries = await fs.readdir(dir).catch((err: unknown) => {
if ((err as NodeJS.ErrnoException).code === "ENOENT") {
return [];
}
throw err;
});
await Promise.all(
entries.map(async (entry) => {
await fs.rm(path.join(dir, entry), { recursive: true, force: true });
}),
);
for (const state of prefixRoots.values()) {
if (state.root === dir) {
state.nextIndex = 0;
}
}
}),
);
},
};
}