@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
@@ -2,8 +2,21 @@ import {
2
2
  withFileCommitLock
3
3
  } from "./chunk-AEHCVWU5.js";
4
4
  import {
5
+ parentChainWithRoot
6
+ } from "./chunk-GM5YXU4L.js";
7
+ import {
8
+ isRecord
9
+ } from "./chunk-U722UUFN.js";
10
+ import {
11
+ bytesEqual,
12
+ compareSnapshotsByName,
13
+ compareText,
14
+ copyBytes,
5
15
  parseFileSystemVersion
6
- } from "./chunk-AYZ4HN5M.js";
16
+ } from "./chunk-P4WATND4.js";
17
+ import {
18
+ decodeUtf8Text
19
+ } from "./chunk-FA7UNOXK.js";
7
20
  import {
8
21
  FsError,
9
22
  WORKSPACE_ROOT,
@@ -12,160 +25,19 @@ import {
12
25
  workspacePathBasename,
13
26
  workspacePathContains,
14
27
  workspacePathDirname
15
- } from "./chunk-SI2LU2RP.js";
16
-
17
- // src/filesystem/indexeddb-store.ts
18
- var RawIndexedDBFileSystemStore = class {
19
- constructor(databaseName, storeName) {
20
- this.databaseName = databaseName;
21
- this.storeName = storeName;
22
- this.database = null;
23
- this.opening = null;
24
- this.closed = false;
25
- }
26
- async transaction(mode, operation) {
27
- const database = await this.getDatabase();
28
- const nativeTransaction = database.transaction(this.storeName, mode);
29
- const completion = waitForTransaction(nativeTransaction);
30
- const transaction = new RawIndexedDBFileSystemTransaction(
31
- nativeTransaction.objectStore(this.storeName)
32
- );
33
- let result;
34
- try {
35
- result = await operation(transaction);
36
- } catch (error) {
37
- try {
38
- nativeTransaction.abort();
39
- } catch {
40
- }
41
- await completion.catch(() => void 0);
42
- throw error;
43
- }
44
- await completion;
45
- return result;
46
- }
47
- close() {
48
- if (this.closed) return;
49
- this.closed = true;
50
- this.database?.close();
51
- this.database = null;
52
- this.opening = null;
53
- }
54
- getDatabase() {
55
- if (this.closed) {
56
- return Promise.reject(new Error("The IndexedDB filesystem store is closed."));
57
- }
58
- if (this.database) return Promise.resolve(this.database);
59
- if (this.opening) return this.opening;
60
- if (typeof indexedDB === "undefined") {
61
- return Promise.reject(new Error("IndexedDB is not available in this environment."));
62
- }
63
- this.opening = openDatabaseWithStore(this.databaseName, this.storeName).then((database) => {
64
- if (this.closed) {
65
- database.close();
66
- throw new Error("The IndexedDB filesystem store is closed.");
67
- }
68
- this.database = database;
69
- this.opening = null;
70
- database.onversionchange = () => {
71
- database.close();
72
- if (this.database === database) this.database = null;
73
- };
74
- return database;
75
- }).catch((error) => {
76
- this.opening = null;
77
- throw error;
78
- });
79
- return this.opening;
80
- }
81
- };
82
- var RawIndexedDBFileSystemTransaction = class {
83
- constructor(store) {
84
- this.store = store;
85
- }
86
- async get(key) {
87
- const value = await requestResult(this.store.get(key));
88
- return value === void 0 ? null : value;
89
- }
90
- async put(key, value) {
91
- await requestResult(this.store.put(value, key));
92
- }
93
- async delete(key) {
94
- await requestResult(this.store.delete(key));
95
- }
96
- async keys() {
97
- const keys = await requestResult(this.store.getAllKeys());
98
- return keys.map((key) => {
99
- if (typeof key !== "string") {
100
- throw new Error("The DocBlocks filesystem store contains a non-string key.");
101
- }
102
- return key;
103
- });
104
- }
105
- async hasKeyWithPrefix(prefix) {
106
- const cursor = await requestResult(this.store.openKeyCursor(IDBKeyRange.lowerBound(prefix)));
107
- return cursor !== null && typeof cursor.key === "string" && cursor.key.startsWith(prefix);
108
- }
109
- };
110
- async function openDatabaseWithStore(databaseName, storeName) {
111
- const database = await openDatabase(databaseName, void 0, (upgradeDatabase) => {
112
- if (!upgradeDatabase.objectStoreNames.contains(storeName)) {
113
- upgradeDatabase.createObjectStore(storeName);
114
- }
115
- });
116
- if (database.objectStoreNames.contains(storeName)) return database;
117
- const nextVersion = database.version + 1;
118
- database.close();
119
- return openDatabase(databaseName, nextVersion, (upgradeDatabase) => {
120
- if (!upgradeDatabase.objectStoreNames.contains(storeName)) {
121
- upgradeDatabase.createObjectStore(storeName);
122
- }
123
- });
124
- }
125
- function openDatabase(databaseName, version, upgrade) {
126
- return new Promise((resolve, reject) => {
127
- const request = version === void 0 ? indexedDB.open(databaseName) : indexedDB.open(databaseName, version);
128
- let settled = false;
129
- request.onupgradeneeded = () => upgrade(request.result);
130
- request.onsuccess = () => {
131
- if (settled) {
132
- request.result.close();
133
- return;
134
- }
135
- settled = true;
136
- resolve(request.result);
137
- };
138
- request.onerror = () => {
139
- if (settled) return;
140
- settled = true;
141
- reject(request.error ?? new Error(`Could not open IndexedDB database ${databaseName}.`));
142
- };
143
- request.onblocked = () => {
144
- if (settled) return;
145
- settled = true;
146
- reject(new Error(`IndexedDB database ${databaseName} is blocked by another open page.`));
147
- };
148
- });
149
- }
150
- function requestResult(request) {
151
- return new Promise((resolve, reject) => {
152
- request.onsuccess = () => resolve(request.result);
153
- request.onerror = () => reject(request.error ?? new Error("IndexedDB request failed."));
154
- });
155
- }
156
- function waitForTransaction(transaction) {
157
- return new Promise((resolve, reject) => {
158
- transaction.oncomplete = () => resolve();
159
- transaction.onabort = () => reject(transaction.error ?? new Error("IndexedDB transaction was aborted."));
160
- transaction.onerror = () => reject(transaction.error ?? new Error("IndexedDB transaction failed."));
161
- });
162
- }
28
+ } from "./chunk-JS6XFWQK.js";
29
+ import {
30
+ RawIndexedDBFileSystemStore,
31
+ indexedDBWorkspaceDatabaseName
32
+ } from "./chunk-RVPGQBWR.js";
163
33
 
164
34
  // src/filesystem/indexeddb-provider-v2.ts
165
35
  var ENTRY_SCHEMA_VERSION = 1;
166
36
  var STATE_SCHEMA_VERSION = 1;
167
37
  var LEGACY_CONFLICT_SCHEMA_VERSION = 2;
168
38
  var LEGACY_CONFLICT_SCHEMA_VERSION_V1 = 1;
39
+ var LEGACY_OPAQUE_SCHEMA_VERSION = 2;
40
+ var LEGACY_OPAQUE_SCHEMA_VERSION_V1 = 1;
169
41
  var ENTRY_PREFIX = "v2:entry:";
170
42
  var STATE_KEY = "v2:state";
171
43
  var LEGACY_CONFLICT_PREFIX = "v2:legacy-conflict:";
@@ -200,7 +72,7 @@ var IndexedDBFileSystemProviderV2 = class {
200
72
  this.disposed = false;
201
73
  this.id = id;
202
74
  this.label = label;
203
- this.store = options.store ?? new RawIndexedDBFileSystemStore(`docblocks-fs-${id}`, "files");
75
+ this.store = options.store ?? new RawIndexedDBFileSystemStore(indexedDBWorkspaceDatabaseName(id), "files");
204
76
  this.now = options.now ?? (() => /* @__PURE__ */ new Date());
205
77
  this.closeStoreOnDispose = options.closeStoreOnDispose ?? true;
206
78
  this.versionPrefix = `idb-${encodeURIComponent(id).slice(0, 900) || "workspace"}`;
@@ -268,7 +140,7 @@ var IndexedDBFileSystemProviderV2 = class {
268
140
  children.push(toEntrySnapshot(entry));
269
141
  }
270
142
  }
271
- children.sort(compareSnapshots);
143
+ children.sort(compareSnapshotsByName);
272
144
  return Object.freeze(children);
273
145
  });
274
146
  }
