Skip to content

@stainless-code/persist

Hydration-aware persistence for any reactive store — zero-dep persistSource core; codecs, backends, cross-tab transport, source + framework hydration adapters ship as opt-in recipes

persist-pinia

63 linesSource

Persist a Pinia store instance with @stainless-code/persist (persistStore). Use when wiring Pinia option/setup stores to storage; hydrate applies via $state = (not $patch), with default shallow merge.

Persisting Pinia

@stainless-code/persist/sources/pinia maps a store instance onto persistSource. Hydrate applies via $state = (not $patch); default merge still shallow-spreads, so keys absent from the payload can remain. Subscribe uses $subscribe(…, { detached: true }) so the listener survives Vue effectScope stop.

When to use this skill

  • You have const store = useX() and want reload survival for option or setup stores.
  • You need Persist's gate / codecs / cross-tab instead of (or beside) pinia-plugin-persistedstate.

Install

shell
bun add @stainless-code/persist pinia

pinia is an optional peer of /sources/pinia (Vue app + createPinia() still required by Pinia).

Minimal wiring

ts
import { defineStore } from "pinia";
import { createJSONStorage } from "@stainless-code/persist";
import { persistStore } from "@stainless-code/persist/sources/pinia";

const usePrefs = defineStore("prefs", {
  state: () => ({ theme: "light" as const }),
});

const store = usePrefs(); // instance, after pinia is active
const persist = persistStore(store, {
  name: "app:prefs:v1",
  storage: createJSONStorage(() => localStorage),
});

Common mistakes

  • Passing defineStore(...) / the factory instead of usePrefs() instance.
  • Expecting $patch semantics on hydrate. Persist assigns $state after merge.
  • Name clash with Redux persistStore. Import from /sources/pinia (or alias).
  • Call before setActivePinia / app.use(pinia). Same as any Pinia store use.

API surface

  • persistStore(store, options) → PersistApi — store is a Pinia Store
  • Options / PersistApi: same as persistSource

See also: react-persist / Vue hydration adapters for UI gating on async backends.