Skip to content

feat(storage): add FileSystemHandleStore - #460

Open
jwindhager wants to merge 1 commit into
manzt:mainfrom
TissUUmaps:fs-handle-store
Open

jwindhager wants to merge 1 commit into
manzt:mainfrom
TissUUmaps:fs-handle-store

Conversation

@jwindhager

@jwindhager jwindhager commented Sep 24, 2026 •

Copy link
Copy Markdown

Adds FileSystemHandleStore to @zarrita/storage, a read/write store backed by a FileSystemDirectoryHandle. It works with the Origin Private File System (OPFS; navigator.storage.getDirectory(), all major browsers) and with directories from the File System Access API (showDirectoryPicker(), Chromium only).

import { FileSystemHandleStore } from "@zarrita/storage";

const handle = await showDirectoryPicker();
const store = new FileSystemHandleStore(handle);

Motivation

This builds on #161, which was read-only and predates some later changes to the store interface. In https://github.com/orgs/zarr-developers/discussions/69, this was eventually considered resolved because it's easy to do in user-land. The basic version is short, but a correct one takes more work, and many projects have ended up writing their own against zarrita's store interface, e.g.:

Having one maintained implementation upstream therefore seems worth it.

What's included

  • get, getRange (offset/length and suffix, reading via File.slice), and set (creates missing directories)
  • AbortSignal support on all methods. Aborting one caller doesn't affect others that share a cached directory lookup
  • Directory handle caching. Failed lookups are evicted, and writes skip the cache, so a stale/failed lookup never blocks a set
  • Missing keys return undefined, including when a path segment is a file or the key is a directory (NotFoundError/TypeMismatchError). Other errors are rethrown.
  • A failed or aborted write keeps the previous contents (writes go through a swap file) and removes a newly created file, so a failed write doesn't leave behind an empty key (best-effort; a concurrent set of the same new key can be affected)

This store is currently in use with the development version of TissUUmaps 4 and the OpenSeadragon OMEZarrTileSource.

Developed with the help of AI (incl. tests). I closely supervised and thoroughly reviewed everything.

@changeset-bot

changeset-bot Bot commented Sep 24, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: 9a1af2e

The changes in this PR will be included in the next version bump.

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@keller-mark

keller-mark commented Sep 24, 2026 •

Copy link
Copy Markdown
Collaborator

Note that the store in Vitessce (code, more code) also supports drag-and-drop (dropping a local folder onto a file input or dropzone), in addition to the directory picker. Does your implementation support this, or can it be updated to support this functionality?

(it also was intended to support selection of multiple folders or files, including individual files such as zip files, although that is not fully implemented)

@jwindhager

jwindhager commented Sep 24, 2026 •

Copy link
Copy Markdown
Author

Thanks! It should support drag-and-drop in Chromium: DataTransferItem.getAsFileSystemHandle() returns a FileSystemDirectoryHandle for a dropped folder, which can be passed directly. Supporting drag-and-drop and file inputs in all browsers requires different APIs, though: DataTransferItem.webkitGetAsEntry() gives a FileSystemDirectoryEntry, and <input webkitdirectory> gives a flat FileList, neither of which will work with this store.

I'd rather keep this PR focused on FileSystemDirectoryHandle (OPFS, directory picker, Chromium drag-and-drop; hence the store name). That said, I think it would be really useful to also add a small read-only store over a FileList/File[] in a follow-up, which would cover file inputs and dropped folders with their files collected into a list.

Individual zip files should already work via ZipFileStore.fromBlob(file).

@aganders3

Copy link
Copy Markdown
Contributor

Thanks! We actually dropped our support in Idetik, so I would definitely be happy to see this move forward.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants