Persistence API

QuantaJS persistence automatically saves and rehydrates store state with adapter-based storage.

Exports

import {
  createPersistenceManager,
  LocalStorageAdapter,
  SessionStorageAdapter,
  IndexedDBAdapter,
  MigrationManager,
  createMigrationManager,
  CommonMigrations,
} from '@quantajs/core';

PersistenceConfig<T>

interface PersistenceConfig<T = any> {
  adapter: PersistenceAdapter;
  serialize?: (data: any) => string;
  deserialize?: (data: string) => any;
  migrations?: Record<number, (data: any) => any>;
  version?: number;
  debounceMs?: number;
  include?: Array<keyof T>;
  exclude?: Array<keyof T>;
  transform?: {
    in?: (data: any) => any;
    out?: (data: any) => any;
  };
  onError?: (
    error: Error,
    operation: 'read' | 'write' | 'remove' | 'watch-setup'
  ) => void;
  validator?: (data: any) => boolean;
}

Adapter Classes

LocalStorageAdapter

const adapter = new LocalStorageAdapter('app-store');
  • Uses browser localStorage
  • Supports cross-tab sync through storage events

SessionStorageAdapter

const adapter = new SessionStorageAdapter('session-store');
  • Uses browser sessionStorage
  • Session-scoped persistence

IndexedDBAdapter

const adapter = new IndexedDBAdapter('store-key', 'app-db', 'stores', 1);
  • Async persistence for larger datasets
  • Better fit for high-volume/local-first workloads

Store-Level Usage

import { createStore, LocalStorageAdapter } from '@quantajs/core';

const userStore = createStore('user', {
  state: () => ({
    profile: null as null | { id: string; name: string },
    theme: 'light' as 'light' | 'dark',
  }),
  persist: {
    adapter: new LocalStorageAdapter('user-store-v1'),
    version: 1,
    include: ['profile', 'theme'],
    debounceMs: 250,
  },
});

Validation and Transform

persist: {
  adapter: new LocalStorageAdapter('settings-v2'),
  transform: {
    out: (data) => ({ ...data, savedAt: Date.now() }),
    in: (data) => ({ ...data, savedAt: undefined }),
  },
  validator: (data) => typeof data === 'object' && data !== null,
  onError(error, operation) {
    console.warn('Persistence error:', operation, error.message);
  },
}

Migrations

import { CommonMigrations } from '@quantajs/core';

persist: {
  adapter: new LocalStorageAdapter('app-store'),
  version: 3,
  migrations: {
    2: CommonMigrations.addProperty('featureFlags', {}),
    3: CommonMigrations.renameProperty('user', 'currentUser'),
  },
}

PersistenceManager

When persistence is enabled, stores expose store.$persist:

interface PersistenceManager {
  save(): Promise<void>;
  load(): Promise<void>;
  clear(): Promise<void>;
  getAdapter(): PersistenceAdapter;
  isRehydrated(): boolean;
  destroy(): void;
}

Behavior Notes

  • Rehydration is attempted automatically during store setup.
  • Invalid/malformed payloads are safely rejected and routed to onError.
  • Cross-tab sync behavior depends on adapter capabilities.
  • Call destroy() to clean up persistence watchers/listeners for disposed stores.