ProvenPin Install

Zustand 5 store with persist middleware, tested with Vitest: working versions (tested 2026-10-15)

A typed Zustand 5 vanilla store with actions, derived selectors and persist middleware on a custom storage, tested with Vitest including state reset between tests.

passed4 passed · 0 failed2026-10-15 11:57 UTC
Status
passed
Last passed
2026-10-15 11:57 UTC
Tests
4 / 4
Language
TypeScript
Runtime
node v22.23.3
pinned versions3
zustand@5.0.15@types/node@24.19.2vitest@5.0.4
run it
npm install --no-audit --no-fund --ignore-scripts=false
npm test
test environment
node v22.23.3
linux 6.17.0-1022-azure
x64
runner: github-actions 38730348195

The code

Exactly the files that passed. Your agent can pull them with get_recipe("zustand-store-vitest") (install), or see them on GitHub.

package.json
{
  "name": "zustand-store-vitest",
  "private": true,
  "type": "module",
  "scripts": {
    "test": "vitest run --reporter=default --reporter=json --outputFile=test-report.json"
  },
  "dependencies": {
    "zustand": "5.0.15"
  },
  "devDependencies": {
    "@types/node": "24.19.2",
    "vitest": "5.0.4"
  }
}
src/cart.ts
import { createStore } from "zustand/vanilla";
import { persist, createJSONStorage, type StateStorage } from "zustand/middleware";

export type Item = { sku: string; price: number; qty: number };
type CartState = {
  items: Item[];
  add: (sku: string, price: number) => void;
  remove: (sku: string) => void;
  clear: () => void;
};

export const total = (s: Pick<CartState, "items">) => s.items.reduce((n, i) => n + i.price * i.qty, 0);

// Use createStore for logic/tests; in React wrap it with useStore(store, selector).
export function createCartStore(storage: StateStorage) {
  return createStore<CartState>()(persist((set) => ({
    items: [],
    add: (sku, price) => set((s) => {
      const hit = s.items.find((i) => i.sku === sku);
      return { items: hit ? s.items.map((i) => (i.sku === sku ? { ...i, qty: i.qty + 1 } : i)) : [...s.items, { sku, price, qty: 1 }] };
    }),
    remove: (sku) => set((s) => ({ items: s.items.filter((i) => i.sku !== sku) })),
    clear: () => set({ items: [] }),
  }), { name: "cart", storage: createJSONStorage(() => storage), partialize: (s) => ({ items: s.items }) }));
}
test/cart.test.ts
import { describe, it, expect, beforeEach } from "vitest";
import type { StateStorage } from "zustand/middleware";
import { createCartStore, total } from "../src/cart";

let mem: Record<string, string>;
const storage: StateStorage = { getItem: (k) => mem[k] ?? null, setItem: (k, v) => { mem[k] = v; }, removeItem: (k) => { delete mem[k]; } };
beforeEach(() => { mem = {}; });

describe("cart store", () => {
  it("adds, merges quantities and totals", () => {
    const s = createCartStore(storage);
    s.getState().add("mug", 10); s.getState().add("mug", 10); s.getState().add("tee", 25);
    expect(s.getState().items).toEqual([{ sku: "mug", price: 10, qty: 2 }, { sku: "tee", price: 25, qty: 1 }]);
    expect(total(s.getState())).toBe(45);
  });

  it("persists only data, not actions", () => {
    const s = createCartStore(storage);
    s.getState().add("mug", 10);
    expect(JSON.parse(mem.cart)).toEqual({ state: { items: [{ sku: "mug", price: 10, qty: 1 }] }, version: 0 });
  });

  it("rehydrates from storage", () => {
    createCartStore(storage).getState().add("tee", 25);
    expect(createCartStore(storage).getState().items).toHaveLength(1);
  });

  it("notifies subscribers", () => {
    const s = createCartStore(storage);
    const seen: number[] = [];
    s.subscribe((st) => seen.push(st.items.length));
    s.getState().add("a", 1); s.getState().clear();
    expect(seen).toEqual([1, 0]);
  });
});

Connect to ProvenPin

Add the free MCP server so your agent can pull this recipe and others like it. Same setup as the docs.

terminal
claude mcp add --transport http provenpin https://mcp.provenpin.com/mcp

Any other MCP client: Streamable HTTP at https://mcp.provenpin.com/mcp. No API key, no signup.