Skip to content

API reference > @kontsedal/olas-persist

olas-persist package ​

Functions ​

Function

Description

clearPersisted(storage, options)

Clear persisted keys. Useful for "log out" flows that want to drop stored state without enumerating consumers. Errors — quota, security exceptions on delete — are routed through the optional onError; a failed enumeration reports under the key '<keys>'.

Scope is never implicit: pass a prefix, or pass all: true to accept that everything the adapter can see goes. With neither, it throws.

ts
await clearPersisted(localStorageAdapter(), { prefix: 'my-app/' })
await clearPersisted(sessionAdapter, { all: true })

An adapter without keys() cannot be enumerated, so the call reports'<keys>' through onError and deletes nothing.

createPersisted(ctx, key, source, options)

Persist a signal-like source under key. Loads the stored value on construction (sync for localStorage, async for any storage that returns a promise). Subsequent writes to the source are mirrored to storage.

Cleanup (unsubscribe + cross-tab listener removal) is bound to ctx.

indexedDbAdapter(options)

IndexedDB-backed StorageAdapter. Async on every operation; cross-tab change notifications layered via BroadcastChannel in a browser (IDB has no native change event, so external IDB writes by code that doesn't go through this adapter are *not* observed). When no IDBFactory is available (SSR, restricted environments), every method resolves to a no-op.

Storage is a single key/value object store inside a single database; fine for the persisted-signal use case createPersisted is built around. For larger or schema-shaped data, write a custom adapter against your own IDB layout.

localStorageAdapter()

The browser's localStorage, as a StorageAdapter — the default storage. SSR-safe: without localStorage every read is null and every write a no-op. A localStorage that throws when the page reads it, as in a sandboxed iframe, counts as missing. A factory, like indexedDbAdapter(), so both adapters are chosen the same way.

persistQueryCachePlugin(options)

Persist the query cache across reloads. The plugin stores each opted-in entry's server truth, throttled, and restores the stored cache when the root starts. Server truth is what dehydrate() would ship: while an optimistic write is live, the data beneath it, so a guess is never stored, whichever write carried it, and a committed one is. An entry the cache garbage-collects is dropped from storage too.

ts
const user = defineQuery({ id: 'user', key: () => [], fetcher, meta: { persist: true } })

createRoot(app, { deps, queries: queryEngine(), plugins: [persistQueryCachePlugin()] })

With synchronous storage (the default, localStorage) the restore happens during setup, before any controller subscribes, so a restored entry is there on the first read. With asynchronous storage the restore lands later. It fills only entries nothing has subscribed to yet, and never overwrites one a fetch is already filling. root.waitForIdle() waits for it. AwaitrestoreQueryCache before createRoot instead when the first render must see the restored data.

Every storage write carries the whole cache, and every tab of the app writes the same key. So each write reads what storage holds first and merges this session's writes into it. An entry this session never binds stays in storage until it passes maxAgeMs, and so does an entry another tab wrote. When both hold a copy of one entry, the one with the newerlastUpdatedAt is kept. A read that fails holds the write: the next write reads storage again, and writes once a read lands. A session whose reads all fail writes nothing, because its write would delete the entries it could not read.

The read and the write are two steps, not one transaction. Two tabs that write in the same moment can each miss the other's newest entry. The next write of the tab that lost it puts it back, since each write carries every entry its tab wrote.

restoreQueryCache(options)

Read the stored cache ahead of createRoot, for storage that reads asynchronously (IndexedDB). Resolves with a DehydratedState forcreateRoot({ hydrate }), or undefined when there is nothing to restore.

ts
const storage = indexedDbAdapter()
const hydrate = await restoreQueryCache({ storage })
const root = createRoot(app, {
  deps,
  queries: queryEngine(),
  hydrate,
  plugins: [persistQueryCachePlugin({ storage, restore: false })],
})

Variables ​

Variable

Description

PERSIST_QUERY_CACHE_PLUGIN_NAME

The plugin's name.

Type Aliases ​

Type Alias

Description

ClearPersistedOptions

Options for clearPersisted(storage?, options). Pass a non-empty prefix, or all: true. With neither, the call throws.

IndexedDbAdapterOptions

Configuration for indexedDbAdapter. All fields optional; sane defaults picked for typical app use.

PersistableSource

What createPersisted can persist: anything with value, set andsubscribe, such as a Signal<T> or a Field<T>. subscribe may call the handler at once with the current value, or only on a change.

Persisted

What createPersisted returns.

PersistErrorOp

Where a PersistOptions.onError fired. Distinguishes the failing operation for routing (e.g. quota-exceeded vs schema-migration-failed vs deserialization-corrupted).

PersistOptions

Options for createPersisted(ctx, key, source, options?).

PersistQueryCacheOptions

Options for persistQueryCachePlugin and restoreQueryCache.

QueryCacheErrorOp

Where a persistQueryCachePlugin error came from.

StorageAdapter

A key-value storage backend. get, set and delete may be synchronous (localStorage) or return promises (IndexedDB). Shared by createPersisted,persistQueryCache and @kontsedal/olas-mutation-queue.

Released under the MIT License.