@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.
- package/.rush/temp/{81e0881271ff236956b2f52e8ca99da6574c6e1e.tar.log → 662cc3506cc3ef5cddbcdc44d137af1d16679cbe.tar.log} +17 -3
- package/.rush/temp/chunked-rush-logs/ts-web-extras.build.chunks.jsonl +37 -34
- package/.rush/temp/operation/build/all.log +37 -34
- package/.rush/temp/operation/build/log-chunks.jsonl +37 -34
- package/.rush/temp/operation/build/state.json +1 -1
- package/.rush/temp/shrinkwrap-deps.json +690 -633
- package/config/typedoc.json +2 -1
- package/dist/packlets/file-tree/fileApiTreeAccessors.js +15 -0
- package/dist/packlets/file-tree/fileApiTreeAccessors.js.map +1 -1
- package/dist/packlets/file-tree/fileSystemAccessTreeAccessors.js +79 -10
- package/dist/packlets/file-tree/fileSystemAccessTreeAccessors.js.map +1 -1
- package/dist/packlets/file-tree/httpTreeAccessors.js +366 -0
- package/dist/packlets/file-tree/httpTreeAccessors.js.map +1 -0
- package/dist/packlets/file-tree/index.js +1 -0
- package/dist/packlets/file-tree/index.js.map +1 -1
- package/dist/packlets/file-tree/localStorageTreeAccessors.js +51 -0
- package/dist/packlets/file-tree/localStorageTreeAccessors.js.map +1 -1
- package/dist/test/unit/fileApiTreeAccessors.test.js +51 -0
- package/dist/test/unit/fileApiTreeAccessors.test.js.map +1 -1
- package/dist/test/unit/fileSystemAccessTreeAccessors.test.js +265 -160
- package/dist/test/unit/fileSystemAccessTreeAccessors.test.js.map +1 -1
- package/dist/test/unit/httpTreeAccessors.test.js +1364 -0
- package/dist/test/unit/httpTreeAccessors.test.js.map +1 -0
- package/dist/test/unit/localStorageTreeAccessors.test.js +218 -1
- package/dist/test/unit/localStorageTreeAccessors.test.js.map +1 -1
- package/dist/ts-web-extras.d.ts +144 -0
- package/dist/tsdoc-metadata.json +1 -1
- package/docs/CryptoUtils/README.md +60 -0
- package/docs/CryptoUtils/classes/BrowserCryptoProvider.decrypt.md +27 -0
- package/docs/CryptoUtils/classes/BrowserCryptoProvider.deriveKey.md +26 -0
- package/docs/CryptoUtils/classes/BrowserCryptoProvider.encrypt.md +25 -0
- package/docs/CryptoUtils/classes/BrowserCryptoProvider.fromBase64.md +24 -0
- package/docs/CryptoUtils/classes/BrowserCryptoProvider.generateKey.md +17 -0
- package/docs/CryptoUtils/classes/BrowserCryptoProvider.generateRandomBytes.md +24 -0
- package/docs/CryptoUtils/classes/BrowserCryptoProvider.md +151 -0
- package/docs/CryptoUtils/classes/BrowserCryptoProvider.toBase64.md +24 -0
- package/docs/CryptoUtils/classes/BrowserHashProvider.hashParts.md +26 -0
- package/docs/CryptoUtils/classes/BrowserHashProvider.hashString.md +25 -0
- package/docs/CryptoUtils/classes/BrowserHashProvider.md +81 -0
- package/docs/CryptoUtils/functions/createBrowserCryptoProvider.md +12 -0
- package/docs/FileTreeHelpers/README.md +85 -0
- package/docs/FileTreeHelpers/functions/extractFileListMetadata.md +11 -0
- package/docs/FileTreeHelpers/functions/extractFileMetadata.md +11 -0
- package/docs/FileTreeHelpers/functions/fromDirectoryUpload.md +12 -0
- package/docs/FileTreeHelpers/functions/fromFileList.md +12 -0
- package/docs/FileTreeHelpers/functions/getOriginalFile.md +11 -0
- package/docs/FileTreeHelpers/variables/defaultFileApiTreeInitParams.md +9 -0
- package/docs/README.md +524 -0
- package/docs/classes/BrowserCryptoProvider.decrypt.md +27 -0
- package/docs/classes/BrowserCryptoProvider.deriveKey.md +26 -0
- package/docs/classes/BrowserCryptoProvider.encrypt.md +25 -0
- package/docs/classes/BrowserCryptoProvider.fromBase64.md +24 -0
- package/docs/classes/BrowserCryptoProvider.generateKey.md +17 -0
- package/docs/classes/BrowserCryptoProvider.generateRandomBytes.md +24 -0
- package/docs/classes/BrowserCryptoProvider.md +151 -0
- package/docs/classes/BrowserCryptoProvider.toBase64.md +24 -0
- package/docs/classes/BrowserHashProvider.hashParts.md +26 -0
- package/docs/classes/BrowserHashProvider.hashString.md +25 -0
- package/docs/classes/BrowserHashProvider.md +81 -0
- package/docs/classes/DirectoryHandleStore.getAll.md +17 -0
- package/docs/classes/DirectoryHandleStore.getAllLabels.md +17 -0
- package/docs/classes/DirectoryHandleStore.load.md +24 -0
- package/docs/classes/DirectoryHandleStore.md +120 -0
- package/docs/classes/DirectoryHandleStore.remove.md +24 -0
- package/docs/classes/DirectoryHandleStore.save.md +25 -0
- package/docs/classes/FileApiTreeAccessors.create.md +25 -0
- package/docs/classes/FileApiTreeAccessors.createFromHttp.md +24 -0
- package/docs/classes/FileApiTreeAccessors.createFromLocalStorage.md +25 -0
- package/docs/classes/FileApiTreeAccessors.createPersistent.md +26 -0
- package/docs/classes/FileApiTreeAccessors.createPersistentFromFile.md +27 -0
- package/docs/classes/FileApiTreeAccessors.extractFileMetadata.md +24 -0
- package/docs/classes/FileApiTreeAccessors.fromDirectoryUpload.md +25 -0
- package/docs/classes/FileApiTreeAccessors.fromFileList.md +25 -0
- package/docs/classes/FileApiTreeAccessors.getOriginalFile.md +27 -0
- package/docs/classes/FileApiTreeAccessors.md +172 -0
- package/docs/classes/FileSystemAccessTreeAccessors.deleteFile.md +22 -0
- package/docs/classes/FileSystemAccessTreeAccessors.fileIsMutable.md +22 -0
- package/docs/classes/FileSystemAccessTreeAccessors.fromDirectoryHandle.md +25 -0
- package/docs/classes/FileSystemAccessTreeAccessors.fromFileHandle.md +29 -0
- package/docs/classes/FileSystemAccessTreeAccessors.getDirtyPaths.md +15 -0
- package/docs/classes/FileSystemAccessTreeAccessors.isDirty.md +15 -0
- package/docs/classes/FileSystemAccessTreeAccessors.md +275 -0
- package/docs/classes/FileSystemAccessTreeAccessors.saveFileContents.md +23 -0
- package/docs/classes/FileSystemAccessTreeAccessors.syncToDisk.md +15 -0
- package/docs/classes/HttpTreeAccessors.deleteFile.md +22 -0
- package/docs/classes/HttpTreeAccessors.fileIsMutable.md +24 -0
- package/docs/classes/HttpTreeAccessors.fromHttp.md +24 -0
- package/docs/classes/HttpTreeAccessors.getDirtyPaths.md +17 -0
- package/docs/classes/HttpTreeAccessors.isDirty.md +17 -0
- package/docs/classes/HttpTreeAccessors.md +261 -0
- package/docs/classes/HttpTreeAccessors.saveFileContents.md +25 -0
- package/docs/classes/HttpTreeAccessors.syncToDisk.md +22 -0
- package/docs/classes/LocalStorageTreeAccessors.deleteFile.md +24 -0
- package/docs/classes/LocalStorageTreeAccessors.fileIsMutable.md +24 -0
- package/docs/classes/LocalStorageTreeAccessors.fromStorage.md +25 -0
- package/docs/classes/LocalStorageTreeAccessors.getDirtyPaths.md +17 -0
- package/docs/classes/LocalStorageTreeAccessors.isDirty.md +17 -0
- package/docs/classes/LocalStorageTreeAccessors.md +270 -0
- package/docs/classes/LocalStorageTreeAccessors.saveFileContents.md +25 -0
- package/docs/classes/LocalStorageTreeAccessors.syncToDisk.md +17 -0
- package/docs/functions/createBrowserCryptoProvider.md +12 -0
- package/docs/functions/exportAsJson.md +12 -0
- package/docs/functions/exportUsingFileSystemAPI.md +11 -0
- package/docs/functions/extractDirectoryPath.md +13 -0
- package/docs/functions/extractFileListMetadata.md +11 -0
- package/docs/functions/extractFileMetadata.md +11 -0
- package/docs/functions/fromDirectoryUpload.md +12 -0
- package/docs/functions/fromFileList.md +12 -0
- package/docs/functions/getOriginalFile.md +11 -0
- package/docs/functions/isDirectoryHandle.md +11 -0
- package/docs/functions/isFileHandle.md +11 -0
- package/docs/functions/isFilePath.md +11 -0
- package/docs/functions/parseContextFilter.md +12 -0
- package/docs/functions/parseQualifierDefaults.md +12 -0
- package/docs/functions/parseResourceTypes.md +12 -0
- package/docs/functions/parseUrlParameters.md +11 -0
- package/docs/functions/safeShowDirectoryPicker.md +11 -0
- package/docs/functions/safeShowOpenFilePicker.md +11 -0
- package/docs/functions/safeShowSaveFilePicker.md +11 -0
- package/docs/functions/supportsFileSystemAccess.md +11 -0
- package/docs/interfaces/FilePickerAcceptType.accept.md +9 -0
- package/docs/interfaces/FilePickerAcceptType.description.md +9 -0
- package/docs/interfaces/FilePickerAcceptType.md +61 -0
- package/docs/interfaces/FileSystemCreateWritableOptions.keepExistingData.md +9 -0
- package/docs/interfaces/FileSystemCreateWritableOptions.md +44 -0
- package/docs/interfaces/FileSystemDirectoryHandle._asyncIterator_.md +13 -0
- package/docs/interfaces/FileSystemDirectoryHandle.entries.md +13 -0
- package/docs/interfaces/FileSystemDirectoryHandle.getDirectoryHandle.md +21 -0
- package/docs/interfaces/FileSystemDirectoryHandle.getFileHandle.md +21 -0
- package/docs/interfaces/FileSystemDirectoryHandle.keys.md +13 -0
- package/docs/interfaces/FileSystemDirectoryHandle.kind.md +9 -0
- package/docs/interfaces/FileSystemDirectoryHandle.md +224 -0
- package/docs/interfaces/FileSystemDirectoryHandle.removeEntry.md +21 -0
- package/docs/interfaces/FileSystemDirectoryHandle.resolve.md +20 -0
- package/docs/interfaces/FileSystemDirectoryHandle.values.md +13 -0
- package/docs/interfaces/FileSystemFileHandle.createWritable.md +20 -0
- package/docs/interfaces/FileSystemFileHandle.getFile.md +13 -0
- package/docs/interfaces/FileSystemFileHandle.kind.md +9 -0
- package/docs/interfaces/FileSystemFileHandle.md +146 -0
- package/docs/interfaces/FileSystemGetDirectoryOptions.create.md +9 -0
- package/docs/interfaces/FileSystemGetDirectoryOptions.md +44 -0
- package/docs/interfaces/FileSystemGetFileOptions.create.md +9 -0
- package/docs/interfaces/FileSystemGetFileOptions.md +44 -0
- package/docs/interfaces/FileSystemHandle.isSameEntry.md +20 -0
- package/docs/interfaces/FileSystemHandle.kind.md +9 -0
- package/docs/interfaces/FileSystemHandle.md +118 -0
- package/docs/interfaces/FileSystemHandle.name.md +9 -0
- package/docs/interfaces/FileSystemHandle.queryPermission.md +20 -0
- package/docs/interfaces/FileSystemHandle.requestPermission.md +20 -0
- package/docs/interfaces/FileSystemHandlePermissionDescriptor.md +44 -0
- package/docs/interfaces/FileSystemHandlePermissionDescriptor.mode.md +9 -0
- package/docs/interfaces/FileSystemRemoveOptions.md +44 -0
- package/docs/interfaces/FileSystemRemoveOptions.recursive.md +9 -0
- package/docs/interfaces/FileSystemWritableFileStream.md +142 -0
- package/docs/interfaces/FileSystemWritableFileStream.seek.md +20 -0
- package/docs/interfaces/FileSystemWritableFileStream.truncate.md +20 -0
- package/docs/interfaces/FileSystemWritableFileStream.write.md +20 -0
- package/docs/interfaces/IDirectoryHandleTreeInitializer.dirHandles.md +9 -0
- package/docs/interfaces/IDirectoryHandleTreeInitializer.md +78 -0
- package/docs/interfaces/IDirectoryHandleTreeInitializer.nonRecursive.md +9 -0
- package/docs/interfaces/IDirectoryHandleTreeInitializer.prefix.md +9 -0
- package/docs/interfaces/IFileHandleTreeInitializer.fileHandles.md +9 -0
- package/docs/interfaces/IFileHandleTreeInitializer.md +61 -0
- package/docs/interfaces/IFileHandleTreeInitializer.prefix.md +9 -0
- package/docs/interfaces/IFileListTreeInitializer.fileList.md +9 -0
- package/docs/interfaces/IFileListTreeInitializer.md +44 -0
- package/docs/interfaces/IFileMetadata.lastModified.md +9 -0
- package/docs/interfaces/IFileMetadata.md +112 -0
- package/docs/interfaces/IFileMetadata.name.md +9 -0
- package/docs/interfaces/IFileMetadata.path.md +9 -0
- package/docs/interfaces/IFileMetadata.size.md +9 -0
- package/docs/interfaces/IFileMetadata.type.md +9 -0
- package/docs/interfaces/IFileSystemAccessTreeParams.autoSync.md +12 -0
- package/docs/interfaces/IFileSystemAccessTreeParams.filePath.md +13 -0
- package/docs/interfaces/IFileSystemAccessTreeParams.logger.md +11 -0
- package/docs/interfaces/IFileSystemAccessTreeParams.md +148 -0
- package/docs/interfaces/IFileSystemAccessTreeParams.requireWritePermission.md +13 -0
- package/docs/interfaces/IFsAccessApis.md +62 -0
- package/docs/interfaces/IFsAccessApis.showDirectoryPicker.md +20 -0
- package/docs/interfaces/IFsAccessApis.showOpenFilePicker.md +20 -0
- package/docs/interfaces/IFsAccessApis.showSaveFilePicker.md +20 -0
- package/docs/interfaces/IHttpTreeParams.autoSync.md +9 -0
- package/docs/interfaces/IHttpTreeParams.baseUrl.md +9 -0
- package/docs/interfaces/IHttpTreeParams.fetchImpl.md +9 -0
- package/docs/interfaces/IHttpTreeParams.logger.md +9 -0
- package/docs/interfaces/IHttpTreeParams.md +182 -0
- package/docs/interfaces/IHttpTreeParams.namespace.md +9 -0
- package/docs/interfaces/IHttpTreeParams.userId.md +9 -0
- package/docs/interfaces/ILocalStorageTreeParams.autoSync.md +12 -0
- package/docs/interfaces/ILocalStorageTreeParams.md +131 -0
- package/docs/interfaces/ILocalStorageTreeParams.pathToKeyMap.md +13 -0
- package/docs/interfaces/ILocalStorageTreeParams.storage.md +12 -0
- package/docs/interfaces/IUrlConfigOptions.config.md +11 -0
- package/docs/interfaces/IUrlConfigOptions.configStartDir.md +11 -0
- package/docs/interfaces/IUrlConfigOptions.contextFilter.md +11 -0
- package/docs/interfaces/IUrlConfigOptions.input.md +11 -0
- package/docs/interfaces/IUrlConfigOptions.inputStartDir.md +11 -0
- package/docs/interfaces/IUrlConfigOptions.interactive.md +11 -0
- package/docs/interfaces/IUrlConfigOptions.loadZip.md +11 -0
- package/docs/interfaces/IUrlConfigOptions.maxDistance.md +11 -0
- package/docs/interfaces/IUrlConfigOptions.md +248 -0
- package/docs/interfaces/IUrlConfigOptions.qualifierDefaults.md +11 -0
- package/docs/interfaces/IUrlConfigOptions.reduceQualifiers.md +11 -0
- package/docs/interfaces/IUrlConfigOptions.resourceTypes.md +11 -0
- package/docs/interfaces/IUrlConfigOptions.zipFile.md +11 -0
- package/docs/interfaces/IUrlConfigOptions.zipPath.md +11 -0
- package/docs/interfaces/ShowDirectoryPickerOptions.id.md +9 -0
- package/docs/interfaces/ShowDirectoryPickerOptions.md +78 -0
- package/docs/interfaces/ShowDirectoryPickerOptions.mode.md +9 -0
- package/docs/interfaces/ShowDirectoryPickerOptions.startIn.md +9 -0
- package/docs/interfaces/ShowOpenFilePickerOptions.excludeAcceptAllOption.md +9 -0
- package/docs/interfaces/ShowOpenFilePickerOptions.id.md +9 -0
- package/docs/interfaces/ShowOpenFilePickerOptions.md +112 -0
- package/docs/interfaces/ShowOpenFilePickerOptions.multiple.md +9 -0
- package/docs/interfaces/ShowOpenFilePickerOptions.startIn.md +9 -0
- package/docs/interfaces/ShowOpenFilePickerOptions.types.md +9 -0
- package/docs/interfaces/ShowSaveFilePickerOptions.excludeAcceptAllOption.md +9 -0
- package/docs/interfaces/ShowSaveFilePickerOptions.id.md +9 -0
- package/docs/interfaces/ShowSaveFilePickerOptions.md +112 -0
- package/docs/interfaces/ShowSaveFilePickerOptions.startIn.md +9 -0
- package/docs/interfaces/ShowSaveFilePickerOptions.suggestedName.md +9 -0
- package/docs/interfaces/ShowSaveFilePickerOptions.types.md +9 -0
- package/docs/type-aliases/TreeInitializer.md +11 -0
- package/docs/type-aliases/WellKnownDirectory.md +11 -0
- package/docs/type-aliases/WindowWithFsAccess.md +11 -0
- package/docs/variables/DEFAULT_DIRECTORY_HANDLE_DB.md +9 -0
- package/docs/variables/DEFAULT_DIRECTORY_HANDLE_STORE.md +9 -0
- package/docs/variables/defaultFileApiTreeInitParams.md +9 -0
- package/etc/ts-web-extras.api.md +33 -0
- package/lib/packlets/file-tree/fileApiTreeAccessors.d.ts +9 -0
- package/lib/packlets/file-tree/fileApiTreeAccessors.d.ts.map +1 -1
- package/lib/packlets/file-tree/fileApiTreeAccessors.js +15 -0
- package/lib/packlets/file-tree/fileApiTreeAccessors.js.map +1 -1
- package/lib/packlets/file-tree/fileSystemAccessTreeAccessors.d.ts +17 -1
- package/lib/packlets/file-tree/fileSystemAccessTreeAccessors.d.ts.map +1 -1
- package/lib/packlets/file-tree/fileSystemAccessTreeAccessors.js +78 -9
- package/lib/packlets/file-tree/fileSystemAccessTreeAccessors.js.map +1 -1
- package/lib/packlets/file-tree/httpTreeAccessors.d.ts +108 -0
- package/lib/packlets/file-tree/httpTreeAccessors.d.ts.map +1 -0
- package/lib/packlets/file-tree/httpTreeAccessors.js +370 -0
- package/lib/packlets/file-tree/httpTreeAccessors.js.map +1 -0
- package/lib/packlets/file-tree/index.d.ts +1 -0
- package/lib/packlets/file-tree/index.d.ts.map +1 -1
- package/lib/packlets/file-tree/index.js +1 -0
- package/lib/packlets/file-tree/index.js.map +1 -1
- package/lib/packlets/file-tree/localStorageTreeAccessors.d.ts +12 -0
- package/lib/packlets/file-tree/localStorageTreeAccessors.d.ts.map +1 -1
- package/lib/packlets/file-tree/localStorageTreeAccessors.js +51 -0
- package/lib/packlets/file-tree/localStorageTreeAccessors.js.map +1 -1
- package/lib/test/unit/fileApiTreeAccessors.test.js +51 -0
- package/lib/test/unit/fileApiTreeAccessors.test.js.map +1 -1
- package/lib/test/unit/fileSystemAccessTreeAccessors.test.js +265 -160
- package/lib/test/unit/fileSystemAccessTreeAccessors.test.js.map +1 -1
- package/lib/test/unit/httpTreeAccessors.test.d.ts +2 -0
- package/lib/test/unit/httpTreeAccessors.test.d.ts.map +1 -0
- package/lib/test/unit/httpTreeAccessors.test.js +1366 -0
- package/lib/test/unit/httpTreeAccessors.test.js.map +1 -0
- package/lib/test/unit/localStorageTreeAccessors.test.js +218 -1
- package/lib/test/unit/localStorageTreeAccessors.test.js.map +1 -1
- package/package.json +13 -12
- package/rush-logs/ts-web-extras.build.cache.log +1 -1
- package/rush-logs/ts-web-extras.build.log +37 -34
- package/src/packlets/file-tree/fileApiTreeAccessors.ts +18 -0
- package/src/packlets/file-tree/fileSystemAccessTreeAccessors.ts +100 -8
- package/src/packlets/file-tree/httpTreeAccessors.ts +478 -0
- package/src/packlets/file-tree/index.ts +1 -0
- package/src/packlets/file-tree/localStorageTreeAccessors.ts +53 -0
- package/src/test/unit/fileApiTreeAccessors.test.ts +69 -0
- package/src/test/unit/fileSystemAccessTreeAccessors.test.ts +341 -188
- package/src/test/unit/httpTreeAccessors.test.ts +1750 -0
- package/src/test/unit/localStorageTreeAccessors.test.ts +269 -1
- package/temp/build/typescript/ts_8nwakTlr.json +1 -1
- package/temp/coverage/crypto-utils/browserCryptoProvider.ts.html +1 -1
- package/temp/coverage/crypto-utils/browserHashProvider.ts.html +1 -1
- package/temp/coverage/crypto-utils/index.html +1 -1
- package/temp/coverage/file-tree/directoryHandleStore.ts.html +1 -1
- package/temp/coverage/file-tree/fileApiTreeAccessors.ts.html +60 -6
- package/temp/coverage/file-tree/fileSystemAccessTreeAccessors.ts.html +410 -134
- package/temp/coverage/file-tree/httpTreeAccessors.ts.html +1519 -0
- package/temp/coverage/file-tree/index.html +35 -20
- package/temp/coverage/file-tree/localStorageTreeAccessors.ts.html +318 -159
- package/temp/coverage/helpers/fileTreeHelpers.ts.html +1 -1
- package/temp/coverage/helpers/index.html +1 -1
- package/temp/coverage/index.html +11 -11
- package/temp/coverage/lcov-report/crypto-utils/browserCryptoProvider.ts.html +1 -1
- package/temp/coverage/lcov-report/crypto-utils/browserHashProvider.ts.html +1 -1
- package/temp/coverage/lcov-report/crypto-utils/index.html +1 -1
- package/temp/coverage/lcov-report/file-tree/directoryHandleStore.ts.html +1 -1
- package/temp/coverage/lcov-report/file-tree/fileApiTreeAccessors.ts.html +60 -6
- package/temp/coverage/lcov-report/file-tree/fileSystemAccessTreeAccessors.ts.html +410 -134
- package/temp/coverage/lcov-report/file-tree/httpTreeAccessors.ts.html +1519 -0
- package/temp/coverage/lcov-report/file-tree/index.html +35 -20
- package/temp/coverage/lcov-report/file-tree/localStorageTreeAccessors.ts.html +318 -159
- package/temp/coverage/lcov-report/helpers/fileTreeHelpers.ts.html +1 -1
- package/temp/coverage/lcov-report/helpers/index.html +1 -1
- package/temp/coverage/lcov-report/index.html +11 -11
- package/temp/coverage/lcov-report/url-utils/index.html +1 -1
- package/temp/coverage/lcov-report/url-utils/urlParams.ts.html +1 -1
- package/temp/coverage/lcov.info +2052 -1195
- package/temp/coverage/url-utils/index.html +1 -1
- package/temp/coverage/url-utils/urlParams.ts.html +1 -1
- package/temp/test/jest/haste-map-7492f1b44480e0cdd1f220078fb3afd8-c8dd6c3430605adeb2f1cadf4f75e791-8c9336785555d572065b28c111982ba4 +0 -0
- package/temp/test/jest/perf-cache-7492f1b44480e0cdd1f220078fb3afd8-da39a3ee5e6b4b0d3255bfef95601890 +1 -1
- package/temp/ts-web-extras.api.json +1314 -355
- package/temp/ts-web-extras.api.md +33 -0
- package/docs/index.md +0 -34
- package/docs/ts-web-extras.cryptoutils.browsercryptoprovider._constructor_.md +0 -50
- package/docs/ts-web-extras.cryptoutils.browsercryptoprovider.decrypt.md +0 -104
- package/docs/ts-web-extras.cryptoutils.browsercryptoprovider.derivekey.md +0 -88
- package/docs/ts-web-extras.cryptoutils.browsercryptoprovider.encrypt.md +0 -72
- package/docs/ts-web-extras.cryptoutils.browsercryptoprovider.frombase64.md +0 -56
- package/docs/ts-web-extras.cryptoutils.browsercryptoprovider.generatekey.md +0 -19
- package/docs/ts-web-extras.cryptoutils.browsercryptoprovider.generaterandombytes.md +0 -56
- package/docs/ts-web-extras.cryptoutils.browsercryptoprovider.md +0 -169
- package/docs/ts-web-extras.cryptoutils.browsercryptoprovider.tobase64.md +0 -56
- package/docs/ts-web-extras.cryptoutils.browserhashprovider.hashparts.md +0 -88
- package/docs/ts-web-extras.cryptoutils.browserhashprovider.hashstring.md +0 -72
- package/docs/ts-web-extras.cryptoutils.browserhashprovider.md +0 -66
- package/docs/ts-web-extras.cryptoutils.createbrowsercryptoprovider.md +0 -19
- package/docs/ts-web-extras.cryptoutils.md +0 -71
- package/docs/ts-web-extras.exportasjson.md +0 -70
- package/docs/ts-web-extras.exportusingfilesystemapi.md +0 -104
- package/docs/ts-web-extras.extractdirectorypath.md +0 -52
- package/docs/ts-web-extras.fileapitreeaccessors.create.md +0 -72
- package/docs/ts-web-extras.fileapitreeaccessors.createfromlocalstorage.md +0 -74
- package/docs/ts-web-extras.fileapitreeaccessors.createpersistent.md +0 -76
- package/docs/ts-web-extras.fileapitreeaccessors.extractfilemetadata.md +0 -54
- package/docs/ts-web-extras.fileapitreeaccessors.fromdirectoryupload.md +0 -72
- package/docs/ts-web-extras.fileapitreeaccessors.fromfilelist.md +0 -72
- package/docs/ts-web-extras.fileapitreeaccessors.getoriginalfile.md +0 -72
- package/docs/ts-web-extras.fileapitreeaccessors.md +0 -146
- package/docs/ts-web-extras.filepickeraccepttype.accept.md +0 -11
- package/docs/ts-web-extras.filepickeraccepttype.description.md +0 -11
- package/docs/ts-web-extras.filepickeraccepttype.md +0 -75
- package/docs/ts-web-extras.filesystemaccesstreeaccessors._constructor_.md +0 -114
- package/docs/ts-web-extras.filesystemaccesstreeaccessors.fileismutable.md +0 -52
- package/docs/ts-web-extras.filesystemaccesstreeaccessors.fromdirectoryhandle.md +0 -72
- package/docs/ts-web-extras.filesystemaccesstreeaccessors.getdirtypaths.md +0 -17
- package/docs/ts-web-extras.filesystemaccesstreeaccessors.isdirty.md +0 -17
- package/docs/ts-web-extras.filesystemaccesstreeaccessors.md +0 -159
- package/docs/ts-web-extras.filesystemaccesstreeaccessors.savefilecontents.md +0 -66
- package/docs/ts-web-extras.filesystemaccesstreeaccessors.synctodisk.md +0 -17
- package/docs/ts-web-extras.filesystemcreatewritableoptions_2.keepexistingdata.md +0 -11
- package/docs/ts-web-extras.filesystemcreatewritableoptions_2.md +0 -58
- package/docs/ts-web-extras.filesystemdirectoryhandle_2._symbol.asynciterator_.md +0 -15
- package/docs/ts-web-extras.filesystemdirectoryhandle_2.entries.md +0 -15
- package/docs/ts-web-extras.filesystemdirectoryhandle_2.getdirectoryhandle.md +0 -66
- package/docs/ts-web-extras.filesystemdirectoryhandle_2.getfilehandle.md +0 -66
- package/docs/ts-web-extras.filesystemdirectoryhandle_2.keys.md +0 -15
- package/docs/ts-web-extras.filesystemdirectoryhandle_2.kind.md +0 -11
- package/docs/ts-web-extras.filesystemdirectoryhandle_2.md +0 -146
- package/docs/ts-web-extras.filesystemdirectoryhandle_2.removeentry.md +0 -66
- package/docs/ts-web-extras.filesystemdirectoryhandle_2.resolve.md +0 -50
- package/docs/ts-web-extras.filesystemdirectoryhandle_2.values.md +0 -15
- package/docs/ts-web-extras.filesystemfilehandle_2.createwritable.md +0 -52
- package/docs/ts-web-extras.filesystemfilehandle_2.getfile.md +0 -15
- package/docs/ts-web-extras.filesystemfilehandle_2.kind.md +0 -11
- package/docs/ts-web-extras.filesystemfilehandle_2.md +0 -92
- package/docs/ts-web-extras.filesystemgetdirectoryoptions_2.create.md +0 -11
- package/docs/ts-web-extras.filesystemgetdirectoryoptions_2.md +0 -58
- package/docs/ts-web-extras.filesystemgetfileoptions_2.create.md +0 -11
- package/docs/ts-web-extras.filesystemgetfileoptions_2.md +0 -58
- package/docs/ts-web-extras.filesystemhandle_2.issameentry.md +0 -50
- package/docs/ts-web-extras.filesystemhandle_2.kind.md +0 -11
- package/docs/ts-web-extras.filesystemhandle_2.md +0 -119
- package/docs/ts-web-extras.filesystemhandle_2.name.md +0 -11
- package/docs/ts-web-extras.filesystemhandle_2.querypermission.md +0 -52
- package/docs/ts-web-extras.filesystemhandle_2.requestpermission.md +0 -52
- package/docs/ts-web-extras.filesystemhandlepermissiondescriptor.md +0 -58
- package/docs/ts-web-extras.filesystemhandlepermissiondescriptor.mode.md +0 -11
- package/docs/ts-web-extras.filesystemremoveoptions_2.md +0 -58
- package/docs/ts-web-extras.filesystemremoveoptions_2.recursive.md +0 -11
- package/docs/ts-web-extras.filesystemwritablefilestream_2.md +0 -57
- package/docs/ts-web-extras.filesystemwritablefilestream_2.seek.md +0 -50
- package/docs/ts-web-extras.filesystemwritablefilestream_2.truncate.md +0 -50
- package/docs/ts-web-extras.filesystemwritablefilestream_2.write.md +0 -50
- package/docs/ts-web-extras.filetreehelpers.defaultfileapitreeinitparams.md +0 -13
- package/docs/ts-web-extras.filetreehelpers.extractfilelistmetadata.md +0 -56
- package/docs/ts-web-extras.filetreehelpers.extractfilemetadata.md +0 -56
- package/docs/ts-web-extras.filetreehelpers.fromdirectoryupload.md +0 -76
- package/docs/ts-web-extras.filetreehelpers.fromfilelist.md +0 -76
- package/docs/ts-web-extras.filetreehelpers.getoriginalfile.md +0 -72
- package/docs/ts-web-extras.filetreehelpers.md +0 -102
- package/docs/ts-web-extras.idirectoryhandletreeinitializer.dirhandles.md +0 -11
- package/docs/ts-web-extras.idirectoryhandletreeinitializer.md +0 -100
- package/docs/ts-web-extras.idirectoryhandletreeinitializer.nonrecursive.md +0 -11
- package/docs/ts-web-extras.idirectoryhandletreeinitializer.prefix.md +0 -11
- package/docs/ts-web-extras.ifilehandletreeinitializer.filehandles.md +0 -11
- package/docs/ts-web-extras.ifilehandletreeinitializer.md +0 -79
- package/docs/ts-web-extras.ifilehandletreeinitializer.prefix.md +0 -11
- package/docs/ts-web-extras.ifilelisttreeinitializer.filelist.md +0 -11
- package/docs/ts-web-extras.ifilelisttreeinitializer.md +0 -58
- package/docs/ts-web-extras.ifilemetadata.lastmodified.md +0 -11
- package/docs/ts-web-extras.ifilemetadata.md +0 -124
- package/docs/ts-web-extras.ifilemetadata.name.md +0 -11
- package/docs/ts-web-extras.ifilemetadata.path.md +0 -11
- package/docs/ts-web-extras.ifilemetadata.size.md +0 -11
- package/docs/ts-web-extras.ifilemetadata.type.md +0 -11
- package/docs/ts-web-extras.ifilesystemaccesstreeparams.autosync.md +0 -13
- package/docs/ts-web-extras.ifilesystemaccesstreeparams.md +0 -78
- package/docs/ts-web-extras.ifilesystemaccesstreeparams.requirewritepermission.md +0 -13
- package/docs/ts-web-extras.ifsaccessapis.md +0 -56
- package/docs/ts-web-extras.ifsaccessapis.showdirectorypicker.md +0 -52
- package/docs/ts-web-extras.ifsaccessapis.showopenfilepicker.md +0 -52
- package/docs/ts-web-extras.ifsaccessapis.showsavefilepicker.md +0 -52
- package/docs/ts-web-extras.ilocalstoragetreeparams.autosync.md +0 -13
- package/docs/ts-web-extras.ilocalstoragetreeparams.md +0 -97
- package/docs/ts-web-extras.ilocalstoragetreeparams.pathtokeymap.md +0 -13
- package/docs/ts-web-extras.ilocalstoragetreeparams.storage.md +0 -13
- package/docs/ts-web-extras.isdirectoryhandle.md +0 -56
- package/docs/ts-web-extras.isfilehandle.md +0 -56
- package/docs/ts-web-extras.isfilepath.md +0 -52
- package/docs/ts-web-extras.iurlconfigoptions.config.md +0 -13
- package/docs/ts-web-extras.iurlconfigoptions.configstartdir.md +0 -13
- package/docs/ts-web-extras.iurlconfigoptions.contextfilter.md +0 -13
- package/docs/ts-web-extras.iurlconfigoptions.input.md +0 -13
- package/docs/ts-web-extras.iurlconfigoptions.inputstartdir.md +0 -13
- package/docs/ts-web-extras.iurlconfigoptions.interactive.md +0 -13
- package/docs/ts-web-extras.iurlconfigoptions.loadzip.md +0 -13
- package/docs/ts-web-extras.iurlconfigoptions.maxdistance.md +0 -13
- package/docs/ts-web-extras.iurlconfigoptions.md +0 -286
- package/docs/ts-web-extras.iurlconfigoptions.qualifierdefaults.md +0 -13
- package/docs/ts-web-extras.iurlconfigoptions.reducequalifiers.md +0 -13
- package/docs/ts-web-extras.iurlconfigoptions.resourcetypes.md +0 -13
- package/docs/ts-web-extras.iurlconfigoptions.zipfile.md +0 -13
- package/docs/ts-web-extras.iurlconfigoptions.zippath.md +0 -13
- package/docs/ts-web-extras.localstoragetreeaccessors.fileismutable.md +0 -56
- package/docs/ts-web-extras.localstoragetreeaccessors.fromstorage.md +0 -56
- package/docs/ts-web-extras.localstoragetreeaccessors.getdirtypaths.md +0 -19
- package/docs/ts-web-extras.localstoragetreeaccessors.isdirty.md +0 -19
- package/docs/ts-web-extras.localstoragetreeaccessors.md +0 -131
- package/docs/ts-web-extras.localstoragetreeaccessors.savefilecontents.md +0 -72
- package/docs/ts-web-extras.localstoragetreeaccessors.synctodisk.md +0 -19
- package/docs/ts-web-extras.md +0 -558
- package/docs/ts-web-extras.parsecontextfilter.md +0 -52
- package/docs/ts-web-extras.parsequalifierdefaults.md +0 -52
- package/docs/ts-web-extras.parseresourcetypes.md +0 -52
- package/docs/ts-web-extras.parseurlparameters.md +0 -17
- package/docs/ts-web-extras.safeshowdirectorypicker.md +0 -72
- package/docs/ts-web-extras.safeshowopenfilepicker.md +0 -72
- package/docs/ts-web-extras.safeshowsavefilepicker.md +0 -72
- package/docs/ts-web-extras.showdirectorypickeroptions.id.md +0 -11
- package/docs/ts-web-extras.showdirectorypickeroptions.md +0 -96
- package/docs/ts-web-extras.showdirectorypickeroptions.mode.md +0 -11
- package/docs/ts-web-extras.showdirectorypickeroptions.startin.md +0 -11
- package/docs/ts-web-extras.showopenfilepickeroptions.excludeacceptalloption.md +0 -11
- package/docs/ts-web-extras.showopenfilepickeroptions.id.md +0 -11
- package/docs/ts-web-extras.showopenfilepickeroptions.md +0 -134
- package/docs/ts-web-extras.showopenfilepickeroptions.multiple.md +0 -11
- package/docs/ts-web-extras.showopenfilepickeroptions.startin.md +0 -11
- package/docs/ts-web-extras.showopenfilepickeroptions.types.md +0 -11
- package/docs/ts-web-extras.showsavefilepickeroptions.excludeacceptalloption.md +0 -11
- package/docs/ts-web-extras.showsavefilepickeroptions.id.md +0 -11
- package/docs/ts-web-extras.showsavefilepickeroptions.md +0 -134
- package/docs/ts-web-extras.showsavefilepickeroptions.startin.md +0 -11
- package/docs/ts-web-extras.showsavefilepickeroptions.suggestedname.md +0 -11
- package/docs/ts-web-extras.showsavefilepickeroptions.types.md +0 -11
- package/docs/ts-web-extras.supportsfilesystemaccess.md +0 -56
- package/docs/ts-web-extras.treeinitializer.md +0 -15
- package/docs/ts-web-extras.wellknowndirectory.md +0 -13
- package/docs/ts-web-extras.windowwithfsaccess.md +0 -15
- /package/temp/test/jest/jest-transform-cache-7492f1b44480e0cdd1f220078fb3afd8-79ef2876fae7ca75eedb2aa53dc48338/{8d/package_8dcbedef69e4299f0f51fcda8f4f1c8e → 7c/package_7c16afc8299e635d80273763175c7a50} +0 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"localStorageTreeAccessors.test.js","sourceRoot":"","sources":["../../../src/test/unit/localStorageTreeAccessors.test.ts"],"names":[],"mappings":"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","sourcesContent":["/*\n * Copyright (c) 2026 Erik Fortune\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\nimport '@fgv/ts-utils-jest';\nimport { FileTree } from '@fgv/ts-json-base';\nimport { LocalStorageTreeAccessors, FileApiTreeAccessors } from '../../packlets/file-tree';\n\n/**\n * Mock Storage implementation for testing\n */\nclass MockStorage implements Storage {\n private _data: Map<string, string> = new Map();\n\n get length(): number {\n return this._data.size;\n }\n\n clear(): void {\n this._data.clear();\n }\n\n getItem(key: string): string | null {\n return this._data.get(key) ?? null;\n }\n\n key(index: number): string | null {\n const keys = Array.from(this._data.keys());\n return keys[index] ?? null;\n }\n\n removeItem(key: string): void {\n this._data.delete(key);\n }\n\n setItem(key: string, value: string): void {\n this._data.set(key, value);\n }\n}\n\ndescribe('LocalStorageTreeAccessors', () => {\n let mockStorage: MockStorage;\n\n beforeEach(() => {\n mockStorage = new MockStorage();\n });\n\n describe('fromStorage', () => {\n test('creates accessors from empty storage', () => {\n const result = LocalStorageTreeAccessors.fromStorage({\n pathToKeyMap: {\n '/data/ingredients': 'test:ingredients:v1'\n },\n storage: mockStorage\n });\n\n expect(result).toSucceedAndSatisfy((accessors) => {\n expect(accessors).toBeInstanceOf(LocalStorageTreeAccessors);\n expect(accessors.isDirty()).toBe(false);\n });\n });\n\n test('loads collections from storage', () => {\n mockStorage.setItem(\n 'test:ingredients:v1',\n JSON.stringify({\n collection1: { items: { item1: {} } },\n collection2: { items: { item2: {} } }\n })\n );\n\n const result = LocalStorageTreeAccessors.fromStorage({\n pathToKeyMap: {\n '/data/ingredients': 'test:ingredients:v1'\n },\n storage: mockStorage\n });\n\n expect(result).toSucceedAndSatisfy((accessors) => {\n expect(accessors.getFileContents('/data/ingredients/collection1.json')).toSucceed();\n expect(accessors.getFileContents('/data/ingredients/collection2.json')).toSucceed();\n });\n });\n\n test('loads from multiple storage keys', () => {\n mockStorage.setItem('test:ingredients:v1', JSON.stringify({ ing1: { items: {} } }));\n mockStorage.setItem('test:fillings:v1', JSON.stringify({ fill1: { items: {} } }));\n\n const result = LocalStorageTreeAccessors.fromStorage({\n pathToKeyMap: {\n '/data/ingredients': 'test:ingredients:v1',\n '/data/fillings': 'test:fillings:v1'\n },\n storage: mockStorage\n });\n\n expect(result).toSucceedAndSatisfy((accessors) => {\n expect(accessors.getFileContents('/data/ingredients/ing1.json')).toSucceed();\n expect(accessors.getFileContents('/data/fillings/fill1.json')).toSucceed();\n });\n });\n\n test('skips corrupted JSON data', () => {\n mockStorage.setItem('test:ingredients:v1', 'not valid json');\n\n const result = LocalStorageTreeAccessors.fromStorage({\n pathToKeyMap: {\n '/data/ingredients': 'test:ingredients:v1'\n },\n storage: mockStorage\n });\n\n expect(result).toSucceedAndSatisfy((accessors) => {\n expect(accessors).toBeInstanceOf(LocalStorageTreeAccessors);\n });\n });\n\n test('skips non-object JSON', () => {\n mockStorage.setItem('test:ingredients:v1', '\"string value\"');\n\n const result = LocalStorageTreeAccessors.fromStorage({\n pathToKeyMap: {\n '/data/ingredients': 'test:ingredients:v1'\n },\n storage: mockStorage\n });\n\n expect(result).toSucceedAndSatisfy((accessors) => {\n expect(accessors).toBeInstanceOf(LocalStorageTreeAccessors);\n });\n });\n\n test('loads string values (new format) with inferred extension', () => {\n mockStorage.setItem(\n 'test:ingredients:v1',\n JSON.stringify({\n jsonCollection: '{\"items\":{}}',\n yamlCollection: 'metadata:\\n name: test\\nitems: {}'\n })\n );\n\n const result = LocalStorageTreeAccessors.fromStorage({\n pathToKeyMap: {\n '/data/ingredients': 'test:ingredients:v1'\n },\n storage: mockStorage\n });\n\n expect(result).toSucceedAndSatisfy((accessors) => {\n expect(accessors.getFileContents('/data/ingredients/jsonCollection.json')).toSucceedWith(\n '{\"items\":{}}'\n );\n expect(accessors.getFileContents('/data/ingredients/yamlCollection.yaml')).toSucceedWith(\n 'metadata:\\n name: test\\nitems: {}'\n );\n });\n });\n\n test('skips non-object non-string collection values', () => {\n mockStorage.setItem(\n 'test:ingredients:v1',\n JSON.stringify({\n good: { items: {} },\n bad: 42\n })\n );\n\n const result = LocalStorageTreeAccessors.fromStorage({\n pathToKeyMap: {\n '/data/ingredients': 'test:ingredients:v1'\n },\n storage: mockStorage\n });\n\n expect(result).toSucceedAndSatisfy((accessors) => {\n expect(accessors.getFileContents('/data/ingredients/good.json')).toSucceed();\n });\n });\n\n test('applies prefix parameter', () => {\n mockStorage.setItem('test:ingredients:v1', JSON.stringify({ collection1: { items: {} } }));\n\n const result = LocalStorageTreeAccessors.fromStorage({\n pathToKeyMap: {\n '/data/ingredients': 'test:ingredients:v1'\n },\n storage: mockStorage,\n prefix: '/myapp'\n });\n\n expect(result).toSucceedAndSatisfy((accessors) => {\n expect(accessors.getFileContents('/myapp/data/ingredients/collection1.json')).toSucceed();\n });\n });\n\n test('succeeds with empty storage when no data present', () => {\n const result = LocalStorageTreeAccessors.fromStorage({\n pathToKeyMap: {\n '/data/ingredients': 'test:ingredients:v1'\n },\n storage: mockStorage\n });\n\n expect(result).toSucceedAndSatisfy((accessors) => {\n expect(accessors).toBeInstanceOf(LocalStorageTreeAccessors);\n });\n });\n });\n\n describe('dirty tracking', () => {\n test('starts with no dirty files', () => {\n mockStorage.setItem('test:ingredients:v1', JSON.stringify({ collection1: { items: {} } }));\n\n const accessors = LocalStorageTreeAccessors.fromStorage({\n pathToKeyMap: {\n '/data/ingredients': 'test:ingredients:v1'\n },\n storage: mockStorage,\n mutable: true\n }).orThrow();\n\n expect(accessors.isDirty()).toBe(false);\n expect(accessors.getDirtyPaths()).toEqual([]);\n });\n\n test('marks files as dirty after modification', () => {\n mockStorage.setItem('test:ingredients:v1', JSON.stringify({ collection1: { items: {} } }));\n\n const accessors = LocalStorageTreeAccessors.fromStorage({\n pathToKeyMap: {\n '/data/ingredients': 'test:ingredients:v1'\n },\n storage: mockStorage,\n mutable: true\n }).orThrow();\n\n const newContent = JSON.stringify({ items: { modified: true } });\n accessors.saveFileContents('/data/ingredients/collection1.json', newContent).orThrow();\n\n expect(accessors.isDirty()).toBe(true);\n expect(accessors.getDirtyPaths()).toContain('/data/ingredients/collection1.json');\n });\n\n test('tracks multiple dirty files', () => {\n mockStorage.setItem(\n 'test:ingredients:v1',\n JSON.stringify({\n collection1: { items: {} },\n collection2: { items: {} }\n })\n );\n\n const accessors = LocalStorageTreeAccessors.fromStorage({\n pathToKeyMap: {\n '/data/ingredients': 'test:ingredients:v1'\n },\n storage: mockStorage,\n mutable: true\n }).orThrow();\n\n accessors\n .saveFileContents('/data/ingredients/collection1.json', JSON.stringify({ items: { a: 1 } }))\n .orThrow();\n accessors\n .saveFileContents('/data/ingredients/collection2.json', JSON.stringify({ items: { b: 2 } }))\n .orThrow();\n\n expect(accessors.isDirty()).toBe(true);\n expect(accessors.getDirtyPaths()).toHaveLength(2);\n });\n });\n\n describe('syncToDisk', () => {\n test('syncs modified files to storage', async () => {\n mockStorage.setItem(\n 'test:ingredients:v1',\n JSON.stringify({ collection1: { items: { original: true } } })\n );\n\n const accessors = LocalStorageTreeAccessors.fromStorage({\n pathToKeyMap: {\n '/data/ingredients': 'test:ingredients:v1'\n },\n storage: mockStorage,\n mutable: true\n }).orThrow();\n\n const newContent = JSON.stringify({ items: { modified: true } });\n accessors.saveFileContents('/data/ingredients/collection1.json', newContent).orThrow();\n\n const syncResult = await accessors.syncToDisk();\n expect(syncResult).toSucceed();\n\n const stored = mockStorage.getItem('test:ingredients:v1');\n expect(stored).toBeTruthy();\n const parsed = JSON.parse(stored!);\n // New format: values are raw content strings\n expect(parsed.collection1).toBe(newContent);\n });\n\n test('clears dirty state after successful sync', async () => {\n mockStorage.setItem('test:ingredients:v1', JSON.stringify({ collection1: { items: {} } }));\n\n const accessors = LocalStorageTreeAccessors.fromStorage({\n pathToKeyMap: {\n '/data/ingredients': 'test:ingredients:v1'\n },\n storage: mockStorage,\n mutable: true\n }).orThrow();\n\n accessors\n .saveFileContents('/data/ingredients/collection1.json', JSON.stringify({ items: { a: 1 } }))\n .orThrow();\n expect(accessors.isDirty()).toBe(true);\n\n await accessors.syncToDisk();\n expect(accessors.isDirty()).toBe(false);\n expect(accessors.getDirtyPaths()).toEqual([]);\n });\n\n test('syncs multiple files to same storage key', async () => {\n mockStorage.setItem(\n 'test:ingredients:v1',\n JSON.stringify({\n collection1: { items: {} },\n collection2: { items: {} }\n })\n );\n\n const accessors = LocalStorageTreeAccessors.fromStorage({\n pathToKeyMap: {\n '/data/ingredients': 'test:ingredients:v1'\n },\n storage: mockStorage,\n mutable: true\n }).orThrow();\n\n const content1 = JSON.stringify({ items: { a: 1 } });\n const content2 = JSON.stringify({ items: { b: 2 } });\n accessors.saveFileContents('/data/ingredients/collection1.json', content1).orThrow();\n accessors.saveFileContents('/data/ingredients/collection2.json', content2).orThrow();\n\n await accessors.syncToDisk();\n\n const stored = mockStorage.getItem('test:ingredients:v1');\n const parsed = JSON.parse(stored!);\n // New format: values are raw content strings\n expect(parsed.collection1).toBe(content1);\n expect(parsed.collection2).toBe(content2);\n });\n\n test('syncs files to different storage keys', async () => {\n mockStorage.setItem('test:ingredients:v1', JSON.stringify({ ing1: { items: {} } }));\n mockStorage.setItem('test:fillings:v1', JSON.stringify({ fill1: { items: {} } }));\n\n const accessors = LocalStorageTreeAccessors.fromStorage({\n pathToKeyMap: {\n '/data/ingredients': 'test:ingredients:v1',\n '/data/fillings': 'test:fillings:v1'\n },\n storage: mockStorage,\n mutable: true\n }).orThrow();\n\n accessors\n .saveFileContents('/data/ingredients/ing1.json', JSON.stringify({ items: { a: 1 } }))\n .orThrow();\n accessors.saveFileContents('/data/fillings/fill1.json', JSON.stringify({ items: { b: 2 } })).orThrow();\n\n await accessors.syncToDisk();\n\n const ingContent = JSON.stringify({ items: { a: 1 } });\n const fillContent = JSON.stringify({ items: { b: 2 } });\n const ingStored = JSON.parse(mockStorage.getItem('test:ingredients:v1')!);\n const fillStored = JSON.parse(mockStorage.getItem('test:fillings:v1')!);\n // New format: values are raw content strings\n expect(ingStored.ing1).toBe(ingContent);\n expect(fillStored.fill1).toBe(fillContent);\n });\n\n test('succeeds with no dirty files', async () => {\n const accessors = LocalStorageTreeAccessors.fromStorage({\n pathToKeyMap: {\n '/data/ingredients': 'test:ingredients:v1'\n },\n storage: mockStorage\n }).orThrow();\n\n const result = await accessors.syncToDisk();\n expect(result).toSucceed();\n });\n\n test('preserves existing collections when syncing', async () => {\n mockStorage.setItem(\n 'test:ingredients:v1',\n JSON.stringify({\n existing: { items: { keep: true } },\n toModify: { items: { original: true } }\n })\n );\n\n const accessors = LocalStorageTreeAccessors.fromStorage({\n pathToKeyMap: {\n '/data/ingredients': 'test:ingredients:v1'\n },\n storage: mockStorage,\n mutable: true\n }).orThrow();\n\n const modifiedContent = JSON.stringify({ items: { modified: true } });\n accessors.saveFileContents('/data/ingredients/toModify.json', modifiedContent).orThrow();\n await accessors.syncToDisk();\n\n const stored = JSON.parse(mockStorage.getItem('test:ingredients:v1')!);\n // existing was loaded from legacy format and not modified, so it stays as legacy object\n // toModify was saved with new content, so it's now a raw string\n expect(stored.toModify).toBe(modifiedContent);\n });\n });\n\n describe('autoSync mode', () => {\n test('automatically syncs on save when enabled', () => {\n mockStorage.setItem('test:ingredients:v1', JSON.stringify({ collection1: { items: {} } }));\n\n const accessors = LocalStorageTreeAccessors.fromStorage({\n pathToKeyMap: {\n '/data/ingredients': 'test:ingredients:v1'\n },\n storage: mockStorage,\n mutable: true,\n autoSync: true\n }).orThrow();\n\n accessors\n .saveFileContents('/data/ingredients/collection1.json', JSON.stringify({ items: { auto: true } }))\n .orThrow();\n\n expect(accessors.isDirty()).toBe(false);\n const autoContent = JSON.stringify({ items: { auto: true } });\n const stored = JSON.parse(mockStorage.getItem('test:ingredients:v1')!);\n // New format: values are raw content strings\n expect(stored.collection1).toBe(autoContent);\n });\n\n test('does not auto-sync when disabled', () => {\n mockStorage.setItem('test:ingredients:v1', JSON.stringify({ collection1: { items: {} } }));\n\n const accessors = LocalStorageTreeAccessors.fromStorage({\n pathToKeyMap: {\n '/data/ingredients': 'test:ingredients:v1'\n },\n storage: mockStorage,\n mutable: true,\n autoSync: false\n }).orThrow();\n\n accessors\n .saveFileContents('/data/ingredients/collection1.json', JSON.stringify({ items: { manual: true } }))\n .orThrow();\n\n expect(accessors.isDirty()).toBe(true);\n // Storage should still have the original legacy format (not yet synced)\n const stored = JSON.parse(mockStorage.getItem('test:ingredients:v1')!);\n expect(stored.collection1).toEqual({ items: {} });\n });\n });\n\n describe('fileIsMutable', () => {\n test('returns persistent detail when mutable', () => {\n mockStorage.setItem('test:ingredients:v1', JSON.stringify({ collection1: { items: {} } }));\n\n const accessors = LocalStorageTreeAccessors.fromStorage({\n pathToKeyMap: {\n '/data/ingredients': 'test:ingredients:v1'\n },\n storage: mockStorage,\n mutable: true\n }).orThrow();\n\n expect(accessors.fileIsMutable('/data/ingredients/collection1.json')).toSucceedWithDetail(\n true,\n 'persistent'\n );\n });\n\n test('returns not-mutable when not mutable', () => {\n mockStorage.setItem('test:ingredients:v1', JSON.stringify({ collection1: { items: {} } }));\n\n const accessors = LocalStorageTreeAccessors.fromStorage({\n pathToKeyMap: {\n '/data/ingredients': 'test:ingredients:v1'\n },\n storage: mockStorage,\n mutable: false\n }).orThrow();\n\n const result = accessors.fileIsMutable('/data/ingredients/collection1.json');\n expect(result.isFailure()).toBe(true);\n if (result.isFailure()) {\n expect(result.detail).toBe('not-mutable');\n }\n });\n });\n\n describe('integration with FileApiTreeAccessors', () => {\n test('createFromLocalStorage creates FileTree with persistent accessors', () => {\n mockStorage.setItem('test:ingredients:v1', JSON.stringify({ collection1: { items: {} } }));\n\n const result = FileApiTreeAccessors.createFromLocalStorage({\n pathToKeyMap: {\n '/data/ingredients': 'test:ingredients:v1'\n },\n storage: mockStorage,\n mutable: true\n });\n\n expect(result).toSucceed();\n\n const tree = result.orThrow();\n expect(tree).toBeInstanceOf(FileTree.FileTree);\n expect(FileTree.isPersistentAccessors(tree.hal)).toBe(true);\n\n const file = tree.getFile('/data/ingredients/collection1.json').orThrow();\n expect(file.getIsMutable()).toSucceedWithDetail(true, 'persistent');\n });\n\n test('createFromLocalStorage with multiple paths', () => {\n mockStorage.setItem('test:ingredients:v1', JSON.stringify({ ing1: { items: {} } }));\n mockStorage.setItem('test:fillings:v1', JSON.stringify({ fill1: { items: {} } }));\n\n const result = FileApiTreeAccessors.createFromLocalStorage({\n pathToKeyMap: {\n '/data/ingredients': 'test:ingredients:v1',\n '/data/fillings': 'test:fillings:v1'\n },\n storage: mockStorage,\n mutable: true\n });\n\n expect(result).toSucceedAndSatisfy((tree) => {\n expect(tree.getFile('/data/ingredients/ing1.json')).toSucceed();\n expect(tree.getFile('/data/fillings/fill1.json')).toSucceed();\n });\n });\n\n test('createFromLocalStorage with empty storage', () => {\n const result = FileApiTreeAccessors.createFromLocalStorage({\n pathToKeyMap: {\n '/data/ingredients': 'test:ingredients:v1'\n },\n storage: mockStorage\n });\n\n expect(result).toSucceedAndSatisfy((tree) => {\n expect(tree).toBeInstanceOf(FileTree.FileTree);\n });\n });\n\n test('createFromLocalStorage fails when localStorage is not available', () => {\n // Remove the global window object to ensure no fallback\n const originalWindow = (global as any).window;\n delete (global as any).window;\n\n const result = FileApiTreeAccessors.createFromLocalStorage({\n pathToKeyMap: {\n '/data/ingredients': 'test:ingredients:v1'\n },\n storage: undefined\n });\n\n // Restore window\n (global as any).window = originalWindow;\n\n expect(result).toFailWith(/localStorage is not available/i);\n });\n });\n\n describe('path matching and error handling', () => {\n test('handles files outside configured paths', async () => {\n mockStorage.setItem('test:ingredients:v1', JSON.stringify({ collection1: { items: {} } }));\n\n const accessors = LocalStorageTreeAccessors.fromStorage({\n pathToKeyMap: {\n '/data/ingredients': 'test:ingredients:v1'\n },\n storage: mockStorage,\n mutable: true\n }).orThrow();\n\n // Try to save a file outside the configured path\n const saveResult = accessors.saveFileContents('/other/path/file.json', JSON.stringify({ test: 1 }));\n expect(saveResult).toSucceed();\n\n // But syncing should fail because no storage key is configured\n const syncResult = await accessors.syncToDisk();\n expect(syncResult).toFailWith(/No storage key configured for path/i);\n });\n\n test('handles files inside configured paths', async () => {\n mockStorage.setItem('test:ingredients:v1', JSON.stringify({ collection1: { items: {} } }));\n\n const accessors = LocalStorageTreeAccessors.fromStorage({\n pathToKeyMap: {\n '/data/ingredients': 'test:ingredients:v1'\n },\n storage: mockStorage,\n mutable: true\n }).orThrow();\n\n // Save a file inside the configured path\n accessors.saveFileContents('/data/ingredients/newfile.json', JSON.stringify({ test: 1 })).orThrow();\n\n // Syncing should succeed\n const syncResult = await accessors.syncToDisk();\n expect(syncResult).toSucceed();\n });\n\n test('handles failed content retrieval during sync', async () => {\n mockStorage.setItem('test:ingredients:v1', JSON.stringify({ collection1: { items: {} } }));\n\n const accessors = LocalStorageTreeAccessors.fromStorage({\n pathToKeyMap: {\n '/data/ingredients': 'test:ingredients:v1'\n },\n storage: mockStorage,\n mutable: true\n }).orThrow();\n\n // Modify a file\n accessors.saveFileContents('/data/ingredients/collection1.json', JSON.stringify({ test: 1 })).orThrow();\n\n // Override getFileContents to fail\n const originalGetFileContents = accessors.getFileContents.bind(accessors);\n accessors.getFileContents = jest.fn((path: string) => {\n if (path === '/data/ingredients/collection1.json') {\n return { isSuccess: () => false, isFailure: () => true, message: 'File not found' } as any;\n }\n return originalGetFileContents(path);\n });\n\n const syncResult = await accessors.syncToDisk();\n expect(syncResult).toFailWith(/Failed to get file contents.*File not found/i);\n });\n\n test('handles corrupted JSON in localStorage during sync', async () => {\n mockStorage.setItem('test:ingredients:v1', JSON.stringify({ collection1: { items: {} } }));\n\n const accessors = LocalStorageTreeAccessors.fromStorage({\n pathToKeyMap: {\n '/data/ingredients': 'test:ingredients:v1'\n },\n storage: mockStorage,\n mutable: true\n }).orThrow();\n\n // Modify a file\n accessors.saveFileContents('/data/ingredients/collection1.json', JSON.stringify({ test: 1 })).orThrow();\n\n // Corrupt the existing storage data\n mockStorage.setItem('test:ingredients:v1', 'not valid json');\n\n // Sync should still succeed by starting fresh\n const syncResult = await accessors.syncToDisk();\n expect(syncResult).toSucceed();\n\n // Verify the data was written correctly despite corrupted previous data\n const stored = mockStorage.getItem('test:ingredients:v1');\n const parsed = JSON.parse(stored!);\n // New format: values are raw content strings\n expect(parsed.collection1).toBe(JSON.stringify({ test: 1 }));\n });\n\n test('syncs non-JSON content (YAML) without error', async () => {\n const accessors = LocalStorageTreeAccessors.fromStorage({\n pathToKeyMap: {\n '/data/ingredients': 'test:ingredients:v1'\n },\n storage: mockStorage,\n mutable: true\n }).orThrow();\n\n // Create and save a YAML file\n const yamlContent = 'metadata:\\n name: test\\nitems: {}';\n accessors.saveFileContents('/data/ingredients/my-collection.yaml', yamlContent).orThrow();\n\n const syncResult = await accessors.syncToDisk();\n expect(syncResult).toSucceed();\n\n const stored = JSON.parse(mockStorage.getItem('test:ingredients:v1')!);\n expect(stored['my-collection']).toBe(yamlContent);\n });\n\n test('handles multiple sync failures with aggregated errors', async () => {\n const accessors = LocalStorageTreeAccessors.fromStorage({\n pathToKeyMap: {\n '/data/ingredients': 'test:ingredients:v1'\n },\n storage: mockStorage,\n mutable: true\n }).orThrow();\n\n // Add files outside configured paths\n accessors.saveFileContents('/other1/file1.json', JSON.stringify({ test: 1 })).orThrow();\n accessors.saveFileContents('/other2/file2.json', JSON.stringify({ test: 2 })).orThrow();\n\n const syncResult = await accessors.syncToDisk();\n expect(syncResult).toFailWith(/Failed to sync 2 file\\(s\\)/i);\n });\n\n test('handles auto-sync failure', () => {\n mockStorage.setItem('test:ingredients:v1', JSON.stringify({ collection1: { items: {} } }));\n\n const accessors = LocalStorageTreeAccessors.fromStorage({\n pathToKeyMap: {\n '/data/ingredients': 'test:ingredients:v1'\n },\n storage: mockStorage,\n mutable: true,\n autoSync: true\n }).orThrow();\n\n // Try to save a file outside configured path with autoSync enabled\n const saveResult = accessors.saveFileContents('/other/path/file.json', JSON.stringify({ test: 1 }));\n expect(saveResult).toFailWith(/No storage key configured for path/i);\n });\n });\n});\n"]}
|
|
1
|
+
{"version":3,"file":"localStorageTreeAccessors.test.js","sourceRoot":"","sources":["../../../src/test/unit/localStorageTreeAccessors.test.ts"],"names":[],"mappings":"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","sourcesContent":["/*\n * Copyright (c) 2026 Erik Fortune\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\nimport '@fgv/ts-utils-jest';\nimport { FileTree } from '@fgv/ts-json-base';\nimport { LocalStorageTreeAccessors, FileApiTreeAccessors } from '../../packlets/file-tree';\n\n/**\n * Mock Storage implementation for testing\n */\nclass MockStorage implements Storage {\n private _data: Map<string, string> = new Map();\n\n get length(): number {\n return this._data.size;\n }\n\n clear(): void {\n this._data.clear();\n }\n\n getItem(key: string): string | null {\n return this._data.get(key) ?? null;\n }\n\n key(index: number): string | null {\n const keys = Array.from(this._data.keys());\n return keys[index] ?? null;\n }\n\n removeItem(key: string): void {\n this._data.delete(key);\n }\n\n setItem(key: string, value: string): void {\n this._data.set(key, value);\n }\n}\n\ndescribe('LocalStorageTreeAccessors', () => {\n let mockStorage: MockStorage;\n\n beforeEach(() => {\n mockStorage = new MockStorage();\n });\n\n describe('fromStorage', () => {\n test('creates accessors from empty storage', () => {\n const result = LocalStorageTreeAccessors.fromStorage({\n pathToKeyMap: {\n '/data/ingredients': 'test:ingredients:v1'\n },\n storage: mockStorage\n });\n\n expect(result).toSucceedAndSatisfy((accessors) => {\n expect(accessors).toBeInstanceOf(LocalStorageTreeAccessors);\n expect(accessors.isDirty()).toBe(false);\n });\n });\n\n test('loads collections from storage', () => {\n mockStorage.setItem(\n 'test:ingredients:v1',\n JSON.stringify({\n collection1: { items: { item1: {} } },\n collection2: { items: { item2: {} } }\n })\n );\n\n const result = LocalStorageTreeAccessors.fromStorage({\n pathToKeyMap: {\n '/data/ingredients': 'test:ingredients:v1'\n },\n storage: mockStorage\n });\n\n expect(result).toSucceedAndSatisfy((accessors) => {\n expect(accessors.getFileContents('/data/ingredients/collection1.json')).toSucceed();\n expect(accessors.getFileContents('/data/ingredients/collection2.json')).toSucceed();\n });\n });\n\n test('loads from multiple storage keys', () => {\n mockStorage.setItem('test:ingredients:v1', JSON.stringify({ ing1: { items: {} } }));\n mockStorage.setItem('test:fillings:v1', JSON.stringify({ fill1: { items: {} } }));\n\n const result = LocalStorageTreeAccessors.fromStorage({\n pathToKeyMap: {\n '/data/ingredients': 'test:ingredients:v1',\n '/data/fillings': 'test:fillings:v1'\n },\n storage: mockStorage\n });\n\n expect(result).toSucceedAndSatisfy((accessors) => {\n expect(accessors.getFileContents('/data/ingredients/ing1.json')).toSucceed();\n expect(accessors.getFileContents('/data/fillings/fill1.json')).toSucceed();\n });\n });\n\n test('skips corrupted JSON data', () => {\n mockStorage.setItem('test:ingredients:v1', 'not valid json');\n\n const result = LocalStorageTreeAccessors.fromStorage({\n pathToKeyMap: {\n '/data/ingredients': 'test:ingredients:v1'\n },\n storage: mockStorage\n });\n\n expect(result).toSucceedAndSatisfy((accessors) => {\n expect(accessors).toBeInstanceOf(LocalStorageTreeAccessors);\n });\n });\n\n test('skips non-object JSON', () => {\n mockStorage.setItem('test:ingredients:v1', '\"string value\"');\n\n const result = LocalStorageTreeAccessors.fromStorage({\n pathToKeyMap: {\n '/data/ingredients': 'test:ingredients:v1'\n },\n storage: mockStorage\n });\n\n expect(result).toSucceedAndSatisfy((accessors) => {\n expect(accessors).toBeInstanceOf(LocalStorageTreeAccessors);\n });\n });\n\n test('loads string values (new format) with inferred extension', () => {\n mockStorage.setItem(\n 'test:ingredients:v1',\n JSON.stringify({\n jsonCollection: '{\"items\":{}}',\n yamlCollection: 'metadata:\\n name: test\\nitems: {}'\n })\n );\n\n const result = LocalStorageTreeAccessors.fromStorage({\n pathToKeyMap: {\n '/data/ingredients': 'test:ingredients:v1'\n },\n storage: mockStorage\n });\n\n expect(result).toSucceedAndSatisfy((accessors) => {\n expect(accessors.getFileContents('/data/ingredients/jsonCollection.json')).toSucceedWith(\n '{\"items\":{}}'\n );\n expect(accessors.getFileContents('/data/ingredients/yamlCollection.yaml')).toSucceedWith(\n 'metadata:\\n name: test\\nitems: {}'\n );\n });\n });\n\n test('skips non-object non-string collection values', () => {\n mockStorage.setItem(\n 'test:ingredients:v1',\n JSON.stringify({\n good: { items: {} },\n bad: 42\n })\n );\n\n const result = LocalStorageTreeAccessors.fromStorage({\n pathToKeyMap: {\n '/data/ingredients': 'test:ingredients:v1'\n },\n storage: mockStorage\n });\n\n expect(result).toSucceedAndSatisfy((accessors) => {\n expect(accessors.getFileContents('/data/ingredients/good.json')).toSucceed();\n });\n });\n\n test('applies prefix parameter', () => {\n mockStorage.setItem('test:ingredients:v1', JSON.stringify({ collection1: { items: {} } }));\n\n const result = LocalStorageTreeAccessors.fromStorage({\n pathToKeyMap: {\n '/data/ingredients': 'test:ingredients:v1'\n },\n storage: mockStorage,\n prefix: '/myapp'\n });\n\n expect(result).toSucceedAndSatisfy((accessors) => {\n expect(accessors.getFileContents('/myapp/data/ingredients/collection1.json')).toSucceed();\n });\n });\n\n test('succeeds with empty storage when no data present', () => {\n const result = LocalStorageTreeAccessors.fromStorage({\n pathToKeyMap: {\n '/data/ingredients': 'test:ingredients:v1'\n },\n storage: mockStorage\n });\n\n expect(result).toSucceedAndSatisfy((accessors) => {\n expect(accessors).toBeInstanceOf(LocalStorageTreeAccessors);\n });\n });\n });\n\n describe('dirty tracking', () => {\n test('starts with no dirty files', () => {\n mockStorage.setItem('test:ingredients:v1', JSON.stringify({ collection1: { items: {} } }));\n\n const accessors = LocalStorageTreeAccessors.fromStorage({\n pathToKeyMap: {\n '/data/ingredients': 'test:ingredients:v1'\n },\n storage: mockStorage,\n mutable: true\n }).orThrow();\n\n expect(accessors.isDirty()).toBe(false);\n expect(accessors.getDirtyPaths()).toEqual([]);\n });\n\n test('marks files as dirty after modification', () => {\n mockStorage.setItem('test:ingredients:v1', JSON.stringify({ collection1: { items: {} } }));\n\n const accessors = LocalStorageTreeAccessors.fromStorage({\n pathToKeyMap: {\n '/data/ingredients': 'test:ingredients:v1'\n },\n storage: mockStorage,\n mutable: true\n }).orThrow();\n\n const newContent = JSON.stringify({ items: { modified: true } });\n accessors.saveFileContents('/data/ingredients/collection1.json', newContent).orThrow();\n\n expect(accessors.isDirty()).toBe(true);\n expect(accessors.getDirtyPaths()).toContain('/data/ingredients/collection1.json');\n });\n\n test('tracks multiple dirty files', () => {\n mockStorage.setItem(\n 'test:ingredients:v1',\n JSON.stringify({\n collection1: { items: {} },\n collection2: { items: {} }\n })\n );\n\n const accessors = LocalStorageTreeAccessors.fromStorage({\n pathToKeyMap: {\n '/data/ingredients': 'test:ingredients:v1'\n },\n storage: mockStorage,\n mutable: true\n }).orThrow();\n\n accessors\n .saveFileContents('/data/ingredients/collection1.json', JSON.stringify({ items: { a: 1 } }))\n .orThrow();\n accessors\n .saveFileContents('/data/ingredients/collection2.json', JSON.stringify({ items: { b: 2 } }))\n .orThrow();\n\n expect(accessors.isDirty()).toBe(true);\n expect(accessors.getDirtyPaths()).toHaveLength(2);\n });\n });\n\n describe('syncToDisk', () => {\n test('syncs modified files to storage', async () => {\n mockStorage.setItem(\n 'test:ingredients:v1',\n JSON.stringify({ collection1: { items: { original: true } } })\n );\n\n const accessors = LocalStorageTreeAccessors.fromStorage({\n pathToKeyMap: {\n '/data/ingredients': 'test:ingredients:v1'\n },\n storage: mockStorage,\n mutable: true\n }).orThrow();\n\n const newContent = JSON.stringify({ items: { modified: true } });\n accessors.saveFileContents('/data/ingredients/collection1.json', newContent).orThrow();\n\n const syncResult = await accessors.syncToDisk();\n expect(syncResult).toSucceed();\n\n const stored = mockStorage.getItem('test:ingredients:v1');\n expect(stored).toBeTruthy();\n const parsed = JSON.parse(stored!);\n // New format: values are raw content strings\n expect(parsed.collection1).toBe(newContent);\n });\n\n test('clears dirty state after successful sync', async () => {\n mockStorage.setItem('test:ingredients:v1', JSON.stringify({ collection1: { items: {} } }));\n\n const accessors = LocalStorageTreeAccessors.fromStorage({\n pathToKeyMap: {\n '/data/ingredients': 'test:ingredients:v1'\n },\n storage: mockStorage,\n mutable: true\n }).orThrow();\n\n accessors\n .saveFileContents('/data/ingredients/collection1.json', JSON.stringify({ items: { a: 1 } }))\n .orThrow();\n expect(accessors.isDirty()).toBe(true);\n\n await accessors.syncToDisk();\n expect(accessors.isDirty()).toBe(false);\n expect(accessors.getDirtyPaths()).toEqual([]);\n });\n\n test('syncs multiple files to same storage key', async () => {\n mockStorage.setItem(\n 'test:ingredients:v1',\n JSON.stringify({\n collection1: { items: {} },\n collection2: { items: {} }\n })\n );\n\n const accessors = LocalStorageTreeAccessors.fromStorage({\n pathToKeyMap: {\n '/data/ingredients': 'test:ingredients:v1'\n },\n storage: mockStorage,\n mutable: true\n }).orThrow();\n\n const content1 = JSON.stringify({ items: { a: 1 } });\n const content2 = JSON.stringify({ items: { b: 2 } });\n accessors.saveFileContents('/data/ingredients/collection1.json', content1).orThrow();\n accessors.saveFileContents('/data/ingredients/collection2.json', content2).orThrow();\n\n await accessors.syncToDisk();\n\n const stored = mockStorage.getItem('test:ingredients:v1');\n const parsed = JSON.parse(stored!);\n // New format: values are raw content strings\n expect(parsed.collection1).toBe(content1);\n expect(parsed.collection2).toBe(content2);\n });\n\n test('syncs files to different storage keys', async () => {\n mockStorage.setItem('test:ingredients:v1', JSON.stringify({ ing1: { items: {} } }));\n mockStorage.setItem('test:fillings:v1', JSON.stringify({ fill1: { items: {} } }));\n\n const accessors = LocalStorageTreeAccessors.fromStorage({\n pathToKeyMap: {\n '/data/ingredients': 'test:ingredients:v1',\n '/data/fillings': 'test:fillings:v1'\n },\n storage: mockStorage,\n mutable: true\n }).orThrow();\n\n accessors\n .saveFileContents('/data/ingredients/ing1.json', JSON.stringify({ items: { a: 1 } }))\n .orThrow();\n accessors.saveFileContents('/data/fillings/fill1.json', JSON.stringify({ items: { b: 2 } })).orThrow();\n\n await accessors.syncToDisk();\n\n const ingContent = JSON.stringify({ items: { a: 1 } });\n const fillContent = JSON.stringify({ items: { b: 2 } });\n const ingStored = JSON.parse(mockStorage.getItem('test:ingredients:v1')!);\n const fillStored = JSON.parse(mockStorage.getItem('test:fillings:v1')!);\n // New format: values are raw content strings\n expect(ingStored.ing1).toBe(ingContent);\n expect(fillStored.fill1).toBe(fillContent);\n });\n\n test('succeeds with no dirty files', async () => {\n const accessors = LocalStorageTreeAccessors.fromStorage({\n pathToKeyMap: {\n '/data/ingredients': 'test:ingredients:v1'\n },\n storage: mockStorage\n }).orThrow();\n\n const result = await accessors.syncToDisk();\n expect(result).toSucceed();\n });\n\n test('preserves existing collections when syncing', async () => {\n mockStorage.setItem(\n 'test:ingredients:v1',\n JSON.stringify({\n existing: { items: { keep: true } },\n toModify: { items: { original: true } }\n })\n );\n\n const accessors = LocalStorageTreeAccessors.fromStorage({\n pathToKeyMap: {\n '/data/ingredients': 'test:ingredients:v1'\n },\n storage: mockStorage,\n mutable: true\n }).orThrow();\n\n const modifiedContent = JSON.stringify({ items: { modified: true } });\n accessors.saveFileContents('/data/ingredients/toModify.json', modifiedContent).orThrow();\n await accessors.syncToDisk();\n\n const stored = JSON.parse(mockStorage.getItem('test:ingredients:v1')!);\n // existing was loaded from legacy format and not modified, so it stays as legacy object\n // toModify was saved with new content, so it's now a raw string\n expect(stored.toModify).toBe(modifiedContent);\n });\n });\n\n describe('autoSync mode', () => {\n test('automatically syncs on save when enabled', () => {\n mockStorage.setItem('test:ingredients:v1', JSON.stringify({ collection1: { items: {} } }));\n\n const accessors = LocalStorageTreeAccessors.fromStorage({\n pathToKeyMap: {\n '/data/ingredients': 'test:ingredients:v1'\n },\n storage: mockStorage,\n mutable: true,\n autoSync: true\n }).orThrow();\n\n accessors\n .saveFileContents('/data/ingredients/collection1.json', JSON.stringify({ items: { auto: true } }))\n .orThrow();\n\n expect(accessors.isDirty()).toBe(false);\n const autoContent = JSON.stringify({ items: { auto: true } });\n const stored = JSON.parse(mockStorage.getItem('test:ingredients:v1')!);\n // New format: values are raw content strings\n expect(stored.collection1).toBe(autoContent);\n });\n\n test('does not auto-sync when disabled', () => {\n mockStorage.setItem('test:ingredients:v1', JSON.stringify({ collection1: { items: {} } }));\n\n const accessors = LocalStorageTreeAccessors.fromStorage({\n pathToKeyMap: {\n '/data/ingredients': 'test:ingredients:v1'\n },\n storage: mockStorage,\n mutable: true,\n autoSync: false\n }).orThrow();\n\n accessors\n .saveFileContents('/data/ingredients/collection1.json', JSON.stringify({ items: { manual: true } }))\n .orThrow();\n\n expect(accessors.isDirty()).toBe(true);\n // Storage should still have the original legacy format (not yet synced)\n const stored = JSON.parse(mockStorage.getItem('test:ingredients:v1')!);\n expect(stored.collection1).toEqual({ items: {} });\n });\n });\n\n describe('fileIsMutable', () => {\n test('returns persistent detail when mutable', () => {\n mockStorage.setItem('test:ingredients:v1', JSON.stringify({ collection1: { items: {} } }));\n\n const accessors = LocalStorageTreeAccessors.fromStorage({\n pathToKeyMap: {\n '/data/ingredients': 'test:ingredients:v1'\n },\n storage: mockStorage,\n mutable: true\n }).orThrow();\n\n expect(accessors.fileIsMutable('/data/ingredients/collection1.json')).toSucceedWithDetail(\n true,\n 'persistent'\n );\n });\n\n test('returns not-mutable when not mutable', () => {\n mockStorage.setItem('test:ingredients:v1', JSON.stringify({ collection1: { items: {} } }));\n\n const accessors = LocalStorageTreeAccessors.fromStorage({\n pathToKeyMap: {\n '/data/ingredients': 'test:ingredients:v1'\n },\n storage: mockStorage,\n mutable: false\n }).orThrow();\n\n const result = accessors.fileIsMutable('/data/ingredients/collection1.json');\n expect(result.isFailure()).toBe(true);\n if (result.isFailure()) {\n expect(result.detail).toBe('not-mutable');\n }\n });\n });\n\n describe('integration with FileApiTreeAccessors', () => {\n test('createFromLocalStorage creates FileTree with persistent accessors', () => {\n mockStorage.setItem('test:ingredients:v1', JSON.stringify({ collection1: { items: {} } }));\n\n const result = FileApiTreeAccessors.createFromLocalStorage({\n pathToKeyMap: {\n '/data/ingredients': 'test:ingredients:v1'\n },\n storage: mockStorage,\n mutable: true\n });\n\n expect(result).toSucceed();\n\n const tree = result.orThrow();\n expect(tree).toBeInstanceOf(FileTree.FileTree);\n expect(FileTree.isPersistentAccessors(tree.hal)).toBe(true);\n\n const file = tree.getFile('/data/ingredients/collection1.json').orThrow();\n expect(FileTree.isMutableFileItem(file)).toBe(true);\n if (FileTree.isMutableFileItem(file)) {\n expect(file.getIsMutable()).toSucceedWithDetail(true, 'persistent');\n }\n });\n\n test('createFromLocalStorage with multiple paths', () => {\n mockStorage.setItem('test:ingredients:v1', JSON.stringify({ ing1: { items: {} } }));\n mockStorage.setItem('test:fillings:v1', JSON.stringify({ fill1: { items: {} } }));\n\n const result = FileApiTreeAccessors.createFromLocalStorage({\n pathToKeyMap: {\n '/data/ingredients': 'test:ingredients:v1',\n '/data/fillings': 'test:fillings:v1'\n },\n storage: mockStorage,\n mutable: true\n });\n\n expect(result).toSucceedAndSatisfy((tree) => {\n expect(tree.getFile('/data/ingredients/ing1.json')).toSucceed();\n expect(tree.getFile('/data/fillings/fill1.json')).toSucceed();\n });\n });\n\n test('createFromLocalStorage with empty storage', () => {\n const result = FileApiTreeAccessors.createFromLocalStorage({\n pathToKeyMap: {\n '/data/ingredients': 'test:ingredients:v1'\n },\n storage: mockStorage\n });\n\n expect(result).toSucceedAndSatisfy((tree) => {\n expect(tree).toBeInstanceOf(FileTree.FileTree);\n });\n });\n\n test('createFromLocalStorage fails when localStorage is not available', () => {\n // Remove the global window object to ensure no fallback\n const originalWindow = (global as any).window;\n delete (global as any).window;\n\n const result = FileApiTreeAccessors.createFromLocalStorage({\n pathToKeyMap: {\n '/data/ingredients': 'test:ingredients:v1'\n },\n storage: undefined\n });\n\n // Restore window\n (global as any).window = originalWindow;\n\n expect(result).toFailWith(/localStorage is not available/i);\n });\n });\n\n describe('path matching and error handling', () => {\n test('handles files outside configured paths', async () => {\n mockStorage.setItem('test:ingredients:v1', JSON.stringify({ collection1: { items: {} } }));\n\n const accessors = LocalStorageTreeAccessors.fromStorage({\n pathToKeyMap: {\n '/data/ingredients': 'test:ingredients:v1'\n },\n storage: mockStorage,\n mutable: true\n }).orThrow();\n\n // Try to save a file outside the configured path\n const saveResult = accessors.saveFileContents('/other/path/file.json', JSON.stringify({ test: 1 }));\n expect(saveResult).toSucceed();\n\n // But syncing should fail because no storage key is configured\n const syncResult = await accessors.syncToDisk();\n expect(syncResult).toFailWith(/No storage key configured for path/i);\n });\n\n test('handles files inside configured paths', async () => {\n mockStorage.setItem('test:ingredients:v1', JSON.stringify({ collection1: { items: {} } }));\n\n const accessors = LocalStorageTreeAccessors.fromStorage({\n pathToKeyMap: {\n '/data/ingredients': 'test:ingredients:v1'\n },\n storage: mockStorage,\n mutable: true\n }).orThrow();\n\n // Save a file inside the configured path\n accessors.saveFileContents('/data/ingredients/newfile.json', JSON.stringify({ test: 1 })).orThrow();\n\n // Syncing should succeed\n const syncResult = await accessors.syncToDisk();\n expect(syncResult).toSucceed();\n });\n\n test('handles failed content retrieval during sync', async () => {\n mockStorage.setItem('test:ingredients:v1', JSON.stringify({ collection1: { items: {} } }));\n\n const accessors = LocalStorageTreeAccessors.fromStorage({\n pathToKeyMap: {\n '/data/ingredients': 'test:ingredients:v1'\n },\n storage: mockStorage,\n mutable: true\n }).orThrow();\n\n // Modify a file\n accessors.saveFileContents('/data/ingredients/collection1.json', JSON.stringify({ test: 1 })).orThrow();\n\n // Override getFileContents to fail\n const originalGetFileContents = accessors.getFileContents.bind(accessors);\n accessors.getFileContents = jest.fn((path: string) => {\n if (path === '/data/ingredients/collection1.json') {\n return { isSuccess: () => false, isFailure: () => true, message: 'File not found' } as any;\n }\n return originalGetFileContents(path);\n });\n\n const syncResult = await accessors.syncToDisk();\n expect(syncResult).toFailWith(/Failed to get file contents.*File not found/i);\n });\n\n test('handles corrupted JSON in localStorage during sync', async () => {\n mockStorage.setItem('test:ingredients:v1', JSON.stringify({ collection1: { items: {} } }));\n\n const accessors = LocalStorageTreeAccessors.fromStorage({\n pathToKeyMap: {\n '/data/ingredients': 'test:ingredients:v1'\n },\n storage: mockStorage,\n mutable: true\n }).orThrow();\n\n // Modify a file\n accessors.saveFileContents('/data/ingredients/collection1.json', JSON.stringify({ test: 1 })).orThrow();\n\n // Corrupt the existing storage data\n mockStorage.setItem('test:ingredients:v1', 'not valid json');\n\n // Sync should still succeed by starting fresh\n const syncResult = await accessors.syncToDisk();\n expect(syncResult).toSucceed();\n\n // Verify the data was written correctly despite corrupted previous data\n const stored = mockStorage.getItem('test:ingredients:v1');\n const parsed = JSON.parse(stored!);\n // New format: values are raw content strings\n expect(parsed.collection1).toBe(JSON.stringify({ test: 1 }));\n });\n\n test('syncs non-JSON content (YAML) without error', async () => {\n const accessors = LocalStorageTreeAccessors.fromStorage({\n pathToKeyMap: {\n '/data/ingredients': 'test:ingredients:v1'\n },\n storage: mockStorage,\n mutable: true\n }).orThrow();\n\n // Create and save a YAML file\n const yamlContent = 'metadata:\\n name: test\\nitems: {}';\n accessors.saveFileContents('/data/ingredients/my-collection.yaml', yamlContent).orThrow();\n\n const syncResult = await accessors.syncToDisk();\n expect(syncResult).toSucceed();\n\n const stored = JSON.parse(mockStorage.getItem('test:ingredients:v1')!);\n expect(stored['my-collection']).toBe(yamlContent);\n });\n\n test('handles multiple sync failures with aggregated errors', async () => {\n const accessors = LocalStorageTreeAccessors.fromStorage({\n pathToKeyMap: {\n '/data/ingredients': 'test:ingredients:v1'\n },\n storage: mockStorage,\n mutable: true\n }).orThrow();\n\n // Add files outside configured paths\n accessors.saveFileContents('/other1/file1.json', JSON.stringify({ test: 1 })).orThrow();\n accessors.saveFileContents('/other2/file2.json', JSON.stringify({ test: 2 })).orThrow();\n\n const syncResult = await accessors.syncToDisk();\n expect(syncResult).toFailWith(/Failed to sync 2 file\\(s\\)/i);\n });\n\n test('handles auto-sync failure', () => {\n mockStorage.setItem('test:ingredients:v1', JSON.stringify({ collection1: { items: {} } }));\n\n const accessors = LocalStorageTreeAccessors.fromStorage({\n pathToKeyMap: {\n '/data/ingredients': 'test:ingredients:v1'\n },\n storage: mockStorage,\n mutable: true,\n autoSync: true\n }).orThrow();\n\n // Try to save a file outside configured path with autoSync enabled\n const saveResult = accessors.saveFileContents('/other/path/file.json', JSON.stringify({ test: 1 }));\n expect(saveResult).toFailWith(/No storage key configured for path/i);\n });\n });\n\n describe('deleteFile', () => {\n test('deletes a file from in-memory storage and from localStorage', () => {\n mockStorage.setItem(\n 'test:ingredients:v1',\n JSON.stringify({\n collection1: '{\"items\":{}}',\n collection2: '{\"items\":{}}'\n })\n );\n\n const accessors = LocalStorageTreeAccessors.fromStorage({\n pathToKeyMap: {\n '/data/ingredients': 'test:ingredients:v1'\n },\n storage: mockStorage,\n mutable: true\n }).orThrow();\n\n const result = accessors.deleteFile('/data/ingredients/collection1.json');\n expect(result).toSucceedWith(true);\n\n // File should no longer be accessible in-memory\n expect(accessors.getFileContents('/data/ingredients/collection1.json')).toFail();\n\n // The deleted collection should be removed from localStorage; collection2 remains\n const stored = mockStorage.getItem('test:ingredients:v1');\n expect(stored).toBeTruthy();\n const parsed = JSON.parse(stored!);\n expect(parsed).not.toHaveProperty('collection1');\n expect(parsed).toHaveProperty('collection2');\n });\n\n test('removes the storage key entirely when last entry is deleted', () => {\n mockStorage.setItem('test:ingredients:v1', JSON.stringify({ onlyCollection: '{\"items\":{}}' }));\n\n const accessors = LocalStorageTreeAccessors.fromStorage({\n pathToKeyMap: {\n '/data/ingredients': 'test:ingredients:v1'\n },\n storage: mockStorage,\n mutable: true\n }).orThrow();\n\n const result = accessors.deleteFile('/data/ingredients/onlyCollection.json');\n expect(result).toSucceedWith(true);\n\n // Storage key should be removed entirely since no more entries remain\n expect(mockStorage.getItem('test:ingredients:v1')).toBeNull();\n });\n\n test('removes path from dirty set when deleting a dirty file', () => {\n mockStorage.setItem('test:ingredients:v1', JSON.stringify({ collection1: '{\"items\":{}}' }));\n\n const accessors = LocalStorageTreeAccessors.fromStorage({\n pathToKeyMap: {\n '/data/ingredients': 'test:ingredients:v1'\n },\n storage: mockStorage,\n mutable: true\n }).orThrow();\n\n // Mark file as dirty first\n accessors\n .saveFileContents('/data/ingredients/collection1.json', JSON.stringify({ items: { modified: true } }))\n .orThrow();\n expect(accessors.isDirty()).toBe(true);\n\n // Deleting the file should clean it from the dirty set\n const result = accessors.deleteFile('/data/ingredients/collection1.json');\n expect(result).toSucceedWith(true);\n expect(accessors.isDirty()).toBe(false);\n expect(accessors.getDirtyPaths()).not.toContain('/data/ingredients/collection1.json');\n });\n\n test('fails when deleting a non-existent file', () => {\n const accessors = LocalStorageTreeAccessors.fromStorage({\n pathToKeyMap: {\n '/data/ingredients': 'test:ingredients:v1'\n },\n storage: mockStorage,\n mutable: true\n }).orThrow();\n\n const result = accessors.deleteFile('/data/ingredients/nonexistent.json');\n expect(result).toFail();\n });\n\n test('does not modify storage when file has no matching storage key', () => {\n // Create accessors with one path, but a file that will be stored outside that path\n const accessors = LocalStorageTreeAccessors.fromStorage({\n pathToKeyMap: {\n '/data/ingredients': 'test:ingredients:v1'\n },\n storage: mockStorage,\n mutable: true\n }).orThrow();\n\n // Add and delete a file inside the configured path but with no existing storage entry\n accessors.saveFileContents('/data/ingredients/newfile.json', '{\"items\":{}}').orThrow();\n // Sync so it exists in storage\n mockStorage.setItem('test:ingredients:v1', JSON.stringify({ newfile: '{\"items\":{}}' }));\n\n // Now re-load and delete — the file should be removed from storage\n const accessors2 = LocalStorageTreeAccessors.fromStorage({\n pathToKeyMap: {\n '/data/ingredients': 'test:ingredients:v1'\n },\n storage: mockStorage,\n mutable: true\n }).orThrow();\n\n const result = accessors2.deleteFile('/data/ingredients/newfile.json');\n expect(result).toSucceedWith(true);\n expect(mockStorage.getItem('test:ingredients:v1')).toBeNull();\n });\n\n test('handles deletion when localStorage key has no entry for the file', () => {\n // Storage key exists but does not contain an entry for the file being deleted\n mockStorage.setItem('test:ingredients:v1', JSON.stringify({ other: '{\"items\":{}}' }));\n\n // Manually add a file to in-memory without it being in the storage JSON\n const accessors = LocalStorageTreeAccessors.fromStorage({\n pathToKeyMap: {\n '/data/ingredients': 'test:ingredients:v1'\n },\n storage: mockStorage,\n mutable: true\n }).orThrow();\n\n // Save a new file (marks dirty but does not update storage yet)\n accessors.saveFileContents('/data/ingredients/newfile.json', '{\"items\":{}}').orThrow();\n\n // Clear the dirty flag by directly removing from storage (simulate storage mismatch)\n // Then delete the file — _deleteFileFromStorage gets the existing JSON which lacks 'newfile'\n // This exercises the path where the collection is not in the existing JSON\n mockStorage.setItem('test:ingredients:v1', JSON.stringify({ other: '{\"items\":{}}' }));\n\n const result = accessors.deleteFile('/data/ingredients/newfile.json');\n expect(result).toSucceedWith(true);\n\n // 'other' should still remain in storage since only 'newfile' was deleted (which wasn't there)\n const stored = mockStorage.getItem('test:ingredients:v1');\n expect(stored).toBeTruthy();\n const parsed = JSON.parse(stored!);\n expect(parsed).toHaveProperty('other');\n });\n\n test('handles deletion when storage entry for key is missing entirely', () => {\n // No storage key at all — _deleteFileFromStorage should return early\n const accessors = LocalStorageTreeAccessors.fromStorage({\n pathToKeyMap: {\n '/data/ingredients': 'test:ingredients:v1'\n },\n storage: mockStorage,\n mutable: true\n }).orThrow();\n\n // Manually put a file in memory by saving it\n accessors.saveFileContents('/data/ingredients/newfile.json', '{\"items\":{}}').orThrow();\n\n // Delete the storage key so getItem returns null\n mockStorage.removeItem('test:ingredients:v1');\n\n // deleteFile should still succeed (in-memory deletion succeeds; storage cleanup is a no-op)\n const result = accessors.deleteFile('/data/ingredients/newfile.json');\n expect(result).toSucceedWith(true);\n });\n\n test('handles deletion when storage contains corrupted JSON', () => {\n mockStorage.setItem('test:ingredients:v1', JSON.stringify({ collection1: '{\"items\":{}}' }));\n\n const accessors = LocalStorageTreeAccessors.fromStorage({\n pathToKeyMap: {\n '/data/ingredients': 'test:ingredients:v1'\n },\n storage: mockStorage,\n mutable: true\n }).orThrow();\n\n // Corrupt the storage so JSON.parse fails in _deleteFileFromStorage\n mockStorage.setItem('test:ingredients:v1', 'not valid json {{{');\n\n // deleteFile should still succeed — corrupted JSON is silently ignored\n const result = accessors.deleteFile('/data/ingredients/collection1.json');\n expect(result).toSucceedWith(true);\n });\n\n test('deletes a file at a path outside all configured storage keys', () => {\n // A file can be saved in-memory at a path that has no matching storage key.\n // When deleted, _deleteFileFromStorage should return early without touching storage.\n const accessors = LocalStorageTreeAccessors.fromStorage({\n pathToKeyMap: {\n '/data/ingredients': 'test:ingredients:v1'\n },\n storage: mockStorage,\n mutable: true\n }).orThrow();\n\n // Save a file outside the configured path (succeeds in-memory, marks dirty)\n accessors.saveFileContents('/untracked/file.json', '{\"items\":{}}').orThrow();\n\n // Delete it — should succeed even though there is no storage key for this path\n const result = accessors.deleteFile('/untracked/file.json');\n expect(result).toSucceedWith(true);\n\n // Storage should be untouched\n expect(mockStorage.getItem('test:ingredients:v1')).toBeNull();\n });\n });\n\n describe('inferContentType callback in _loadFromStorage', () => {\n test('calls inferContentType when loading files from storage', () => {\n // Covers lines 163-164: the params.inferContentType branch in _loadFromStorage\n mockStorage.setItem(\n 'test:ingredients:v1',\n JSON.stringify({\n myCollection: '{\"items\":{}}'\n })\n );\n\n const inferContentType = jest.fn((filePath: string, _provided: string | undefined) => {\n const { succeed: s } = require('@fgv/ts-utils') as typeof import('@fgv/ts-utils');\n return s('application/json' as string);\n });\n\n const result = LocalStorageTreeAccessors.fromStorage({\n pathToKeyMap: {\n '/data/ingredients': 'test:ingredients:v1'\n },\n storage: mockStorage,\n inferContentType\n });\n\n expect(result).toSucceed();\n expect(inferContentType).toHaveBeenCalledWith('/data/ingredients/myCollection.json', undefined);\n });\n });\n\n describe('extension-less file path handling', () => {\n test('syncs a file whose path has no extension (collection ID has no dot)', async () => {\n // Covers line 249: dotIndex <= 0 case in _getCollectionIdFromPath, returning cleanPath as-is\n // We save a file at a path with no file extension; the collection ID extracted\n // will be the entire basename (no dot to strip).\n const accessors = LocalStorageTreeAccessors.fromStorage({\n pathToKeyMap: {\n '/data/ingredients': 'test:ingredients:v1'\n },\n storage: mockStorage,\n mutable: true\n }).orThrow();\n\n // Save a file at a path with no extension\n accessors.saveFileContents('/data/ingredients/nodot', '{\"items\":{}}').orThrow();\n\n const syncResult = await accessors.syncToDisk();\n expect(syncResult).toSucceed();\n\n // The collection ID stored in localStorage should be 'nodot' (no extension stripped)\n const stored = mockStorage.getItem('test:ingredients:v1');\n expect(stored).toBeTruthy();\n const parsed = JSON.parse(stored!) as Record<string, unknown>;\n expect(parsed.nodot).toBe('{\"items\":{}}');\n });\n });\n});\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@fgv/ts-web-extras",
|
|
3
|
-
"version": "5.1.0-
|
|
3
|
+
"version": "5.1.0-10",
|
|
4
4
|
"description": "Browser-compatible utilities and FileTree implementations",
|
|
5
5
|
"main": "lib/index.js",
|
|
6
6
|
"types": "dist/ts-web-extras.d.ts",
|
|
@@ -37,27 +37,28 @@
|
|
|
37
37
|
"typescript": "5.9.3",
|
|
38
38
|
"eslint-plugin-n": "^17.23.1",
|
|
39
39
|
"@rushstack/eslint-config": "4.6.4",
|
|
40
|
-
"@rushstack/heft": "1.2.
|
|
40
|
+
"@rushstack/heft": "1.2.7",
|
|
41
41
|
"@rushstack/heft-jest-plugin": "1.2.6",
|
|
42
|
-
"@rushstack/heft-node-rig": "2.11.
|
|
42
|
+
"@rushstack/heft-node-rig": "2.11.27",
|
|
43
43
|
"@types/heft-jest": "1.0.6",
|
|
44
44
|
"eslint-plugin-tsdoc": "~0.5.2",
|
|
45
45
|
"@rushstack/eslint-patch": "1.14.1",
|
|
46
46
|
"@types/react": "~19.2.8",
|
|
47
47
|
"typedoc": "~0.28.16",
|
|
48
48
|
"typedoc-plugin-markdown": "~4.9.0",
|
|
49
|
-
"@fgv/heft-dual-rig": "
|
|
50
|
-
"@fgv/ts-
|
|
51
|
-
"@fgv/ts-
|
|
52
|
-
"@fgv/
|
|
53
|
-
"@fgv/ts-utils-jest": "5.1.0-
|
|
49
|
+
"@fgv/heft-dual-rig": "5.1.0-10",
|
|
50
|
+
"@fgv/ts-extras": "5.1.0-10",
|
|
51
|
+
"@fgv/ts-utils": "5.1.0-10",
|
|
52
|
+
"@fgv/typedoc-compact-theme": "5.1.0-10",
|
|
53
|
+
"@fgv/ts-utils-jest": "5.1.0-10",
|
|
54
|
+
"@fgv/ts-json-base": "5.1.0-10"
|
|
54
55
|
},
|
|
55
56
|
"peerDependencies": {
|
|
56
57
|
"react": ">=18 <20",
|
|
57
58
|
"react-dom": ">=18 <20",
|
|
58
|
-
"@fgv/ts-
|
|
59
|
-
"@fgv/ts-
|
|
60
|
-
"@fgv/ts-
|
|
59
|
+
"@fgv/ts-extras": "5.1.0-10",
|
|
60
|
+
"@fgv/ts-json-base": "5.1.0-10",
|
|
61
|
+
"@fgv/ts-utils": "5.1.0-10"
|
|
61
62
|
},
|
|
62
63
|
"exports": {
|
|
63
64
|
".": {
|
|
@@ -74,7 +75,7 @@
|
|
|
74
75
|
},
|
|
75
76
|
"repository": {
|
|
76
77
|
"type": "git",
|
|
77
|
-
"url": "https://github.com/ErikFortune/fgv.git"
|
|
78
|
+
"url": "git+https://github.com/ErikFortune/fgv.git"
|
|
78
79
|
},
|
|
79
80
|
"dependencies": {
|
|
80
81
|
"idb-keyval": "^6.2.2"
|
|
@@ -2,51 +2,54 @@ Invoking: heft test --clean
|
|
|
2
2
|
---- build started ----
|
|
3
3
|
[build:typescript] The TypeScript compiler version 5.9.3 is newer than the latest version that was tested with Heft (5.8); it may not work correctly.
|
|
4
4
|
[build:typescript] Using TypeScript version 5.9.3
|
|
5
|
-
[build:api-extractor] Using API Extractor version 7.57.
|
|
5
|
+
[build:api-extractor] Using API Extractor version 7.57.7
|
|
6
6
|
[build:api-extractor] Analysis will use the bundled TypeScript version 5.8.2
|
|
7
7
|
[build:api-extractor] *** The target project appears to use TypeScript 5.9.3 which is newer than the bundled compiler engine; consider upgrading API Extractor.
|
|
8
|
-
---- build finished (
|
|
8
|
+
---- build finished (25.276s) ----
|
|
9
9
|
---- test started ----
|
|
10
10
|
[test:jest] Using Jest version 29.5.0
|
|
11
11
|
[test:jest]
|
|
12
|
-
[test:jest] Run start.
|
|
12
|
+
[test:jest] Run start. 9 test suites
|
|
13
|
+
[test:jest] START lib/test/unit/httpTreeAccessors.test.js
|
|
13
14
|
[test:jest] START lib/test/unit/fileApiTreeAccessors.test.js
|
|
14
|
-
[test:jest] START lib/test/unit/fileTreeHelpers.test.js
|
|
15
|
-
[test:jest] START lib/test/unit/fileSystemAccessTreeAccessors.test.js
|
|
16
15
|
[test:jest] START lib/test/unit/localStorageTreeAccessors.test.js
|
|
17
|
-
[test:jest]
|
|
16
|
+
[test:jest] START lib/test/unit/fileSystemAccessTreeAccessors.test.js
|
|
17
|
+
[test:jest] PASS lib/test/unit/httpTreeAccessors.test.js (duration: 2.122s, 61 passed, 0 failed)
|
|
18
|
+
[test:jest] START lib/test/unit/fileTreeHelpers.test.js
|
|
19
|
+
[test:jest] PASS lib/test/unit/localStorageTreeAccessors.test.js (duration: 1.833s, 44 passed, 0 failed)
|
|
18
20
|
[test:jest] START lib/test/unit/fileApiTypes.test.js
|
|
19
|
-
[test:jest] PASS lib/test/unit/
|
|
21
|
+
[test:jest] PASS lib/test/unit/fileApiTreeAccessors.test.js (duration: 2.101s, 65 passed, 0 failed)
|
|
20
22
|
[test:jest] START lib/test/unit/urlParams.test.js
|
|
21
|
-
[test:jest] PASS lib/test/unit/fileSystemAccessTreeAccessors.test.js (duration:
|
|
23
|
+
[test:jest] PASS lib/test/unit/fileSystemAccessTreeAccessors.test.js (duration: 1.500s, 44 passed, 0 failed)
|
|
22
24
|
[test:jest] START lib/test/unit/directoryHandleStore.test.js
|
|
23
|
-
[test:jest] PASS lib/test/unit/
|
|
25
|
+
[test:jest] PASS lib/test/unit/fileApiTypes.test.js (duration: 1.394s, 36 passed, 0 failed)
|
|
24
26
|
[test:jest] START lib/test/unit/browserHashProvider.test.js
|
|
25
|
-
[test:jest] PASS lib/test/unit/
|
|
26
|
-
[test:jest] PASS lib/test/unit/urlParams.test.js (duration: 1.
|
|
27
|
-
[test:jest] PASS lib/test/unit/directoryHandleStore.test.js (duration: 1.
|
|
28
|
-
[test:jest] PASS lib/test/unit/browserHashProvider.test.js (duration: 1.
|
|
27
|
+
[test:jest] PASS lib/test/unit/fileTreeHelpers.test.js (duration: 1.637s, 35 passed, 0 failed)
|
|
28
|
+
[test:jest] PASS lib/test/unit/urlParams.test.js (duration: 1.677s, 60 passed, 0 failed)
|
|
29
|
+
[test:jest] PASS lib/test/unit/directoryHandleStore.test.js (duration: 1.637s, 19 passed, 0 failed)
|
|
30
|
+
[test:jest] PASS lib/test/unit/browserHashProvider.test.js (duration: 1.575s, 15 passed, 0 failed)
|
|
29
31
|
[test:jest]
|
|
30
32
|
[test:jest] Tests finished:
|
|
31
|
-
[test:jest] Successes:
|
|
33
|
+
[test:jest] Successes: 379
|
|
32
34
|
[test:jest] Failures: 0
|
|
33
|
-
[test:jest] Total:
|
|
34
|
-
|
|
35
|
-
File | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s
|
|
36
|
-
|
|
37
|
-
All files | 100 |
|
|
38
|
-
crypto-utils | 100 | 100 | 100 | 100 |
|
|
39
|
-
browserCryptoProvider.ts | 100 | 100 | 100 | 100 |
|
|
40
|
-
browserHashProvider.ts | 100 | 100 | 100 | 100 |
|
|
41
|
-
file-tree | 100 |
|
|
42
|
-
directoryHandleStore.ts | 100 | 100 | 100 | 100 |
|
|
43
|
-
fileApiTreeAccessors.ts | 100 | 100 | 100 | 100 |
|
|
44
|
-
fileSystemAccessTreeAccessors.ts | 100 |
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
35
|
+
[test:jest] Total: 380
|
|
36
|
+
-----------------------------------|---------|----------|---------|---------|-------------------
|
|
37
|
+
File | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s
|
|
38
|
+
-----------------------------------|---------|----------|---------|---------|-------------------
|
|
39
|
+
All files | 100 | 99.62 | 100 | 100 |
|
|
40
|
+
crypto-utils | 100 | 100 | 100 | 100 |
|
|
41
|
+
browserCryptoProvider.ts | 100 | 100 | 100 | 100 |
|
|
42
|
+
browserHashProvider.ts | 100 | 100 | 100 | 100 |
|
|
43
|
+
file-tree | 100 | 99.58 | 100 | 100 |
|
|
44
|
+
directoryHandleStore.ts | 100 | 100 | 100 | 100 |
|
|
45
|
+
fileApiTreeAccessors.ts | 100 | 100 | 100 | 100 |
|
|
46
|
+
fileSystemAccessTreeAccessors.ts | 100 | 100 | 100 | 100 |
|
|
47
|
+
httpTreeAccessors.ts | 100 | 98.42 | 100 | 100 | 369
|
|
48
|
+
localStorageTreeAccessors.ts | 100 | 100 | 100 | 100 |
|
|
49
|
+
helpers | 100 | 100 | 100 | 100 |
|
|
50
|
+
fileTreeHelpers.ts | 100 | 100 | 100 | 100 |
|
|
51
|
+
url-utils | 100 | 100 | 100 | 100 |
|
|
52
|
+
urlParams.ts | 100 | 100 | 100 | 100 |
|
|
53
|
+
-----------------------------------|---------|----------|---------|---------|-------------------
|
|
54
|
+
---- test finished (8.152s) ----
|
|
55
|
+
-------------------- Finished (33.436s) --------------------
|
|
@@ -30,6 +30,7 @@ import {
|
|
|
30
30
|
FileSystemDirectoryHandle
|
|
31
31
|
} from '../file-api-types';
|
|
32
32
|
import { FileSystemAccessTreeAccessors, IFileSystemAccessTreeParams } from './fileSystemAccessTreeAccessors';
|
|
33
|
+
import { HttpTreeAccessors, IHttpTreeParams } from './httpTreeAccessors';
|
|
33
34
|
import { LocalStorageTreeAccessors, ILocalStorageTreeParams } from './localStorageTreeAccessors';
|
|
34
35
|
|
|
35
36
|
/**
|
|
@@ -130,6 +131,23 @@ export class FileApiTreeAccessors<TCT extends string = string> {
|
|
|
130
131
|
return FileTree.FileTree.create<TCT>(accessorsResult.value);
|
|
131
132
|
}
|
|
132
133
|
|
|
134
|
+
/**
|
|
135
|
+
* Create a persistent FileTree from an HTTP storage service.
|
|
136
|
+
*
|
|
137
|
+
* @param params - Configuration including API base URL, namespace, and optional autoSync
|
|
138
|
+
* @returns Promise resolving to a FileTree with persistence capability
|
|
139
|
+
* @public
|
|
140
|
+
*/
|
|
141
|
+
public static async createFromHttp<TCT extends string = string>(
|
|
142
|
+
params: IHttpTreeParams<TCT>
|
|
143
|
+
): Promise<Result<FileTree.FileTree<TCT>>> {
|
|
144
|
+
const accessorsResult = await HttpTreeAccessors.fromHttp<TCT>(params);
|
|
145
|
+
if (accessorsResult.isFailure()) {
|
|
146
|
+
return fail(accessorsResult.message);
|
|
147
|
+
}
|
|
148
|
+
return FileTree.FileTree.create<TCT>(accessorsResult.value);
|
|
149
|
+
}
|
|
150
|
+
|
|
133
151
|
/**
|
|
134
152
|
* Create a persistent FileTree from a single File System Access API file handle.
|
|
135
153
|
* The tree contains exactly one file at `/<filename>`.
|