@hyperframes/studio-server 0.8.127 → 0.8.128
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@hyperframes/studio-server",
|
|
3
|
-
"version": "0.8.
|
|
3
|
+
"version": "0.8.128",
|
|
4
4
|
"repository": {
|
|
5
5
|
"type": "git",
|
|
6
6
|
"url": "https://github.com/heygen-com/hyperframes",
|
|
@@ -81,8 +81,8 @@
|
|
|
81
81
|
"postcss": "^8.5.8",
|
|
82
82
|
"postcss-selector-parser": "^7.1.2",
|
|
83
83
|
"sharp": "^0.35.0",
|
|
84
|
-
"@hyperframes/core": "0.8.
|
|
85
|
-
"@hyperframes/parsers": "0.8.
|
|
84
|
+
"@hyperframes/core": "0.8.128",
|
|
85
|
+
"@hyperframes/parsers": "0.8.128"
|
|
86
86
|
},
|
|
87
87
|
"devDependencies": {
|
|
88
88
|
"@types/node": "^25.0.10",
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/history/projectHistory.ts","../src/helpers/fileVersion.ts","../src/helpers/projectSignature.ts","../src/history/blobStore.ts","../src/history/pruneHistories.ts","../src/history/historyId.ts","../src/history/ownerLock.ts","../src/history/historyLog.ts","../src/history/historyCache.ts"],"sourcesContent":["import { randomUUID } from \"node:crypto\";\nimport { mkdir, readdir, rm, rmdir, writeFile } from \"node:fs/promises\";\nimport {\n type Dirent,\n type Stats,\n existsSync,\n lstatSync,\n statSync,\n mkdirSync,\n readdirSync,\n readFileSync,\n realpathSync,\n rmSync,\n} from \"node:fs\";\nimport { homedir } from \"node:os\";\nimport { dirname, isAbsolute, join, relative, resolve, sep } from \"node:path\";\nimport { replaceFileAtomically } from \"@hyperframes/core/atomic-file\";\nimport {\n DELETED_VERSION,\n fileContentVersion,\n hashOfVersion,\n hashVersion,\n onFileOverwritten,\n recordFileWriteReceipt,\n} from \"../helpers/fileVersion.js\";\nimport { realFilePath } from \"../helpers/safePath.js\";\nimport {\n STUDIO_SIGNATURE_MANIFEST_PATHS,\n affectsProjectSignature,\n listProjectFiles,\n} from \"../helpers/projectSignature.js\";\nimport { openBlobStore, type BlobStore } from \"./blobStore.js\";\nimport { pruneGoneProjectHistoriesDaily } from \"./pruneHistories.js\";\nimport {\n ID_PATH,\n isRecordedFolder,\n sameFolder,\n projectHistoryId,\n readId,\n recordProject,\n type FolderIdentity,\n} from \"./historyId.js\";\nimport { takeHistoryOwnership } from \"./ownerLock.js\";\nimport {\n START,\n foldOldest,\n manifestAround,\n manifestAt,\n readLog,\n saveRecord,\n referencedHashes,\n stepTarget,\n undoneIds,\n writeLog,\n type HistoryEntry,\n type HistoryEntrySide,\n type HistoryFileChange,\n type HistoryLog,\n type HistoryWho,\n type LogRecord,\n type Manifest,\n} from \"./historyLog.js\";\n\n/** Where hosts keep project histories unless told otherwise: outside every project, so no tidy-up takes one away. */\nexport const DEFAULT_HISTORY_ROOT = join(homedir(), \".cache\", \"hyperframes\", \"history\");\n\nexport interface ProjectHistoryOptions {\n projectDir: string;\n /** Kept outside the project, so nothing tidying the project can take its history with it. */\n historyRoot: string;\n now?: () => number;\n /** Writes with no window open group into one entry until this long without another (default 2 s)... */\n quietMs?: number;\n /** ...or this long after the first (default 30 s). */\n maxGroupMs?: number;\n /** Past this many stored bytes the oldest unpinned entries are folded away (default 2 GB). */\n budgetBytes?: number;\n /** A sweep or commit that a watcher or timer started failed. */\n onError?: (error: unknown) => void;\n /** How long an open waits for another process to close the same history (default 5 s). */\n ownerWaitMs?: number;\n /** A CLI turn's window from an earlier open: writes since, within its idle limit, become the entry with its id. */\n closedWindow?: ClosedWindow;\n undoScope?: \"own\" | \"everyone\";\n pruneGoneProjectsBudgetMs?: number;\n}\n\ninterface ClaimOptions {\n coalesceKey?: string;\n idleMs?: number;\n /** Per path, the version (fileContentVersion) the claimer overwrote: earlier changes stay their writer's. */\n overwrote?: Readonly<Record<string, string>>;\n}\n\ninterface Writing {\n writeToken?: string;\n}\n\nexport interface ClosedWindow {\n id: string;\n who: HistoryWho;\n label: string;\n startedAt: number;\n lastWriteAt: number;\n idleMs: number;\n}\n\nexport const MAX_WINDOW_IDLE_MS = 10 * 60_000;\n\nexport const UNDO_MODES = [\"just-this\", \"back-to-before\", \"keep-later-edits\"] as const;\nexport type UndoMode = (typeof UNDO_MODES)[number];\n\nexport interface HistoryListItem extends HistoryEntry {\n pinned: boolean;\n undone: boolean;\n}\n\nexport type HistoryResult =\n | { ok: true; entry: HistoryEntry | null }\n | { ok: false; conflict: { files: string[]; newer: string[] } };\n\nexport interface HistoryWindow {\n readonly id: string;\n readonly startedAt: number;\n /** Records everything written since the window opened as one entry (null when nothing changed); after the window\n * ended by itself or by flush, returns the entry it became. */\n close(): Promise<HistoryEntry | null>;\n}\n\nexport interface ProjectHistory {\n readonly projectId: string;\n /** Writes until close() are one entry with the window's id; another writer or an operation meanwhile commits the\n * part so far first (fresh id), returned by close() if nothing else remained. Overlaps go to the newest. */\n beginWindow(\n who: HistoryWho,\n label: string,\n options?: { idleMs?: number },\n ): Promise<HistoryWindow>;\n /**\n * For a writer that records after writing (Studio): moves the uncommitted changes to `paths` into one entry of\n * `who`'s, each cut at the `overwrote` version so earlier parts stay their writer's. Same-key claims merge until\n * another key, idle, an operation, a window, or another write. Null when nothing was claimed or a drag nets to 0.\n */\n claim(\n who: HistoryWho,\n label: string,\n paths: readonly string[],\n options?: ClaimOptions,\n ): Promise<{ id: string } | null>;\n /** A watcher saw `path` change (project-relative or absolute). */\n noteChange(path: string): void;\n list(): HistoryListItem[];\n /** Cmd+Z (back) and Cmd+Shift+Z (forward) over `who`'s own and outside changes, or all (undoScope everyone). */\n step(direction: \"back\" | \"forward\", who: HistoryWho, options?: Writing): Promise<HistoryResult>;\n /** The entry `who`'s next step reverts, pending changes included, as of the last scan (a step scans first). */\n next(direction: \"back\" | \"forward\", who: HistoryWho): HistoryEntry | undefined;\n /** A file changed since returns a conflict; `mode` takes a choice (keep-later-edits: null when none is left). */\n undo(id: string, options: { who: HistoryWho; mode?: UndoMode } & Writing): Promise<HistoryResult>;\n /** Makes the files equal what they were right after `point` (an entry id, or START). */\n restore(point: string, who: HistoryWho, options?: Writing): Promise<HistoryEntry | null>;\n /** The files at `point` without writing anything: path to hash, read through readBlob. */\n peek(point: string): Record<string, string> | null;\n checkout(entryId: string, side: HistoryEntrySide, emptyDir: string): Promise<void>;\n readBlob(hash: string): Promise<Buffer>;\n pin(id: string, pinned: boolean): void;\n onEntry(listener: (entry: HistoryEntry) => void): () => void;\n /** Takes in every pending write and commits every open window and the outside group. */\n flush(): Promise<void>;\n /** True once another project stands at the folder's path: open that one's history instead. */\n replacedAtPath(): boolean;\n close(): Promise<void>;\n}\n\nconst OUTSIDE: HistoryWho = { kind: \"outside\", name: \"Outside\" };\nconst OUTSIDE_LABEL = \"Changed outside the app\";\n\ninterface Tracked {\n hash: string;\n stat: string;\n}\n\ninterface Group {\n id: string;\n who: HistoryWho;\n label: string;\n startedAt: number;\n changes: Map<string, HistoryFileChange>;\n /** Windows only: the idle lifetime, its timer, the last write's time, and the entry it became once ended. */\n idleMs?: number;\n lastWriteAt?: number;\n idleTimer?: NodeJS.Timeout;\n entry?: HistoryEntry | null;\n parts?: Set<string>;\n}\n\n/**\n * A stat is only trusted once the file is older than any file system's timestamp tick (git's \"racily clean\"): a\n * same-size rewrite inside one tick keeps its size, mtime and ctime. \"\" is never trusted, so the file is re-hashed.\n */\nconst RACY_MS = 2000;\nconst statKey = (file: { size: number; mtimeMs: number; ctimeMs: number }, sweptAt: number) =>\n sweptAt - Math.max(file.mtimeMs, file.ctimeMs) < RACY_MS\n ? \"\"\n : `${file.size}:${file.mtimeMs}:${file.ctimeMs}`;\n\nconst MEDIA_LEDGER = \".media/manifest.jsonl\";\nconst KEPT_HIDDEN_PATHS = new Set<string>([...STUDIO_SIGNATURE_MANIFEST_PATHS, MEDIA_LEDGER]);\n\n/** A hidden name anywhere in a path (a tool's own record, .DS_Store) is nobody's work, except the kept ones above. */\nfunction isHistoryPath(path: string): boolean {\n if (KEPT_HIDDEN_PATHS.has(path)) return true;\n return !path.split(\"/\").some((segment) => segment.startsWith(\".\"));\n}\n\nfunction withoutHiddenPaths(log: HistoryLog): HistoryLog {\n for (const path of log.baseline.keys()) if (!isHistoryPath(path)) log.baseline.delete(path);\n for (const entry of log.entries)\n entry.files = entry.files.filter((file) => isHistoryPath(file.path));\n return log;\n}\n\nconst historyFiles = (dir: string) =>\n listProjectFiles(dir).filter((file) => isHistoryPath(file.path));\n\nconst sameWho = (a: HistoryWho, b: HistoryWho) => a.kind === b.kind && a.name === b.name;\n\n/** Cuts a change at the overwritten `at`: [kept before it, claimed after]; `at` unknown or not kept claims all. */\nfunction splitAt(\n change: HistoryFileChange,\n at: string | undefined,\n kept: boolean,\n): [HistoryFileChange | null, HistoryFileChange | null] {\n if (at === change.after) return [change, null];\n if (!at || at === change.before || !kept) return [null, change];\n return [\n { ...change, after: at },\n { ...change, before: at },\n ];\n}\n\nconst isMissingFolder = (error: unknown) =>\n [\"ENOENT\", \"ENOTDIR\"].includes((error as NodeJS.ErrnoException).code ?? \"\");\n\n/** Removes a folder at `dir` that holds only empty folders (inTheWay checked), so a file can take its place. */\nasync function removeEmptyFolders(dir: string): Promise<void> {\n let entries: Dirent[];\n try {\n entries = await readdir(dir, { withFileTypes: true });\n } catch (error) {\n if (isMissingFolder(error)) return;\n throw error;\n }\n for (const entry of entries)\n if (entry.isDirectory()) await removeEmptyFolders(join(dir, entry.name));\n await rmdir(dir);\n}\n\n/** The first file or link under folder `dir` (project path `at`) not in `deleted`; links are not followed. */\nfunction fileLeftIn(dir: string, at: string, deleted: ReadonlySet<string>): string | undefined {\n for (const entry of readdirSync(dir, { withFileTypes: true })) {\n const path = `${at}/${entry.name}`;\n const left = entry.isDirectory()\n ? fileLeftIn(join(dir, entry.name), path, deleted)\n : deleted.has(path)\n ? undefined\n : path;\n if (left) return left;\n }\n return undefined;\n}\n\n/** Whether the project's disk treats `A` and `a` as one name: its history-id file answers when upper-cased. */\nfunction ignoresCase(dir: string): boolean {\n const self = statSync(join(dir, ID_PATH), { throwIfNoEntry: false });\n const other = statSync(join(dir, ID_PATH.toUpperCase()), { throwIfNoEntry: false });\n return self !== undefined && other?.ino === self.ino && other.dev === self.dev;\n}\n\nconst blocks = (removed: string, added: string) =>\n added.startsWith(`${removed}/`) || removed.startsWith(`${added}/`);\n\n/** A window takes a write within idleMs of its last one; past that it has ended, even before its timer commits it. */\nconst MAX_TIMER_MS = 2 ** 31 - 1;\n\nconst takesWrite = (window: Group, at: number) =>\n window.idleMs === undefined || at - (window.lastWriteAt ?? at) <= window.idleMs;\n\nfunction chainBackFrom(\n byAfter: Map<string, string> | undefined,\n hash: string,\n): Map<string, string> {\n const chain = new Map<string, string>();\n let at = hash;\n let prior = byAfter?.get(at);\n while (prior !== undefined && !chain.has(at)) {\n chain.set(at, prior);\n at = prior;\n prior = byAfter?.get(at);\n }\n return chain;\n}\n\n/** Files one change to a group; a later change to the same path keeps the group's first \"before\". */\nfunction addChange(group: Group, path: string, before: string | null, after: string | null): void {\n const earlier = group.changes.get(path);\n const from = earlier ? earlier.before : before;\n if (from === after) group.changes.delete(path);\n else group.changes.set(path, { path, before: from, after });\n}\n\nclass Engine {\n readonly dir: string;\n readonly foldsCase: boolean;\n readonly folder: FolderIdentity & { dev: number };\n readonly home: string;\n log: HistoryLog = { baseline: new Map(), entries: [], pins: new Set() };\n tracked = new Map<string, Tracked>();\n windows: Group[] = [];\n outside: Group | null = null;\n /** A coalescing claim, open until another key, its idle timer, an operation, a window, or another write. */\n claimed: { group: Group; key: string; timer?: NodeJS.Timeout } | null = null;\n /** Per path and hash an API write left, the hash of the bytes it replaced, until walked or written past. */\n overwritten = new Map<string, Map<string, string>>();\n stopHearing: (() => void) | undefined;\n writeToken: string | undefined;\n quietTimer: NodeJS.Timeout | undefined;\n maxTimer: NodeJS.Timeout | undefined;\n notedTimer: NodeJS.Timeout | null = null;\n listeners = new Set<(entry: HistoryEntry) => void>();\n tail: Promise<unknown> = Promise.resolve();\n closed = false;\n closing: Promise<void> | undefined;\n\n constructor(\n readonly options: ProjectHistoryOptions,\n readonly projectId: string,\n readonly blobs: BlobStore,\n ) {\n this.dir = resolve(options.projectDir);\n this.home = join(options.historyRoot, projectId);\n this.foldsCase = ignoresCase(this.dir);\n const folder = statSync(this.dir, { throwIfNoEntry: false });\n // Checked after the ownership wait, so a folder swapped for a copy meanwhile is refused.\n if (!folder || readId(this.dir) !== projectId || !isRecordedFolder(this.home, folder))\n throw this.replaced();\n this.folder = { dev: folder.dev, ino: folder.ino, birthtimeMs: folder.birthtimeMs };\n }\n\n /** A path as the project's disk compares names: folded where `A` and `a` are one name. */\n nameKey(path: string): string {\n return this.foldsCase ? path.toLowerCase() : path;\n }\n\n get logFile() {\n return join(this.home, \"log.jsonl\");\n }\n\n now(): number {\n return (this.options.now ?? Date.now)();\n }\n\n /** One operation at a time, in order: sweeps, windows and undos never interleave. */\n queue<T>(task: () => Promise<T>): Promise<T> {\n if (this.closed)\n return Promise.reject(new HistoryClosedError(\"This project's history is closed.\"));\n const run = this.tail.then(task);\n this.tail = run.catch(() => undefined);\n return run;\n }\n\n /** Another project if the folder or its id changed, or the id is gone: a recreated folder may reuse the inode. */\n whereFolder(): \"here\" | \"gone\" | \"replaced\" {\n const now = statSync(this.dir, { throwIfNoEntry: false });\n if (!now) return \"gone\";\n const same = now.dev === this.folder.dev && sameFolder(now, this.folder);\n return same && readId(this.dir) === this.projectId ? \"here\" : \"replaced\";\n }\n\n assertWritable(): void {\n const folder = this.whereFolder();\n if (folder === \"gone\") throw new Error(`The project folder is gone: ${this.dir}`);\n if (folder === \"replaced\") throw this.replaced();\n }\n\n persistLog(record?: LogRecord): void {\n if (record) saveRecord(this.logFile, this.log, record);\n else writeLog(this.logFile, this.log);\n if (!existsSync(join(this.home, \"project.json\")))\n recordProject(this.home, this.dir, this.folder);\n }\n\n replaced(): HistoryClosedError {\n return new HistoryClosedError(`${this.dir} is now another project.`);\n }\n\n assertOpen(): void {\n if (this.closed) throw new HistoryClosedError(\"This project's history is closed.\");\n if (this.whereFolder() === \"replaced\") throw this.replaced();\n }\n\n async start(): Promise<void> {\n const log = readLog(this.logFile, (line) =>\n this.options.onError?.(\n new Error(`History log line ${line} could not be read and was skipped.`),\n ),\n );\n if (!log) return this.firstOpen();\n this.log = withoutHiddenPaths(log);\n if (!this.log.keepsLedger) await this.takeInUnnamedLedger();\n const cache = this.readStatCache();\n const last = this.log.entries.at(-1)?.id ?? START;\n for (const [path, hash] of manifestAt(this.log, last) ?? []) {\n const cached = cache.get(path);\n this.tracked.set(path, { hash, stat: cached?.hash === hash ? cached.stat : \"\" });\n }\n // What changed while the project was closed is one outside entry, or the closed window's.\n this.reopenClosedWindow();\n await this.settleAll();\n }\n\n hearWrites(): void {\n const realDir = realFilePath(this.dir);\n this.stopHearing = onFileOverwritten((absPath, version, bytes) => {\n const after = hashOfVersion(version);\n if (!after || !affectsProjectSignature(realDir, absPath)) return;\n const replaced = hashOfVersion(fileContentVersion(bytes));\n if (!replaced || replaced === after) return;\n const path = relative(realDir, absPath).split(sep).join(\"/\");\n if (!isHistoryPath(path)) return;\n // One chain per file, a new Map per write (forgetWritesBefore checks identity); off-chain notes were overwritten.\n this.overwritten.set(\n path,\n chainBackFrom(this.overwritten.get(path), replaced).set(after, replaced),\n );\n this.queue(async () => {\n if (!this.blobs.has(replaced)) await this.storeBytes(bytes);\n }).catch((error) => this.options.onError?.(error));\n });\n }\n\n async storeBytes(bytes: string | Uint8Array): Promise<void> {\n const staged = join(this.home, `overwrote-${randomUUID()}`);\n await mkdir(this.home, { recursive: true });\n await writeFile(staged, bytes);\n try {\n await this.blobs.put(staged);\n } finally {\n await rm(staged, { force: true });\n }\n }\n\n /** Read at a state no API write left, with no write heard since `heard`: no walk passes it, so forget the rest. */\n forgetWritesBefore(\n path: string,\n hash: string | null,\n heard: Map<string, string> | undefined,\n ): void {\n if (this.overwritten.get(path) === heard && !(hash && heard?.has(hash)))\n this.overwritten.delete(path);\n }\n\n reopenClosedWindow(): void {\n const closed = this.options.closedWindow;\n if (!closed || this.log.entries.some((entry) => entry.id === closed.id)) return;\n const { id, who, label, startedAt, lastWriteAt, idleMs } = closed;\n this.windows.push({ id, who, label, startedAt, lastWriteAt, idleMs, changes: new Map() });\n }\n\n async takeInUnnamedLedger(): Promise<void> {\n const named = (path: string) =>\n this.log.entries.some((entry) => entry.files.some((file) => file.path === path));\n const listed = () => historyFiles(this.dir).some((file) => file.path === MEDIA_LEDGER);\n const hash =\n this.log.baseline.has(MEDIA_LEDGER) || named(MEDIA_LEDGER) || !listed()\n ? null\n : await this.storeIfPresent(MEDIA_LEDGER);\n if (hash !== null) this.log.baseline.set(MEDIA_LEDGER, hash);\n this.log.keepsLedger = true;\n this.persistLog();\n }\n\n async firstOpen(): Promise<void> {\n const sweptAt = this.now();\n for (const file of historyFiles(this.dir)) {\n const hash = await this.storeIfPresent(file.path);\n if (this.whereFolder() !== \"here\") throw this.replaced();\n if (hash !== null) this.tracked.set(file.path, { hash, stat: statKey(file, sweptAt) });\n }\n this.log.baseline = this.manifest();\n this.log.keepsLedger = true;\n this.persistLog();\n this.saveStatCache();\n }\n\n manifest(): Manifest {\n return new Map([...this.tracked].map(([path, file]) => [path, file.hash]));\n }\n\n readStatCache(): Map<string, Tracked> {\n try {\n const files = JSON.parse(readFileSync(join(this.home, \"stat.json\"), \"utf-8\"));\n return new Map(Object.entries(files as Record<string, Tracked>));\n } catch {\n return new Map();\n }\n }\n\n saveStatCache(): void {\n const files = JSON.stringify(Object.fromEntries(this.tracked));\n mkdirSync(this.home, { recursive: true });\n replaceFileAtomically(join(this.home, \"stat.json\"), files, 0o644);\n }\n\n /**\n * Takes in every write since the last sweep and files each change to its writer. ponytail: always the whole\n * project (a stat per file, a hash only when the stat moved); per-path sweeps if projects reach tens of thousands.\n */\n async sweep(): Promise<void> {\n // A folder moved or removed was not emptied, and another project at its path is none of this history's.\n if (this.whereFolder() !== \"here\") return;\n const sweptAt = this.now();\n const changedAt = (file: { mtimeMs: number; ctimeMs: number }) =>\n Math.min(sweptAt, Math.max(file.mtimeMs, file.ctimeMs));\n const seen = historyFiles(this.dir);\n const heard = new Map(this.overwritten);\n const present = new Set(seen.map((file) => file.path));\n const removed = [...this.tracked.keys()]\n .filter((path) => !present.has(path))\n .map((path) => {\n const standing = this.standingAt(path);\n return { at: standing ? changedAt(standing.stat) : sweptAt, path, file: null };\n });\n // A file in the way of a removal (a/b over file a, or the reverse) appeared no earlier than that removal.\n const appearedAt = (file: (typeof seen)[number]) =>\n Math.max(\n changedAt(file),\n ...removed\n .filter((gone) => blocks(this.nameKey(gone.path), this.nameKey(file.path)))\n .map((gone) => gone.at),\n );\n const events = [\n ...removed,\n ...seen.map((file) => ({ at: appearedAt(file), path: file.path, file })),\n ].sort((a, b) => a.at - b.at);\n let changed = false;\n for (const { at, path, file } of events) {\n if (file) {\n changed = (await this.observe(path, statKey(file, sweptAt), at)) || changed;\n continue;\n }\n const known = this.tracked.get(path)!;\n this.tracked.delete(path);\n this.forgetWritesBefore(path, null, heard.get(path));\n await this.record(path, known.hash, null, at);\n changed = true;\n }\n if (changed) this.saveStatCache();\n }\n\n /** The file's hash once copied in; null when it was removed before the copy (the next sweep records that). */\n async storeIfPresent(path: string): Promise<string | null> {\n try {\n return await this.blobs.put(join(this.dir, path));\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code === \"ENOENT\") return null;\n throw error;\n }\n }\n\n async observe(path: string, stat: string, at: number): Promise<boolean> {\n const known = this.tracked.get(path) ?? { hash: null, stat: null };\n if (stat && known.stat === stat) return false;\n const heard = this.overwritten.get(path);\n const hash = await this.storeIfPresent(path);\n if (hash === null || this.whereFolder() !== \"here\") return false;\n this.tracked.set(path, { hash, stat });\n this.forgetWritesBefore(path, hash, heard);\n if (known.hash !== hash) await this.record(path, known.hash, hash, at);\n return known.hash !== hash || known.stat !== stat;\n }\n\n async record(\n path: string,\n before: string | null,\n after: string | null,\n at: number,\n ): Promise<void> {\n const endedBeforeThisWrite = this.windows.filter((open) => !takesWrite(open, at));\n if (endedBeforeThisWrite.length) await this.commitOutside();\n for (const window of endedBeforeThisWrite) await this.endWindow(window);\n const window = this.windows.at(-1);\n if (window) this.touch(window, at);\n addChange(window ?? this.outsideGroup(), path, before, after);\n }\n\n /** ponytail: another's write between Studio's write and its sweep folds into Studio's entry (per-write tokens). */\n async claimNow(\n who: HistoryWho,\n label: string,\n paths: readonly string[],\n { coalesceKey, idleMs, overwrote = {} }: ClaimOptions,\n ): Promise<{ id: string } | null> {\n await this.sweep();\n const taken = await this.takeClaimed(who, paths, overwrote);\n if (!taken.length) return this.claimNothing(coalesceKey);\n const held = this.heldFor(coalesceKey, taken);\n if (!held) await this.commitClaim();\n await this.commitPending();\n const group = held ?? this.newGroup(who, label);\n for (const change of taken) addChange(group, change.path, change.before, change.after);\n if (coalesceKey) return this.holdClaim(group, coalesceKey, idleMs);\n const entry = await this.commit(group);\n return entry && { id: entry.id };\n }\n\n /** A claim that took nothing still ends a held claim under another key. */\n async claimNothing(coalesceKey: string | undefined): Promise<null> {\n if (coalesceKey !== this.claimed?.key) await this.commitClaim();\n return null;\n }\n\n /** Commits every other writer's pending changes, oldest first; open windows stay open. */\n async commitPending(): Promise<void> {\n await this.commitOutside();\n for (const window of [...this.windows])\n if (window.changes.size) await this.commitCut(window, [...window.changes.keys()]);\n }\n\n pendingElsewhere(): boolean {\n return (\n Boolean(this.outside?.changes.size) || this.windows.some((open) => open.changes.size > 0)\n );\n }\n\n /** The held claim `taken` continues: same key, each file from its own last change, no held file changed since. */\n heldFor(key: string | undefined, taken: readonly HistoryFileChange[]): Group | null {\n const group =\n key && this.claimed?.key === key && !this.pendingElsewhere() ? this.claimed.group : null;\n const after = (path: string, before: string | null) => {\n const own = group?.changes.get(path);\n return own ? own.after : before;\n };\n const takenPaths = new Set(taken.map((change) => change.path));\n const untouched = (change: HistoryFileChange) =>\n takenPaths.has(change.path) || (this.tracked.get(change.path)?.hash ?? null) === change.after;\n return group &&\n taken.every((change) => after(change.path, change.before) === change.before) &&\n [...group.changes.values()].every(untouched)\n ? group\n : null;\n }\n\n logPath(path: string): string {\n return relative(this.dir, resolve(this.dir, path)).split(sep).join(\"/\");\n }\n\n /** Takes `paths`' uncommitted changes from others, cut at what `who` overwrote. */\n async takeClaimed(\n who: HistoryWho,\n paths: readonly string[],\n overwrote: Readonly<Record<string, string>>,\n ): Promise<HistoryFileChange[]> {\n const wanted = new Set(paths.map((path) => this.logPath(path)));\n const at = new Map(\n Object.entries(overwrote).map(([path, version]) => [\n this.logPath(path),\n hashOfVersion(version),\n ]),\n );\n const others = this.windows.filter((open) => !sameWho(open.who, who));\n const groups = this.outside ? [this.outside, ...others] : others;\n const hits = groups.flatMap((group) =>\n [...group.changes.values()]\n .filter((change) => wanted.has(change.path))\n .map((change) => ({ group, change })),\n );\n const cuts: Array<string | undefined> = [];\n const walked = hits.map(() => new Set<string>());\n for (const [i, { change }] of hits.entries()) {\n const told = at.get(change.path);\n cuts.push(this.overwrittenBy(change, told, walked[i]!) ?? told);\n }\n hits.forEach(({ change }, i) => this.forgetOverwritten(change.path, walked[i]!));\n return hits.flatMap(({ group, change }, i) => this.cutOut(group, change, cuts[i]) ?? []);\n }\n\n /** Walks the server's writes back from `change.after` to the stored bytes they replaced. */\n overwrittenBy(change: HistoryFileChange, told: string | undefined, seen: Set<string>) {\n let found: string | undefined;\n for (let hash = change.after; hash; ) {\n // A loop (X, Y, back to X) says nothing about what was there first: the client's word stands.\n if (seen.has(hash)) return undefined;\n seen.add(hash);\n const replaced = this.overwritten.get(change.path)?.get(hash);\n if (replaced === undefined) break;\n found = hash = replaced;\n if (hash === change.before || hash === told) return hash;\n }\n return found;\n }\n\n forgetOverwritten(path: string, hashes: Iterable<string>): void {\n const byAfter = this.overwritten.get(path);\n for (const hash of hashes) byAfter?.delete(hash);\n if (byAfter?.size === 0) this.overwritten.delete(path);\n }\n\n cutOut(group: Group, change: HistoryFileChange, cut: string | undefined) {\n const [kept, claimed] = splitAt(change, cut, cut !== undefined && this.blobs.has(cut));\n group.changes.delete(change.path);\n if (kept) group.changes.set(kept.path, kept);\n return claimed;\n }\n\n /** Commits the window's cut `paths` as their own entry, other files staying: a window holds one change per file,\n * so the writer's next write to a cut file would otherwise span the claimer's edit. */\n async commitCut(window: Group, paths: readonly string[]): Promise<void> {\n const part = { ...this.newGroup(window.who, window.label), startedAt: window.startedAt };\n for (const path of paths) {\n part.changes.set(path, window.changes.get(path)!);\n window.changes.delete(path);\n }\n (window.parts ??= new Set()).add(part.id);\n window.entry = await this.commit(part);\n }\n\n holdClaim(\n group: Group,\n key: string,\n idleMs = this.options.quietMs ?? 2000,\n ): { id: string } | null {\n clearTimeout(this.claimed?.timer);\n const timer = Number.isFinite(idleMs)\n ? setTimeout(() => this.background(() => this.commitClaim()), idleMs)\n : undefined;\n timer?.unref?.();\n this.claimed = { group, key, timer };\n return group.changes.size ? { id: group.id } : null;\n }\n\n async commitClaim(): Promise<void> {\n const held = this.claimed;\n this.claimed = null;\n if (!held) return;\n clearTimeout(held.timer);\n await this.commit(held.group);\n }\n\n outsideGroup(): Group {\n const { quietMs = 2000, maxGroupMs = 30_000 } = this.options;\n const closeIn = (ms: number) => {\n const timer = setTimeout(() => this.background(() => this.commitOutside()), ms);\n timer.unref?.();\n return timer;\n };\n if (!this.outside) {\n this.outside = this.newGroup(OUTSIDE, OUTSIDE_LABEL);\n this.maxTimer = closeIn(maxGroupMs);\n }\n clearTimeout(this.quietTimer);\n this.quietTimer = closeIn(quietMs);\n return this.outside;\n }\n\n newGroup(who: HistoryWho, label: string): Group {\n return { id: randomUUID(), who, label, startedAt: this.now(), changes: new Map() };\n }\n\n async commitOutside(): Promise<void> {\n if (this.outside?.changes.size) await this.commitClaim();\n clearTimeout(this.quietTimer);\n clearTimeout(this.maxTimer);\n const group = this.outside;\n this.outside = null;\n if (group) await this.commit(group);\n }\n\n async commit(group: Group, extra: Partial<HistoryEntry> = {}): Promise<HistoryEntry | null> {\n const undoesEmptied =\n this.log.entries.find((entry) => entry.id === extra.undoes)?.files.length === 0;\n if (!group.changes.size && !undoesEmptied) return null;\n const pending = this.pendingEntry(group);\n const endedAt = Math.max(pending.endedAt, this.log.entries.at(-1)?.endedAt ?? 0);\n const entry: HistoryEntry = { ...pending, endedAt, ...extra };\n this.log.entries.push(entry);\n try {\n this.persistLog({ type: \"entry\", entry });\n } catch (error) {\n this.log.entries.pop();\n throw error;\n }\n for (const listener of this.listeners) listener(entry);\n for (const change of group.changes.values()) {\n const walked = new Set<string>();\n this.overwrittenBy(change, undefined, walked);\n this.forgetOverwritten(change.path, walked);\n }\n await this.keepWithinBudget();\n return entry;\n }\n\n /** Stored bytes beyond what the current files need: a project larger than the budget still keeps its history. */\n historyBytes(): number {\n let current = 0;\n for (const hash of new Set([...this.tracked.values()].map((file) => file.hash)))\n current += this.blobs.size(hash);\n return this.blobs.bytes() - current;\n }\n\n async keepWithinBudget(): Promise<void> {\n const budget = this.options.budgetBytes ?? 2 * 1024 ** 3;\n let folded = false;\n while (this.historyBytes() > budget) {\n await this.blobs.prune(\n new Set([\n ...referencedHashes(this.log, this.manifest()),\n ...this.pendingHashes(),\n ...[...this.overwritten.values()].flatMap((byAfter) => [...byAfter.values()]),\n ]),\n );\n if (this.historyBytes() <= budget || !foldOldest(this.log)) break;\n folded = true;\n }\n if (folded) this.persistLog();\n }\n\n /** Hashes only pending changes point at yet, such as a claim's stored cut. */\n pendingHashes(): string[] {\n const changes = [...this.windows, this.outside, this.claimed?.group].flatMap((group) => [\n ...(group?.changes.values() ?? []),\n ]);\n return changes\n .flatMap((change) => [change.before, change.after])\n .filter((hash): hash is string => hash !== null);\n }\n\n /** Before an operation or a window: every write is filed and every pending change committed, in write order. */\n async settle(): Promise<void> {\n await this.sweep();\n await this.commitClaim();\n await this.commitPending();\n }\n\n /** A watcher saw a write: one sweep per burst takes it in (a deleted folder is reported by its name alone). */\n noteChange(path: string): void {\n const absolute = resolve(this.dir, path);\n if (this.notedTimer || !affectsProjectSignature(this.dir, absolute)) return;\n if (!isHistoryPath(relative(this.dir, absolute).split(sep).join(\"/\"))) return;\n this.notedTimer = setTimeout(() => {\n this.notedTimer = null;\n this.background(() => this.sweep());\n }, 20);\n this.notedTimer.unref?.();\n }\n\n background(task: () => Promise<unknown>): void {\n this.queue(task).catch((error) => {\n if (!(error instanceof HistoryClosedError)) this.options.onError?.(error);\n });\n }\n\n beginWindow(who: HistoryWho, label: string, idleMs: number): Promise<HistoryWindow> {\n return this.queue(async () => {\n // Writes before the window opened are not this writer's, and are logged before it.\n await this.settle();\n const window = { ...this.newGroup(who, label), idleMs };\n this.windows.push(window);\n this.touch(window, this.now());\n const close = () => this.queue(() => this.sweepAndEnd(window));\n return { id: window.id, startedAt: window.startedAt, close };\n });\n }\n\n /** A window with no write for its idleMs ends, so a close that never comes cannot hold every later write. */\n touch(window: Group, at: number): void {\n window.lastWriteAt = Math.max(window.lastWriteAt ?? at, at);\n this.endWhenIdle(window, window.idleMs);\n }\n\n endWhenIdle(window: Group, delay: number | undefined): void {\n clearTimeout(window.idleTimer);\n if (window.idleMs === undefined || !Number.isFinite(window.idleMs) || delay === undefined)\n return;\n window.idleTimer = setTimeout(\n () => {\n const left = window.idleMs! - (this.now() - (window.lastWriteAt ?? this.now()));\n if (left > 0) this.endWhenIdle(window, left);\n else this.background(() => this.sweepAndEnd(window));\n },\n Math.min(delay, MAX_TIMER_MS),\n );\n window.idleTimer.unref?.();\n }\n\n async sweepAndEnd(window: Group): Promise<HistoryEntry | null> {\n await this.sweep();\n return this.endWindow(window);\n }\n\n /** Commits an open window once; ending it again returns the entry it became. */\n async endWindow(window: Group): Promise<HistoryEntry | null> {\n if (!this.windows.includes(window)) return window.entry ?? null;\n clearTimeout(window.idleTimer);\n await this.commitClaim();\n this.windows = this.windows.filter((open) => open !== window);\n window.entry = (await this.commit(window)) ?? window.entry ?? null;\n return window.entry;\n }\n\n /** Every pending write, open window and outside group, committed: for flush and close. */\n async settleAll(): Promise<void> {\n await this.sweep();\n await this.commitClaim();\n for (const window of [...this.windows]) await this.endWindow(window);\n await this.commitOutside();\n }\n\n /** What took a removed path's place, dating its removal: an entry at the path, or a file at a folder above it. */\n standingAt(path: string): { at: string; stat: Stats } | undefined {\n const parts = path.split(\"/\");\n for (let depth = 1; depth <= parts.length; depth += 1) {\n const at = parts.slice(0, depth).join(\"/\");\n const stat = lstatSync(join(this.dir, at), { throwIfNoEntry: false });\n if (!stat) return undefined;\n if (at === path || !stat.isDirectory()) return { at, stat };\n }\n return undefined;\n }\n\n /** What a write of `path` would have to delete: a file or link at or above it, or a file in a folder at it. */\n inTheWay(path: string, deleted: ReadonlySet<string>): string | undefined {\n const standing = this.standingAt(path);\n if (!standing) return undefined;\n if (standing.stat.isSymbolicLink()) return standing.at;\n if (standing.at === path && !standing.stat.isDirectory()) return undefined;\n // On-disk names, so an entry `a` found at `A` on a case-insensitive disk matches its tracked paths.\n const real = realpathSync.native(join(this.dir, standing.at));\n const at = relative(realpathSync.native(this.dir), real).split(sep).join(\"/\");\n if (standing.at !== path) return deleted.has(at) ? undefined : at;\n return fileLeftIn(real, at, deleted);\n }\n\n /** Writes `target` (path to hash, null deletes) as one entry of `who`'s. */\n async writeAs(\n who: HistoryWho,\n label: string,\n target: Map<string, string | null>,\n extra: Partial<HistoryEntry>,\n ): Promise<HistoryEntry | null> {\n this.assertWritable();\n const changes = [...target]\n .filter(([path, hash]) => (this.tracked.get(path)?.hash ?? null) !== hash)\n .sort(([, a], [, b]) => Number(a !== null) - Number(b !== null));\n const deleted = new Set(changes.filter(([, hash]) => hash === null).map(([path]) => path));\n const blocked = changes\n .filter(([, hash]) => hash !== null)\n .map(([path]) => this.inTheWay(path, deleted))\n .find(Boolean);\n if (blocked) throw new Error(`${blocked} is in the way; move or delete it, then try again.`);\n const group = this.newGroup(who, label);\n this.windows.push(group);\n try {\n for (const [path, hash] of changes) await this.writeProjectFile(path, hash);\n await this.sweep();\n } finally {\n this.windows = this.windows.filter((open) => open !== group);\n }\n return this.commit(group, extra);\n }\n\n /** Writes one project file (null deletes it), first leaving the running operation's receipt for its echo. */\n async writeProjectFile(path: string, hash: string | null): Promise<void> {\n this.assertWritable();\n const absPath = join(this.dir, path);\n const { writeToken } = this;\n if (writeToken) {\n const version = hash === null ? DELETED_VERSION : hashVersion(hash);\n recordFileWriteReceipt(absPath, { path, version, writeToken });\n }\n if (hash === null) {\n this.assertWritable();\n rmSync(absPath, { force: true });\n } else {\n await removeEmptyFolders(absPath);\n await this.blobs.writeTo(hash, absPath, () => this.assertWritable());\n }\n }\n\n entry(id: string): HistoryEntry {\n const entry = this.log.entries.find((candidate) => candidate.id === id);\n if (!entry) throw new Error(\"That change is no longer kept in this project's history.\");\n return entry;\n }\n\n undoLabel(entry: HistoryEntry): string {\n if (!entry.undoes) return `Undid: ${entry.label}`;\n const original = this.log.entries.find((candidate) => candidate.id === entry.undoes);\n return `Redid: ${original?.label ?? entry.label}`;\n }\n\n async undoNow(id: string, who: HistoryWho, mode?: UndoMode): Promise<HistoryResult> {\n const entry = this.entry(id);\n const changed = this.movedOn(entry);\n if (changed.length && !mode) return { ok: false, conflict: this.conflict(entry, changed) };\n if (mode === \"back-to-before\") {\n const index = this.log.entries.indexOf(entry);\n const point = index > 0 ? this.log.entries[index - 1]!.id : START;\n return {\n ok: true,\n entry: await this.restoreNow(point, who, `Went back to before: ${entry.label}`),\n };\n }\n const target = new Map(\n entry.files\n .filter((file) => mode !== \"keep-later-edits\" || !changed.includes(file))\n .map((file) => [file.path, file.before]),\n );\n return {\n ok: true,\n entry: await this.writeAs(who, this.undoLabel(entry), target, { undoes: id }),\n };\n }\n\n movedOn(entry: HistoryEntry): HistoryFileChange[] {\n return entry.files.filter((file) => (this.tracked.get(file.path)?.hash ?? null) !== file.after);\n }\n\n next(direction: \"back\" | \"forward\", who: HistoryWho): HistoryEntry | undefined {\n // An outside change has no known author, so it is everyone's; a step commits it after the held claim.\n const mine = (author: HistoryWho) => sameWho(author, who) || sameWho(author, OUTSIDE);\n const pending = [...[...this.windows].reverse(), this.outside, this.claimed?.group].find(\n (group) => group?.changes.size && mine(group.who),\n );\n if (pending) return direction === \"back\" ? this.pendingEntry(pending) : undefined;\n const everyone = this.options.undoScope === \"everyone\";\n const ofOpenTurn = (entry: HistoryEntry) =>\n this.windows.some((open) => open.parts?.has(entry.id));\n return stepTarget(\n this.log.entries,\n direction,\n (entry) => entry.files.length > 0 && (mine(entry.who) || (everyone && !ofOpenTurn(entry))),\n );\n }\n\n /** A pending group as the entry it becomes once committed (a window's part gets a fresh id). */\n pendingEntry(group: Group): HistoryEntry {\n const files = [...group.changes.values()].sort((a, b) => a.path.localeCompare(b.path));\n const { id, who, label, startedAt, lastWriteAt } = group;\n return { id, who, label, startedAt, endedAt: lastWriteAt ?? this.now(), files };\n }\n\n conflict(\n entry: HistoryEntry,\n changed: HistoryFileChange[],\n ): { files: string[]; newer: string[] } {\n const paths = new Set(changed.map((file) => file.path));\n const after = this.log.entries.slice(this.log.entries.indexOf(entry) + 1);\n const newer = after.filter((later) => later.files.some((file) => paths.has(file.path)));\n return { files: [...paths], newer: newer.map((later) => later.id) };\n }\n\n async restoreNow(point: string, who: HistoryWho, label: string): Promise<HistoryEntry | null> {\n const files = manifestAt(this.log, point);\n if (!files) throw new Error(\"That point is no longer kept in this project's history.\");\n const target = new Map<string, string | null>(\n [...this.tracked.keys()].map((path) => [path, null]),\n );\n for (const [path, hash] of files) target.set(path, hash);\n return this.writeAs(who, label, target, { restoredTo: point });\n }\n\n /** Settles, then runs `task` with its writes labelled `writeToken`. */\n operation<T>(writeToken: string | undefined, task: () => Promise<T>): Promise<T> {\n return this.queue(async () => {\n await this.settle();\n this.writeToken = writeToken;\n try {\n return await task();\n } finally {\n this.writeToken = undefined;\n }\n });\n }\n\n pointLabel(point: string): string {\n return point === START ? \"the start\" : this.entry(point).label;\n }\n\n api(): ProjectHistory {\n return {\n projectId: this.projectId,\n beginWindow: (who, label, options = {}) =>\n this.beginWindow(who, label, options.idleMs ?? this.options.maxGroupMs ?? 30_000),\n claim: (who, label, paths, options = {}) =>\n this.queue(() => this.claimNow(who, label, paths, options)),\n noteChange: (path) => {\n if (!this.closed) this.noteChange(path);\n },\n list: () => {\n this.assertOpen();\n const undone = undoneIds(this.log.entries);\n return this.log.entries.map((entry) => ({\n ...entry,\n pinned: this.log.pins.has(entry.id),\n undone: undone.has(entry.id),\n }));\n },\n step: (direction, who, { writeToken } = {}) =>\n this.operation(writeToken, async () => {\n const target = this.next(direction, who);\n return target ? this.undoNow(target.id, who) : { ok: true, entry: null };\n }),\n undo: (id, { who, mode, writeToken }) =>\n this.operation(writeToken, () => this.undoNow(id, who, mode)),\n restore: (point, who, { writeToken } = {}) =>\n this.operation(writeToken, () =>\n this.restoreNow(point, who, `Restored: ${this.pointLabel(point)}`),\n ),\n peek: (point) => {\n this.assertOpen();\n const files = manifestAt(this.log, point);\n return files && Object.fromEntries(files);\n },\n checkout: (entryId, side, emptyDir) =>\n this.queue(async () => {\n this.entry(entryId);\n if (!existsSync(this.dir)) throw new Error(`The project folder is gone: ${this.dir}`);\n const dest = resolve(emptyDir);\n if (isWithin(this.dir, dest))\n throw new Error(`Checkout writes outside the project only: ${dest}`);\n if ((await readdir(dest).catch(missingIsEmpty)).length > 0)\n throw new Error(`Checkout writes into an empty folder only: ${dest}`);\n const files = manifestAround(this.log, entryId, side)!;\n try {\n for (const [path, hash] of files) await this.blobs.writeTo(hash, join(dest, path));\n } catch (error) {\n for (const name of await readdir(dest).catch(() => []))\n await rm(join(dest, name), { recursive: true, force: true });\n throw error;\n }\n }),\n next: (direction, who) => {\n this.assertOpen();\n return this.next(direction, who);\n },\n readBlob: async (hash) => {\n this.assertOpen();\n return this.blobs.read(hash);\n },\n pin: (id, pinned) => {\n this.assertOpen();\n this.entry(id);\n if (pinned) this.log.pins.add(id);\n else this.log.pins.delete(id);\n this.persistLog({ type: \"pin\", id, pinned });\n },\n onEntry: (listener) => {\n this.listeners.add(listener);\n return () => this.listeners.delete(listener);\n },\n flush: () => this.queue(() => this.settleAll()),\n replacedAtPath: () => this.whereFolder() === \"replaced\",\n close: () =>\n (this.closing ??= (async () => {\n if (this.notedTimer) clearTimeout(this.notedTimer);\n this.stopHearing?.();\n const settled = this.queue(() => this.settleAll());\n this.closed = true;\n await settled;\n })()),\n };\n }\n}\n\n/** Compares real on-disk paths; `.native` gives a case-insensitive disk's real letter case, so no alias gets in. */\nfunction isWithin(dir: string, path: string): boolean {\n let probe = resolve(path);\n while (!existsSync(probe) && dirname(probe) !== probe) probe = dirname(probe);\n const rel = relative(realpathSync.native(dir), realpathSync.native(probe));\n return rel === \"\" || (rel !== \"..\" && !rel.startsWith(`..${sep}`) && !isAbsolute(rel));\n}\n\nfunction missingIsEmpty(error: NodeJS.ErrnoException): string[] {\n if (error.code === \"ENOENT\") return [];\n throw error;\n}\n\n/** A call on a history that was closed, or whose folder is now another project. */\nexport class HistoryClosedError extends Error {\n constructor(message: string) {\n super(message);\n this.name = \"HistoryClosedError\";\n }\n}\n\n/** Opens a project's history: every write to its files becomes an entry that can be undone or restored. */\nexport async function openProjectHistory(options: ProjectHistoryOptions): Promise<ProjectHistory> {\n if (!existsSync(options.projectDir))\n throw new HistoryClosedError(`${options.projectDir} is gone or now another project.`);\n const projectId = projectHistoryId(options.projectDir, options.historyRoot);\n const release = await takeHistoryOwnership(\n join(options.historyRoot, projectId),\n options.ownerWaitMs ?? 5000,\n );\n try {\n const blobs = await openBlobStore(join(options.historyRoot, projectId, \"blobs\"));\n const engine = new Engine(options, projectId, blobs);\n await engine.queue(async () => {\n await engine.start();\n engine.hearWrites();\n });\n pruneGoneProjectHistoriesDaily(options.historyRoot, engine.now(), {\n onError: options.onError,\n budgetMs: options.pruneGoneProjectsBudgetMs,\n });\n const api = engine.api();\n return {\n ...api,\n close: () => api.close().finally(release),\n };\n } catch (error) {\n release();\n throw error;\n }\n}\n","import { createHash, randomUUID } from \"node:crypto\";\nimport { realFilePath } from \"./safePath.js\";\n\nexport interface FileWriteReceipt {\n path: string;\n version: string;\n writeToken: string;\n from?: string;\n}\n\ninterface StoredReceipt extends FileWriteReceipt {\n recordedAt: number;\n}\n\ntype OverwriteListener = (absPath: string, version: string, overwrote: string | Uint8Array) => void;\n\nconst RECEIPT_TTL_MS = 10_000;\nconst receipts = new Map<string, StoredReceipt[]>();\nconst overwriteListeners = new Set<OverwriteListener>();\n\n/** Strong content version used as both the JSON version and HTTP ETag. */\nexport function fileContentVersion(content: string | Uint8Array): string {\n return hashVersion(createHash(\"sha256\").update(content).digest(\"hex\"));\n}\n\n/** The version a deletion's receipt is kept under: a deleted file has no bytes to hash. */\nexport const DELETED_VERSION = '\"deleted\"';\n\nexport function hashVersion(hex: string): string {\n return `\"sha256:${hex}\"`;\n}\n\n/** The sha256 a version names, or undefined when it is not a content version. */\nexport function hashOfVersion(version: string): string | undefined {\n return /^\"sha256:([0-9a-f]{64})\"$/.exec(version)?.[1];\n}\n\n/** A validator from a file's inode, change time and size, or null while the change is under three\n * seconds old. Change time, not mtime: copy tools (`cp -p`, rsync, robocopy) set mtime back but not\n * ctime, which Node reads from NTFS ChangeTime on Windows. A same-size rewrite within one tick keeps\n * both, so only a settled file is tagged. */\nexport function settledFileTag(\n stat: { ino: number; ctimeMs: number; size: number },\n now = Date.now(),\n): string | null {\n if (now - stat.ctimeMs < 3000) return null;\n return [stat.ino, stat.ctimeMs, stat.size].map((n) => n.toString(36)).join(\"-\");\n}\n\nexport function createWriteToken(requestToken?: string): string {\n const token = requestToken?.trim();\n return token && token.length <= 200 ? token : randomUUID();\n}\n\n/** Hears the bytes each API write replaced, so a project history can keep a save it never saw. */\nexport function onFileOverwritten(listener: OverwriteListener): () => void {\n overwriteListeners.add(listener);\n return () => overwriteListeners.delete(listener);\n}\n\nexport function recordFileWriteReceipt(\n filePath: string,\n {\n overwrote,\n path,\n version,\n writeToken,\n }: Omit<FileWriteReceipt, \"from\"> & {\n overwrote?: string | Uint8Array;\n },\n): void {\n const receipt = { path, version, writeToken };\n const absPath = realFilePath(filePath);\n if (overwrote !== undefined)\n for (const listener of overwriteListeners) listener(absPath, receipt.version, overwrote);\n const now = Date.now();\n for (const [path, list] of receipts) {\n const live = list.filter((entry) => now - entry.recordedAt < RECEIPT_TTL_MS);\n if (live.length > 0) receipts.set(path, live);\n else receipts.delete(path);\n }\n const from = overwrote === undefined ? undefined : fileContentVersion(overwrote);\n receipts.set(absPath, [\n ...(receipts.get(absPath) ?? []),\n { ...receipt, ...(from && { from }), recordedAt: now },\n ]);\n}\n\nexport function clearFileWriteReceipt(filePath: string, version: string, writeToken: string): void {\n const absPath = realFilePath(filePath);\n const current = (receipts.get(absPath) ?? []).filter(\n (entry) => entry.version !== version || entry.writeToken !== writeToken,\n );\n if (current.length > 0) receipts.set(absPath, current);\n else receipts.delete(absPath);\n}\n\n/**\n * Attach one API write's identity to the watcher echo for its exact bytes.\n *\n * Reading is non-destructive: one watcher event fans out to every open SSE\n * subscriber, and a receipt removed by the first reader leaves the rest seeing\n * an unlabelled change and reloading the preview on Studio's own edit. Only the\n * TTL removes a receipt.\n */\nexport function identifyFileWrite(\n filePath: string,\n expectedVersion: string,\n): FileWriteReceipt | null {\n const receipt = newestReceipt(realFilePath(filePath), expectedVersion);\n if (!receipt) return null;\n const { path, version, writeToken, from } = receipt;\n return { path, version, writeToken, ...(from && { from }) };\n}\n\nfunction newestReceipt(absPath: string, expectedVersion: string): StoredReceipt | undefined {\n const now = Date.now();\n const current = (receipts.get(absPath) ?? []).filter(\n (entry) => now - entry.recordedAt < RECEIPT_TTL_MS,\n );\n if (current.length > 0) receipts.set(absPath, current);\n else receipts.delete(absPath);\n // Newest match, not oldest: identical bytes written twice inside the TTL\n // (undo, retyping a value) share a version, and the older token was already\n // spent by the client on its own echo. The destructive read used to advance\n // past it; scanning from the end keeps that cursor without the eviction.\n let receipt: StoredReceipt | undefined;\n for (let i = current.length - 1; i >= 0 && !receipt; i -= 1) {\n if (current[i]?.version === expectedVersion) receipt = current[i];\n }\n return receipt;\n}\n\n/**\n * @deprecated Renamed to {@link identifyFileWrite}, which despite this alias's\n * name does NOT consume the receipt: one watcher event fans out to every SSE\n * subscriber, so a destructive read left all but the first reloading on Studio's\n * own write. Kept for one release; call `identifyFileWrite` instead.\n */\nexport const consumeFileWriteReceipt = identifyFileWrite;\n\nexport function resetFileWriteReceipts(): void {\n receipts.clear();\n}\n","import { createHash } from \"node:crypto\";\nimport { lstatSync, readFileSync, readdirSync } from \"node:fs\";\nimport { extname, isAbsolute, relative, resolve, sep } from \"node:path\";\nimport { isAtomicTempPath } from \"@hyperframes/core/atomic-file\";\nimport type { ResolvedProject, StudioApiAdapter } from \"../types.js\";\n\nconst SIGNATURE_TEXT_EXTENSIONS = new Set([\n \".cjs\",\n \".css\",\n \".html\",\n \".js\",\n \".json\",\n \".jsx\",\n \".mjs\",\n \".svg\",\n \".ts\",\n \".tsx\",\n]);\nconst SIGNATURE_EXCLUDED_DIRS = new Set([\n \".cache\",\n \".git\",\n \".hyperframes\",\n \".next\",\n \".thumbnails\",\n \".transcode-cache\",\n \".vite\",\n \".waveform-cache\",\n \"build\",\n \"coverage\",\n \"dist\",\n \"node_modules\",\n \"outputs\",\n \"renders\",\n]);\nconst MAX_SIGNATURE_TEXT_BYTES = 2_000_000;\nexport const STUDIO_SIGNATURE_MANIFEST_PATHS = [\n \".hyperframes/studio-manual-edits.json\",\n \".hyperframes/studio-motion.json\",\n] as const;\n\n/**\n * Whether a write at `changedPath` can change `createProjectSignature(projectDir)`.\n *\n * Owned here because it is the exact complement of what the walk below collects,\n * and a second copy of that reasoning drifts the moment either set changes. A\n * watcher that invalidates on everything is not merely wasteful: `.thumbnails/`\n * is written by the thumbnail route on every capture, and each capture reads the\n * preview, so an unfiltered watcher discards the memo on roughly every request of\n * the one workload the memo exists for.\n *\n * Note this is not `WATCHER_EXCLUDED_DIRS`, which is character-identical but\n * excludes all of `.hyperframes/` — the signature deliberately reads two manifest\n * files from inside it, so filtering with that set would stop motion-state saves\n * from ever invalidating.\n *\n * Every segment is tested, not just the parents, so a directory event on an\n * excluded dir itself (`unlinkDir .thumbnails`) is filtered too. The cost is that\n * a *file* literally named `dist` at the project root reads as excluded; the walk\n * would collect it, so it is a false negative, and no real project has one.\n */\nexport function affectsProjectSignature(projectDir: string, changedPath: string): boolean {\n const relativePath = relative(resolve(projectDir), resolve(changedPath));\n if (\n relativePath === \"\" ||\n relativePath.startsWith(\"..\") ||\n isAbsolute(relativePath) ||\n isAtomicTempPath(relativePath)\n ) {\n return false;\n }\n const segments = relativePath.split(sep);\n if (STUDIO_SIGNATURE_MANIFEST_PATHS.includes(segments.join(\"/\") as never)) return true;\n return !segments.some((segment) => SIGNATURE_EXCLUDED_DIRS.has(segment));\n}\n\ninterface ProjectSignatureFile {\n file: string;\n mtimeMs: number;\n ctimeMs: number;\n size: number;\n textContentEligible: boolean;\n}\n\ninterface ProjectSignatureCacheEntry {\n fingerprint: string;\n signature: string;\n}\n\nconst projectSignatureCache = new Map<string, ProjectSignatureCacheEntry>();\nconst COARSEST_FILE_TIME_TICK_MS = 2000;\n\nfunction isPathWithin(parentDir: string, childPath: string): boolean {\n const childRelativePath = relative(parentDir, childPath);\n return (\n childRelativePath === \"\" ||\n (!childRelativePath.startsWith(\"..\") && !isAbsolute(childRelativePath))\n );\n}\n\nfunction isTextContentEligible(file: string, size: number): boolean {\n return (\n SIGNATURE_TEXT_EXTENSIONS.has(extname(file).toLowerCase()) && size <= MAX_SIGNATURE_TEXT_BYTES\n );\n}\n\nconst isSkippedEntry = (entry: string) =>\n SIGNATURE_EXCLUDED_DIRS.has(entry) || isAtomicTempPath(entry);\n\nfunction collectProjectSignatureFiles(\n projectDir: string,\n dir: string,\n files: ProjectSignatureFile[],\n): void {\n let entries: string[];\n try {\n entries = readdirSync(dir).sort();\n } catch {\n return;\n }\n\n for (const entry of entries) {\n if (isSkippedEntry(entry)) continue;\n const file = resolve(dir, entry);\n if (!isPathWithin(projectDir, file)) continue;\n let stat: ReturnType<typeof lstatSync>;\n try {\n stat = lstatSync(file);\n } catch {\n continue;\n }\n if (stat.isSymbolicLink()) continue;\n if (stat.isDirectory()) {\n collectProjectSignatureFiles(projectDir, file, files);\n } else if (stat.isFile()) {\n files.push({\n file,\n mtimeMs: stat.mtimeMs,\n ctimeMs: stat.ctimeMs,\n size: stat.size,\n textContentEligible: isTextContentEligible(file, stat.size),\n });\n }\n }\n}\n\nfunction collectProjectSignatureManifestFiles(\n projectDir: string,\n files: ProjectSignatureFile[],\n): void {\n const seen = new Set(files.map((entry) => entry.file));\n for (const manifestPath of STUDIO_SIGNATURE_MANIFEST_PATHS) {\n const file = resolve(projectDir, manifestPath);\n if (seen.has(file) || !isPathWithin(projectDir, file)) continue;\n let stat: ReturnType<typeof lstatSync>;\n try {\n stat = lstatSync(file);\n } catch {\n continue;\n }\n if (stat.isSymbolicLink() || !stat.isFile()) continue;\n files.push({\n file,\n mtimeMs: stat.mtimeMs,\n ctimeMs: stat.ctimeMs,\n size: stat.size,\n textContentEligible: isTextContentEligible(file, stat.size),\n });\n seen.add(file);\n }\n}\n\nfunction createProjectFingerprint(projectDir: string, files: ProjectSignatureFile[]): string {\n const hash = createHash(\"sha256\");\n for (const entry of files) {\n hash.update(relative(projectDir, entry.file));\n hash.update(\"\\0\");\n hash.update(String(entry.size));\n hash.update(\"\\0\");\n hash.update(String(entry.mtimeMs));\n hash.update(\"\\0\");\n hash.update(String(entry.ctimeMs));\n hash.update(\"\\0\");\n hash.update(entry.textContentEligible ? \"text\" : \"binary\");\n hash.update(\"\\0\");\n }\n return hash.digest(\"hex\").slice(0, 24);\n}\n\nfunction collectProjectFiles(normalizedProjectDir: string): ProjectSignatureFile[] {\n const collected: ProjectSignatureFile[] = [];\n collectProjectSignatureFiles(normalizedProjectDir, normalizedProjectDir, collected);\n collectProjectSignatureManifestFiles(normalizedProjectDir, collected);\n return collected;\n}\n\n/** The files a project is made of (the signature's set: source plus Studio's two manifests), paths with `/`. */\nexport function listProjectFiles(\n projectDir: string,\n): Array<{ path: string; size: number; mtimeMs: number; ctimeMs: number }> {\n const normalizedProjectDir = resolve(projectDir);\n return collectProjectFiles(normalizedProjectDir).map((entry) => ({\n path: relative(normalizedProjectDir, entry.file).split(sep).join(\"/\"),\n size: entry.size,\n mtimeMs: entry.mtimeMs,\n ctimeMs: entry.ctimeMs,\n }));\n}\n\n/**\n * Resolve the project signature through the adapter's cached path when the host\n * provides one (the CLI invalidates its cache from the file watcher), falling\n * back to a direct computation.\n */\nexport function resolveProjectSignature(adapter: StudioApiAdapter, projectDir: string): string {\n return adapter.getProjectSignature?.(projectDir) ?? createProjectSignature(projectDir);\n}\n\n/** The shared route opening: resolve the project (null → caller 404s) with its signature. */\nexport async function resolveProjectAndSignature(\n adapter: StudioApiAdapter,\n projectId: string,\n): Promise<{ project: ResolvedProject; signature: string } | null> {\n const project = await adapter.resolveProject(projectId);\n if (!project) return null;\n return { project, signature: resolveProjectSignature(adapter, project.dir) };\n}\n\n/**\n * Creates a stable preview cache-busting signature for project source plus Studio manifests.\n * `excluding` (project-relative paths) leaves those files out.\n */\nexport function createProjectSignature(\n projectDir: string,\n excluding: ReadonlySet<string> = new Set(),\n): string {\n const normalizedProjectDir = resolve(projectDir);\n const signedAt = Date.now();\n const collected = collectProjectFiles(normalizedProjectDir);\n const files = collected.filter(\n (entry) => !excluding.has(relative(normalizedProjectDir, entry.file).split(sep).join(\"/\")),\n );\n files.sort((a, b) => a.file.localeCompare(b.file));\n\n const fingerprint = createProjectFingerprint(normalizedProjectDir, files);\n const cacheKey = excluding.size\n ? `${normalizedProjectDir}\\0${createHash(\"sha256\")\n .update([...excluding].sort().join(\"\\0\"))\n .digest(\"hex\")}`\n : normalizedProjectDir;\n const cached = projectSignatureCache.get(cacheKey);\n if (cached?.fingerprint === fingerprint) return cached.signature;\n\n const hash = createHash(\"sha256\");\n for (const entry of files) {\n const relativePath = relative(normalizedProjectDir, entry.file);\n hash.update(relativePath);\n hash.update(\"\\0\");\n hash.update(String(entry.size));\n hash.update(\"\\0\");\n if (entry.textContentEligible) {\n try {\n hash.update(readFileSync(entry.file));\n } catch {\n hash.update(String(entry.mtimeMs));\n }\n } else {\n hash.update(String(entry.mtimeMs));\n }\n hash.update(\"\\0\");\n }\n const signature = hash.digest(\"hex\").slice(0, 24);\n const settledATickBeforeSigning = files.every(\n (entry) => Math.max(entry.mtimeMs, entry.ctimeMs) < signedAt - COARSEST_FILE_TIME_TICK_MS,\n );\n if (settledATickBeforeSigning) projectSignatureCache.set(cacheKey, { fingerprint, signature });\n return signature;\n}\n","import { createHash, randomUUID } from \"node:crypto\";\nimport { constants, createReadStream, renameSync } from \"node:fs\";\nimport { copyFile, mkdir, readdir, readFile, rename, rm, stat } from \"node:fs/promises\";\nimport { dirname, join } from \"node:path\";\nimport { atomicTempPath } from \"@hyperframes/core/atomic-file\";\n\n/** File contents stored once by sha256, text and binary alike. */\nexport interface BlobStore {\n /** Copies the file in (a clone where the file system can) and returns the copy's hash. */\n put(absPath: string): Promise<string>;\n has(hash: string): boolean;\n read(hash: string): Promise<Buffer>;\n /** Writes the blob's bytes to `absPath` by clone-or-copy and rename, so a reader never sees half a file. */\n writeTo(hash: string, absPath: string, beforeReplace?: () => void): Promise<void>;\n bytes(): number;\n size(hash: string): number;\n prune(keep: ReadonlySet<string>): Promise<void>;\n}\n\nconst BLOB_HASH = /^[0-9a-f]{64}$/;\n\nasync function hashFile(path: string): Promise<string> {\n const hash = createHash(\"sha256\");\n for await (const chunk of createReadStream(path)) hash.update(chunk);\n return hash.digest(\"hex\");\n}\n\nasync function cloneOrCopy(from: string, to: string, beforeReplace?: () => void): Promise<void> {\n await mkdir(dirname(to), { recursive: true });\n const temp = atomicTempPath(to);\n try {\n await copyFile(from, temp, constants.COPYFILE_FICLONE);\n beforeReplace?.();\n renameSync(temp, to);\n } catch (error) {\n await rm(temp, { force: true });\n throw error;\n }\n}\n\nexport async function openBlobStore(dir: string): Promise<BlobStore> {\n const sizes = new Map<string, number>();\n await mkdir(dir, { recursive: true });\n for (const shard of await readdir(dir))\n for (const hash of await readdir(join(dir, shard)).catch(() => []))\n sizes.set(hash, (await stat(join(dir, shard, hash))).size);\n const pathOf = (hash: string) => {\n // Checked where the path is joined, so no caller can read or write outside the store.\n if (!BLOB_HASH.test(hash)) throw new Error(\"That is not a history blob.\");\n return join(dir, hash.slice(0, 2), hash);\n };\n let total = [...sizes.values()].reduce((sum, size) => sum + size, 0);\n\n return {\n async put(absPath) {\n // Hash the copy, not the source, so a write racing the copy can never file bytes under the wrong hash.\n const temp = join(dir, `incoming-${randomUUID()}`);\n // Recreated if removed while open, so a missing folder is never mistaken for a deleted project file.\n await mkdir(dir, { recursive: true });\n await copyFile(absPath, temp, constants.COPYFILE_FICLONE);\n const hash = await hashFile(temp);\n if (sizes.has(hash)) {\n await rm(temp, { force: true });\n return hash;\n }\n await mkdir(dirname(pathOf(hash)), { recursive: true });\n const size = (await stat(temp)).size;\n await rename(temp, pathOf(hash));\n sizes.set(hash, size);\n total += size;\n return hash;\n },\n has: (hash) => sizes.has(hash),\n read: async (hash) => readFile(pathOf(hash)),\n writeTo: async (hash, absPath, beforeReplace) =>\n cloneOrCopy(pathOf(hash), absPath, beforeReplace),\n bytes: () => total,\n size: (hash) => sizes.get(hash) ?? 0,\n async prune(keep) {\n for (const [hash, size] of sizes) {\n if (keep.has(hash)) continue;\n await rm(pathOf(hash), { force: true });\n sizes.delete(hash);\n total -= size;\n }\n },\n };\n}\n","import { randomUUID } from \"node:crypto\";\nimport { readdirSync, readFileSync, renameSync, statSync, writeFileSync } from \"node:fs\";\nimport { lstat, readdir, rm } from \"node:fs/promises\";\nimport { tmpdir } from \"node:os\";\nimport { dirname, join } from \"node:path\";\nimport { isSafePath } from \"../helpers/safePath.js\";\nimport { ID_PATH, isHistoryId, readId, readRecord } from \"./historyId.js\";\nimport { HistoryBusyError, takeHistoryOwnership } from \"./ownerLock.js\";\n\nconst DAY_MS = 24 * 60 * 60 * 1000;\n/** A gone project's history stays this long after its last use, so a moved project reopened in time keeps it. */\nexport const KEEP_GONE_PROJECT_HISTORY_MS = 14 * DAY_MS;\nconst PRUNED_PREFIX = \".pruned-\";\nconst LAST_PRUNE_FILE = \".last-prune\";\n\ninterface PruneOptions {\n now?: number;\n /** Reports what would go, with the same checks, and removes nothing. */\n dryRun?: boolean;\n /** Projects under this folder are scratch: their history goes as soon as they do. */\n tempDir?: string;\n /** One history that could not be checked or removed; the rest are still pruned. */\n onError?: (error: unknown) => void;\n /** Starts no further history after this long; the rest wait for the next run. */\n budgetMs?: number;\n}\n\nexport interface ProjectHistoryRecord {\n id: string;\n projectDir: string;\n lastUsedMs: number;\n}\n\n/** Every history whose project is still in the folder it was recorded for; reads only. */\nexport function listProjectHistories(historyRoot: string): ProjectHistoryRecord[] {\n return namesIn(historyRoot)\n .filter(isHistoryId)\n .flatMap((id) => {\n const home = join(historyRoot, id);\n const projectDir = readRecord(home)?.dir;\n if (typeof projectDir !== \"string\" || readId(projectDir) !== id) return [];\n return [{ id, projectDir, lastUsedMs: lastUsed(home) }];\n });\n}\n\nfunction namesIn(historyRoot: string): string[] {\n try {\n return readdirSync(historyRoot);\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code === \"ENOENT\") return [];\n throw error;\n }\n}\n\nexport interface PrunedHistory {\n id: string;\n projectDir: string;\n bytes: number;\n}\n\n/** Removes the histories whose project is gone and that no live process holds. */\nexport async function pruneGoneProjectHistories(\n historyRoot: string,\n options: PruneOptions = {},\n): Promise<PrunedHistory[]> {\n return (await pruneWithin(historyRoot, options)).pruned;\n}\n\nasync function pruneWithin(\n historyRoot: string,\n {\n now = Date.now(),\n dryRun = false,\n tempDir = tmpdir(),\n onError = (error) => console.warn(\"[history] could not prune a history:\", error),\n budgetMs = Infinity,\n measure = true,\n }: PruneOptions & { measure?: boolean },\n): Promise<{ pruned: PrunedHistory[]; finished: boolean }> {\n const started = performance.now();\n const names = namesIn(historyRoot);\n const pruned: PrunedHistory[] = [];\n for (const name of names) {\n if (performance.now() - started >= budgetMs) return { pruned, finished: false };\n try {\n const gone = await pruneEntry(historyRoot, name, { now, dryRun, tempDir, measure });\n if (gone) pruned.push(gone);\n } catch (error) {\n onError(error);\n }\n }\n return { pruned, finished: true };\n}\n\nasync function pruneEntry(historyRoot: string, name: string, run: PruneRun) {\n if (name.startsWith(PRUNED_PREFIX)) {\n if (!run.dryRun) await rm(join(historyRoot, name), { recursive: true, force: true });\n return null;\n }\n return isHistoryId(name) ? pruneOne(historyRoot, name, run) : null;\n}\n\ntype PruneRun = { now: number; dryRun: boolean; tempDir: string; measure: boolean };\n\nasync function pruneOne(\n historyRoot: string,\n id: string,\n run: PruneRun,\n): Promise<PrunedHistory | null> {\n const home = join(historyRoot, id);\n if (abandonedProject(home, id, run.now, run.tempDir) === null) return null;\n const release = await takeUnlessBusy(home);\n if (!release) return null;\n let taken: { projectDir: string; trash: string | null } | null;\n try {\n taken = recheckAndMoveAway(historyRoot, id, run);\n } catch (error) {\n release();\n throw error;\n }\n if (!taken?.trash) release();\n if (!taken) return null;\n const bytes = await clearAway(taken.trash, home, run.measure);\n return { id, projectDir: taken.projectDir, bytes };\n}\n\n/** Removes the moved-away history, if any; its size when asked, measured first. */\nasync function clearAway(trash: string | null, home: string, measure: boolean): Promise<number> {\n const bytes = measure ? await bytesIn(trash ?? home) : 0;\n if (trash) await rm(trash, { recursive: true, force: true });\n return bytes;\n}\n\nasync function takeUnlessBusy(home: string): Promise<(() => void) | null> {\n try {\n return await takeHistoryOwnership(home, 0);\n } catch (error) {\n if (error instanceof HistoryBusyError) return null;\n throw error;\n }\n}\n\nfunction recheckAndMoveAway(historyRoot: string, id: string, { now, dryRun, tempDir }: PruneRun) {\n const home = join(historyRoot, id);\n // Re-read under the lock: an open that recorded this project again meanwhile keeps it.\n const projectDir = abandonedProject(home, id, now, tempDir);\n if (projectDir === null) return null;\n if (dryRun) return { projectDir, trash: null };\n // One rename takes the lock along, so an interrupted delete leaves a `.pruned-` folder the next run finishes.\n const trash = join(historyRoot, `${PRUNED_PREFIX}${id}-${randomUUID()}`);\n renameSync(home, trash);\n return { projectDir, trash };\n}\n\n/** The folder a history was recorded for, when that project is gone; null while it may still need its history. */\nfunction abandonedProject(home: string, id: string, now: number, tempDir: string): string | null {\n const record = readRecord(home);\n const dir = record?.dir;\n if (typeof dir !== \"string\") return null;\n if (now - lastUsed(home) < KEEP_GONE_PROJECT_HISTORY_MS && !isSafePath(tempDir, dir)) return null;\n return projectGone(dir, id, record?.dev, tempDir) ? dir : null;\n}\n\nfunction projectGone(dir: string, id: string, dev: unknown, tempDir: string): boolean {\n if (!statSync(join(dir, ID_PATH), { throwIfNoEntry: false }))\n return diskStillHere(dir, dev, tempDir);\n // An id file this version cannot read is refused, never replaced, so its history is still the project's.\n const there = readId(dir);\n return there !== null && there !== id;\n}\n\n/** A project without its id is gone only if the disk that held it is here: an unmounted drive or share keeps it. */\nfunction diskStillHere(dir: string, dev: unknown, tempDir: string): boolean {\n let at = dir;\n let stat = statSync(at, { throwIfNoEntry: false });\n while (!stat) {\n if (dirname(at) === at) return false;\n at = dirname(at);\n stat = statSync(at, { throwIfNoEntry: false });\n }\n if (typeof dev === \"number\") return stat.dev === dev;\n // Recorded before `dev`: a missing folder may sit on an unmounted disk, so only an emptied folder or temp counts.\n return at === dir || isSafePath(tempDir, at);\n}\n\nfunction lastUsed(home: string): number {\n const mtime = (file: string) =>\n statSync(join(home, file), { throwIfNoEntry: false })?.mtimeMs ?? 0;\n return Math.max(mtime(\"project.json\"), mtime(\"log.jsonl\"));\n}\n\nasync function bytesIn(dir: string): Promise<number> {\n let total = 0;\n for (const entry of await readdir(dir, { withFileTypes: true })) {\n const path = join(dir, entry.name);\n total += entry.isDirectory() ? await bytesIn(path) : (await lstat(path)).size;\n }\n return total;\n}\n\nfunction prunedWithinADay(stamp: string, now: number): boolean {\n try {\n const last = Number(readFileSync(stamp, \"utf-8\"));\n return last <= now && now - last < DAY_MS;\n } catch {\n return false;\n }\n}\n\nconst pruning = new Set<string>();\n\n/** Prunes `historyRoot` in the background until one run finishes a day, whichever process opens a history first. */\nexport function pruneGoneProjectHistoriesDaily(\n historyRoot: string,\n now: number,\n { onError, budgetMs }: Pick<PruneOptions, \"onError\" | \"budgetMs\"> = {},\n): void {\n const stamp = join(historyRoot, LAST_PRUNE_FILE);\n if (pruning.has(historyRoot) || prunedWithinADay(stamp, now)) return;\n pruning.add(historyRoot);\n setImmediate(() => {\n pruneWithin(historyRoot, { now, onError, budgetMs, measure: false })\n .then(({ finished }) => finished && writeFileSync(stamp, String(now)))\n .catch((error) => onError?.(error))\n .finally(() => pruning.delete(historyRoot));\n });\n}\n","import { randomUUID } from \"node:crypto\";\nimport { existsSync, mkdirSync, readFileSync, statSync, writeFileSync } from \"node:fs\";\nimport { basename, join, resolve } from \"node:path\";\nimport { replaceFileAtomically } from \"@hyperframes/core/atomic-file\";\nimport { mkdirWithinProject } from \"../helpers/safePath.js\";\n\nexport const ID_PATH = join(\".hyperframes\", \"history-id\");\n/** The only shape minted here; the id is project content and becomes a path, so nothing else is trusted. */\nconst ID_SHAPE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/;\n\nexport const isHistoryId = (name: string) => ID_SHAPE.test(name);\n\nexport function readId(projectDir: string): string | null {\n try {\n const id = readFileSync(join(projectDir, ID_PATH), \"utf-8\").trim();\n return ID_SHAPE.test(id) ? id : null;\n } catch {\n return null;\n }\n}\n\nexport type FolderIdentity = { ino: number; birthtimeMs: number };\n\nexport const sameFolder = (a: FolderIdentity, b: FolderIdentity) =>\n a.ino === b.ino && a.birthtimeMs === b.birthtimeMs;\n\nexport function isRecordedFolder(historyDir: string, folder: FolderIdentity): boolean {\n const was = readRecord(historyDir);\n if (typeof was?.ino === \"number\")\n return sameFolder({ ino: was.ino, birthtimeMs: was.born ?? NaN }, folder);\n const unreadableSo0878KeptTheId = typeof was?.dir !== \"string\";\n if (unreadableSo0878KeptTheId) return true;\n return !isCopyOf0878Folder(was!.dir as string, basename(historyDir), folder);\n}\n\nexport function readRecord(\n historyDir: string,\n): { dir?: unknown; ino?: unknown; born?: number; dev?: unknown } | null {\n try {\n return JSON.parse(readFileSync(join(historyDir, \"project.json\"), \"utf-8\"));\n } catch {\n return null;\n }\n}\n\nfunction isCopyOf0878Folder(recordedDir: string, id: string, folder: FolderIdentity): boolean {\n let there;\n try {\n there = statSync(recordedDir, { throwIfNoEntry: false });\n } catch {\n return false;\n }\n return !!there && !sameFolder(there, folder) && readId(recordedDir) === id;\n}\n\n/**\n * The project's history id, kept in the project so a rename or move keeps its history; only the folder its history\n * was recorded for keeps it (isRecordedFolder). An id file that cannot be read is refused, never replaced.\n */\nexport function projectHistoryId(projectDir: string, historyRoot: string): string {\n const dir = resolve(projectDir);\n const folder = statSync(dir);\n let id = readId(dir);\n if (!id && existsSync(join(dir, ID_PATH)))\n throw new HistoryIdError(\n `${join(dir, ID_PATH)} holds no history id this version can read; move it aside to start anew.`,\n );\n if (\n !id ||\n (existsSync(join(historyRoot, id)) && !isRecordedFolder(join(historyRoot, id), folder))\n ) {\n id = randomUUID();\n mkdirWithinProject(dir, join(dir, \".hyperframes\"));\n writeFileSync(join(dir, ID_PATH), `${id}\\n`);\n }\n recordProject(join(historyRoot, id), dir, folder);\n return id;\n}\n\nexport class HistoryIdError extends Error {\n constructor(message: string) {\n super(message);\n this.name = \"HistoryIdError\";\n }\n}\n\nexport function recordProject(\n historyDir: string,\n dir: string,\n folder: FolderIdentity & { dev: number },\n): void {\n const record = { dir, ino: folder.ino, born: folder.birthtimeMs, dev: folder.dev };\n mkdirSync(historyDir, { recursive: true });\n replaceFileAtomically(join(historyDir, \"project.json\"), JSON.stringify(record), 0o644);\n}\n","import { randomUUID } from \"node:crypto\";\nimport { linkSync, mkdirSync, readFileSync, rmSync, writeFileSync } from \"node:fs\";\nimport { join } from \"node:path\";\n\nexport class HistoryBusyError extends Error {\n constructor(readonly pid: number) {\n super(`This project's history is open in another process (pid ${pid}).`);\n this.name = \"HistoryBusyError\";\n }\n}\n\nfunction alive(pid: number): boolean {\n if (!Number.isInteger(pid) || pid <= 0) return false;\n try {\n process.kill(pid, 0);\n return true;\n } catch (error) {\n return (error as NodeJS.ErrnoException).code === \"EPERM\";\n }\n}\n\n/** The pid in `file`; null when there is no file, NaN when it holds no pid (so it reads as dead). */\nfunction ownerOf(file: string): number | null {\n try {\n const text = readFileSync(file, \"utf-8\");\n return /^\\d+$/.test(text) ? Number(text) : Number.NaN;\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code === \"ENOENT\") return null;\n throw error;\n }\n}\n\n/** Takes `file` if nobody holds it: written aside and linked in, so a reader never sees it without its pid. */\nfunction claim(file: string): boolean {\n const draft = `${file}-${randomUUID()}.tmp`;\n writeFileSync(draft, String(process.pid));\n try {\n linkSync(draft, file);\n return true;\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code !== \"EEXIST\") throw error;\n return false;\n } finally {\n rmSync(draft, { force: true });\n }\n}\n\n/** Removes `file` only while it names this process, so a release never takes a later owner's lock. */\nfunction releaseOwn(file: string): void {\n if (ownerOf(file) === process.pid) rmSync(file, { force: true });\n}\n\n/**\n * Removes a dead owner's lock under an evict lock, re-reading the owner, so a live owner's lock survives. False when\n * another evictor holds it. ponytail: a crashed evictor's lock is cleared unguarded; racing that can give two owners.\n */\nfunction evictDeadOwner(file: string): boolean {\n const evictor = `${file}.evict`;\n if (!claim(evictor)) {\n const holder = ownerOf(evictor);\n if (holder !== null && !alive(holder)) rmSync(evictor, { force: true });\n return false;\n }\n try {\n const pid = ownerOf(file);\n if (pid !== null && !alive(pid)) rmSync(file, { force: true });\n return true;\n } finally {\n releaseOwn(evictor);\n }\n}\n\n/**\n * One process at a time keeps a project's history open (a second opener would fork the log). Waits up to `waitMs`\n * for the owner to close, takes over a dead owner's lock.\n */\nexport async function takeHistoryOwnership(home: string, waitMs: number): Promise<() => void> {\n const file = join(home, \"owner.pid\");\n const deadline = Date.now() + waitMs;\n mkdirSync(home, { recursive: true });\n for (;;) {\n if (claim(file)) {\n let held = true;\n return () => {\n if (held) releaseOwn(file);\n held = false;\n };\n }\n const pid = ownerOf(file);\n if (pid === null) continue;\n if (!alive(pid) && evictDeadOwner(file)) continue;\n if (Date.now() >= deadline) throw new HistoryBusyError(pid);\n await new Promise((settle) => setTimeout(settle, 50));\n }\n}\n","import { closeSync, constants, mkdirSync, openSync, readFileSync, writeSync } from \"node:fs\";\nimport { dirname } from \"node:path\";\nimport { replaceFileAtomically } from \"@hyperframes/core/atomic-file\";\n\nexport interface HistoryWho {\n kind: \"person\" | \"agent\" | \"outside\";\n /** Shown in the History list: \"You\", the agent's name, \"Outside\". */\n name: string;\n}\n\n/** A file's sha256 before and after; null is \"did not exist\", so a create or delete undoes like any edit. */\nexport interface HistoryFileChange {\n path: string;\n before: string | null;\n after: string | null;\n}\n\nexport type HistoryEntrySide = \"before\" | \"after\";\n\nexport interface HistoryEntry {\n id: string;\n who: HistoryWho;\n label: string;\n startedAt: number;\n endedAt: number;\n files: HistoryFileChange[];\n /** Set on an undo: the entry it reverted. Redo is undoing the undo. */\n undoes?: string;\n /** Set on a restore: the point (an entry id, or START) the files were made equal to. */\n restoredTo?: string;\n}\n\n/** The point before the first kept entry. */\nexport const START = \"start\";\n\n/** Path to hash. */\nexport type Manifest = Map<string, string>;\n\nexport interface HistoryLog {\n baseline: Manifest;\n entries: HistoryEntry[];\n pins: Set<string>;\n keepsLedger?: boolean;\n}\n\nexport type LogRecord =\n | { type: \"baseline\"; files: Record<string, string>; keepsLedger?: boolean }\n | { type: \"entry\"; entry: HistoryEntry }\n | { type: \"pin\"; id: string; pinned: boolean };\n\nfunction parseRecord(line: string): LogRecord | null {\n try {\n return JSON.parse(line);\n } catch {\n return null;\n }\n}\n\n/** `onUnreadable` hears of a damaged line; a torn last line (a crash mid-append) is expected and dropped quietly. */\nexport function readLog(file: string, onUnreadable: (line: number) => void): HistoryLog | null {\n let text: string;\n try {\n text = readFileSync(file, \"utf-8\");\n } catch {\n return null;\n }\n const log: HistoryLog = { baseline: new Map(), entries: [], pins: new Set() };\n const lines = text.split(\"\\n\");\n lines.forEach((line, index) => {\n const record = line ? parseRecord(line) : null;\n if (record) applyRecord(log, record);\n else if (line && index < lines.length - 1) onUnreadable(index + 1);\n });\n return log;\n}\n\nfunction applyRecord(log: HistoryLog, record: LogRecord): void {\n if (record.type === \"baseline\") {\n log.baseline = new Map(Object.entries(record.files));\n log.keepsLedger = record.keepsLedger === true;\n } else if (record.type === \"entry\") log.entries.push(record.entry);\n else if (record.pinned) log.pins.add(record.id);\n else log.pins.delete(record.id);\n}\n\n/** Appends `record`, already applied to `log`; a log file that is gone is written whole, so a restart replays it. */\nexport function saveRecord(file: string, log: HistoryLog, record: LogRecord): void {\n let fd: number;\n try {\n // No O_CREAT: an append never creates a log that would lack its baseline.\n fd = openSync(file, constants.O_WRONLY | constants.O_APPEND);\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code !== \"ENOENT\") throw error;\n return writeLog(file, log);\n }\n try {\n writeSync(fd, `${JSON.stringify(record)}\\n`);\n } finally {\n closeSync(fd);\n }\n}\n\nexport function writeLog(file: string, log: HistoryLog): void {\n const records: LogRecord[] = [\n {\n type: \"baseline\",\n files: Object.fromEntries(log.baseline),\n ...(log.keepsLedger && { keepsLedger: true }),\n },\n ...log.entries.map((entry) => ({ type: \"entry\" as const, entry })),\n ...[...log.pins].map((id) => ({ type: \"pin\" as const, id, pinned: true })),\n ];\n mkdirSync(dirname(file), { recursive: true });\n replaceFileAtomically(file, records.map((r) => `${JSON.stringify(r)}\\n`).join(\"\"), 0o644);\n}\n\nfunction applyEntry(manifest: Manifest, entry: HistoryEntry, side: HistoryEntrySide): void {\n for (const file of entry.files) {\n const hash = file[side];\n if (hash === null) manifest.delete(file.path);\n else manifest.set(file.path, hash);\n }\n}\n\n/** The files as they were right after `point`. Null when that point is no longer kept. */\nexport function manifestAt(log: HistoryLog, point: string): Manifest | null {\n return point === START ? new Map(log.baseline) : manifestAround(log, point, \"after\");\n}\n\n/** Entry `id`'s own files as it found (`before`) or left (`after`) them; the rest as earlier entries left them. */\nexport function manifestAround(\n log: HistoryLog,\n id: string,\n side: HistoryEntrySide,\n): Manifest | null {\n const manifest = new Map(log.baseline);\n for (const entry of log.entries) {\n applyEntry(manifest, entry, entry.id === id ? side : \"after\");\n if (entry.id === id) return manifest;\n }\n return null;\n}\n\n/** Entries currently reverted: an undo that is itself in effect reverts its target. */\nexport function undoneIds(entries: readonly HistoryEntry[]): Set<string> {\n const undone = new Set<string>();\n for (let i = entries.length - 1; i >= 0; i -= 1) {\n const entry = entries[i]!;\n if (entry.undoes && !undone.has(entry.id)) undone.add(entry.undoes);\n }\n return undone;\n}\n\n/**\n * What Cmd+Z (back) or Cmd+Shift+Z (forward) reverts for `mine`. Back: the newest change `mine` owns that is still\n * in effect. Forward: the newest of `mine`'s undos still in effect, while `mine` has made no change since.\n */\nexport function stepTarget(\n entries: readonly HistoryEntry[],\n direction: \"back\" | \"forward\",\n mine: (entry: HistoryEntry) => boolean,\n): HistoryEntry | undefined {\n const undone = undoneIds(entries);\n const byId = new Map(entries.map((entry) => [entry.id, entry]));\n const owns = ownerOf(entries, byId, mine);\n const newestFirst = [...entries].reverse();\n if (direction === \"back\")\n return newestFirst.find((entry) => !entry.undoes && !undone.has(entry.id) && owns(entry));\n for (const entry of newestFirst) {\n if (!entry.undoes) {\n if (owns(entry)) return undefined;\n continue;\n }\n const target = byId.get(entry.undoes);\n if (mine(entry) && !undone.has(entry.id) && target && !target.undoes) return entry;\n }\n return undefined;\n}\n\n/** A change is yours to step over if you made it, or your redo is what brought it back. */\nfunction ownerOf(\n entries: readonly HistoryEntry[],\n byId: ReadonlyMap<string, HistoryEntry>,\n mine: (entry: HistoryEntry) => boolean,\n): (entry: HistoryEntry) => boolean {\n const redoneBy = new Map<string, HistoryEntry>();\n for (const entry of entries) {\n const target = entry.undoes ? byId.get(entry.undoes) : undefined;\n if (target?.undoes) redoneBy.set(target.undoes, entry);\n }\n return (entry) => mine(entry) || mine(redoneBy.get(entry.id) ?? entry);\n}\n\n/**\n * Folds the oldest entry into the baseline unless it is pinned. ponytail: an old pin therefore holds everything\n * after it; per-point snapshots would lift that. Returns whether one was folded.\n */\nexport function foldOldest(log: HistoryLog): boolean {\n const oldest = log.entries[0];\n if (!oldest || log.pins.has(oldest.id)) return false;\n applyEntry(log.baseline, oldest, \"after\");\n log.entries.shift();\n return true;\n}\n\n/** Every hash a kept point can still need. */\nexport function referencedHashes(log: HistoryLog, current: Manifest): Set<string> {\n const keep = new Set([...log.baseline.values(), ...current.values()]);\n for (const entry of log.entries)\n for (const file of entry.files) {\n if (file.before) keep.add(file.before);\n if (file.after) keep.add(file.after);\n }\n return keep;\n}\n","import type { ProjectHistory } from \"./projectHistory.js\";\n\ntype Opened = Promise<ProjectHistory | null>;\n\n/** A host's histories, one per project folder, opened on first use; a new project at the path gets its own. */\nexport function historyCache(open: (projectDir: string) => Opened) {\n const histories = new Map<string, Opened>();\n const get = async (projectDir: string): Promise<ProjectHistory | null> => {\n let cached = histories.get(projectDir);\n if (!cached) histories.set(projectDir, (cached = open(projectDir)));\n const opened = await cached;\n if (!opened?.replacedAtPath()) return opened;\n const reopen = () => open(projectDir);\n if (histories.get(projectDir) === cached)\n histories.set(projectDir, opened.close().then(reopen, reopen));\n return get(projectDir);\n };\n return {\n get,\n /** The history if one was opened, without opening it. */\n peek: (projectDir: string) => histories.get(projectDir),\n forget: (projectDir: string) => histories.delete(projectDir),\n closeAll: () =>\n Promise.all(\n [...histories.values()].map((opened) => opened.then((history) => history?.close())),\n ),\n };\n}\n"],"mappings":"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","names":["randomUUID","mkdir","readdir","rm","existsSync","lstatSync","statSync","mkdirSync","readdirSync","readFileSync","rmSync","dirname","isAbsolute","join","relative","resolve","sep","replaceFileAtomically","stat","path","createHash","stat","createHash","randomUUID","randomUUID","readdirSync","readFileSync","renameSync","statSync","writeFileSync","readdir","rm","dirname","join","randomUUID","readFileSync","join","resolve","join","readFileSync","resolve","randomUUID","randomUUID","mkdirSync","readFileSync","writeFileSync","join","join","readdirSync","rm","randomUUID","renameSync","statSync","stat","dirname","readdir","readFileSync","writeFileSync","constants","mkdirSync","readFileSync","dirname","replaceFileAtomically","ownerOf","join","readdir","readdirSync","statSync","resolve","existsSync","relative","sep","randomUUID","mkdir","rm","readFileSync","mkdirSync","replaceFileAtomically","stat","window","entry","lstatSync","rmSync","dirname","isAbsolute"]}
|