fix: finalize durable Pi lifecycle
This commit is contained in:
@@ -22,6 +22,11 @@ export interface SettingsDurability {
|
||||
syncDirectory(directory: string): void;
|
||||
}
|
||||
|
||||
export interface SettingsSnapshot {
|
||||
exists: boolean;
|
||||
rawBase64: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Settings files are installation defaults only. Personal workspace/model/thinking choices
|
||||
* belong to the browser and must never be written back here by request handlers.
|
||||
@@ -39,6 +44,45 @@ export function loadSettings(cfg: AppConfig): Settings {
|
||||
}
|
||||
}
|
||||
|
||||
/** Capture exact file existence and bytes so host-side configuration can compensate losslessly. */
|
||||
export function captureSettingsSnapshot(cfg: AppConfig): SettingsSnapshot {
|
||||
try {
|
||||
return { exists: true, rawBase64: readFileSync(cfg.settingsFile).toString("base64") };
|
||||
} catch (error) {
|
||||
if ((error as NodeJS.ErrnoException).code === "ENOENT") {
|
||||
return { exists: false, rawBase64: "" };
|
||||
}
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
/** Restore a previously captured settings file exactly, including the clean absent state. */
|
||||
export function restoreSettingsSnapshot(
|
||||
cfg: AppConfig,
|
||||
snapshot: SettingsSnapshot,
|
||||
durability: SettingsDurability = defaultDurability,
|
||||
): void {
|
||||
if (typeof snapshot.exists !== "boolean" || typeof snapshot.rawBase64 !== "string") {
|
||||
throw new Error("invalid settings snapshot");
|
||||
}
|
||||
const raw = Buffer.from(snapshot.rawBase64, "base64");
|
||||
if (raw.toString("base64") !== snapshot.rawBase64 || (!snapshot.exists && raw.length !== 0)) {
|
||||
throw new Error("invalid settings snapshot");
|
||||
}
|
||||
const directory = dirname(cfg.settingsFile);
|
||||
mkdirSync(directory, { recursive: true });
|
||||
if (snapshot.exists) {
|
||||
replaceSettingsFile(cfg.settingsFile, raw);
|
||||
} else {
|
||||
try {
|
||||
unlinkSync(cfg.settingsFile);
|
||||
} catch (error) {
|
||||
if ((error as NodeJS.ErrnoException).code !== "ENOENT") throw error;
|
||||
}
|
||||
}
|
||||
durability.syncDirectory(directory);
|
||||
}
|
||||
|
||||
/** Persist settings (pretty JSON). Creates the parent directory if needed. */
|
||||
export function saveSettings(
|
||||
cfg: AppConfig,
|
||||
|
||||
Reference in New Issue
Block a user