mirror of
https://github.com/backnotprop/plannotator.git
synced 2026-09-14 14:17:26 +08:00
195328f7a6
* Persist saved annotate file edits in drafts * Handle stale saved file edit context * Test source edit conflict actions * Return source metadata for single-file docs * Fix saved file edit conflict races * Handle deleted source files in annotate edits * Tighten annotate missing-file recovery * Reset edit state for missing file reopen * Tighten source edit restore path handling * Harden source edit recovery paths * Harden source edit disk reconciliation * Fix live file tree startup delay * Document file tree watcher startup ordering * Preserve source save through missing files and symlinks * Harden missing source file recovery * Tighten annotate source edit boundaries
48 lines
1.5 KiB
TypeScript
48 lines
1.5 KiB
TypeScript
import type { SavedFileChangeDraftData } from './editableDocuments';
|
|
import type { SourceSaveProbeResult } from './sourceDocumentClient';
|
|
|
|
export interface SavedFileChangeValidationResult {
|
|
valid: SavedFileChangeDraftData[];
|
|
dropped: Array<{ change: SavedFileChangeDraftData; reason: 'changed' | 'missing' | 'noop' }>;
|
|
unverified: SavedFileChangeDraftData[];
|
|
}
|
|
|
|
export async function validateSavedFileChanges(
|
|
changes: SavedFileChangeDraftData[],
|
|
resolveSourceSave: (change: SavedFileChangeDraftData) => Promise<SourceSaveProbeResult>,
|
|
): Promise<SavedFileChangeValidationResult> {
|
|
const valid: SavedFileChangeDraftData[] = [];
|
|
const dropped: SavedFileChangeValidationResult['dropped'] = [];
|
|
const unverified: SavedFileChangeDraftData[] = [];
|
|
|
|
for (const change of changes) {
|
|
if (change.beforeText === change.afterText) {
|
|
dropped.push({ change, reason: 'noop' });
|
|
continue;
|
|
}
|
|
|
|
const expectedHash = change.afterHash ?? change.sourceSave.hash;
|
|
const probe = await resolveSourceSave(change);
|
|
if (probe.status === 'unavailable') {
|
|
unverified.push(change);
|
|
continue;
|
|
}
|
|
if (probe.status === 'missing') {
|
|
dropped.push({ change, reason: 'missing' });
|
|
continue;
|
|
}
|
|
if (probe.sourceSave.hash !== expectedHash) {
|
|
dropped.push({ change, reason: 'changed' });
|
|
continue;
|
|
}
|
|
|
|
valid.push({
|
|
...change,
|
|
sourceSave: probe.sourceSave,
|
|
afterHash: probe.sourceSave.hash,
|
|
});
|
|
}
|
|
|
|
return { valid, dropped, unverified };
|
|
}
|