state

package
v2.2.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Aug 17, 2026 License: AGPL-3.0 Imports: 11 Imported by: 0

Documentation

Overview

Package state provides stores, signals, computed values and watchers.

Concurrency contract: Store and Signal are safe for concurrent use, so background goroutines (tickers, feeds, host pushes) may call Set/Get directly. Listeners, watchers and dependent effects run synchronously on the goroutine that performed the Set, outside internal locks, so they may call back into the store or signal. Two things are deliberately not parallel-safe: computed functions run under the store lock and must only read the state map they receive, and signal dependency tracking (Effect) assumes effects never execute in parallel; effects are registered on the render goroutine and re-run on whichever goroutine calls Set.

Index

Constants

This section is empty.

Variables

View Source
var (
	// ErrResourcePending is returned by Read while a resource is loading.
	ErrResourcePending = errors.New("state: resource pending")
	// ErrNilResource is returned when Read is called on a nil resource.
	ErrNilResource = errors.New("state: nil resource")
)
View Source
var GlobalStoreManager = &StoreManager{
	modules: make(map[string]map[string]*Store),
}

GlobalStoreManager is the process-wide store registry.

View Source
var OnCallbackPanic func(recovered any, context string, stack []byte)

OnCallbackPanic receives panics recovered at state callback boundaries. Core installs the browser error pipeline here; packages that use state on their own still get a log entry instead of a process-ending panic.

View Source
var StoreHook func(module, store, key string, value any)

StoreHook is invoked on every mutation when non-nil, allowing external observers (e.g. plugins) to react to state changes without creating an import cycle with core.

Functions

func Batch

func Batch(fn func())

Batch defers dependent effects until fn completes and runs each effect once.

func ClearResourceCache

func ClearResourceCache(key string)

ClearResourceCache removes a shared resource cache entry.

func Dispatch

func Dispatch(ctx Context, a Action) error

Dispatch executes the given Action with the provided context. If the action is nil it is a no-op and nil is returned.

func Effect

func Effect(fn func() func()) func()

Effect registers a reactive computation that automatically re-runs when its dependent signals change. The provided function may return a cleanup function that will run before the next execution and when the effect is stopped.

func Map

func Map[T, R any](s *Store, key, dep string, compute func(T) R)

Map registers a computed value derived from a single dependency using a strongly typed mapping function. The mapping function receives the current value of the dependency and its result is stored under the provided key. If the dependency cannot be asserted to the expected type, the zero value of the return type is used instead.

func Map2

func Map2[A, B, R any](s *Store, key, depA, depB string, compute func(A, B) R)

Map2 registers a computed value derived from two dependencies. The mapping function receives the current values of both dependencies and its result is stored under the provided key. If any dependency fails type assertion the zero value of the return type is used.

func SetLogger

func SetLogger(l Logger)

SetLogger replaces the logger used by stores.

func Untracked

func Untracked[T any](fn func() T) T

Untracked evaluates fn without subscribing the current effect.

func UseAction

func UseAction(ctx Context, a Action) func() error

UseAction binds an Action to a Context and returns a function that executes the action when invoked. It can be used in places that expect a simple callback.

Types

type Action

type Action func(ctx Context) error

Action represents a unit of work executed with a Context. It returns an error if the action fails.

type Computed

type Computed struct {
	// contains filtered or unexported fields
}

Computed represents a derived state value based on other store keys. It holds the target key for the computed value, the list of dependencies and the function used to calculate the value.

func NewComputed

func NewComputed(key string, deps []string, compute func(map[string]any) any) *Computed

NewComputed creates a new Computed value.

func (*Computed) Deps

func (c *Computed) Deps() []string

Deps returns the list of keys this computed value depends on.

func (*Computed) Evaluate

func (c *Computed) Evaluate(state map[string]any) any

Evaluate executes the compute function using the provided state and returns the result.

func (*Computed) Key

func (c *Computed) Key() string

Key returns the store key associated with the computed value.

type Context

type Context = context.Context

Context is an alias of context.Context used by Actions. This allows the API to remain stable if a custom context is needed later.

type Logger

type Logger interface {
	Debug(format string, args ...any)
}

Logger receives debug messages from stores.

type MemoValue

type MemoValue[T any] struct {
	// contains filtered or unexported fields
}

MemoValue is a read-only signal derived from other signals.

func Memo

func Memo[T any](compute func() T) *MemoValue[T]

Memo creates a cached derivation and tracks every signal read by compute.

func (*MemoValue[T]) Get

func (m *MemoValue[T]) Get() T

Get returns the current memoized value and tracks the caller.

func (*MemoValue[T]) OnChange

func (m *MemoValue[T]) OnChange(fn func(T)) *Subscription

OnChange subscribes to memo changes.

func (*MemoValue[T]) Read

func (m *MemoValue[T]) Read() any

Read returns the current value without knowing T.

func (*MemoValue[T]) Stop

func (m *MemoValue[T]) Stop()

Stop releases the memo's dependencies.

