Something went wrong. Try again.
A fully featured CLI used as an alternative to AppView applications (Bsky.app/mu.social)
Something went wrong. Try again.
12345678910111213141516171819202122232425262728293031323334353637383940414243444546import * as FS from 'node:fs';import * as PATH from 'node:path';import { configDir } from './config.ts';
// What atcli remembers between runs that is neither a setting nor a secret:// where a watch got to (--resume), and the newest item seen in each listing// (--new). One small JSON file beside the config, keyed by account and by// what was listed; it is safe to delete, which only forgets.
function stateFile(): string { return PATH.join(configDir(), 'state.json');}
function readAll(): Record<string, string> { try { return JSON.parse(FS.readFileSync(stateFile(), 'utf-8')) as Record<string, string>; } catch { return {}; }}
export function readState(key: string): string | undefined { return readAll()[key];}
export function writeState(key: string, value: string): void { const state = readAll(); if (state[key] === value) return; state[key] = value; FS.mkdirSync(PATH.dirname(stateFile()), { recursive: true, mode: 0o700 }); const temp = `${stateFile()}.${process.pid}.tmp`; FS.writeFileSync(temp, `${JSON.stringify(state, null, 2)}\n`, { mode: 0o600 }); FS.renameSync(temp, stateFile());}
/** Forget what is remembered for keys starting with `prefix`; all of it without one. Returns how many. */export function clearState(prefix = ''): number { const state = readAll(); const gone = Object.keys(state).filter((key) => key.startsWith(prefix)); if (!gone.length) return 0; for (const key of gone) delete state[key]; FS.mkdirSync(PATH.dirname(stateFile()), { recursive: true, mode: 0o700 }); FS.writeFileSync(stateFile(), `${JSON.stringify(state, null, 2)}\n`, { mode: 0o600 }); return gone.length;}