Files
skills/docs/persistence/storage/storage-browser-indexeddb/README.md
2026-05-29 08:20:56 +01:00

94 lines
8.0 KiB
Markdown

# @suaveplan/storage-browser-indexeddb - Browser IndexedDB AbstractStorage adapter for @suaveplan/storage: structured-clone key-value storage via globalThis.indexedDB, AbortSignal everywhere, strict key sanitisation, TTL via expiresAt index, metadata storage, partial reads, DOMException → typed IndexedDbError mapping, full OTel surface.
Browser-tier `AbstractStorage` adapter backed by the W3C IndexedDB API (`globalThis.indexedDB`). Provides persistent, origin-scoped key-value storage for browser consumers — vault snapshots, drive chunk caches, in-app i18n catalogues, password manager records — with full `AbstractStorage` conformance, TTL via an `expiresAt` index, AbortSignal threading, strict key sanitisation, Zod-validated options, structured `IndexedDbError` boundary, DOMException → typed-code mapping, and a complete OpenTelemetry surface.
<!-- begin:auto-docs -->
## Documentation tree
- [error-codes](./src/error-codes/error-codes.md) — <!-- begin:auto-docs --> _(no submodules)_ <!-- end:auto-docs -->
- [error-codes](./src/error-codes/error-codes.md) — <!-- begin:auto-docs --> _(no submodules)_ <!-- end:auto-docs -->
- [idb-adapter](./src/idb-adapter/idb-adapter.md) — <!-- begin:auto-docs --> _(no submodules)_ <!-- end:auto-docs -->
- [idb-adapter](./src/idb-adapter/idb-adapter.md) — <!-- begin:auto-docs --> _(no submodules)_ <!-- end:auto-docs -->
- [indexeddb-storage](./src/indexeddb-storage/indexeddb-storage.md) — <!-- begin:auto-docs --> _(no submodules)_ <!-- end:auto-docs --> - indexeddb-storage.ops — This module owns the Promis…
- [indexeddb-storage.config](./src/indexeddb-storage/indexeddb-storage.config.md) — This module exposes the two building blocks every public method of `IndexedDbStorage` relies on: `resolveOptions` valid…
- [indexeddb-storage.crud](./src/indexeddb-storage/indexeddb-storage.crud.md) — This module hosts the pure CRUD primitives that `IndexedDbStorage` composes its public methods from. Splitting them out…
- [indexeddb-storage.errors](./src/indexeddb-storage/indexeddb-storage.errors.md) — This module concentrates the DOMException-to-`IndexedDbError` translation that the `IndexedDbStorage` class relies on.…
- [indexeddb-storage](./src/indexeddb-storage/indexeddb-storage.md) — <!-- begin:auto-docs --> _(no submodules)_ <!-- end:auto-docs --> - indexeddb-storage.ops — This module owns the Promis…
- [indexeddb-storage.ops](./src/indexeddb-storage/indexeddb-storage.ops.md) — This module owns the Promise-bridging glue around the callback-shaped `IDBRequest` and `IDBTransaction` APIs. Separatin…
- [key-sanitizer](./src/key-sanitizer/key-sanitizer.md) — <!-- begin:auto-docs --> _(no submodules)_ <!-- end:auto-docs -->
- [key-sanitizer](./src/key-sanitizer/key-sanitizer.md) — <!-- begin:auto-docs --> _(no submodules)_ <!-- end:auto-docs -->
- [otel](./src/otel/otel.md) — <!-- begin:auto-docs --> _(no submodules)_ <!-- end:auto-docs -->
- [otel](./src/otel/otel.md) — <!-- begin:auto-docs --> _(no submodules)_ <!-- end:auto-docs -->
- [registry](./src/registry/registry.md) — <!-- begin:auto-docs --> _(no submodules)_ <!-- end:auto-docs -->
- [registry](./src/registry/registry.md) — <!-- begin:auto-docs --> _(no submodules)_ <!-- end:auto-docs -->
<!-- end:auto-docs -->
- [error-codes](./src/error-codes/error-codes.md) — <!-- begin:auto-docs --> _(no submodules)_- [idb-adapter](./src/idb-adapter/idb-adapter.md) — <!-- begin:auto-docs --> _(no submodules)_ - [idb-adapter](./src/idb-adapter/idb-adapter.md) — <!-- begin:auto-docs --> _(no submodules)_- [indexeddb-storage](./src/indexeddb-storage/indexeddb-storage.md) — <!-- begin:auto-docs --> _(no submodules)_ - [indexeddb-storage.config](./src/indexeddb-storage/indexeddb-storage.config.md) — This module exposes the two building blocks every public method of `IndexedDbStorage` relies on: `resolveOptions` valid…
- [indexeddb-storage.crud](./src/indexeddb-storage/indexeddb-storage.crud.md) — This module hosts the pure CRUD primitives that `IndexedDbStorage` composes its public methods from. Splitting them out…
- [indexeddb-storage.errors](./src/indexeddb-storage/indexeddb-storage.errors.md) — This module concentrates the DOMException-to-`IndexedDbError` translation that the `IndexedDbStorage` class relies on.…
- [indexeddb-storage](./src/indexeddb-storage/indexeddb-storage.md) — <!-- begin:auto-docs --> _(no submodules)_ - [indexeddb-storage.ops](./src/indexeddb-storage/indexeddb-storage.ops.md) — This module owns the Promise-bridging glue around the callback-shaped `IDBRequest` and `IDBTransaction` APIs. Separatin…
- [key-sanitizer](./src/key-sanitizer/key-sanitizer.md) — <!-- begin:auto-docs --> _(no submodules)_ - [key-sanitizer](./src/key-sanitizer/key-sanitizer.md) — <!-- begin:auto-docs --> _(no submodules)_- [otel](./src/otel/otel.md) — <!-- begin:auto-docs --> _(no submodules)_ - [otel](./src/otel/otel.md) — <!-- begin:auto-docs --> _(no submodules)_- [registry](./src/registry/registry.md) — <!-- begin:auto-docs --> _(no submodules)_ - [registry](./src/registry/registry.md) — <!-- begin:auto-docs --> _(no submodules)_
## Install
```bash
bun add @suaveplan/storage-browser-indexeddb
```
## Quick start
```ts
import {
createIndexedDbStorage,
isIndexedDbAvailable,
} from "@suaveplan/storage-browser-indexeddb";
if (!isIndexedDbAvailable()) {
throw new Error("This browser does not support IndexedDB");
}
const storage = createIndexedDbStorage({ dbName: "myapp" });
await storage.set("user/42", new TextEncoder().encode("hello"));
const back = await storage.get("user/42");
```
## Factory integration
```ts
import { registerIndexedDbProvider } from "@suaveplan/storage-browser-indexeddb/registry";
import { createStorage } from "@suaveplan/storage/factory";
registerIndexedDbProvider();
const storage = createStorage({ type: "indexeddb", config: { dbName: "myapp" } });
```
The package does NOT self-register at module-evaluation time — call `registerIndexedDbProvider()` explicitly so `sideEffects: false` bundlers can tree-shake the factory path when not used.
## Capabilities
| Capability | Value | Notes |
|---|---|---|
| `partialReads` | `true` | Via `Uint8Array.subarray(...)` on the in-memory copy of the stored row. |
| `partialWrites` | `false` | IndexedDB has no random-access put; `setPartial` uses the `AbstractStorage` read-modify-write fallback. |
| `nativeStreams` | `false` | IndexedDB has no native streaming surface; `createReadStream` / `createWriteStream` use the buffered fallback. |
| `atomicWrites` | `true` | Each `objectStore.put` is a single-transaction commit. |
| `contentAddressable` | `false` | Keys are caller-supplied strings. |
## Modules
- [`src/error-codes/error-codes.ts`](./src/error-codes/error-codes.md) — `INDEXEDDB_CODES` registry + `IndexedDbError`.
- [`src/key-sanitizer/key-sanitizer.ts`](./src/key-sanitizer/key-sanitizer.md) — strict key boundary.
- [`src/idb-adapter/idb-adapter.ts`](./src/idb-adapter/idb-adapter.md) — `defaultIndexedDB()` + `isIndexedDbAvailable()`.
- [`src/indexeddb-storage/indexeddb-storage.ts`](./src/indexeddb-storage/indexeddb-storage.md) — the `IndexedDbStorage` class.
- [`src/indexeddb-storage/indexeddb-storage.config.ts`](./src/indexeddb-storage/indexeddb-storage.config.md) — option resolver + OTel wrapper.
- [`src/indexeddb-storage/indexeddb-storage.crud.ts`](./src/indexeddb-storage/indexeddb-storage.crud.md) — CRUD primitives.
- [`src/indexeddb-storage/indexeddb-storage.errors.ts`](./src/indexeddb-storage/indexeddb-storage.errors.md) — DOMException mapping.
- [`src/indexeddb-storage/indexeddb-storage.ops.ts`](./src/indexeddb-storage/indexeddb-storage.ops.md) — transaction + open + cursor helpers.
- [`src/otel/otel.ts`](./src/otel/otel.md) — OpenTelemetry instrument set.
- [`src/registry/registry.ts`](./src/registry/registry.md) — `registerIndexedDbProvider()`.
- [`src/types/idb-like.types.ts`](./src/types/idb-like.types.md) — structural IndexedDB surface.
- [`src/types/indexeddb-storage.types.ts`](./src/types/indexeddb-storage.types.md) — option boundary.
## License
MIT.