type ReactiveString

type ReactiveString = ReactiveVar[string]

ReactiveString is a convenience alias for ReactiveVar[string].

type ReactiveVar

type ReactiveVar[T any] struct {
	// contains filtered or unexported fields
}

ReactiveVar stores a value and notifies listeners when it changes.

func NewReactiveVar

func NewReactiveVar[T any](initial T) *ReactiveVar[T]

NewReactiveVar creates a reactive value.

func (*ReactiveVar[T]) Get

func (rv *ReactiveVar[T]) Get() T

Get returns the current value.

func (*ReactiveVar[T]) OnChange

func (rv *ReactiveVar[T]) OnChange(listener func(T))

OnChange registers a listener.

func (*ReactiveVar[T]) Set

func (rv *ReactiveVar[T]) Set(newValue T)

Set updates the value and notifies listeners.

type Resource

type Resource[T any] struct {
	// contains filtered or unexported fields
}

Resource wraps cancellable asynchronous data in reactive signals.

func NewResource

func NewResource[T any](loader func(context.Context) (T, error), opts ...ResourceOption) *Resource[T]

NewResource creates a resource and starts loading by default.

func (*Resource[T]) Close

func (r *Resource[T]) Close()

Close cancels pending work and prevents future loads.

func (*Resource[T]) Error

func (r *Resource[T]) Error() error

Error returns the current load error.

func (*Resource[T]) Invalidate

func (r *Resource[T]) Invalidate()

Invalidate clears the cache and returns the resource to idle.

func (*Resource[T]) Load

func (r *Resource[T]) Load(ctx context.Context)

Load starts or joins the current keyed request.

func (*Resource[T]) Loading

func (r *Resource[T]) Loading() bool

Loading reports whether a load is in progress.

func (*Resource[T]) Mutate

func (r *Resource[T]) Mutate(value T)

Mutate replaces the value without loading.

func (*Resource[T]) Read

func (r *Resource[T]) Read() (T, error)

Read returns the value, the load error, or ErrResourcePending.

func (*Resource[T]) Reload

func (r *Resource[T]) Reload(ctx context.Context)

Reload clears the keyed cache and starts a new load.

func (*Resource[T]) Status

func (r *Resource[T]) Status() ResourceStatus

Status returns the current reactive status.

func (*Resource[T]) Value

func (r *Resource[T]) Value() T

Value returns the latest successful value.

type ResourceOption

type ResourceOption func(*resourceConfig)

ResourceOption configures a Resource.

func WithResourceKey

func WithResourceKey(key string) ResourceOption

WithResourceKey enables request deduplication and caching for key.

func WithResourceTTL

func WithResourceTTL(ttl time.Duration) ResourceOption

WithResourceTTL expires a keyed cache entry after ttl.

func WithoutImmediateLoad

func WithoutImmediateLoad() ResourceOption

WithoutImmediateLoad leaves a resource idle until Load is called.

type ResourceStatus

type ResourceStatus string

ResourceStatus describes the current resource state.

const (
	// ResourceIdle indicates that loading has not started.
	ResourceIdle ResourceStatus = "idle"
	// ResourceLoading indicates that a load is in progress.
	ResourceLoading ResourceStatus = "loading"
	// ResourceReady indicates that a value is available.
	ResourceReady ResourceStatus = "ready"
	// ResourceError indicates that loading failed.
	ResourceError ResourceStatus = "error"
)

type Signal

type Signal[T any] struct {
	// contains filtered or unexported fields
}

Signal holds a value of type T and tracks which effects depend on it. Get/Set are safe for concurrent use, so background goroutines may feed a signal; dependent effects run synchronously on the goroutine calling Set.

func NewSignal

func NewSignal[T any](initial T) *Signal[T]

NewSignal creates a new Signal with the given initial value.

func (*Signal[T]) Channel

func (s *Signal[T]) Channel() <-chan T

Channel returns a read-only channel that receives the new value on each Set. The channel is created lazily on first call and shared across all listeners. It is closed automatically when all OnChange listeners are removed.

func (*Signal[T]) Get

func (s *Signal[T]) Get() T

Get returns the current value of the signal and registers the calling effect.

func (*Signal[T]) OnChange

func (s *Signal[T]) OnChange(fn func(T)) *Subscription

OnChange registers a callback that fires whenever the signal's value changes. Returns a Subscription that can be stopped to remove the listener.

func (*Signal[T]) Read

func (s *Signal[T]) Read() any

Read implements a generic getter for use without knowing T.

func (*Signal[T]) Set

func (s *Signal[T]) Set(v T)

Set updates the signal's value and notifies dependent effects. Effects run synchronously on the calling goroutine, outside the signal's lock.

func (*Signal[T]) SetFromHost

func (s *Signal[T]) SetFromHost(raw any)

SetFromHost sets the signal value from an untyped host payload. JSON decodes numbers as float64 and composites as []any/map[string]any, so payloads that do not assert directly to T are converted through a JSON round-trip into T. Payloads that cannot represent T are ignored.

