# @suaveplan/storage-browser-opfs - Browser OPFS AbstractStorage adapter for @suaveplan/storage: origin-scoped persistent file storage via navigator.storage.getDirectory(), AbortSignal everywhere, strict key sanitisation, native Web Streams, native partial reads + partial writes, DOMException → typed OpfsError mapping, full OTel surface. Browser-tier `AbstractStorage` adapter backed by the Origin Private File System (OPFS). Provides persistent, origin-scoped key-value storage for browser consumers (vault snapshots, drive chunk caches, in-app i18n catalogues, SQLite-WASM backing files), with full `AbstractStorage` conformance, native Web Streams, native partial reads + partial writes, AbortSignal threading, Zod-validated options, structured `OpfsError` boundary, and a complete OpenTelemetry surface. ## Documentation tree - [filename-codec](./src/filename-codec/filename-codec.md) — _(no submodules)_ - [filename-codec](./src/filename-codec/filename-codec.md) — _(no submodules)_ - [in-memory-opfs](./src/in-memory-opfs/in-memory-opfs.md) — _(no submodules)_ - [in-memory-opfs](./src/in-memory-opfs/in-memory-opfs.md) — _(no submodules)_ - [key-sanitizer](./src/key-sanitizer/key-sanitizer.md) — _(no submodules)_ - [key-sanitizer](./src/key-sanitizer/key-sanitizer.md) — _(no submodules)_ - [opfs-adapter](./src/opfs-adapter/opfs-adapter.md) — _(no submodules)_ - [opfs-adapter](./src/opfs-adapter/opfs-adapter.md) — _(no submodules)_ - [opfs-storage](./src/opfs-storage/opfs-storage.md) — _(no submodules)_ - opfs-storage.ops — Hosts pure / nearly-pure helpers… - [opfs-storage.errors](./src/opfs-storage/opfs-storage.errors.md) — Encapsulates the mapping between WHATWG `DOMException` shapes thrown by the OPFS API and the typed `OpfsError` codes th… - [opfs-storage](./src/opfs-storage/opfs-storage.md) — _(no submodules)_ - opfs-storage.ops — Hosts pure / nearly-pure helpers… - [opfs-storage.ops](./src/opfs-storage/opfs-storage.ops.md) — Hosts pure / nearly-pure helpers that `OpfsStorage` calls but that would push the class file over the 300-line hard bud… - [opfs-storage.streams](./src/opfs-storage/opfs-storage.streams.md) — Factors the `createReadStream` / `createWriteStream` builders out of the main `OpfsStorage` class so the class stays un… - [otel](./src/otel/otel.md) — _(no submodules)_ - [otel](./src/otel/otel.md) — _(no submodules)_ - [registry](./src/registry/registry.md) — _(no submodules)_ - [registry](./src/registry/registry.md) — _(no submodules)_ - [error-codes](./src/error-codes.md) — Single source of truth for every error code the `@suaveplan/storage-browser-opfs` package can throw. The registry uses… - [filename-codec](./src/filename-codec/filename-codec.md) — _(no submodules)_- [in-memory-opfs](./src/in-memory-opfs/in-memory-opfs.md) — _(no submodules)_ - [in-memory-opfs](./src/in-memory-opfs/in-memory-opfs.md) — _(no submodules)_- [key-sanitizer](./src/key-sanitizer/key-sanitizer.md) — _(no submodules)_ - [key-sanitizer](./src/key-sanitizer/key-sanitizer.md) — _(no submodules)_- [opfs-adapter](./src/opfs-adapter/opfs-adapter.md) — _(no submodules)_ - [opfs-adapter](./src/opfs-adapter/opfs-adapter.md) — _(no submodules)_- [opfs-storage](./src/opfs-storage/opfs-storage.md) — _(no submodules)_ - [opfs-storage.errors](./src/opfs-storage/opfs-storage.errors.md) — Encapsulates the mapping between WHATWG `DOMException` shapes thrown by the OPFS API and the typed `OpfsError` codes th… - [opfs-storage](./src/opfs-storage/opfs-storage.md) — _(no submodules)_ - [opfs-storage.ops](./src/opfs-storage/opfs-storage.ops.md) — Hosts pure / nearly-pure helpers that `OpfsStorage` calls but that would push the class file over the 300-line hard bud… - [opfs-storage.streams](./src/opfs-storage/opfs-storage.streams.md) — Factors the `createReadStream` / `createWriteStream` builders out of the main `OpfsStorage` class so the class stays un… - [otel](./src/otel/otel.md) — _(no submodules)_ - [otel](./src/otel/otel.md) — _(no submodules)_- [registry](./src/registry/registry.md) — _(no submodules)_ - [registry](./src/registry/registry.md) — _(no submodules)_- [error-codes](./src/error-codes.md) — Single source of truth for every error code the `@suaveplan/storage-browser-opfs` package can throw. The registry uses… ## Install ```bash bun add @suaveplan/storage-browser-opfs ``` ## Quick start ```ts import { createOpfsStorage, isOpfsAvailable, } from "@suaveplan/storage-browser-opfs"; if (!isOpfsAvailable()) { throw new Error("This browser does not support OPFS"); } const storage = createOpfsStorage({ directory: "myapp" }); await storage.set("user/42", new TextEncoder().encode("hello")); const back = await storage.get("user/42"); ``` ## Factory integration ```ts import { registerOpfsProvider } from "@suaveplan/storage-browser-opfs/registry"; import { createStorage } from "@suaveplan/storage/factory"; registerOpfsProvider(); const storage = createStorage({ type: "opfs", config: { directory: "myapp" } }); ``` The package does NOT self-register at module-evaluation time — call `registerOpfsProvider()` explicitly so `sideEffects: false` bundlers can tree-shake the factory path when not used. ## Capabilities | Capability | Value | Notes | |---|---|---| | `partialReads` | `true` | Via `File.slice(...).arrayBuffer()`. | | `partialWrites` | `true` | Via `FileSystemWritableFileStream.seek()`. | | `nativeStreams` | `true` | `File.stream()` for read; buffered close-on-commit for write. | | `atomicWrites` | `false` | Close-as-commit semantics within a single realm; no cross-realm locking. | | `contentAddressable` | `false` | Keys are caller-supplied strings. | ## Modules - [`src/error-codes.ts`](./src/error-codes.md) — `OPFS_CODES` registry + `OpfsError`. - [`src/key-sanitizer/key-sanitizer.ts`](./src/key-sanitizer/key-sanitizer.md) — strict key boundary. - [`src/filename-codec/filename-codec.ts`](./src/filename-codec/filename-codec.md) — caller-key ↔ OPFS-filename round-trip. - [`src/opfs-adapter/opfs-adapter.ts`](./src/opfs-adapter/opfs-adapter.md) — `defaultOpfs()` + `isOpfsAvailable()`. - [`src/opfs-storage/opfs-storage.ts`](./src/opfs-storage/opfs-storage.md) — the `OpfsStorage` class. - [`src/opfs-storage/opfs-storage.errors.ts`](./src/opfs-storage/opfs-storage.errors.md) — DOMException mapping. - [`src/opfs-storage/opfs-storage.ops.ts`](./src/opfs-storage/opfs-storage.ops.md) — internal helpers. - [`src/opfs-storage/opfs-storage.streams.ts`](./src/opfs-storage/opfs-storage.streams.md) — `ReadableStream`/`WritableStream` builders. - [`src/otel/otel.ts`](./src/otel/otel.md) — OpenTelemetry instrument set. - [`src/registry/registry.ts`](./src/registry/registry.md) — `registerOpfsProvider()`. - [`src/in-memory-opfs/in-memory-opfs.ts`](./src/in-memory-opfs/in-memory-opfs.md) — real-implementation test double, exposed under `./in-memory-opfs` for downstream test packages. - [`src/types/opfs-like.types.ts`](./src/types/opfs-like.types.md) — structural OPFS surface. - [`src/types/opfs-storage.types.ts`](./src/types/opfs-storage.types.md) — option boundary. ## License MIT.