@@ -377,6 +249,7 @@ var IndexedDBFileSystemProviderV2 = class {
377
249
  await this.ensureInitialized("remove");
378
250
  return this.withMutationLock(
379
251
  () => this.transaction("readwrite", { operation: "remove", path: canonical }, async (tx) => {
252
+ await assertNoLegacyConflictInSubtree(tx, canonical, "remove");
380
253
  const mutation = new EntryMutation(tx);
381
254
  const existing = await mutation.get(canonical);
382
255
  const state = await readRequiredState(tx);
@@ -418,8 +291,8 @@ var IndexedDBFileSystemProviderV2 = class {
418
291
  "readwrite",
419
292
  { operation: "move", path: sourcePath, destinationPath },
420
293
  async (tx) => {
421
- await assertNoLegacyConflict(tx, sourcePath, "move");
422
- await assertNoLegacyConflict(tx, destinationPath, "move");
294
+ await assertNoLegacyConflictInSubtree(tx, sourcePath, "move");
295
+ await assertNoLegacyConflictInSubtree(tx, destinationPath, "move");
423
296
  const mutation = new EntryMutation(tx);
424
297
  const source = await mutation.get(sourcePath);
425
298
  if (!source) {
@@ -652,6 +525,91 @@ var IndexedDBFileSystemProviderV2 = class {
652
525
  })
653
526
  );
654
527
  }
528
+ /**
529
+ * List the unrecognized legacy keys this workspace archived during migration.
530
+ *
531
+ * Migration deletes the legacy `fs:` namespace, but a key it cannot interpret
532
+ * is copied aside first rather than dropped: those bytes belong to whatever
533
+ * tool wrote them against this origin, and DocBlocks is not entitled to
534
+ * decide they are worthless. Nothing else reads that archive, so without this
535
+ * call the bytes are invisible and their quota is unaccountable.
536
+ *
537
+ * Values are deliberately excluded — an archive large enough to matter is an
538
+ * archive too large to materialize just to count it. Use
539
+ * {@link readLegacyOpaqueRecord} for the values themselves.
540
+ */
541
+ async listLegacyOpaqueRecords() {
542
+ this.assertOpen("read");
543
+ await this.ensureInitialized("read");
544
+ return this.transaction("readonly", { operation: "read" }, async (tx) => {
545
+ const keys = (await tx.keys()).filter((key) => key.startsWith(LEGACY_OPAQUE_PREFIX));
546
+ const summaries = [];
547
+ for (const key of keys) {
548
+ summaries.push(
549
+ toOpaqueSummary(validateLegacyOpaqueRecord(await tx.get(key), key))
550
+ );
551
+ }
552
+ summaries.sort((left, right) => compareText(left.key, right.key));
553
+ return Object.freeze(summaries);
554
+ });
555
+ }
556
+ /** Retrieve every archived value for one unrecognized legacy key. */
557
+ async readLegacyOpaqueRecord(key) {
558
+ this.assertOpen("read");
559
+ await this.ensureInitialized("read");
560
+ return this.transaction("readonly", { operation: "read" }, async (tx) => {
561
+ const archiveKey = legacyOpaqueKey(key);
562
+ const raw = await tx.get(archiveKey);
563
+ if (raw === null) return null;
564
+ return toPublicOpaqueRecord(validateLegacyOpaqueRecord(raw, archiveKey));
565
+ });
566
+ }
567
+ /**
568
+ * Permanently destroy archived legacy values. This is the only operation that
569
+ * can lose data the archive exists to protect.
570
+ *
571
+ * For every target, all of that key's archived value snapshots are erased and
572
+ * the quota they held is reclaimed. There is no undo, no tombstone, and no
573
+ * other copy: migration already deleted the original `fs:` key, so the
574
+ * archive is the last one. Retrieve anything worth keeping with
575
+ * {@link readLegacyOpaqueRecord} before calling this.
576
+ *
577
+ * Each target must carry the `valueCount` the caller actually observed, which
578
+ * is why a target is a value returned by {@link listLegacyOpaqueRecords} or
579
+ * {@link readLegacyOpaqueRecord} rather than a bare key. A stale client can
580
+ * append a new snapshot at any time; if any target has grown since it was
581
+ * observed, the whole call fails with `conflict` and destroys nothing, so
582
+ * re-list and look again. A key that is already absent is not an error —
583
+ * discarding what is gone is a no-op — but a key whose count disagrees is.
584
+ *
585
+ * @returns how many records were destroyed.
586
+ */
587
+ async discardLegacyOpaqueRecords(targets) {
588
+ this.assertOpen("remove");
589
+ if (targets.length === 0) return 0;
590
+ await this.ensureInitialized("remove");
591
+ return this.withMutationLock(
592
+ () => this.transaction("readwrite", { operation: "remove" }, async (tx) => {
593
+ const doomed = [];
594
+ for (const target of targets) {
595
+ const archiveKey = legacyOpaqueKey(target.key);
596
+ const raw = await tx.get(archiveKey);
597
+ if (raw === null) continue;
598
+ const record = validateLegacyOpaqueRecord(raw, archiveKey);
599
+ if (record.values.length !== target.valueCount) {
600
+ throw new FsError(
601
+ "conflict",
602
+ `Archived legacy key ${target.key} now holds ${record.values.length} values, not ${target.valueCount}. Read it again before discarding it.`,
603
+ { operation: "remove", retryable: false }
604
+ );
605
+ }
606
+ doomed.push(archiveKey);
607
+ }
608
+ for (const archiveKey of doomed) await tx.delete(archiveKey);
609
+ return doomed.length;
610
+ })
611
+ );
612
+ }
655
613
  async ensureInitialized(operation) {
656
614
  this.assertOpen(operation);
657
615
  if (this.initialization) return this.initialization;
@@ -754,7 +712,7 @@ var IndexedDBFileSystemProviderV2 = class {
754
712
  for (const entry of entries.values()) {
755
713
  await tx.put(entryKey(entry.path), entry);
756
714
  }
757
- await deleteLegacyNamespace(tx, keys);
715
+ await deleteLegacyNamespace(tx, keys, now);
758
716
  const state = {
759
717
  schemaVersion: STATE_SCHEMA_VERSION,
760
718
  migrationVersion: 2,
@@ -793,7 +751,7 @@ var IndexedDBFileSystemProviderV2 = class {
793
751
  fileRecoveryCandidate(legacy, entry?.kind === "directory" ? "kind-collision" : reason, now)
794
752
  );
795
753
  }
796
- await deleteLegacyNamespace(tx, keys);
754
+ await deleteLegacyNamespace(tx, keys, now);
797
755
  for (const key of keys) {
798
756
  if (key.startsWith(LEGACY_IGNORED_PREFIX)) await tx.delete(key);
799
757
  }
@@ -880,7 +838,7 @@ var IndexedDBFileSystemProviderV2 = class {
880
838
  }
881
839
  async planParents(mutation, path, createParents, operation) {
882
840
  const missing = [];
883
- for (const parent of parentChain(path)) {
841
+ for (const parent of parentChainWithRoot(path)) {
884
842
  const entry = await mutation.get(parent);
885
843
  if (entry?.kind === "file") {
886
844
  throw this.error(
@@ -905,7 +863,7 @@ var IndexedDBFileSystemProviderV2 = class {
905
863
  }
906
864
  }
907
865
  async touchParents(mutation, path, next) {
908
- for (const parent of parentChain(path)) {
866
+ for (const parent of parentChainWithRoot(path)) {
909
867
  const entry = await mutation.get(parent);
910
868
  if (entry?.kind === "directory") {
911
869
  mutation.set(parent, directoryRecord(parent, next.version, next.lastModified));
@@ -1119,15 +1077,21 @@ function validateIgnoredLegacyPath(value) {
1119
1077
  if (!path) throw corrupt("Ignored legacy recovery marker cannot target the workspace root.");
1120
1078
  return path;
1121
1079
  }
1122
- function bytesEqual(left, right) {
1123
- const leftBytes = ArrayBuffer.isView(left) ? new Uint8Array(left.buffer, left.byteOffset, left.byteLength) : new Uint8Array(left);
1124
- const rightBytes = ArrayBuffer.isView(right) ? new Uint8Array(right.buffer, right.byteOffset, right.byteLength) : new Uint8Array(right);
1125
- if (leftBytes.byteLength !== rightBytes.byteLength) return false;
1126
- return leftBytes.every((byte, index) => byte === rightBytes[index]);
1127
- }
1128
1080
  async function assertNoLegacyConflict(transaction, path, operation) {
1129
1081
  if (await transaction.get(legacyConflictKey(path)) === null) return;
1130
- throw new FsError(
1082
+ throw legacyConflictBlocked(path, operation);
1083
+ }
1084
+ async function assertNoLegacyConflictInSubtree(transaction, path, operation) {
1085
+ for (const key of await transaction.keys()) {
1086
+ if (!key.startsWith(LEGACY_CONFLICT_PREFIX)) continue;
1087
+ const conflictPath = parseWorkspacePath(key.slice(LEGACY_CONFLICT_PREFIX.length));
1088
+ if (conflictPath === path || workspacePathContains(path, conflictPath, false)) {
1089
+ throw legacyConflictBlocked(conflictPath, operation);
1090
+ }
1091
+ }
1092
+ }
1093
+ function legacyConflictBlocked(path, operation) {
1094
+ return new FsError(
1131
1095
  "conflict",
1132
1096
  "Resolve the legacy migration conflict before mutating this path.",
1133
1097
  {
@@ -1282,18 +1246,91 @@ function legacyPayloadsMatchEntry(legacy, entry) {
1282
1246
  return (legacy.content === null || bytesEqual(new TextEncoder().encode(legacy.content), entry.data)) && (legacy.binary === null || bytesEqual(legacy.binary, entry.data));
1283
1247
  }
1284
1248
  function hasFileAncestor(entries, path) {
1285
- return parentChain(path).some((parent) => entries.get(parent)?.kind === "file");
1249
+ return parentChainWithRoot(path).some((parent) => entries.get(parent)?.kind === "file");
1250
+ }
1251
+ function legacyOpaqueKey(key) {
1252
+ return `${LEGACY_OPAQUE_PREFIX}${encodeURIComponent(key)}`;
1253
+ }
1254
+ function validateLegacyOpaqueRecord(value, archiveKey) {
1255
+ if (!isRecord(value) || !Array.isArray(value.values)) {
1256
+ throw corrupt(`Archived legacy record is corrupt: ${archiveKey}.`);
1257
+ }
1258
+ const key = readString(value.key, "archived legacy key");
1259
+ if (legacyOpaqueKey(key) !== archiveKey) {
1260
+ throw corrupt(`Archived legacy record key does not match its key: ${archiveKey}.`);
1261
+ }
1262
+ if (value.schemaVersion === LEGACY_OPAQUE_SCHEMA_VERSION_V1) {
1263
+ return {
1264
+ schemaVersion: LEGACY_OPAQUE_SCHEMA_VERSION,
1265
+ key,
1266
+ values: Object.freeze(
1267
+ value.values.map(
1268
+ (item) => ({ value: item, archivedAt: null })
1269
+ )
1270
+ )
1271
+ };
1272
+ }
1273
+ if (value.schemaVersion !== LEGACY_OPAQUE_SCHEMA_VERSION) {
1274
+ throw corrupt(`Unsupported archived legacy record schema: ${archiveKey}.`);
1275
+ }
1276
+ const values = value.values.map((item) => {
1277
+ if (!isRecord(item)) throw corrupt(`Archived legacy value is corrupt: ${archiveKey}.`);
1278
+ return {
1279
+ value: item.value,
1280
+ // A v2 record legitimately carries null here for values it inherited from
1281
+ // the untimestamped v1 shape, so this must stay nullable on the way back
1282
+ // in or re-archiving a v1 record would make it permanently unreadable.
1283
+ archivedAt: item.archivedAt === null ? null : readString(item.archivedAt, "archived legacy timestamp")
1284
+ };
1285
+ });
1286
+ if (values.length === 0) throw corrupt(`Archived legacy record has no values: ${archiveKey}.`);
1287
+ return { schemaVersion: LEGACY_OPAQUE_SCHEMA_VERSION, key, values: Object.freeze(values) };
1288
+ }
1289
+ function opaqueValueByteLength(value) {
1290
+ if (value instanceof ArrayBuffer) return value.byteLength;
1291
+ if (ArrayBuffer.isView(value)) return value.byteLength;
1292
+ if (typeof value === "string") return new TextEncoder().encode(value).byteLength;
1293
+ return null;
1294
+ }
1295
+ function toOpaqueSummary(record) {
1296
+ let byteLength = 0;
1297
+ for (const item of record.values) {
1298
+ const size = opaqueValueByteLength(item.value);
1299
+ byteLength = size === null || byteLength === null ? null : byteLength + size;
1300
+ }
1301
+ const stamps = record.values.map((item) => item.archivedAt);
1302
+ return Object.freeze({
1303
+ key: record.key,
1304
+ valueCount: record.values.length,
1305
+ byteLength,
1306
+ firstArchivedAt: stamps[0] ?? null,
1307
+ lastArchivedAt: stamps[stamps.length - 1] ?? null
1308
+ });
1286
1309
  }
1287
- async function deleteLegacyNamespace(transaction, keys) {
1310
+ function toPublicOpaqueRecord(record) {
1311
+ return Object.freeze({
1312
+ ...toOpaqueSummary(record),
1313
+ values: Object.freeze(
1314
+ record.values.map(
1315
+ (item) => Object.freeze({
1316
+ value: item.value instanceof ArrayBuffer ? copyBytes(item.value) : item.value,
1317
+ byteLength: opaqueValueByteLength(item.value),
1318
+ archivedAt: item.archivedAt
1319
+ })
1320
+ )
1321
+ )
1322
+ });
1323
+ }
1324
+ async function deleteLegacyNamespace(transaction, keys, archivedAt) {
1288
1325
  for (const key of keys) {
1289
1326
  if (key.startsWith(LEGACY_PREFIX) && !isRecognizedLegacyKey(key)) {
1290
- const archiveKey = `${LEGACY_OPAQUE_PREFIX}${encodeURIComponent(key)}`;
1327
+ const archiveKey = legacyOpaqueKey(key);
1291
1328
  const existing = await transaction.get(archiveKey);
1292
- const values = isRecord(existing) && existing.schemaVersion === 1 && existing.key === key && Array.isArray(existing.values) ? existing.values : [];
1329
+ const values = existing === null ? [] : validateLegacyOpaqueRecord(existing, archiveKey).values;
1293
1330
  await transaction.put(archiveKey, {
1294
- schemaVersion: 1,
1331
+ schemaVersion: LEGACY_OPAQUE_SCHEMA_VERSION,
1295
1332
  key,
1296
- values: [...values, await transaction.get(key)]
1333
+ values: [...values, { value: await transaction.get(key), archivedAt }]
1297
1334
  });
1298
1335
  }
1299
1336
  if (key.startsWith(LEGACY_PREFIX) || key.startsWith(LEGACY_IGNORED_PREFIX))
@@ -1354,19 +1391,10 @@ function selectLegacyPayload(conflict, resolution, path) {
1354
1391
  return { kind: "file", data: copyBytes(data) };
1355
1392
  }
1356
1393
  function addParentDirectories(entries, path, version, lastModified) {
1357
- for (const parent of parentChain(path)) {
1394
+ for (const parent of parentChainWithRoot(path)) {
1358
1395
  if (!entries.has(parent)) entries.set(parent, directoryRecord(parent, version, lastModified));
1359
1396
  }
1360
1397
  }
1361
- function parentChain(path) {
1362
- const parents = [];
1363
- let current = workspacePathDirname(path);
1364
- while (true) {
1365
- parents.unshift(current);
1366
- if (!current) return parents;
1367
- current = workspacePathDirname(current);
1368
- }
1369
- }
1370
1398
  function directoryRecord(path, version, lastModified) {
1371
1399
  return {
1372
1400
  schemaVersion: ENTRY_SCHEMA_VERSION,
@@ -1413,19 +1441,6 @@ function toDirectorySnapshot(entry) {
1413
1441
  lastModified: entry.lastModified
1414
1442
  });
1415
1443
  }
1416
- function compareSnapshots(left, right) {
1417
- if (left.kind !== right.kind) return left.kind === "directory" ? -1 : 1;
1418
- return compareText(left.name, right.name);
1419
- }
1420
- function compareText(left, right) {
1421
- return left < right ? -1 : left > right ? 1 : 0;
1422
- }
1423
- function copyBytes(data) {
1424
- const source = ArrayBuffer.isView(data) ? new Uint8Array(data.buffer, data.byteOffset, data.byteLength) : new Uint8Array(data);
1425
- const copy = new Uint8Array(source.byteLength);
1426
- copy.set(source);
1427
- return copy.buffer;
1428
- }
1429
1444
  function validateBytes(value, path) {
1430
1445
  if (value instanceof ArrayBuffer) return copyBytes(value);
1431
1446
  if (value instanceof Uint8Array) return copyBytes(value);
@@ -1435,9 +1450,6 @@ function readString(value, label) {
1435
1450
  if (typeof value !== "string") throw corrupt(`Invalid ${label}.`);
1436
1451
  return value;
1437
1452
  }
1438
- function isRecord(value) {
1439
- return typeof value === "object" && value !== null;
1440
- }
1441
1453
  function corrupt(message, path) {
1442
1454
  return new FsError("io", message, { operation: "read", path, retryable: false });
1443
1455
  }
@@ -1448,7 +1460,7 @@ var IndexedDBFileSystemProvider = class {
1448
1460
  this.disposed = false;
1449
1461
  this.id = id;
1450
1462
  this.label = label;
1451
- const store = options.store ?? new RawIndexedDBFileSystemStore(`docblocks-fs-${id}`, "files");
1463
+ const store = options.store ?? new RawIndexedDBFileSystemStore(indexedDBWorkspaceDatabaseName(id), "files");
1452
1464
  this.v2 = new IndexedDBFileSystemProviderV2(id, label, {
1453
1465
  store,
1454
1466
  now: options.now,
@@ -1462,20 +1474,21 @@ var IndexedDBFileSystemProvider = class {
1462
1474
  }
1463
1475
  async readFile(path) {
1464
1476
  this.assertOpen("read");
1465
- const read = await this.v2.readFile(this.path(path, false, "read"));
1466
- return read ? new TextDecoder().decode(read.data) : null;
1477
+ const canonical = this.path(path);
1478
+ const read = await this.v2.readFile(canonical);
1479
+ return read ? this.decode(read.data, canonical, "read") : null;
1467
1480
  }
1468
1481
  async writeFile(path, content) {
1469
1482
  this.assertOpen("write");
1470
- await this.v2.writeFile(this.path(path, false, "write"), new TextEncoder().encode(content), {
1483
+ await this.v2.writeFile(this.path(path), new TextEncoder().encode(content), {
1471
1484
  createParents: true
1472
1485
  });
1473
1486
  }
1474
1487
  async commitFile(path, content, expectedContent) {
1475
1488
  this.assertOpen("write");
1476
- const canonical = this.path(path, false, "write");
1489
+ const canonical = this.path(path);
1477
1490
  const current = await this.v2.readFile(canonical);
1478
- const currentContent = current ? new TextDecoder().decode(current.data) : null;
1491
+ const currentContent = current ? this.decode(current.data, canonical, "write") : null;
1479
1492
  if (currentContent !== expectedContent && currentContent !== content) {
1480
1493
  return {
1481
1494
  status: "conflict",
@@ -1494,28 +1507,28 @@ var IndexedDBFileSystemProvider = class {
1494
1507
  const latest = await this.v2.readFile(canonical);
1495
1508
  return {
1496
1509
  status: "conflict",
1497
- content: latest ? new TextDecoder().decode(latest.data) : null,
1510
+ content: latest ? this.decode(latest.data, canonical, "write") : null,
1498
1511
  version: latest?.entry.version ?? null
1499
1512
  };
1500
1513
  }
1501
1514
  }
1502
1515
  async delete(path) {
1503
1516
  this.assertOpen("remove");
1504
- await this.v2.remove(this.path(path, false, "remove"), {
1517
+ await this.v2.remove(this.path(path), {
1505
1518
  recursive: true,
1506
1519
  missing: "ignore"
1507
1520
  });
1508
1521
  }
1509
1522
  async rename(oldPath, newPath) {
1510
1523
  this.assertOpen("move");
1511
- await this.v2.move(this.path(oldPath, false, "move"), this.path(newPath, false, "move"), {
1524
+ await this.v2.move(this.path(oldPath), this.path(newPath), {
1512
1525
  createParents: true
1513
1526
  });
1514
1527
  }
1515
1528
  async readDirectory(path) {
1516
1529
  this.assertOpen("list");
1517
1530
  try {
1518
- const entries = await this.v2.readDirectory(this.path(path, true, "list"));
1531
+ const entries = await this.v2.readDirectory(this.path(path));
1519
1532
  return entries.map((entry) => ({
1520
1533
  kind: entry.kind,
1521
1534
  name: entry.name,
@@ -1528,18 +1541,18 @@ var IndexedDBFileSystemProvider = class {
1528
1541
  }
1529
1542
  async exists(path) {
1530
1543
  this.assertOpen("stat");
1531
- return await this.v2.stat(this.path(path, true, "stat")) !== null;
1544
+ return await this.v2.stat(this.path(path)) !== null;
1532
1545
  }
1533
1546
  async createDirectory(path) {
1534
1547
  this.assertOpen("create-directory");
1535
- await this.v2.createDirectory(this.path(path, false, "create-directory"), {
1548
+ await this.v2.createDirectory(this.path(path), {
1536
1549
  createParents: true,
1537
1550
  mode: "ensure"
1538
1551
  });
1539
1552
  }
1540
1553
  async stat(path) {
1541
1554
  this.assertOpen("stat");
1542
- const entry = await this.v2.stat(this.path(path, false, "stat"));
1555
+ const entry = await this.v2.stat(this.path(path));
1543
1556
  if (!entry || entry.kind !== "file") return null;
1544
1557
  return {
1545
1558
  name: entry.name,
@@ -1550,28 +1563,40 @@ var IndexedDBFileSystemProvider = class {
1550
1563
  }
1551
1564
  async readBinary(path) {
1552
1565
  this.assertOpen("read");
1553
- return (await this.v2.readFile(this.path(path, false, "read")))?.data ?? null;
1566
+ return (await this.v2.readFile(this.path(path)))?.data ?? null;
1554
1567
  }
1555
1568
  async writeBinary(path, data) {
1556
1569
  this.assertOpen("write");
1557
- await this.v2.writeFile(this.path(path, false, "write"), data, { createParents: true });
1558
- }
1559
- path(path, allowRoot, operation) {
1560
- const canonical = parseWorkspacePath(path);
1561
- if (canonical || allowRoot) return canonical;
1562
- throw new FsError("invalid-path", "The filesystem root cannot be used as a mutation target.", {
1563
- operation,
1564
- path
1565
- });
1570
+ await this.v2.writeFile(this.path(path), data, { createParents: true });
1571
+ }
1572
+ /**
1573
+ * Canonicalize only. Root policy is the v2 authority's to state: it accepts
1574
+ * the root wherever the root is a legitimate target (`stat`, `readDirectory`,
1575
+ * `createDirectory`) and rejects it with one consistent code and message
1576
+ * everywhere else. Re-deriving that policy here is how this facade previously
1577
+ * drifted from both v2 and its sibling facades.
1578
+ */
1579
+ path(path) {
1580
+ return parseWorkspacePath(path);
1581
+ }
1582
+ /**
1583
+ * Byte-authoritative entries may hold payloads that are not valid UTF-8. A
1584
+ * lossy decode would hand the caller replacement characters that a later save
1585
+ * writes back over the user's original bytes, so surface the fault instead.
1586
+ */
1587
+ decode(data, path, operation) {
1588
+ return decodeUtf8Text(data, { label: "The file", operation, path });
1566
1589
  }
1567
1590
  assertOpen(operation) {
1568
1591
  if (!this.disposed) return;
1569
- throw new FsError("closed", "The IndexedDB filesystem provider is disposed.", { operation });
1592
+ throw new FsError("disposed", "Filesystem provider is disposed.", { operation });
1570
1593
  }
1571
1594
  };
1572
1595
 
1573
1596
  // src/filesystem/indexeddb-content-container.ts
1574
1597
  import { findDocumentPath } from "@bendyline/squisq/storage";
1598
+
1599
+ // src/filesystem/internal/mime.ts
1575
1600
  var EXTENSION_MIME_MAP = {
1576
1601
  ".md": "text/markdown",
1577
1602
  ".txt": "text/plain",
@@ -1595,6 +1620,8 @@ function guessMimeType(path) {
1595
1620
  const ext = path.slice(dot).toLowerCase();
1596
1621
  return EXTENSION_MIME_MAP[ext] ?? "application/octet-stream";
1597
1622
  }
1623
+
1624
+ // src/filesystem/indexeddb-content-container.ts
1598
1625
  var IndexedDBContentContainer = class {
1599
1626
  constructor(workspaceId) {
1600
1627
  this.provider = new IndexedDBFileSystemProviderV2(`${workspaceId}-media`, "Media Storage");
@@ -1659,6 +1686,7 @@ var IndexedDBContentContainer = class {
1659
1686
  export {
1660
1687
  IndexedDBFileSystemProviderV2,
1661
1688
  IndexedDBFileSystemProvider,
1689
+ guessMimeType,
1662
1690
  IndexedDBContentContainer
1663
1691
  };
1664
- //# sourceMappingURL=chunk-J32GU3F3.js.map
1692
+ //# sourceMappingURL=chunk-6IYMTYMQ.js.map