@bendyline/docblocks 1.1.2 → 2.0.0

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.
Files changed (270) hide show
  1. package/README.md +76 -11
  2. package/dist/chunk-2D7Y4IR3.js +1293 -0
  3. package/dist/chunk-2D7Y4IR3.js.map +1 -0
  4. package/dist/chunk-5MYAICRE.js +957 -0
  5. package/dist/chunk-5MYAICRE.js.map +1 -0
  6. package/dist/chunk-75UUF6C4.js +802 -0
  7. package/dist/chunk-75UUF6C4.js.map +1 -0
  8. package/dist/chunk-AEHCVWU5.js +25 -0
  9. package/dist/chunk-AEHCVWU5.js.map +1 -0
  10. package/dist/chunk-AYZ4HN5M.js +20 -0
  11. package/dist/chunk-AYZ4HN5M.js.map +1 -0
  12. package/dist/chunk-EGNDADXB.js +111 -0
  13. package/dist/chunk-EGNDADXB.js.map +1 -0
  14. package/dist/chunk-EZKJZUNJ.js +13 -0
  15. package/dist/chunk-EZKJZUNJ.js.map +1 -0
  16. package/dist/chunk-FNW556FN.js +75 -0
  17. package/dist/chunk-FNW556FN.js.map +1 -0
  18. package/dist/chunk-GCPBEMMH.js +563 -0
  19. package/dist/chunk-GCPBEMMH.js.map +1 -0
  20. package/dist/chunk-J32GU3F3.js +1664 -0
  21. package/dist/chunk-J32GU3F3.js.map +1 -0
  22. package/dist/chunk-PGR7LK6D.js +1062 -0
  23. package/dist/chunk-PGR7LK6D.js.map +1 -0
  24. package/dist/chunk-RQJRQF46.js +787 -0
  25. package/dist/chunk-RQJRQF46.js.map +1 -0
  26. package/dist/{chunk-ME76RUMR.js → chunk-RVQHY3XU.js} +15 -1
  27. package/dist/chunk-RVQHY3XU.js.map +1 -0
  28. package/dist/chunk-SI2LU2RP.js +224 -0
  29. package/dist/chunk-SI2LU2RP.js.map +1 -0
  30. package/dist/chunk-W5UUUII5.js +142 -0
  31. package/dist/chunk-W5UUUII5.js.map +1 -0
  32. package/dist/document/document-session.d.ts +127 -0
  33. package/dist/document/document-session.d.ts.map +1 -0
  34. package/dist/document/document-session.js +749 -0
  35. package/dist/document/document-session.js.map +1 -0
  36. package/dist/document/filesystem-target.d.ts +17 -0
  37. package/dist/document/filesystem-target.d.ts.map +1 -0
  38. package/dist/document/filesystem-target.js +70 -0
  39. package/dist/document/filesystem-target.js.map +1 -0
  40. package/dist/document/index.d.ts +6 -0
  41. package/dist/document/index.d.ts.map +1 -0
  42. package/dist/document/index.js +4 -0
  43. package/dist/document/index.js.map +1 -0
  44. package/dist/document/recovery-journal.d.ts +125 -0
  45. package/dist/document/recovery-journal.d.ts.map +1 -0
  46. package/dist/document/recovery-journal.js +385 -0
  47. package/dist/document/recovery-journal.js.map +1 -0
  48. package/dist/document/types.d.ts +89 -0
  49. package/dist/document/types.d.ts.map +1 -0
  50. package/dist/document/types.js +9 -0
  51. package/dist/document/types.js.map +1 -0
  52. package/dist/filesystem/commit-lock.d.ts +3 -0
  53. package/dist/filesystem/commit-lock.d.ts.map +1 -0
  54. package/dist/filesystem/commit-lock.js +20 -0
  55. package/dist/filesystem/commit-lock.js.map +1 -0
  56. package/dist/filesystem/dbk-workspace.d.ts +34 -0
  57. package/dist/filesystem/dbk-workspace.d.ts.map +1 -0
  58. package/dist/filesystem/dbk-workspace.js +85 -0
  59. package/dist/filesystem/dbk-workspace.js.map +1 -0
  60. package/dist/filesystem/electron-provider-v2.d.ts +36 -0
  61. package/dist/filesystem/electron-provider-v2.d.ts.map +1 -0
  62. package/dist/filesystem/electron-provider-v2.js +503 -0
  63. package/dist/filesystem/electron-provider-v2.js.map +1 -0
  64. package/dist/filesystem/electron-provider.d.ts +6 -3
  65. package/dist/filesystem/electron-provider.d.ts.map +1 -1
  66. package/dist/filesystem/electron-provider.js +18 -13
  67. package/dist/filesystem/electron-provider.js.map +1 -1
  68. package/dist/filesystem/electron.d.ts +4 -0
  69. package/dist/filesystem/electron.d.ts.map +1 -0
  70. package/dist/filesystem/electron.js +4 -0
  71. package/dist/filesystem/electron.js.map +1 -0
  72. package/dist/filesystem/filesystem-content-container.d.ts +1 -1
  73. package/dist/filesystem/filesystem-content-container.d.ts.map +1 -1
  74. package/dist/filesystem/filesystem-content-container.js +50 -13
  75. package/dist/filesystem/filesystem-content-container.js.map +1 -1
  76. package/dist/filesystem/fs-error.d.ts +46 -0
  77. package/dist/filesystem/fs-error.d.ts.map +1 -0
  78. package/dist/filesystem/fs-error.js +170 -0
  79. package/dist/filesystem/fs-error.js.map +1 -0
  80. package/dist/filesystem/index.d.ts +15 -1
  81. package/dist/filesystem/index.d.ts.map +1 -1
  82. package/dist/filesystem/index.js +13 -0
  83. package/dist/filesystem/index.js.map +1 -1
  84. package/dist/filesystem/indexeddb-content-container.d.ts +3 -1
  85. package/dist/filesystem/indexeddb-content-container.d.ts.map +1 -1
  86. package/dist/filesystem/indexeddb-content-container.js +18 -11
  87. package/dist/filesystem/indexeddb-content-container.js.map +1 -1
  88. package/dist/filesystem/indexeddb-provider-v2.d.ts +96 -0
  89. package/dist/filesystem/indexeddb-provider-v2.d.ts.map +1 -0
  90. package/dist/filesystem/indexeddb-provider-v2.js +1241 -0
  91. package/dist/filesystem/indexeddb-provider-v2.js.map +1 -0
  92. package/dist/filesystem/indexeddb-provider.d.ts +21 -14
  93. package/dist/filesystem/indexeddb-provider.d.ts.map +1 -1
  94. package/dist/filesystem/indexeddb-provider.js +111 -261
  95. package/dist/filesystem/indexeddb-provider.js.map +1 -1
  96. package/dist/filesystem/indexeddb-store.d.ts +34 -0
  97. package/dist/filesystem/indexeddb-store.d.ts.map +1 -0
  98. package/dist/filesystem/indexeddb-store.js +165 -0
  99. package/dist/filesystem/indexeddb-store.js.map +1 -0
  100. package/dist/filesystem/indexeddb.d.ts +5 -0
  101. package/dist/filesystem/indexeddb.d.ts.map +1 -0
  102. package/dist/filesystem/indexeddb.js +5 -0
  103. package/dist/filesystem/indexeddb.js.map +1 -0
  104. package/dist/filesystem/legacy-v2-adapter.d.ts +62 -0
  105. package/dist/filesystem/legacy-v2-adapter.d.ts.map +1 -0
  106. package/dist/filesystem/legacy-v2-adapter.js +499 -0
  107. package/dist/filesystem/legacy-v2-adapter.js.map +1 -0
  108. package/dist/filesystem/memory-provider-v2.d.ts +92 -0
  109. package/dist/filesystem/memory-provider-v2.d.ts.map +1 -0
  110. package/dist/filesystem/memory-provider-v2.js +615 -0
  111. package/dist/filesystem/memory-provider-v2.js.map +1 -0
  112. package/dist/filesystem/memory-provider.d.ts +54 -0
  113. package/dist/filesystem/memory-provider.d.ts.map +1 -0
  114. package/dist/filesystem/memory-provider.js +132 -0
  115. package/dist/filesystem/memory-provider.js.map +1 -0
  116. package/dist/filesystem/memory.d.ts +4 -0
  117. package/dist/filesystem/memory.d.ts.map +1 -0
  118. package/dist/filesystem/memory.js +4 -0
  119. package/dist/filesystem/memory.js.map +1 -0
  120. package/dist/filesystem/move-entry.d.ts +9 -0
  121. package/dist/filesystem/move-entry.d.ts.map +1 -0
  122. package/dist/filesystem/move-entry.js +103 -0
  123. package/dist/filesystem/move-entry.js.map +1 -0
  124. package/dist/filesystem/move-error.d.ts +53 -0
  125. package/dist/filesystem/move-error.d.ts.map +1 -0
  126. package/dist/filesystem/move-error.js +99 -0
  127. package/dist/filesystem/move-error.js.map +1 -0
  128. package/dist/filesystem/native-provider-v2.d.ts +75 -0
  129. package/dist/filesystem/native-provider-v2.d.ts.map +1 -0
  130. package/dist/filesystem/native-provider-v2.js +849 -0
  131. package/dist/filesystem/native-provider-v2.js.map +1 -0
  132. package/dist/filesystem/native-provider.d.ts +9 -1
  133. package/dist/filesystem/native-provider.d.ts.map +1 -1
  134. package/dist/filesystem/native-provider.js +172 -37
  135. package/dist/filesystem/native-provider.js.map +1 -1
  136. package/dist/filesystem/native.d.ts +4 -0
  137. package/dist/filesystem/native.d.ts.map +1 -0
  138. package/dist/filesystem/native.js +4 -0
  139. package/dist/filesystem/native.js.map +1 -0
  140. package/dist/filesystem/types.d.ts +37 -4
  141. package/dist/filesystem/types.d.ts.map +1 -1
  142. package/dist/filesystem/types.js +11 -3
  143. package/dist/filesystem/types.js.map +1 -1
  144. package/dist/filesystem/v2.d.ts +172 -0
  145. package/dist/filesystem/v2.d.ts.map +1 -0
  146. package/dist/filesystem/v2.js +16 -0
  147. package/dist/filesystem/v2.js.map +1 -0
  148. package/dist/filesystem/workspace-path.d.ts +21 -0
  149. package/dist/filesystem/workspace-path.d.ts.map +1 -0
  150. package/dist/filesystem/workspace-path.js +80 -0
  151. package/dist/filesystem/workspace-path.js.map +1 -0
  152. package/dist/host/filesystem-v2.d.ts +45 -0
  153. package/dist/host/filesystem-v2.d.ts.map +1 -0
  154. package/dist/host/filesystem-v2.js +13 -0
  155. package/dist/host/filesystem-v2.js.map +1 -0
  156. package/dist/host/git.d.ts +200 -0
  157. package/dist/host/git.d.ts.map +1 -0
  158. package/dist/host/git.js +15 -0
  159. package/dist/host/git.js.map +1 -0
  160. package/dist/host/index.d.ts +4 -1
  161. package/dist/host/index.d.ts.map +1 -1
  162. package/dist/host/index.js +2 -0
  163. package/dist/host/index.js.map +1 -1
  164. package/dist/host/types.d.ts +114 -31
  165. package/dist/host/types.d.ts.map +1 -1
  166. package/dist/host/wire-policy.d.ts +22 -0
  167. package/dist/host/wire-policy.d.ts.map +1 -0
  168. package/dist/host/wire-policy.js +92 -0
  169. package/dist/host/wire-policy.js.map +1 -0
  170. package/dist/index.d.ts +2 -1
  171. package/dist/index.d.ts.map +1 -1
  172. package/dist/index.js +2 -1
  173. package/dist/index.js.map +1 -1
  174. package/dist/mcp/index.d.ts +4 -0
  175. package/dist/mcp/index.d.ts.map +1 -0
  176. package/dist/mcp/index.js +4 -0
  177. package/dist/mcp/index.js.map +1 -0
  178. package/dist/mcp/types.d.ts +466 -0
  179. package/dist/mcp/types.d.ts.map +1 -0
  180. package/dist/mcp/types.js +25 -0
  181. package/dist/mcp/types.js.map +1 -0
  182. package/dist/mcp/wire.d.ts +29 -0
  183. package/dist/mcp/wire.d.ts.map +1 -0
  184. package/dist/mcp/wire.js +1046 -0
  185. package/dist/mcp/wire.js.map +1 -0
  186. package/dist/mcp/zod.d.ts +5763 -0
  187. package/dist/mcp/zod.d.ts.map +1 -0
  188. package/dist/mcp/zod.js +908 -0
  189. package/dist/mcp/zod.js.map +1 -0
  190. package/dist/types-CX893hgH.d.ts +468 -0
  191. package/dist/types-CsX6EN2t.d.ts +301 -0
  192. package/dist/types-eOlt9J7n.d.ts +478 -0
  193. package/dist/vscode/index.d.ts +3 -0
  194. package/dist/vscode/index.d.ts.map +1 -0
  195. package/dist/vscode/index.js +3 -0
  196. package/dist/vscode/index.js.map +1 -0
  197. package/dist/vscode/messages.d.ts +204 -0
  198. package/dist/vscode/messages.d.ts.map +1 -0
  199. package/dist/vscode/messages.js +494 -0
  200. package/dist/vscode/messages.js.map +1 -0
  201. package/dist/workspace/index.d.ts +3 -2
  202. package/dist/workspace/index.d.ts.map +1 -1
  203. package/dist/workspace/index.js +2 -1
  204. package/dist/workspace/index.js.map +1 -1
  205. package/dist/workspace/reconcile-electron.d.ts +19 -0
  206. package/dist/workspace/reconcile-electron.d.ts.map +1 -0
  207. package/dist/workspace/reconcile-electron.js +42 -0
  208. package/dist/workspace/reconcile-electron.js.map +1 -0
  209. package/dist/workspace/types.d.ts +41 -1
  210. package/dist/workspace/types.d.ts.map +1 -1
  211. package/dist/workspace/types.js +0 -4
  212. package/dist/workspace/types.js.map +1 -1
  213. package/dist/workspace/workspace-manager.d.ts +17 -5
  214. package/dist/workspace/workspace-manager.d.ts.map +1 -1
  215. package/dist/workspace/workspace-manager.js +55 -11
  216. package/dist/workspace/workspace-manager.js.map +1 -1
  217. package/dist/workspace-path-CWVrcuPL.d.ts +21 -0
  218. package/package.json +43 -2
  219. package/src/document/document-session.ts +834 -0
  220. package/src/document/filesystem-target.ts +109 -0
  221. package/src/document/index.ts +41 -0
  222. package/src/document/recovery-journal.ts +536 -0
  223. package/src/document/types.ts +116 -0
  224. package/src/filesystem/commit-lock.ts +29 -0
  225. package/src/filesystem/dbk-workspace.ts +135 -0
  226. package/src/filesystem/electron-provider-v2.ts +630 -0
  227. package/src/filesystem/electron-provider.ts +25 -14
  228. package/src/filesystem/electron.ts +3 -0
  229. package/src/filesystem/filesystem-content-container.ts +53 -15
  230. package/src/filesystem/fs-error.ts +234 -0
  231. package/src/filesystem/index.ts +119 -0
  232. package/src/filesystem/indexeddb-content-container.ts +20 -12
  233. package/src/filesystem/indexeddb-provider-v2.ts +1740 -0
  234. package/src/filesystem/indexeddb-provider.ts +126 -300
  235. package/src/filesystem/indexeddb-store.ts +207 -0
  236. package/src/filesystem/indexeddb.ts +12 -0
  237. package/src/filesystem/legacy-v2-adapter.ts +779 -0
  238. package/src/filesystem/memory-provider-v2.ts +896 -0
  239. package/src/filesystem/memory-provider.ts +180 -0
  240. package/src/filesystem/memory.ts +15 -0
  241. package/src/filesystem/move-entry.ts +142 -0
  242. package/src/filesystem/move-error.ts +159 -0
  243. package/src/filesystem/native-provider-v2.ts +1165 -0
  244. package/src/filesystem/native-provider.ts +194 -41
  245. package/src/filesystem/native.ts +16 -0
  246. package/src/filesystem/types.ts +49 -4
  247. package/src/filesystem/v2.ts +231 -0
  248. package/src/filesystem/workspace-path.ts +92 -0
  249. package/src/host/filesystem-v2.ts +104 -0
  250. package/src/host/git.ts +246 -0
  251. package/src/host/index.ts +46 -0
  252. package/src/host/types.ts +155 -34
  253. package/src/host/wire-policy.ts +103 -0
  254. package/src/index.ts +2 -1
  255. package/src/mcp/index.ts +3 -0
  256. package/src/mcp/types.ts +594 -0
  257. package/src/mcp/wire.ts +1280 -0
  258. package/src/mcp/zod.ts +1000 -0
  259. package/src/vscode/index.ts +2 -0
  260. package/src/vscode/messages.ts +704 -0
  261. package/src/workspace/index.ts +8 -1
  262. package/src/workspace/reconcile-electron.ts +65 -0
  263. package/src/workspace/types.ts +39 -1
  264. package/src/workspace/workspace-manager.ts +71 -10
  265. package/dist/chunk-GUNM43XZ.js +0 -63
  266. package/dist/chunk-GUNM43XZ.js.map +0 -1
  267. package/dist/chunk-IM7LCQJ6.js +0 -850
  268. package/dist/chunk-IM7LCQJ6.js.map +0 -1
  269. package/dist/chunk-ME76RUMR.js.map +0 -1
  270. package/dist/index-pgBHBQ9G.d.ts +0 -213
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/filesystem/memory-provider-v2.ts","../src/filesystem/memory-provider.ts"],"sourcesContent":["import { FsError, type FsOperation } from './fs-error.js';\nimport type { FileCommitResult } from './types.js';\nimport {\n parseFileSystemVersion,\n type FileSystemCreateDirectoryOptions,\n type FileSystemDirectorySnapshot,\n type FileSystemEntrySnapshot,\n type FileSystemFileRead,\n type FileSystemFileSnapshot,\n type FileSystemMoveOptions,\n type FileSystemProviderCapabilities,\n type FileSystemProviderV2,\n type FileSystemRemoveOptions,\n type FileSystemRemoveResult,\n type FileSystemSnapshot,\n type FileSystemSnapshotEntry,\n type FileSystemVersion,\n type FileSystemWatchEvent,\n type FileSystemWatchListener,\n type FileSystemWatchOptions,\n type FileSystemWatchSubscription,\n type FileSystemWriteOptions,\n} from './v2.js';\nimport {\n WORKSPACE_ROOT,\n parseWorkspacePath,\n workspacePathBasename,\n workspacePathContains,\n workspacePathDirname,\n type WorkspacePath,\n} from './workspace-path.js';\n\ninterface MemoryEntryBase {\n readonly version: FileSystemVersion;\n readonly lastModified: string;\n}\n\ninterface MemoryFileEntry extends MemoryEntryBase {\n readonly kind: 'file';\n readonly data: ArrayBuffer;\n /** Compatibility metadata only; v2 always treats the payload as bytes. */\n readonly payloadKind: MemoryFilePayloadKind;\n}\n\ninterface MemoryDirectoryEntry extends MemoryEntryBase {\n readonly kind: 'directory';\n}\n\ntype MemoryEntry = MemoryFileEntry | MemoryDirectoryEntry;\n\nexport type MemoryFilePayloadKind = 'text' | 'binary';\n\nexport interface MemoryFileSystemV2StateFile {\n readonly path: WorkspacePath;\n readonly data: ArrayBuffer;\n readonly payloadKind: MemoryFilePayloadKind;\n}\n\nexport interface MemoryFileSystemV2CompatibilityFile {\n readonly data: ArrayBuffer;\n readonly payloadKind: MemoryFilePayloadKind;\n}\n\nexport interface MemoryFileSystemV2State {\n readonly revision: number;\n readonly files: readonly MemoryFileSystemV2StateFile[];\n readonly directories: readonly WorkspacePath[];\n}\n\nexport interface MemoryFileSystemV2ReplacementFile {\n readonly path: WorkspacePath;\n readonly data: ArrayBuffer | Uint8Array;\n readonly payloadKind: MemoryFilePayloadKind;\n}\n\nexport interface MemoryFileSystemV2Replacement {\n readonly files: readonly MemoryFileSystemV2ReplacementFile[];\n readonly directories?: readonly WorkspacePath[];\n}\n\ninterface MemoryWatcher {\n readonly listener: FileSystemWatchListener;\n readonly onError: FileSystemWatchOptions['onError'];\n}\n\ntype MemoryWatchEventInput = FileSystemWatchEvent extends infer Event\n ? Event extends FileSystemWatchEvent\n ? Omit<Event, 'sequence' | 'origin'>\n : never\n : never;\n\nconst MEMORY_CAPABILITIES: FileSystemProviderCapabilities = Object.freeze({\n writeAtomicity: 'process',\n moveAtomicity: 'process',\n snapshotAtomicity: 'process',\n conditionalWrite: 'process',\n recursiveRemove: true,\n watch: true,\n caseSensitivity: 'sensitive',\n symlinkPolicy: 'unsupported',\n durability: 'volatile',\n});\n\n/**\n * Correctness reference for FileSystemProviderV2.\n *\n * Every mutation validates first, stages a fresh map, swaps it once, and only\n * then emits notifications. File buffers are owned by the provider and every\n * read/snapshot returns a defensive copy.\n */\nexport class MemoryFileSystemProviderV2 implements FileSystemProviderV2 {\n public readonly id: string;\n public readonly label: string;\n public readonly capabilities = MEMORY_CAPABILITIES;\n\n private entries: Map<WorkspacePath, MemoryEntry>;\n private readonly watchers = new Set<MemoryWatcher>();\n private readonly subscriptions = new Set<FileSystemWatchSubscription>();\n private readonly pendingEvents: FileSystemWatchEvent[] = [];\n private emittingEvents = false;\n private mutationCounter = 0;\n private eventSequence = 0;\n private treeVersion: FileSystemVersion;\n private disposed = false;\n private disposePromise: Promise<void> | null = null;\n\n public constructor(id: string, label: string) {\n this.id = id;\n this.label = label;\n this.treeVersion = parseFileSystemVersion(`${id}:0`);\n const now = new Date().toISOString();\n this.entries = new Map([\n [WORKSPACE_ROOT, { kind: 'directory', version: this.treeVersion, lastModified: now }],\n ]);\n }\n\n /** Monotonic in-process revision used by synchronous transient-workspace staging. */\n public get mutationRevision(): number {\n return this.mutationCounter;\n }\n\n /** @internal Atomically couple owned bytes to their v1 compatibility kind. */\n public readCompatibilityFile(path: WorkspacePath): MemoryFileSystemV2CompatibilityFile | null {\n this.assertOpen('read');\n const canonical = this.canonical(path);\n const entry = this.entries.get(canonical);\n if (!entry) return null;\n if (entry.kind !== 'file') {\n throw this.error(\n 'type-mismatch',\n 'read',\n canonical,\n 'Expected a file but found a directory.',\n );\n }\n return Object.freeze({ data: entry.data.slice(0), payloadKind: entry.payloadKind });\n }\n\n /** @internal Capture an owned synchronous copy for DBK whole-tree staging. */\n public captureState(): MemoryFileSystemV2State {\n this.assertOpen('snapshot');\n const files: MemoryFileSystemV2StateFile[] = [];\n const directories: WorkspacePath[] = [];\n for (const [path, entry] of [...this.entries].sort(([left], [right]) =>\n compareText(left, right),\n )) {\n if (!path) continue;\n if (entry.kind === 'directory') directories.push(path);\n else {\n files.push(\n Object.freeze({ path, data: entry.data.slice(0), payloadKind: entry.payloadKind }),\n );\n }\n }\n return Object.freeze({\n revision: this.mutationCounter,\n files: Object.freeze(files),\n directories: Object.freeze(directories),\n });\n }\n\n /** @internal Atomically replace a transient workspace after complete validation. */\n public replaceState(replacement: MemoryFileSystemV2Replacement, expectedRevision?: number): void {\n this.assertOpen('write');\n const stagedFiles = new Map<\n WorkspacePath,\n { readonly data: ArrayBuffer; readonly payloadKind: MemoryFilePayloadKind }\n >();\n const stagedDirectories = new Set<WorkspacePath>();\n const explicitDirectories = new Set<WorkspacePath>();\n\n for (const rawDirectory of replacement.directories ?? []) {\n const directory = this.canonicalNonRoot(rawDirectory, 'create-directory');\n if (explicitDirectories.has(directory)) {\n throw this.error(\n 'already-exists',\n 'create-directory',\n directory,\n 'Duplicate replacement directory.',\n );\n }\n explicitDirectories.add(directory);\n stagedDirectories.add(directory);\n addParentPaths(stagedDirectories, directory);\n }\n for (const rawFile of replacement.files) {\n const path = this.canonicalNonRoot(rawFile.path, 'write');\n if (stagedFiles.has(path)) {\n throw this.error('already-exists', 'write', path, 'Duplicate replacement file.');\n }\n if (!isMemoryFilePayloadKind(rawFile.payloadKind)) {\n throw this.error('type-mismatch', 'write', path, 'Invalid replacement payload kind.');\n }\n stagedFiles.set(path, {\n data: copyBytes(rawFile.data),\n payloadKind: rawFile.payloadKind,\n });\n addParentPaths(stagedDirectories, path);\n }\n for (const path of stagedFiles.keys()) {\n if (stagedDirectories.has(path)) {\n throw this.error(\n 'type-mismatch',\n 'write',\n path,\n 'Replacement path has conflicting file and directory kinds.',\n );\n }\n for (const parent of parentChain(path)) {\n if (parent && stagedFiles.has(parent)) {\n throw this.error('type-mismatch', 'write', parent, 'A replacement parent is a file.');\n }\n }\n }\n if (expectedRevision !== undefined && expectedRevision !== this.mutationCounter) {\n throw this.error(\n 'conflict',\n 'write',\n WORKSPACE_ROOT,\n 'Memory filesystem changed while replacement contents were staged.',\n );\n }\n\n const version = this.nextVersion();\n const now = new Date().toISOString();\n const next = new Map<WorkspacePath, MemoryEntry>([\n [WORKSPACE_ROOT, { kind: 'directory', version, lastModified: now }],\n ]);\n this.addDirectories(next, [...stagedDirectories], version, now);\n for (const [path, file] of stagedFiles) {\n next.set(path, {\n kind: 'file',\n data: file.data,\n payloadKind: file.payloadKind,\n version,\n lastModified: now,\n });\n }\n this.entries = next;\n this.emit({\n type: 'overflow',\n kind: null,\n path: WORKSPACE_ROOT,\n destinationPath: null,\n version: null,\n previousVersion: null,\n });\n }\n\n /** @internal Synchronous setup hook used before a transient provider is published. */\n public seedText(path: WorkspacePath, content: string): void {\n this.writeFileNow(path, new TextEncoder().encode(content), { createParents: true }, 'text');\n }\n\n /** @internal Legacy text write that preserves text/binary compatibility metadata. */\n public async writeText(\n path: WorkspacePath,\n content: string,\n options: FileSystemWriteOptions = {},\n ): Promise<FileSystemFileSnapshot> {\n return this.writeFileNow(path, new TextEncoder().encode(content), options, 'text');\n }\n\n /** @internal Legacy binary write that explicitly changes compatibility payload kind. */\n public async writeBinary(\n path: WorkspacePath,\n data: ArrayBuffer | Uint8Array,\n options: FileSystemWriteOptions = {},\n ): Promise<FileSystemFileSnapshot> {\n return this.writeFileNow(path, data, options, 'binary');\n }\n\n /** @internal Atomic legacy compare-and-write over the authoritative v2 entry. */\n public async commitText(\n path: WorkspacePath,\n content: string,\n expectedContent: string | null,\n ): Promise<FileCommitResult> {\n this.assertOpen('write');\n const canonical = this.canonicalNonRoot(path, 'write');\n const existing = this.entries.get(canonical);\n if (existing?.kind === 'directory') {\n throw this.error('type-mismatch', 'write', canonical, 'Cannot replace a directory.');\n }\n const currentContent =\n existing?.kind === 'file' && existing.payloadKind === 'text'\n ? new TextDecoder().decode(existing.data)\n : null;\n if (\n (existing?.kind === 'file' && existing.payloadKind === 'binary') ||\n (currentContent !== expectedContent && currentContent !== content)\n ) {\n return {\n status: 'conflict',\n content: currentContent,\n version: existing?.version ?? null,\n };\n }\n const written = this.writeFileNow(\n canonical,\n new TextEncoder().encode(content),\n { createParents: true, expectedVersion: existing?.version ?? null },\n 'text',\n );\n return { status: 'committed', version: written.version };\n }\n\n public async stat(path: WorkspacePath): Promise<FileSystemEntrySnapshot | null> {\n this.assertOpen('stat');\n const canonical = this.canonical(path);\n const entry = this.entries.get(canonical);\n return entry ? this.toEntrySnapshot(canonical, entry) : null;\n }\n\n public async readFile(path: WorkspacePath): Promise<FileSystemFileRead | null> {\n this.assertOpen('read');\n const canonical = this.canonical(path);\n const entry = this.entries.get(canonical);\n if (!entry) return null;\n if (entry.kind !== 'file') {\n throw this.error(\n 'type-mismatch',\n 'read',\n canonical,\n 'Expected a file but found a directory.',\n );\n }\n return Object.freeze({\n entry: this.toFileSnapshot(canonical, entry),\n data: entry.data.slice(0),\n });\n }\n\n public async readDirectory(path: WorkspacePath): Promise<readonly FileSystemEntrySnapshot[]> {\n this.assertOpen('list');\n const canonical = this.canonical(path);\n const directory = this.entries.get(canonical);\n if (!directory) {\n throw this.error('not-found', 'list', canonical, 'Directory does not exist.');\n }\n if (directory.kind !== 'directory') {\n throw this.error(\n 'type-mismatch',\n 'list',\n canonical,\n 'Expected a directory but found a file.',\n );\n }\n\n const children: FileSystemEntrySnapshot[] = [];\n for (const [entryPath, entry] of this.entries) {\n if (entryPath && workspacePathDirname(entryPath) === canonical) {\n children.push(this.toEntrySnapshot(entryPath, entry));\n }\n }\n children.sort(compareSnapshots);\n return Object.freeze(children);\n }\n\n public async writeFile(\n path: WorkspacePath,\n data: ArrayBuffer | Uint8Array,\n options: FileSystemWriteOptions = {},\n ): Promise<FileSystemFileSnapshot> {\n return this.writeFileNow(path, data, options);\n }\n\n private writeFileNow(\n path: WorkspacePath,\n data: ArrayBuffer | Uint8Array,\n options: FileSystemWriteOptions,\n payloadKind?: MemoryFilePayloadKind,\n ): FileSystemFileSnapshot {\n this.assertOpen('write');\n const canonical = this.canonicalNonRoot(path, 'write');\n const existing = this.entries.get(canonical);\n if (existing?.kind === 'directory') {\n throw this.error(\n 'type-mismatch',\n 'write',\n canonical,\n 'Cannot replace a directory with a file.',\n );\n }\n\n const mode = options.mode ?? 'upsert';\n if (mode === 'create' && existing) {\n throw this.error('already-exists', 'write', canonical, 'File already exists.');\n }\n if (mode === 'replace' && !existing) {\n throw this.error('not-found', 'write', canonical, 'File does not exist.');\n }\n this.assertExpectedVersion(existing, options.expectedVersion, 'write', canonical);\n\n const missingParents = this.planParents(canonical, options.createParents ?? false, 'write');\n const ownedData = copyBytes(data);\n const version = this.nextVersion();\n const now = new Date().toISOString();\n const next = new Map(this.entries);\n this.addDirectories(next, missingParents, version, now);\n next.set(canonical, {\n kind: 'file',\n data: ownedData,\n payloadKind: payloadKind ?? (existing?.kind === 'file' ? existing.payloadKind : 'binary'),\n version,\n lastModified: now,\n });\n this.touchParents(next, canonical, version, now);\n this.entries = next;\n\n for (const directoryPath of missingParents) {\n this.emit({\n type: 'created',\n kind: 'directory',\n path: directoryPath,\n destinationPath: null,\n version,\n previousVersion: null,\n });\n }\n this.emit({\n type: existing ? 'modified' : 'created',\n kind: 'file',\n path: canonical,\n destinationPath: null,\n version,\n previousVersion: existing?.version ?? null,\n });\n return this.toFileSnapshot(canonical, next.get(canonical) as MemoryFileEntry);\n }\n\n public async createDirectory(\n path: WorkspacePath,\n options: FileSystemCreateDirectoryOptions = {},\n ): Promise<FileSystemDirectorySnapshot> {\n this.assertOpen('create-directory');\n const canonical = this.canonical(path);\n const existing = this.entries.get(canonical);\n if (existing) {\n if (existing.kind !== 'directory') {\n throw this.error(\n 'type-mismatch',\n 'create-directory',\n canonical,\n 'Cannot replace a file with a directory.',\n );\n }\n if ((options.mode ?? 'ensure') === 'create') {\n throw this.error(\n 'already-exists',\n 'create-directory',\n canonical,\n 'Directory already exists.',\n );\n }\n return this.toDirectorySnapshot(canonical, existing);\n }\n\n const missingParents = this.planParents(\n canonical,\n options.createParents ?? false,\n 'create-directory',\n );\n const version = this.nextVersion();\n const now = new Date().toISOString();\n const next = new Map(this.entries);\n const created = [...missingParents, canonical];\n this.addDirectories(next, created, version, now);\n this.touchParents(next, canonical, version, now);\n this.entries = next;\n\n for (const directoryPath of created) {\n this.emit({\n type: 'created',\n kind: 'directory',\n path: directoryPath,\n destinationPath: null,\n version,\n previousVersion: null,\n });\n }\n return this.toDirectorySnapshot(canonical, next.get(canonical) as MemoryDirectoryEntry);\n }\n\n public async remove(\n path: WorkspacePath,\n options: FileSystemRemoveOptions = {},\n ): Promise<FileSystemRemoveResult> {\n this.assertOpen('remove');\n const canonical = this.canonicalNonRoot(path, 'remove');\n const existing = this.entries.get(canonical);\n if (!existing) {\n if ((options.missing ?? 'error') === 'ignore') {\n return Object.freeze({ removed: false, version: this.treeVersion });\n }\n throw this.error('not-found', 'remove', canonical, 'Entry does not exist.');\n }\n this.assertExpectedVersion(existing, options.expectedVersion, 'remove', canonical);\n\n const descendants = [...this.entries.keys()].filter((candidate) =>\n workspacePathContains(canonical, candidate, false),\n );\n if (existing.kind === 'directory' && descendants.length > 0 && !options.recursive) {\n throw this.error('not-empty', 'remove', canonical, 'Directory is not empty.');\n }\n\n const version = this.nextVersion();\n const now = new Date().toISOString();\n const next = new Map(this.entries);\n next.delete(canonical);\n if (existing.kind === 'directory') {\n for (const descendant of descendants) next.delete(descendant);\n }\n this.touchParents(next, canonical, version, now);\n this.entries = next;\n\n this.emit({\n type: 'removed',\n kind: existing.kind,\n path: canonical,\n destinationPath: null,\n version: null,\n previousVersion: existing.version,\n });\n return Object.freeze({ removed: true, version });\n }\n\n public async move(\n oldPath: WorkspacePath,\n newPath: WorkspacePath,\n options: FileSystemMoveOptions = {},\n ): Promise<FileSystemEntrySnapshot> {\n this.assertOpen('move');\n const sourcePath = this.canonicalNonRoot(oldPath, 'move');\n const destinationPath = this.canonicalNonRoot(newPath, 'move');\n const source = this.entries.get(sourcePath);\n if (!source) throw this.error('not-found', 'move', sourcePath, 'Source does not exist.');\n this.assertExpectedVersion(source, options.expectedVersion, 'move', sourcePath);\n if (sourcePath === destinationPath) return this.toEntrySnapshot(sourcePath, source);\n if (this.entries.has(destinationPath)) {\n throw new FsError('already-exists', 'Destination already exists.', {\n operation: 'move',\n path: sourcePath,\n destinationPath,\n });\n }\n if (source.kind === 'directory' && workspacePathContains(sourcePath, destinationPath, false)) {\n throw new FsError('invalid-path', 'Cannot move a directory into itself.', {\n operation: 'move',\n path: sourcePath,\n destinationPath,\n });\n }\n\n const missingParents = this.planParents(\n destinationPath,\n options.createParents ?? false,\n 'move',\n );\n const sourcePaths = [...this.entries.keys()].filter((candidate) =>\n workspacePathContains(sourcePath, candidate),\n );\n const sourceSet = new Set(sourcePaths);\n const remapped = sourcePaths.map((currentPath) => {\n const suffix = currentPath.slice(sourcePath.length);\n const target = parseWorkspacePath(`${destinationPath}${suffix}`);\n if (this.entries.has(target) && !sourceSet.has(target)) {\n throw new FsError('already-exists', 'A destination descendant already exists.', {\n operation: 'move',\n path: currentPath,\n destinationPath: target,\n });\n }\n return [currentPath, target] as const;\n });\n\n const version = this.nextVersion();\n const now = new Date().toISOString();\n const next = new Map(this.entries);\n for (const currentPath of sourcePaths) next.delete(currentPath);\n this.addDirectories(next, missingParents, version, now);\n for (const [currentPath, targetPath] of remapped) {\n const current = this.entries.get(currentPath)!;\n next.set(targetPath, this.withVersion(current, version, now));\n }\n this.touchParents(next, sourcePath, version, now);\n this.touchParents(next, destinationPath, version, now);\n this.entries = next;\n\n for (const directoryPath of missingParents) {\n this.emit({\n type: 'created',\n kind: 'directory',\n path: directoryPath,\n destinationPath: null,\n version,\n previousVersion: null,\n });\n }\n this.emit({\n type: 'moved',\n kind: source.kind,\n path: sourcePath,\n destinationPath,\n version,\n previousVersion: source.version,\n });\n return this.toEntrySnapshot(destinationPath, next.get(destinationPath)!);\n }\n\n public async snapshot(): Promise<FileSystemSnapshot> {\n this.assertOpen('snapshot');\n const entries: FileSystemSnapshotEntry[] = [...this.entries.entries()]\n .sort(([left], [right]) => compareText(left, right))\n .map(([path, entry]) => {\n if (entry.kind === 'file') {\n return Object.freeze({ ...this.toFileSnapshot(path, entry), data: entry.data.slice(0) });\n }\n return this.toDirectorySnapshot(path, entry);\n });\n return Object.freeze({ version: this.treeVersion, entries: Object.freeze(entries) });\n }\n\n public watch(\n listener: FileSystemWatchListener,\n options: FileSystemWatchOptions = {},\n ): FileSystemWatchSubscription {\n this.assertOpen('watch');\n const watcher: MemoryWatcher = { listener, onError: options.onError };\n this.watchers.add(watcher);\n let closed = false;\n let disposePromise: Promise<void> | null = null;\n const subscription: FileSystemWatchSubscription = {\n get closed() {\n return closed;\n },\n ready: Promise.resolve(),\n dispose: () => {\n if (disposePromise) return disposePromise;\n closed = true;\n this.watchers.delete(watcher);\n this.subscriptions.delete(subscription);\n disposePromise = Promise.resolve();\n return disposePromise;\n },\n };\n this.subscriptions.add(subscription);\n return subscription;\n }\n\n public dispose(): Promise<void> {\n if (this.disposePromise) return this.disposePromise;\n this.disposed = true;\n this.disposePromise = Promise.all(\n [...this.subscriptions].map((subscription) => subscription.dispose()),\n ).then(() => undefined);\n return this.disposePromise;\n }\n\n private canonical(path: WorkspacePath): WorkspacePath {\n return parseWorkspacePath(path);\n }\n\n private canonicalNonRoot(path: WorkspacePath, operation: FsOperation): WorkspacePath {\n const canonical = this.canonical(path);\n if (!canonical) {\n throw this.error(\n 'invalid-path',\n operation,\n canonical,\n 'The workspace root is not a file entry.',\n );\n }\n return canonical;\n }\n\n private assertOpen(operation: FsOperation): void {\n if (!this.disposed) return;\n throw new FsError('disposed', 'Filesystem provider is disposed.', { operation });\n }\n\n private assertExpectedVersion(\n entry: MemoryEntry | undefined,\n expected: FileSystemVersion | null | undefined,\n operation: FsOperation,\n path: WorkspacePath,\n ): void {\n if (expected === undefined) return;\n if (expected === null ? !entry : entry?.version === expected) return;\n throw this.error(\n 'conflict',\n operation,\n path,\n 'Entry version does not match the expected version.',\n );\n }\n\n private planParents(\n path: WorkspacePath,\n createParents: boolean,\n operation: FsOperation,\n ): WorkspacePath[] {\n const missing: WorkspacePath[] = [];\n for (const parent of parentChain(path)) {\n if (!parent) continue;\n const entry = this.entries.get(parent);\n if (entry?.kind === 'file') {\n throw this.error(\n 'type-mismatch',\n operation,\n parent,\n 'A parent path is a file, not a directory.',\n );\n }\n if (!entry) {\n if (!createParents) {\n throw this.error('not-found', operation, parent, 'Parent directory does not exist.');\n }\n missing.push(parent);\n }\n }\n return missing;\n }\n\n private addDirectories(\n target: Map<WorkspacePath, MemoryEntry>,\n paths: readonly WorkspacePath[],\n version: FileSystemVersion,\n lastModified: string,\n ): void {\n for (const path of paths) {\n target.set(path, { kind: 'directory', version, lastModified });\n }\n }\n\n private touchParents(\n target: Map<WorkspacePath, MemoryEntry>,\n path: WorkspacePath,\n version: FileSystemVersion,\n lastModified: string,\n ): void {\n for (const parent of parentChain(path)) {\n const entry = target.get(parent);\n if (entry?.kind === 'directory') {\n target.set(parent, { kind: 'directory', version, lastModified });\n }\n }\n }\n\n private withVersion(\n entry: MemoryEntry,\n version: FileSystemVersion,\n lastModified: string,\n ): MemoryEntry {\n return entry.kind === 'file'\n ? {\n kind: 'file',\n data: entry.data,\n payloadKind: entry.payloadKind,\n version,\n lastModified,\n }\n : { kind: 'directory', version, lastModified };\n }\n\n private nextVersion(): FileSystemVersion {\n this.mutationCounter += 1;\n this.treeVersion = parseFileSystemVersion(`${this.id}:${this.mutationCounter}`);\n return this.treeVersion;\n }\n\n private toEntrySnapshot(path: WorkspacePath, entry: MemoryEntry): FileSystemEntrySnapshot {\n return entry.kind === 'file'\n ? this.toFileSnapshot(path, entry)\n : this.toDirectorySnapshot(path, entry);\n }\n\n private toFileSnapshot(path: WorkspacePath, entry: MemoryFileEntry): FileSystemFileSnapshot {\n return Object.freeze({\n kind: 'file',\n path,\n name: workspacePathBasename(path),\n size: entry.data.byteLength,\n version: entry.version,\n lastModified: entry.lastModified,\n });\n }\n\n private toDirectorySnapshot(\n path: WorkspacePath,\n entry: MemoryDirectoryEntry,\n ): FileSystemDirectorySnapshot {\n return Object.freeze({\n kind: 'directory',\n path,\n name: workspacePathBasename(path),\n size: null,\n version: entry.version,\n lastModified: entry.lastModified,\n });\n }\n\n private emit(event: MemoryWatchEventInput): void {\n const complete: FileSystemWatchEvent = Object.freeze({\n ...event,\n sequence: ++this.eventSequence,\n origin: 'local',\n });\n this.pendingEvents.push(complete);\n if (this.emittingEvents) return;\n\n this.emittingEvents = true;\n try {\n while (this.pendingEvents.length > 0) {\n const pending = this.pendingEvents.shift();\n if (!pending) continue;\n for (const watcher of [...this.watchers]) {\n try {\n watcher.listener(pending);\n } catch {\n // A watcher is observational; it cannot roll back a completed mutation.\n }\n }\n }\n } finally {\n this.emittingEvents = false;\n }\n }\n\n private error(\n code: ConstructorParameters<typeof FsError>[0],\n operation: FsOperation,\n path: WorkspacePath,\n message: string,\n ): FsError {\n return new FsError(code, message, { operation, path });\n }\n}\n\nfunction parentChain(path: WorkspacePath): WorkspacePath[] {\n const parents: WorkspacePath[] = [];\n let current = workspacePathDirname(path);\n while (true) {\n parents.unshift(current);\n if (!current) return parents;\n current = workspacePathDirname(current);\n }\n}\n\nfunction addParentPaths(target: Set<WorkspacePath>, path: WorkspacePath): void {\n for (const parent of parentChain(path)) {\n if (parent) target.add(parent);\n }\n}\n\nfunction isMemoryFilePayloadKind(value: unknown): value is MemoryFilePayloadKind {\n return value === 'text' || value === 'binary';\n}\n\nfunction copyBytes(data: ArrayBuffer | Uint8Array): ArrayBuffer {\n const source = ArrayBuffer.isView(data)\n ? new Uint8Array(data.buffer, data.byteOffset, data.byteLength)\n : new Uint8Array(data);\n const copy = new Uint8Array(source.byteLength);\n copy.set(source);\n return copy.buffer as ArrayBuffer;\n}\n\nfunction compareSnapshots(left: FileSystemEntrySnapshot, right: FileSystemEntrySnapshot): number {\n if (left.kind !== right.kind) return left.kind === 'directory' ? -1 : 1;\n return compareText(left.name, right.name);\n}\n\nfunction compareText(left: string, right: string): number {\n return left < right ? -1 : left > right ? 1 : 0;\n}\n","/**\n * In-memory filesystem used by transient loose-file and DBK workspaces.\n *\n * MemoryFileSystemProviderV2 is authoritative. This class is the temporary\n * text-oriented v1 facade retained while callers migrate to the byte contract.\n */\n\nimport { FsError, type FsOperation } from './fs-error.js';\nimport {\n MemoryFileSystemProviderV2,\n type MemoryFileSystemV2ReplacementFile,\n} from './memory-provider-v2.js';\nimport type { FileCommitResult, FileSystemEntry, FileSystemProvider, FileMeta } from './types.js';\nimport { parseWorkspacePath, type WorkspacePath } from './workspace-path.js';\n\nexport type MemoryFileSystemSnapshotFile =\n | {\n readonly kind: 'text';\n readonly path: string;\n readonly content: string;\n }\n | {\n readonly kind: 'binary';\n readonly path: string;\n readonly data: ArrayBuffer | Uint8Array;\n };\n\n/** Complete provider-relative state for a transient memory workspace. */\nexport interface MemoryFileSystemSnapshot {\n readonly files: readonly MemoryFileSystemSnapshotFile[];\n readonly directories?: readonly string[];\n}\n\nfunction canonicalPath(path: string): WorkspacePath {\n return parseWorkspacePath(path);\n}\n\nfunction entryPath(path: string, operation: FsOperation): WorkspacePath {\n const canonical = canonicalPath(path);\n if (!canonical) {\n throw new FsError('invalid-path', 'The workspace root is not a file entry.', {\n operation,\n path,\n });\n }\n return canonical;\n}\n\nfunction decode(data: ArrayBuffer): string {\n return new TextDecoder().decode(data);\n}\n\n/**\n * Legacy facade over the correctness-first memory provider.\n *\n * Synchronous seed/snapshot replacement methods remain because DBK import\n * fully stages external bytes before publishing one atomic in-memory swap.\n */\nexport class MemoryFileSystemProvider implements FileSystemProvider {\n public readonly id: string;\n public readonly label: string;\n public readonly v2: MemoryFileSystemProviderV2;\n\n public constructor(id: string, label: string) {\n this.id = id;\n this.label = label;\n this.v2 = new MemoryFileSystemProviderV2(id, label);\n }\n\n /** Monotonic version of the complete in-memory tree. */\n public get treeVersion(): number {\n return this.v2.mutationRevision;\n }\n\n /** Capture an owned deterministic copy of the complete transient tree. */\n public captureContents(): MemoryFileSystemSnapshot {\n const state = this.v2.captureState();\n return {\n files: state.files.map((file) =>\n file.payloadKind === 'text'\n ? { kind: 'text' as const, path: file.path, content: decode(file.data) }\n : { kind: 'binary' as const, path: file.path, data: file.data.slice(0) },\n ),\n directories: [...state.directories],\n };\n }\n\n /** Atomically replace the complete tree after validating and owning all input. */\n public replaceContents(snapshot: MemoryFileSystemSnapshot, expectedTreeVersion?: number): void {\n const files: MemoryFileSystemV2ReplacementFile[] = snapshot.files.map((file) => ({\n path: entryPath(file.path, 'write'),\n payloadKind: file.kind,\n data: file.kind === 'text' ? new TextEncoder().encode(file.content) : file.data,\n }));\n const directories = (snapshot.directories ?? []).map((path) =>\n entryPath(path, 'create-directory'),\n );\n this.v2.replaceState({ files, directories }, expectedTreeVersion);\n }\n\n /** Seed synchronously before publishing a transient provider to consumers. */\n public seedText(path: string, content: string): void {\n this.v2.seedText(entryPath(path, 'write'), content);\n }\n\n public async readFile(path: string): Promise<string | null> {\n const file = await this.v2.readFile(entryPath(path, 'read'));\n return file ? decode(file.data) : null;\n }\n\n public async writeFile(path: string, content: string): Promise<void> {\n await this.v2.writeText(entryPath(path, 'write'), content, { createParents: true });\n }\n\n public commitFile(\n path: string,\n content: string,\n expectedContent: string | null,\n ): Promise<FileCommitResult> {\n return this.v2.commitText(entryPath(path, 'write'), content, expectedContent);\n }\n\n public async delete(path: string): Promise<void> {\n await this.v2.remove(entryPath(path, 'remove'), { recursive: true, missing: 'ignore' });\n }\n\n public async rename(oldPath: string, newPath: string): Promise<void> {\n await this.v2.move(entryPath(oldPath, 'move'), entryPath(newPath, 'move'), {\n createParents: true,\n });\n }\n\n public async readDirectory(path: string): Promise<FileSystemEntry[]> {\n const canonical = canonicalPath(path);\n try {\n const entries = await this.v2.readDirectory(canonical);\n return entries.map((entry) => ({\n kind: entry.kind,\n name: entry.name,\n path: entry.path,\n }));\n } catch (error: unknown) {\n // Preserve the v1 missing-directory behavior only on the compatibility facade.\n if (error instanceof FsError && error.code === 'not-found') return [];\n throw error;\n }\n }\n\n public async exists(path: string): Promise<boolean> {\n return (await this.v2.stat(canonicalPath(path))) !== null;\n }\n\n public async createDirectory(path: string): Promise<void> {\n await this.v2.createDirectory(canonicalPath(path), { createParents: true });\n }\n\n public async stat(path: string): Promise<FileMeta | null> {\n const canonical = canonicalPath(path);\n if (!canonical) return null;\n const entry = await this.v2.stat(canonical);\n if (!entry || entry.kind !== 'file') return null;\n return {\n name: entry.name,\n path: entry.path,\n size: entry.size,\n lastModified: entry.lastModified,\n };\n }\n\n public async readBinary(path: string): Promise<ArrayBuffer | null> {\n const canonical = entryPath(path, 'read');\n const file = this.v2.readCompatibilityFile(canonical);\n if (!file || file.payloadKind !== 'binary') return null;\n return file.data;\n }\n\n public async writeBinary(path: string, data: ArrayBuffer | Uint8Array): Promise<void> {\n await this.v2.writeBinary(entryPath(path, 'write'), data, { createParents: true });\n }\n}\n"],"mappings":"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","names":["entryPath"]}
@@ -1,3 +1,16 @@
1
+ // src/host/filesystem-v2.ts
2
+ var ELECTRON_FILE_SYSTEM_V2_CAPABILITIES = Object.freeze({
3
+ writeAtomicity: "process",
4
+ moveAtomicity: "process",
5
+ snapshotAtomicity: "process",
6
+ conditionalWrite: "process",
7
+ recursiveRemove: true,
8
+ watch: true,
9
+ caseSensitivity: "platform",
10
+ symlinkPolicy: "follow-contained",
11
+ durability: "best-effort"
12
+ });
13
+
1
14
  // src/host/index.ts
2
15
  function isElectronHost() {
3
16
  if (typeof globalThis === "undefined") return false;
@@ -16,8 +29,9 @@ function maybeGetDocBlocksHost() {
16
29
  }
17
30
 
18
31
  export {
32
+ ELECTRON_FILE_SYSTEM_V2_CAPABILITIES,
19
33
  isElectronHost,
20
34
  getDocBlocksHost,
21
35
  maybeGetDocBlocksHost
22
36
  };
23
- //# sourceMappingURL=chunk-ME76RUMR.js.map
37
+ //# sourceMappingURL=chunk-RVQHY3XU.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/host/filesystem-v2.ts","../src/host/index.ts"],"sourcesContent":["import type {\n FileSystemCreateDirectoryOptions,\n FileSystemDirectorySnapshot,\n FileSystemEntrySnapshot,\n FileSystemFileRead,\n FileSystemFileSnapshot,\n FileSystemMoveOptions,\n FileSystemProviderCapabilities,\n FileSystemRemoveOptions,\n FileSystemRemoveResult,\n FileSystemSnapshot,\n FileSystemWatchEvent,\n FileSystemWriteOptions,\n SerializedFsError,\n WorkspacePath,\n} from '../filesystem/index.js';\n\n/** Stable capabilities shared by the Electron v2 client and native backend. */\nexport const ELECTRON_FILE_SYSTEM_V2_CAPABILITIES: FileSystemProviderCapabilities = Object.freeze({\n writeAtomicity: 'process',\n moveAtomicity: 'process',\n snapshotAtomicity: 'process',\n conditionalWrite: 'process',\n recursiveRemove: true,\n watch: true,\n caseSensitivity: 'platform',\n symlinkPolicy: 'follow-contained',\n durability: 'best-effort',\n});\n\n/** Explicit result envelope; Electron does not preserve custom Error fields. */\nexport type HostFileSystemV2Result<T> =\n | { readonly ok: true; readonly value: T }\n | { readonly ok: false; readonly error: SerializedFsError };\n\nexport interface HostFileSystemV2OpenRequest {\n readonly instanceId: string;\n /** Main-owned persisted workspace authority, never an absolute path. */\n readonly providerId: string;\n readonly label: string;\n}\n\nexport type HostFileSystemV2WatchMessage =\n | {\n readonly instanceId: string;\n readonly subscriptionId: string;\n readonly kind: 'event';\n readonly event: FileSystemWatchEvent;\n }\n | {\n readonly instanceId: string;\n readonly subscriptionId: string;\n readonly kind: 'error';\n readonly error: SerializedFsError;\n };\n\n/** Wire-level filesystem v2 API exposed by preload. */\nexport interface DocBlocksHostFsV2API {\n open(\n request: HostFileSystemV2OpenRequest,\n ): Promise<HostFileSystemV2Result<FileSystemProviderCapabilities>>;\n stat(\n instanceId: string,\n path: WorkspacePath,\n ): Promise<HostFileSystemV2Result<FileSystemEntrySnapshot | null>>;\n readFile(\n instanceId: string,\n path: WorkspacePath,\n ): Promise<HostFileSystemV2Result<FileSystemFileRead | null>>;\n readDirectory(\n instanceId: string,\n path: WorkspacePath,\n ): Promise<HostFileSystemV2Result<readonly FileSystemEntrySnapshot[]>>;\n writeFile(\n instanceId: string,\n path: WorkspacePath,\n data: ArrayBuffer | Uint8Array,\n options?: FileSystemWriteOptions,\n ): Promise<HostFileSystemV2Result<FileSystemFileSnapshot>>;\n createDirectory(\n instanceId: string,\n path: WorkspacePath,\n options?: FileSystemCreateDirectoryOptions,\n ): Promise<HostFileSystemV2Result<FileSystemDirectorySnapshot>>;\n remove(\n instanceId: string,\n path: WorkspacePath,\n options?: FileSystemRemoveOptions,\n ): Promise<HostFileSystemV2Result<FileSystemRemoveResult>>;\n move(\n instanceId: string,\n oldPath: WorkspacePath,\n newPath: WorkspacePath,\n options?: FileSystemMoveOptions,\n ): Promise<HostFileSystemV2Result<FileSystemEntrySnapshot>>;\n snapshot(instanceId: string): Promise<HostFileSystemV2Result<FileSystemSnapshot>>;\n watchSubscribe(instanceId: string, subscriptionId: string): Promise<HostFileSystemV2Result<null>>;\n watchUnsubscribe(\n instanceId: string,\n subscriptionId: string,\n ): Promise<HostFileSystemV2Result<null>>;\n dispose(instanceId: string): Promise<HostFileSystemV2Result<null>>;\n onWatchMessage(listener: (message: HostFileSystemV2WatchMessage) => void): () => void;\n}\n","/**\n * Host bridge — shared types + runtime access for the Electron desktop\n * host. The renderer calls `getDocBlocksHost()` to reach the preload\n * contextBridge; `isElectronHost()` gates desktop-only UI branches.\n */\n\nexport type {\n DocBlocksHostAPI,\n DocBlocksHostFsAPI,\n DocBlocksHostExternalAPI,\n DocBlocksHostWorkspacesAPI,\n DocBlocksHostShellAPI,\n DocBlocksHostExportAPI,\n DocBlocksHostFfmpegAPI,\n DocBlocksHostUpdaterAPI,\n DocBlocksHostLifecycleAPI,\n ElectronWorkspaceInfo,\n ExternalBinaryCommitResult,\n HostCloseReason,\n HostEnvironment,\n HostExportTargetGrant,\n HostPrepareCloseRequest,\n HostPrepareCloseResult,\n MenuCommand,\n OpenRequest,\n UpdateInstallResult,\n UpdaterStatus,\n} from './types.js';\n\nexport type {\n DocBlocksHostGitAPI,\n GitBranchInfo,\n GitCapabilities,\n GitCloneHandle,\n GitCloneProgress,\n GitError,\n GitErrorCode,\n GitFileAtRevision,\n GitFileChange,\n GitFileStatusCode,\n GitLogEntry,\n GitLogOptions,\n GitRemoteInfo,\n GitRepoDetection,\n GitResult,\n GitRevision,\n GitStatus,\n} from './git.js';\n\nexport {\n ELECTRON_FILE_SYSTEM_V2_CAPABILITIES,\n type DocBlocksHostFsV2API,\n type HostFileSystemV2OpenRequest,\n type HostFileSystemV2Result,\n type HostFileSystemV2WatchMessage,\n} from './filesystem-v2.js';\n\nexport {\n HOST_WIRE_LIMITS,\n isBoundedBytePayload,\n isBoundedString,\n isTrustedRendererUrl,\n parseExternalHttpUrl,\n parseOpenRequest,\n} from './wire-policy.js';\n\nimport type { DocBlocksHostAPI } from './types.js';\n\n/** True when running inside the Electron desktop shell. */\nexport function isElectronHost(): boolean {\n if (typeof globalThis === 'undefined') return false;\n const host = (globalThis as { docBlocksHost?: unknown }).docBlocksHost;\n return (\n typeof host === 'object' &&\n host !== null &&\n typeof (host as { fs?: unknown }).fs === 'object' &&\n (host as { fs?: unknown }).fs !== null\n );\n}\n\n/** Return the host API, or throw if not running under Electron. */\nexport function getDocBlocksHost(): DocBlocksHostAPI {\n const host = (globalThis as { docBlocksHost?: DocBlocksHostAPI }).docBlocksHost;\n if (!host) {\n throw new Error('docBlocksHost is not available — not running under Electron?');\n }\n return host;\n}\n\n/** Return the host API, or null if not running under Electron. */\nexport function maybeGetDocBlocksHost(): DocBlocksHostAPI | null {\n return (globalThis as { docBlocksHost?: DocBlocksHostAPI }).docBlocksHost ?? null;\n}\n"],"mappings":";AAkBO,IAAM,uCAAuE,OAAO,OAAO;AAAA,EAChG,gBAAgB;AAAA,EAChB,eAAe;AAAA,EACf,mBAAmB;AAAA,EACnB,kBAAkB;AAAA,EAClB,iBAAiB;AAAA,EACjB,OAAO;AAAA,EACP,iBAAiB;AAAA,EACjB,eAAe;AAAA,EACf,YAAY;AACd,CAAC;;;ACyCM,SAAS,iBAA0B;AACxC,MAAI,OAAO,eAAe,YAAa,QAAO;AAC9C,QAAM,OAAQ,WAA2C;AACzD,SACE,OAAO,SAAS,YAChB,SAAS,QACT,OAAQ,KAA0B,OAAO,YACxC,KAA0B,OAAO;AAEtC;AAGO,SAAS,mBAAqC;AACnD,QAAM,OAAQ,WAAoD;AAClE,MAAI,CAAC,MAAM;AACT,UAAM,IAAI,MAAM,mEAA8D;AAAA,EAChF;AACA,SAAO;AACT;AAGO,SAAS,wBAAiD;AAC/D,SAAQ,WAAoD,iBAAiB;AAC/E;","names":[]}
@@ -0,0 +1,224 @@
1
+ // src/filesystem/fs-error.ts
2
+ var FS_ERROR_CODES = /* @__PURE__ */ new Set([
3
+ "invalid-path",
4
+ "path-escape",
5
+ "not-found",
6
+ "already-exists",
7
+ "type-mismatch",
8
+ "not-empty",
9
+ "permission-denied",
10
+ "conflict",
11
+ "quota-exceeded",
12
+ "not-supported",
13
+ "busy",
14
+ "disposed",
15
+ "closed",
16
+ "aborted",
17
+ "io"
18
+ ]);
19
+ var FS_OPERATIONS = /* @__PURE__ */ new Set([
20
+ "parse-path",
21
+ "read",
22
+ "stat",
23
+ "list",
24
+ "write",
25
+ "create-directory",
26
+ "remove",
27
+ "move",
28
+ "snapshot",
29
+ "watch",
30
+ "dispose"
31
+ ]);
32
+ var FsError = class extends Error {
33
+ constructor(code, message, context = {}) {
34
+ super(message);
35
+ this.name = "FsError";
36
+ this.code = code;
37
+ this.operation = context.operation ?? null;
38
+ this.path = context.path ?? null;
39
+ this.destinationPath = context.destinationPath ?? null;
40
+ this.retryable = context.retryable ?? (code === "io" || code === "aborted" || code === "busy");
41
+ }
42
+ toJSON() {
43
+ return {
44
+ name: "FsError",
45
+ code: this.code,
46
+ message: this.message,
47
+ operation: this.operation,
48
+ path: this.path,
49
+ destinationPath: this.destinationPath,
50
+ retryable: this.retryable
51
+ };
52
+ }
53
+ };
54
+ function mapDomExceptionToFsErrorCode(name) {
55
+ switch (name) {
56
+ case "NotFoundError":
57
+ return "not-found";
58
+ case "ConstraintError":
59
+ return "already-exists";
60
+ case "TypeMismatchError":
61
+ return "type-mismatch";
62
+ case "InvalidModificationError":
63
+ return "not-empty";
64
+ case "NotAllowedError":
65
+ case "SecurityError":
66
+ case "NoModificationAllowedError":
67
+ return "permission-denied";
68
+ case "QuotaExceededError":
69
+ return "quota-exceeded";
70
+ case "NotSupportedError":
71
+ return "not-supported";
72
+ case "InvalidStateError":
73
+ return "disposed";
74
+ case "AbortError":
75
+ return "aborted";
76
+ default:
77
+ return "io";
78
+ }
79
+ }
80
+ function mapNodeErrorCodeToFsErrorCode(code) {
81
+ switch (code) {
82
+ case "ENOENT":
83
+ return "not-found";
84
+ case "ENOTDIR":
85
+ return "type-mismatch";
86
+ case "EEXIST":
87
+ return "already-exists";
88
+ case "EISDIR":
89
+ return "type-mismatch";
90
+ case "ENOTEMPTY":
91
+ return "not-empty";
92
+ case "EACCES":
93
+ case "EPERM":
94
+ return "permission-denied";
95
+ case "ENOSPC":
96
+ case "EDQUOT":
97
+ return "quota-exceeded";
98
+ case "EBUSY":
99
+ return "busy";
100
+ case "EXDEV":
101
+ case "ENOTSUP":
102
+ case "EOPNOTSUPP":
103
+ return "not-supported";
104
+ default:
105
+ return "io";
106
+ }
107
+ }
108
+ function isSerializedFsError(value) {
109
+ if (!value || typeof value !== "object") return false;
110
+ const candidate = value;
111
+ return candidate.name === "FsError" && typeof candidate.code === "string" && FS_ERROR_CODES.has(candidate.code) && typeof candidate.message === "string" && (candidate.operation === null || typeof candidate.operation === "string" && FS_OPERATIONS.has(candidate.operation)) && (candidate.path === null || typeof candidate.path === "string") && (candidate.destinationPath === null || typeof candidate.destinationPath === "string") && typeof candidate.retryable === "boolean";
112
+ }
113
+ function deserializeFsError(value) {
114
+ return new FsError(value.code, value.message, {
115
+ operation: value.operation ?? void 0,
116
+ path: value.path ?? void 0,
117
+ destinationPath: value.destinationPath ?? void 0,
118
+ retryable: value.retryable
119
+ });
120
+ }
121
+ function fsErrorFromUnknown(error, context = {}) {
122
+ if (error instanceof FsError) return error;
123
+ if (isSerializedFsError(error)) return deserializeFsError(error);
124
+ const name = getErrorStringField(error, "name");
125
+ const nodeCode = getErrorStringField(error, "code");
126
+ const message = getErrorStringField(error, "message") ?? String(error);
127
+ const code = context.defaultCode ?? (nodeCode ? mapNodeErrorCodeToFsErrorCode(nodeCode) : name ? mapDomExceptionToFsErrorCode(name) : "io");
128
+ return new FsError(code, message, context);
129
+ }
130
+ function serializeFsError(error, context = {}) {
131
+ return fsErrorFromUnknown(error, context).toJSON();
132
+ }
133
+ function isQuotaExceededError(error) {
134
+ if (error instanceof FsError) return error.code === "quota-exceeded";
135
+ if (isSerializedFsError(error)) return error.code === "quota-exceeded";
136
+ return getErrorStringField(error, "name") === "QuotaExceededError";
137
+ }
138
+ function getErrorStringField(error, key) {
139
+ if (!error || typeof error !== "object") return null;
140
+ const value = error[key];
141
+ return typeof value === "string" ? value : null;
142
+ }
143
+
144
+ // src/filesystem/workspace-path.ts
145
+ var WORKSPACE_ROOT = "";
146
+ function parseWorkspacePath(input) {
147
+ if ([...input].some((character) => {
148
+ const codePoint = character.codePointAt(0) ?? 0;
149
+ return codePoint <= 31 || codePoint === 127;
150
+ })) {
151
+ throw invalidPath(input, "Workspace paths must not contain NUL or other control characters.");
152
+ }
153
+ if (/^[a-zA-Z]:/u.test(input)) {
154
+ throw new FsError("path-escape", "Workspace paths must not be OS drive-qualified paths.", {
155
+ operation: "parse-path",
156
+ path: input
157
+ });
158
+ }
159
+ const normalized = input.replace(/\\/g, "/").replace(/\/+/g, "/").replace(/^\/|\/$/g, "");
160
+ if (!normalized) return WORKSPACE_ROOT;
161
+ const segments = normalized.split("/");
162
+ if (segments.some((segment) => segment === "." || segment === "..")) {
163
+ throw new FsError("path-escape", 'Workspace paths must not contain "." or ".." segments.', {
164
+ operation: "parse-path",
165
+ path: input
166
+ });
167
+ }
168
+ return normalized;
169
+ }
170
+ function tryParseWorkspacePath(input) {
171
+ if (typeof input !== "string") return null;
172
+ try {
173
+ return parseWorkspacePath(input);
174
+ } catch {
175
+ return null;
176
+ }
177
+ }
178
+ function workspacePathToLegacy(path) {
179
+ return path ? `/${path}` : "/";
180
+ }
181
+ function workspacePathJoin(parent, child) {
182
+ const childPath = parseWorkspacePath(child);
183
+ if (!parent) return childPath;
184
+ if (!childPath) return parent;
185
+ return parseWorkspacePath(`${parent}/${childPath}`);
186
+ }
187
+ function workspacePathDirname(path) {
188
+ if (!path) return WORKSPACE_ROOT;
189
+ const slash = path.lastIndexOf("/");
190
+ return slash < 0 ? WORKSPACE_ROOT : path.slice(0, slash);
191
+ }
192
+ function workspacePathBasename(path) {
193
+ if (!path) return "";
194
+ const slash = path.lastIndexOf("/");
195
+ return slash < 0 ? path : path.slice(slash + 1);
196
+ }
197
+ function workspacePathContains(parent, candidate, inclusive = true) {
198
+ if (parent === candidate) return inclusive;
199
+ if (!parent) return candidate !== WORKSPACE_ROOT;
200
+ return candidate.startsWith(`${parent}/`);
201
+ }
202
+ function invalidPath(path, message) {
203
+ return new FsError("invalid-path", message, { operation: "parse-path", path });
204
+ }
205
+
206
+ export {
207
+ FsError,
208
+ mapDomExceptionToFsErrorCode,
209
+ mapNodeErrorCodeToFsErrorCode,
210
+ isSerializedFsError,
211
+ deserializeFsError,
212
+ fsErrorFromUnknown,
213
+ serializeFsError,
214
+ isQuotaExceededError,
215
+ WORKSPACE_ROOT,
216
+ parseWorkspacePath,
217
+ tryParseWorkspacePath,
218
+ workspacePathToLegacy,
219
+ workspacePathJoin,
220
+ workspacePathDirname,
221
+ workspacePathBasename,
222
+ workspacePathContains
223
+ };
224
+ //# sourceMappingURL=chunk-SI2LU2RP.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/filesystem/fs-error.ts","../src/filesystem/workspace-path.ts"],"sourcesContent":["/** Stable error codes shared by every filesystem transport and backend. */\nexport type FsErrorCode =\n | 'invalid-path'\n | 'path-escape'\n | 'not-found'\n | 'already-exists'\n | 'type-mismatch'\n | 'not-empty'\n | 'permission-denied'\n | 'conflict'\n | 'quota-exceeded'\n | 'not-supported'\n | 'busy'\n | 'disposed'\n | 'closed'\n | 'aborted'\n | 'io';\n\nexport type FsOperation =\n | 'parse-path'\n | 'read'\n | 'stat'\n | 'list'\n | 'write'\n | 'create-directory'\n | 'remove'\n | 'move'\n | 'snapshot'\n | 'watch'\n | 'dispose';\n\n/** Plain-data form safe to send over IPC, postMessage, or JSON. */\nexport interface SerializedFsError {\n readonly name: 'FsError';\n readonly code: FsErrorCode;\n readonly message: string;\n readonly operation: FsOperation | null;\n readonly path: string | null;\n readonly destinationPath: string | null;\n readonly retryable: boolean;\n}\n\nexport interface FsErrorContext {\n readonly operation?: FsOperation;\n readonly path?: string;\n readonly destinationPath?: string;\n readonly retryable?: boolean;\n readonly defaultCode?: FsErrorCode;\n}\n\nconst FS_ERROR_CODES: ReadonlySet<string> = new Set<FsErrorCode>([\n 'invalid-path',\n 'path-escape',\n 'not-found',\n 'already-exists',\n 'type-mismatch',\n 'not-empty',\n 'permission-denied',\n 'conflict',\n 'quota-exceeded',\n 'not-supported',\n 'busy',\n 'disposed',\n 'closed',\n 'aborted',\n 'io',\n]);\n\nconst FS_OPERATIONS: ReadonlySet<string> = new Set<FsOperation>([\n 'parse-path',\n 'read',\n 'stat',\n 'list',\n 'write',\n 'create-directory',\n 'remove',\n 'move',\n 'snapshot',\n 'watch',\n 'dispose',\n]);\n\n/** Error with a stable code and a deliberately serializable public shape. */\nexport class FsError extends Error {\n public readonly code: FsErrorCode;\n public readonly operation: FsOperation | null;\n public readonly path: string | null;\n public readonly destinationPath: string | null;\n public readonly retryable: boolean;\n\n public constructor(code: FsErrorCode, message: string, context: FsErrorContext = {}) {\n super(message);\n this.name = 'FsError';\n this.code = code;\n this.operation = context.operation ?? null;\n this.path = context.path ?? null;\n this.destinationPath = context.destinationPath ?? null;\n this.retryable = context.retryable ?? (code === 'io' || code === 'aborted' || code === 'busy');\n }\n\n public toJSON(): SerializedFsError {\n return {\n name: 'FsError',\n code: this.code,\n message: this.message,\n operation: this.operation,\n path: this.path,\n destinationPath: this.destinationPath,\n retryable: this.retryable,\n };\n }\n}\n\nexport function mapDomExceptionToFsErrorCode(name: string): FsErrorCode {\n switch (name) {\n case 'NotFoundError':\n return 'not-found';\n case 'ConstraintError':\n return 'already-exists';\n case 'TypeMismatchError':\n return 'type-mismatch';\n case 'InvalidModificationError':\n return 'not-empty';\n case 'NotAllowedError':\n case 'SecurityError':\n case 'NoModificationAllowedError':\n return 'permission-denied';\n case 'QuotaExceededError':\n return 'quota-exceeded';\n case 'NotSupportedError':\n return 'not-supported';\n case 'InvalidStateError':\n return 'disposed';\n case 'AbortError':\n return 'aborted';\n default:\n return 'io';\n }\n}\n\nexport function mapNodeErrorCodeToFsErrorCode(code: string): FsErrorCode {\n switch (code) {\n case 'ENOENT':\n return 'not-found';\n case 'ENOTDIR':\n return 'type-mismatch';\n case 'EEXIST':\n return 'already-exists';\n case 'EISDIR':\n return 'type-mismatch';\n case 'ENOTEMPTY':\n return 'not-empty';\n case 'EACCES':\n case 'EPERM':\n return 'permission-denied';\n case 'ENOSPC':\n case 'EDQUOT':\n return 'quota-exceeded';\n case 'EBUSY':\n return 'busy';\n case 'EXDEV':\n case 'ENOTSUP':\n case 'EOPNOTSUPP':\n return 'not-supported';\n default:\n return 'io';\n }\n}\n\nexport function isSerializedFsError(value: unknown): value is SerializedFsError {\n if (!value || typeof value !== 'object') return false;\n const candidate = value as Partial<Record<keyof SerializedFsError, unknown>>;\n return (\n candidate.name === 'FsError' &&\n typeof candidate.code === 'string' &&\n FS_ERROR_CODES.has(candidate.code) &&\n typeof candidate.message === 'string' &&\n (candidate.operation === null ||\n (typeof candidate.operation === 'string' && FS_OPERATIONS.has(candidate.operation))) &&\n (candidate.path === null || typeof candidate.path === 'string') &&\n (candidate.destinationPath === null || typeof candidate.destinationPath === 'string') &&\n typeof candidate.retryable === 'boolean'\n );\n}\n\nexport function deserializeFsError(value: SerializedFsError): FsError {\n return new FsError(value.code, value.message, {\n operation: value.operation ?? undefined,\n path: value.path ?? undefined,\n destinationPath: value.destinationPath ?? undefined,\n retryable: value.retryable,\n });\n}\n\nexport function fsErrorFromUnknown(error: unknown, context: FsErrorContext = {}): FsError {\n if (error instanceof FsError) return error;\n if (isSerializedFsError(error)) return deserializeFsError(error);\n\n const name = getErrorStringField(error, 'name');\n const nodeCode = getErrorStringField(error, 'code');\n const message = getErrorStringField(error, 'message') ?? String(error);\n const code =\n context.defaultCode ??\n (nodeCode\n ? mapNodeErrorCodeToFsErrorCode(nodeCode)\n : name\n ? mapDomExceptionToFsErrorCode(name)\n : 'io');\n return new FsError(code, message, context);\n}\n\nexport function serializeFsError(error: unknown, context: FsErrorContext = {}): SerializedFsError {\n return fsErrorFromUnknown(error, context).toJSON();\n}\n\n/**\n * True when a storage backend rejected an operation because the origin or\n * device is out of space. Covers typed `FsError`s (`'quota-exceeded'`, from\n * DOMException `QuotaExceededError` or Node `ENOSPC`/`EDQUOT`), serialized\n * transport copies, and raw DOMExceptions from backends that do not wrap\n * their errors (e.g. the File System Access API) — including cross-realm\n * instances where `instanceof DOMException` would fail.\n */\nexport function isQuotaExceededError(error: unknown): boolean {\n if (error instanceof FsError) return error.code === 'quota-exceeded';\n if (isSerializedFsError(error)) return error.code === 'quota-exceeded';\n return getErrorStringField(error, 'name') === 'QuotaExceededError';\n}\n\nfunction getErrorStringField(error: unknown, key: 'name' | 'message' | 'code'): string | null {\n if (!error || typeof error !== 'object') return null;\n const value = (error as Record<string, unknown>)[key];\n return typeof value === 'string' ? value : null;\n}\n","import { FsError } from './fs-error.js';\n\ndeclare const workspacePathBrand: unique symbol;\n\n/** Canonical, root-relative, forward-slash path within one workspace. */\nexport type WorkspacePath = string & { readonly [workspacePathBrand]: 'WorkspacePath' };\n\nexport const WORKSPACE_ROOT = '' as WorkspacePath;\n\n/**\n * Parse a legacy/user path into its one canonical workspace representation.\n * Leading/trailing and repeated separators are normalized; traversal and NUL\n * segments are rejected rather than resolved.\n */\nexport function parseWorkspacePath(input: string): WorkspacePath {\n if (\n [...input].some((character) => {\n const codePoint = character.codePointAt(0) ?? 0;\n return codePoint <= 0x1f || codePoint === 0x7f;\n })\n ) {\n throw invalidPath(input, 'Workspace paths must not contain NUL or other control characters.');\n }\n if (/^[a-zA-Z]:/u.test(input)) {\n throw new FsError('path-escape', 'Workspace paths must not be OS drive-qualified paths.', {\n operation: 'parse-path',\n path: input,\n });\n }\n\n const normalized = input\n .replace(/\\\\/g, '/')\n .replace(/\\/+/g, '/')\n .replace(/^\\/|\\/$/g, '');\n if (!normalized) return WORKSPACE_ROOT;\n\n const segments = normalized.split('/');\n if (segments.some((segment) => segment === '.' || segment === '..')) {\n throw new FsError('path-escape', 'Workspace paths must not contain \".\" or \"..\" segments.', {\n operation: 'parse-path',\n path: input,\n });\n }\n return normalized as WorkspacePath;\n}\n\nexport function tryParseWorkspacePath(input: unknown): WorkspacePath | null {\n if (typeof input !== 'string') return null;\n try {\n return parseWorkspacePath(input);\n } catch {\n return null;\n }\n}\n\n/** Convert a canonical path to the slash-prefixed form accepted by v1 providers. */\nexport function workspacePathToLegacy(path: WorkspacePath): string {\n return path ? `/${path}` : '/';\n}\n\nexport function workspacePathJoin(parent: WorkspacePath, child: string): WorkspacePath {\n const childPath = parseWorkspacePath(child);\n if (!parent) return childPath;\n if (!childPath) return parent;\n return parseWorkspacePath(`${parent}/${childPath}`);\n}\n\nexport function workspacePathDirname(path: WorkspacePath): WorkspacePath {\n if (!path) return WORKSPACE_ROOT;\n const slash = path.lastIndexOf('/');\n return slash < 0 ? WORKSPACE_ROOT : (path.slice(0, slash) as WorkspacePath);\n}\n\nexport function workspacePathBasename(path: WorkspacePath): string {\n if (!path) return '';\n const slash = path.lastIndexOf('/');\n return slash < 0 ? path : path.slice(slash + 1);\n}\n\nexport function workspacePathContains(\n parent: WorkspacePath,\n candidate: WorkspacePath,\n inclusive = true,\n): boolean {\n if (parent === candidate) return inclusive;\n if (!parent) return candidate !== WORKSPACE_ROOT;\n return candidate.startsWith(`${parent}/`);\n}\n\nfunction invalidPath(path: string, message: string): FsError {\n return new FsError('invalid-path', message, { operation: 'parse-path', path });\n}\n"],"mappings":"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","names":[]}
@@ -0,0 +1,142 @@
1
+ import {
2
+ getFileSystemProviderV2
3
+ } from "./chunk-EZKJZUNJ.js";
4
+
5
+ // src/workspace/workspace-manager.ts
6
+ import { LocalForageAdapter } from "@bendyline/squisq/storage";
7
+ var DB_NAME = "docblocks-workspaces";
8
+ var STORE_NAME = "workspaces";
9
+ var LIST_KEY = "workspace-list";
10
+ var DEFAULT_WORKSPACE_ID = "default";
11
+ var store = new LocalForageAdapter({
12
+ name: DB_NAME,
13
+ storeName: STORE_NAME
14
+ });
15
+ var transientWorkspaces = /* @__PURE__ */ new Map();
16
+ function registerTransientWorkspace(descriptor, provider) {
17
+ const previous = transientWorkspaces.get(descriptor.id);
18
+ if (previous && previous.provider !== provider) {
19
+ void getFileSystemProviderV2(previous.provider)?.dispose();
20
+ }
21
+ transientWorkspaces.set(descriptor.id, { descriptor, provider });
22
+ }
23
+ function getTransientWorkspace(id) {
24
+ return transientWorkspaces.get(id) ?? null;
25
+ }
26
+ async function unregisterTransientWorkspace(id) {
27
+ const entry = transientWorkspaces.get(id);
28
+ if (!entry) return;
29
+ transientWorkspaces.delete(id);
30
+ await getFileSystemProviderV2(entry.provider)?.dispose();
31
+ }
32
+ async function listPersisted() {
33
+ const list = await store.get(LIST_KEY);
34
+ return list ?? [];
35
+ }
36
+ async function listWorkspaces() {
37
+ const persisted = await listPersisted();
38
+ const transient = [...transientWorkspaces.values()].map((t) => t.descriptor);
39
+ return [...persisted, ...transient];
40
+ }
41
+ async function getWorkspace(id) {
42
+ const transient = transientWorkspaces.get(id);
43
+ if (transient) return transient.descriptor;
44
+ const list = await listPersisted();
45
+ return list.find((w) => w.id === id) ?? null;
46
+ }
47
+ async function saveWorkspace(workspace) {
48
+ if (workspace.type === "transient") return;
49
+ const list = await listPersisted();
50
+ const idx = list.findIndex((w) => w.id === workspace.id);
51
+ if (idx >= 0) {
52
+ list[idx] = workspace;
53
+ } else {
54
+ list.push(workspace);
55
+ }
56
+ await store.set(LIST_KEY, list);
57
+ }
58
+ async function removeWorkspace(id) {
59
+ if (transientWorkspaces.has(id)) {
60
+ await unregisterTransientWorkspace(id);
61
+ return;
62
+ }
63
+ const list = await listPersisted();
64
+ const filtered = list.filter((w) => w.id !== id);
65
+ await store.set(LIST_KEY, filtered);
66
+ }
67
+ async function touchWorkspace(id) {
68
+ const transient = transientWorkspaces.get(id);
69
+ if (transient) {
70
+ transient.descriptor.lastOpened = (/* @__PURE__ */ new Date()).toISOString();
71
+ return;
72
+ }
73
+ const list = await listPersisted();
74
+ const workspace = list.find((w) => w.id === id);
75
+ if (workspace) {
76
+ workspace.lastOpened = (/* @__PURE__ */ new Date()).toISOString();
77
+ await store.set(LIST_KEY, list);
78
+ }
79
+ }
80
+ async function ensureDefaultWorkspace() {
81
+ const existing = await getWorkspace(DEFAULT_WORKSPACE_ID);
82
+ if (existing) return existing;
83
+ const descriptor = {
84
+ id: DEFAULT_WORKSPACE_ID,
85
+ name: "My Documents",
86
+ type: "indexeddb",
87
+ lastOpened: (/* @__PURE__ */ new Date()).toISOString()
88
+ };
89
+ await saveWorkspace(descriptor);
90
+ return descriptor;
91
+ }
92
+
93
+ // src/workspace/reconcile-electron.ts
94
+ function comparableRoot(rootPath, platform) {
95
+ const normalized = rootPath.replace(/\\/gu, "/").replace(/\/+$/gu, "");
96
+ return platform === "win32" ? normalized.toLowerCase() : normalized;
97
+ }
98
+ function reconcileElectronWorkspaceDescriptors(local, hostWorkspaces, platform, now) {
99
+ const electron = local.filter((workspace) => workspace.type === "electron-native");
100
+ const matchedLocalIds = /* @__PURE__ */ new Set();
101
+ const idRemap = {};
102
+ const upsert = hostWorkspaces.map((hostWorkspace) => {
103
+ const root = comparableRoot(hostWorkspace.rootPath, platform);
104
+ const candidates = electron.filter(
105
+ (workspace) => workspace.rootPath && comparableRoot(workspace.rootPath, platform) === root
106
+ );
107
+ const matching = candidates.sort(
108
+ (left, right) => right.lastOpened.localeCompare(left.lastOpened)
109
+ )[0];
110
+ if (matching) {
111
+ matchedLocalIds.add(matching.id);
112
+ if (matching.id !== hostWorkspace.id) idRemap[matching.id] = hostWorkspace.id;
113
+ }
114
+ return {
115
+ id: hostWorkspace.id,
116
+ name: matching?.name ?? hostWorkspace.name,
117
+ type: "electron-native",
118
+ rootPath: hostWorkspace.rootPath,
119
+ lastOpened: matching?.lastOpened ?? now,
120
+ ...matching?.versioningOverride ? { versioningOverride: matching.versioningOverride } : {}
121
+ };
122
+ });
123
+ const canonicalIds = new Set(hostWorkspaces.map((workspace) => workspace.id));
124
+ const removeIds = electron.filter(
125
+ (workspace) => !canonicalIds.has(workspace.id) || matchedLocalIds.has(workspace.id) && !upsert.some((candidate) => candidate.id === workspace.id)
126
+ ).map((workspace) => workspace.id);
127
+ return { removeIds, upsert, idRemap };
128
+ }
129
+
130
+ export {
131
+ registerTransientWorkspace,
132
+ getTransientWorkspace,
133
+ unregisterTransientWorkspace,
134
+ listWorkspaces,
135
+ getWorkspace,
136
+ saveWorkspace,
137
+ removeWorkspace,
138
+ touchWorkspace,
139
+ ensureDefaultWorkspace,
140
+ reconcileElectronWorkspaceDescriptors
141
+ };
142
+ //# sourceMappingURL=chunk-W5UUUII5.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/workspace/workspace-manager.ts","../src/workspace/reconcile-electron.ts"],"sourcesContent":["/**\n * WorkspaceManager — manages the list of known workspaces in IndexedDB\n * and provides helpers for creating / switching / removing them.\n *\n * The actual FileSystemProvider instances are created by the caller\n * (since native providers need a DirectoryHandle from user interaction).\n */\n\nimport { LocalForageAdapter } from '@bendyline/squisq/storage';\nimport { getFileSystemProviderV2, type FileSystemProvider } from '../filesystem/types.js';\nimport type { WorkspaceDescriptor } from './types.js';\n\nconst DB_NAME = 'docblocks-workspaces';\nconst STORE_NAME = 'workspaces';\nconst LIST_KEY = 'workspace-list';\nconst DEFAULT_WORKSPACE_ID = 'default';\n\nconst store = new LocalForageAdapter({\n name: DB_NAME,\n storeName: STORE_NAME,\n});\n\n/**\n * Session-only transient workspaces (a loose file or `.dbk` opened from the\n * OS). Kept purely in memory — never written to the persisted list — with\n * their pre-built provider registered alongside the descriptor. Lost on\n * reload, which is the intended \"transient for the app session\" behaviour.\n */\ninterface TransientEntry {\n descriptor: WorkspaceDescriptor;\n provider: FileSystemProvider;\n}\nconst transientWorkspaces = new Map<string, TransientEntry>();\n\n/** Register a transient workspace and its (already-built) provider. */\nexport function registerTransientWorkspace(\n descriptor: WorkspaceDescriptor,\n provider: FileSystemProvider,\n): void {\n const previous = transientWorkspaces.get(descriptor.id);\n if (previous && previous.provider !== provider) {\n void getFileSystemProviderV2(previous.provider)?.dispose();\n }\n transientWorkspaces.set(descriptor.id, { descriptor, provider });\n}\n\n/** Look up a transient workspace (descriptor + provider) by id, if any. */\nexport function getTransientWorkspace(\n id: string,\n): { descriptor: WorkspaceDescriptor; provider: FileSystemProvider } | null {\n return transientWorkspaces.get(id) ?? null;\n}\n\n/** Forget a transient workspace (e.g. when it is closed). */\nexport async function unregisterTransientWorkspace(id: string): Promise<void> {\n const entry = transientWorkspaces.get(id);\n if (!entry) return;\n transientWorkspaces.delete(id);\n await getFileSystemProviderV2(entry.provider)?.dispose();\n}\n\n/** The persisted (on-disk) workspace list only — excludes transient ones. */\nasync function listPersisted(): Promise<WorkspaceDescriptor[]> {\n const list = await store.get<WorkspaceDescriptor[]>(LIST_KEY);\n return list ?? [];\n}\n\n/**\n * Get all known workspace descriptors — persisted plus any session-only\n * transient ones (so they show in the picker and resolve for the session).\n */\nexport async function listWorkspaces(): Promise<WorkspaceDescriptor[]> {\n const persisted = await listPersisted();\n const transient = [...transientWorkspaces.values()].map((t) => t.descriptor);\n return [...persisted, ...transient];\n}\n\n/**\n * Get a specific workspace descriptor by id (transient or persisted).\n */\nexport async function getWorkspace(id: string): Promise<WorkspaceDescriptor | null> {\n const transient = transientWorkspaces.get(id);\n if (transient) return transient.descriptor;\n const list = await listPersisted();\n return list.find((w) => w.id === id) ?? null;\n}\n\n/**\n * Add or update a workspace descriptor. If a workspace with the same id\n * already exists, it is replaced. Transient workspaces are never persisted.\n */\nexport async function saveWorkspace(workspace: WorkspaceDescriptor): Promise<void> {\n if (workspace.type === 'transient') return;\n const list = await listPersisted();\n const idx = list.findIndex((w) => w.id === workspace.id);\n if (idx >= 0) {\n list[idx] = workspace;\n } else {\n list.push(workspace);\n }\n await store.set(LIST_KEY, list);\n}\n\n/**\n * Remove a workspace descriptor by id (transient or persisted).\n */\nexport async function removeWorkspace(id: string): Promise<void> {\n if (transientWorkspaces.has(id)) {\n await unregisterTransientWorkspace(id);\n return;\n }\n const list = await listPersisted();\n const filtered = list.filter((w) => w.id !== id);\n await store.set(LIST_KEY, filtered);\n}\n\n/**\n * Touch the lastOpened timestamp on a workspace. For transient workspaces this\n * updates the in-memory descriptor only (nothing is persisted).\n */\nexport async function touchWorkspace(id: string): Promise<void> {\n const transient = transientWorkspaces.get(id);\n if (transient) {\n transient.descriptor.lastOpened = new Date().toISOString();\n return;\n }\n const list = await listPersisted();\n const workspace = list.find((w) => w.id === id);\n if (workspace) {\n workspace.lastOpened = new Date().toISOString();\n await store.set(LIST_KEY, list);\n }\n}\n\n/**\n * Ensure a default IndexedDB workspace exists. Called on app startup.\n * Returns the descriptor.\n */\nexport async function ensureDefaultWorkspace(): Promise<WorkspaceDescriptor> {\n const existing = await getWorkspace(DEFAULT_WORKSPACE_ID);\n if (existing) return existing;\n\n const descriptor: WorkspaceDescriptor = {\n id: DEFAULT_WORKSPACE_ID,\n name: 'My Documents',\n type: 'indexeddb',\n lastOpened: new Date().toISOString(),\n };\n await saveWorkspace(descriptor);\n return descriptor;\n}\n","import type { ElectronWorkspaceInfo, HostEnvironment } from '../host/types.js';\nimport type { WorkspaceDescriptor } from './types.js';\n\nexport interface ElectronWorkspaceReconciliation {\n /** Obsolete renderer descriptors to remove before attempting restoration. */\n readonly removeIds: readonly string[];\n /** Canonical main-authorized descriptors to insert or replace. */\n readonly upsert: readonly WorkspaceDescriptor[];\n /** Safe navigation migration for a local descriptor matched by root. */\n readonly idRemap: Readonly<Record<string, string>>;\n}\n\nfunction comparableRoot(rootPath: string, platform: HostEnvironment['platform']): string {\n const normalized = rootPath.replace(/\\\\/gu, '/').replace(/\\/+$/gu, '');\n return platform === 'win32' ? normalized.toLowerCase() : normalized;\n}\n\n/**\n * Reconcile renderer IndexedDB metadata with the main process authority list.\n * `hostWorkspaces` is authoritative: local Electron descriptors absent from\n * it cannot be opened safely and are removed. Root-path matching carries user\n * metadata across an id migration without treating that display path as\n * authority.\n */\nexport function reconcileElectronWorkspaceDescriptors(\n local: readonly WorkspaceDescriptor[],\n hostWorkspaces: readonly ElectronWorkspaceInfo[],\n platform: HostEnvironment['platform'],\n now: string,\n): ElectronWorkspaceReconciliation {\n const electron = local.filter((workspace) => workspace.type === 'electron-native');\n const matchedLocalIds = new Set<string>();\n const idRemap: Record<string, string> = {};\n const upsert = hostWorkspaces.map((hostWorkspace): WorkspaceDescriptor => {\n const root = comparableRoot(hostWorkspace.rootPath, platform);\n const candidates = electron.filter(\n (workspace) => workspace.rootPath && comparableRoot(workspace.rootPath, platform) === root,\n );\n const matching = candidates.sort((left, right) =>\n right.lastOpened.localeCompare(left.lastOpened),\n )[0];\n if (matching) {\n matchedLocalIds.add(matching.id);\n if (matching.id !== hostWorkspace.id) idRemap[matching.id] = hostWorkspace.id;\n }\n return {\n id: hostWorkspace.id,\n name: matching?.name ?? hostWorkspace.name,\n type: 'electron-native',\n rootPath: hostWorkspace.rootPath,\n lastOpened: matching?.lastOpened ?? now,\n ...(matching?.versioningOverride ? { versioningOverride: matching.versioningOverride } : {}),\n };\n });\n const canonicalIds = new Set(hostWorkspaces.map((workspace) => workspace.id));\n const removeIds = electron\n .filter(\n (workspace) =>\n !canonicalIds.has(workspace.id) ||\n (matchedLocalIds.has(workspace.id) &&\n !upsert.some((candidate) => candidate.id === workspace.id)),\n )\n .map((workspace) => workspace.id);\n return { removeIds, upsert, idRemap };\n}\n"],"mappings":"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","names":[]}