DeutschGitHub
prototypepackages/state-store/src

State Store

@ralphschuler/state-store

Owns state snapshots and exposes explicit updates and disposable subscriptions.

storeproxysubscriptions

01 · Problem

What is it for?

Unrestricted mutable objects hide who changed a value and when listeners should run.

02 · Mental model

How should you think about it?

A store owns its state. Updates pass through a deliberate pipeline and subscriptions have explicit disposal.

In this repository

Owns state snapshots and exposes explicit updates and disposable subscriptions. State values must be structured-cloneable. Nested changes require an explicit set; proxy-reserved names cannot be state keys.

03 · Control flow

What happens in which order?

  1. Own an initial state copy.
  2. Transform the proposed change through interceptors.
  3. Run middleware.
  4. Commit the change.
  5. Notify a snapshot of listeners.

04 · Building blocks

The important contracts

createStateStore / StateStoreConstruct a store that owns its state.
set / snapshotUpdate explicitly and read independent copies.
subscribeObserve one property and return an unsubscribe function.

05 · Build it yourself

Implement a small core

Start with this small independent implementation, then use the steps below to make its contract explicit.

  1. Own an initial state copy.
  2. Transform the proposed change through interceptors.
  3. Run middleware.
  4. Commit the change.
  5. Notify a snapshot of listeners.
Concept sketch · may reference omitted helpers
class Store<S extends object> {
  private listeners = new Set<(state: Readonly<S>) => void>();

  constructor(private state: S) {}
  get() { return this.state as Readonly<S>; }
  set(update: Partial<S>) {
    this.state = { ...this.state, ...update };
    for (const listener of this.listeners) listener(this.state);
  }
  subscribe(listener: (state: Readonly<S>) => void) {
    this.listeners.add(listener);
    return () => this.listeners.delete(listener);
  }
}

06 · Verify

What should you test?

  • Ensure methods remain reachable through the proxy.
  • Unsubscribe one listener without affecting others.
  • Prevent consumers from mutating internal snapshots.

Try it yourself

Turn the first verification claim into a failing test, implement the smallest fix, then add a boundary case.

Ensure methods remain reachable through the proxy.

Compare your approach

Your check should fail when the stated invariant is deliberately broken, and pass again after the fix. Keep setup deterministic and assert an observable result.

07 · Limits

Trade-offs and failure modes

  • Shallow state needs explicit nested-update rules.
  • Function-valued data must not be confused with subscription registration.
  • Middleware must call next at most once.
Important

State values must be structured-cloneable. Nested changes require an explicit set; proxy-reserved names cannot be state keys.

08 · Keep exploring

Source code and related ideas

yarn tsx packages/state-store/examples/basic.ts