@stainless-code/persist
Version:
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
76 lines (54 loc) • 2.48 kB
Markdown
---
name: persist-tanstack-store
description: Persist a @tanstack/store Store or writable Atom with @stainless-code/persist (persistStore/persistAtom). Use when wiring TanStack Store to storage, or choosing persistAtom replace-merge vs persistStore.
license: MIT
metadata:
type: composition
library: "@stainless-code/persist"
library_version: "0.4.1"
framework: "@tanstack/store"
requires:
- persist
sources:
- stainless-code/persist:src/adapters/sources/tanstack-store.ts
---
# Persisting TanStack Store
Thin adapters over `persistSource` — shared Options / gate / throttle / cross-tab live in skill `persist`.
`persistStore(store, options)` for `Store` (action-bearing included). `persistAtom(atom, options)` for a writable `Atom`.
## Install
```bash
bun add @stainless-code/persist @tanstack/store
# Set/Map/Date on string-wire backends:
bun add seroval
```
`@tanstack/store` is an optional peer of `/sources/tanstack-store`.
## Minimal wiring
```ts
import { Store } from "@tanstack/store";
import { createJSONStorage } from "@stainless-code/persist";
import { persistStore } from "@stainless-code/persist/sources/tanstack-store";
const store = new Store({ theme: "light" });
const persist = persistStore(store, {
name: "app:prefs:v1",
storage: createJSONStorage(() => localStorage),
});
```
`Set`/`Map`/`Date` → `createSerovalStorage` from `/codecs/seroval` (see `persist-seroval`).
Keep the `PersistApi` for `rehydrate()` / `destroy()` / `onHydrate` / `clearStorage()`. Non-singletons must `destroy()` on teardown.
## `persistAtom` vs `persistStore`
`persistAtom` only:
- **Default `merge` REPLACES** (`(persisted) => persisted`) — shallow-spreading a primitive corrupts it. Override uses `??`, so `merge: undefined` still replace-merges.
- **Throws on readonly atoms** — `"[persistAtom] Cannot persist a readonly atom."`
```ts
import { createAtom } from "@tanstack/store";
import { persistAtom } from "@stainless-code/persist/sources/tanstack-store";
const theme = createAtom<"light" | "dark">("light");
persistAtom(theme, { name: "app:theme:v1" });
```
## When to drop to `persistSource`
- No first-party adapter for the store shape.
- You need subscription timing without the adapter's opinions.
Zustand → `persist-zustand`. UI gate → `react-persist` (or other `*-persist`).
## API surface
- `persistStore(store, options) → PersistApi`
- `persistAtom(atom, options) → PersistApi` (writable only; replace-merge default)