preact-sigma 6.0.2 → 6.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.mts CHANGED
@@ -1,4 +1,4 @@
1
- import { a as SigmaState, c as query, d as Draft, f as Immutable, i as SigmaRef, l as setAutoFreeze, m as Cleanup, n as Sigma, o as SigmaTarget, p as typeSymbol, r as SigmaDefinition, s as castProtected, t as Protected, u as sigma } from "./sigma-BhmvUxp9.mjs";
1
+ import { a as SigmaState, c as query, d as Draft, f as Immutable, i as SigmaRef, l as setAutoFreeze, m as Cleanup, n as Sigma, o as SigmaTarget, p as typeSymbol, r as SigmaDefinition, s as castProtected, t as Protected, u as sigma } from "./sigma-c48-qjsH.mjs";
2
2
 
3
3
  //#region src/defaults.d.ts
4
4
  /**
package/dist/index.mjs CHANGED
@@ -1,4 +1,4 @@
1
- import { a as setAutoFreeze, c as listenersSymbol, i as query, n as SigmaTarget, o as sigma, r as castProtected, t as Sigma } from "./sigma-tZ0xhlG3.mjs";
1
+ import { a as setAutoFreeze, c as listenersSymbol, i as query, n as SigmaTarget, o as sigma, r as castProtected, t as Sigma } from "./sigma-0X8yJrUR.mjs";
2
2
  import { useEffect, useRef } from "preact/hooks";
3
3
  //#region src/defaults.ts
4
4
  /**
@@ -1,7 +1,13 @@
1
- import { f as Immutable, n as Sigma } from "./sigma-BhmvUxp9.mjs";
1
+ import { f as Immutable, n as Sigma, t as Protected } from "./sigma-c48-qjsH.mjs";
2
2
 
3
3
  //#region src/persist.d.ts
4
4
  type MaybePromise<T> = T | Promise<T>;
5
+ /**
6
+ * Sigma instance or protected consumer view accepted by persistence helpers.
7
+ *
8
+ * Restore and hydrate helpers may replace committed state through this trusted owner boundary.
9
+ */
10
+ type PersistInstance<TState extends object> = Sigma<TState> | Protected<Sigma<TState>>;
5
11
  /** Decode-time context passed to persistence codecs. */
