Something went wrong. Try again.
Monorepo for the nibling.run platform
Something went wrong. Try again.
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556import type { FileTree } from "@nibling/sdk";import type { Files } from "../files.ts";
/** A project's files as the views see them, plus what a save needs: which paths changed and a copy to write. */export interface ProjectFiles extends Files { /** Paths whose bytes differ from the last saved tree, sorted. */ dirty(): string[]; /** A copy of the current tree. */ snapshot(): FileTree; /** * Records `tree` as what the PDS holds. Pass the snapshot a save wrote, so edits made while the save * was in flight stay dirty. */ markSaved(tree: FileTree): void;}
const encoder = new TextEncoder();const decoder = new TextDecoder();
export function projectFiles(tree: FileTree): ProjectFiles { const current = new Map(tree); let saved: FileTree = new Map(tree); const touched = new Set<string>(); const listeners = new Set<(path: string) => void>(); const changed = (path: string) => !same(current.get(path), saved.get(path));
return { list: () => [...current.keys()].sort(), read(path) { const bytes = current.get(path); return bytes && decoder.decode(bytes); }, write(path, text) { current.set(path, encoder.encode(text)); touched.add(path); for (const listener of listeners) listener(path); }, watch(listener) { listeners.add(listener); return () => listeners.delete(listener); }, dirty: () => [...touched].filter(changed).sort(), snapshot: () => new Map(current), markSaved(next) { saved = new Map(next); for (const path of touched) if (!changed(path)) touched.delete(path); }, };}
function same(a: Uint8Array | undefined, b: Uint8Array | undefined): boolean { if (a === b) return true; if (!a || !b || a.length !== b.length) return false; return a.every((byte, i) => byte === b[i]);}