r-state-tree 0.4.0 → 0.4.2

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/README.md CHANGED
@@ -1,6 +1,10 @@
1
1
  # r-state-tree
2
2
 
3
- Reactive state management featuring store trees, computed child stores, and snapshot utilities backed by `@preact/signals-core`.
3
+ r-state-tree is a reactive state management library for building complex applications by moving state out of your render tree.
4
+
5
+ - Stores hold application/view state as a tree and drive your UI.
6
+ - Models hold domain state as a separate tree with snapshots, identifiers and references.
7
+ - Views become dumb renderers that react to Stores/Models.
4
8
 
5
9
  ## Installation
6
10
 
@@ -14,6 +18,13 @@ This library uses [TC39 Stage 3 Decorators](https://github.com/tc39/proposal-dec
14
18
 
15
19
  The library includes a decorator metadata polyfill for runtimes that don't yet natively support `Symbol.metadata`.
16
20
 
21
+ ## Core concepts
22
+
23
+ - Stores: application/view state containers. Create with `createStore()`, attach with `mount()`. Compose with `@child` (single or arrays, stable via `{ key }`). React to changes with `effect`/`reaction` and store lifecycles (`storeDidMount`/`storeWillUnmount`). Update reactive `props` via `updateStore()`.
24
+ - Models: domain state containers. Create with `Model.create()`. Persistent via snapshots (`toSnapshot`, `applySnapshot`, `onSnapshot`, diffs via `onSnapshotDiff`). Structure with `@state`, `@child`, identifiers via `@id`, and references via `@modelRef`.
25
+ - Context: pass data through Store/Model trees without prop drilling using `createContext<T>()`, `[Context.provide]`, and `Context.consume(this)`. Context is reactive and can be overridden by descendants.
26
+ - Reactivity: powered by signals. Use `@observable`, `@computed`, `effect`, `reaction`, `batch`, and `untracked` for precise updates.
27
+
17
28
  ## Stores
18
29
 
19
30
  Stores describe reactive state containers composed into a tree.
@@ -51,15 +62,15 @@ updateStore(app.todo, { title: "Ship release" });
51
62
 
52
63
  ### Child stores
53
64
 
54
- Use `@child` for single child stores and `@children` for arrays.
65
+ Use `@child` for both single child stores and arrays.
55
66
 
56
67
  ```ts
57
- import { child, children } from "r-state-tree";
68
+ import { child } from "r-state-tree";
58
69
 
59
70
  class ListStore extends Store {
60
71
  items = ["Buy milk", "Walk dog"];
61
72
 
62
- @children get todos() {
73
+ @child get todos() {
63
74
  return this.items.map((title, i) =>
64
75
  createStore(TodoStore, { title, key: i })
65
76
  );
@@ -143,6 +154,44 @@ batch(() => {
143
154
  });
144
155
  ```
145
156
 
157
+ ## Modeling guide
158
+
159
+ - Root store: mount a single root Store that composes the application via `@child` properties.
160
+ - View stores: create one Store per view/route/tab. Views render from stores; stores drive view transitions.
161
+ - Keyed children: pass `{ key }` when creating child stores to preserve identity across reorders.
162
+ - Models in stores: pass domain Models via `{ models }` and consume with `@model` on the Store.
163
+
164
+ ```ts
165
+ import { Store, Model, child, createStore, mount } from "r-state-tree";
166
+
167
+ class TabViewStore extends Store<{ title: string }> {}
168
+
169
+ class RootStore extends Store {
170
+ @child get tabs() {
171
+ return ["Home", "Profile"].map((title, i) =>
172
+ createStore(TabViewStore, { title, key: i })
173
+ );
174
+ }
175
+ }
176
+
177
+ const root = mount(createStore(RootStore));
178
+ ```
179
+
180
+ Passing models into stores:
181
+
182
+ ```ts
183
+ class User extends Model {
184
+ // ... @id, @state, etc.
185
+ }
186
+
187
+ class ProfileStore extends Store {
188
+ @model user: User; // injected model
189
+ }
190
+
191
+ const user = User.create({ id: 1, name: "Alice" });
192
+ const profile = mount(createStore(ProfileStore, { models: { user } }));
193
+ ```
194
+
146
195
  ## Observable classes
147
196
 
148
197
  For reactive class instances outside the Model/Store system, use `@observable` and `@computed` decorators:
@@ -190,6 +239,61 @@ effect(() => {
190
239
  state.count++; // Triggers the effect
191
240
  ```
192
241
 
242
+ ## Observables (low‑level)
243
+
244
+ Create reactive structures outside Stores/Models. Supported: Objects, Arrays, Map, Set, WeakMap, WeakSet.
245
+
246
+ - Track reads with `effect`/`reaction`. Nested values are tracked when you access them inside your effects.
247
+ - Access raw values via `source(observable)`; check if something is reactive with `isObservable(value)`.
248
+ - Arrays: reading specific indices (`arr[i]`) or `length` tracks those; common mutators (`push/pop/shift/unshift/splice/reverse/sort/fill`) are reactive; non-index and symbol keys are not reactive.
249
+
250
+ ```ts
251
+ import { observable, effect, computed, reaction } from "r-state-tree";
252
+
253
+ // Object
254
+ const state = observable({ count: 0, nested: { value: 1 } });
255
+
256
+ effect(() => {
257
+ // tracks reads
258
+ state.count;
259
+ state.nested.value;
260
+ });
261
+
262
+ state.count++;
263
+ state.nested.value++;
264
+
265
+ // Computed
266
+ const doubled = computed(() => state.count * 2);
267
+ effect(() => {
268
+ doubled.value;
269
+ });
270
+
271
+ // Array
272
+ const arr = observable([0, 1]);
273
+ effect(() => arr[0]);
274
+ arr[0]++; // triggers; arr.push(2) does not, index 0 didn't change
275
+
276
+ // Map
277
+ const map = observable(new Map([["k", 1]]));
278
+ effect(() => map.get("k"));
279
+ map.set("k", 2); // triggers
280
+
281
+ // Set
282
+ const set = observable(new Set([1]));
283
+ effect(() => set.has(2));
284
+ set.add(2); // triggers
285
+
286
+ // Reaction (runs only on changes, skips initial)
287
+ let last: number | undefined;
288
+ reaction(
289
+ () => state.count,
290
+ (v) => {
291
+ last = v;
292
+ }
293
+ );
294
+ state.count++;
295
+ ```
296
+
193
297
  ## Models and snapshots
194
298
 
195
299
  Models capture persistent state with snapshot utilities.
@@ -198,14 +302,14 @@ Models capture persistent state with snapshot utilities.
198
302
  import {
199
303
  Model,
200
304
  state,
201
- identifier,
305
+ id,
202
306
  applySnapshot,
203
307
  onSnapshot,
204
308
  toSnapshot,
205
309
  } from "r-state-tree";
206
310
 
207
311
  class TodoModel extends Model {
208
- @identifier id = 0;
312
+ @id id = 0;
209
313
  @state title = "";
210
314
  @state completed = false;
211
315
  }
@@ -220,44 +324,72 @@ todo.title = "Learn r-state-tree";
220
324
  stop();
221
325
  ```
222
326
 
327
+ ### Model lifecycle hooks
328
+
329
+ Models support lifecycle methods:
330
+
331
+ ```ts
332
+ class TodoModel extends Model {
333
+ @child tags: TagModel[] = [];
334
+
335
+ modelDidInit(snapshot?, ...args: unknown[]) {
336
+ // Called when model is created via Model.create()
337
+ // Receives the snapshot and any additional arguments passed to create()
338
+ console.log("Model initialized", snapshot);
339
+ }
340
+
341
+ modelDidAttach() {
342
+ // Called when this model is attached as a child to another model
343
+ console.log("Model attached to parent");
344
+ }
345
+
346
+ modelWillDetach() {
347
+ // Called when this model is detached from its parent
348
+ console.log("Model will be detached");
349
+ }
350
+ }
351
+ ```
352
+
223
353
  ### Model decorators
224
354
 
225
355
  Use decorators to configure model properties:
226
356
 
227
357
  ```ts
228
- import {
229
- Model,
230
- state,
231
- identifier,
232
- child,
233
- children,
234
- modelRef,
235
- modelRefs,
236
- } from "r-state-tree";
358
+ import { Model, state, id, child, modelRef } from "r-state-tree";
237
359
 
238
360
  class User extends Model {
239
- @identifier id = 0;
361
+ @id id = 0;
240
362
  @state name = "";
241
363
  }
242
364
 
243
365
  class TodoModel extends Model {
244
- @identifier id = 0;
366
+ @id id = 0;
245
367
  @state title = "";
246
368
  @modelRef assignee?: User; // Reference to another model by ID
247
369
  @child metadata = MetadataModel.create(); // Nested child model
248
- @children tags: TagModel[] = []; // Array of child models
370
+ @child tags: TagModel[] = []; // Array of child models
371
+ }
372
+ ```
373
+
374
+ The `@child` and `@modelRef` decorators support both single values and arrays. You can also specify the child type using `@child(ChildType)`:
375
+
376
+ ```ts
377
+ class TodoModel extends Model {
378
+ @child(TagModel) tags: TagModel[] = []; // Type-safe array of child models
379
+ @child(TagModel) primaryTag: TagModel | null = null; // Can switch between single and array at runtime
249
380
  }
250
381
  ```
251
382
 
252
383
  ### Model references
253
384
 
254
- Reference models by ID using `@modelRef` and `@modelRefs`:
385
+ Reference models by ID using `@modelRef`:
255
386
 
256
387
  ```ts
257
388
  class ProjectModel extends Model {
258
- @identifier id = 0;
259
- @children users: User[] = [];
260
- @modelRef owner?: User;
389
+ @id id = 0;
390
+ @child users: User[] = [];
391
+ @modelRef owner?: User; // Single reference
392
+ @modelRef assignees: User[] = []; // Array of references
261
393
 
262
394
  assignOwner(userId: number) {
263
395
  // Find user by ID and set as owner
@@ -278,6 +410,81 @@ const project = ProjectModel.create({
278
410
  project.owner?.name; // "Alice"
279
411
  ```
280
412
 
413
+ Both `@child` and `@modelRef` support runtime type switching between single values and arrays:
414
+
415
+ ```ts
416
+ class ItemModel extends Model {
417
+ @id id = 0;
418
+ @state value = 0;
419
+ }
420
+
421
+ class ContainerModel extends Model {
422
+ @child(ItemModel) items: ItemModel | ItemModel[]; // Can be single or array
423
+
424
+ setSingle() {
425
+ this.items = ItemModel.create({ id: 1, value: 10 });
426
+ }
427
+
428
+ setArray() {
429
+ this.items = [
430
+ ItemModel.create({ id: 2, value: 20 }),
431
+ ItemModel.create({ id: 3, value: 30 }),
432
+ ];
433
+ }
434
+ }
435
+ ```
436
+
437
+ ## API surface
438
+
439
+ - Stores
440
+ - `Store`, `createStore`, `mount`, `unmount`, `updateStore`
441
+ - Models
442
+ - `Model`, decorators: `@state`, `@id`, `@child`, `@modelRef`
443
+ - Snapshots
444
+ - `onSnapshot`, `toSnapshot`, `applySnapshot`, `onSnapshotDiff`
445
+ - Types: `Snapshot`, `SnapshotDiff`, `IdType`, `Configuration`
446
+ - Context
447
+ - `createContext`, type `Context`
448
+ - Reactivity and observables
449
+ - `observable`, `computed`, `effect`, `reaction`, `batch`, `untracked`, `Observable`
450
+ - Utilities: `isObservable`, `source`, `reportObserved`, `reportChanged`
451
+ - Signals interop
452
+ - `signal`, `getSignal`, types `Signal`, `ReadonlySignal`
453
+
454
+ ## UI integration and signals interop
455
+
456
+ r-state-tree is built on `@preact/signals-core`. You can interoperate with signals directly:
457
+
458
+ - Per-property signals via `$prop` on observable objects (including Stores/Models), or `getSignal(obj, key)`.
459
+ - Re-exported utilities: `signal`, `computed`, `effect`, `batch`, `untracked`, and types `Signal`, `ReadonlySignal`.
460
+
461
+ ```ts
462
+ import { observable, effect, getSignal } from "r-state-tree";
463
+
464
+ const state = observable({ count: 0 });
465
+
466
+ // Either form returns a Signal<number>
467
+ const s1 = state.$count;
468
+ const s2 = getSignal(state, "count");
469
+
470
+ effect(() => {
471
+ // Use s1.value (or s2.value) in your UI binding
472
+ console.log("count:", s1.value);
473
+ });
474
+
475
+ // Update via signal or through the object
476
+ s1.value = 1;
477
+ state.count = 2;
478
+ ```
479
+
480
+ ### Identifier and reference rules
481
+
482
+ - `@id` values are unique within a tree. They cannot be cleared to `undefined` after assignment.
483
+ - Identifiers can be reassigned to a new value (including in snapshots) as long as uniqueness is preserved.
484
+ - `@modelRef` requires the referenced model to have an id and be attached to the tree; the ref becomes `undefined` when the model detaches.
485
+ - When a model is re-attached to the same tree, compatible refs restore automatically; attaching to a different root does not restore prior refs.
486
+ - `@modelRef` and `@child` can switch between single and array at runtime; reactions observe the property itself rather than internal array mutations.
487
+
281
488
  ### Snapshot diffs
282
489
 
283
490
  Use `onSnapshotDiff` to receive undo/redo payloads:
package/dist/api.d.ts ADDED
@@ -0,0 +1,9 @@
1
+ import { Snapshot, SnapshotDiff } from "./types";
2
+ import Store from "./store/Store";
3
+ import Model from "./model/Model";
4
+ export declare function mount<T extends Store>(container: T): T;
5
+ export declare function unmount<S extends Store>(container: S): void;
6
+ export declare function toSnapshot<T extends Model>(model: T): Snapshot<T>;
7
+ export declare function onSnapshot<T extends Model>(model: T, callback: (snapshot: Snapshot<T>, model: T) => void): () => void;
8
+ export declare function onSnapshotDiff<T extends Model>(model: T, callback: (snapshotDiff: SnapshotDiff<T>, model: T) => void): () => void;
9
+ export declare function applySnapshot<T extends Model>(model: T, snapshot: Snapshot<T>): T;
@@ -0,0 +1,2 @@
1
+ import { ComputedNode } from "./observables";
2
+ export default function <T extends Record<PropertyKey, any>>(computed: ComputedNode<T>): T;
@@ -0,0 +1,13 @@
1
+ import type Model from "./model/Model";
2
+ import type Store from "./store/Store";
3
+ declare const CONTEXT_SYMBOL: unique symbol;
4
+ declare const HAS_DEFAULT: unique symbol;
5
+ export interface Context<T> {
6
+ readonly [CONTEXT_SYMBOL]: symbol;
7
+ readonly [HAS_DEFAULT]: boolean;
8
+ readonly defaultValue: T | undefined;
9
+ readonly provide: symbol;
10
+ consume(instance: Model | Store): T;
11
+ }
12
+ export declare function createContext<T>(defaultValue?: T): Context<T>;
13
+ export {};
@@ -0,0 +1,6 @@
1
+ import "@tsmetadata/polyfill";
2
+ export declare const child: any;
3
+ export declare const modelRef: any;
4
+ export declare const model: any;
5
+ export declare const id: any;
6
+ export declare const state: any;
@@ -0,0 +1,10 @@
1
+ import "@tsmetadata/polyfill";
2
+ import Store, { createStore, updateStore } from "./store/Store";
3
+ import Model from "./model/Model";
4
+ import { mount, unmount, onSnapshot, toSnapshot, applySnapshot, onSnapshotDiff } from "./api";
5
+ import { createContext } from "./context";
6
+ export { createStore, Store, Model, mount, unmount, updateStore, onSnapshot, onSnapshotDiff, toSnapshot, applySnapshot, createContext, };
7
+ export { observable, computed, source, reportChanged, reportObserved, getSignal, isObservable, reaction, Signal, ReadonlySignal, batch, untracked, effect, Observable, signal, } from "./observables";
8
+ export * from "./decorators";
9
+ export type { Configuration, Snapshot, IdType, SnapshotDiff } from "./types";
10
+ export type { Context } from "./context";
@@ -0,0 +1,35 @@
1
+ import { ArrayAdministration } from "../observables";
2
+ export declare function notifyArrayUpdate<T>(arr: T[], index: number, oldValue: T, newValue: T): void;
3
+ export declare function notifySpliceArray<T>(arr: T[], index: number, added: T[], removed: T[]): void;
4
+ export declare function observe<T>(obj: object, method: MutationListener<T>): () => void;
5
+ export type UpdateArrayEvent<T> = {
6
+ object: T[];
7
+ type: "updateArray";
8
+ index: number;
9
+ oldValue: T;
10
+ newValue: T;
11
+ };
12
+ export type SpliceArrayEvent<T> = {
13
+ object: T[];
14
+ type: "spliceArray";
15
+ index: number;
16
+ added: T[];
17
+ removed: T[];
18
+ };
19
+ export type MutationEvent<T> = UpdateArrayEvent<T> | SpliceArrayEvent<T>;
20
+ export type MutationListener<T> = (ev: MutationEvent<T>) => void;
21
+ export type HasListener<T> = {
22
+ listener: ObservableListener<T>;
23
+ };
24
+ declare class ObservableListener<T> {
25
+ private listeners;
26
+ private notifying;
27
+ subscribe(l: MutationListener<T>): () => void;
28
+ get size(): number;
29
+ notify(ev: MutationEvent<T>): void;
30
+ }
31
+ export declare class ChildModelsAdministration<T> extends ArrayAdministration<T> {
32
+ set(index: number, newValue: T): void;
33
+ spliceWithArray(index: number, deleteCount?: number | undefined, newItems?: T[] | undefined): T[];
34
+ }
35
+ export {};
@@ -0,0 +1,17 @@
1
+ import { ModelConfiguration, Snapshot } from "../types";
2
+ type ExtractModelDidInitArgs<T extends Model> = T extends {
3
+ modelDidInit(...args: infer Args): unknown;
4
+ } ? Args extends [infer Snapshot, ...infer Rest] ? Rest : [] : [];
5
+ export default class Model {
6
+ static get types(): ModelConfiguration<unknown>;
7
+ static childTypes: object;
8
+ static create<T extends Model = Model>(this: {
9
+ new (...args: unknown[]): T;
10
+ }, snapshot?: Snapshot<T>, ...args: ExtractModelDidInitArgs<T>): T;
11
+ constructor();
12
+ get parent(): Model | null;
13
+ modelDidInit(snapshot?: Snapshot<this>, ...args: unknown[]): void;
14
+ modelDidAttach(): void;
15
+ modelWillDetach(): void;
16
+ }
17
+ export {};
@@ -0,0 +1,42 @@
1
+ import { PreactObjectAdministration, ComputedNode, AtomNode } from "../observables";
2
+ import Model from "../model/Model";
3
+ import { ModelConfiguration, Snapshot, SnapshotChange } from "../types";
4
+ export declare function getConfigurationFromSnapshot(snapshot: object): ModelConfiguration<unknown> | undefined;
5
+ export declare function getModelAdm<T extends Model>(model: T): ModelAdministration;
6
+ export declare class ModelAdministration extends PreactObjectAdministration<any> {
7
+ static proxyTraps: ProxyHandler<object>;
8
+ private configurationGetter?;
9
+ private _parent;
10
+ private parentAtom;
11
+ referencedAtoms: Map<PropertyKey, AtomNode>;
12
+ referencedModels: Map<PropertyKey, ComputedNode<Model[]>>;
13
+ activeModels: Set<PropertyKey>;
14
+ root: ModelAdministration;
15
+ private modelsTraceUnsub;
16
+ private writeInProgress;
17
+ private computedSnapshot;
18
+ private snapshotMap;
19
+ private contextCache;
20
+ parentName: PropertyKey | null;
21
+ get parent(): ModelAdministration | null;
22
+ set parent(value: ModelAdministration | null);
23
+ setConfiguration(configurationGetter: () => ModelConfiguration<any>): void;
24
+ private get configuration();
25
+ private getReferencedAtom;
26
+ private setState;
27
+ private setId;
28
+ private setModel;
29
+ private setModels;
30
+ private getModelRef;
31
+ private getModelRefs;
32
+ private setModelRef;
33
+ private setModelRefs;
34
+ private attach;
35
+ private detach;
36
+ getContextValue<T>(contextId: symbol, provideSymbol: symbol, defaultValue: T | undefined, hasDefault: boolean): T;
37
+ private lookupContextValue;
38
+ private toJSON;
39
+ onSnapshotChange(onChange: SnapshotChange<any>): () => void;
40
+ loadSnapshot(snapshot: Snapshot<any>): void;
41
+ getSnapshot(): Snapshot<any>;
42
+ }
@@ -0,0 +1,8 @@
1
+ import { IdType } from "../types";
2
+ import Model from "./Model";
3
+ export declare function onSnapshotLoad<T>(fn: () => T): T;
4
+ export declare function setIdentifier(model: Model, id: string | number): void;
5
+ export declare function getIdentifier(model: Model): IdType | undefined;
6
+ export declare function getModelById(root: Model, id: IdType): Model | undefined;
7
+ export declare function onModelAttached(model: Model): void;
8
+ export declare function onModelDetached(model: Model): void;
@@ -0,0 +1,21 @@
1
+ import { AtomNode } from "./preact";
2
+ import { Administration } from "./internal/Administration";
3
+ import { SignalMap } from "./internal/NodeMap";
4
+ export declare class ArrayAdministration<T> extends Administration<T[]> {
5
+ valuesMap: SignalMap<number>;
6
+ keysAtom: AtomNode;
7
+ static proxyTraps: ProxyHandler<Array<unknown>>;
8
+ static methods: Partial<{
9
+ [K in keyof typeof Array.prototype as (typeof Array.prototype)[K] extends Function ? K : never]: (typeof Array.prototype)[K];
10
+ }>;
11
+ constructor(source?: T[]);
12
+ protected reportObserveDeep(): void;
13
+ getNode(key?: number): unknown;
14
+ get(index: number): T | undefined;
15
+ set(index: number, newValue: T): void;
16
+ getArrayLength(): number;
17
+ setArrayLength(newLength: number): void;
18
+ spliceWithArray(index: number, deleteCount?: number, newItems?: T[]): T[];
19
+ spliceItemsIntoValues(index: number, deleteCount: number, newItems: T[]): T[];
20
+ onArrayChanged(lengthChanged?: boolean, index?: number, count?: number): void;
21
+ }
@@ -0,0 +1,43 @@
1
+ import { AtomNode } from "./preact";
2
+ import { Administration } from "./internal/Administration";
3
+ import { AtomMap, SignalMap } from "./internal/NodeMap";
4
+ type Collection<K, V> = Set<K> | Map<K, V>;
5
+ export declare class CollectionAdministration<K, V = K> extends Administration<Collection<K, V>> {
6
+ isMap: boolean;
7
+ hasMap: AtomMap<K>;
8
+ valuesMap: SignalMap<K>;
9
+ keysAtom: AtomNode;
10
+ static proxyTraps: ProxyHandler<Set<unknown> | Map<unknown, unknown>>;
11
+ static methods: {
12
+ clear: (this: any) => unknown;
13
+ forEach: (this: any) => unknown;
14
+ has: (this: any) => unknown;
15
+ add: (this: any) => unknown;
16
+ set: (this: any) => unknown;
17
+ get: (this: any) => unknown;
18
+ delete: (this: any) => unknown;
19
+ entries: (this: any) => unknown;
20
+ keys: (this: any) => unknown;
21
+ values: (this: any) => unknown;
22
+ [Symbol.iterator]: (this: any) => unknown;
23
+ };
24
+ constructor(source: Collection<K, V>);
25
+ private hasEntry;
26
+ private onCollectionChange;
27
+ protected reportObserveDeep(): void;
28
+ getNode(key?: K): unknown;
29
+ clear(): void;
30
+ forEach(callbackFn: (value: V, key: K, collection: Collection<K, V>) => void, thisArg?: unknown): void;
31
+ get size(): number;
32
+ add(value: K): this;
33
+ delete(value: K): boolean;
34
+ has(value: K): boolean;
35
+ entries(): IterableIterator<[K, V]>;
36
+ keys(): IterableIterator<K>;
37
+ get(key: K): V | undefined;
38
+ set(key: K, value: V): this;
39
+ values(): IterableIterator<V>;
40
+ [Symbol.iterator](): IterableIterator<[K, V] | V>;
41
+ [Symbol.toStringTag]: string;
42
+ }
43
+ export {};
@@ -0,0 +1,4 @@
1
+ import { Administration } from "./internal/Administration";
2
+ export declare class DateAdministration extends Administration<Date> {
3
+ static proxyTraps: ProxyHandler<Date>;
4
+ }
@@ -0,0 +1,6 @@
1
+ export { getAdministration, getSource, isObservable, getObservable, getObservableClassInstance, getInternalNode, createObservableWithCustomAdministration, } from "./internal/lookup";
2
+ export { ArrayAdministration } from "./array";
3
+ export { CollectionAdministration } from "./collection";
4
+ export { DateAdministration } from "./date";
5
+ export { ObjectAdministration } from "./object";
6
+ export { AtomNode, reaction, SignalNode, createAtom, batch, createComputed, createSignal, untracked, ListenerNode, createListener, ComputedNode, PreactObjectAdministration, getSignal, source, reportChanged, reportObserved, observable, computed, Signal, ReadonlySignal, effect, signal, Observable, } from "./preact";
@@ -0,0 +1,17 @@
1
+ import { ObservedAtomNode } from "../preact";
2
+ import { SignalMap } from "./NodeMap";
3
+ export declare class Administration<T extends object = any> {
4
+ static readonly proxyTraps: ProxyHandler<object>;
5
+ readonly proxy: T;
6
+ readonly source: T;
7
+ readonly atom: ObservedAtomNode;
8
+ protected valuesMap?: SignalMap;
9
+ protected isObserved: boolean;
10
+ private forceObservedAtoms?;
11
+ constructor(source: T);
12
+ protected flushChange(): void;
13
+ getNode(): unknown;
14
+ reportChanged(): void;
15
+ protected reportObserveDeep(): void;
16
+ reportObserved(deep?: boolean): void;
17
+ }
@@ -0,0 +1,23 @@
1
+ import { AtomNode, ObservedAtomNode, SignalNode } from "../preact";
2
+ declare class NodeMap<K = unknown, GraphNode extends AtomNode | SignalNode<unknown> = AtomNode | SignalNode<unknown>> {
3
+ private map;
4
+ private weakMap;
5
+ private observedAtom?;
6
+ private cleanUpRegistered;
7
+ constructor(observedAtom?: ObservedAtomNode);
8
+ private registerCleanup;
9
+ protected createNode(_initialValue?: unknown): GraphNode;
10
+ get(key: unknown): GraphNode | undefined;
11
+ delete(key: K): void;
12
+ add(key: K, atom: GraphNode): void;
13
+ getOrCreate(key: K, value?: unknown): GraphNode;
14
+ reportObserved(key: K, value?: unknown): void;
15
+ reportChanged(key: K, value?: unknown): void;
16
+ }
17
+ export declare class AtomMap<K = unknown> extends NodeMap<K, AtomNode> {
18
+ protected createNode(): AtomNode;
19
+ }
20
+ export declare class SignalMap<K = unknown, V = unknown> extends NodeMap<K, SignalNode<V>> {
21
+ protected createNode(initialValue?: unknown): SignalNode<V>;
22
+ }
23
+ export {};
@@ -0,0 +1,14 @@
1
+ import { CollectionAdministration } from "../collection";
2
+ import { PreactObjectAdministration } from "../preact";
3
+ import { ArrayAdministration } from "../array";
4
+ import { DateAdministration } from "../date";
5
+ import { Administration } from "./Administration";
6
+ export declare function getAdministration<T extends object>(obj: T): T extends Set<infer S> ? CollectionAdministration<S> : T extends Map<infer K, infer V> ? CollectionAdministration<K, V> : T extends Array<infer R> ? ArrayAdministration<R> : T extends Date ? DateAdministration : PreactObjectAdministration<any>;
7
+ export declare function getSource<T>(obj: T): T;
8
+ export declare function getAction<T extends Function>(fn: T): T;
9
+ export declare function getObservableClassInstance<T extends object>(value: T): T;
10
+ export declare function getObservableIfExists<T>(value: T): T | undefined;
11
+ export declare function createObservableWithCustomAdministration<T>(value: T, Adm: new (obj: any) => Administration): T;
12
+ export declare function getObservable<T>(value: T): T;
13
+ export declare function isObservable(obj: unknown): boolean;
14
+ export declare function getInternalNode(obj: object, key?: PropertyKey): any;
@@ -0,0 +1,9 @@
1
+ import { AtomNode, ComputedNode, SignalNode } from "../preact";
2
+ export declare function defaultEquals<T>(a: T, b: T): boolean;
3
+ export declare function isNonPrimitive(val: unknown): val is object;
4
+ export declare function isPropertyKey(val: unknown): val is string | number | symbol;
5
+ export type PropertyType = "action" | "computed" | "observable";
6
+ export declare function getPropertyType(key: PropertyKey, obj: object): PropertyType | null;
7
+ export declare function getPropertyDescriptor(obj: object, key: PropertyKey): PropertyDescriptor | undefined;
8
+ export declare function isPlainObject(value: unknown): value is object;
9
+ export declare function resolveNode(node: SignalNode<unknown> | AtomNode | ComputedNode<unknown>): unknown;
@@ -0,0 +1,25 @@
1
+ import { AtomNode, ComputedNode } from "./preact";
2
+ import { PropertyType } from "./internal/utils";
3
+ import { Administration } from "./internal/Administration";
4
+ import { AtomMap, SignalMap } from "./internal/NodeMap";
5
+ export declare class ObjectAdministration<T extends object> extends Administration<T> {
6
+ keysAtom: AtomNode;
7
+ hasMap: AtomMap<PropertyKey>;
8
+ valuesMap: SignalMap<PropertyKey>;
9
+ computedMap: Map<PropertyKey, ComputedNode<T[keyof T]>>;
10
+ types: Map<PropertyKey, PropertyType | null>;
11
+ static proxyTraps: ProxyHandler<object>;
12
+ constructor(source?: T);
13
+ private get;
14
+ private set;
15
+ private getComputed;
16
+ private callComputed;
17
+ private getType;
18
+ protected reportObserveDeep(): void;
19
+ reportChanged(): void;
20
+ getNode(key?: keyof T): unknown;
21
+ read(key: keyof T): unknown;
22
+ write(key: keyof T, newValue: T[keyof T]): void;
23
+ has(key: keyof T): boolean;
24
+ remove(key: keyof T): void;
25
+ }
@@ -0,0 +1,69 @@
1
+ import { signal, Signal, ReadonlySignal, batch, effect, untracked } from "@preact/signals-core";
2
+ import { ObjectAdministration } from "./object";
3
+ export { isObservable } from "./index";
4
+ export declare class PreactObjectAdministration<T extends object> extends ObjectAdministration<T> {
5
+ static proxyTraps: ProxyHandler<object>;
6
+ }
7
+ export interface AtomNode {
8
+ reportObserved(): void;
9
+ reportChanged(val?: unknown): void;
10
+ node?: Signal<unknown>;
11
+ }
12
+ export type ObservedAtomNode = AtomNode & {
13
+ observing: boolean;
14
+ onObservedStateChange(callback: (observing: boolean) => void): () => void;
15
+ };
16
+ export interface SignalNode<T> {
17
+ reportObserved(): void;
18
+ reportChanged(val: T): void;
19
+ node?: Signal<T>;
20
+ get: () => T;
21
+ set: (value: T) => T;
22
+ }
23
+ export interface ComputedNode<T> {
24
+ get(): T;
25
+ node?: ReadonlySignal<T>;
26
+ clear: () => void;
27
+ }
28
+ export interface ListenerNode {
29
+ dispose: () => void;
30
+ track: <T>(trackFn: () => T) => T;
31
+ isDisposed: boolean;
32
+ }
33
+ export declare function createObservedAtom(): {
34
+ node: Signal<number>;
35
+ reportObserved(): number;
36
+ reportChanged(): number;
37
+ readonly observing: boolean;
38
+ onObservedStateChange(callback: (observing: boolean) => void): () => void;
39
+ };
40
+ export declare function createSignal<T>(initialValue: T): SignalNode<T>;
41
+ export declare function createAtom(): AtomNode;
42
+ export { effect, signal, batch, untracked, Signal, ReadonlySignal };
43
+ export declare function reaction<T>(fn: () => T, callback: (value: T) => void): () => void;
44
+ export type Listener = {
45
+ dispose: () => void;
46
+ track: <T>(trackFn: () => T) => T;
47
+ isDisposed: boolean;
48
+ callback(listener: Listener): void;
49
+ };
50
+ export declare function createListener(callback: (listener: Listener) => void): Listener;
51
+ export declare function createComputed<T>(fn: () => T, context?: unknown): ComputedNode<T>;
52
+ export type PreactObservable<T> = T extends Function ? T : T extends Map<infer K, infer V> ? Map<K, PreactObservable<V>> : T extends Array<infer V> ? Array<PreactObservable<V>> : T extends Set<infer V> ? Set<PreactObservable<V>> : T extends WeakSet<infer V> ? WeakSet<PreactObservable<V>> : T extends WeakMap<infer K, infer V> ? WeakMap<K, PreactObservable<V>> : {
53
+ [key in keyof T]: T[key] extends object ? PreactObservable<T[key]> : T[key];
54
+ } & {
55
+ readonly [key in keyof T as T[key] extends object ? never : `$${string & key}`]?: Signal<T[key]>;
56
+ };
57
+ export declare function observable<T>(obj: T): PreactObservable<T>;
58
+ export declare function observable(value: undefined, context: ClassFieldDecoratorContext): void;
59
+ export declare function computed<T>(value: () => T, context: ClassGetterDecoratorContext): void;
60
+ export declare function computed<T>(fn: () => T): ReadonlySignal<T>;
61
+ export declare function source<T>(obj: PreactObservable<T> | T): T;
62
+ export declare class Observable {
63
+ constructor();
64
+ }
65
+ export declare function reportChanged<T extends object>(obj: T): T;
66
+ export declare function reportObserved<T extends object>(obj: T, opts?: {
67
+ deep?: boolean;
68
+ }): T;
69
+ export declare function getSignal<T extends object>(obj: T, key: keyof T): Signal<T[keyof T]>;
@@ -1672,13 +1672,13 @@ function onSnapshotLoad(fn) {
1672
1672
  rootMap.set(root, set);
1673
1673
  }
1674
1674
  if (idMap.has(model2)) {
1675
- const id = idMap.get(model2);
1676
- if (set.has(id)) {
1675
+ const id2 = idMap.get(model2);
1676
+ if (set.has(id2)) {
1677
1677
  throw new Error(
1678
1678
  "r-state-tree duplicate ids detected after snapshot was loaded"
1679
1679
  );
1680
1680
  }
1681
- set.add(id);
1681
+ set.add(id2);
1682
1682
  }
1683
1683
  });
1684
1684
  } finally {
@@ -1687,40 +1687,40 @@ function onSnapshotLoad(fn) {
1687
1687
  }
1688
1688
  }
1689
1689
  }
