feat: bootstrap boss control plane prototype
This commit is contained in:
61
src/store.ts
Normal file
61
src/store.ts
Normal file
@@ -0,0 +1,61 @@
|
||||
import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
|
||||
import { dirname } from "node:path";
|
||||
import type { AppState } from "./types.js";
|
||||
|
||||
function defaultState(): AppState {
|
||||
return {
|
||||
sessions: [],
|
||||
messages: [],
|
||||
tasks: [],
|
||||
workers: [],
|
||||
approvals: [],
|
||||
events: [],
|
||||
};
|
||||
}
|
||||
|
||||
export class FileStore {
|
||||
private state: AppState;
|
||||
|
||||
constructor(private readonly filePath: string) {
|
||||
this.ensureDirectory();
|
||||
this.state = this.load();
|
||||
}
|
||||
|
||||
get snapshot(): AppState {
|
||||
return structuredClone(this.state);
|
||||
}
|
||||
|
||||
mutate<T>(mutator: (state: AppState) => T): T {
|
||||
const result = mutator(this.state);
|
||||
this.save();
|
||||
return result;
|
||||
}
|
||||
|
||||
reset(): AppState {
|
||||
this.state = defaultState();
|
||||
this.save();
|
||||
return this.snapshot;
|
||||
}
|
||||
|
||||
private ensureDirectory(): void {
|
||||
mkdirSync(dirname(this.filePath), { recursive: true });
|
||||
}
|
||||
|
||||
private load(): AppState {
|
||||
if (!existsSync(this.filePath)) {
|
||||
return defaultState();
|
||||
}
|
||||
|
||||
try {
|
||||
const raw = readFileSync(this.filePath, "utf8");
|
||||
return { ...defaultState(), ...(JSON.parse(raw) as AppState) };
|
||||
} catch {
|
||||
return defaultState();
|
||||
}
|
||||
}
|
||||
|
||||
private save(): void {
|
||||
writeFileSync(this.filePath, `${JSON.stringify(this.state, null, 2)}\n`, "utf8");
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user