func (*Signal[T]) SubCount

func (s *Signal[T]) SubCount() int

SubCount returns the number of active effect subscriptions.

type Store

type Store struct {
	// contains filtered or unexported fields
}

Store holds keyed state with listeners, computed values, watchers and optional history. All methods are safe for concurrent use: internal state is mutex-protected, and listeners/watchers are invoked outside the lock (on the goroutine that called Set), so they may call back into the store. Computed functions run under the lock and must only read the state map they receive, never call store methods.

func NewStore

func NewStore(name string, opts ...StoreOption) *Store

NewStore creates a new store with the given name and optional configuration. By default stores are registered under the "default" module.

func (*Store) Get

func (s *Store) Get(key string) any

Get returns the value stored under key.

func (*Store) Module

func (s *Store) Module() string

Module reports the module namespace of the store.

func (*Store) Name

func (s *Store) Name() string

Name returns the store name within its module namespace.

func (*Store) OnChange

func (s *Store) OnChange(key string, listener func(any)) func()

OnChange registers a listener and returns its unsubscribe function.

func (*Store) Redo

func (s *Store) Redo()

Redo reapplies the last mutation that was undone.

func (*Store) RegisterComputed

func (s *Store) RegisterComputed(c *Computed)

RegisterComputed registers a computed value on the store. The computed value is evaluated immediately and whenever one of its dependencies changes. The compute function runs under the store lock: it must only read the state map it receives and never call store methods.

func (*Store) RegisterWatcher

func (s *Store) RegisterWatcher(w *Watcher) func()

RegisterWatcher registers a watcher that triggers when any of its dependencies change. If the dependency list is empty the watcher is triggered on every state update. It returns a function that removes the watcher.

func (*Store) Set

func (s *Store) Set(key string, value any)

Set stores a value and notifies dependents.

func (*Store) Snapshot

func (s *Store) Snapshot() map[string]any

Snapshot copies the current state of the store.

func (*Store) Undo

func (s *Store) Undo()

Undo reverts the last mutation recorded in the store's history.

type StoreManager

type StoreManager struct {
	// contains filtered or unexported fields
}

StoreManager groups stores by module and name.

func NewStoreManager

func NewStoreManager() *StoreManager

NewStoreManager creates a standalone manager for isolating store instances.

func (*StoreManager) DumpState

func (sm *StoreManager) DumpState()

DumpState writes every registered store to the debug logger.

func (*StoreManager) GetStore

func (sm *StoreManager) GetStore(module, name string) *Store

GetStore returns a registered store or nil.

func (*StoreManager) NewStore

func (sm *StoreManager) NewStore(name string, opts ...StoreOption) *Store

NewStore creates and registers a store in this manager.

func (*StoreManager) RegisterStore

func (sm *StoreManager) RegisterStore(module, name string, store *Store)

RegisterStore registers a store by module and name.

func (*StoreManager) Snapshot

func (sm *StoreManager) Snapshot() map[string]map[string]map[string]any

Snapshot returns a deep copy of all registered stores and their states.

func (*StoreManager) UnregisterStore

func (sm *StoreManager) UnregisterStore(module, name string)

UnregisterStore removes the store identified by module and name. If the store or module does not exist, it is a no-op.

type StoreOption

type StoreOption func(*Store)

StoreOption configures optional behaviour for a Store during creation.

func WithDevTools

func WithDevTools() StoreOption

WithDevTools enables logging of state mutations for development.

func WithHistory

func WithHistory(limit int) StoreOption

WithHistory enables mutation history with the provided limit. The limit controls how many past mutations are retained for undo/redo.

func WithModule

func WithModule(module string) StoreOption

WithModule namespaces a store under the provided module.

func WithPersistence

func WithPersistence() StoreOption

WithPersistence enables localStorage persistence for the store.

type Subscription

type Subscription struct {
	// contains filtered or unexported fields
}

Subscription represents a cancellable listener returned by OnChange.

func (*Subscription) Stop

func (s *Subscription) Stop()

Stop removes the listener and releases the associated channel.

type Watcher

type Watcher struct {
	// contains filtered or unexported fields
}

Watcher represents a callback that reacts to changes on specific store keys. When any of the dependencies change, the associated function is triggered.

func NewWatcher

func NewWatcher(deps []string, run func(map[string]any), opts ...WatcherOption) *Watcher

NewWatcher creates a new Watcher.

func (*Watcher) Deps

func (w *Watcher) Deps() []string

Deps returns the list of keys the watcher observes.

func (*Watcher) Run

func (w *Watcher) Run(state map[string]any)

Run triggers the watcher with the provided state.

type WatcherOption

type WatcherOption func(*Watcher)

WatcherOption configures optional watcher behaviour.

func WatcherDeep

func WatcherDeep() WatcherOption

WatcherDeep enables deep watching of nested keys.

func WatcherImmediate

func WatcherImmediate() WatcherOption

WatcherImmediate triggers the watcher immediately after registration.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL