@fgv/ts-web-extras 5.1.0-0 → 5.1.0-10

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 (462) hide show
  1. package/.rush/temp/{81e0881271ff236956b2f52e8ca99da6574c6e1e.tar.log → 662cc3506cc3ef5cddbcdc44d137af1d16679cbe.tar.log} +17 -3
  2. package/.rush/temp/chunked-rush-logs/ts-web-extras.build.chunks.jsonl +37 -34
  3. package/.rush/temp/operation/build/all.log +37 -34
  4. package/.rush/temp/operation/build/log-chunks.jsonl +37 -34
  5. package/.rush/temp/operation/build/state.json +1 -1
  6. package/.rush/temp/shrinkwrap-deps.json +690 -633
  7. package/config/typedoc.json +2 -1
  8. package/dist/packlets/file-tree/fileApiTreeAccessors.js +15 -0
  9. package/dist/packlets/file-tree/fileApiTreeAccessors.js.map +1 -1
  10. package/dist/packlets/file-tree/fileSystemAccessTreeAccessors.js +79 -10
  11. package/dist/packlets/file-tree/fileSystemAccessTreeAccessors.js.map +1 -1
  12. package/dist/packlets/file-tree/httpTreeAccessors.js +366 -0
  13. package/dist/packlets/file-tree/httpTreeAccessors.js.map +1 -0
  14. package/dist/packlets/file-tree/index.js +1 -0
  15. package/dist/packlets/file-tree/index.js.map +1 -1
  16. package/dist/packlets/file-tree/localStorageTreeAccessors.js +51 -0
  17. package/dist/packlets/file-tree/localStorageTreeAccessors.js.map +1 -1
  18. package/dist/test/unit/fileApiTreeAccessors.test.js +51 -0
  19. package/dist/test/unit/fileApiTreeAccessors.test.js.map +1 -1
  20. package/dist/test/unit/fileSystemAccessTreeAccessors.test.js +265 -160
  21. package/dist/test/unit/fileSystemAccessTreeAccessors.test.js.map +1 -1
  22. package/dist/test/unit/httpTreeAccessors.test.js +1364 -0
  23. package/dist/test/unit/httpTreeAccessors.test.js.map +1 -0
  24. package/dist/test/unit/localStorageTreeAccessors.test.js +218 -1
  25. package/dist/test/unit/localStorageTreeAccessors.test.js.map +1 -1
  26. package/dist/ts-web-extras.d.ts +144 -0
  27. package/dist/tsdoc-metadata.json +1 -1
  28. package/docs/CryptoUtils/README.md +60 -0
  29. package/docs/CryptoUtils/classes/BrowserCryptoProvider.decrypt.md +27 -0
  30. package/docs/CryptoUtils/classes/BrowserCryptoProvider.deriveKey.md +26 -0
  31. package/docs/CryptoUtils/classes/BrowserCryptoProvider.encrypt.md +25 -0
  32. package/docs/CryptoUtils/classes/BrowserCryptoProvider.fromBase64.md +24 -0
  33. package/docs/CryptoUtils/classes/BrowserCryptoProvider.generateKey.md +17 -0
  34. package/docs/CryptoUtils/classes/BrowserCryptoProvider.generateRandomBytes.md +24 -0
  35. package/docs/CryptoUtils/classes/BrowserCryptoProvider.md +151 -0
  36. package/docs/CryptoUtils/classes/BrowserCryptoProvider.toBase64.md +24 -0
  37. package/docs/CryptoUtils/classes/BrowserHashProvider.hashParts.md +26 -0
  38. package/docs/CryptoUtils/classes/BrowserHashProvider.hashString.md +25 -0
  39. package/docs/CryptoUtils/classes/BrowserHashProvider.md +81 -0
  40. package/docs/CryptoUtils/functions/createBrowserCryptoProvider.md +12 -0
  41. package/docs/FileTreeHelpers/README.md +85 -0
  42. package/docs/FileTreeHelpers/functions/extractFileListMetadata.md +11 -0
  43. package/docs/FileTreeHelpers/functions/extractFileMetadata.md +11 -0
  44. package/docs/FileTreeHelpers/functions/fromDirectoryUpload.md +12 -0
  45. package/docs/FileTreeHelpers/functions/fromFileList.md +12 -0
  46. package/docs/FileTreeHelpers/functions/getOriginalFile.md +11 -0
  47. package/docs/FileTreeHelpers/variables/defaultFileApiTreeInitParams.md +9 -0
  48. package/docs/README.md +524 -0
  49. package/docs/classes/BrowserCryptoProvider.decrypt.md +27 -0
  50. package/docs/classes/BrowserCryptoProvider.deriveKey.md +26 -0
  51. package/docs/classes/BrowserCryptoProvider.encrypt.md +25 -0
  52. package/docs/classes/BrowserCryptoProvider.fromBase64.md +24 -0
  53. package/docs/classes/BrowserCryptoProvider.generateKey.md +17 -0
  54. package/docs/classes/BrowserCryptoProvider.generateRandomBytes.md +24 -0
  55. package/docs/classes/BrowserCryptoProvider.md +151 -0
  56. package/docs/classes/BrowserCryptoProvider.toBase64.md +24 -0
  57. package/docs/classes/BrowserHashProvider.hashParts.md +26 -0
  58. package/docs/classes/BrowserHashProvider.hashString.md +25 -0
  59. package/docs/classes/BrowserHashProvider.md +81 -0
  60. package/docs/classes/DirectoryHandleStore.getAll.md +17 -0
  61. package/docs/classes/DirectoryHandleStore.getAllLabels.md +17 -0
  62. package/docs/classes/DirectoryHandleStore.load.md +24 -0
  63. package/docs/classes/DirectoryHandleStore.md +120 -0
  64. package/docs/classes/DirectoryHandleStore.remove.md +24 -0
  65. package/docs/classes/DirectoryHandleStore.save.md +25 -0
  66. package/docs/classes/FileApiTreeAccessors.create.md +25 -0
  67. package/docs/classes/FileApiTreeAccessors.createFromHttp.md +24 -0
  68. package/docs/classes/FileApiTreeAccessors.createFromLocalStorage.md +25 -0
  69. package/docs/classes/FileApiTreeAccessors.createPersistent.md +26 -0
  70. package/docs/classes/FileApiTreeAccessors.createPersistentFromFile.md +27 -0
  71. package/docs/classes/FileApiTreeAccessors.extractFileMetadata.md +24 -0
  72. package/docs/classes/FileApiTreeAccessors.fromDirectoryUpload.md +25 -0
  73. package/docs/classes/FileApiTreeAccessors.fromFileList.md +25 -0
  74. package/docs/classes/FileApiTreeAccessors.getOriginalFile.md +27 -0
  75. package/docs/classes/FileApiTreeAccessors.md +172 -0
  76. package/docs/classes/FileSystemAccessTreeAccessors.deleteFile.md +22 -0
  77. package/docs/classes/FileSystemAccessTreeAccessors.fileIsMutable.md +22 -0
  78. package/docs/classes/FileSystemAccessTreeAccessors.fromDirectoryHandle.md +25 -0
  79. package/docs/classes/FileSystemAccessTreeAccessors.fromFileHandle.md +29 -0
  80. package/docs/classes/FileSystemAccessTreeAccessors.getDirtyPaths.md +15 -0
  81. package/docs/classes/FileSystemAccessTreeAccessors.isDirty.md +15 -0
  82. package/docs/classes/FileSystemAccessTreeAccessors.md +275 -0
  83. package/docs/classes/FileSystemAccessTreeAccessors.saveFileContents.md +23 -0
  84. package/docs/classes/FileSystemAccessTreeAccessors.syncToDisk.md +15 -0
  85. package/docs/classes/HttpTreeAccessors.deleteFile.md +22 -0
  86. package/docs/classes/HttpTreeAccessors.fileIsMutable.md +24 -0
  87. package/docs/classes/HttpTreeAccessors.fromHttp.md +24 -0
  88. package/docs/classes/HttpTreeAccessors.getDirtyPaths.md +17 -0
  89. package/docs/classes/HttpTreeAccessors.isDirty.md +17 -0
  90. package/docs/classes/HttpTreeAccessors.md +261 -0
  91. package/docs/classes/HttpTreeAccessors.saveFileContents.md +25 -0
  92. package/docs/classes/HttpTreeAccessors.syncToDisk.md +22 -0
  93. package/docs/classes/LocalStorageTreeAccessors.deleteFile.md +24 -0
  94. package/docs/classes/LocalStorageTreeAccessors.fileIsMutable.md +24 -0
  95. package/docs/classes/LocalStorageTreeAccessors.fromStorage.md +25 -0
  96. package/docs/classes/LocalStorageTreeAccessors.getDirtyPaths.md +17 -0
  97. package/docs/classes/LocalStorageTreeAccessors.isDirty.md +17 -0
  98. package/docs/classes/LocalStorageTreeAccessors.md +270 -0
  99. package/docs/classes/LocalStorageTreeAccessors.saveFileContents.md +25 -0
  100. package/docs/classes/LocalStorageTreeAccessors.syncToDisk.md +17 -0
  101. package/docs/functions/createBrowserCryptoProvider.md +12 -0
  102. package/docs/functions/exportAsJson.md +12 -0
  103. package/docs/functions/exportUsingFileSystemAPI.md +11 -0
  104. package/docs/functions/extractDirectoryPath.md +13 -0
  105. package/docs/functions/extractFileListMetadata.md +11 -0
  106. package/docs/functions/extractFileMetadata.md +11 -0
  107. package/docs/functions/fromDirectoryUpload.md +12 -0
  108. package/docs/functions/fromFileList.md +12 -0
  109. package/docs/functions/getOriginalFile.md +11 -0
  110. package/docs/functions/isDirectoryHandle.md +11 -0
  111. package/docs/functions/isFileHandle.md +11 -0
  112. package/docs/functions/isFilePath.md +11 -0
  113. package/docs/functions/parseContextFilter.md +12 -0
  114. package/docs/functions/parseQualifierDefaults.md +12 -0
  115. package/docs/functions/parseResourceTypes.md +12 -0
  116. package/docs/functions/parseUrlParameters.md +11 -0
  117. package/docs/functions/safeShowDirectoryPicker.md +11 -0
  118. package/docs/functions/safeShowOpenFilePicker.md +11 -0
  119. package/docs/functions/safeShowSaveFilePicker.md +11 -0
  120. package/docs/functions/supportsFileSystemAccess.md +11 -0
  121. package/docs/interfaces/FilePickerAcceptType.accept.md +9 -0
  122. package/docs/interfaces/FilePickerAcceptType.description.md +9 -0
  123. package/docs/interfaces/FilePickerAcceptType.md +61 -0
  124. package/docs/interfaces/FileSystemCreateWritableOptions.keepExistingData.md +9 -0
  125. package/docs/interfaces/FileSystemCreateWritableOptions.md +44 -0
  126. package/docs/interfaces/FileSystemDirectoryHandle._asyncIterator_.md +13 -0
  127. package/docs/interfaces/FileSystemDirectoryHandle.entries.md +13 -0
  128. package/docs/interfaces/FileSystemDirectoryHandle.getDirectoryHandle.md +21 -0
  129. package/docs/interfaces/FileSystemDirectoryHandle.getFileHandle.md +21 -0
  130. package/docs/interfaces/FileSystemDirectoryHandle.keys.md +13 -0
  131. package/docs/interfaces/FileSystemDirectoryHandle.kind.md +9 -0
  132. package/docs/interfaces/FileSystemDirectoryHandle.md +224 -0
  133. package/docs/interfaces/FileSystemDirectoryHandle.removeEntry.md +21 -0
  134. package/docs/interfaces/FileSystemDirectoryHandle.resolve.md +20 -0
  135. package/docs/interfaces/FileSystemDirectoryHandle.values.md +13 -0
  136. package/docs/interfaces/FileSystemFileHandle.createWritable.md +20 -0
  137. package/docs/interfaces/FileSystemFileHandle.getFile.md +13 -0
  138. package/docs/interfaces/FileSystemFileHandle.kind.md +9 -0
  139. package/docs/interfaces/FileSystemFileHandle.md +146 -0
  140. package/docs/interfaces/FileSystemGetDirectoryOptions.create.md +9 -0
  141. package/docs/interfaces/FileSystemGetDirectoryOptions.md +44 -0
  142. package/docs/interfaces/FileSystemGetFileOptions.create.md +9 -0
  143. package/docs/interfaces/FileSystemGetFileOptions.md +44 -0
  144. package/docs/interfaces/FileSystemHandle.isSameEntry.md +20 -0
  145. package/docs/interfaces/FileSystemHandle.kind.md +9 -0
  146. package/docs/interfaces/FileSystemHandle.md +118 -0
  147. package/docs/interfaces/FileSystemHandle.name.md +9 -0
  148. package/docs/interfaces/FileSystemHandle.queryPermission.md +20 -0
  149. package/docs/interfaces/FileSystemHandle.requestPermission.md +20 -0
  150. package/docs/interfaces/FileSystemHandlePermissionDescriptor.md +44 -0
  151. package/docs/interfaces/FileSystemHandlePermissionDescriptor.mode.md +9 -0
  152. package/docs/interfaces/FileSystemRemoveOptions.md +44 -0
  153. package/docs/interfaces/FileSystemRemoveOptions.recursive.md +9 -0
  154. package/docs/interfaces/FileSystemWritableFileStream.md +142 -0
  155. package/docs/interfaces/FileSystemWritableFileStream.seek.md +20 -0
  156. package/docs/interfaces/FileSystemWritableFileStream.truncate.md +20 -0
  157. package/docs/interfaces/FileSystemWritableFileStream.write.md +20 -0
  158. package/docs/interfaces/IDirectoryHandleTreeInitializer.dirHandles.md +9 -0
  159. package/docs/interfaces/IDirectoryHandleTreeInitializer.md +78 -0
  160. package/docs/interfaces/IDirectoryHandleTreeInitializer.nonRecursive.md +9 -0
  161. package/docs/interfaces/IDirectoryHandleTreeInitializer.prefix.md +9 -0
  162. package/docs/interfaces/IFileHandleTreeInitializer.fileHandles.md +9 -0
  163. package/docs/interfaces/IFileHandleTreeInitializer.md +61 -0
  164. package/docs/interfaces/IFileHandleTreeInitializer.prefix.md +9 -0
  165. package/docs/interfaces/IFileListTreeInitializer.fileList.md +9 -0
  166. package/docs/interfaces/IFileListTreeInitializer.md +44 -0
  167. package/docs/interfaces/IFileMetadata.lastModified.md +9 -0
  168. package/docs/interfaces/IFileMetadata.md +112 -0
  169. package/docs/interfaces/IFileMetadata.name.md +9 -0
  170. package/docs/interfaces/IFileMetadata.path.md +9 -0
  171. package/docs/interfaces/IFileMetadata.size.md +9 -0
  172. package/docs/interfaces/IFileMetadata.type.md +9 -0
  173. package/docs/interfaces/IFileSystemAccessTreeParams.autoSync.md +12 -0
  174. package/docs/interfaces/IFileSystemAccessTreeParams.filePath.md +13 -0
  175. package/docs/interfaces/IFileSystemAccessTreeParams.logger.md +11 -0
  176. package/docs/interfaces/IFileSystemAccessTreeParams.md +148 -0
  177. package/docs/interfaces/IFileSystemAccessTreeParams.requireWritePermission.md +13 -0
  178. package/docs/interfaces/IFsAccessApis.md +62 -0
  179. package/docs/interfaces/IFsAccessApis.showDirectoryPicker.md +20 -0
  180. package/docs/interfaces/IFsAccessApis.showOpenFilePicker.md +20 -0
  181. package/docs/interfaces/IFsAccessApis.showSaveFilePicker.md +20 -0
  182. package/docs/interfaces/IHttpTreeParams.autoSync.md +9 -0
  183. package/docs/interfaces/IHttpTreeParams.baseUrl.md +9 -0
  184. package/docs/interfaces/IHttpTreeParams.fetchImpl.md +9 -0
  185. package/docs/interfaces/IHttpTreeParams.logger.md +9 -0
  186. package/docs/interfaces/IHttpTreeParams.md +182 -0
  187. package/docs/interfaces/IHttpTreeParams.namespace.md +9 -0
  188. package/docs/interfaces/IHttpTreeParams.userId.md +9 -0
  189. package/docs/interfaces/ILocalStorageTreeParams.autoSync.md +12 -0
  190. package/docs/interfaces/ILocalStorageTreeParams.md +131 -0
  191. package/docs/interfaces/ILocalStorageTreeParams.pathToKeyMap.md +13 -0
  192. package/docs/interfaces/ILocalStorageTreeParams.storage.md +12 -0
  193. package/docs/interfaces/IUrlConfigOptions.config.md +11 -0
  194. package/docs/interfaces/IUrlConfigOptions.configStartDir.md +11 -0
  195. package/docs/interfaces/IUrlConfigOptions.contextFilter.md +11 -0
  196. package/docs/interfaces/IUrlConfigOptions.input.md +11 -0
  197. package/docs/interfaces/IUrlConfigOptions.inputStartDir.md +11 -0
  198. package/docs/interfaces/IUrlConfigOptions.interactive.md +11 -0
  199. package/docs/interfaces/IUrlConfigOptions.loadZip.md +11 -0
  200. package/docs/interfaces/IUrlConfigOptions.maxDistance.md +11 -0
  201. package/docs/interfaces/IUrlConfigOptions.md +248 -0
  202. package/docs/interfaces/IUrlConfigOptions.qualifierDefaults.md +11 -0
  203. package/docs/interfaces/IUrlConfigOptions.reduceQualifiers.md +11 -0
  204. package/docs/interfaces/IUrlConfigOptions.resourceTypes.md +11 -0
  205. package/docs/interfaces/IUrlConfigOptions.zipFile.md +11 -0
  206. package/docs/interfaces/IUrlConfigOptions.zipPath.md +11 -0
  207. package/docs/interfaces/ShowDirectoryPickerOptions.id.md +9 -0
  208. package/docs/interfaces/ShowDirectoryPickerOptions.md +78 -0
  209. package/docs/interfaces/ShowDirectoryPickerOptions.mode.md +9 -0
  210. package/docs/interfaces/ShowDirectoryPickerOptions.startIn.md +9 -0
  211. package/docs/interfaces/ShowOpenFilePickerOptions.excludeAcceptAllOption.md +9 -0
  212. package/docs/interfaces/ShowOpenFilePickerOptions.id.md +9 -0
  213. package/docs/interfaces/ShowOpenFilePickerOptions.md +112 -0
  214. package/docs/interfaces/ShowOpenFilePickerOptions.multiple.md +9 -0
  215. package/docs/interfaces/ShowOpenFilePickerOptions.startIn.md +9 -0
  216. package/docs/interfaces/ShowOpenFilePickerOptions.types.md +9 -0
  217. package/docs/interfaces/ShowSaveFilePickerOptions.excludeAcceptAllOption.md +9 -0
  218. package/docs/interfaces/ShowSaveFilePickerOptions.id.md +9 -0
  219. package/docs/interfaces/ShowSaveFilePickerOptions.md +112 -0
  220. package/docs/interfaces/ShowSaveFilePickerOptions.startIn.md +9 -0
  221. package/docs/interfaces/ShowSaveFilePickerOptions.suggestedName.md +9 -0
  222. package/docs/interfaces/ShowSaveFilePickerOptions.types.md +9 -0
  223. package/docs/type-aliases/TreeInitializer.md +11 -0
  224. package/docs/type-aliases/WellKnownDirectory.md +11 -0
  225. package/docs/type-aliases/WindowWithFsAccess.md +11 -0
  226. package/docs/variables/DEFAULT_DIRECTORY_HANDLE_DB.md +9 -0
  227. package/docs/variables/DEFAULT_DIRECTORY_HANDLE_STORE.md +9 -0
  228. package/docs/variables/defaultFileApiTreeInitParams.md +9 -0
  229. package/etc/ts-web-extras.api.md +33 -0
  230. package/lib/packlets/file-tree/fileApiTreeAccessors.d.ts +9 -0
  231. package/lib/packlets/file-tree/fileApiTreeAccessors.d.ts.map +1 -1
  232. package/lib/packlets/file-tree/fileApiTreeAccessors.js +15 -0
  233. package/lib/packlets/file-tree/fileApiTreeAccessors.js.map +1 -1
  234. package/lib/packlets/file-tree/fileSystemAccessTreeAccessors.d.ts +17 -1
  235. package/lib/packlets/file-tree/fileSystemAccessTreeAccessors.d.ts.map +1 -1
  236. package/lib/packlets/file-tree/fileSystemAccessTreeAccessors.js +78 -9
  237. package/lib/packlets/file-tree/fileSystemAccessTreeAccessors.js.map +1 -1
  238. package/lib/packlets/file-tree/httpTreeAccessors.d.ts +108 -0
  239. package/lib/packlets/file-tree/httpTreeAccessors.d.ts.map +1 -0
  240. package/lib/packlets/file-tree/httpTreeAccessors.js +370 -0
  241. package/lib/packlets/file-tree/httpTreeAccessors.js.map +1 -0
  242. package/lib/packlets/file-tree/index.d.ts +1 -0
  243. package/lib/packlets/file-tree/index.d.ts.map +1 -1
  244. package/lib/packlets/file-tree/index.js +1 -0
  245. package/lib/packlets/file-tree/index.js.map +1 -1
  246. package/lib/packlets/file-tree/localStorageTreeAccessors.d.ts +12 -0
  247. package/lib/packlets/file-tree/localStorageTreeAccessors.d.ts.map +1 -1
  248. package/lib/packlets/file-tree/localStorageTreeAccessors.js +51 -0
  249. package/lib/packlets/file-tree/localStorageTreeAccessors.js.map +1 -1
  250. package/lib/test/unit/fileApiTreeAccessors.test.js +51 -0
  251. package/lib/test/unit/fileApiTreeAccessors.test.js.map +1 -1
  252. package/lib/test/unit/fileSystemAccessTreeAccessors.test.js +265 -160
  253. package/lib/test/unit/fileSystemAccessTreeAccessors.test.js.map +1 -1
  254. package/lib/test/unit/httpTreeAccessors.test.d.ts +2 -0
  255. package/lib/test/unit/httpTreeAccessors.test.d.ts.map +1 -0
  256. package/lib/test/unit/httpTreeAccessors.test.js +1366 -0
  257. package/lib/test/unit/httpTreeAccessors.test.js.map +1 -0
  258. package/lib/test/unit/localStorageTreeAccessors.test.js +218 -1
  259. package/lib/test/unit/localStorageTreeAccessors.test.js.map +1 -1
  260. package/package.json +13 -12
  261. package/rush-logs/ts-web-extras.build.cache.log +1 -1
  262. package/rush-logs/ts-web-extras.build.log +37 -34
  263. package/src/packlets/file-tree/fileApiTreeAccessors.ts +18 -0
  264. package/src/packlets/file-tree/fileSystemAccessTreeAccessors.ts +100 -8
  265. package/src/packlets/file-tree/httpTreeAccessors.ts +478 -0
  266. package/src/packlets/file-tree/index.ts +1 -0
  267. package/src/packlets/file-tree/localStorageTreeAccessors.ts +53 -0
  268. package/src/test/unit/fileApiTreeAccessors.test.ts +69 -0
  269. package/src/test/unit/fileSystemAccessTreeAccessors.test.ts +341 -188
  270. package/src/test/unit/httpTreeAccessors.test.ts +1750 -0
  271. package/src/test/unit/localStorageTreeAccessors.test.ts +269 -1
  272. package/temp/build/typescript/ts_8nwakTlr.json +1 -1
  273. package/temp/coverage/crypto-utils/browserCryptoProvider.ts.html +1 -1
  274. package/temp/coverage/crypto-utils/browserHashProvider.ts.html +1 -1
  275. package/temp/coverage/crypto-utils/index.html +1 -1
  276. package/temp/coverage/file-tree/directoryHandleStore.ts.html +1 -1
  277. package/temp/coverage/file-tree/fileApiTreeAccessors.ts.html +60 -6
  278. package/temp/coverage/file-tree/fileSystemAccessTreeAccessors.ts.html +410 -134
  279. package/temp/coverage/file-tree/httpTreeAccessors.ts.html +1519 -0
  280. package/temp/coverage/file-tree/index.html +35 -20
  281. package/temp/coverage/file-tree/localStorageTreeAccessors.ts.html +318 -159
  282. package/temp/coverage/helpers/fileTreeHelpers.ts.html +1 -1
  283. package/temp/coverage/helpers/index.html +1 -1
  284. package/temp/coverage/index.html +11 -11
  285. package/temp/coverage/lcov-report/crypto-utils/browserCryptoProvider.ts.html +1 -1
  286. package/temp/coverage/lcov-report/crypto-utils/browserHashProvider.ts.html +1 -1
  287. package/temp/coverage/lcov-report/crypto-utils/index.html +1 -1
  288. package/temp/coverage/lcov-report/file-tree/directoryHandleStore.ts.html +1 -1
  289. package/temp/coverage/lcov-report/file-tree/fileApiTreeAccessors.ts.html +60 -6
  290. package/temp/coverage/lcov-report/file-tree/fileSystemAccessTreeAccessors.ts.html +410 -134
  291. package/temp/coverage/lcov-report/file-tree/httpTreeAccessors.ts.html +1519 -0
  292. package/temp/coverage/lcov-report/file-tree/index.html +35 -20
  293. package/temp/coverage/lcov-report/file-tree/localStorageTreeAccessors.ts.html +318 -159
  294. package/temp/coverage/lcov-report/helpers/fileTreeHelpers.ts.html +1 -1
  295. package/temp/coverage/lcov-report/helpers/index.html +1 -1
  296. package/temp/coverage/lcov-report/index.html +11 -11
  297. package/temp/coverage/lcov-report/url-utils/index.html +1 -1
  298. package/temp/coverage/lcov-report/url-utils/urlParams.ts.html +1 -1
  299. package/temp/coverage/lcov.info +2052 -1195
  300. package/temp/coverage/url-utils/index.html +1 -1
  301. package/temp/coverage/url-utils/urlParams.ts.html +1 -1
  302. package/temp/test/jest/haste-map-7492f1b44480e0cdd1f220078fb3afd8-c8dd6c3430605adeb2f1cadf4f75e791-8c9336785555d572065b28c111982ba4 +0 -0
  303. package/temp/test/jest/perf-cache-7492f1b44480e0cdd1f220078fb3afd8-da39a3ee5e6b4b0d3255bfef95601890 +1 -1
  304. package/temp/ts-web-extras.api.json +1314 -355
  305. package/temp/ts-web-extras.api.md +33 -0
  306. package/docs/index.md +0 -34
  307. package/docs/ts-web-extras.cryptoutils.browsercryptoprovider._constructor_.md +0 -50
  308. package/docs/ts-web-extras.cryptoutils.browsercryptoprovider.decrypt.md +0 -104
  309. package/docs/ts-web-extras.cryptoutils.browsercryptoprovider.derivekey.md +0 -88
  310. package/docs/ts-web-extras.cryptoutils.browsercryptoprovider.encrypt.md +0 -72
  311. package/docs/ts-web-extras.cryptoutils.browsercryptoprovider.frombase64.md +0 -56
  312. package/docs/ts-web-extras.cryptoutils.browsercryptoprovider.generatekey.md +0 -19
  313. package/docs/ts-web-extras.cryptoutils.browsercryptoprovider.generaterandombytes.md +0 -56
  314. package/docs/ts-web-extras.cryptoutils.browsercryptoprovider.md +0 -169
  315. package/docs/ts-web-extras.cryptoutils.browsercryptoprovider.tobase64.md +0 -56
  316. package/docs/ts-web-extras.cryptoutils.browserhashprovider.hashparts.md +0 -88
  317. package/docs/ts-web-extras.cryptoutils.browserhashprovider.hashstring.md +0 -72
  318. package/docs/ts-web-extras.cryptoutils.browserhashprovider.md +0 -66
  319. package/docs/ts-web-extras.cryptoutils.createbrowsercryptoprovider.md +0 -19
  320. package/docs/ts-web-extras.cryptoutils.md +0 -71
  321. package/docs/ts-web-extras.exportasjson.md +0 -70
  322. package/docs/ts-web-extras.exportusingfilesystemapi.md +0 -104
  323. package/docs/ts-web-extras.extractdirectorypath.md +0 -52
  324. package/docs/ts-web-extras.fileapitreeaccessors.create.md +0 -72
  325. package/docs/ts-web-extras.fileapitreeaccessors.createfromlocalstorage.md +0 -74
  326. package/docs/ts-web-extras.fileapitreeaccessors.createpersistent.md +0 -76
  327. package/docs/ts-web-extras.fileapitreeaccessors.extractfilemetadata.md +0 -54
  328. package/docs/ts-web-extras.fileapitreeaccessors.fromdirectoryupload.md +0 -72
  329. package/docs/ts-web-extras.fileapitreeaccessors.fromfilelist.md +0 -72
  330. package/docs/ts-web-extras.fileapitreeaccessors.getoriginalfile.md +0 -72
  331. package/docs/ts-web-extras.fileapitreeaccessors.md +0 -146
  332. package/docs/ts-web-extras.filepickeraccepttype.accept.md +0 -11
  333. package/docs/ts-web-extras.filepickeraccepttype.description.md +0 -11
  334. package/docs/ts-web-extras.filepickeraccepttype.md +0 -75
  335. package/docs/ts-web-extras.filesystemaccesstreeaccessors._constructor_.md +0 -114
  336. package/docs/ts-web-extras.filesystemaccesstreeaccessors.fileismutable.md +0 -52
  337. package/docs/ts-web-extras.filesystemaccesstreeaccessors.fromdirectoryhandle.md +0 -72
  338. package/docs/ts-web-extras.filesystemaccesstreeaccessors.getdirtypaths.md +0 -17
  339. package/docs/ts-web-extras.filesystemaccesstreeaccessors.isdirty.md +0 -17
  340. package/docs/ts-web-extras.filesystemaccesstreeaccessors.md +0 -159
  341. package/docs/ts-web-extras.filesystemaccesstreeaccessors.savefilecontents.md +0 -66
  342. package/docs/ts-web-extras.filesystemaccesstreeaccessors.synctodisk.md +0 -17
  343. package/docs/ts-web-extras.filesystemcreatewritableoptions_2.keepexistingdata.md +0 -11
  344. package/docs/ts-web-extras.filesystemcreatewritableoptions_2.md +0 -58
  345. package/docs/ts-web-extras.filesystemdirectoryhandle_2._symbol.asynciterator_.md +0 -15
  346. package/docs/ts-web-extras.filesystemdirectoryhandle_2.entries.md +0 -15
  347. package/docs/ts-web-extras.filesystemdirectoryhandle_2.getdirectoryhandle.md +0 -66
  348. package/docs/ts-web-extras.filesystemdirectoryhandle_2.getfilehandle.md +0 -66
  349. package/docs/ts-web-extras.filesystemdirectoryhandle_2.keys.md +0 -15
  350. package/docs/ts-web-extras.filesystemdirectoryhandle_2.kind.md +0 -11
  351. package/docs/ts-web-extras.filesystemdirectoryhandle_2.md +0 -146
  352. package/docs/ts-web-extras.filesystemdirectoryhandle_2.removeentry.md +0 -66
  353. package/docs/ts-web-extras.filesystemdirectoryhandle_2.resolve.md +0 -50
  354. package/docs/ts-web-extras.filesystemdirectoryhandle_2.values.md +0 -15
  355. package/docs/ts-web-extras.filesystemfilehandle_2.createwritable.md +0 -52
  356. package/docs/ts-web-extras.filesystemfilehandle_2.getfile.md +0 -15
  357. package/docs/ts-web-extras.filesystemfilehandle_2.kind.md +0 -11
  358. package/docs/ts-web-extras.filesystemfilehandle_2.md +0 -92
  359. package/docs/ts-web-extras.filesystemgetdirectoryoptions_2.create.md +0 -11
  360. package/docs/ts-web-extras.filesystemgetdirectoryoptions_2.md +0 -58
  361. package/docs/ts-web-extras.filesystemgetfileoptions_2.create.md +0 -11
  362. package/docs/ts-web-extras.filesystemgetfileoptions_2.md +0 -58
  363. package/docs/ts-web-extras.filesystemhandle_2.issameentry.md +0 -50
  364. package/docs/ts-web-extras.filesystemhandle_2.kind.md +0 -11
  365. package/docs/ts-web-extras.filesystemhandle_2.md +0 -119
  366. package/docs/ts-web-extras.filesystemhandle_2.name.md +0 -11
  367. package/docs/ts-web-extras.filesystemhandle_2.querypermission.md +0 -52
  368. package/docs/ts-web-extras.filesystemhandle_2.requestpermission.md +0 -52
  369. package/docs/ts-web-extras.filesystemhandlepermissiondescriptor.md +0 -58
  370. package/docs/ts-web-extras.filesystemhandlepermissiondescriptor.mode.md +0 -11
  371. package/docs/ts-web-extras.filesystemremoveoptions_2.md +0 -58
  372. package/docs/ts-web-extras.filesystemremoveoptions_2.recursive.md +0 -11
  373. package/docs/ts-web-extras.filesystemwritablefilestream_2.md +0 -57
  374. package/docs/ts-web-extras.filesystemwritablefilestream_2.seek.md +0 -50
  375. package/docs/ts-web-extras.filesystemwritablefilestream_2.truncate.md +0 -50
  376. package/docs/ts-web-extras.filesystemwritablefilestream_2.write.md +0 -50
  377. package/docs/ts-web-extras.filetreehelpers.defaultfileapitreeinitparams.md +0 -13
  378. package/docs/ts-web-extras.filetreehelpers.extractfilelistmetadata.md +0 -56
  379. package/docs/ts-web-extras.filetreehelpers.extractfilemetadata.md +0 -56
  380. package/docs/ts-web-extras.filetreehelpers.fromdirectoryupload.md +0 -76
  381. package/docs/ts-web-extras.filetreehelpers.fromfilelist.md +0 -76
  382. package/docs/ts-web-extras.filetreehelpers.getoriginalfile.md +0 -72
  383. package/docs/ts-web-extras.filetreehelpers.md +0 -102
  384. package/docs/ts-web-extras.idirectoryhandletreeinitializer.dirhandles.md +0 -11
  385. package/docs/ts-web-extras.idirectoryhandletreeinitializer.md +0 -100
  386. package/docs/ts-web-extras.idirectoryhandletreeinitializer.nonrecursive.md +0 -11
  387. package/docs/ts-web-extras.idirectoryhandletreeinitializer.prefix.md +0 -11
  388. package/docs/ts-web-extras.ifilehandletreeinitializer.filehandles.md +0 -11
  389. package/docs/ts-web-extras.ifilehandletreeinitializer.md +0 -79
  390. package/docs/ts-web-extras.ifilehandletreeinitializer.prefix.md +0 -11
  391. package/docs/ts-web-extras.ifilelisttreeinitializer.filelist.md +0 -11
  392. package/docs/ts-web-extras.ifilelisttreeinitializer.md +0 -58
  393. package/docs/ts-web-extras.ifilemetadata.lastmodified.md +0 -11
  394. package/docs/ts-web-extras.ifilemetadata.md +0 -124
  395. package/docs/ts-web-extras.ifilemetadata.name.md +0 -11
  396. package/docs/ts-web-extras.ifilemetadata.path.md +0 -11
  397. package/docs/ts-web-extras.ifilemetadata.size.md +0 -11
  398. package/docs/ts-web-extras.ifilemetadata.type.md +0 -11
  399. package/docs/ts-web-extras.ifilesystemaccesstreeparams.autosync.md +0 -13
  400. package/docs/ts-web-extras.ifilesystemaccesstreeparams.md +0 -78
  401. package/docs/ts-web-extras.ifilesystemaccesstreeparams.requirewritepermission.md +0 -13
  402. package/docs/ts-web-extras.ifsaccessapis.md +0 -56
  403. package/docs/ts-web-extras.ifsaccessapis.showdirectorypicker.md +0 -52
  404. package/docs/ts-web-extras.ifsaccessapis.showopenfilepicker.md +0 -52
  405. package/docs/ts-web-extras.ifsaccessapis.showsavefilepicker.md +0 -52
  406. package/docs/ts-web-extras.ilocalstoragetreeparams.autosync.md +0 -13
  407. package/docs/ts-web-extras.ilocalstoragetreeparams.md +0 -97
  408. package/docs/ts-web-extras.ilocalstoragetreeparams.pathtokeymap.md +0 -13
  409. package/docs/ts-web-extras.ilocalstoragetreeparams.storage.md +0 -13
  410. package/docs/ts-web-extras.isdirectoryhandle.md +0 -56
  411. package/docs/ts-web-extras.isfilehandle.md +0 -56
  412. package/docs/ts-web-extras.isfilepath.md +0 -52
  413. package/docs/ts-web-extras.iurlconfigoptions.config.md +0 -13
  414. package/docs/ts-web-extras.iurlconfigoptions.configstartdir.md +0 -13
  415. package/docs/ts-web-extras.iurlconfigoptions.contextfilter.md +0 -13
  416. package/docs/ts-web-extras.iurlconfigoptions.input.md +0 -13
  417. package/docs/ts-web-extras.iurlconfigoptions.inputstartdir.md +0 -13
  418. package/docs/ts-web-extras.iurlconfigoptions.interactive.md +0 -13
  419. package/docs/ts-web-extras.iurlconfigoptions.loadzip.md +0 -13
  420. package/docs/ts-web-extras.iurlconfigoptions.maxdistance.md +0 -13
  421. package/docs/ts-web-extras.iurlconfigoptions.md +0 -286
  422. package/docs/ts-web-extras.iurlconfigoptions.qualifierdefaults.md +0 -13
  423. package/docs/ts-web-extras.iurlconfigoptions.reducequalifiers.md +0 -13
  424. package/docs/ts-web-extras.iurlconfigoptions.resourcetypes.md +0 -13
  425. package/docs/ts-web-extras.iurlconfigoptions.zipfile.md +0 -13
  426. package/docs/ts-web-extras.iurlconfigoptions.zippath.md +0 -13
  427. package/docs/ts-web-extras.localstoragetreeaccessors.fileismutable.md +0 -56
  428. package/docs/ts-web-extras.localstoragetreeaccessors.fromstorage.md +0 -56
  429. package/docs/ts-web-extras.localstoragetreeaccessors.getdirtypaths.md +0 -19
  430. package/docs/ts-web-extras.localstoragetreeaccessors.isdirty.md +0 -19
  431. package/docs/ts-web-extras.localstoragetreeaccessors.md +0 -131
  432. package/docs/ts-web-extras.localstoragetreeaccessors.savefilecontents.md +0 -72
  433. package/docs/ts-web-extras.localstoragetreeaccessors.synctodisk.md +0 -19
  434. package/docs/ts-web-extras.md +0 -558
  435. package/docs/ts-web-extras.parsecontextfilter.md +0 -52
  436. package/docs/ts-web-extras.parsequalifierdefaults.md +0 -52
  437. package/docs/ts-web-extras.parseresourcetypes.md +0 -52
  438. package/docs/ts-web-extras.parseurlparameters.md +0 -17
  439. package/docs/ts-web-extras.safeshowdirectorypicker.md +0 -72
  440. package/docs/ts-web-extras.safeshowopenfilepicker.md +0 -72
  441. package/docs/ts-web-extras.safeshowsavefilepicker.md +0 -72
  442. package/docs/ts-web-extras.showdirectorypickeroptions.id.md +0 -11
  443. package/docs/ts-web-extras.showdirectorypickeroptions.md +0 -96
  444. package/docs/ts-web-extras.showdirectorypickeroptions.mode.md +0 -11
  445. package/docs/ts-web-extras.showdirectorypickeroptions.startin.md +0 -11
  446. package/docs/ts-web-extras.showopenfilepickeroptions.excludeacceptalloption.md +0 -11
  447. package/docs/ts-web-extras.showopenfilepickeroptions.id.md +0 -11
  448. package/docs/ts-web-extras.showopenfilepickeroptions.md +0 -134
  449. package/docs/ts-web-extras.showopenfilepickeroptions.multiple.md +0 -11
  450. package/docs/ts-web-extras.showopenfilepickeroptions.startin.md +0 -11
  451. package/docs/ts-web-extras.showopenfilepickeroptions.types.md +0 -11
  452. package/docs/ts-web-extras.showsavefilepickeroptions.excludeacceptalloption.md +0 -11
  453. package/docs/ts-web-extras.showsavefilepickeroptions.id.md +0 -11
  454. package/docs/ts-web-extras.showsavefilepickeroptions.md +0 -134
  455. package/docs/ts-web-extras.showsavefilepickeroptions.startin.md +0 -11
  456. package/docs/ts-web-extras.showsavefilepickeroptions.suggestedname.md +0 -11
  457. package/docs/ts-web-extras.showsavefilepickeroptions.types.md +0 -11
  458. package/docs/ts-web-extras.supportsfilesystemaccess.md +0 -56
  459. package/docs/ts-web-extras.treeinitializer.md +0 -15
  460. package/docs/ts-web-extras.wellknowndirectory.md +0 -13
  461. package/docs/ts-web-extras.windowwithfsaccess.md +0 -15
  462. /package/temp/test/jest/jest-transform-cache-7492f1b44480e0cdd1f220078fb3afd8-79ef2876fae7ca75eedb2aa53dc48338/{8d/package_8dcbedef69e4299f0f51fcda8f4f1c8e → 7c/package_7c16afc8299e635d80273763175c7a50} +0 -0
