mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-08 05:41:24 +00:00
71 lines
1.8 KiB
TypeScript
71 lines
1.8 KiB
TypeScript
import { randomUUID } from "node:crypto";
|
|
import fs from "node:fs/promises";
|
|
import path from "node:path";
|
|
import { resolveStateDir } from "../config/paths.js";
|
|
|
|
export function resolvePairingPaths(baseDir: string | undefined, subdir: string) {
|
|
const root = baseDir ?? resolveStateDir();
|
|
const dir = path.join(root, subdir);
|
|
return {
|
|
dir,
|
|
pendingPath: path.join(dir, "pending.json"),
|
|
pairedPath: path.join(dir, "paired.json"),
|
|
};
|
|
}
|
|
|
|
export async function readJsonFile<T>(filePath: string): Promise<T | null> {
|
|
try {
|
|
const raw = await fs.readFile(filePath, "utf8");
|
|
return JSON.parse(raw) as T;
|
|
} catch {
|
|
return null;
|
|
}
|
|
}
|
|
|
|
export async function writeJsonAtomic(filePath: string, value: unknown) {
|
|
const dir = path.dirname(filePath);
|
|
await fs.mkdir(dir, { recursive: true });
|
|
const tmp = `${filePath}.${randomUUID()}.tmp`;
|
|
await fs.writeFile(tmp, JSON.stringify(value, null, 2), "utf8");
|
|
try {
|
|
await fs.chmod(tmp, 0o600);
|
|
} catch {
|
|
// best-effort; ignore on platforms without chmod
|
|
}
|
|
await fs.rename(tmp, filePath);
|
|
try {
|
|
await fs.chmod(filePath, 0o600);
|
|
} catch {
|
|
// best-effort; ignore on platforms without chmod
|
|
}
|
|
}
|
|
|
|
export function pruneExpiredPending<T extends { ts: number }>(
|
|
pendingById: Record<string, T>,
|
|
nowMs: number,
|
|
ttlMs: number,
|
|
) {
|
|
for (const [id, req] of Object.entries(pendingById)) {
|
|
if (nowMs - req.ts > ttlMs) {
|
|
delete pendingById[id];
|
|
}
|
|
}
|
|
}
|
|
|
|
export function createAsyncLock() {
|
|
let lock: Promise<void> = Promise.resolve();
|
|
return async function withLock<T>(fn: () => Promise<T>): Promise<T> {
|
|
const prev = lock;
|
|
let release: (() => void) | undefined;
|
|
lock = new Promise<void>((resolve) => {
|
|
release = resolve;
|
|
});
|
|
await prev;
|
|
try {
|
|
return await fn();
|
|
} finally {
|
|
release?.();
|
|
}
|
|
};
|
|
}
|