@bendyline/docblocks 2.0.0 → 2.1.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 (286) hide show
  1. package/dist/{chunk-J32GU3F3.js → chunk-6IYMTYMQ.js} +249 -221
  2. package/dist/chunk-6IYMTYMQ.js.map +1 -0
  3. package/dist/{chunk-75UUF6C4.js → chunk-B56KWCSE.js} +2 -2
  4. package/dist/{chunk-RVQHY3XU.js → chunk-BNKV7MTO.js} +1 -1
  5. package/dist/{chunk-RVQHY3XU.js.map → chunk-BNKV7MTO.js.map} +1 -1
  6. package/dist/chunk-BXMF5YQJ.js +149 -0
  7. package/dist/chunk-BXMF5YQJ.js.map +1 -0
  8. package/dist/{chunk-PGR7LK6D.js → chunk-COYQXQK3.js} +14 -5
  9. package/dist/chunk-COYQXQK3.js.map +1 -0
  10. package/dist/{chunk-RQJRQF46.js → chunk-DN7A33LL.js} +42 -49
  11. package/dist/chunk-DN7A33LL.js.map +1 -0
  12. package/dist/chunk-FA7UNOXK.js +20 -0
  13. package/dist/chunk-FA7UNOXK.js.map +1 -0
  14. package/dist/chunk-GM5YXU4L.js +29 -0
  15. package/dist/chunk-GM5YXU4L.js.map +1 -0
  16. package/dist/{chunk-SI2LU2RP.js → chunk-JS6XFWQK.js} +2 -1
  17. package/dist/chunk-JS6XFWQK.js.map +1 -0
  18. package/dist/{chunk-EGNDADXB.js → chunk-MNSZ7EZN.js} +2 -2
  19. package/dist/chunk-P3DVZQ6S.js +228 -0
  20. package/dist/chunk-P3DVZQ6S.js.map +1 -0
  21. package/dist/chunk-P4WATND4.js +52 -0
  22. package/dist/chunk-P4WATND4.js.map +1 -0
  23. package/dist/chunk-RVPGQBWR.js +169 -0
  24. package/dist/chunk-RVPGQBWR.js.map +1 -0
  25. package/dist/chunk-U722UUFN.js +9 -0
  26. package/dist/chunk-U722UUFN.js.map +1 -0
  27. package/dist/{chunk-GCPBEMMH.js → chunk-VTCSF7VS.js} +11 -21
  28. package/dist/chunk-VTCSF7VS.js.map +1 -0
  29. package/dist/{chunk-2D7Y4IR3.js → chunk-WJKYY5QR.js} +123 -66
  30. package/dist/chunk-WJKYY5QR.js.map +1 -0
  31. package/dist/{chunk-5MYAICRE.js → chunk-XUML3MKV.js} +44 -56
  32. package/dist/chunk-XUML3MKV.js.map +1 -0
  33. package/dist/document/index.d.ts +358 -6
  34. package/dist/document/index.js +24 -3
  35. package/dist/document/index.js.map +1 -1
  36. package/dist/filesystem/electron.d.ts +73 -4
  37. package/dist/filesystem/electron.js +16 -3
  38. package/dist/filesystem/electron.js.map +1 -1
  39. package/dist/filesystem/index.d.ts +228 -22
  40. package/dist/filesystem/index.js +133 -19
  41. package/dist/filesystem/index.js.map +1 -1
  42. package/dist/filesystem/indexeddb.d.ts +284 -5
  43. package/dist/filesystem/indexeddb.js +22 -4
  44. package/dist/filesystem/indexeddb.js.map +1 -1
  45. package/dist/filesystem/memory.d.ts +152 -4
  46. package/dist/filesystem/memory.js +12 -3
  47. package/dist/filesystem/memory.js.map +1 -1
  48. package/dist/filesystem/native.d.ts +136 -4
  49. package/dist/filesystem/native.js +27 -3
  50. package/dist/filesystem/native.js.map +1 -1
  51. package/dist/host/index.d.ts +32 -9
  52. package/dist/host/index.js +26 -29
  53. package/dist/host/index.js.map +1 -1
  54. package/dist/index.d.ts +14 -10
  55. package/dist/index.js +204 -9
  56. package/dist/index.js.map +1 -1
  57. package/dist/mcp/index.d.ts +33 -4
  58. package/dist/mcp/index.js +31 -3
  59. package/dist/mcp/index.js.map +1 -1
  60. package/dist/mcp/zod.d.ts +637 -635
  61. package/dist/mcp/zod.js +700 -884
  62. package/dist/mcp/zod.js.map +1 -1
  63. package/dist/share/index.d.ts +43 -0
  64. package/dist/share/index.js +13 -0
  65. package/dist/share/index.js.map +1 -0
  66. package/dist/{types-CsX6EN2t.d.ts → types-BEg5SQ1_.d.ts} +1 -1
  67. package/dist/{types-eOlt9J7n.d.ts → types-CueK0tvU.d.ts} +34 -11
  68. package/dist/vscode/index.d.ts +220 -3
  69. package/dist/vscode/index.js +382 -2
  70. package/dist/vscode/index.js.map +1 -1
  71. package/dist/workspace/index.d.ts +141 -4
  72. package/dist/workspace/index.js +28 -2
  73. package/dist/workspace/index.js.map +1 -1
  74. package/package.json +9 -5
  75. package/dist/chunk-2D7Y4IR3.js.map +0 -1
  76. package/dist/chunk-5MYAICRE.js.map +0 -1
  77. package/dist/chunk-AYZ4HN5M.js +0 -20
  78. package/dist/chunk-AYZ4HN5M.js.map +0 -1
  79. package/dist/chunk-GCPBEMMH.js.map +0 -1
  80. package/dist/chunk-J32GU3F3.js.map +0 -1
  81. package/dist/chunk-PGR7LK6D.js.map +0 -1
  82. package/dist/chunk-RQJRQF46.js.map +0 -1
  83. package/dist/chunk-SI2LU2RP.js.map +0 -1
  84. package/dist/chunk-W5UUUII5.js +0 -142
  85. package/dist/chunk-W5UUUII5.js.map +0 -1
  86. package/dist/document/document-session.d.ts +0 -127
  87. package/dist/document/document-session.d.ts.map +0 -1
  88. package/dist/document/document-session.js +0 -749
  89. package/dist/document/document-session.js.map +0 -1
  90. package/dist/document/filesystem-target.d.ts +0 -17
  91. package/dist/document/filesystem-target.d.ts.map +0 -1
  92. package/dist/document/filesystem-target.js +0 -70
  93. package/dist/document/filesystem-target.js.map +0 -1
  94. package/dist/document/index.d.ts.map +0 -1
  95. package/dist/document/recovery-journal.d.ts +0 -125
  96. package/dist/document/recovery-journal.d.ts.map +0 -1
  97. package/dist/document/recovery-journal.js +0 -385
  98. package/dist/document/recovery-journal.js.map +0 -1
  99. package/dist/document/types.d.ts +0 -89
  100. package/dist/document/types.d.ts.map +0 -1
  101. package/dist/document/types.js +0 -9
  102. package/dist/document/types.js.map +0 -1
  103. package/dist/filesystem/commit-lock.d.ts +0 -3
  104. package/dist/filesystem/commit-lock.d.ts.map +0 -1
  105. package/dist/filesystem/commit-lock.js +0 -20
  106. package/dist/filesystem/commit-lock.js.map +0 -1
  107. package/dist/filesystem/dbk-workspace.d.ts +0 -34
  108. package/dist/filesystem/dbk-workspace.d.ts.map +0 -1
  109. package/dist/filesystem/dbk-workspace.js +0 -85
  110. package/dist/filesystem/dbk-workspace.js.map +0 -1
  111. package/dist/filesystem/electron-provider-v2.d.ts +0 -36
  112. package/dist/filesystem/electron-provider-v2.d.ts.map +0 -1
  113. package/dist/filesystem/electron-provider-v2.js +0 -503
  114. package/dist/filesystem/electron-provider-v2.js.map +0 -1
  115. package/dist/filesystem/electron-provider.d.ts +0 -35
  116. package/dist/filesystem/electron-provider.d.ts.map +0 -1
  117. package/dist/filesystem/electron-provider.js +0 -69
  118. package/dist/filesystem/electron-provider.js.map +0 -1
  119. package/dist/filesystem/electron.d.ts.map +0 -1
  120. package/dist/filesystem/file-media-provider.d.ts +0 -23
  121. package/dist/filesystem/file-media-provider.d.ts.map +0 -1
  122. package/dist/filesystem/file-media-provider.js +0 -85
  123. package/dist/filesystem/file-media-provider.js.map +0 -1
  124. package/dist/filesystem/filesystem-content-container.d.ts +0 -24
  125. package/dist/filesystem/filesystem-content-container.d.ts.map +0 -1
  126. package/dist/filesystem/filesystem-content-container.js +0 -153
  127. package/dist/filesystem/filesystem-content-container.js.map +0 -1
  128. package/dist/filesystem/fs-error.d.ts +0 -46
  129. package/dist/filesystem/fs-error.d.ts.map +0 -1
  130. package/dist/filesystem/fs-error.js +0 -170
  131. package/dist/filesystem/fs-error.js.map +0 -1
  132. package/dist/filesystem/index.d.ts.map +0 -1
  133. package/dist/filesystem/indexeddb-content-container.d.ts +0 -22
  134. package/dist/filesystem/indexeddb-content-container.d.ts.map +0 -1
  135. package/dist/filesystem/indexeddb-content-container.js +0 -100
  136. package/dist/filesystem/indexeddb-content-container.js.map +0 -1
  137. package/dist/filesystem/indexeddb-provider-v2.d.ts +0 -96
  138. package/dist/filesystem/indexeddb-provider-v2.d.ts.map +0 -1
  139. package/dist/filesystem/indexeddb-provider-v2.js +0 -1241
  140. package/dist/filesystem/indexeddb-provider-v2.js.map +0 -1
  141. package/dist/filesystem/indexeddb-provider.d.ts +0 -39
  142. package/dist/filesystem/indexeddb-provider.d.ts.map +0 -1
  143. package/dist/filesystem/indexeddb-provider.js +0 -145
  144. package/dist/filesystem/indexeddb-provider.js.map +0 -1
  145. package/dist/filesystem/indexeddb-store.d.ts +0 -34
  146. package/dist/filesystem/indexeddb-store.d.ts.map +0 -1
  147. package/dist/filesystem/indexeddb-store.js +0 -165
  148. package/dist/filesystem/indexeddb-store.js.map +0 -1
  149. package/dist/filesystem/indexeddb.d.ts.map +0 -1
  150. package/dist/filesystem/legacy-v2-adapter.d.ts +0 -62
  151. package/dist/filesystem/legacy-v2-adapter.d.ts.map +0 -1
  152. package/dist/filesystem/legacy-v2-adapter.js +0 -499
  153. package/dist/filesystem/legacy-v2-adapter.js.map +0 -1
  154. package/dist/filesystem/memory-provider-v2.d.ts +0 -92
  155. package/dist/filesystem/memory-provider-v2.d.ts.map +0 -1
  156. package/dist/filesystem/memory-provider-v2.js +0 -615
  157. package/dist/filesystem/memory-provider-v2.js.map +0 -1
  158. package/dist/filesystem/memory-provider.d.ts +0 -54
  159. package/dist/filesystem/memory-provider.d.ts.map +0 -1
  160. package/dist/filesystem/memory-provider.js +0 -132
  161. package/dist/filesystem/memory-provider.js.map +0 -1
  162. package/dist/filesystem/memory.d.ts.map +0 -1
  163. package/dist/filesystem/move-entry.d.ts +0 -9
  164. package/dist/filesystem/move-entry.d.ts.map +0 -1
  165. package/dist/filesystem/move-entry.js +0 -103
  166. package/dist/filesystem/move-entry.js.map +0 -1
  167. package/dist/filesystem/move-error.d.ts +0 -53
  168. package/dist/filesystem/move-error.d.ts.map +0 -1
  169. package/dist/filesystem/move-error.js +0 -99
  170. package/dist/filesystem/move-error.js.map +0 -1
  171. package/dist/filesystem/native-provider-v2.d.ts +0 -75
  172. package/dist/filesystem/native-provider-v2.d.ts.map +0 -1
  173. package/dist/filesystem/native-provider-v2.js +0 -849
  174. package/dist/filesystem/native-provider-v2.js.map +0 -1
  175. package/dist/filesystem/native-provider.d.ts +0 -53
  176. package/dist/filesystem/native-provider.d.ts.map +0 -1
  177. package/dist/filesystem/native-provider.js +0 -471
  178. package/dist/filesystem/native-provider.js.map +0 -1
  179. package/dist/filesystem/native.d.ts.map +0 -1
  180. package/dist/filesystem/types.d.ts +0 -83
  181. package/dist/filesystem/types.d.ts.map +0 -1
  182. package/dist/filesystem/types.js +0 -16
  183. package/dist/filesystem/types.js.map +0 -1
  184. package/dist/filesystem/v2.d.ts +0 -172
  185. package/dist/filesystem/v2.d.ts.map +0 -1
  186. package/dist/filesystem/v2.js +0 -16
  187. package/dist/filesystem/v2.js.map +0 -1
  188. package/dist/filesystem/workspace-path.d.ts +0 -21
  189. package/dist/filesystem/workspace-path.d.ts.map +0 -1
  190. package/dist/filesystem/workspace-path.js +0 -80
  191. package/dist/filesystem/workspace-path.js.map +0 -1
  192. package/dist/host/filesystem-v2.d.ts +0 -45
  193. package/dist/host/filesystem-v2.d.ts.map +0 -1
  194. package/dist/host/filesystem-v2.js +0 -13
  195. package/dist/host/filesystem-v2.js.map +0 -1
  196. package/dist/host/git.d.ts +0 -200
  197. package/dist/host/git.d.ts.map +0 -1
  198. package/dist/host/git.js +0 -15
  199. package/dist/host/git.js.map +0 -1
  200. package/dist/host/index.d.ts.map +0 -1
  201. package/dist/host/types.d.ts +0 -232
  202. package/dist/host/types.d.ts.map +0 -1
  203. package/dist/host/types.js +0 -10
  204. package/dist/host/types.js.map +0 -1
  205. package/dist/host/wire-policy.d.ts +0 -22
  206. package/dist/host/wire-policy.d.ts.map +0 -1
  207. package/dist/host/wire-policy.js +0 -92
  208. package/dist/host/wire-policy.js.map +0 -1
  209. package/dist/index.d.ts.map +0 -1
  210. package/dist/mcp/index.d.ts.map +0 -1
  211. package/dist/mcp/types.d.ts +0 -466
  212. package/dist/mcp/types.d.ts.map +0 -1
  213. package/dist/mcp/types.js +0 -25
  214. package/dist/mcp/types.js.map +0 -1
  215. package/dist/mcp/wire.d.ts +0 -29
  216. package/dist/mcp/wire.d.ts.map +0 -1
  217. package/dist/mcp/wire.js +0 -1046
  218. package/dist/mcp/wire.js.map +0 -1
  219. package/dist/mcp/zod.d.ts.map +0 -1
  220. package/dist/vscode/index.d.ts.map +0 -1
  221. package/dist/vscode/messages.d.ts +0 -204
  222. package/dist/vscode/messages.d.ts.map +0 -1
  223. package/dist/vscode/messages.js +0 -494
  224. package/dist/vscode/messages.js.map +0 -1
  225. package/dist/workspace/index.d.ts.map +0 -1
  226. package/dist/workspace/reconcile-electron.d.ts +0 -19
  227. package/dist/workspace/reconcile-electron.d.ts.map +0 -1
  228. package/dist/workspace/reconcile-electron.js +0 -42
  229. package/dist/workspace/reconcile-electron.js.map +0 -1
  230. package/dist/workspace/types.d.ts +0 -69
  231. package/dist/workspace/types.d.ts.map +0 -1
  232. package/dist/workspace/types.js +0 -2
  233. package/dist/workspace/types.js.map +0 -1
  234. package/dist/workspace/workspace-manager.d.ts +0 -47
  235. package/dist/workspace/workspace-manager.d.ts.map +0 -1
  236. package/dist/workspace/workspace-manager.js +0 -126
  237. package/dist/workspace/workspace-manager.js.map +0 -1
  238. package/src/document/document-session.ts +0 -834
  239. package/src/document/filesystem-target.ts +0 -109
  240. package/src/document/index.ts +0 -41
  241. package/src/document/recovery-journal.ts +0 -536
  242. package/src/document/types.ts +0 -116
  243. package/src/filesystem/commit-lock.ts +0 -29
  244. package/src/filesystem/dbk-workspace.ts +0 -135
  245. package/src/filesystem/electron-provider-v2.ts +0 -630
  246. package/src/filesystem/electron-provider.ts +0 -99
  247. package/src/filesystem/electron.ts +0 -3
  248. package/src/filesystem/file-media-provider.ts +0 -103
  249. package/src/filesystem/filesystem-content-container.ts +0 -164
  250. package/src/filesystem/fs-error.ts +0 -234
  251. package/src/filesystem/index.ts +0 -143
  252. package/src/filesystem/indexeddb-content-container.ts +0 -112
  253. package/src/filesystem/indexeddb-provider-v2.ts +0 -1740
  254. package/src/filesystem/indexeddb-provider.ts +0 -171
  255. package/src/filesystem/indexeddb-store.ts +0 -207
  256. package/src/filesystem/indexeddb.ts +0 -12
  257. package/src/filesystem/legacy-v2-adapter.ts +0 -779
  258. package/src/filesystem/memory-provider-v2.ts +0 -896
  259. package/src/filesystem/memory-provider.ts +0 -180
  260. package/src/filesystem/memory.ts +0 -15
  261. package/src/filesystem/move-entry.ts +0 -142
  262. package/src/filesystem/move-error.ts +0 -159
  263. package/src/filesystem/native-provider-v2.ts +0 -1165
  264. package/src/filesystem/native-provider.ts +0 -537
  265. package/src/filesystem/native.ts +0 -16
  266. package/src/filesystem/types.ts +0 -114
  267. package/src/filesystem/v2.ts +0 -231
  268. package/src/filesystem/workspace-path.ts +0 -92
  269. package/src/host/filesystem-v2.ts +0 -104
  270. package/src/host/git.ts +0 -246
  271. package/src/host/index.ts +0 -93
  272. package/src/host/types.ts +0 -274
  273. package/src/host/wire-policy.ts +0 -103
  274. package/src/index.ts +0 -10
  275. package/src/mcp/index.ts +0 -3
  276. package/src/mcp/types.ts +0 -594
  277. package/src/mcp/wire.ts +0 -1280
  278. package/src/mcp/zod.ts +0 -1000
  279. package/src/vscode/index.ts +0 -2
  280. package/src/vscode/messages.ts +0 -704
  281. package/src/workspace/index.ts +0 -17
  282. package/src/workspace/reconcile-electron.ts +0 -65
  283. package/src/workspace/types.ts +0 -67
  284. package/src/workspace/workspace-manager.ts +0 -151
  285. /package/dist/{chunk-75UUF6C4.js.map → chunk-B56KWCSE.js.map} +0 -0
  286. /package/dist/{chunk-EGNDADXB.js.map → chunk-MNSZ7EZN.js.map} +0 -0
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/document/document-session.ts","../src/document/filesystem-target.ts","../src/document/recovery-journal.ts"],"sourcesContent":["import type {\n DocumentCommitTarget,\n DocumentConflictStrategy,\n DocumentExternalChangeResult,\n DocumentExternalSnapshot,\n DocumentSaveReason,\n DocumentSessionConflict,\n DocumentSessionEditScope,\n DocumentSessionLifecycle,\n DocumentSessionOptions,\n DocumentSessionSnapshot,\n DocumentSessionStatus,\n DocumentSessionTransition,\n} from './types.js';\nimport { isFileSystemMoveStateError } from '../filesystem/move-error.js';\nimport type { DocumentRecoveryJournal } from './recovery-journal.js';\n\ntype SessionListener = () => void;\n\nconst DEFAULT_AUTO_SAVE_RETRY_DELAYS_MS = [1_000, 3_000, 10_000] as const;\n\n/**\n * Raised by a commit target when optimistic external-change verification\n * fails. The session converts it into durable conflict state.\n */\nexport class DocumentCommitConflictError extends Error {\n public readonly externalContent: string | null;\n public readonly externalVersion: string | number | null;\n\n public constructor(\n message: string,\n externalContent: string | null,\n externalVersion: string | number | null = null,\n ) {\n super(message);\n this.name = 'DocumentCommitConflictError';\n this.externalContent = externalContent;\n this.externalVersion = externalVersion;\n }\n}\n\nexport class DocumentSessionConflictError extends Error {\n public readonly conflict: DocumentSessionConflict;\n\n public constructor(conflict: DocumentSessionConflict) {\n super('The document changed outside DocBlocks while local edits were pending.');\n this.name = 'DocumentSessionConflictError';\n this.conflict = conflict;\n }\n}\n\n/**\n * A revisioned, serialized persistence boundary for one active document.\n *\n * Invariants:\n * - only drain() calls target.commit();\n * - at most one commit is in flight;\n * - revisions never decrease, including across target transitions;\n * - destructive operations wait for an in-flight commit and run last;\n * - a target is never changed by a React effect cleanup.\n */\nexport class DocumentSession {\n private readonly autoSaveDelayMs: number;\n private readonly autoSaveRetryDelaysMs: readonly number[];\n private readonly recoveryJournal: DocumentRecoveryJournal | null;\n private readonly listeners = new Set<SessionListener>();\n private autoSaveEnabled: boolean;\n\n private target: DocumentCommitTarget | null = null;\n private content = '';\n private persistedContent: string | null = null;\n private revision = 0;\n private persistedRevision = 0;\n private savingRevision: number | null = null;\n private savingContent: string | null = null;\n private generation = 0;\n private externalSequence = -1;\n private lifecycle: DocumentSessionLifecycle = 'open';\n private frozen = false;\n private error: Error | null = null;\n private conflict: DocumentSessionConflict | null = null;\n\n private autoSaveTimer: ReturnType<typeof setTimeout> | null = null;\n private autoSaveRetryAttempt = 0;\n private drainPromise: Promise<void> | null = null;\n private haltDrain = false;\n private operationTail: Promise<void> = Promise.resolve();\n private snapshot: DocumentSessionSnapshot;\n\n public constructor(options: DocumentSessionOptions = {}) {\n this.autoSaveDelayMs = Math.max(0, options.autoSaveDelayMs ?? 500);\n this.autoSaveEnabled = options.autoSaveEnabled ?? true;\n this.autoSaveRetryDelaysMs = normalizeRetryDelays(\n options.autoSaveRetryDelaysMs ?? DEFAULT_AUTO_SAVE_RETRY_DELAYS_MS,\n );\n this.recoveryJournal = options.recoveryJournal ?? null;\n this.snapshot = this.createSnapshot();\n }\n\n public readonly subscribe = (listener: SessionListener): (() => void) => {\n this.listeners.add(listener);\n return () => this.listeners.delete(listener);\n };\n\n public readonly getSnapshot = (): DocumentSessionSnapshot => this.snapshot;\n\n /** Enable or disable automatic persistence without weakening explicit or lifecycle flushes. */\n public setAutoSaveEnabled(enabled: boolean): void {\n if (this.autoSaveEnabled === enabled) return;\n this.autoSaveEnabled = enabled;\n if (!enabled) {\n this.clearAutoSaveTimer();\n return;\n }\n if (\n this.target &&\n this.lifecycle === 'open' &&\n !this.frozen &&\n !this.conflict &&\n this.persistedRevision < this.revision\n ) {\n this.scheduleAutoSave();\n }\n }\n\n /**\n * Record a complete local snapshot and schedule its persistence.\n * Returns the assigned monotonic revision.\n */\n public edit(content: string, scope: DocumentSessionEditScope): number {\n if (!this.target || this.lifecycle !== 'open' || this.frozen) {\n throw new Error('Cannot edit a document session that is not open.');\n }\n if (scope.targetKey !== this.target.key || scope.generation !== this.generation) {\n throw new Error('Cannot apply an edit from an obsolete document instance.');\n }\n if (content === this.content) return this.revision;\n\n this.content = content;\n this.revision += 1;\n this.error = null;\n this.autoSaveRetryAttempt = 0;\n if (this.conflict) {\n this.conflict = {\n ...this.conflict,\n localContent: content,\n localRevision: this.revision,\n };\n }\n this.writeRecoverySnapshot();\n if (!this.conflict) this.scheduleAutoSave();\n this.emit();\n return this.revision;\n }\n\n /**\n * Persist the revision current when flush() is called. A later edit may\n * advance the session again, but commits remain strictly serialized.\n */\n public async flush(reason: DocumentSaveReason = 'manual'): Promise<DocumentSessionSnapshot> {\n this.clearAutoSaveTimer();\n if (!this.target) return this.snapshot;\n if (this.conflict) throw new DocumentSessionConflictError(this.conflict);\n\n const requiredRevision = this.revision;\n while (this.target && this.persistedRevision < requiredRevision) {\n if (this.conflict) throw new DocumentSessionConflictError(this.conflict);\n if (this.haltDrain) {\n throw new Error('Document persistence was cancelled before the requested revision saved.');\n }\n try {\n await this.ensureDrain(reason);\n } catch (error: unknown) {\n if (this.conflict) throw new DocumentSessionConflictError(this.conflict);\n throw error;\n }\n }\n\n if (this.conflict) throw new DocumentSessionConflictError(this.conflict);\n if (this.persistedRevision < requiredRevision) {\n throw new Error('The document target closed before the requested revision saved.');\n }\n return this.snapshot;\n }\n\n /**\n * Flush the old document, then replace it with a new clean baseline.\n * UI state should change only after this promise resolves.\n */\n public transitionTo(\n target: DocumentCommitTarget | null,\n content: string,\n ): Promise<DocumentSessionSnapshot> {\n return this.enqueueOperation(() =>\n this.performTransition(async () => ({ target, content })).then((snapshot) => {\n if (!snapshot) throw new Error('A fixed document transition cannot be cancelled.');\n return snapshot;\n }),\n );\n }\n\n /**\n * Freeze and flush the current document before reading the next one. The\n * loader may return null when a navigation request was superseded, leaving\n * the current target active and clean.\n */\n public transitionWithLoad(\n load: () => Promise<DocumentSessionTransition | null>,\n ): Promise<DocumentSessionSnapshot | null> {\n return this.enqueueOperation(() => this.performTransition(load));\n }\n\n /**\n * Flush the current path, run the storage move, and only then swap the\n * commit target. No edit can enter between those steps.\n */\n public retarget(\n nextTarget: DocumentCommitTarget,\n moveStorage: () => Promise<void>,\n ): Promise<DocumentSessionSnapshot> {\n return this.enqueueOperation(async () => {\n this.assertNotPreparingClose();\n if (!this.target) throw new Error('Cannot retarget a session without a document.');\n\n this.lifecycle = 'transitioning';\n this.frozen = true;\n this.emit();\n try {\n this.haltDrain = false;\n await this.flush('transition');\n await moveStorage();\n this.generation += 1;\n this.externalSequence = -1;\n this.target = nextTarget;\n this.error = null;\n this.conflict = null;\n this.lifecycle = 'open';\n this.frozen = false;\n this.emit();\n return this.snapshot;\n } catch (error: unknown) {\n if (isFileSystemMoveStateError(error)) {\n if (error.documentLocation === 'destination') {\n this.generation += 1;\n this.externalSequence = -1;\n this.target = nextTarget;\n }\n this.haltDrain = true;\n this.error = error;\n this.lifecycle = 'open';\n // The provider could not establish one authoritative compound move.\n // Keep editing frozen until navigation/recovery chooses a real path.\n this.frozen = true;\n this.emit();\n throw error;\n }\n this.lifecycle = 'open';\n this.frozen = false;\n this.emit();\n throw error;\n }\n });\n }\n\n /**\n * Cancel queued writes, wait for an already-running write, then delete.\n * The deletion is therefore the final storage operation for this target.\n */\n public delete(deleteStorage: () => Promise<void>): Promise<DocumentSessionSnapshot> {\n return this.enqueueOperation(async () => {\n this.assertNotPreparingClose();\n this.lifecycle = 'transitioning';\n this.frozen = true;\n this.haltDrain = true;\n this.clearAutoSaveTimer();\n this.emit();\n\n await this.awaitActiveDrain();\n try {\n await deleteStorage();\n } catch (error: unknown) {\n this.haltDrain = false;\n this.lifecycle = 'open';\n this.frozen = false;\n if (this.target && this.persistedRevision < this.revision && !this.conflict) {\n this.scheduleAutoSave();\n }\n this.emit();\n throw error;\n }\n\n this.discardRecoverySnapshot();\n this.detach();\n return this.snapshot;\n });\n }\n\n /**\n * Discard queued changes and detach without mutating storage. This is used\n * for explicitly abandoned sessions, never as an implicit effect cleanup.\n */\n public cancel(): Promise<DocumentSessionSnapshot> {\n return this.enqueueOperation(async () => {\n this.lifecycle = 'transitioning';\n this.frozen = true;\n this.haltDrain = true;\n this.clearAutoSaveTimer();\n this.emit();\n await this.awaitActiveDrain();\n this.discardRecoverySnapshot();\n this.detach();\n return this.snapshot;\n });\n }\n\n /**\n * Observe a filesystem/host change captured for targetKey. Clean sessions\n * adopt it. Dirty or saving sessions preserve local text and enter conflict.\n */\n public observeExternal(change: DocumentExternalSnapshot): DocumentExternalChangeResult {\n if (!this.target || change.targetKey !== this.target.key || this.lifecycle === 'closed') {\n return 'ignored';\n }\n if (change.sequence !== undefined) {\n if (!Number.isSafeInteger(change.sequence) || change.sequence <= this.externalSequence) {\n return 'ignored';\n }\n this.externalSequence = change.sequence;\n }\n\n // While conflicted, a current observation equal to the latest local\n // snapshot proves that revision durable without requiring another write.\n // Never acknowledge while a commit is still running; its eventual result\n // remains authoritative for the serialized drain.\n if (\n this.conflict &&\n change.content === this.content &&\n this.savingRevision === null &&\n this.lifecycle === 'open'\n ) {\n this.clearAutoSaveTimer();\n this.autoSaveRetryAttempt = 0;\n this.persistedRevision = this.revision;\n this.persistedContent = this.content;\n this.haltDrain = false;\n this.error = null;\n this.conflict = null;\n this.discardRecoverySnapshot();\n this.emit();\n return 'applied';\n }\n\n // Once a conflict exists, every later accepted observation refreshes its\n // external branch before ordinary duplicate suppression. In particular,\n // A -> local C -> external B -> external A must offer A, not stale B, when\n // the user chooses Reload external.\n if (this.conflict) {\n const externalVersion = change.version ?? null;\n if (\n this.conflict.localContent === this.content &&\n this.conflict.localRevision === this.revision &&\n this.conflict.externalContent === change.content &&\n this.conflict.externalVersion === externalVersion\n ) {\n return 'ignored';\n }\n\n this.clearAutoSaveTimer();\n this.haltDrain = true;\n this.conflict = {\n targetKey: change.targetKey,\n localContent: this.content,\n localRevision: this.revision,\n externalContent: change.content,\n externalVersion,\n };\n this.error = null;\n this.writeRecoverySnapshot();\n this.emit();\n return 'conflict';\n }\n\n if (\n change.content === this.content ||\n change.content === this.persistedContent ||\n (this.savingRevision !== null && change.content === this.savingContent)\n ) {\n return 'ignored';\n }\n\n const isClean =\n this.persistedRevision === this.revision &&\n this.savingRevision === null &&\n this.error === null &&\n this.conflict === null;\n\n if (isClean && change.content !== null) {\n this.content = change.content;\n this.revision += 1;\n this.persistedRevision = this.revision;\n this.persistedContent = change.content;\n this.generation += 1;\n this.discardRecoverySnapshot();\n this.emit();\n return 'applied';\n }\n\n this.clearAutoSaveTimer();\n this.haltDrain = true;\n this.conflict = {\n targetKey: change.targetKey,\n localContent: this.content,\n localRevision: this.revision,\n externalContent: change.content,\n externalVersion: change.version ?? null,\n };\n this.error = null;\n this.writeRecoverySnapshot();\n this.emit();\n return 'conflict';\n }\n\n public resolveConflict(strategy: DocumentConflictStrategy): Promise<DocumentSessionSnapshot> {\n return this.enqueueOperation(async () => {\n if (!this.conflict) return this.snapshot;\n\n this.clearAutoSaveTimer();\n this.haltDrain = true;\n await this.awaitActiveDrain();\n // A watcher may refresh or converge the conflict while an in-flight\n // commit settles. Resolve the branch that is current now, never the\n // snapshot captured before the await.\n const currentConflict = this.conflict;\n if (!currentConflict) return this.snapshot;\n\n if (strategy === 'use-external') {\n this.discardRecoverySnapshot();\n this.generation += 1;\n this.revision += 1;\n this.conflict = null;\n this.error = null;\n this.haltDrain = false;\n\n if (currentConflict.externalContent === null) {\n this.target = null;\n this.content = '';\n this.persistedContent = null;\n this.persistedRevision = this.revision;\n this.lifecycle = 'closed';\n this.frozen = true;\n } else {\n this.content = currentConflict.externalContent;\n this.persistedContent = currentConflict.externalContent;\n this.persistedRevision = this.revision;\n this.lifecycle = 'open';\n this.frozen = false;\n }\n this.emit();\n return this.snapshot;\n }\n\n // Keep the local branch, but make the observed external snapshot the\n // optimistic baseline for the next conditional commit.\n this.persistedContent = currentConflict.externalContent;\n // A clean external deletion/conflict has no unsaved local revision.\n // Keeping local still requires a fresh commit that recreates/overwrites\n // the target, so make that intent explicit with a new revision.\n this.revision += 1;\n this.conflict = null;\n this.error = null;\n this.haltDrain = false;\n this.lifecycle = 'open';\n this.frozen = false;\n this.writeRecoverySnapshot();\n this.emit();\n return this.flush('conflict');\n });\n }\n\n /**\n * Freeze edits and flush through the latest revision. A successful call\n * remains frozen until cancelClose(); the owning host may now destroy it.\n */\n public prepareClose(): Promise<DocumentSessionSnapshot> {\n return this.enqueueOperation(async () => {\n if (this.lifecycle === 'closing') return this.snapshot;\n this.lifecycle = 'closing';\n this.frozen = true;\n this.haltDrain = false;\n this.emit();\n try {\n await this.flush('close');\n return this.snapshot;\n } catch (error: unknown) {\n this.lifecycle = 'open';\n this.frozen = false;\n this.emit();\n throw error;\n }\n });\n }\n\n /** Resume editing when a host cancels a prepared close. */\n public cancelClose(): void {\n if (this.lifecycle !== 'closing') return;\n this.lifecycle = 'open';\n this.frozen = false;\n this.haltDrain = false;\n if (this.target && this.persistedRevision < this.revision && !this.conflict) {\n this.scheduleAutoSave();\n }\n this.emit();\n }\n\n private async performTransition(\n load: () => Promise<DocumentSessionTransition | null>,\n ): Promise<DocumentSessionSnapshot | null> {\n this.assertNotPreparingClose();\n this.lifecycle = 'transitioning';\n this.frozen = true;\n this.emit();\n\n try {\n this.haltDrain = false;\n await this.flush('transition');\n this.clearAutoSaveTimer();\n const next = await load();\n if (!next) {\n this.lifecycle = 'open';\n this.frozen = false;\n this.emit();\n return null;\n }\n\n this.generation += 1;\n this.externalSequence = -1;\n this.target = next.target;\n this.content = next.content;\n this.revision += 1;\n this.persistedRevision = this.revision;\n this.persistedContent = next.target ? next.content : null;\n this.savingRevision = null;\n this.savingContent = null;\n this.error = null;\n this.conflict = null;\n this.haltDrain = false;\n this.lifecycle = 'open';\n this.frozen = false;\n const recoveryState = this.restoreRecoverySnapshot();\n if (recoveryState === 'dirty') this.scheduleAutoSave();\n this.emit();\n return this.snapshot;\n } catch (error: unknown) {\n this.lifecycle = 'open';\n this.frozen = false;\n this.emit();\n throw error;\n }\n }\n\n private scheduleAutoSave(delayMs = this.autoSaveDelayMs): void {\n this.clearAutoSaveTimer();\n if (!this.autoSaveEnabled) return;\n this.autoSaveTimer = setTimeout(() => {\n this.autoSaveTimer = null;\n const target = this.target;\n const generation = this.generation;\n void this.flush('autosave').then(\n () => {\n this.autoSaveRetryAttempt = 0;\n },\n () => {\n // Preserve honest error/conflict state while making ordinary I/O\n // failures recoverable. A newer edit already owns a fresh debounce\n // timer, and lifecycle operations cancel this retry path.\n if (\n this.autoSaveTimer !== null ||\n !target ||\n target !== this.target ||\n generation !== this.generation ||\n this.lifecycle !== 'open' ||\n this.frozen ||\n this.haltDrain ||\n this.conflict ||\n this.persistedRevision >= this.revision\n ) {\n return;\n }\n const retryDelay = this.autoSaveRetryDelaysMs[this.autoSaveRetryAttempt];\n if (retryDelay === undefined) return;\n this.autoSaveRetryAttempt += 1;\n this.scheduleAutoSave(retryDelay);\n },\n );\n }, delayMs);\n }\n\n private clearAutoSaveTimer(): void {\n if (this.autoSaveTimer === null) return;\n clearTimeout(this.autoSaveTimer);\n this.autoSaveTimer = null;\n }\n\n private ensureDrain(reason: DocumentSaveReason): Promise<void> {\n if (this.drainPromise) return this.drainPromise;\n const running = this.drain(reason);\n this.drainPromise = running;\n const clear = () => {\n if (this.drainPromise === running) this.drainPromise = null;\n };\n void running.then(clear, clear);\n return running;\n }\n\n private async drain(reason: DocumentSaveReason): Promise<void> {\n while (\n this.target &&\n !this.haltDrain &&\n !this.conflict &&\n this.persistedRevision < this.revision\n ) {\n const target = this.target;\n const generation = this.generation;\n const saveRevision = this.revision;\n const saveContent = this.content;\n const previousPersistedRevision = this.persistedRevision;\n const previousPersistedContent = this.persistedContent;\n\n this.savingRevision = saveRevision;\n this.savingContent = saveContent;\n this.error = null;\n this.emit();\n\n try {\n await target.commit({\n targetKey: target.key,\n content: saveContent,\n revision: saveRevision,\n persistedRevision: previousPersistedRevision,\n persistedContent: previousPersistedContent,\n reason,\n });\n } catch (error: unknown) {\n this.savingRevision = null;\n this.savingContent = null;\n if (error instanceof DocumentCommitConflictError) {\n this.haltDrain = true;\n this.conflict = {\n targetKey: target.key,\n localContent: this.content,\n localRevision: this.revision,\n externalContent: error.externalContent,\n externalVersion: error.externalVersion,\n };\n this.error = null;\n } else {\n this.error = toError(error);\n }\n this.emit();\n throw error;\n }\n\n if (generation !== this.generation || target !== this.target) return;\n this.persistedRevision = Math.max(this.persistedRevision, saveRevision);\n this.persistedContent = saveContent;\n this.autoSaveRetryAttempt = 0;\n this.savingRevision = null;\n this.savingContent = null;\n this.error = null;\n const activeConflict = this.getSnapshot().conflict;\n if (activeConflict?.externalContent === saveContent && this.content === saveContent) {\n // An observation that matched the in-flight local snapshot could not\n // be acknowledged until the commit settled. Its successful return now\n // proves both branches converged on the same durable revision.\n this.conflict = null;\n this.haltDrain = false;\n }\n this.recoveryJournal?.acknowledge({\n targetKey: target.key,\n generation,\n persistedRevision: this.persistedRevision,\n });\n this.emit();\n }\n }\n\n private async awaitActiveDrain(): Promise<void> {\n const active = this.drainPromise;\n if (!active) return;\n try {\n await active;\n } catch {\n // A destructive cancellation still waits for the operation to settle,\n // but a failed obsolete write must not prevent the requested deletion.\n }\n }\n\n /**\n * Rehydrate a synchronous crash snapshot after the durable baseline has\n * been read. A matching baseline is safe to resume as dirty; a changed\n * baseline becomes an explicit conflict and is never auto-overwritten.\n */\n private restoreRecoverySnapshot(): 'none' | 'dirty' | 'conflict' {\n if (!this.target || !this.recoveryJournal) return 'none';\n const recovered = this.recoveryJournal.lookup(this.target.key);\n if (!recovered) return 'none';\n\n if (recovered.content === this.content) {\n this.recoveryJournal.acknowledge({\n targetKey: recovered.targetKey,\n generation: recovered.generation,\n persistedRevision: recovered.revision,\n });\n return 'none';\n }\n\n const externalContent = this.content;\n this.generation = Math.max(this.generation, recovered.generation) + 1;\n this.revision = Math.max(this.revision, recovered.revision) + 1;\n this.content = recovered.content;\n\n if (recovered.persistedContent === externalContent) {\n this.writeRecoverySnapshot();\n return 'dirty';\n }\n\n // Preserve the journal's prior baseline so a second crash continues to\n // reopen as a conflict until the user explicitly chooses a branch.\n this.persistedContent = recovered.persistedContent;\n this.haltDrain = true;\n this.conflict = {\n targetKey: this.target.key,\n localContent: recovered.content,\n localRevision: this.revision,\n externalContent,\n externalVersion: null,\n };\n this.writeRecoverySnapshot();\n return 'conflict';\n }\n\n private writeRecoverySnapshot(): void {\n if (!this.target || !this.recoveryJournal) return;\n if (this.persistedRevision >= this.revision && !this.conflict) return;\n this.recoveryJournal.write({\n targetKey: this.target.key,\n generation: this.generation,\n revision: this.revision,\n content: this.content,\n persistedContent: this.persistedContent,\n });\n }\n\n private discardRecoverySnapshot(): void {\n if (!this.target) return;\n this.recoveryJournal?.discard(this.target.key);\n }\n\n private detach(): void {\n this.clearAutoSaveTimer();\n this.autoSaveRetryAttempt = 0;\n this.generation += 1;\n this.externalSequence = -1;\n this.target = null;\n this.persistedContent = null;\n this.savingRevision = null;\n this.savingContent = null;\n this.error = null;\n this.conflict = null;\n this.haltDrain = false;\n this.lifecycle = 'closed';\n this.frozen = true;\n this.emit();\n }\n\n private assertNotPreparingClose(): void {\n if (this.lifecycle === 'closing') {\n throw new Error('The document is already prepared for close.');\n }\n }\n\n private enqueueOperation<T>(operation: () => Promise<T>): Promise<T> {\n const run = this.operationTail.then(operation, operation);\n this.operationTail = run.then(\n () => undefined,\n () => undefined,\n );\n return run;\n }\n\n private createSnapshot(): DocumentSessionSnapshot {\n return Object.freeze({\n targetKey: this.target?.key ?? null,\n content: this.content,\n revision: this.revision,\n persistedRevision: this.persistedRevision,\n persistedContent: this.persistedContent,\n savingRevision: this.savingRevision,\n generation: this.generation,\n status: this.computeStatus(),\n lifecycle: this.lifecycle,\n frozen: this.frozen,\n error: this.error,\n conflict: this.conflict,\n });\n }\n\n private computeStatus(): DocumentSessionStatus {\n if (this.lifecycle === 'closed') return 'closed';\n if (!this.target) return 'idle';\n if (this.conflict) return 'conflict';\n if (this.error) return 'error';\n if (this.savingRevision !== null) return 'saving';\n return this.persistedRevision < this.revision ? 'dirty' : 'saved';\n }\n\n private emit(): void {\n this.snapshot = this.createSnapshot();\n for (const listener of [...this.listeners]) listener();\n }\n}\n\nfunction toError(error: unknown): Error {\n return error instanceof Error ? error : new Error(String(error));\n}\n\nfunction normalizeRetryDelays(delays: readonly number[]): readonly number[] {\n return delays.map((delay) => {\n if (!Number.isFinite(delay) || delay < 0) {\n throw new TypeError('Autosave retry delays must be finite, non-negative numbers.');\n }\n return Math.floor(delay);\n });\n}\n","import { getFileSystemProviderV2, type FileSystemProvider } from '../filesystem/types.js';\nimport { FsError } from '../filesystem/fs-error.js';\nimport { parseWorkspacePath } from '../filesystem/workspace-path.js';\nimport { decodeUtf8Text } from '../filesystem/utf8.js';\nimport { DocumentCommitConflictError } from './document-session.js';\nimport type { DocumentCommitTarget, DocumentExternalVersion } from './types.js';\n\nexport interface FileSystemDocumentTargetOptions {\n /**\n * Compare the current file with the session's persisted baseline before\n * replacing it. Enabled by default.\n */\n verifyExternalChanges?: boolean;\n onCommitted?: (content: string, revision: number) => void;\n}\n\n/**\n * Adapt a FileSystemProvider path to the commit protocol used by\n * DocumentSession. The optimistic read catches external edits/deletions\n * before a local write recreates or silently replaces them.\n */\nexport function createFileSystemDocumentTarget(\n provider: FileSystemProvider,\n path: string,\n options: FileSystemDocumentTargetOptions = {},\n): DocumentCommitTarget {\n const verifyExternalChanges = options.verifyExternalChanges ?? true;\n const canonicalPath = parseWorkspacePath(path);\n const providerV2 = getFileSystemProviderV2(provider);\n return {\n key: provider.id + ':' + canonicalPath,\n async commit(request) {\n if (providerV2 && providerV2.capabilities.conditionalWrite !== 'none') {\n const current = await providerV2.readFile(canonicalPath);\n const currentContent = current\n ? decodeUtf8Text(current.data, {\n label: 'The external document',\n path: canonicalPath,\n })\n : null;\n if (currentContent !== request.persistedContent && currentContent !== request.content) {\n throw new DocumentCommitConflictError(\n 'The document changed outside DocBlocks: ' + path,\n currentContent,\n current?.entry.version ?? null,\n );\n }\n if (currentContent === request.content) {\n options.onCommitted?.(request.content, request.revision);\n return { version: current?.entry.version ?? null };\n }\n\n try {\n const committed = await providerV2.writeFile(\n canonicalPath,\n new TextEncoder().encode(request.content),\n {\n mode: current ? 'replace' : 'create',\n createParents: true,\n expectedVersion: current?.entry.version ?? null,\n },\n );\n options.onCommitted?.(request.content, request.revision);\n return { version: committed.version };\n } catch (error: unknown) {\n if (\n error instanceof FsError &&\n (error.code === 'conflict' ||\n error.code === 'already-exists' ||\n error.code === 'not-found')\n ) {\n const external = await providerV2.readFile(canonicalPath);\n throw new DocumentCommitConflictError(\n 'The document changed outside DocBlocks: ' + path,\n external\n ? decodeUtf8Text(external.data, {\n label: 'The external document',\n path: canonicalPath,\n })\n : null,\n external?.entry.version ?? null,\n );\n }\n throw error;\n }\n }\n\n if (provider.commitFile) {\n const result = await provider.commitFile(path, request.content, request.persistedContent);\n if (result.status === 'conflict') {\n throw new DocumentCommitConflictError(\n 'The document changed outside DocBlocks: ' + path,\n result.content,\n result.version,\n );\n }\n options.onCommitted?.(request.content, request.revision);\n return { version: result.version };\n }\n\n if (verifyExternalChanges) {\n const current = await provider.readFile(path);\n if (current !== request.persistedContent && current !== request.content) {\n const meta = await provider.stat(path).catch(() => null);\n const version: DocumentExternalVersion = meta?.lastModified ?? null;\n throw new DocumentCommitConflictError(\n 'The document changed outside DocBlocks: ' + path,\n current,\n version,\n );\n }\n }\n\n await provider.writeFile(path, request.content);\n options.onCommitted?.(request.content, request.revision);\n const meta = await provider.stat(path).catch(() => null);\n return { version: meta?.lastModified ?? null };\n },\n };\n}\n","/**\n * Synchronous crash-recovery journal for dirty document snapshots.\n *\n * The journal deliberately depends on a tiny injected Storage-like contract\n * instead of reading `window.localStorage` at module load time. This keeps the\n * document package usable in Node, Electron main, VS Code extension hosts, and\n * tests while allowing browser renderers to use localStorage for a best-effort\n * write that completes before the current JavaScript turn ends.\n */\n\nexport const DOCUMENT_RECOVERY_JOURNAL_STORAGE_KEY = 'docblocks:document-recovery:v1';\nexport const DOCUMENT_RECOVERY_JOURNAL_SCHEMA_VERSION = 1;\n\nexport interface DocumentRecoveryStorage {\n getItem(key: string): string | null;\n setItem(key: string, value: string): void;\n removeItem(key: string): void;\n}\n\nexport interface DocumentRecoveryRecord {\n /** Stable commit-target key, including the workspace/provider scope. */\n targetKey: string;\n /** DocumentSession generation that produced this snapshot. */\n generation: number;\n /** Monotonic DocumentSession revision represented by `content`. */\n revision: number;\n /** Complete markdown snapshot. */\n content: string;\n /**\n * Content last acknowledged by the commit target when this draft was made.\n * Recovery may be applied automatically only when storage still matches this\n * baseline; otherwise the caller must surface an external-change conflict.\n */\n persistedContent: string | null;\n /** Time the dirty record for this target was first created. */\n createdAt: number;\n /** Time the record was most recently replaced. */\n updatedAt: number;\n}\n\nexport interface DocumentRecoveryWrite {\n targetKey: string;\n generation: number;\n revision: number;\n content: string;\n persistedContent: string | null;\n}\n\nexport interface DocumentRecoveryAcknowledgement {\n targetKey: string;\n generation: number;\n /** Highest revision durably acknowledged by the commit target. */\n persistedRevision: number;\n}\n\nexport type DocumentRecoveryWriteFailure =\n | 'invalid-record'\n | 'record-too-large'\n | 'storage-unavailable'\n | 'quota-exceeded';\n\nexport type DocumentRecoveryWriteResult =\n | { status: 'stored'; evicted: number }\n | { status: 'unchanged'; evicted: 0 }\n | { status: 'ignored-stale'; evicted: 0 }\n | { status: 'rejected'; reason: DocumentRecoveryWriteFailure; evicted: number };\n\nexport interface DocumentRecoveryJournalOptions {\n storageKey?: string;\n /** Maximum number of document records retained. Defaults to 20. */\n maxEntries?: number;\n /** Conservative UTF-16 estimate for the whole serialized journal. */\n maxStorageBytes?: number;\n /** Conservative UTF-16 estimate for one serialized record. */\n maxRecordBytes?: number;\n /** Records older than this are discarded while reading. Defaults to 7 days. */\n maxAgeMs?: number;\n /** Tolerated clock skew for records dated in the future. Defaults to 5 minutes. */\n maxFutureSkewMs?: number;\n /** Injected for deterministic tests. */\n now?: () => number;\n}\n\ninterface DocumentRecoveryEnvelope {\n schemaVersion: typeof DOCUMENT_RECOVERY_JOURNAL_SCHEMA_VERSION;\n records: DocumentRecoveryRecord[];\n}\n\ninterface LoadedRecords {\n records: DocumentRecoveryRecord[];\n needsRepair: boolean;\n}\n\ninterface PersistResult {\n stored: boolean;\n evicted: number;\n reason?: 'storage-unavailable' | 'quota-exceeded';\n}\n\nconst DEFAULT_MAX_ENTRIES = 20;\nconst DEFAULT_MAX_STORAGE_BYTES = 2_000_000;\nconst DEFAULT_MAX_RECORD_BYTES = 1_000_000;\nconst DEFAULT_MAX_AGE_MS = 7 * 24 * 60 * 60 * 1000;\nconst DEFAULT_MAX_FUTURE_SKEW_MS = 5 * 60 * 1000;\nconst MAX_TARGET_KEY_LENGTH = 4096;\n\n/**\n * Best-effort, synchronous recovery storage.\n *\n * Normal save acknowledgement is the only automatic path that removes the\n * current record. Explicit discard, age expiry, corruption repair, and bounded\n * eviction are intentional exceptions: callers can discard after the user\n * rejects recovery, and the journal must never grow without limit.\n */\nexport class DocumentRecoveryJournal {\n private readonly storage: DocumentRecoveryStorage | null;\n private readonly storageKey: string;\n private readonly maxEntries: number;\n private readonly maxStorageBytes: number;\n private readonly maxRecordBytes: number;\n private readonly maxAgeMs: number;\n private readonly maxFutureSkewMs: number;\n private readonly now: () => number;\n\n public constructor(\n storage: DocumentRecoveryStorage | null,\n options: DocumentRecoveryJournalOptions = {},\n ) {\n this.storage = storage;\n this.storageKey = options.storageKey?.trim() || DOCUMENT_RECOVERY_JOURNAL_STORAGE_KEY;\n this.maxEntries = positiveInteger(options.maxEntries, DEFAULT_MAX_ENTRIES);\n this.maxStorageBytes = positiveInteger(options.maxStorageBytes, DEFAULT_MAX_STORAGE_BYTES);\n this.maxRecordBytes = Math.min(\n positiveInteger(options.maxRecordBytes, DEFAULT_MAX_RECORD_BYTES),\n this.maxStorageBytes,\n );\n this.maxAgeMs = nonNegativeFinite(options.maxAgeMs, DEFAULT_MAX_AGE_MS);\n this.maxFutureSkewMs = nonNegativeFinite(options.maxFutureSkewMs, DEFAULT_MAX_FUTURE_SKEW_MS);\n this.now = options.now ?? Date.now;\n }\n\n /**\n * Synchronously persist the latest dirty snapshot for a target.\n * Storage/quota failures are returned, never thrown into an editor onChange.\n */\n public write(input: DocumentRecoveryWrite): DocumentRecoveryWriteResult {\n const timestamp = this.now();\n if (!isValidWrite(input) || !Number.isFinite(timestamp) || timestamp < 0) {\n return { status: 'rejected', reason: 'invalid-record', evicted: 0 };\n }\n if (!this.storage) {\n return { status: 'rejected', reason: 'storage-unavailable', evicted: 0 };\n }\n if (\n estimatedBytes(input.content) > this.maxRecordBytes ||\n (input.persistedContent !== null &&\n estimatedBytes(input.persistedContent) > this.maxRecordBytes)\n ) {\n return { status: 'rejected', reason: 'record-too-large', evicted: 0 };\n }\n\n const loaded = this.load(timestamp);\n const existing = loaded.records.find((record) => record.targetKey === input.targetKey);\n if (existing) {\n const ordering = compareGenerationRevision(input, existing);\n if (ordering < 0) return { status: 'ignored-stale', evicted: 0 };\n if (ordering === 0) {\n if (\n existing.content === input.content &&\n existing.persistedContent === input.persistedContent\n ) {\n return { status: 'unchanged', evicted: 0 };\n }\n // A revision is an immutable content snapshot. Reusing it for different\n // content would make acknowledgement and recovery ambiguous.\n return { status: 'rejected', reason: 'invalid-record', evicted: 0 };\n }\n }\n\n const candidate: DocumentRecoveryRecord = {\n targetKey: input.targetKey,\n generation: input.generation,\n revision: input.revision,\n content: input.content,\n persistedContent: input.persistedContent,\n createdAt: existing?.createdAt ?? timestamp,\n updatedAt: timestamp,\n };\n if (estimatedBytes(JSON.stringify(candidate)) > this.maxRecordBytes) {\n return { status: 'rejected', reason: 'record-too-large', evicted: 0 };\n }\n if (estimatedBytes(serializeEnvelope([candidate])) > this.maxStorageBytes) {\n return { status: 'rejected', reason: 'record-too-large', evicted: 0 };\n }\n\n const next = loaded.records.filter((record) => record.targetKey !== input.targetKey);\n next.push(candidate);\n const persisted = this.persistBounded(next, input.targetKey);\n if (!persisted.stored) {\n return {\n status: 'rejected',\n reason: persisted.reason ?? 'quota-exceeded',\n evicted: persisted.evicted,\n };\n }\n return { status: 'stored', evicted: persisted.evicted };\n }\n\n /** Return the recoverable snapshot for one target, if present and valid. */\n public lookup(targetKey: string, generation?: number): DocumentRecoveryRecord | null {\n if (!isValidTargetKey(targetKey) || !isOptionalGeneration(generation)) return null;\n const record = this.load(this.now()).records.find(\n (candidate) =>\n candidate.targetKey === targetKey &&\n (generation === undefined || candidate.generation === generation),\n );\n return record ? cloneRecord(record) : null;\n }\n\n /** List valid records, newest first. Optionally restrict to one target. */\n public list(targetKey?: string): DocumentRecoveryRecord[] {\n if (targetKey !== undefined && !isValidTargetKey(targetKey)) return [];\n return this.load(this.now())\n .records.filter((record) => targetKey === undefined || record.targetKey === targetKey)\n .sort(compareNewestFirst)\n .map(cloneRecord);\n }\n\n /**\n * Clear a record only when the same generation has durably acknowledged at\n * least the journaled revision. A stale acknowledgement cannot erase a newer\n * crash-recovery snapshot.\n */\n public acknowledge(input: DocumentRecoveryAcknowledgement): boolean {\n if (!isValidAcknowledgement(input) || !this.storage) return false;\n const records = this.load(this.now()).records;\n const record = records.find((candidate) => candidate.targetKey === input.targetKey);\n if (\n !record ||\n record.generation !== input.generation ||\n record.revision > input.persistedRevision\n ) {\n return false;\n }\n\n return this.persistExact(records.filter((candidate) => candidate !== record));\n }\n\n /** Explicitly discard recovery data after a user or lifecycle decision. */\n public discard(targetKey: string, generation?: number): boolean {\n if (!isValidTargetKey(targetKey) || !isOptionalGeneration(generation) || !this.storage) {\n return false;\n }\n const records = this.load(this.now()).records;\n const next = records.filter(\n (record) =>\n record.targetKey !== targetKey ||\n (generation !== undefined && record.generation !== generation),\n );\n if (next.length === records.length) return false;\n return this.persistExact(next);\n }\n\n private load(timestamp: number): LoadedRecords {\n if (!this.storage) return { records: [], needsRepair: false };\n\n let raw: string | null;\n try {\n raw = this.storage.getItem(this.storageKey);\n } catch {\n return { records: [], needsRepair: false };\n }\n if (raw === null) return { records: [], needsRepair: false };\n\n let parsed: unknown;\n try {\n parsed = JSON.parse(raw) as unknown;\n } catch {\n this.tryRemove();\n return { records: [], needsRepair: true };\n }\n if (!isEnvelope(parsed)) {\n this.tryRemove();\n return { records: [], needsRepair: true };\n }\n\n const byTarget = new Map<string, DocumentRecoveryRecord>();\n let needsRepair = estimatedBytes(raw) > this.maxStorageBytes;\n for (const candidate of parsed.records) {\n if (!isValidStoredRecord(candidate, timestamp, this.maxAgeMs, this.maxFutureSkewMs)) {\n needsRepair = true;\n continue;\n }\n if (estimatedBytes(JSON.stringify(candidate)) > this.maxRecordBytes) {\n needsRepair = true;\n continue;\n }\n const current = byTarget.get(candidate.targetKey);\n if (!current || compareStoredRecords(candidate, current) > 0) {\n if (current) needsRepair = true;\n byTarget.set(candidate.targetKey, cloneRecord(candidate));\n } else {\n needsRepair = true;\n }\n }\n\n const records = [...byTarget.values()].sort(compareNewestFirst);\n while (records.length > this.maxEntries) {\n records.pop();\n needsRepair = true;\n }\n while (\n records.length > 0 &&\n estimatedBytes(serializeEnvelope(records)) > this.maxStorageBytes\n ) {\n records.pop();\n needsRepair = true;\n }\n if (needsRepair) {\n // Best effort only. Read APIs must still return the validated in-memory\n // records even when storage is temporarily unavailable.\n this.persistBounded(records);\n }\n return { records, needsRepair };\n }\n\n private persistBounded(\n records: DocumentRecoveryRecord[],\n protectedTarget?: string,\n ): PersistResult {\n if (!this.storage) {\n return { stored: false, evicted: 0, reason: 'storage-unavailable' };\n }\n\n const next = [...records].sort(compareNewestFirst);\n let evicted = 0;\n while (next.length > this.maxEntries) {\n if (!evictOldest(next, protectedTarget)) break;\n evicted += 1;\n }\n\n let serialized = serializeEnvelope(next);\n while (estimatedBytes(serialized) > this.maxStorageBytes) {\n if (!evictOldest(next, protectedTarget)) {\n return { stored: false, evicted, reason: 'quota-exceeded' };\n }\n evicted += 1;\n serialized = serializeEnvelope(next);\n }\n\n for (;;) {\n try {\n this.storage.setItem(this.storageKey, serialized);\n return { stored: true, evicted };\n } catch {\n if (!evictOldest(next, protectedTarget)) {\n return { stored: false, evicted, reason: 'quota-exceeded' };\n }\n evicted += 1;\n serialized = serializeEnvelope(next);\n }\n }\n }\n\n private persistExact(records: DocumentRecoveryRecord[]): boolean {\n if (!this.storage) return false;\n if (records.length === 0) {\n try {\n this.storage.removeItem(this.storageKey);\n return true;\n } catch {\n return false;\n }\n }\n try {\n this.storage.setItem(this.storageKey, serializeEnvelope(records));\n return true;\n } catch {\n return false;\n }\n }\n\n private tryRemove(): void {\n try {\n this.storage?.removeItem(this.storageKey);\n } catch {\n // Recovery is best effort; a denied cleanup must not fail application startup.\n }\n }\n}\n\n/**\n * Resolve browser localStorage on demand. Importing this module never touches\n * browser globals, and access errors (sandboxing/security settings) yield null.\n */\nexport function getDefaultDocumentRecoveryStorage(): DocumentRecoveryStorage | null {\n try {\n const candidate = Reflect.get(globalThis, 'localStorage') as unknown;\n if (!isStorage(candidate)) return null;\n return candidate;\n } catch {\n return null;\n }\n}\n\nfunction serializeEnvelope(records: DocumentRecoveryRecord[]): string {\n const envelope: DocumentRecoveryEnvelope = {\n schemaVersion: DOCUMENT_RECOVERY_JOURNAL_SCHEMA_VERSION,\n records,\n };\n return JSON.stringify(envelope);\n}\n\n/** localStorage quotas are commonly measured from UTF-16 storage usage. */\nfunction estimatedBytes(value: string): number {\n return value.length * 2;\n}\n\nfunction positiveInteger(value: number | undefined, fallback: number): number {\n return Number.isSafeInteger(value) && (value ?? 0) > 0 ? (value as number) : fallback;\n}\n\nfunction nonNegativeFinite(value: number | undefined, fallback: number): number {\n return Number.isFinite(value) && (value ?? -1) >= 0 ? (value as number) : fallback;\n}\n\nfunction isEnvelope(value: unknown): value is DocumentRecoveryEnvelope {\n if (!isObject(value)) return false;\n return (\n value.schemaVersion === DOCUMENT_RECOVERY_JOURNAL_SCHEMA_VERSION && Array.isArray(value.records)\n );\n}\n\nfunction isValidStoredRecord(\n value: unknown,\n timestamp: number,\n maxAgeMs: number,\n maxFutureSkewMs: number,\n): value is DocumentRecoveryRecord {\n if (!isObject(value)) return false;\n if (\n !isValidTargetKey(value.targetKey) ||\n !isNonNegativeSafeInteger(value.generation) ||\n !isNonNegativeSafeInteger(value.revision) ||\n typeof value.content !== 'string' ||\n (value.persistedContent !== null && typeof value.persistedContent !== 'string') ||\n !isNonNegativeFiniteNumber(value.createdAt) ||\n !isNonNegativeFiniteNumber(value.updatedAt) ||\n value.createdAt > value.updatedAt\n ) {\n return false;\n }\n if (!Number.isFinite(timestamp) || timestamp < 0) return false;\n if (value.updatedAt > timestamp + maxFutureSkewMs) return false;\n return timestamp - value.updatedAt <= maxAgeMs;\n}\n\nfunction isValidWrite(value: DocumentRecoveryWrite): boolean {\n return (\n isValidTargetKey(value.targetKey) &&\n isNonNegativeSafeInteger(value.generation) &&\n isNonNegativeSafeInteger(value.revision) &&\n typeof value.content === 'string' &&\n (value.persistedContent === null || typeof value.persistedContent === 'string')\n );\n}\n\nfunction isValidAcknowledgement(value: DocumentRecoveryAcknowledgement): boolean {\n return (\n isValidTargetKey(value.targetKey) &&\n isNonNegativeSafeInteger(value.generation) &&\n isNonNegativeSafeInteger(value.persistedRevision)\n );\n}\n\nfunction isValidTargetKey(value: unknown): value is string {\n return typeof value === 'string' && value.length > 0 && value.length <= MAX_TARGET_KEY_LENGTH;\n}\n\nfunction isOptionalGeneration(value: number | undefined): boolean {\n return value === undefined || isNonNegativeSafeInteger(value);\n}\n\nfunction isNonNegativeSafeInteger(value: unknown): value is number {\n return typeof value === 'number' && Number.isSafeInteger(value) && value >= 0;\n}\n\nfunction isNonNegativeFiniteNumber(value: unknown): value is number {\n return typeof value === 'number' && Number.isFinite(value) && value >= 0;\n}\n\nfunction isObject(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null;\n}\n\nfunction isStorage(value: unknown): value is DocumentRecoveryStorage {\n if (!isObject(value)) return false;\n return (\n typeof value.getItem === 'function' &&\n typeof value.setItem === 'function' &&\n typeof value.removeItem === 'function'\n );\n}\n\nfunction compareGenerationRevision(\n left: Pick<DocumentRecoveryRecord, 'generation' | 'revision'>,\n right: Pick<DocumentRecoveryRecord, 'generation' | 'revision'>,\n): number {\n if (left.generation !== right.generation) return left.generation - right.generation;\n return left.revision - right.revision;\n}\n\nfunction compareStoredRecords(left: DocumentRecoveryRecord, right: DocumentRecoveryRecord): number {\n return compareGenerationRevision(left, right) || left.updatedAt - right.updatedAt;\n}\n\nfunction compareNewestFirst(left: DocumentRecoveryRecord, right: DocumentRecoveryRecord): number {\n return right.updatedAt - left.updatedAt || right.revision - left.revision;\n}\n\nfunction cloneRecord(record: DocumentRecoveryRecord): DocumentRecoveryRecord {\n return { ...record };\n}\n\nfunction evictOldest(records: DocumentRecoveryRecord[], protectedTarget?: string): boolean {\n let oldestIndex = -1;\n for (let index = 0; index < records.length; index += 1) {\n if (records[index].targetKey === protectedTarget) continue;\n if (oldestIndex < 0 || compareNewestFirst(records[index], records[oldestIndex]) > 0) {\n oldestIndex = index;\n }\n }\n if (oldestIndex < 0) return false;\n records.splice(oldestIndex, 1);\n return true;\n}\n"],"mappings":"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","names":["meta"]}
@@ -1,6 +1,15 @@
1
1
  import {
2
+ parentChainWithRoot
3
+ } from "./chunk-GM5YXU4L.js";
4
+ import {
5
+ compareSnapshotsByName,
6
+ compareText,
7
+ copyBytes,
2
8
  parseFileSystemVersion
3
- } from "./chunk-AYZ4HN5M.js";
9
+ } from "./chunk-P4WATND4.js";
10
+ import {
11
+ decodeUtf8Text
12
+ } from "./chunk-FA7UNOXK.js";
4
13
  import {
5
14
  FsError,
6
15
  WORKSPACE_ROOT,
@@ -8,7 +17,7 @@ import {
8
17
  workspacePathBasename,
9
18
  workspacePathContains,
10
19
  workspacePathDirname
11
- } from "./chunk-SI2LU2RP.js";
20
+ } from "./chunk-JS6XFWQK.js";
12
21
 
13
22
  // src/filesystem/memory-provider-v2.ts
14
23
  var MEMORY_CAPABILITIES = Object.freeze({
@@ -126,7 +135,7 @@ var MemoryFileSystemProviderV2 = class {
126
135
  "Replacement path has conflicting file and directory kinds."
127
136
  );
128
137
  }
129
- for (const parent of parentChain(path)) {
138
+ for (const parent of parentChainWithRoot(path)) {
130
139
  if (parent && stagedFiles.has(parent)) {
131
140
  throw this.error("type-mismatch", "write", parent, "A replacement parent is a file.");
132
141
  }
@@ -185,8 +194,12 @@ var MemoryFileSystemProviderV2 = class {
185
194
  if (existing?.kind === "directory") {
186
195
  throw this.error("type-mismatch", "write", canonical, "Cannot replace a directory.");
187
196
  }
188
- const currentContent = existing?.kind === "file" && existing.payloadKind === "text" ? new TextDecoder().decode(existing.data) : null;
189
- if (existing?.kind === "file" && existing.payloadKind === "binary" || currentContent !== expectedContent && currentContent !== content) {
197
+ const currentContent = existing?.kind === "file" ? decodeUtf8Text(existing.data, {
198
+ label: "The stored file",
199
+ operation: "write",
200
+ path: canonical
201
+ }) : null;
202
+ if (currentContent !== expectedContent && currentContent !== content) {
190
203
  return {
191
204
  status: "conflict",
192
205
  content: currentContent,
@@ -246,7 +259,7 @@ var MemoryFileSystemProviderV2 = class {
246
259
  children.push(this.toEntrySnapshot(entryPath2, entry));
247
260
  }
248
261
  }
249
- children.sort(compareSnapshots);
262
+ children.sort(compareSnapshotsByName);
250
263
  return Object.freeze(children);
251
264
  }
252
265
  async writeFile(path, data, options = {}) {
@@ -537,7 +550,7 @@ var MemoryFileSystemProviderV2 = class {
537
550
  }
538
551
  planParents(path, createParents, operation) {
539
552
  const missing = [];
540
- for (const parent of parentChain(path)) {
553
+ for (const parent of parentChainWithRoot(path)) {
541
554
  if (!parent) continue;
542
555
  const entry = this.entries.get(parent);
543
556
  if (entry?.kind === "file") {
@@ -563,7 +576,7 @@ var MemoryFileSystemProviderV2 = class {
563
576
  }
564
577
  }
565
578
  touchParents(target, path, version, lastModified) {
566
- for (const parent of parentChain(path)) {
579
+ for (const parent of parentChainWithRoot(path)) {
567
580
  const entry = target.get(parent);
568
581
  if (entry?.kind === "directory") {
569
582
  target.set(parent, { kind: "directory", version, lastModified });
@@ -635,36 +648,14 @@ var MemoryFileSystemProviderV2 = class {
635
648
  return new FsError(code, message, { operation, path });
636
649
  }
637
650
  };
638
- function parentChain(path) {
639
- const parents = [];
640
- let current = workspacePathDirname(path);
641
- while (true) {
642
- parents.unshift(current);
643
- if (!current) return parents;
644
- current = workspacePathDirname(current);
645
- }
646
- }
647
651
  function addParentPaths(target, path) {
648
- for (const parent of parentChain(path)) {
652
+ for (const parent of parentChainWithRoot(path)) {
649
653
  if (parent) target.add(parent);
650
654
  }
651
655
  }
652
656
  function isMemoryFilePayloadKind(value) {
653
657
  return value === "text" || value === "binary";
654
658
  }
655
- function copyBytes(data) {
656
- const source = ArrayBuffer.isView(data) ? new Uint8Array(data.buffer, data.byteOffset, data.byteLength) : new Uint8Array(data);
657
- const copy = new Uint8Array(source.byteLength);
658
- copy.set(source);
659
- return copy.buffer;
660
- }
661
- function compareSnapshots(left, right) {
662
- if (left.kind !== right.kind) return left.kind === "directory" ? -1 : 1;
663
- return compareText(left.name, right.name);
664
- }
665
- function compareText(left, right) {
666
- return left < right ? -1 : left > right ? 1 : 0;
667
- }
668
659
 
669
660
  // src/filesystem/memory-provider.ts
670
661
  function canonicalPath(path) {
@@ -680,8 +671,8 @@ function entryPath(path, operation) {
680
671
  }
681
672
  return canonical;
682
673
  }
683
- function decode(data) {
684
- return new TextDecoder().decode(data);
674
+ function decode(data, path) {
675
+ return decodeUtf8Text(data, { label: "The file", operation: "read", path });
685
676
  }
686
677
  var MemoryFileSystemProvider = class {
687
678
  constructor(id, label) {
@@ -698,7 +689,7 @@ var MemoryFileSystemProvider = class {
698
689
  const state = this.v2.captureState();
699
690
  return {
700
691
  files: state.files.map(
701
- (file) => file.payloadKind === "text" ? { kind: "text", path: file.path, content: decode(file.data) } : { kind: "binary", path: file.path, data: file.data.slice(0) }
692
+ (file) => file.payloadKind === "text" ? { kind: "text", path: file.path, content: decode(file.data, file.path) } : { kind: "binary", path: file.path, data: file.data.slice(0) }
702
693
  ),
703
694
  directories: [...state.directories]
704
695
  };
@@ -720,20 +711,21 @@ var MemoryFileSystemProvider = class {
720
711
  this.v2.seedText(entryPath(path, "write"), content);
721
712
  }
722
713
  async readFile(path) {
723
- const file = await this.v2.readFile(entryPath(path, "read"));
724
- return file ? decode(file.data) : null;
714
+ const canonical = canonicalPath(path);
715
+ const file = await this.v2.readFile(canonical);
716
+ return file ? decode(file.data, canonical) : null;
725
717
  }
726
718
  async writeFile(path, content) {
727
- await this.v2.writeText(entryPath(path, "write"), content, { createParents: true });
719
+ await this.v2.writeText(canonicalPath(path), content, { createParents: true });
728
720
  }
729
721
  commitFile(path, content, expectedContent) {
730
- return this.v2.commitText(entryPath(path, "write"), content, expectedContent);
722
+ return this.v2.commitText(canonicalPath(path), content, expectedContent);
731
723
  }
732
724
  async delete(path) {
733
- await this.v2.remove(entryPath(path, "remove"), { recursive: true, missing: "ignore" });
725
+ await this.v2.remove(canonicalPath(path), { recursive: true, missing: "ignore" });
734
726
  }
735
727
  async rename(oldPath, newPath) {
736
- await this.v2.move(entryPath(oldPath, "move"), entryPath(newPath, "move"), {
728
+ await this.v2.move(canonicalPath(oldPath), canonicalPath(newPath), {
737
729
  createParents: true
738
730
  });
739
731
  }
@@ -758,9 +750,7 @@ var MemoryFileSystemProvider = class {
758
750
  await this.v2.createDirectory(canonicalPath(path), { createParents: true });
759
751
  }
760
752
  async stat(path) {
761
- const canonical = canonicalPath(path);
762
- if (!canonical) return null;
763
- const entry = await this.v2.stat(canonical);
753
+ const entry = await this.v2.stat(canonicalPath(path));
764
754
  if (!entry || entry.kind !== "file") return null;
765
755
  return {
766
756
  name: entry.name,
@@ -769,14 +759,17 @@ var MemoryFileSystemProvider = class {
769
759
  lastModified: entry.lastModified
770
760
  };
771
761
  }
762
+ /**
763
+ * Every stored file is bytes, so every stored file is readable as binary.
764
+ * `payloadKind` records how a file was written for DBK export fidelity; it is
765
+ * not a filter. Gating on it made `readBinary` report an existing text file as
766
+ * missing, which no other provider does and which callers read as "no file".
767
+ */
772
768
  async readBinary(path) {
773
- const canonical = entryPath(path, "read");
774
- const file = this.v2.readCompatibilityFile(canonical);
775
- if (!file || file.payloadKind !== "binary") return null;
776
- return file.data;
769
+ return this.v2.readCompatibilityFile(canonicalPath(path))?.data ?? null;
777
770
  }
778
771
  async writeBinary(path, data) {
779
- await this.v2.writeBinary(entryPath(path, "write"), data, { createParents: true });
772
+ await this.v2.writeBinary(canonicalPath(path), data, { createParents: true });
780
773
  }
781
774
  };
782
775
 
@@ -784,4 +777,4 @@ export {
784
777
  MemoryFileSystemProviderV2,
785
778
  MemoryFileSystemProvider
786
779
  };
787
- //# sourceMappingURL=chunk-RQJRQF46.js.map
780
+ //# sourceMappingURL=chunk-DN7A33LL.js.map
@@ -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';\nimport { copyBytes } from './internal/bytes.js';\nimport { compareSnapshotsByName, compareText } from './internal/entry-order.js';\nimport { parentChainWithRoot } from './internal/parent-chain.js';\nimport { decodeUtf8Text } from './utf8.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 parentChainWithRoot(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 // Every file is bytes, so the baseline is decided by the bytes, not by the\n // compatibility kind. Gating on `payloadKind === 'binary'` reported\n // `conflict` with a null `content`, which callers read as \"deleted\n // externally\" — a phantom deletion for a file that is plainly still there.\n // Undecodable bytes are a real fault and are raised as one, matching the\n // IndexedDB facade and the v2 commit target.\n const currentContent =\n existing?.kind === 'file'\n ? decodeUtf8Text(existing.data, {\n label: 'The stored file',\n operation: 'write',\n path: canonical,\n })\n : null;\n if (currentContent !== expectedContent && currentContent !== content) {\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(compareSnapshotsByName);\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 parentChainWithRoot(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 parentChainWithRoot(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 addParentPaths(target: Set<WorkspacePath>, path: WorkspacePath): void {\n for (const parent of parentChainWithRoot(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","/**\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';\nimport { decodeUtf8Text } from './utf8.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\n/**\n * Canonicalize and reject the root eagerly.\n *\n * Only the synchronous staging entry points need this: they must validate every\n * input before `replaceState` swaps the tree, so they cannot rely on the v2\n * authority to reject the root mid-swap. The async provider methods pass paths\n * straight through, letting v2 state root policy once for every facade.\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\n/**\n * Byte-authoritative entries may hold payloads that are not valid UTF-8. A\n * lossy decode would hand the caller replacement characters that a later save\n * writes back over the user's original bytes, so surface the fault instead.\n */\nfunction decode(data: ArrayBuffer, path?: WorkspacePath): string {\n return decodeUtf8Text(data, { label: 'The file', operation: 'read', path });\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, file.path) }\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 canonical = canonicalPath(path);\n const file = await this.v2.readFile(canonical);\n return file ? decode(file.data, canonical) : null;\n }\n\n public async writeFile(path: string, content: string): Promise<void> {\n await this.v2.writeText(canonicalPath(path), 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(canonicalPath(path), content, expectedContent);\n }\n\n public async delete(path: string): Promise<void> {\n await this.v2.remove(canonicalPath(path), { recursive: true, missing: 'ignore' });\n }\n\n public async rename(oldPath: string, newPath: string): Promise<void> {\n await this.v2.move(canonicalPath(oldPath), canonicalPath(newPath), {\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 entry = await this.v2.stat(canonicalPath(path));\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 /**\n * Every stored file is bytes, so every stored file is readable as binary.\n * `payloadKind` records how a file was written for DBK export fidelity; it is\n * not a filter. Gating on it made `readBinary` report an existing text file as\n * missing, which no other provider does and which callers read as \"no file\".\n */\n public async readBinary(path: string): Promise<ArrayBuffer | null> {\n return this.v2.readCompatibilityFile(canonicalPath(path))?.data ?? null;\n }\n\n public async writeBinary(path: string, data: ArrayBuffer | Uint8Array): Promise<void> {\n await this.v2.writeBinary(canonicalPath(path), data, { createParents: true });\n }\n}\n"],"mappings":"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","names":["entryPath"]}
@@ -0,0 +1,20 @@
1
+ import {
2
+ FsError
3
+ } from "./chunk-JS6XFWQK.js";
4
+
5
+ // src/filesystem/utf8.ts
6
+ function decodeUtf8Text(data, options = {}) {
7
+ try {
8
+ return new TextDecoder("utf-8", { fatal: true }).decode(data);
9
+ } catch {
10
+ throw new FsError("corrupt", `${options.label ?? "Text content"} is not valid UTF-8.`, {
11
+ operation: options.operation ?? "read",
12
+ path: options.path
13
+ });
14
+ }
15
+ }
16
+
17
+ export {
18
+ decodeUtf8Text
19
+ };
20
+ //# sourceMappingURL=chunk-FA7UNOXK.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/filesystem/utf8.ts"],"sourcesContent":["import { FsError, type FsOperation } from './fs-error.js';\n\nexport interface DecodeUtf8TextOptions {\n /** User-facing description of the payload being decoded. */\n readonly label?: string;\n /** Filesystem operation that produced the bytes. */\n readonly operation?: FsOperation;\n /** Canonical or display path associated with the payload. */\n readonly path?: string;\n}\n\n/**\n * Decode byte-authoritative text without silently replacing malformed input.\n * Replacement characters are unsafe at persistence boundaries because a later\n * save can permanently overwrite the original bytes with altered content.\n */\nexport function decodeUtf8Text(\n data: ArrayBuffer | ArrayBufferView,\n options: DecodeUtf8TextOptions = {},\n): string {\n try {\n return new TextDecoder('utf-8', { fatal: true }).decode(data);\n } catch {\n throw new FsError('corrupt', `${options.label ?? 'Text content'} is not valid UTF-8.`, {\n operation: options.operation ?? 'read',\n path: options.path,\n });\n }\n}\n"],"mappings":";;;;;AAgBO,SAAS,eACd,MACA,UAAiC,CAAC,GAC1B;AACR,MAAI;AACF,WAAO,IAAI,YAAY,SAAS,EAAE,OAAO,KAAK,CAAC,EAAE,OAAO,IAAI;AAAA,EAC9D,QAAQ;AACN,UAAM,IAAI,QAAQ,WAAW,GAAG,QAAQ,SAAS,cAAc,wBAAwB;AAAA,MACrF,WAAW,QAAQ,aAAa;AAAA,MAChC,MAAM,QAAQ;AAAA,IAChB,CAAC;AAAA,EACH;AACF;","names":[]}
@@ -0,0 +1,29 @@
1
+ import {
2
+ workspacePathDirname
3
+ } from "./chunk-JS6XFWQK.js";
4
+
5
+ // src/filesystem/internal/parent-chain.ts
6
+ function parentChain(path) {
7
+ const parents = [];
8
+ let current = workspacePathDirname(path);
9
+ while (current) {
10
+ parents.unshift(current);
11
+ current = workspacePathDirname(current);
12
+ }
13
+ return parents;
14
+ }
15
+ function parentChainWithRoot(path) {
16
+ const parents = [];
17
+ let current = workspacePathDirname(path);
18
+ while (true) {
19
+ parents.unshift(current);
20
+ if (!current) return parents;
21
+ current = workspacePathDirname(current);
22
+ }
23
+ }
24
+
25
+ export {
26
+ parentChain,
27
+ parentChainWithRoot
28
+ };
29
+ //# sourceMappingURL=chunk-GM5YXU4L.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/filesystem/internal/parent-chain.ts"],"sourcesContent":["/**\n * Ancestor enumeration shared by every filesystem provider.\n *\n * Two variants exist because backends genuinely disagree about whether the\n * workspace root is an *entry*, and that difference is real rather than\n * accidental:\n *\n * - IndexedDB and memory store the root as a first-class directory record\n * (IndexedDB initialization fails with `corrupt` if the root record is\n * missing). Their parent walks must visit the root so it is version-bumped\n * and kind-checked like any other directory.\n * - Native (File System Access) has no root record — the root *is* the\n * directory handle the user granted, always present and never created.\n * Visiting it would be a guaranteed no-op.\n *\n * Both orderings are root-most first, so callers that create missing parents\n * create them top-down.\n */\n\nimport { workspacePathDirname, type WorkspacePath } from '../workspace-path.js';\n\n/**\n * Strict ancestors of `path`, excluding the workspace root.\n *\n * Use when the root is implicit and always exists.\n */\nexport function parentChain(path: WorkspacePath): WorkspacePath[] {\n const parents: WorkspacePath[] = [];\n let current = workspacePathDirname(path);\n while (current) {\n parents.unshift(current);\n current = workspacePathDirname(current);\n }\n return parents;\n}\n\n/**\n * Strict ancestors of `path`, including the workspace root as the first entry.\n *\n * Use when the root is a stored entry that participates in kind checks and\n * version bumps.\n */\nexport function parentChainWithRoot(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"],"mappings":";;;;;AA0BO,SAAS,YAAY,MAAsC;AAChE,QAAM,UAA2B,CAAC;AAClC,MAAI,UAAU,qBAAqB,IAAI;AACvC,SAAO,SAAS;AACd,YAAQ,QAAQ,OAAO;AACvB,cAAU,qBAAqB,OAAO;AAAA,EACxC;AACA,SAAO;AACT;AAQO,SAAS,oBAAoB,MAAsC;AACxE,QAAM,UAA2B,CAAC;AAClC,MAAI,UAAU,qBAAqB,IAAI;AACvC,SAAO,MAAM;AACX,YAAQ,QAAQ,OAAO;AACvB,QAAI,CAAC,QAAS,QAAO;AACrB,cAAU,qBAAqB,OAAO;AAAA,EACxC;AACF;","names":[]}
@@ -8,6 +8,7 @@ var FS_ERROR_CODES = /* @__PURE__ */ new Set([
8
8
  "not-empty",
9
9
  "permission-denied",
10
10
  "conflict",
11
+ "corrupt",
11
12
  "quota-exceeded",
12
13
  "not-supported",
13
14
  "busy",
@@ -221,4 +222,4 @@ export {
221
222
  workspacePathBasename,
222
223
  workspacePathContains
223
224
  };
224
- //# sourceMappingURL=chunk-SI2LU2RP.js.map
225
+ //# sourceMappingURL=chunk-JS6XFWQK.js.map