@fgv/ts-web-extras 5.1.0-0 → 5.1.0-1
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/chunked-rush-logs/ts-web-extras.build.chunks.jsonl +56 -33
- package/.rush/temp/chunked-rush-logs/ts-web-extras.test.chunks.jsonl +70 -0
- package/.rush/temp/operation/build/all.log +56 -33
- package/.rush/temp/operation/build/error.log +18 -0
- package/.rush/temp/operation/build/log-chunks.jsonl +56 -33
- package/.rush/temp/operation/build/state.json +1 -1
- package/.rush/temp/operation/test/all.log +70 -0
- package/.rush/temp/operation/test/error.log +16 -0
- package/.rush/temp/operation/test/log-chunks.jsonl +70 -0
- package/.rush/temp/operation/test/state.json +3 -0
- 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 +279 -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 +1000 -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 +124 -0
- package/docs/@fgv/namespaces/CryptoUtils/README.md +18 -0
- package/docs/@fgv/namespaces/CryptoUtils/classes/BrowserCryptoProvider.md +203 -0
- package/docs/@fgv/namespaces/CryptoUtils/classes/BrowserHashProvider.md +63 -0
- package/docs/@fgv/namespaces/CryptoUtils/functions/createBrowserCryptoProvider.md +18 -0
- package/docs/@fgv/namespaces/FileTreeHelpers/README.md +19 -0
- package/docs/@fgv/namespaces/FileTreeHelpers/functions/extractFileListMetadata.md +23 -0
- package/docs/@fgv/namespaces/FileTreeHelpers/functions/extractFileMetadata.md +23 -0
- package/docs/@fgv/namespaces/FileTreeHelpers/functions/fromDirectoryUpload.md +33 -0
- package/docs/@fgv/namespaces/FileTreeHelpers/functions/fromFileList.md +33 -0
- package/docs/@fgv/namespaces/FileTreeHelpers/functions/getOriginalFile.md +25 -0
- package/docs/@fgv/namespaces/FileTreeHelpers/variables/defaultFileApiTreeInitParams.md +11 -0
- package/docs/README.md +78 -0
- package/docs/classes/DirectoryHandleStore.md +116 -0
- package/docs/classes/FileApiTreeAccessors.md +286 -0
- package/docs/classes/FileSystemAccessTreeAccessors.md +557 -0
- package/docs/classes/HttpTreeAccessors.md +508 -0
- package/docs/classes/LocalStorageTreeAccessors.md +520 -0
- package/docs/functions/exportAsJson.md +23 -0
- package/docs/functions/exportUsingFileSystemAPI.md +26 -0
- package/docs/functions/extractDirectoryPath.md +23 -0
- package/docs/functions/isDirectoryHandle.md +23 -0
- package/docs/functions/isFileHandle.md +23 -0
- package/docs/functions/isFilePath.md +21 -0
- package/docs/functions/parseContextFilter.md +22 -0
- package/docs/functions/parseQualifierDefaults.md +22 -0
- package/docs/functions/parseResourceTypes.md +22 -0
- package/docs/functions/parseUrlParameters.md +15 -0
- package/docs/functions/safeShowDirectoryPicker.md +24 -0
- package/docs/functions/safeShowOpenFilePicker.md +24 -0
- package/docs/functions/safeShowSaveFilePicker.md +24 -0
- package/docs/functions/supportsFileSystemAccess.md +23 -0
- package/docs/interfaces/FilePickerAcceptType.md +16 -0
- package/docs/interfaces/FileSystemCreateWritableOptions.md +15 -0
- package/docs/interfaces/FileSystemDirectoryHandle.md +187 -0
- package/docs/interfaces/FileSystemFileHandle.md +106 -0
- package/docs/interfaces/FileSystemGetDirectoryOptions.md +15 -0
- package/docs/interfaces/FileSystemGetFileOptions.md +15 -0
- package/docs/interfaces/FileSystemHandle.md +69 -0
- package/docs/interfaces/FileSystemHandlePermissionDescriptor.md +15 -0
- package/docs/interfaces/FileSystemRemoveOptions.md +15 -0
- package/docs/interfaces/FileSystemWritableFileStream.md +127 -0
- package/docs/interfaces/IDirectoryHandleTreeInitializer.md +17 -0
- package/docs/interfaces/IFileHandleTreeInitializer.md +16 -0
- package/docs/interfaces/IFileListTreeInitializer.md +15 -0
- package/docs/interfaces/IFileMetadata.md +19 -0
- package/docs/interfaces/IFileSystemAccessTreeParams.md +30 -0
- package/docs/interfaces/IFsAccessApis.md +57 -0
- package/docs/interfaces/IHttpTreeParams.md +32 -0
- package/docs/interfaces/ILocalStorageTreeParams.md +30 -0
- package/docs/interfaces/IUrlConfigOptions.md +27 -0
- package/docs/interfaces/ShowDirectoryPickerOptions.md +17 -0
- package/docs/interfaces/ShowOpenFilePickerOptions.md +19 -0
- package/docs/interfaces/ShowSaveFilePickerOptions.md +19 -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 +11 -0
- package/docs/variables/DEFAULT_DIRECTORY_HANDLE_STORE.md +11 -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 +88 -0
- package/lib/packlets/file-tree/httpTreeAccessors.d.ts.map +1 -0
- package/lib/packlets/file-tree/httpTreeAccessors.js +283 -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 +1002 -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 +25 -25
- package/rush-logs/ts-web-extras.build.cache.log +0 -3
- package/rush-logs/ts-web-extras.build.error.log +18 -0
- package/rush-logs/ts-web-extras.build.log +56 -33
- package/rush-logs/ts-web-extras.test.cache.log +1 -0
- package/rush-logs/ts-web-extras.test.error.log +16 -0
- package/rush-logs/ts-web-extras.test.log +70 -0
- 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 +381 -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 +1278 -0
- package/src/test/unit/localStorageTreeAccessors.test.ts +269 -1
- package/temp/build/typescript/ts_8nwakTlr.json +1 -1
- package/temp/coverage/crypto/browserHashProvider.ts.html +304 -0
- package/temp/coverage/crypto/index.html +116 -0
- 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 +1228 -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/browserHashProvider.ts.html +304 -0
- package/temp/coverage/lcov-report/crypto/index.html +116 -0
- 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 +1228 -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 +1920 -1196
- 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-b931e4e63102f86c5bd4949f7dced44f-9d713eb41149188b4e5c0ae3d86d0a57-2ad8e16b24e391b8cdbe50b55c137169 +0 -0
- package/temp/test/jest/perf-cache-b931e4e63102f86c5bd4949f7dced44f-da39a3ee5e6b4b0d3255bfef95601890 +1 -0
- package/temp/ts-web-extras.api.json +1313 -354
- package/temp/ts-web-extras.api.md +33 -0
- package/.rush/temp/81e0881271ff236956b2f52e8ca99da6574c6e1e.tar.log +0 -223
- 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/haste-map-7492f1b44480e0cdd1f220078fb3afd8-c8dd6c3430605adeb2f1cadf4f75e791-8c9336785555d572065b28c111982ba4 +0 -0
- package/temp/test/jest/perf-cache-7492f1b44480e0cdd1f220078fb3afd8-da39a3ee5e6b4b0d3255bfef95601890 +0 -1
- /package/temp/test/jest/{jest-transform-cache-7492f1b44480e0cdd1f220078fb3afd8-79ef2876fae7ca75eedb2aa53dc48338/8d/package_8dcbedef69e4299f0f51fcda8f4f1c8e → jest-transform-cache-b931e4e63102f86c5bd4949f7dced44f-79ef2876fae7ca75eedb2aa53dc48338/b5/package_b5f57afc9ec2c011239b1608ee5bdfa5} +0 -0
|
@@ -21,6 +21,7 @@
|
|
|
21
21
|
*/
|
|
22
22
|
|
|
23
23
|
import '@fgv/ts-utils-jest';
|
|
24
|
+
import { fail, type Result, Logging } from '@fgv/ts-utils';
|
|
24
25
|
import { FileSystemAccessTreeAccessors } from '../../packlets/file-tree';
|
|
25
26
|
import { FileApiTreeAccessors } from '../../packlets/file-tree';
|
|
26
27
|
import { FileTree } from '@fgv/ts-json-base';
|
|
@@ -166,7 +167,7 @@ describe('FileSystemAccessTreeAccessors', () => {
|
|
|
166
167
|
|
|
167
168
|
test('fails gracefully when queryPermission throws', async () => {
|
|
168
169
|
const fileHandle = {
|
|
169
|
-
kind: 'file'
|
|
170
|
+
kind: 'file',
|
|
170
171
|
name: 'collection.yaml',
|
|
171
172
|
async getFile(): Promise<File> {
|
|
172
173
|
return createMockFileHandle('collection.yaml', {
|
|
@@ -466,267 +467,419 @@ describe('FileSystemAccessTreeAccessors', () => {
|
|
|
466
467
|
accessors.saveFileContents('/test.txt', 'modified').orThrow();
|
|
467
468
|
|
|
468
469
|
// Verify file is marked dirty but not synced
|
|
469
|
-
expect(accessors.isDirty()).toBe(true);
|
|
470
470
|
expect(accessors.getDirtyPaths()).toContain('/test.txt');
|
|
471
471
|
|
|
472
472
|
// In-memory content should be modified
|
|
473
473
|
expect(accessors.getFileContents('/test.txt')).toSucceedWith('modified');
|
|
474
474
|
});
|
|
475
|
-
});
|
|
476
|
-
});
|
|
477
475
|
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
476
|
+
test('logs when save auto-sync returns a failure Result', async () => {
|
|
477
|
+
const logger = {
|
|
478
|
+
detail: jest.fn(),
|
|
479
|
+
info: jest.fn(),
|
|
480
|
+
warn: jest.fn(),
|
|
481
|
+
error: jest.fn()
|
|
482
|
+
} as unknown as Logging.LogReporter<unknown>;
|
|
483
|
+
const dirHandle = createMockDirectoryHandle('/', {
|
|
484
|
+
'test.txt': { content: 'original', type: 'text/plain' }
|
|
485
|
+
});
|
|
486
|
+
|
|
487
|
+
const accessors = (
|
|
488
|
+
await FileSystemAccessTreeAccessors.fromDirectoryHandle(dirHandle, {
|
|
489
|
+
mutable: true,
|
|
490
|
+
autoSync: true,
|
|
491
|
+
logger
|
|
492
|
+
})
|
|
493
|
+
).orThrow();
|
|
494
|
+
|
|
495
|
+
(
|
|
496
|
+
accessors as unknown as {
|
|
497
|
+
_syncFile: (_path: string) => Promise<Result<void>>;
|
|
498
|
+
}
|
|
499
|
+
)._syncFile = async () => fail<void>('simulated save sync failure');
|
|
500
|
+
|
|
501
|
+
accessors.saveFileContents('/test.txt', 'modified').orThrow();
|
|
502
|
+
await new Promise<void>((resolve) => setTimeout(resolve, 0));
|
|
503
|
+
|
|
504
|
+
expect(logger.error).toHaveBeenCalledWith(expect.stringContaining('simulated save sync failure'));
|
|
482
505
|
});
|
|
483
506
|
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
507
|
+
test('logs when delete auto-sync throws unexpectedly', async () => {
|
|
508
|
+
const logger = {
|
|
509
|
+
detail: jest.fn(),
|
|
510
|
+
info: jest.fn(),
|
|
511
|
+
warn: jest.fn(),
|
|
512
|
+
error: jest.fn()
|
|
513
|
+
} as unknown as Logging.LogReporter<unknown>;
|
|
514
|
+
const dirHandle = createMockDirectoryHandle('/', {
|
|
515
|
+
'test.txt': { content: 'original', type: 'text/plain' }
|
|
516
|
+
});
|
|
487
517
|
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
518
|
+
const accessors = (
|
|
519
|
+
await FileSystemAccessTreeAccessors.fromDirectoryHandle(dirHandle, {
|
|
520
|
+
mutable: true,
|
|
521
|
+
autoSync: true,
|
|
522
|
+
logger
|
|
523
|
+
})
|
|
524
|
+
).orThrow();
|
|
491
525
|
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
526
|
+
(
|
|
527
|
+
accessors as unknown as {
|
|
528
|
+
_deleteFileFromDisk: (_path: string) => Promise<Result<void>>;
|
|
529
|
+
}
|
|
530
|
+
)._deleteFileFromDisk = async () => {
|
|
531
|
+
throw new Error('simulated delete throw');
|
|
532
|
+
};
|
|
498
533
|
|
|
499
|
-
|
|
500
|
-
await
|
|
501
|
-
mutable: true,
|
|
502
|
-
requireWritePermission: false
|
|
503
|
-
})
|
|
504
|
-
).orThrow();
|
|
534
|
+
accessors.deleteFile('/test.txt').orThrow();
|
|
535
|
+
await new Promise<void>((resolve) => setTimeout(resolve, 0));
|
|
505
536
|
|
|
506
|
-
|
|
507
|
-
|
|
537
|
+
expect(logger.error).toHaveBeenCalledWith(expect.stringContaining('simulated delete throw'));
|
|
538
|
+
});
|
|
508
539
|
});
|
|
509
540
|
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
541
|
+
describe('fileIsMutable', () => {
|
|
542
|
+
test('returns persistent detail when write permission granted', async () => {
|
|
543
|
+
const dirHandle = createMockDirectoryHandle('/', {
|
|
544
|
+
'test.txt': { content: 'test', type: 'text/plain' }
|
|
545
|
+
});
|
|
546
|
+
|
|
547
|
+
const accessors = (
|
|
548
|
+
await FileSystemAccessTreeAccessors.fromDirectoryHandle(dirHandle, { mutable: true })
|
|
549
|
+
).orThrow();
|
|
550
|
+
|
|
551
|
+
const result = accessors.fileIsMutable('/test.txt');
|
|
552
|
+
expect(result).toSucceedWithDetail(true, 'persistent');
|
|
513
553
|
});
|
|
514
554
|
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
555
|
+
test('returns transient detail when write permission not granted', async () => {
|
|
556
|
+
const dirHandle = createMockDirectoryHandle(
|
|
557
|
+
'/',
|
|
558
|
+
{ 'test.txt': { content: 'test', type: 'text/plain' } },
|
|
559
|
+
{ hasWritePermission: false }
|
|
560
|
+
);
|
|
518
561
|
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
562
|
+
const accessors = (
|
|
563
|
+
await FileSystemAccessTreeAccessors.fromDirectoryHandle(dirHandle, {
|
|
564
|
+
mutable: true,
|
|
565
|
+
requireWritePermission: false
|
|
566
|
+
})
|
|
567
|
+
).orThrow();
|
|
523
568
|
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
const dirHandle = createMockDirectoryHandle('/', {
|
|
527
|
-
'test.txt': { content: 'test content', type: 'text/plain' }
|
|
569
|
+
const result = accessors.fileIsMutable('/test.txt');
|
|
570
|
+
expect(result).toSucceedWithDetail(true, 'transient');
|
|
528
571
|
});
|
|
529
572
|
|
|
530
|
-
|
|
531
|
-
|
|
573
|
+
test('returns not-mutable when mutability disabled', async () => {
|
|
574
|
+
const dirHandle = createMockDirectoryHandle('/', {
|
|
575
|
+
'test.txt': { content: 'test', type: 'text/plain' }
|
|
576
|
+
});
|
|
532
577
|
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
578
|
+
const accessors = (
|
|
579
|
+
await FileSystemAccessTreeAccessors.fromDirectoryHandle(dirHandle, { mutable: false })
|
|
580
|
+
).orThrow();
|
|
536
581
|
|
|
537
|
-
|
|
538
|
-
|
|
582
|
+
const result = accessors.fileIsMutable('/test.txt');
|
|
583
|
+
expect(result).toFailWithDetail(/mutability is disabled/i, 'not-mutable');
|
|
584
|
+
});
|
|
539
585
|
});
|
|
540
586
|
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
587
|
+
describe('integration with FileApiTreeAccessors', () => {
|
|
588
|
+
test('createPersistent creates FileTree with persistent accessors', async () => {
|
|
589
|
+
const dirHandle = createMockDirectoryHandle('/', {
|
|
590
|
+
'test.txt': { content: 'test content', type: 'text/plain' }
|
|
591
|
+
});
|
|
545
592
|
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
autoSync: true
|
|
549
|
-
});
|
|
593
|
+
const result = await FileApiTreeAccessors.createPersistent(dirHandle, { mutable: true });
|
|
594
|
+
expect(result).toSucceed();
|
|
550
595
|
|
|
551
|
-
|
|
596
|
+
const tree = result.orThrow();
|
|
552
597
|
expect(tree).toBeInstanceOf(FileTree.FileTree);
|
|
598
|
+
expect(FileTree.isPersistentAccessors(tree.hal)).toBe(true);
|
|
599
|
+
|
|
600
|
+
const file = tree.getFile('/test.txt').orThrow();
|
|
601
|
+
expect(FileTree.isMutableFileItem(file)).toBe(true);
|
|
602
|
+
if (FileTree.isMutableFileItem(file)) {
|
|
603
|
+
expect(file.getIsMutable()).toSucceedWithDetail(true, 'persistent');
|
|
604
|
+
}
|
|
553
605
|
});
|
|
554
606
|
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
607
|
+
test('createPersistent with autoSync option', async () => {
|
|
608
|
+
const dirHandle = createMockDirectoryHandle('/', {
|
|
609
|
+
'test.txt': { content: 'original', type: 'text/plain' }
|
|
610
|
+
});
|
|
558
611
|
|
|
559
|
-
|
|
560
|
-
|
|
612
|
+
const result = await FileApiTreeAccessors.createPersistent(dirHandle, {
|
|
613
|
+
mutable: true,
|
|
614
|
+
autoSync: true
|
|
615
|
+
});
|
|
561
616
|
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
const content = await diskFile.text();
|
|
566
|
-
expect(content).toBe('modified');
|
|
567
|
-
});
|
|
617
|
+
expect(result).toSucceedAndSatisfy((tree) => {
|
|
618
|
+
expect(tree).toBeInstanceOf(FileTree.FileTree);
|
|
619
|
+
});
|
|
568
620
|
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
621
|
+
const tree = result.orThrow();
|
|
622
|
+
const file = tree.getFile('/test.txt').orThrow();
|
|
623
|
+
expect(FileTree.isMutableFileItem(file)).toBe(true);
|
|
624
|
+
if (FileTree.isMutableFileItem(file)) {
|
|
625
|
+
file.setRawContents('modified').orThrow();
|
|
626
|
+
}
|
|
575
627
|
|
|
576
|
-
|
|
577
|
-
|
|
628
|
+
// Give auto-sync time to complete
|
|
629
|
+
await new Promise((resolve) => setTimeout(resolve, 10));
|
|
630
|
+
|
|
631
|
+
// Verify file was written
|
|
632
|
+
const fileHandle = await dirHandle.getFileHandle('test.txt');
|
|
633
|
+
const diskFile = await fileHandle.getFile();
|
|
634
|
+
const content = await diskFile.text();
|
|
635
|
+
expect(content).toBe('modified');
|
|
578
636
|
});
|
|
579
|
-
expect(result).toFailWith(/write permission required/i);
|
|
580
|
-
});
|
|
581
|
-
});
|
|
582
637
|
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
);
|
|
638
|
+
test('createPersistent fails with appropriate error', async () => {
|
|
639
|
+
const dirHandle = createMockDirectoryHandle(
|
|
640
|
+
'/',
|
|
641
|
+
{ 'test.txt': { content: 'test', type: 'text/plain' } },
|
|
642
|
+
{ hasWritePermission: false }
|
|
643
|
+
);
|
|
590
644
|
|
|
591
|
-
|
|
592
|
-
|
|
645
|
+
const result = await FileApiTreeAccessors.createPersistent(dirHandle, {
|
|
646
|
+
requireWritePermission: true
|
|
647
|
+
});
|
|
648
|
+
expect(result).toFailWith(/write permission required/i);
|
|
593
649
|
});
|
|
594
|
-
// Should succeed but without write permission due to error
|
|
595
|
-
expect(result).toSucceed();
|
|
596
650
|
});
|
|
597
651
|
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
652
|
+
describe('error handling', () => {
|
|
653
|
+
test('handles permission query errors gracefully', async () => {
|
|
654
|
+
const dirHandle = createMockDirectoryHandle(
|
|
655
|
+
'/',
|
|
656
|
+
{ 'test.txt': { content: 'test', type: 'text/plain' } },
|
|
657
|
+
{ permissionError: true }
|
|
658
|
+
);
|
|
604
659
|
|
|
605
|
-
|
|
606
|
-
|
|
660
|
+
const result = await FileSystemAccessTreeAccessors.fromDirectoryHandle(dirHandle, {
|
|
661
|
+
requireWritePermission: false
|
|
662
|
+
});
|
|
663
|
+
// Should succeed but without write permission due to error
|
|
664
|
+
expect(result).toSucceed();
|
|
607
665
|
});
|
|
608
|
-
|
|
609
|
-
|
|
666
|
+
|
|
667
|
+
test('handles permission status "prompt" by requesting permission', async () => {
|
|
668
|
+
const dirHandle = createMockDirectoryHandle(
|
|
669
|
+
'/',
|
|
670
|
+
{ 'test.txt': { content: 'test', type: 'text/plain' } },
|
|
671
|
+
{ permissionStatus: 'prompt', requestGranted: true }
|
|
672
|
+
);
|
|
673
|
+
|
|
674
|
+
const result = await FileSystemAccessTreeAccessors.fromDirectoryHandle(dirHandle, {
|
|
675
|
+
requireWritePermission: true
|
|
676
|
+
});
|
|
677
|
+
expect(result).toSucceedAndSatisfy((accessors) => {
|
|
678
|
+
expect(accessors).toBeInstanceOf(FileSystemAccessTreeAccessors);
|
|
679
|
+
});
|
|
610
680
|
});
|
|
611
|
-
});
|
|
612
681
|
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
682
|
+
test('handles sync failures with aggregated errors', async () => {
|
|
683
|
+
const dirHandle = createMockDirectoryHandle('/', {
|
|
684
|
+
'file1.txt': { content: 'content1', type: 'text/plain' },
|
|
685
|
+
'file2.txt': { content: 'content2', type: 'text/plain' }
|
|
686
|
+
});
|
|
687
|
+
|
|
688
|
+
const accessors = (
|
|
689
|
+
await FileSystemAccessTreeAccessors.fromDirectoryHandle(dirHandle, { mutable: true })
|
|
690
|
+
).orThrow();
|
|
691
|
+
|
|
692
|
+
// Modify files
|
|
693
|
+
accessors.saveFileContents('/file1.txt', 'modified1').orThrow();
|
|
694
|
+
accessors.saveFileContents('/file2.txt', 'modified2').orThrow();
|
|
695
|
+
|
|
696
|
+
// Replace the file handles with ones that fail to write
|
|
697
|
+
const handles = (accessors as any)._handles as Map<string, any>;
|
|
698
|
+
for (const [, handle] of handles) {
|
|
699
|
+
handle.createWritable = jest.fn().mockRejectedValue(new Error('Write permission denied'));
|
|
700
|
+
}
|
|
701
|
+
|
|
702
|
+
const syncResult = await accessors.syncToDisk();
|
|
703
|
+
expect(syncResult).toFailWith(/Failed to sync 2 file\(s\)/i);
|
|
617
704
|
});
|
|
618
705
|
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
706
|
+
test('handles getFileContents failure during sync', async () => {
|
|
707
|
+
const dirHandle = createMockDirectoryHandle('/', {
|
|
708
|
+
'test.txt': { content: 'original', type: 'text/plain' }
|
|
709
|
+
});
|
|
622
710
|
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
711
|
+
const accessors = (
|
|
712
|
+
await FileSystemAccessTreeAccessors.fromDirectoryHandle(dirHandle, { mutable: true })
|
|
713
|
+
).orThrow();
|
|
626
714
|
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
for (const [, handle] of handles) {
|
|
630
|
-
handle.createWritable = jest.fn().mockRejectedValue(new Error('Write permission denied'));
|
|
631
|
-
}
|
|
715
|
+
// Add a new file
|
|
716
|
+
accessors.saveFileContents('/newfile.txt', 'new content').orThrow();
|
|
632
717
|
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
718
|
+
// Override getFileContents to fail
|
|
719
|
+
const originalGetFileContents = accessors.getFileContents.bind(accessors);
|
|
720
|
+
accessors.getFileContents = jest.fn((path: string) => {
|
|
721
|
+
if (path === '/newfile.txt') {
|
|
722
|
+
return { isSuccess: () => false, isFailure: () => true, message: 'File read error' } as any;
|
|
723
|
+
}
|
|
724
|
+
return originalGetFileContents(path);
|
|
725
|
+
});
|
|
636
726
|
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
'test.txt': { content: 'original', type: 'text/plain' }
|
|
727
|
+
const syncResult = await accessors.syncToDisk();
|
|
728
|
+
expect(syncResult).toFailWith(/File read error/i);
|
|
640
729
|
});
|
|
641
730
|
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
731
|
+
test('handles file write failure during sync', async () => {
|
|
732
|
+
const dirHandle = createMockDirectoryHandle('/', {
|
|
733
|
+
'test.txt': { content: 'original', type: 'text/plain' }
|
|
734
|
+
});
|
|
645
735
|
|
|
646
|
-
|
|
647
|
-
|
|
736
|
+
const accessors = (
|
|
737
|
+
await FileSystemAccessTreeAccessors.fromDirectoryHandle(dirHandle, { mutable: true })
|
|
738
|
+
).orThrow();
|
|
648
739
|
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
740
|
+
accessors.saveFileContents('/test.txt', 'modified').orThrow();
|
|
741
|
+
|
|
742
|
+
// Replace the handle with one that fails to write
|
|
743
|
+
const handles = (accessors as any)._handles as Map<string, any>;
|
|
744
|
+
const handle = handles.get('/test.txt');
|
|
745
|
+
handle.createWritable = jest.fn().mockRejectedValue(new Error('Disk full'));
|
|
746
|
+
|
|
747
|
+
const syncResult = await accessors.syncToDisk();
|
|
748
|
+
expect(syncResult).toFailWith(/Failed to write file.*Disk full/i);
|
|
656
749
|
});
|
|
657
750
|
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
751
|
+
test('handles invalid file path with no filename', async () => {
|
|
752
|
+
const dirHandle = createMockDirectoryHandle('/', {
|
|
753
|
+
'existing.txt': { content: 'existing', type: 'text/plain' }
|
|
754
|
+
});
|
|
661
755
|
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
756
|
+
const accessors = (
|
|
757
|
+
await FileSystemAccessTreeAccessors.fromDirectoryHandle(dirHandle, { mutable: true })
|
|
758
|
+
).orThrow();
|
|
759
|
+
|
|
760
|
+
// Override resolveAbsolutePath to return an empty path to trigger the error
|
|
761
|
+
const originalResolveAbsolutePath = (accessors as any).resolveAbsolutePath.bind(accessors);
|
|
762
|
+
(accessors as any).resolveAbsolutePath = jest.fn((path: string) => {
|
|
763
|
+
if (path === '/badpath') {
|
|
764
|
+
return ''; // This will result in no parts after split
|
|
765
|
+
}
|
|
766
|
+
return originalResolveAbsolutePath(path);
|
|
767
|
+
});
|
|
768
|
+
|
|
769
|
+
// Create a new file with the bad path - don't throw if it fails
|
|
770
|
+
const saveResult = accessors.saveFileContents('/badpath', 'content');
|
|
771
|
+
if (saveResult.isFailure()) {
|
|
772
|
+
// saveFileContents itself might reject the path
|
|
773
|
+
expect(saveResult).toFailWith(/invalid file path/i);
|
|
774
|
+
} else {
|
|
775
|
+
// If save succeeded, sync should fail
|
|
776
|
+
const syncResult = await accessors.syncToDisk();
|
|
777
|
+
expect(syncResult).toFailWith(/Invalid file path/i);
|
|
778
|
+
}
|
|
665
779
|
});
|
|
666
780
|
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
781
|
+
test('handles file creation failure in _createAndWriteFile', async () => {
|
|
782
|
+
const dirHandle = createMockDirectoryHandle('/', {
|
|
783
|
+
'existing.txt': { content: 'existing', type: 'text/plain' }
|
|
784
|
+
});
|
|
670
785
|
|
|
671
|
-
|
|
786
|
+
const accessors = (
|
|
787
|
+
await FileSystemAccessTreeAccessors.fromDirectoryHandle(dirHandle, { mutable: true })
|
|
788
|
+
).orThrow();
|
|
672
789
|
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
const handle = handles.get('/test.txt');
|
|
676
|
-
handle.createWritable = jest.fn().mockRejectedValue(new Error('Disk full'));
|
|
790
|
+
// Add a new file that will need to be created
|
|
791
|
+
accessors.saveFileContents('/newdir/newfile.txt', 'new content').orThrow();
|
|
677
792
|
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
793
|
+
// Mock getDirectoryHandle to fail
|
|
794
|
+
const rootDir = (accessors as any)._rootDir;
|
|
795
|
+
rootDir.getDirectoryHandle = jest.fn().mockRejectedValue(new Error('Permission denied'));
|
|
681
796
|
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
'existing.txt': { content: 'existing', type: 'text/plain' }
|
|
797
|
+
const syncResult = await accessors.syncToDisk();
|
|
798
|
+
expect(syncResult).toFailWith(/Failed to create file.*Permission denied/i);
|
|
685
799
|
});
|
|
686
800
|
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
801
|
+
test('successfully deletes a root-level file from disk via syncToDisk pending deletions', async () => {
|
|
802
|
+
// Covers lines 329-333: the pending deletions loop in syncToDisk
|
|
803
|
+
const dirHandle = createMockDirectoryHandle('/', {
|
|
804
|
+
'toDelete.txt': { content: 'will be deleted', type: 'text/plain' },
|
|
805
|
+
'keep.txt': { content: 'stays', type: 'text/plain' }
|
|
806
|
+
});
|
|
690
807
|
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
808
|
+
const accessors = (
|
|
809
|
+
await FileSystemAccessTreeAccessors.fromDirectoryHandle(dirHandle, { mutable: true })
|
|
810
|
+
).orThrow();
|
|
811
|
+
|
|
812
|
+
// Delete the file from in-memory tree
|
|
813
|
+
accessors.deleteFile('/toDelete.txt').orThrow();
|
|
814
|
+
expect(accessors.isDirty()).toBe(true);
|
|
815
|
+
expect(accessors.getDirtyPaths()).toContain('/toDelete.txt');
|
|
816
|
+
|
|
817
|
+
// syncToDisk should process the pending deletion
|
|
818
|
+
const syncResult = await accessors.syncToDisk();
|
|
819
|
+
expect(syncResult).toSucceed();
|
|
820
|
+
expect(accessors.isDirty()).toBe(false);
|
|
698
821
|
});
|
|
699
822
|
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
823
|
+
test('successfully deletes a nested file from disk via syncToDisk (navigates parent dirs)', async () => {
|
|
824
|
+
// Covers lines 468-469: getDirectoryHandle navigation loop in _deleteFileFromDisk
|
|
825
|
+
const dirHandle = createMockDirectoryHandle('/', {
|
|
826
|
+
'src/utils/helper.txt': { content: 'to be deleted', type: 'text/plain' },
|
|
827
|
+
'src/index.txt': { content: 'stays', type: 'text/plain' }
|
|
828
|
+
});
|
|
829
|
+
|
|
830
|
+
const accessors = (
|
|
831
|
+
await FileSystemAccessTreeAccessors.fromDirectoryHandle(dirHandle, { mutable: true })
|
|
832
|
+
).orThrow();
|
|
833
|
+
|
|
834
|
+
// Delete the nested file
|
|
835
|
+
accessors.deleteFile('/src/utils/helper.txt').orThrow();
|
|
836
|
+
expect(accessors.isDirty()).toBe(true);
|
|
837
|
+
|
|
707
838
|
const syncResult = await accessors.syncToDisk();
|
|
708
|
-
expect(syncResult).
|
|
709
|
-
|
|
710
|
-
|
|
839
|
+
expect(syncResult).toSucceed();
|
|
840
|
+
expect(accessors.isDirty()).toBe(false);
|
|
841
|
+
});
|
|
711
842
|
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
843
|
+
test('aggregates deletion errors when _deleteFileFromDisk fails during syncToDisk', async () => {
|
|
844
|
+
// Covers lines 330-332: the error aggregation when _deleteFileFromDisk returns failure
|
|
845
|
+
const dirHandle = createMockDirectoryHandle('/', {
|
|
846
|
+
'toDelete.txt': { content: 'content', type: 'text/plain' }
|
|
847
|
+
});
|
|
848
|
+
|
|
849
|
+
const accessors = (
|
|
850
|
+
await FileSystemAccessTreeAccessors.fromDirectoryHandle(dirHandle, { mutable: true })
|
|
851
|
+
).orThrow();
|
|
852
|
+
|
|
853
|
+
accessors.deleteFile('/toDelete.txt').orThrow();
|
|
854
|
+
|
|
855
|
+
// Make removeEntry fail to trigger the error path in _deleteFileFromDisk
|
|
856
|
+
const rootDir = (accessors as any)._rootDir;
|
|
857
|
+
rootDir.removeEntry = jest.fn().mockRejectedValue(new Error('Cannot delete: file locked'));
|
|
858
|
+
|
|
859
|
+
const syncResult = await accessors.syncToDisk();
|
|
860
|
+
expect(syncResult).toFailWith(/Failed to sync 1 file/i);
|
|
861
|
+
expect(syncResult).toFailWith(/delete.*toDelete\.txt/i);
|
|
715
862
|
});
|
|
716
863
|
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
864
|
+
test('catch block in _deleteFileFromDisk when removeEntry throws', async () => {
|
|
865
|
+
// Covers lines 473-476: the catch block in _deleteFileFromDisk
|
|
866
|
+
const dirHandle = createMockDirectoryHandle('/', {
|
|
867
|
+
'target.txt': { content: 'content', type: 'text/plain' }
|
|
868
|
+
});
|
|
869
|
+
|
|
870
|
+
const accessors = (
|
|
871
|
+
await FileSystemAccessTreeAccessors.fromDirectoryHandle(dirHandle, { mutable: true })
|
|
872
|
+
).orThrow();
|
|
720
873
|
|
|
721
|
-
|
|
722
|
-
accessors.saveFileContents('/newdir/newfile.txt', 'new content').orThrow();
|
|
874
|
+
accessors.deleteFile('/target.txt').orThrow();
|
|
723
875
|
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
876
|
+
// Directly make _rootDir.removeEntry throw a non-Error value to test the catch branch
|
|
877
|
+
const rootDir = (accessors as any)._rootDir;
|
|
878
|
+
rootDir.removeEntry = jest.fn().mockRejectedValue('non-error string');
|
|
727
879
|
|
|
728
|
-
|
|
729
|
-
|
|
880
|
+
const syncResult = await accessors.syncToDisk();
|
|
881
|
+
expect(syncResult).toFailWith(/Failed to delete file.*non-error string/i);
|
|
882
|
+
});
|
|
730
883
|
});
|
|
731
884
|
});
|
|
732
885
|
});
|