6
12
  interface PersistDecodeContext<TState extends object> {
7
13
  /** Storage key used to read the record being decoded. */
@@ -108,19 +114,19 @@ interface SyncHydrationHandle extends PersistenceHandle {
108
114
  readonly restored: RestoreResult;
109
115
  }
110
116
  /** Restores committed state from a persisted record through an async store. */
111
- declare function restore<TState extends object, TKey extends keyof TState>(instance: Sigma<TState>, options: PickPersistOptions<TState, TKey>): Promise<RestoreResult>;
112
- declare function restore<TState extends object, TStored = Immutable<TState>>(instance: Sigma<TState>, options: PersistOptions<TState, TStored>): Promise<RestoreResult>;
117
+ declare function restore<TState extends object, TKey extends keyof TState>(instance: PersistInstance<TState>, options: PickPersistOptions<TState, TKey>): Promise<RestoreResult>;
118
+ declare function restore<TState extends object, TStored = Immutable<TState>>(instance: PersistInstance<TState>, options: PersistOptions<TState, TStored>): Promise<RestoreResult>;
113
119
  /** Restores committed state from a persisted record through a sync store. */
114
- declare function restoreSync<TState extends object, TKey extends keyof TState>(instance: Sigma<TState>, options: SyncPickPersistOptions<TState, TKey>): RestoreResult;
115
- declare function restoreSync<TState extends object, TStored = Immutable<TState>>(instance: Sigma<TState>, options: SyncPersistOptions<TState, TStored>): RestoreResult;
120
+ declare function restoreSync<TState extends object, TKey extends keyof TState>(instance: PersistInstance<TState>, options: SyncPickPersistOptions<TState, TKey>): RestoreResult;
121
+ declare function restoreSync<TState extends object, TStored = Immutable<TState>>(instance: PersistInstance<TState>, options: SyncPersistOptions<TState, TStored>): RestoreResult;
116
122
  /** Persists future committed state changes for one sigma instance. */
117
- declare function persist<TState extends object, TKey extends keyof TState>(instance: Sigma<TState>, options: PickPersistOptions<TState, TKey>): PersistenceHandle;
118
- declare function persist<TState extends object, TStored = Immutable<TState>>(instance: Sigma<TState>, options: PersistOptions<TState, TStored>): PersistenceHandle;
123
+ declare function persist<TState extends object, TKey extends keyof TState>(instance: PersistInstance<TState>, options: PickPersistOptions<TState, TKey>): PersistenceHandle;
124
+ declare function persist<TState extends object, TStored = Immutable<TState>>(instance: PersistInstance<TState>, options: PersistOptions<TState, TStored>): PersistenceHandle;
119
125
  /** Restores state, then begins persisting future committed changes. */
120
- declare function hydrate<TState extends object, TKey extends keyof TState>(instance: Sigma<TState>, options: PickPersistOptions<TState, TKey>): HydrationHandle;
121
- declare function hydrate<TState extends object, TStored = Immutable<TState>>(instance: Sigma<TState>, options: PersistOptions<TState, TStored>): HydrationHandle;
126
+ declare function hydrate<TState extends object, TKey extends keyof TState>(instance: PersistInstance<TState>, options: PickPersistOptions<TState, TKey>): HydrationHandle;
127
+ declare function hydrate<TState extends object, TStored = Immutable<TState>>(instance: PersistInstance<TState>, options: PersistOptions<TState, TStored>): HydrationHandle;
122
128
  /** Restores state synchronously, then begins persisting future committed changes. */
123
- declare function hydrateSync<TState extends object, TKey extends keyof TState>(instance: Sigma<TState>, options: SyncPickPersistOptions<TState, TKey>): SyncHydrationHandle;
124
- declare function hydrateSync<TState extends object, TStored = Immutable<TState>>(instance: Sigma<TState>, options: SyncPersistOptions<TState, TStored>): SyncHydrationHandle;
129
+ declare function hydrateSync<TState extends object, TKey extends keyof TState>(instance: PersistInstance<TState>, options: SyncPickPersistOptions<TState, TKey>): SyncHydrationHandle;
130
+ declare function hydrateSync<TState extends object, TStored = Immutable<TState>>(instance: PersistInstance<TState>, options: SyncPersistOptions<TState, TStored>): SyncHydrationHandle;
125
131
  //#endregion
126
132
  export { HydrationHandle, PersistCodec, PersistDecodeContext, PersistErrorContext, PersistOptions, PersistRecord, PersistSchedule, PersistStore, PersistenceHandle, PickPersistOptions, RestoreResult, SyncHydrationHandle, SyncPersistOptions, SyncPersistStore, SyncPickPersistOptions, hydrate, hydrateSync, persist, restore, restoreSync };
package/dist/persist.mjs CHANGED
@@ -1,4 +1,4 @@
1
- import { o as sigma, s as isPlainObject } from "./sigma-tZ0xhlG3.mjs";
1
+ import { o as sigma, s as isPlainObject } from "./sigma-0X8yJrUR.mjs";
2
2
  //#region src/persist.ts
3
3
  function createIdentityCodec() {
4
4
  return {
@@ -391,15 +391,22 @@ function castProtected(instance) {
391
391
  *
392
392
  * `TEvents` maps event names to payload types, and `TState` types reactive state.
393
393
  */
394
- var SigmaTarget = class extends Sigma {
394
+ var SigmaTarget = class SigmaTarget extends Sigma {
395
395
  [listenersSymbol] = new SigmaListenerMap();
396
396
  constructor(state) {
397
397
  super(state ?? emptySentinel);
398
398
  }
399
- /** Emits a typed event from an action after unpublished draft changes are committed. */
399
+ /**
400
+ * Emits a typed event.
401
+ *
402
+ * Directly constructed targets can emit from ordinary code. Subclasses emit from action context
403
+ * after unpublished draft changes are committed.
404
+ */
400
405
  emit(name, ...[detail]) {
401
406
  const instance = getActionInstance(this);
402
- assertActionContext(instance, "Cannot emit() from outside an action.");
407
+ if (Object.getPrototypeOf(instance) === SigmaTarget.prototype) {
408
+ if (activeDraft) throw createExternalActionError();
409
+ } else assertActionContext(instance, "Cannot emit() from outside an action.");
403
410
  if (instance === activeDraftInstance && activeDraft) throw new Error("Cannot emit() until you commit() your draft.");
404
411
  this[listenersSymbol].emit(name, detail);
405
412
  }
@@ -128,7 +128,12 @@ declare class SigmaTarget<TEvents extends object = {}, TState extends object = {
128
128
  };
129
129
  protected [listenersSymbol]: SigmaListenerMap;
130
130
  constructor(state?: TState);
131
- /** Emits a typed event from an action after unpublished draft changes are committed. */
131
+ /**
132
+ * Emits a typed event.
133
+ *
134
+ * Directly constructed targets can emit from ordinary code. Subclasses emit from action context
135
+ * after unpublished draft changes are committed.
136
+ */
132
137
  emit<TEvent extends string & keyof TEvents>(name: TEvent, ...[detail]: EventParameters<TEvents[TEvent]>): void;
133
138
  }
134
139
  /** Helpers for observing, accessing, capturing, and replacing committed sigma state. */
@@ -163,6 +168,6 @@ type Protected<T extends Sigma<any>> = BrandProtected<T extends {
163
168
  [typeSymbol]: {
164
169
  state: infer TState extends object;
165
170
  };
166
- } ? { [K in keyof T as K extends ProtectedKey ? never : K]: K extends typeof typeSymbol ? T[K] : K extends keyof TState ? Immutable<T[K]> : T[K] extends AnyFunction ? (...params: Parameters<T[K]>) => Immutable<ReturnType<T[K]>> : Immutable<T[K]> } : never>;
171
+ } ? { readonly [K in keyof T as K extends ProtectedKey ? never : K]: K extends typeof typeSymbol ? T[K] : K extends keyof TState ? Immutable<T[K]> : T[K] extends AnyFunction ? (...params: Parameters<T[K]>) => Immutable<ReturnType<T[K]>> : Immutable<T[K]> } : never>;
167
172
  //#endregion
168
173
  export { SigmaState as a, query as c, Draft as d, Immutable as f, SigmaRef as i, setAutoFreeze as l, Cleanup as m, Sigma as n, SigmaTarget as o, typeSymbol as p, SigmaDefinition as r, castProtected as s, Protected as t, sigma as u };
package/docs/context.md CHANGED
@@ -20,14 +20,14 @@
20
20
  # Core Abstractions
21
21
 
22
22
  - Sigma class: a class that extends `Sigma<TState>` and passes its initial top-level state to `super(...)`. The `TState` argument drives helper typing for subscriptions, signals, and replacement snapshots; a same-named merged interface gives direct property reads their instance types.
23
- - Sigma target: a class that extends `SigmaTarget<TEvents, TState>` when it also emits typed events. Use `SigmaTarget<TEvents>` for event-only targets.
23
+ - Sigma target: a class that extends `SigmaTarget<TEvents>` for typed event actions or `SigmaTarget<TEvents, TState>` when it also owns state. Use `new SigmaTarget<TEvents>()` for standalone event-only targets.
24
24
  - State property: a top-level key from `TState`. Each key becomes a reactive public property and has its own signal.
25
25
  - Private field: an ECMAScript `#field` on the model class. Private fields are ordinary instance storage. They can be read from model members, but they do not create signals or invalidate reactive reads by themselves.
26
26
  - Computed: an argument-free derived getter on the class prototype that reads committed state.
27
27
  - Query: a reactive read method that accepts arguments, is marked with the `query` decorator, and reads committed state.
28
28
  - Action: a prototype method that is not marked as a query. Actions read and write state properties through sigma's draft and commit semantics.
29
29
  - Setup handler: an optional `onSetup(...)` method that owns side effects and returns cleanup resources.
30
- - Event: a typed notification emitted with `this.emit(...)` inside an action and observed through `listen(...)` or `useListener(...)`.
30
+ - Event: a typed notification emitted with `this.emit(...)` inside an action, or with `emit(...)` on a directly constructed `SigmaTarget`, and observed through `listen(...)` or `useListener(...)`.
31
31
  - Protected view: the readonly consumer view returned by `castProtected(...)` and `useSigma(...)`.
32
32
 
33
33
  # Data Flow / Lifecycle
@@ -45,6 +45,7 @@
45
45
 
46
46
  - Define reusable model state: `class Model extends Sigma<TState>`.
47
47
  - Define reusable model state with events: `class Model extends SigmaTarget<TEvents, TState>`.
48
+ - Define a standalone typed event target: `new SigmaTarget<TEvents>()`.
48
49
  - Merge partial constructor input with defaults: `mergeDefaults(initial, defaults)`.
49
50
  - Derive an argument-free value: a class getter.
50
51
  - Derive a reactive read with arguments: an `@query` class method.
@@ -68,7 +69,7 @@
68
69
  - Use `@query` for tracked reads with arguments.
69
70
  - Derive directly from state properties inside an action when the calculation needs unpublished draft values.
70
71
  - Use ordinary actions for routine writes. Reserve `sigma.captureState(...)` and `sigma.replaceState(...)` for replay, reset, restore, or undo-like flows on committed top-level state.
71
- - Emit directly from actions that have no unpublished draft changes. After mutating state, publish first with `this.commit(); this.emit(...)`.
72
+ - Emit directly from standalone `SigmaTarget` instances. In subclasses, emit from actions that have no unpublished draft changes. After mutating state, publish first with `this.commit(); this.emit(...)`.
72
73
  - Prefer `listen(...)` for external event subscriptions. It works with sigma targets and DOM targets.
73
74
  - Put owned side effects in `onSetup(...)`.
74
75
  - Use `sigma.subscribe(this, ...)` inside `onSetup(...)` when a setup-owned side effect should react to future committed publishes. Return that cleanup so the subscription stops with setup.
@@ -104,14 +105,14 @@
104
105
  - Setup handlers return arrays of cleanup resources, and cleanup runs in reverse order.
105
106
  - Call Immer's `enablePatches()` before relying on `sigma.subscribe(instance, handler, { patches: true })`.
106
107
  - `sigma.replaceState(...)` works on committed top-level state and requires a plain object snapshot.
107
- - `SigmaTarget.emit(...)` runs from an action and requires no active unpublished draft. It does not need a `commit(...)` callback.
108
+ - `SigmaTarget.emit(...)` runs directly on standalone targets. In subclasses, it runs from an action and requires no active unpublished draft.
108
109
 
109
110
  # Error Model
110
111
 
111
112
  - Crossing an action boundary with unpublished changes throws until `this.commit()` publishes them. Async actions also reject when they finish with unpublished changes.
112
113
  - Calling `commit(...)` outside an action throws.
113
114
  - Calling `act(...)` outside an `onSetup(...)` setup context throws.
114
- - Calling `emit(...)` outside an action or before committing the active draft throws.
115
+ - Calling `emit(...)` outside an action on a subclass, or before committing the active draft, throws.
115
116
  - Calling an action from a computed or query throws.
116
117
  - Returning an active draft from an action throws.
117
118
  - `sigma.replaceState(...)` throws when the replacement value is not a plain object or when an action still owns unpublished changes.
@@ -116,7 +116,7 @@ interface TodoList extends TodoListState {}
116
116
 
117
117
  ## Events
118
118
 
119
- `SigmaTarget` now takes event types first. Use `SigmaTarget<TEvents>` for event-only targets and `SigmaTarget<TEvents, TState>` for targets that also own state.
119
+ `SigmaTarget` now takes event types first. Use `new SigmaTarget<TEvents>()` for standalone event-only targets, `class Model extends SigmaTarget<TEvents>` for event-only action classes, and `SigmaTarget<TEvents, TState>` for class targets that also own state.
120
120
 
121
121
  ```ts
122
122
  import { listen, SigmaTarget } from "preact-sigma";
@@ -140,7 +140,7 @@ const stop = listen(notifications, "saved", ({ id }) => {
140
140
  });
141
141
  ```
142
142
 
143
- `emit(...)` runs inside actions. If an action mutates state before emitting, publish first with `this.commit()`.
143
+ Directly constructed `SigmaTarget` instances can emit from ordinary code. Subclasses emit inside actions. If an action mutates state before emitting, publish first with `this.commit()`.
144
144
 
145
145
  ## Commit Boundaries
146
146
 
package/docs/persist.md CHANGED
@@ -29,6 +29,7 @@ Use the persist module when those primitives are the right boundary, but you do
29
29
 
30
30
  ## Core Pieces
31
31
 
32
+ - Instance: a raw `Sigma` instance or a protected consumer view returned by `castProtected(...)` or `useSigma(...)`.
32
33
  - Store: owns `get`, `set`, and `delete` for persisted records. These names match [Keyv](https://github.com/jaredwray/keyv) and `Map`.
33
34
  - Codec: owns payload shape, versioning, and migration logic between stored data and a full committed snapshot.
34
35
  - Pick options: persist selected top-level keys without writing a custom codec.
@@ -54,6 +55,7 @@ Use the persist module when those primitives are the right boundary, but you do
54
55
 
55
56
  ## Constraints
56
57
 
58
+ - Persistence helpers are trusted external model owners. Restore and hydrate helpers may replace committed state even when they receive a protected consumer view.
57
59
  - `sigma.replaceState(...)` requires a plain object replacement snapshot. In supported TypeScript usage, pass the class's full `TState` shape.
58
60
  - Custom partial persistence codecs should reconstruct a full replacement snapshot before restore finishes.
59
61
  - Nested sigma-state values are stored only if the chosen codec and payload format support them explicitly.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "preact-sigma",
3
- "version": "6.0.2",
3
+ "version": "6.1.1",
4
4
  "keywords": [],
5
5
  "license": "MIT",
6
6
  "author": "Alec Larson",