跳到主要内容
For AI agents: a documentation index is available at /llms.txt

Persist Plugin

doura-plugin-persist saves named model state to storage and rehydrates it when the store starts.

Setup

import { doura } from 'doura'
import persist, { createWebStorage } from 'doura-plugin-persist'

const store = doura({
plugins: [
[
persist,
{
key: 'my-app',
storage: createWebStorage('local'),
},
],
],
})

createWebStorage('local') wraps localStorage; createWebStorage('session') wraps sessionStorage. Both return the async storage interface expected by the plugin.

Options

interface PersistOptions {
storage: Storage
key: string
blacklist?: string[]
whitelist?: string[]
throttle?: number
version?: number
migrate?: <S = any>(persistedState: S, version: number) => S | Promise<S>
writeFailHandler?: (err: Error) => void
}

Whitelist / Blacklist

Persist only selected model names with whitelist:

const store = doura({
plugins: [
[
persist,
{
key: 'my-app',
storage: createWebStorage('local'),
whitelist: ['user', 'settings'],
},
],
],
})

Persist everything except selected model names with blacklist:

const store = doura({
plugins: [
[
persist,
{
key: 'my-app',
storage: createWebStorage('local'),
blacklist: ['ephemeral'],
},
],
],
})

Only one of whitelist or blacklist should be used.

Rehydration Status

The plugin exports persistModel, a detached control model initialized by the plugin. Use it to gate rendering until storage has loaded.

import { useModel } from 'react-doura'
import { persistModel } from 'doura-plugin-persist'

function App() {
const persist = useModel(persistModel)

if (!persist.rehydrated) {
return <div>Loading...</div>
}

return <MainApp />
}

persistModel state:

  • rehydrated: boolean
  • version: number

Schema Migration

Use version and migrate to transform older persisted state.

const store = doura({
plugins: [
[
persist,
{
key: 'my-app',
storage: createWebStorage('local'),
version: 2,
migrate(storageState, version) {
if (version < 2) {
const user = storageState.user
if (user?.fullName) {
const [firstName, lastName] = user.fullName.split(' ')
user.firstName = firstName
user.lastName = lastName
delete user.fullName
}
}
return storageState
},
},
],
],
})

The migration receives the stored state object keyed by model name and the stored version. It may return the migrated state or a promise for it.

Throttling Writes

const store = doura({
plugins: [
[
persist,
{
key: 'my-app',
storage: createWebStorage('local'),
throttle: 1000,
},
],
],
})

Custom Storage

Any object implementing Storage can be used:

import type { Storage } from 'doura-plugin-persist'

const customStorage: Storage = {
async getItem(key) {
return readFromBackend(key)
},
async setItem(key, value) {
await writeToBackend(key, value)
},
async removeItem(key) {
await deleteFromBackend(key)
},
}

const store = doura({
plugins: [[persist, { key: 'my-app', storage: customStorage }]],
})

Runtime Controls

persistModel exposes actions for runtime control:

import { persistModel } from 'doura-plugin-persist'

const persist = store.getModel(persistModel)

persist.togglePause()
await persist.flush()
await persist.purge()
  • togglePause() pauses or resumes writes.
  • flush() writes pending changes immediately.
  • purge() removes persisted storage for the configured key.

Write Failures

const store = doura({
plugins: [
[
persist,
{
key: 'my-app',
storage: createWebStorage('local'),
writeFailHandler(error) {
console.error('Persistence write failed:', error)
},
},
],
],
})