@@ -20,6 +20,7 @@
20
20
  * SOFTWARE.
21
21
  */
22
22
  import '@fgv/ts-utils-jest';
23
+ import { fail } from '@fgv/ts-utils';
23
24
  import { FileSystemAccessTreeAccessors } from '../../packlets/file-tree';
24
25
  import { FileApiTreeAccessors } from '../../packlets/file-tree';
25
26
  import { FileTree } from '@fgv/ts-json-base';
@@ -331,186 +332,290 @@ describe('FileSystemAccessTreeAccessors', () => {
331
332
  })).orThrow();
332
333
  accessors.saveFileContents('/test.txt', 'modified').orThrow();
333
334
  // Verify file is marked dirty but not synced
334
- expect(accessors.isDirty()).toBe(true);
335
335
  expect(accessors.getDirtyPaths()).toContain('/test.txt');
336
336
  // In-memory content should be modified
337
337
  expect(accessors.getFileContents('/test.txt')).toSucceedWith('modified');
338
338
  });
339
- });
340
- });
341
- describe('fileIsMutable', () => {
342
- test('returns persistent detail when write permission granted', async () => {
343
- const dirHandle = createMockDirectoryHandle('/', {
344
- 'test.txt': { content: 'test', type: 'text/plain' }
345
- });
346
- const accessors = (await FileSystemAccessTreeAccessors.fromDirectoryHandle(dirHandle, { mutable: true })).orThrow();
347
- const result = accessors.fileIsMutable('/test.txt');
348
- expect(result).toSucceedWithDetail(true, 'persistent');
349
- });
350
- test('returns transient detail when write permission not granted', async () => {
351
- const dirHandle = createMockDirectoryHandle('/', { 'test.txt': { content: 'test', type: 'text/plain' } }, { hasWritePermission: false });
352
- const accessors = (await FileSystemAccessTreeAccessors.fromDirectoryHandle(dirHandle, {
353
- mutable: true,
354
- requireWritePermission: false
355
- })).orThrow();
356
- const result = accessors.fileIsMutable('/test.txt');
357
- expect(result).toSucceedWithDetail(true, 'transient');
358
- });
359
- test('returns not-mutable when mutability disabled', async () => {
360
- const dirHandle = createMockDirectoryHandle('/', {
361
- 'test.txt': { content: 'test', type: 'text/plain' }
339
+ test('logs when save auto-sync returns a failure Result', async () => {
340
+ const logger = {
341
+ detail: jest.fn(),
342
+ info: jest.fn(),
343
+ warn: jest.fn(),
344
+ error: jest.fn()
345
+ };
346
+ const dirHandle = createMockDirectoryHandle('/', {
347
+ 'test.txt': { content: 'original', type: 'text/plain' }
348
+ });
349
+ const accessors = (await FileSystemAccessTreeAccessors.fromDirectoryHandle(dirHandle, {
350
+ mutable: true,
351
+ autoSync: true,
352
+ logger
353
+ })).orThrow();
354
+ accessors._syncFile = async () => fail('simulated save sync failure');
355
+ accessors.saveFileContents('/test.txt', 'modified').orThrow();
356
+ await new Promise((resolve) => setTimeout(resolve, 0));
357
+ expect(logger.error).toHaveBeenCalledWith(expect.stringContaining('simulated save sync failure'));
358
+ });
359
+ test('logs when delete auto-sync throws unexpectedly', async () => {
360
+ const logger = {
361
+ detail: jest.fn(),
362
+ info: jest.fn(),
363
+ warn: jest.fn(),
364
+ error: jest.fn()
365
+ };
366
+ const dirHandle = createMockDirectoryHandle('/', {
367
+ 'test.txt': { content: 'original', type: 'text/plain' }
368
+ });
369
+ const accessors = (await FileSystemAccessTreeAccessors.fromDirectoryHandle(dirHandle, {
370
+ mutable: true,
371
+ autoSync: true,
372
+ logger
373
+ })).orThrow();
374
+ accessors._deleteFileFromDisk = async () => {
375
+ throw new Error('simulated delete throw');
376
+ };
377
+ accessors.deleteFile('/test.txt').orThrow();
378
+ await new Promise((resolve) => setTimeout(resolve, 0));
379
+ expect(logger.error).toHaveBeenCalledWith(expect.stringContaining('simulated delete throw'));
362
380
  });
363
- const accessors = (await FileSystemAccessTreeAccessors.fromDirectoryHandle(dirHandle, { mutable: false })).orThrow();
364
- const result = accessors.fileIsMutable('/test.txt');
365
- expect(result).toFailWithDetail(/mutability is disabled/i, 'not-mutable');
366
381
  });
367
- });
368
- describe('integration with FileApiTreeAccessors', () => {
369
- test('createPersistent creates FileTree with persistent accessors', async () => {
370
- const dirHandle = createMockDirectoryHandle('/', {
371
- 'test.txt': { content: 'test content', type: 'text/plain' }
382
+ describe('fileIsMutable', () => {
383
+ test('returns persistent detail when write permission granted', async () => {
384
+ const dirHandle = createMockDirectoryHandle('/', {
385
+ 'test.txt': { content: 'test', type: 'text/plain' }
386
+ });
387
+ const accessors = (await FileSystemAccessTreeAccessors.fromDirectoryHandle(dirHandle, { mutable: true })).orThrow();
388
+ const result = accessors.fileIsMutable('/test.txt');
389
+ expect(result).toSucceedWithDetail(true, 'persistent');
372
390
  });
373
- const result = await FileApiTreeAccessors.createPersistent(dirHandle, { mutable: true });
374
- expect(result).toSucceed();
375
- const tree = result.orThrow();
376
- expect(tree).toBeInstanceOf(FileTree.FileTree);
377
- expect(FileTree.isPersistentAccessors(tree.hal)).toBe(true);
378
- const file = tree.getFile('/test.txt').orThrow();
379
- expect(file.getIsMutable()).toSucceedWithDetail(true, 'persistent');
380
- });
381
- test('createPersistent with autoSync option', async () => {
382
- const dirHandle = createMockDirectoryHandle('/', {
383
- 'test.txt': { content: 'original', type: 'text/plain' }
391
+ test('returns transient detail when write permission not granted', async () => {
392
+ const dirHandle = createMockDirectoryHandle('/', { 'test.txt': { content: 'test', type: 'text/plain' } }, { hasWritePermission: false });
393
+ const accessors = (await FileSystemAccessTreeAccessors.fromDirectoryHandle(dirHandle, {
394
+ mutable: true,
395
+ requireWritePermission: false
396
+ })).orThrow();
397
+ const result = accessors.fileIsMutable('/test.txt');
398
+ expect(result).toSucceedWithDetail(true, 'transient');
384
399
  });
385
- const result = await FileApiTreeAccessors.createPersistent(dirHandle, {
386
- mutable: true,
387
- autoSync: true
400
+ test('returns not-mutable when mutability disabled', async () => {
401
+ const dirHandle = createMockDirectoryHandle('/', {
402
+ 'test.txt': { content: 'test', type: 'text/plain' }
403
+ });
404
+ const accessors = (await FileSystemAccessTreeAccessors.fromDirectoryHandle(dirHandle, { mutable: false })).orThrow();
405
+ const result = accessors.fileIsMutable('/test.txt');
406
+ expect(result).toFailWithDetail(/mutability is disabled/i, 'not-mutable');
388
407
  });
389
- expect(result).toSucceedAndSatisfy((tree) => {
408
+ });
409
+ describe('integration with FileApiTreeAccessors', () => {
410
+ test('createPersistent creates FileTree with persistent accessors', async () => {
411
+ const dirHandle = createMockDirectoryHandle('/', {
412
+ 'test.txt': { content: 'test content', type: 'text/plain' }
413
+ });
414
+ const result = await FileApiTreeAccessors.createPersistent(dirHandle, { mutable: true });
415
+ expect(result).toSucceed();
416
+ const tree = result.orThrow();
390
417
  expect(tree).toBeInstanceOf(FileTree.FileTree);
418
+ expect(FileTree.isPersistentAccessors(tree.hal)).toBe(true);
419
+ const file = tree.getFile('/test.txt').orThrow();
420
+ expect(FileTree.isMutableFileItem(file)).toBe(true);
421
+ if (FileTree.isMutableFileItem(file)) {
422
+ expect(file.getIsMutable()).toSucceedWithDetail(true, 'persistent');
423
+ }
391
424
  });
392
- const tree = result.orThrow();
393
- const file = tree.getFile('/test.txt').orThrow();
394
- file.setRawContents('modified').orThrow();
395
- // Give auto-sync time to complete
396
- await new Promise((resolve) => setTimeout(resolve, 10));
397
- // Verify file was written
398
- const fileHandle = await dirHandle.getFileHandle('test.txt');
399
- const diskFile = await fileHandle.getFile();
400
- const content = await diskFile.text();
401
- expect(content).toBe('modified');
402
- });
403
- test('createPersistent fails with appropriate error', async () => {
404
- const dirHandle = createMockDirectoryHandle('/', { 'test.txt': { content: 'test', type: 'text/plain' } }, { hasWritePermission: false });
405
- const result = await FileApiTreeAccessors.createPersistent(dirHandle, {
406
- requireWritePermission: true
425
+ test('createPersistent with autoSync option', async () => {
426
+ const dirHandle = createMockDirectoryHandle('/', {
427
+ 'test.txt': { content: 'original', type: 'text/plain' }
428
+ });
429
+ const result = await FileApiTreeAccessors.createPersistent(dirHandle, {
430
+ mutable: true,
431
+ autoSync: true
432
+ });
433
+ expect(result).toSucceedAndSatisfy((tree) => {
434
+ expect(tree).toBeInstanceOf(FileTree.FileTree);
435
+ });
436
+ const tree = result.orThrow();
437
+ const file = tree.getFile('/test.txt').orThrow();
438
+ expect(FileTree.isMutableFileItem(file)).toBe(true);
439
+ if (FileTree.isMutableFileItem(file)) {
440
+ file.setRawContents('modified').orThrow();
441
+ }
442
+ // Give auto-sync time to complete
443
+ await new Promise((resolve) => setTimeout(resolve, 10));
444
+ // Verify file was written
445
+ const fileHandle = await dirHandle.getFileHandle('test.txt');
446
+ const diskFile = await fileHandle.getFile();
447
+ const content = await diskFile.text();
448
+ expect(content).toBe('modified');
407
449
  });
408
- expect(result).toFailWith(/write permission required/i);
409
- });
410
- });
411
- describe('error handling', () => {
412
- test('handles permission query errors gracefully', async () => {
413
- const dirHandle = createMockDirectoryHandle('/', { 'test.txt': { content: 'test', type: 'text/plain' } }, { permissionError: true });
414
- const result = await FileSystemAccessTreeAccessors.fromDirectoryHandle(dirHandle, {
415
- requireWritePermission: false
450
+ test('createPersistent fails with appropriate error', async () => {
451
+ const dirHandle = createMockDirectoryHandle('/', { 'test.txt': { content: 'test', type: 'text/plain' } }, { hasWritePermission: false });
452
+ const result = await FileApiTreeAccessors.createPersistent(dirHandle, {
453
+ requireWritePermission: true
454
+ });
455
+ expect(result).toFailWith(/write permission required/i);
416
456
  });
417
- // Should succeed but without write permission due to error
418
- expect(result).toSucceed();
419
457
  });
420
- test('handles permission status "prompt" by requesting permission', async () => {
421
- const dirHandle = createMockDirectoryHandle('/', { 'test.txt': { content: 'test', type: 'text/plain' } }, { permissionStatus: 'prompt', requestGranted: true });
422
- const result = await FileSystemAccessTreeAccessors.fromDirectoryHandle(dirHandle, {
423
- requireWritePermission: true
458
+ describe('error handling', () => {
459
+ test('handles permission query errors gracefully', async () => {
460
+ const dirHandle = createMockDirectoryHandle('/', { 'test.txt': { content: 'test', type: 'text/plain' } }, { permissionError: true });
461
+ const result = await FileSystemAccessTreeAccessors.fromDirectoryHandle(dirHandle, {
462
+ requireWritePermission: false
463
+ });
464
+ // Should succeed but without write permission due to error
465
+ expect(result).toSucceed();
424
466
  });
425
- expect(result).toSucceedAndSatisfy((accessors) => {
426
- expect(accessors).toBeInstanceOf(FileSystemAccessTreeAccessors);
467
+ test('handles permission status "prompt" by requesting permission', async () => {
468
+ const dirHandle = createMockDirectoryHandle('/', { 'test.txt': { content: 'test', type: 'text/plain' } }, { permissionStatus: 'prompt', requestGranted: true });
469
+ const result = await FileSystemAccessTreeAccessors.fromDirectoryHandle(dirHandle, {
470
+ requireWritePermission: true
471
+ });
472
+ expect(result).toSucceedAndSatisfy((accessors) => {
473
+ expect(accessors).toBeInstanceOf(FileSystemAccessTreeAccessors);
474
+ });
427
475
  });
428
- });
429
- test('handles sync failures with aggregated errors', async () => {
430
- const dirHandle = createMockDirectoryHandle('/', {
431
- 'file1.txt': { content: 'content1', type: 'text/plain' },
432
- 'file2.txt': { content: 'content2', type: 'text/plain' }
433
- });
434
- const accessors = (await FileSystemAccessTreeAccessors.fromDirectoryHandle(dirHandle, { mutable: true })).orThrow();
435
- // Modify files
436
- accessors.saveFileContents('/file1.txt', 'modified1').orThrow();
437
- accessors.saveFileContents('/file2.txt', 'modified2').orThrow();
438
- // Replace the file handles with ones that fail to write
439
- const handles = accessors._handles;
440
- for (const [, handle] of handles) {
441
- handle.createWritable = jest.fn().mockRejectedValue(new Error('Write permission denied'));
442
- }
443
- const syncResult = await accessors.syncToDisk();
444
- expect(syncResult).toFailWith(/Failed to sync 2 file\(s\)/i);
445
- });
446
- test('handles getFileContents failure during sync', async () => {
447
- const dirHandle = createMockDirectoryHandle('/', {
448
- 'test.txt': { content: 'original', type: 'text/plain' }
449
- });
450
- const accessors = (await FileSystemAccessTreeAccessors.fromDirectoryHandle(dirHandle, { mutable: true })).orThrow();
451
- // Add a new file
452
- accessors.saveFileContents('/newfile.txt', 'new content').orThrow();
453
- // Override getFileContents to fail
454
- const originalGetFileContents = accessors.getFileContents.bind(accessors);
455
- accessors.getFileContents = jest.fn((path) => {
456
- if (path === '/newfile.txt') {
457
- return { isSuccess: () => false, isFailure: () => true, message: 'File read error' };
476
+ test('handles sync failures with aggregated errors', async () => {
477
+ const dirHandle = createMockDirectoryHandle('/', {
478
+ 'file1.txt': { content: 'content1', type: 'text/plain' },
479
+ 'file2.txt': { content: 'content2', type: 'text/plain' }
480
+ });
481
+ const accessors = (await FileSystemAccessTreeAccessors.fromDirectoryHandle(dirHandle, { mutable: true })).orThrow();
482
+ // Modify files
483
+ accessors.saveFileContents('/file1.txt', 'modified1').orThrow();
484
+ accessors.saveFileContents('/file2.txt', 'modified2').orThrow();
485
+ // Replace the file handles with ones that fail to write
486
+ const handles = accessors._handles;
487
+ for (const [, handle] of handles) {
488
+ handle.createWritable = jest.fn().mockRejectedValue(new Error('Write permission denied'));
458
489
  }
459
- return originalGetFileContents(path);
490
+ const syncResult = await accessors.syncToDisk();
491
+ expect(syncResult).toFailWith(/Failed to sync 2 file\(s\)/i);
460
492
  });
461
- const syncResult = await accessors.syncToDisk();
462
- expect(syncResult).toFailWith(/File read error/i);
463
- });
464
- test('handles file write failure during sync', async () => {
465
- const dirHandle = createMockDirectoryHandle('/', {
466
- 'test.txt': { content: 'original', type: 'text/plain' }
467
- });
468
- const accessors = (await FileSystemAccessTreeAccessors.fromDirectoryHandle(dirHandle, { mutable: true })).orThrow();
469
- accessors.saveFileContents('/test.txt', 'modified').orThrow();
470
- // Replace the handle with one that fails to write
471
- const handles = accessors._handles;
472
- const handle = handles.get('/test.txt');
473
- handle.createWritable = jest.fn().mockRejectedValue(new Error('Disk full'));
474
- const syncResult = await accessors.syncToDisk();
475
- expect(syncResult).toFailWith(/Failed to write file.*Disk full/i);
476
- });
477
- test('handles invalid file path with no filename', async () => {
478
- const dirHandle = createMockDirectoryHandle('/', {
479
- 'existing.txt': { content: 'existing', type: 'text/plain' }
480
- });
481
- const accessors = (await FileSystemAccessTreeAccessors.fromDirectoryHandle(dirHandle, { mutable: true })).orThrow();
482
- // Override resolveAbsolutePath to return an empty path to trigger the error
483
- const originalResolveAbsolutePath = accessors.resolveAbsolutePath.bind(accessors);
484
- accessors.resolveAbsolutePath = jest.fn((path) => {
485
- if (path === '/badpath') {
486
- return ''; // This will result in no parts after split
493
+ test('handles getFileContents failure during sync', async () => {
494
+ const dirHandle = createMockDirectoryHandle('/', {
495
+ 'test.txt': { content: 'original', type: 'text/plain' }
496
+ });
497
+ const accessors = (await FileSystemAccessTreeAccessors.fromDirectoryHandle(dirHandle, { mutable: true })).orThrow();
498
+ // Add a new file
499
+ accessors.saveFileContents('/newfile.txt', 'new content').orThrow();
500
+ // Override getFileContents to fail
501
+ const originalGetFileContents = accessors.getFileContents.bind(accessors);
502
+ accessors.getFileContents = jest.fn((path) => {
503
+ if (path === '/newfile.txt') {
504
+ return { isSuccess: () => false, isFailure: () => true, message: 'File read error' };
505
+ }
506
+ return originalGetFileContents(path);
507
+ });
508
+ const syncResult = await accessors.syncToDisk();
509
+ expect(syncResult).toFailWith(/File read error/i);
510
+ });
511
+ test('handles file write failure during sync', async () => {
512
+ const dirHandle = createMockDirectoryHandle('/', {
513
+ 'test.txt': { content: 'original', type: 'text/plain' }
514
+ });
515
+ const accessors = (await FileSystemAccessTreeAccessors.fromDirectoryHandle(dirHandle, { mutable: true })).orThrow();
516
+ accessors.saveFileContents('/test.txt', 'modified').orThrow();
517
+ // Replace the handle with one that fails to write
518
+ const handles = accessors._handles;
519
+ const handle = handles.get('/test.txt');
520
+ handle.createWritable = jest.fn().mockRejectedValue(new Error('Disk full'));
521
+ const syncResult = await accessors.syncToDisk();
522
+ expect(syncResult).toFailWith(/Failed to write file.*Disk full/i);
523
+ });
524
+ test('handles invalid file path with no filename', async () => {
525
+ const dirHandle = createMockDirectoryHandle('/', {
526
+ 'existing.txt': { content: 'existing', type: 'text/plain' }
527
+ });
528
+ const accessors = (await FileSystemAccessTreeAccessors.fromDirectoryHandle(dirHandle, { mutable: true })).orThrow();
529
+ // Override resolveAbsolutePath to return an empty path to trigger the error
530
+ const originalResolveAbsolutePath = accessors.resolveAbsolutePath.bind(accessors);
531
+ accessors.resolveAbsolutePath = jest.fn((path) => {
532
+ if (path === '/badpath') {
533
+ return ''; // This will result in no parts after split
534
+ }
535
+ return originalResolveAbsolutePath(path);
536
+ });
537
+ // Create a new file with the bad path - don't throw if it fails
538
+ const saveResult = accessors.saveFileContents('/badpath', 'content');
539
+ if (saveResult.isFailure()) {
540
+ // saveFileContents itself might reject the path
541
+ expect(saveResult).toFailWith(/invalid file path/i);
542
+ }
543
+ else {
544
+ // If save succeeded, sync should fail
545
+ const syncResult = await accessors.syncToDisk();
546
+ expect(syncResult).toFailWith(/Invalid file path/i);
487
547
  }
488
- return originalResolveAbsolutePath(path);
489
- });
490
- // Create a new file with the bad path - don't throw if it fails
491
- const saveResult = accessors.saveFileContents('/badpath', 'content');
492
- if (saveResult.isFailure()) {
493
- // saveFileContents itself might reject the path
494
- expect(saveResult).toFailWith(/invalid file path/i);
495
- }
496
- else {
497
- // If save succeeded, sync should fail
548
+ });
549
+ test('handles file creation failure in _createAndWriteFile', async () => {
550
+ const dirHandle = createMockDirectoryHandle('/', {
551
+ 'existing.txt': { content: 'existing', type: 'text/plain' }
552
+ });
553
+ const accessors = (await FileSystemAccessTreeAccessors.fromDirectoryHandle(dirHandle, { mutable: true })).orThrow();
554
+ // Add a new file that will need to be created
555
+ accessors.saveFileContents('/newdir/newfile.txt', 'new content').orThrow();
556
+ // Mock getDirectoryHandle to fail
557
+ const rootDir = accessors._rootDir;
558
+ rootDir.getDirectoryHandle = jest.fn().mockRejectedValue(new Error('Permission denied'));
498
559
  const syncResult = await accessors.syncToDisk();
499
- expect(syncResult).toFailWith(/Invalid file path/i);
500
- }
501
- });
502
- test('handles file creation failure in _createAndWriteFile', async () => {
503
- const dirHandle = createMockDirectoryHandle('/', {
504
- 'existing.txt': { content: 'existing', type: 'text/plain' }
505
- });
506
- const accessors = (await FileSystemAccessTreeAccessors.fromDirectoryHandle(dirHandle, { mutable: true })).orThrow();
507
- // Add a new file that will need to be created
508
- accessors.saveFileContents('/newdir/newfile.txt', 'new content').orThrow();
509
- // Mock getDirectoryHandle to fail
510
- const rootDir = accessors._rootDir;
511
- rootDir.getDirectoryHandle = jest.fn().mockRejectedValue(new Error('Permission denied'));
512
- const syncResult = await accessors.syncToDisk();
513
- expect(syncResult).toFailWith(/Failed to create file.*Permission denied/i);
560
+ expect(syncResult).toFailWith(/Failed to create file.*Permission denied/i);
561
+ });
562
+ test('successfully deletes a root-level file from disk via syncToDisk pending deletions', async () => {
563
+ // Covers lines 329-333: the pending deletions loop in syncToDisk
564
+ const dirHandle = createMockDirectoryHandle('/', {
565
+ 'toDelete.txt': { content: 'will be deleted', type: 'text/plain' },
566
+ 'keep.txt': { content: 'stays', type: 'text/plain' }
567
+ });
568
+ const accessors = (await FileSystemAccessTreeAccessors.fromDirectoryHandle(dirHandle, { mutable: true })).orThrow();
569
+ // Delete the file from in-memory tree
570
+ accessors.deleteFile('/toDelete.txt').orThrow();
571
+ expect(accessors.isDirty()).toBe(true);
572
+ expect(accessors.getDirtyPaths()).toContain('/toDelete.txt');
573
+ // syncToDisk should process the pending deletion
574
+ const syncResult = await accessors.syncToDisk();
575
+ expect(syncResult).toSucceed();
576
+ expect(accessors.isDirty()).toBe(false);
577
+ });
578
+ test('successfully deletes a nested file from disk via syncToDisk (navigates parent dirs)', async () => {
579
+ // Covers lines 468-469: getDirectoryHandle navigation loop in _deleteFileFromDisk
580
+ const dirHandle = createMockDirectoryHandle('/', {
581
+ 'src/utils/helper.txt': { content: 'to be deleted', type: 'text/plain' },
582
+ 'src/index.txt': { content: 'stays', type: 'text/plain' }
583
+ });
584
+ const accessors = (await FileSystemAccessTreeAccessors.fromDirectoryHandle(dirHandle, { mutable: true })).orThrow();
585
+ // Delete the nested file
586
+ accessors.deleteFile('/src/utils/helper.txt').orThrow();
587
+ expect(accessors.isDirty()).toBe(true);
588
+ const syncResult = await accessors.syncToDisk();
589
+ expect(syncResult).toSucceed();
590
+ expect(accessors.isDirty()).toBe(false);
591
+ });
592
+ test('aggregates deletion errors when _deleteFileFromDisk fails during syncToDisk', async () => {
593
+ // Covers lines 330-332: the error aggregation when _deleteFileFromDisk returns failure
594
+ const dirHandle = createMockDirectoryHandle('/', {
595
+ 'toDelete.txt': { content: 'content', type: 'text/plain' }
596
+ });
597
+ const accessors = (await FileSystemAccessTreeAccessors.fromDirectoryHandle(dirHandle, { mutable: true })).orThrow();
598
+ accessors.deleteFile('/toDelete.txt').orThrow();
599
+ // Make removeEntry fail to trigger the error path in _deleteFileFromDisk
600
+ const rootDir = accessors._rootDir;
601
+ rootDir.removeEntry = jest.fn().mockRejectedValue(new Error('Cannot delete: file locked'));
602
+ const syncResult = await accessors.syncToDisk();
603
+ expect(syncResult).toFailWith(/Failed to sync 1 file/i);
604
+ expect(syncResult).toFailWith(/delete.*toDelete\.txt/i);
605
+ });
606
+ test('catch block in _deleteFileFromDisk when removeEntry throws', async () => {
607
+ // Covers lines 473-476: the catch block in _deleteFileFromDisk
608
+ const dirHandle = createMockDirectoryHandle('/', {
609
+ 'target.txt': { content: 'content', type: 'text/plain' }
610
+ });
611
+ const accessors = (await FileSystemAccessTreeAccessors.fromDirectoryHandle(dirHandle, { mutable: true })).orThrow();
612
+ accessors.deleteFile('/target.txt').orThrow();
613
+ // Directly make _rootDir.removeEntry throw a non-Error value to test the catch branch
614
+ const rootDir = accessors._rootDir;
615
+ rootDir.removeEntry = jest.fn().mockRejectedValue('non-error string');
616
+ const syncResult = await accessors.syncToDisk();
617
+ expect(syncResult).toFailWith(/Failed to delete file.*non-error string/i);
618
+ });
514
619
  });
515
620
  });
516
621
  });