1import type { FileTreeBatchOperation } from "@pierre/trees";
2
3function pathDepth(path: string): number {
4 return path.split("/").filter(Boolean).length;
5}
6
7export function buildFileTreePathUpdates(
8 previousPaths: readonly string[],
9 nextPaths: readonly string[],
10): FileTreeBatchOperation[] {
11 const previous = new Set(previousPaths);
12 const next = new Set(nextPaths);
13 const removedDirectoryRoots: string[] = [];
14 const updates: FileTreeBatchOperation[] = [];
15
16 const removedPaths = previousPaths
17 .filter((path) => !next.has(path))
18 .toSorted((left, right) => pathDepth(left) - pathDepth(right));
19 for (const path of removedPaths) {
20 if (removedDirectoryRoots.some((directory) => path.startsWith(directory))) continue;
21 const recursive = path.endsWith("/");
22 updates.push({ type: "remove", path, ...(recursive ? { recursive: true } : {}) });
23 if (recursive) removedDirectoryRoots.push(path);
24 }
25
26 const addedPaths = nextPaths
27 .filter((path) => !previous.has(path))
28 .toSorted((left, right) => pathDepth(left) - pathDepth(right));
29 for (const path of addedPaths) updates.push({ type: "add", path });
30
31 return updates;
32}