repositories / pi-ext
pi-ext
bugabingas pi extensions
owned by admin
extensions/gratis/src/state.ts
Rawimport { mkdir, readFile, rename, writeFile } from "node:fs/promises";
import { homedir } from "node:os";
import path from "node:path";
/**
* Where routing measurements persist across restarts. Same convention as the
* web extension: XDG_STATE_HOME wins, else the platform's user state dir.
*/
export function routingStatePath(
platform: NodeJS.Platform = process.platform,
env: NodeJS.ProcessEnv = process.env,
home = homedir(),
): string {
const paths = platform === "win32" ? path.win32 : path.posix;
const root = env.XDG_STATE_HOME
? paths.join(env.XDG_STATE_HOME, "pi")
: platform === "win32"
? paths.join(
env.LOCALAPPDATA ?? paths.join(home, "AppData", "Local"),
"pi",
)
: platform === "darwin"
? paths.join(home, "Library", "Application Support", "pi")
: paths.join(home, ".local", "state", "pi");
return paths.join(root, "gratis", "routing.json");
}
/** Missing, unreadable, or corrupt state is simply absent. */
export async function loadRoutingState(file: string): Promise<unknown> {
try {
return JSON.parse(await readFile(file, "utf8"));
} catch {
return undefined;
}
}
/** Owner-only, atomic: write a sibling temp file, then rename over the target. */
export async function saveRoutingState(
file: string,
state: unknown,
): Promise<void> {
await mkdir(path.dirname(file), { recursive: true, mode: 0o700 });
const temporary = `${file}.${process.pid}.tmp`;
await writeFile(temporary, JSON.stringify(state), { mode: 0o600 });
await rename(temporary, file);
}