Indexed Db
Opens one IndexedDB connection and builds a handle for each store definition (createIndexedDbStorage or createIndexedDbTable).
createIndexedDb()
Opens one IndexedDB connection and builds a handle for each store definition
(createIndexedDbStorage or createIndexedDbTable). Missing stores/indexes
are created automatically; concurrent opens of the same name are serialized.
version is a minimum, not a pin: adding a store or an index bumps it on its
own, so set it only when existing rows need migrating. Bump it, then rewrite
the rows with migrate in onUpgrade, which runs inside the versionchange
transaction after the declared stores and indexes are created. Everything
there is synchronous — migrate queues a cursor walk instead of returning a
promise, and onUpgrade cannot be async.
migrate rewrites fields, not keys: changing the keyPath field of a row
aborts the upgrade. Indexes are created and filled before onUpgrade runs,
so a migration cannot clean up rows for a unique index added in the same
version — add the index in a later version than the cleanup. A failed
upgrade rolls back whole and is reported with console.warn: ready still
resolves, but reads and writes then reject, because every access retries the
same failing upgrade.
Every write is one transaction, and only one. A single put, delete, set
or clear call opens a readwrite transaction and queues all of its rows or
keys on it, so a batch lands whole or not at all; two calls are two
transactions, and none of them spans stores. Reads work the same way: each
one is its own readonly snapshot.
Examples
Vanilla
import { , , } from 'seitu/web'
import * as from 'zod'
const = ({
: 'app',
: {
: ({
: { : .(['light', 'dark']) },
: { : 'light' },
}),
: ({
: 'id',
: { : 'status' },
: .({ : .(), : .(), : .(['open', 'done']) }),
}),
},
})
const { , } = .
.() // { theme: 'light' } until hydrated
await .
await .({ : '1', : 'Write docs', : 'open' })Migrations
import { , } from 'seitu/web'
import * as from 'zod'
const = ({
: 'app',
: 2, // v1 rows have no `priority`
: {
: ({
: 'id',
: { : 'priority' },
: .({ : .(), : .(), : .() }),
}),
},
: ({ , }) => {
if ( < 2) {
('todos', => ({ ..., : . ?? 0 }))
// Return `null` to drop a row, nothing to keep it as is.
}
},
})
await .Transactions
import { , , } from 'seitu/web'
import * as from 'zod'
const = ({
: 'app',
: {
: ({
: { : .(), : .() },
: { : 0, : 0 },
}),
: ({
: 'id',
: .({ : .(), : .(), : .(['open', 'done']) }),
}),
},
})
const { , } = .
// One `readwrite` transaction: both rows land, or neither does.
await .([
{ : '1', : 'Write docs', : 'done' },
{ : '2', : 'Ship docs', : 'open' },
])
await .(['1', '2'])
await .({ : .(), : 0 })
await .({ : '3', : 'Reconcile', : 'open' })
await .({ : 1 })createIndexedDbStorage()
Key/value store for createIndexedDb({ stores }). get() reads an
in-memory cache hydrated from IndexedDB (await db.ready). set/clear
update the cache now and persist later. SSR snapshot is defaultValues.
Examples
Vanilla
import { , } from 'seitu/web'
import * as from 'zod'
const = ({
: 'app',
: {
: ({
: {
: .().(),
: .({ : .(['light', 'dark']) }),
},
: { : null, : { : 'light' } },
}),
},
})
const { } = .
.()
await .
await .({ : 'abc' })
.() // { token: 'abc', preferences: { theme: 'light' } }
.(.)React
'use client'
import { , } from 'seitu/web'
import { } from 'seitu/react'
import * as from 'zod'
const = ({
: 'app',
: {
: ({
: { : .(), : .() },
: { : 0, : '' },
}),
},
})
export default function () {
const = (..)
return (
<>
<>{.}</>
<>{.}</>
</>
)
}createIndexedDbTable()
Row store for createIndexedDb({ stores }): keyed rows, indexes, range
reads, validation. Use query() for a Readable/Subscribable that
re-runs on table changes. On the server, queries stay on initial.
Key paths must name a schema field that can hold a key, and reads are typed
from that field. Compound (['id', 'order']) and nested ('meta.slug')
paths fall back to IDBValidKey.
Examples
Vanilla
import { , } from 'seitu/web'
import * as from 'zod'
const = ({
: 'app',
: {
: ({
: 'id',
: { : 'status' },
: .({ : .(), : .(), : .(['open', 'done']) }),
}),
},
})
const { } = .
await .({ : '1', : 'Write docs', : 'open' })
await .('1')
await .()
await .('status').('open') // index names and keys are typed
await .('1')
const = .( => .('status').('open'), { : [] })
.()
.( => .())React
'use client'
import { , } from 'seitu/web'
import { } from 'seitu/react'
import * as from 'zod'
const = ({
: 'app',
: {
: ({
: 'id',
: .({ : .(), : .(), : .(['open', 'done']) }),
}),
},
})
const = ...( => .(), { : [] })
export default function () {
const = ()
return (
<>
{.( => < ={.}>{.}</>)}
</>
)
}Last updated on