Something went wrong. Try again.
A local-first note taking app
Something went wrong. Try again.
TypeScript
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101import type { HabitatUri, SerializableSyncSnapshot, SnapshotDirectoryEntry, SnapshotFileEntry, SyncSnapshot,} from './types';import type { FilesystemApi } from '../filesystem/types';
const TEXTILE_DIR = '.textile';const SNAPSHOT_FILE = `${TEXTILE_DIR}/snapshot.json`;
/** * Manages `.textile/snapshot.json` for synced vaults. * Loads, saves, serializes, and deserializes the sync snapshot. */export class VaultSnapshotManager { constructor(private fs: FilesystemApi) {}
/** * Load the snapshot from disk at the given vault root. * Returns `null` if no snapshot exists yet. */ async load(rootPath: string): Promise<SyncSnapshot | null> { try { const raw = await this.fs.readFile(`${rootPath}/${SNAPSHOT_FILE}`); return this.deserialize(raw); } catch { return null; } }
/** * Save the snapshot to disk at the given vault root. * Creates `.textile/` if it does not exist. */ async save(rootPath: string, snapshot: SyncSnapshot): Promise<void> { const textileDir = `${rootPath}/${TEXTILE_DIR}`; if (!(await this.fs.fileExists(textileDir))) { await this.fs.mkdir(textileDir); } const json = this.serialize(snapshot); await this.fs.writeFile(`${rootPath}/${SNAPSHOT_FILE}`, json); }
/** * Convert a SyncSnapshot to a JSON string. * Maps are serialized as arrays of [key, value] tuples. */ serialize(snapshot: SyncSnapshot): string { const serializable: SerializableSyncSnapshot = { timestamp: snapshot.timestamp, rootUri: snapshot.rootUri, files: Array.from(snapshot.files.entries()), directories: Array.from(snapshot.directories.entries()), }; return JSON.stringify(serializable, null, 2); }
/** * Parse a JSON string back into a SyncSnapshot. * Reconstructs Maps from arrays of [key, value] tuples. */ deserialize(raw: string): SyncSnapshot { const parsed = JSON.parse(raw) as SerializableSyncSnapshot;
const files = new Map<string, SnapshotFileEntry>(); if (Array.isArray(parsed.files)) { for (const [key, value] of parsed.files) { files.set(key, value); } }
const directories = new Map<string, SnapshotDirectoryEntry>(); if (Array.isArray(parsed.directories)) { for (const [key, value] of parsed.directories) { directories.set(key, value); } }
return { timestamp: parsed.timestamp, rootUri: parsed.rootUri as HabitatUri, files, directories, }; }
/** * Create an empty snapshot for a new synced vault. */ createEmpty(rootUri: HabitatUri): SyncSnapshot { return { timestamp: Date.now(), rootUri, files: new Map(), directories: new Map(), }; }}