Version v3.0.0 Size 0.8 KB gzip Dependencies Zero dependencies
Why Vault?
Vault gives browser and SQLite persistence one typed schema while keeping backend guarantees explicit. Use KeyValueVaultStore for portable CRUD and observation; choose IndexedDB or the opt-in SQLite subpath when you need atomic transactions or lazy iteration. Durable adapters require codecs so invalid stored data never enters typed code.
ts
// Before
localStorage.setItem('theme', JSON.stringify({ value: 'dark' }));
const theme = JSON.parse(localStorage.getItem('theme') ?? '{}').value;
// After
await store.put('preferences', { id: 'theme', value: 'dark' });
const theme = await store.get('preferences', 'theme');| Feature | Vault | Raw Web Storage | Dexie |
|---|---|---|---|
| Bundle size | 0.8 KB | Browser built-in | Extra dependency |
| Runtime dependencies | |||
| Typed schema and keys | Application-defined | ||
| Portable key-value store API | IndexedDB only | ||
| Explicit atomic transactions | IndexedDB + SQLite capability | ||
| Required durable codecs | |||
| Driver-neutral SQLite | Opt-in subpath |
Use Vault when you need typed browser persistence or application-owned SQLite with honest storage capabilities and required durable codecs.
Consider raw Web Storage when you only persist one or two unstructured values. Consider Dexie when you need a broader IndexedDB ecosystem.
Installation
sh
pnpm add @vielzeug/vaultsh
npm install @vielzeug/vaultsh
yarn add @vielzeug/vaultQuick Start
Define a schema, create a key-value store with codecs, and dispose it with its owner.
ts
import { s } from '@vielzeug/spell';
import { table } from '@vielzeug/vault';
import { createLocalStorage } from '@vielzeug/vault/local-storage';
const PreferenceSchema = s.object({ id: s.string(), theme: s.union('dark', 'light') });
const store = createLocalStorage({
name: 'app-v2',
schema: { preferences: table<{ id: string; theme: 'dark' | 'light' }>('id') },
codecs: { preferences: PreferenceSchema },
});
try {
await store.put('preferences', { id: 'theme', theme: 'dark' });
console.log(await store.get('preferences', 'theme'));
} finally {
await store.dispose();
}Features
table()defines typed records with portable string or number keys.- Spell and other parser schemas work directly as codecs;
validatorCodec()creates an explicit identity-encoding codec. /memoryreturns a portableKeyValueVaultStore— codecs optional (in-memory, no trust boundary)./local-storageand/session-storagereturnKeyValueVaultStore— codecs required.observe()emits current and changed table snapshots.ttlcreates validated expiration durations./indexeddband/sqlitereturnDocumentVaultStorewithbatch()anditerate()— codecs required./indexeddbalso exportsdefineMigration()for schema upgrades.pruneExpired()removes stale TTL entries on demand.- Common helpers are bound to stores and transaction contexts; standalone forms remain exported.
query()provides typed filtering, ordering, pagination, counting, first-match, and deletion.