1690
- function setIdentifier(model2, id) {
1690
+ function setIdentifier(model2, id2) {
1691
1691
  const prevId = idMap.get(model2);
1692
- idMap.set(model2, id);
1692
+ idMap.set(model2, id2);
1693
1693
  if (prevId == null) {
1694
1694
  if (model2.parent) {
1695
1695
  onModelAttached(model2);
1696
1696
  }
1697
- } else if (prevId !== id) {
1697
+ } else if (prevId !== id2) {
1698
1698
  updateIdentifier(model2);
1699
1699
  }
1700
1700
  }
1701
1701
  function getIdentifier(model2) {
1702
1702
  return idMap.get(model2);
1703
1703
  }
1704
- function getModelById(root, id) {
1704
+ function getModelById(root, id2) {
1705
1705
  const map = attachedIdMap.get(root);
1706
- return map?.get(id);
1706
+ return map?.get(id2);
1707
1707
  }
1708
1708
  function updateIdentifier(model2) {
1709
- const id = idMap.get(model2);
1709
+ const id2 = idMap.get(model2);
1710
1710
  let node = model2.parent;
1711
1711
  while (node) {
1712
1712
  const map = attachedIdMap.get(node);
1713
1713
  if (map) {
1714
- map.set(id, model2);
1714
+ map.set(id2, model2);
1715
1715
  }
1716
1716
  node = node.parent;
1717
1717
  }
1718
1718
  }
1719
1719
  function onModelAttached(model2) {
1720
1720
  const attachedMap = attachedIdMap.get(model2);
1721
- const id = idMap.get(model2);
1722
- if (attachedMap || id != null) {
1723
- const id2 = idMap.get(model2);
1721
+ const id2 = idMap.get(model2);
1722
+ if (attachedMap || id2 != null) {
1723
+ const id22 = idMap.get(model2);
1724
1724
  let node = model2.parent;
1725
1725
  while (node) {
1726
1726
  let map = attachedIdMap.get(node);
@@ -1741,26 +1741,26 @@ function onModelAttached(model2) {
1741
1741
  }
1742
1742
  map.set(key, value);
1743
1743
  });
1744
- if (id2 != null) {
1745
- if (map.has(id2)) {
1744
+ if (id22 != null) {
1745
+ if (map.has(id22)) {
1746
1746
  if (loadingSnapshot) {
1747
1747
  potentialDups.add(model2);
1748
- potentialDups.add(map.get(id2));
1748
+ potentialDups.add(map.get(id22));
1749
1749
  } else {
1750
1750
  throw new Error(
1751
- `r-state-tree: id: ${id2} is already assigned to another model`
1751
+ `r-state-tree: id: ${id22} is already assigned to another model`
1752
1752
  );
1753
1753
  }
1754
1754
  }
1755
- map.set(id2, model2);
1755
+ map.set(id22, model2);
1756
1756
  }
1757
1757
  node = node.parent;
1758
1758
  }
1759
1759
  }
1760
1760
  }
1761
1761
  function onModelDetached(model2) {
1762
- const id = idMap.get(model2);
1763
- if (attachedIdMap.has(model2) || id != null) {
1762
+ const id2 = idMap.get(model2);
1763
+ if (attachedIdMap.has(model2) || id2 != null) {
1764
1764
  const attachedMap = attachedIdMap.get(model2);
1765
1765
  let node = model2.parent;
1766
1766
  while (node) {
@@ -1769,8 +1769,8 @@ function onModelDetached(model2) {
1769
1769
  attachedMap?.forEach((value, key) => {
1770
1770
  map.delete(key);
1771
1771
  });
1772
- if (id != null) {
1773
- map.delete(id);
1772
+ if (id2 != null) {
1773
+ map.delete(id2);
1774
1774
  }
1775
1775
  }
1776
1776
  node = node.parent;
@@ -2015,13 +2015,13 @@ class ModelAdministration extends PreactObjectAdministration {
2015
2015
  }
2016
2016
  }
2017
2017
  setId(name, v) {
2018
- const id = getIdentifier(this.proxy);
2019
- if (id === v) {
2018
+ const id2 = getIdentifier(this.proxy);
2019
+ if (id2 === v) {
2020
2020
  return;
2021
2021
  }
2022
- if (id != null && v == null) {
2022
+ if (id2 != null && v == null) {
2023
2023
  throw new Error(
2024
- "r-state-tree can't clear an identifier once it has already been set."
2024
+ "r-state-tree can't clear an id once it has already been set."
2025
2025
  );
2026
2026
  }
2027
2027
  if (v !== void 0) {
@@ -2107,7 +2107,7 @@ class ModelAdministration extends PreactObjectAdministration {
2107
2107
  if (!this.referencedModels) this.referencedModels = /* @__PURE__ */ new Map();
2108
2108
  c = createComputed(() => {
2109
2109
  a.reportObserved();
2110
- const models = (this.source[name] || []).map((id) => getModelById(this.root.proxy, id)).filter((m) => !!m);
2110
+ const models = (this.source[name] || []).map((id2) => getModelById(this.root.proxy, id2)).filter((m) => !!m);
2111
2111
  return models;
2112
2112
  });
2113
2113
  this.referencedModels.set(name, c);
@@ -2115,27 +2115,27 @@ class ModelAdministration extends PreactObjectAdministration {
2115
2115
  return c.get();
2116
2116
  }
2117
2117
  setModelRef(name, modelValue) {
2118
- let id = void 0;
2118
+ let id2 = void 0;
2119
2119
  if (modelValue) {
2120
- id = getIdentifier(modelValue);
2121
- if (id == null) {
2120
+ id2 = getIdentifier(modelValue);
2121
+ if (id2 == null) {
2122
2122
  throw new Error(
2123
2123
  "r-state-tree: Only models with identifiers can be used as a ref"
2124
2124
  );
2125
2125
  }
2126
2126
  }
2127
- this.source[name] = id;
2127
+ this.source[name] = id2;
2128
2128
  this.referencedAtoms?.get(name)?.reportChanged();
2129
2129
  }
2130
2130
  setModelRefs(name, modelValue) {
2131
2131
  const ids = modelValue.map((model2) => {
2132
- const id = getIdentifier(model2);
2133
- if (id == null) {
2132
+ const id2 = getIdentifier(model2);
2133
+ if (id2 == null) {
2134
2134
  throw new Error(
2135
2135
  "r-state-tree: Only models with identifiers can be used as a ref"
2136
2136
  );
2137
2137
  }
2138
- return id;
2138
+ return id2;
2139
2139
  });
2140
2140
  this.source[name] = ids;
2141
2141
  this.referencedAtoms?.get(name)?.reportChanged();
@@ -2304,8 +2304,8 @@ class ModelAdministration extends PreactObjectAdministration {
2304
2304
  model22 = snapshot2;
2305
2305
  } else {
2306
2306
  ensureChildTypes(key);
2307
- const id = childType2 && getSnapshotId(snapshot2, Ctor);
2308
- const foundModel = id != null ? getModelById(this.root.proxy, id) : this.proxy[key][index];
2307
+ const id2 = childType2 && getSnapshotId(snapshot2, Ctor);
2308
+ const foundModel = id2 != null ? getModelById(this.root.proxy, id2) : this.proxy[key][index];
2309
2309
  const adm = foundModel && getModelAdm(foundModel);
2310
2310
  if (adm && foundModel.parent === this.proxy && adm?.parentName === key) {
2311
2311
  adm.loadSnapshot(snapshot2);
@@ -2322,8 +2322,8 @@ class ModelAdministration extends PreactObjectAdministration {
2322
2322
  model2 = value;
2323
2323
  } else {
2324
2324
  ensureChildTypes(key);
2325
- const id = childType2 && getSnapshotId(value, childType2);
2326
- if (id != null && this.proxy[key] && id === getIdentifier(this.proxy[key])) {
2325
+ const id2 = childType2 && getSnapshotId(value, childType2);
2326
+ if (id2 != null && this.proxy[key] && id2 === getIdentifier(this.proxy[key])) {
2327
2327
  const adm = getModelAdm(this.proxy[key]);
2328
2328
  adm.loadSnapshot(value);
2329
2329
  model2 = this.proxy[key];
@@ -2483,7 +2483,7 @@ function makeChildDecorator(typeObj) {
2483
2483
  const child = makeChildDecorator(childType);
2484
2484
  const modelRef = makeChildDecorator(modelRefType);
2485
2485
  const model = makeDecorator(modelType);
2486
- const identifier = makeDecorator(idType);
2486
+ const id = makeDecorator(idType);
2487
2487
  const state = makeDecorator(stateType);
2488
2488
  Object.defineProperty(exports, "ReadonlySignal", {
2489
2489
  enumerable: true,
@@ -2518,7 +2518,7 @@ exports.computed = computed;
2518
2518
  exports.createContext = createContext;
2519
2519
  exports.createStore = createStore;
2520
2520
  exports.getSignal = getSignal;
2521
- exports.identifier = identifier;
2521
+ exports.id = id;
2522
2522
  exports.isObservable = isObservable;
2523
2523
  exports.model = model;
2524
2524
  exports.modelRef = modelRef;
@@ -1671,13 +1671,13 @@ function onSnapshotLoad(fn) {
1671
1671
  rootMap.set(root, set);
1672
1672
  }
1673
1673
  if (idMap.has(model2)) {
1674
- const id = idMap.get(model2);
1675
- if (set.has(id)) {
1674
+ const id2 = idMap.get(model2);
1675
+ if (set.has(id2)) {
1676
1676
  throw new Error(
1677
1677
  "r-state-tree duplicate ids detected after snapshot was loaded"
1678
1678
  );
1679
1679
  }
1680
- set.add(id);
1680
+ set.add(id2);
1681
1681
  }
1682
1682
  });
1683
1683
  } finally {
@@ -1686,40 +1686,40 @@ function onSnapshotLoad(fn) {
1686
1686
  }
1687
1687
  }
1688
1688
  }
1689
- function setIdentifier(model2, id) {
1689
+ function setIdentifier(model2, id2) {
1690
1690
  const prevId = idMap.get(model2);
1691
- idMap.set(model2, id);
1691
+ idMap.set(model2, id2);
1692
1692
  if (prevId == null) {
1693
1693
  if (model2.parent) {
1694
1694
  onModelAttached(model2);
1695
1695
  }
1696
- } else if (prevId !== id) {
1696
+ } else if (prevId !== id2) {
1697
1697
  updateIdentifier(model2);
1698
1698
  }
1699
1699
  }
1700
1700
  function getIdentifier(model2) {
1701
1701
  return idMap.get(model2);
1702
1702
  }
1703
- function getModelById(root, id) {
1703
+ function getModelById(root, id2) {
1704
1704
  const map = attachedIdMap.get(root);
1705
- return map?.get(id);
1705
+ return map?.get(id2);
1706
1706
  }
1707
1707
  function updateIdentifier(model2) {
1708
- const id = idMap.get(model2);
1708
+ const id2 = idMap.get(model2);
1709
1709
  let node = model2.parent;
1710
1710
  while (node) {
1711
1711
  const map = attachedIdMap.get(node);
1712
1712
  if (map) {
1713
- map.set(id, model2);
1713
+ map.set(id2, model2);
1714
1714
  }
1715
1715
  node = node.parent;
1716
1716
  }
1717
1717
  }
1718
1718
  function onModelAttached(model2) {
1719
1719
  const attachedMap = attachedIdMap.get(model2);
1720
- const id = idMap.get(model2);
1721
- if (attachedMap || id != null) {
1722
- const id2 = idMap.get(model2);
1720
+ const id2 = idMap.get(model2);
1721
+ if (attachedMap || id2 != null) {
1722
+ const id22 = idMap.get(model2);
1723
1723
  let node = model2.parent;
1724
1724
  while (node) {
1725
1725
  let map = attachedIdMap.get(node);
@@ -1740,26 +1740,26 @@ function onModelAttached(model2) {
1740
1740
  }
1741
1741
  map.set(key, value);
1742
1742
  });
1743
- if (id2 != null) {
1744
- if (map.has(id2)) {
1743
+ if (id22 != null) {
1744
+ if (map.has(id22)) {
1745
1745
  if (loadingSnapshot) {
1746
1746
  potentialDups.add(model2);
1747
- potentialDups.add(map.get(id2));
1747
+ potentialDups.add(map.get(id22));
1748
1748
  } else {
1749
1749
  throw new Error(
1750
- `r-state-tree: id: ${id2} is already assigned to another model`
1750
+ `r-state-tree: id: ${id22} is already assigned to another model`
1751
1751
  );
1752
1752
  }
1753
1753
  }
1754
- map.set(id2, model2);
1754
+ map.set(id22, model2);
1755
1755
  }
1756
1756
  node = node.parent;
1757
1757
  }
1758
1758
  }
1759
1759
  }
1760
1760
  function onModelDetached(model2) {
1761
- const id = idMap.get(model2);
1762
- if (attachedIdMap.has(model2) || id != null) {
1761
+ const id2 = idMap.get(model2);
1762
+ if (attachedIdMap.has(model2) || id2 != null) {
1763
1763
  const attachedMap = attachedIdMap.get(model2);
1764
1764
  let node = model2.parent;
1765
1765
  while (node) {
@@ -1768,8 +1768,8 @@ function onModelDetached(model2) {
1768
1768
  attachedMap?.forEach((value, key) => {
1769
1769
  map.delete(key);
1770
1770
  });
1771
- if (id != null) {
1772
- map.delete(id);
1771
+ if (id2 != null) {
1772
+ map.delete(id2);
1773
1773
  }
1774
1774
  }
1775
1775
  node = node.parent;
@@ -2014,13 +2014,13 @@ class ModelAdministration extends PreactObjectAdministration {
2014
2014
  }
2015
2015
  }
2016
2016
  setId(name, v) {
2017
- const id = getIdentifier(this.proxy);
2018
- if (id === v) {
2017
+ const id2 = getIdentifier(this.proxy);
2018
+ if (id2 === v) {
2019
2019
  return;
2020
2020
  }
2021
- if (id != null && v == null) {
2021
+ if (id2 != null && v == null) {
2022
2022
  throw new Error(
2023
- "r-state-tree can't clear an identifier once it has already been set."
2023
+ "r-state-tree can't clear an id once it has already been set."
2024
2024
  );
2025
2025
  }
2026
2026
  if (v !== void 0) {
@@ -2106,7 +2106,7 @@ class ModelAdministration extends PreactObjectAdministration {
2106
2106
  if (!this.referencedModels) this.referencedModels = /* @__PURE__ */ new Map();
2107
2107
  c = createComputed(() => {
2108
2108
  a.reportObserved();
2109
- const models = (this.source[name] || []).map((id) => getModelById(this.root.proxy, id)).filter((m) => !!m);
2109
+ const models = (this.source[name] || []).map((id2) => getModelById(this.root.proxy, id2)).filter((m) => !!m);
2110
2110
  return models;
2111
2111
  });
2112
2112
  this.referencedModels.set(name, c);
@@ -2114,27 +2114,27 @@ class ModelAdministration extends PreactObjectAdministration {
2114
2114
  return c.get();
2115
2115
  }
2116
2116
  setModelRef(name, modelValue) {
2117
- let id = void 0;
2117
+ let id2 = void 0;
2118
2118
  if (modelValue) {
2119
- id = getIdentifier(modelValue);
2120
- if (id == null) {
2119
+ id2 = getIdentifier(modelValue);
2120
+ if (id2 == null) {
2121
2121
  throw new Error(
2122
2122
  "r-state-tree: Only models with identifiers can be used as a ref"
2123
2123
  );
2124
2124
  }
2125
2125
  }
2126
- this.source[name] = id;
2126
+ this.source[name] = id2;
2127
2127
  this.referencedAtoms?.get(name)?.reportChanged();
2128
2128
  }
2129
2129
  setModelRefs(name, modelValue) {
2130
2130
  const ids = modelValue.map((model2) => {
2131
- const id = getIdentifier(model2);
2132
- if (id == null) {
2131
+ const id2 = getIdentifier(model2);
2132
+ if (id2 == null) {
2133
2133
  throw new Error(
2134
2134
  "r-state-tree: Only models with identifiers can be used as a ref"
2135
2135
  );
2136
2136
  }
2137
- return id;
2137
+ return id2;
2138
2138
  });
2139
2139
  this.source[name] = ids;
2140
2140
  this.referencedAtoms?.get(name)?.reportChanged();
@@ -2303,8 +2303,8 @@ class ModelAdministration extends PreactObjectAdministration {
2303
2303
  model22 = snapshot2;
2304
2304
  } else {
2305
2305
  ensureChildTypes(key);
2306
- const id = childType2 && getSnapshotId(snapshot2, Ctor);
2307
- const foundModel = id != null ? getModelById(this.root.proxy, id) : this.proxy[key][index];
2306
+ const id2 = childType2 && getSnapshotId(snapshot2, Ctor);
2307
+ const foundModel = id2 != null ? getModelById(this.root.proxy, id2) : this.proxy[key][index];
2308
2308
  const adm = foundModel && getModelAdm(foundModel);
2309
2309
  if (adm && foundModel.parent === this.proxy && adm?.parentName === key) {
2310
2310
  adm.loadSnapshot(snapshot2);
@@ -2321,8 +2321,8 @@ class ModelAdministration extends PreactObjectAdministration {
2321
2321
  model2 = value;
2322
2322
  } else {
2323
2323
  ensureChildTypes(key);
2324
- const id = childType2 && getSnapshotId(value, childType2);
2325
- if (id != null && this.proxy[key] && id === getIdentifier(this.proxy[key])) {
2324
+ const id2 = childType2 && getSnapshotId(value, childType2);
2325
+ if (id2 != null && this.proxy[key] && id2 === getIdentifier(this.proxy[key])) {
2326
2326
  const adm = getModelAdm(this.proxy[key]);
2327
2327
  adm.loadSnapshot(value);
2328
2328
  model2 = this.proxy[key];
@@ -2482,7 +2482,7 @@ function makeChildDecorator(typeObj) {
2482
2482
  const child = makeChildDecorator(childType);
2483
2483
  const modelRef = makeChildDecorator(modelRefType);
2484
2484
  const model = makeDecorator(modelType);
2485
- const identifier = makeDecorator(idType);
2485
+ const id = makeDecorator(idType);
2486
2486
  const state = makeDecorator(stateType);
2487
2487
  export {
2488
2488
  Model,
@@ -2498,7 +2498,7 @@ export {
2498
2498
  createStore,
2499
2499
  effect2 as effect,
2500
2500
  getSignal,
2501
- identifier,
2501
+ id,
2502
2502
  isObservable,
2503
2503
  model,
2504
2504
  modelRef,
@@ -0,0 +1,20 @@
1
+ import { Props, StoreConfiguration } from "../types";
2
+ export declare function allowNewStore<T>(fn: () => T): T;
3
+ type CreateStoreProps<T extends Props> = {
4
+ [K in keyof T as undefined extends T[K] ? K : never]?: T[K] extends infer U ? U extends undefined ? never : undefined extends U ? U | undefined : U : never;
5
+ } & {
6
+ [K in keyof T as undefined extends T[K] ? never : K]?: T[K];
7
+ } & Pick<Props, 'key'>;
8
+ export declare function createStore<K extends Store<T>, T extends Props>(Type: new (props: T) => K, props?: CreateStoreProps<T>): K;
9
+ export declare function updateStore<K extends Store<T>, T extends Props>(store: K, props: CreateStoreProps<T>): K;
10
+ export declare function types<T extends Store>(config: Partial<StoreConfiguration<T>>): Partial<StoreConfiguration<T>>;
11
+ export default class Store<PropsType extends Props = Props> {
12
+ static get types(): StoreConfiguration<unknown>;
13
+ props: PropsType;
14
+ constructor(props: PropsType);
15
+ get key(): string | number | undefined;
16
+ reaction<T>(track: () => T, callback: (a: T) => void): () => void;
17
+ storeDidMount(): void;
18
+ storeWillUnmount(): void;
19
+ }
20
+ export {};
@@ -0,0 +1,30 @@
1
+ import { PreactObjectAdministration as ObjectAdministration } from "../observables";
2
+ import Store from "./Store";
3
+ import { StoreConfiguration, Props } from "../types";
4
+ export declare function updateProps(props: Props, newProps: Props): void;
5
+ export declare function getStoreAdm(store: Store): StoreAdministration;
6
+ export declare class StoreAdministration<StoreType extends Store = Store> extends ObjectAdministration<Store> {
7
+ static proxyTraps: ProxyHandler<object>;
8
+ parent: StoreAdministration | null;
9
+ mounted: boolean;
10
+ private contextCache;
11
+ private childStoreDataMap;
12
+ private reactionsUnsub;
13
+ private configurationGetter?;
14
+ setConfiguration(configurationGetter: () => StoreConfiguration<StoreType>): void;
15
+ private get configuration();
16
+ private createChildStore;
17
+ private setStoreList;
18
+ private setSingleStore;
19
+ private updateStore;
20
+ private getComputedGetter;
21
+ private initializeStore;
22
+ private getStore;
23
+ private getModelRef;
24
+ isRoot(): boolean;
25
+ getContextValue<T>(contextId: symbol, provideSymbol: symbol, defaultValue: T | undefined, hasDefault: boolean): T;
26
+ private lookupContextValue;
27
+ reaction<T>(track: () => T, callback: (a: T) => void): () => void;
28
+ mount(parent?: StoreAdministration | null): void;
29
+ unmount(): void;
30
+ }
@@ -0,0 +1,73 @@
1
+ import Store from "./store/Store";
2
+ import Model from "./model/Model";
3
+ export type StoreElement = {
4
+ Type: new (...args: unknown[]) => Store;
5
+ props: Props;
6
+ key: string | number;
7
+ };
8
+ export type ChildStore = Store | Store[] | null;
9
+ export type Key = string | number | undefined;
10
+ export type Context = {
11
+ [key: string]: unknown;
12
+ };
13
+ export type Props = {
14
+ [key: string]: unknown;
15
+ key?: Key;
16
+ models?: {
17
+ [key: string]: Model | Model[] | null;
18
+ };
19
+ };
20
+ export type StoreCtor<S extends Store = Store> = (new (...args: ConstructorParameters<typeof Store>) => S) & {
21
+ [P in keyof Store]: Store[P];
22
+ };
23
+ export type ChildModel = Model | Model[] | null;
24
+ export type IdType = string | number;
25
+ export declare enum CommonCfgTypes {
26
+ child = "child"
27
+ }
28
+ export declare enum ModelCfgTypes {
29
+ state = "state",
30
+ id = "id",
31
+ modelRef = "modelRef"
32
+ }
33
+ export declare enum StoreCfgTypes {
34
+ model = "model"
35
+ }
36
+ export declare enum ObservableCfgTypes {
37
+ observable = "observable",
38
+ computed = "computed"
39
+ }
40
+ export type ConfigurationTypes = CommonCfgTypes | ModelCfgTypes | StoreCfgTypes | ObservableCfgTypes;
41
+ export type ConfigurationType = {
42
+ type: ConfigurationTypes;
43
+ childType?: Function;
44
+ [key: string]: unknown;
45
+ };
46
+ export type ModelConfiguration<T> = Record<PropertyKey, ConfigurationType>;
47
+ export type StoreConfiguration<T> = Record<PropertyKey, ConfigurationType>;
48
+ export type Configuration<T> = ModelConfiguration<T> | StoreConfiguration<T>;
49
+ type SnapshotValue<T> = T extends Model ? Snapshot<T> : T extends Array<infer R> ? R extends Model ? Array<Snapshot<R>> : T : T;
50
+ export type Snapshot<T extends Model = Model> = {
51
+ [K in keyof T]?: T[K] extends infer U ? U extends Model | Model[] ? SnapshotValue<U> | null : U extends null | undefined ? null : SnapshotValue<Exclude<U, null | undefined>> | null : never;
52
+ };
53
+ export type SnapshotDiff<T extends Model = Model> = {
54
+ undo: Snapshot<T>;
55
+ redo: Snapshot<T>;
56
+ };
57
+ export type SnapshotChange<T extends Model = Model> = (snapshot: Snapshot<T>, model: T) => void;
58
+ export type RefSnapshot = {
59
+ [key: string]: IdType;
60
+ [key: number]: IdType;
61
+ };
62
+ export declare const childType: ((childType: Function) => ConfigurationType) & {
63
+ type: CommonCfgTypes;
64
+ };
65
+ export declare const stateType: ConfigurationType;
66
+ export declare const modelRefType: ((childType: Function) => ConfigurationType) & {
67
+ type: ModelCfgTypes;
68
+ };
69
+ export declare const idType: ConfigurationType;
70
+ export declare const modelType: ConfigurationType;
71
+ export declare const observableType: ConfigurationType;
72
+ export declare const computedType: ConfigurationType;
73
+ export {};
@@ -0,0 +1,5 @@
1
+ import { ModelConfiguration } from "./types";
2
+ export declare function getPropertyDescriptor(obj: object, key: PropertyKey): PropertyDescriptor | undefined;
3
+ export declare function getParentConstructor(Ctor: Function | undefined): Function | undefined;
4
+ export declare function clone<T>(val: T): T;
5
+ export declare function getDiff<T extends object>(o1: T, o2: T, getConfig: (snapshot: object) => ModelConfiguration<unknown> | undefined): Partial<T> | null;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "r-state-tree",
3
- "version": "0.4.0",
3
+ "version": "0.4.2",
4
4
  "description": "reactive state management library",
5
5
  "main": "dist/r-state-tree.cjs",
6
6
  "module": "dist/r-state-tree.js",