r-state-tree 0.6.3 → 0.8.0
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 +190 -56
- package/dist/api.d.ts +2 -2
- package/dist/configuration.d.ts +10 -0
- package/dist/decorators.d.ts +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/model/Model.d.ts +6 -10
- package/dist/model/ModelAdministration.d.ts +14 -0
- package/dist/model/idMap.d.ts +4 -4
- package/dist/observables/preact.d.ts +1 -1
- package/dist/r-state-tree.cjs +657 -305
- package/dist/r-state-tree.js +657 -305
- package/dist/store/Store.d.ts +6 -5
- package/dist/store/StoreAdministration.d.ts +8 -4
- package/dist/types.d.ts +8 -7
- package/package.json +58 -57
package/README.md
CHANGED
|
@@ -14,7 +14,10 @@ pnpm add r-state-tree
|
|
|
14
14
|
|
|
15
15
|
### Requirements
|
|
16
16
|
|
|
17
|
-
This library
|
|
17
|
+
This library strongly recommends using decorators.
|
|
18
|
+
|
|
19
|
+
- Recommended: decorators (`@child`, `@model`, `@state`, `@id`, `@modelRef`, `@computed`). Requires TypeScript 5.0+ with `target: "es2022"` or higher.
|
|
20
|
+
- Fallback: `static types` configuration (no decorators) if you can't or don't want to enable decorators in your toolchain.
|
|
18
21
|
|
|
19
22
|
The library includes a decorator metadata polyfill for runtimes that don't yet natively support `Symbol.metadata`.
|
|
20
23
|
|
|
@@ -22,6 +25,8 @@ The library includes a decorator metadata polyfill for runtimes that don't yet n
|
|
|
22
25
|
|
|
23
26
|
TypeScript 5+ supports TC39 Stage 3 decorators.
|
|
24
27
|
|
|
28
|
+
Only needed if you use decorators.
|
|
29
|
+
|
|
25
30
|
```json
|
|
26
31
|
{
|
|
27
32
|
"compilerOptions": {
|
|
@@ -57,10 +62,10 @@ export default defineConfig({
|
|
|
57
62
|
|
|
58
63
|
## Core concepts
|
|
59
64
|
|
|
60
|
-
- Stores: application/view state containers. Create with `createStore()`, attach with `mount()`. Compose with `@child`
|
|
65
|
+
- Stores: application/view state containers. Create with `createStore()`, attach with `mount()`, and dispose with `Symbol.dispose`. Compose with `@child` and register owned `effect`/`reaction` behavior in constructors. Update reactive `props` via `updateStore()`.
|
|
61
66
|
- 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`.
|
|
62
67
|
- 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.
|
|
63
|
-
- Reactivity: powered by signals. Use `observable()`, `@computed`, `effect`, `reaction`, `batch`, and `untracked` for precise updates.
|
|
68
|
+
- Reactivity: powered by signals. Use `observable()`, `computed` / `@computed`, `effect`, `reaction`, `batch`, and `untracked` for precise updates.
|
|
64
69
|
|
|
65
70
|
## Separation of concerns
|
|
66
71
|
|
|
@@ -105,11 +110,36 @@ const app = mount(createStore(AppStore));
|
|
|
105
110
|
app.todo.title; // "Write docs"
|
|
106
111
|
```
|
|
107
112
|
|
|
113
|
+
Fallback (no decorators) using `static types`:
|
|
114
|
+
|
|
115
|
+
```ts
|
|
116
|
+
import { Store, createStore, mount, child } from "r-state-tree";
|
|
117
|
+
|
|
118
|
+
class TodoStore extends Store<{ title: string }> {
|
|
119
|
+
get title() {
|
|
120
|
+
return this.props.title;
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
class AppStore extends Store {
|
|
125
|
+
get todo() {
|
|
126
|
+
return createStore(TodoStore, { title: "Write docs" });
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
static types = {
|
|
130
|
+
todo: child,
|
|
131
|
+
};
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
const app = mount(createStore(AppStore));
|
|
135
|
+
app.todo.title;
|
|
136
|
+
```
|
|
137
|
+
|
|
108
138
|
### Store creation, props, and typing
|
|
109
139
|
|
|
110
140
|
- Always create with `createStore()` and attach with `mount()`. Stores cannot be constructed with `new` directly.
|
|
111
141
|
- Prefer no custom constructor. Type stores as `Store<Props>` and access props via `this.props`.
|
|
112
|
-
-
|
|
142
|
+
- Constructors may register framework-owned reactions and effects after `super(props)`. Gate external resource acquisition on `isMounted` and return cleanup from effects.
|
|
113
143
|
- Do not shadow or re-declare `props` as a class field; `props` is read-only. Use the generic `Store<{ ... }>` for typing.
|
|
114
144
|
|
|
115
145
|
```ts
|
|
@@ -173,20 +203,28 @@ class ItemsStore extends Store {
|
|
|
173
203
|
}
|
|
174
204
|
```
|
|
175
205
|
|
|
176
|
-
###
|
|
206
|
+
### Store lifetime and owned effects
|
|
177
207
|
|
|
178
|
-
|
|
208
|
+
Mounted stores expose reactive `isMounted` state and implement `Disposable`:
|
|
179
209
|
|
|
180
210
|
```ts
|
|
181
211
|
class TodoStore extends Store {
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
212
|
+
constructor(props) {
|
|
213
|
+
super(props);
|
|
214
|
+
this.effect(() => {
|
|
215
|
+
if (!this.isMounted) return;
|
|
216
|
+
const connection = connect();
|
|
217
|
+
return () => connection.close();
|
|
218
|
+
});
|
|
188
219
|
}
|
|
189
220
|
}
|
|
221
|
+
|
|
222
|
+
const store = mount(createStore(TodoStore));
|
|
223
|
+
store[Symbol.dispose]();
|
|
224
|
+
|
|
225
|
+
{
|
|
226
|
+
using store = mount(createStore(TodoStore));
|
|
227
|
+
} // Symbol.dispose is called automatically
|
|
190
228
|
```
|
|
191
229
|
|
|
192
230
|
### Reactions
|
|
@@ -195,10 +233,11 @@ Create side effects that run when reactive values change:
|
|
|
195
233
|
|
|
196
234
|
```ts
|
|
197
235
|
class TodoStore extends Store {
|
|
198
|
-
|
|
236
|
+
constructor(props) {
|
|
237
|
+
super(props);
|
|
199
238
|
this.reaction(
|
|
200
239
|
() => this.props.title,
|
|
201
|
-
(title) => console.log(
|
|
240
|
+
(title, previousTitle) => console.log(previousTitle, "->", title)
|
|
202
241
|
);
|
|
203
242
|
}
|
|
204
243
|
}
|
|
@@ -270,6 +309,35 @@ const profile = mount(createStore(ProfileStore, { models: { user } }));
|
|
|
270
309
|
profile.user.name; // "Ada"
|
|
271
310
|
```
|
|
272
311
|
|
|
312
|
+
Fallback (no decorators) using `static types`:
|
|
313
|
+
|
|
314
|
+
```ts
|
|
315
|
+
import {
|
|
316
|
+
Model,
|
|
317
|
+
Store,
|
|
318
|
+
createStore,
|
|
319
|
+
mount,
|
|
320
|
+
model,
|
|
321
|
+
id,
|
|
322
|
+
state,
|
|
323
|
+
} from "r-state-tree";
|
|
324
|
+
|
|
325
|
+
class User extends Model {
|
|
326
|
+
id = 0;
|
|
327
|
+
name = "";
|
|
328
|
+
static types = { id, name: state };
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
class ProfileStore extends Store {
|
|
332
|
+
user!: User;
|
|
333
|
+
static types = { user: model };
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
const user = User.create({ id: 1, name: "Ada" });
|
|
337
|
+
const profile = mount(createStore(ProfileStore, { models: { user } }));
|
|
338
|
+
profile.user.name;
|
|
339
|
+
```
|
|
340
|
+
|
|
273
341
|
Type stores as `Store<Props>` and explicitly type `@model` fields for clarity. The `models` prop may also provide arrays of models.
|
|
274
342
|
|
|
275
343
|
## Modeling guide
|
|
@@ -775,41 +843,61 @@ const off = onSnapshot(list, (snap) => {
|
|
|
775
843
|
|
|
776
844
|
Mutate Models through domain methods and let snapshots record changes automatically.
|
|
777
845
|
|
|
778
|
-
### Model
|
|
846
|
+
### Model creation and named factories
|
|
779
847
|
|
|
780
|
-
|
|
848
|
+
`Model.create()` accepts a canonical snapshot. For defaults, identifier generation, normalization, migrations, or external API formats, use a named static factory that prepares the input before calling `create()`:
|
|
781
849
|
|
|
782
850
|
```ts
|
|
783
851
|
class TodoModel extends Model {
|
|
784
|
-
@
|
|
852
|
+
@id id = "";
|
|
853
|
+
@state title = "";
|
|
785
854
|
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
855
|
+
static new(title = "Untitled") {
|
|
856
|
+
return this.create({
|
|
857
|
+
id: crypto.randomUUID(),
|
|
858
|
+
title: title.trim(),
|
|
859
|
+
});
|
|
790
860
|
}
|
|
791
861
|
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
862
|
+
static fromApi(input: ApiTodo) {
|
|
863
|
+
return this.create({
|
|
864
|
+
id: input.todo_id,
|
|
865
|
+
title: input.name.trim(),
|
|
866
|
+
});
|
|
795
867
|
}
|
|
868
|
+
}
|
|
869
|
+
|
|
870
|
+
const todo = TodoModel.new(" Write documentation ");
|
|
871
|
+
todo.title; // "Write documentation"
|
|
872
|
+
```
|
|
873
|
+
|
|
874
|
+
This keeps snapshot hydration predictable: `create(snapshot)` and `applySnapshot(model, snapshot)` both consume the same canonical shape. Named factories make non-canonical inputs and generated values explicit and independently typed. Nested snapshots must already be canonical.
|
|
875
|
+
|
|
876
|
+
### Model attachment and disposal
|
|
877
|
+
|
|
878
|
+
The public `parent` relationship is reactive. Register a model-owned reaction in the constructor to observe attachment and detachment:
|
|
879
|
+
|
|
880
|
+
```ts
|
|
881
|
+
class TodoModel extends Model {
|
|
882
|
+
@child tags: TagModel[] = [];
|
|
796
883
|
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
884
|
+
constructor() {
|
|
885
|
+
super();
|
|
886
|
+
this.reaction(() => this.parent, (parent, previousParent) => {
|
|
887
|
+
if (previousParent) console.log("detached", previousParent);
|
|
888
|
+
if (parent) console.log("attached", parent);
|
|
889
|
+
});
|
|
800
890
|
}
|
|
801
891
|
}
|
|
802
892
|
```
|
|
803
893
|
|
|
804
|
-
|
|
894
|
+
Detachment is reversible; model-owned effects survive reattachment. `model[Symbol.dispose]()` is terminal and recursively disposes owned child models, but never model refs.
|
|
805
895
|
|
|
806
|
-
|
|
807
|
-
- `modelDidAttach`: link to other models or read context after the model is part of a tree.
|
|
808
|
-
- `modelWillDetach`: cleanup before the model is removed or replaced.
|
|
896
|
+
### Model configuration
|
|
809
897
|
|
|
810
|
-
|
|
898
|
+
Recommended: configure model properties with decorators.
|
|
811
899
|
|
|
812
|
-
|
|
900
|
+
Fallback: if you can't or don't want to use decorators, use `static types`.
|
|
813
901
|
|
|
814
902
|
```ts
|
|
815
903
|
import { Model, state, id, child, modelRef } from "r-state-tree";
|
|
@@ -822,13 +910,41 @@ class User extends Model {
|
|
|
822
910
|
class TodoModel extends Model {
|
|
823
911
|
@id id = 0;
|
|
824
912
|
@state title = "";
|
|
825
|
-
@modelRef assignee?: User; // Reference to another model by ID
|
|
913
|
+
@modelRef(User) assignee?: User; // Reference to another model by ID
|
|
826
914
|
@child metadata = MetadataModel.create(); // Nested child model
|
|
827
915
|
@child tags: TagModel[] = []; // Array of child models
|
|
828
916
|
}
|
|
829
917
|
```
|
|
830
918
|
|
|
831
|
-
|
|
919
|
+
Fallback (no decorators) using `static types`:
|
|
920
|
+
|
|
921
|
+
```ts
|
|
922
|
+
import { Model, id, state, child, modelRef } from "r-state-tree";
|
|
923
|
+
|
|
924
|
+
class User extends Model {
|
|
925
|
+
id = 0;
|
|
926
|
+
name = "";
|
|
927
|
+
static types = { id, name: state };
|
|
928
|
+
}
|
|
929
|
+
|
|
930
|
+
class TodoModel extends Model {
|
|
931
|
+
id = 0;
|
|
932
|
+
title = "";
|
|
933
|
+
assignee?: User;
|
|
934
|
+
metadata = MetadataModel.create();
|
|
935
|
+
tags: TagModel[] = [];
|
|
936
|
+
|
|
937
|
+
static types = {
|
|
938
|
+
id,
|
|
939
|
+
title: state,
|
|
940
|
+
assignee: modelRef(User),
|
|
941
|
+
metadata: child(MetadataModel),
|
|
942
|
+
tags: child(TagModel),
|
|
943
|
+
};
|
|
944
|
+
}
|
|
945
|
+
```
|
|
946
|
+
|
|
947
|
+
The `child` and `modelRef` helpers support both single values and arrays. You can also specify the child type using `@child(ChildType)` (decorators) or `child(ChildType)` (`static types`):
|
|
832
948
|
|
|
833
949
|
```ts
|
|
834
950
|
class TodoModel extends Model {
|
|
@@ -839,14 +955,14 @@ class TodoModel extends Model {
|
|
|
839
955
|
|
|
840
956
|
### Model references
|
|
841
957
|
|
|
842
|
-
Reference models by ID using `@modelRef
|
|
958
|
+
Reference models by ID using `@modelRef(ModelType)` (or `modelRef(ModelType)` in `static types`). The model constructor is required because identifiers are namespaced by model type:
|
|
843
959
|
|
|
844
960
|
```ts
|
|
845
961
|
class ProjectModel extends Model {
|
|
846
962
|
@id id = 0;
|
|
847
963
|
@child users: User[] = [];
|
|
848
|
-
@modelRef owner?: User; // Single reference
|
|
849
|
-
@modelRef assignees: User[] = []; // Array of references
|
|
964
|
+
@modelRef(User) owner?: User; // Single reference
|
|
965
|
+
@modelRef(User) assignees: User[] = []; // Array of references
|
|
850
966
|
|
|
851
967
|
assignOwner(userId: number) {
|
|
852
968
|
// Find user by ID and set as owner
|
|
@@ -894,9 +1010,12 @@ class ContainerModel extends Model {
|
|
|
894
1010
|
## API surface
|
|
895
1011
|
|
|
896
1012
|
- Stores
|
|
897
|
-
- `Store`, `createStore`, `mount`, `
|
|
1013
|
+
- `Store`, `createStore`, `mount`, `updateStore`
|
|
898
1014
|
- Models
|
|
899
|
-
|
|
1015
|
+
- `Model`, `Model.create()`
|
|
1016
|
+
- configuration: decorators (`@state`, `@id`, `@child`, `@modelRef`) or `static types` with `state`, `id`, `child`, `modelRef`
|
|
1017
|
+
- Store configuration
|
|
1018
|
+
- decorators (`@child`, `@model`) or `static types` with `child`, `model`
|
|
900
1019
|
- Snapshots
|
|
901
1020
|
- `onSnapshot`, `toSnapshot`, `applySnapshot`, `onSnapshotDiff`
|
|
902
1021
|
- Types: `Snapshot`, `SnapshotDiff`, `IdType`, `Configuration`
|
|
@@ -958,12 +1077,21 @@ Use the observers/renderers provided by the signals bindings for your UI library
|
|
|
958
1077
|
|
|
959
1078
|
### Identifier and reference rules
|
|
960
1079
|
|
|
961
|
-
- `@id` values are unique within a tree.
|
|
962
|
-
- Identifiers can be reassigned
|
|
963
|
-
- `@modelRef`
|
|
1080
|
+
- `@id` values are unique per exact runtime Model class within a tree. Different Model classes may use the same id; subclasses have their own identifier namespace. IDs cannot be cleared to `undefined` after assignment.
|
|
1081
|
+
- Identifiers are mutable and can be reassigned (including in snapshots) as long as the new id is unused by that exact Model class. A failed reassignment preserves the old id and its references.
|
|
1082
|
+
- Use `@modelRef(ModelType)` or `modelRef(ModelType)` when ids can overlap across Model classes; references resolve only within the declared Model class.
|
|
1083
|
+
- `@modelRef(ModelType)` requires an explicit model constructor. The referenced model must have an id and be attached to the tree; the ref becomes `undefined` when the model detaches.
|
|
964
1084
|
- When a model is re-attached to the same tree, compatible refs restore automatically; attaching to a different root does not restore prior refs.
|
|
965
1085
|
- `@modelRef` and `@child` can switch between single and array at runtime; reactions observe the property itself rather than internal array mutations.
|
|
966
1086
|
|
|
1087
|
+
Use `findModelById` for an optional, typed lookup within a model tree:
|
|
1088
|
+
|
|
1089
|
+
```ts
|
|
1090
|
+
const user = findModelById(root, User, 1); // User | undefined
|
|
1091
|
+
```
|
|
1092
|
+
|
|
1093
|
+
The lookup is reactive inside an effect or computed value. It returns `undefined` when the matching model changes its id, detaches, or is disposed.
|
|
1094
|
+
|
|
967
1095
|
### Snapshot diffs
|
|
968
1096
|
|
|
969
1097
|
Use `onSnapshotDiff` to receive undo/redo payloads:
|
|
@@ -1076,17 +1204,22 @@ class ListModel extends Model {
|
|
|
1076
1204
|
}
|
|
1077
1205
|
```
|
|
1078
1206
|
|
|
1079
|
-
Lifecycle
|
|
1207
|
+
Lifecycle registration:
|
|
1080
1208
|
|
|
1081
1209
|
```ts
|
|
1082
1210
|
class M extends Model {
|
|
1083
|
-
|
|
1084
|
-
|
|
1085
|
-
|
|
1211
|
+
constructor() {
|
|
1212
|
+
super();
|
|
1213
|
+
this.reaction(() => this.parent, (parent, previousParent) => {});
|
|
1214
|
+
}
|
|
1086
1215
|
}
|
|
1087
1216
|
class S extends Store {
|
|
1088
|
-
|
|
1089
|
-
|
|
1217
|
+
constructor(props) {
|
|
1218
|
+
super(props);
|
|
1219
|
+
this.effect(() => {
|
|
1220
|
+
if (!this.isMounted) return;
|
|
1221
|
+
});
|
|
1222
|
+
}
|
|
1090
1223
|
}
|
|
1091
1224
|
```
|
|
1092
1225
|
|
|
@@ -1108,11 +1241,11 @@ const off = onSnapshot(m, (snap) =>
|
|
|
1108
1241
|
- Mutating raw `@state` arrays/objects in place (`push`, `obj.x = 1`) and expecting snapshots to update. Snapshots are memoized; use reassignment or store `observable()` containers / `signal()` values in `@state`.
|
|
1109
1242
|
- Passing observables to third‑party APIs that expect cloneable/serializable values (e.g. `structuredClone`). Use `source(value)` to get the backing value. It will be observable-free for values written via r-state-tree’s observable APIs (unwrap-on-write), but `source(...)` is **not** guaranteed observable-free if you manually seed observables into backing sources.
|
|
1110
1243
|
- Creating child stores in constructors: `@child` must be on getters so identity and lifecycle can be managed by the framework.
|
|
1111
|
-
- Passing `models` into child stores during mount can create a recursive mount loop.
|
|
1244
|
+
- Passing `models` into child stores during mount can create a recursive mount loop. Break the ownership cycle rather than wiring models back through a child during mount.
|
|
1112
1245
|
|
|
1113
1246
|
### Circular store/model creation
|
|
1114
1247
|
|
|
1115
|
-
When child stores are created during mount with `models` that point back into the parent, it is easy to trigger an endless mount loop. The runtime
|
|
1248
|
+
When child stores are created during mount with `models` that point back into the parent, it is easy to trigger an endless mount loop. The runtime guards this with a descriptive circular-creation error. Break the cycle so models are produced independently of the child mount.
|
|
1116
1249
|
|
|
1117
1250
|
## LLM implementation checklist
|
|
1118
1251
|
|
|
@@ -1131,8 +1264,8 @@ When child stores are created during mount with `models` that point back into th
|
|
|
1131
1264
|
- For `createStore` props, extend `Record<string, unknown>` only if needed; otherwise rely on proper prop types and context.
|
|
1132
1265
|
- Avoid barrel files if they cause import confusion; prefer direct imports.
|
|
1133
1266
|
- Keep file boundaries clean: one model per file; avoid piling multiple models together.
|
|
1134
|
-
- Do not shadow `props
|
|
1135
|
-
- Use `@model` for injected models; `@child` for child stores; stable keys for arrays.
|
|
1267
|
+
- Do not shadow `props`; constructors are the registration phase for owned reactions and effects.
|
|
1268
|
+
- Use `@model`/`model` for injected models; `@child`/`child` for child stores; stable keys for arrays.
|
|
1136
1269
|
|
|
1137
1270
|
## Typing recipes
|
|
1138
1271
|
|
|
@@ -1142,12 +1275,13 @@ When child stores are created during mount with `models` that point back into th
|
|
|
1142
1275
|
|
|
1143
1276
|
## Cheat sheet
|
|
1144
1277
|
|
|
1278
|
+
- Configuration (no decorators): `static types = { ... }` with `state`, `id`, `child`, `modelRef`, `model`, `computed`
|
|
1145
1279
|
- Decorators (Models): `@state`, `@id`, `@child`, `@modelRef`
|
|
1146
1280
|
- Decorators (Stores): `@child`, `@model`
|
|
1147
|
-
- Core: `createStore`, `mount`, `
|
|
1281
|
+
- Core: `createStore`, `mount`, `Symbol.dispose`, `updateStore`
|
|
1148
1282
|
- Snapshots: `onSnapshot`, `toSnapshot`, `applySnapshot`, `onSnapshotDiff`
|
|
1149
|
-
- Lifecycle:
|
|
1150
|
-
- Best practices: domain in Models; delegate from Stores; stable keys for `@child`;
|
|
1283
|
+
- Lifecycle: reactive `Store.isMounted`, reactive `Model.parent`, and owned `reaction`/`effect`
|
|
1284
|
+
- Best practices: domain in Models; delegate from Stores; stable keys for `@child`; gate resources on lifecycle state; don’t shadow `props`.
|
|
1151
1285
|
|
|
1152
1286
|
## Testing
|
|
1153
1287
|
|
package/dist/api.d.ts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import type { Snapshot, SnapshotDiff } from "./types";
|
|
1
|
+
import type { Snapshot, SnapshotDiff, IdType } from "./types";
|
|
2
2
|
import type Store from "./store/Store";
|
|
3
3
|
import type Model from "./model/Model";
|
|
4
|
+
export declare function findModelById<T extends Model>(root: Model, ModelType: new (...args: any[]) => T, id: IdType): T | undefined;
|
|
4
5
|
export declare function mount<T extends Store>(container: T): T;
|
|
5
|
-
export declare function unmount<S extends Store>(container: S): void;
|
|
6
6
|
export declare function toSnapshot<T extends Model>(model: T): Snapshot<T>;
|
|
7
7
|
export declare function onSnapshot<T extends Model>(model: T, callback: (snapshot: Snapshot<T>, model: T) => void): () => void;
|
|
8
8
|
export declare function onSnapshotDiff<T extends Model>(model: T, callback: (snapshotDiff: SnapshotDiff<T>, model: T) => void): () => void;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { ConfigurationType, ConfigurationTypes } from "./types";
|
|
2
|
+
type Ctor = Function;
|
|
3
|
+
type Config = Record<PropertyKey, ConfigurationType>;
|
|
4
|
+
export declare function getConfigType(entry: ConfigurationType | undefined): ConfigurationTypes | undefined;
|
|
5
|
+
export declare function getConfigChildType(entry: ConfigurationType | undefined): Function | undefined;
|
|
6
|
+
export declare function getConfigurationForCtor(ctor: Ctor | undefined): Config;
|
|
7
|
+
export declare function getConfigurationValue(ctor: Ctor | undefined, key: PropertyKey): ConfigurationType | undefined;
|
|
8
|
+
export declare function getConfigurationType(ctor: Ctor | undefined, key: PropertyKey): ConfigurationTypes | undefined;
|
|
9
|
+
export declare function getConfigurationChildType(ctor: Ctor | undefined, key: PropertyKey): Function | undefined;
|
|
10
|
+
export {};
|
package/dist/decorators.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import "@tsmetadata/polyfill";
|
|
2
2
|
export declare const child: any;
|
|
3
|
-
export declare
|
|
3
|
+
export declare function modelRef<T extends Function>(childCtor: T): any;
|
|
4
4
|
export declare const model: any;
|
|
5
5
|
export declare const id: any;
|
|
6
6
|
export declare const state: any;
|
package/dist/index.d.ts
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import "@tsmetadata/polyfill";
|
|
2
2
|
import Store, { createStore, updateStore } from "./store/Store";
|
|
3
3
|
import Model from "./model/Model";
|
|
4
|
-
import { mount,
|
|
4
|
+
import { mount, onSnapshot, toSnapshot, applySnapshot, onSnapshotDiff, findModelById } from "./api";
|
|
5
5
|
import { createContext } from "./context";
|
|
6
6
|
import { toObservableTree } from "./toObservableTree";
|
|
7
|
-
export { createStore, Store, Model, mount,
|
|
7
|
+
export { createStore, Store, Model, mount, updateStore, onSnapshot, onSnapshotDiff, toSnapshot, applySnapshot, findModelById, createContext, toObservableTree, };
|
|
8
8
|
export { observable, computed, source, reportChanged, reportObserved, getSignal, isObservable, reaction, Signal, type ReadonlySignal, batch, untracked, effect, signal, Observable, } from "./observables";
|
|
9
9
|
export * from "./decorators";
|
|
10
10
|
export type { Configuration, Snapshot, SnapshotValue, IdType, SnapshotDiff, } from "./types";
|
package/dist/model/Model.d.ts
CHANGED
|
@@ -1,17 +1,13 @@
|
|
|
1
1
|
import type { ModelConfiguration, Snapshot } from "../types";
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
} ? Args extends [infer Snapshot, ...infer Rest] ? Rest : [] : [];
|
|
5
|
-
export default class Model {
|
|
6
|
-
static get types(): ModelConfiguration<unknown>;
|
|
2
|
+
export default class Model implements Disposable {
|
|
3
|
+
static types?: ModelConfiguration<unknown>;
|
|
7
4
|
static childTypes: object;
|
|
8
5
|
static create<T extends Model = Model>(this: {
|
|
9
6
|
new (...args: unknown[]): T;
|
|
10
|
-
}, snapshot?: Snapshot<T
|
|
7
|
+
}, snapshot?: Snapshot<T>): T;
|
|
11
8
|
constructor();
|
|
12
9
|
get parent(): Model | null;
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
10
|
+
reaction<T>(track: () => T, callback: (value: T, previousValue: T) => void): () => void;
|
|
11
|
+
effect(callback: () => void | (() => void)): () => void;
|
|
12
|
+
[Symbol.dispose](): void;
|
|
16
13
|
}
|
|
17
|
-
export {};
|
|
@@ -5,6 +5,8 @@ import type { ModelConfiguration, Snapshot, SnapshotChange } from "../types";
|
|
|
5
5
|
export declare function getConfigurationFromSnapshot(snapshot: object): ModelConfiguration<unknown> | undefined;
|
|
6
6
|
export declare function getModelAdm<T extends Model>(model: T): ModelAdministration;
|
|
7
7
|
export declare class ModelAdministration extends PreactObjectAdministration<any> {
|
|
8
|
+
private getCfgType;
|
|
9
|
+
private getCfgChildType;
|
|
8
10
|
static proxyTraps: ProxyHandler<object>;
|
|
9
11
|
private configurationGetter?;
|
|
10
12
|
private _parent;
|
|
@@ -18,13 +20,20 @@ export declare class ModelAdministration extends PreactObjectAdministration<any>
|
|
|
18
20
|
private computedSnapshot;
|
|
19
21
|
private snapshotMap;
|
|
20
22
|
private contextCache;
|
|
23
|
+
private ownedDisposers;
|
|
24
|
+
private disposed;
|
|
21
25
|
parentName: PropertyKey | null;
|
|
22
26
|
get parent(): ModelAdministration | null;
|
|
23
27
|
set parent(value: ModelAdministration | null);
|
|
24
28
|
setConfiguration(configurationGetter: () => ModelConfiguration<any>): void;
|
|
29
|
+
assertUsable(): void;
|
|
30
|
+
private own;
|
|
31
|
+
reaction<T>(track: () => T, callback: (value: T, previousValue: T) => void): () => void;
|
|
32
|
+
effect(callback: () => void | (() => void)): () => void;
|
|
25
33
|
private get configuration();
|
|
26
34
|
private getReferencedAtom;
|
|
27
35
|
private setState;
|
|
36
|
+
private hydrateStateValue;
|
|
28
37
|
private setId;
|
|
29
38
|
private setModel;
|
|
30
39
|
private setModels;
|
|
@@ -32,12 +41,17 @@ export declare class ModelAdministration extends PreactObjectAdministration<any>
|
|
|
32
41
|
private getModelRefs;
|
|
33
42
|
private setModelRef;
|
|
34
43
|
private setModelRefs;
|
|
44
|
+
private getRequiredModelRefType;
|
|
45
|
+
private assertModelRefType;
|
|
35
46
|
private attach;
|
|
47
|
+
private getReactiveRoot;
|
|
36
48
|
private detach;
|
|
49
|
+
dispose(internal?: boolean): void;
|
|
37
50
|
getContextValue<T>(contextId: symbol, provideSymbol: symbol, defaultValue: T | undefined, hasDefault: boolean): T;
|
|
38
51
|
private lookupContextValue;
|
|
39
52
|
private toJSON;
|
|
40
53
|
onSnapshotChange(onChange: SnapshotChange<any>): () => void;
|
|
41
54
|
loadSnapshot(snapshot: Snapshot<any>): void;
|
|
42
55
|
getSnapshot(): Snapshot<any>;
|
|
56
|
+
getSnapshotForRollback(): Snapshot<any>;
|
|
43
57
|
}
|
package/dist/model/idMap.d.ts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import type { IdType } from "../types";
|
|
2
|
-
import
|
|
3
|
-
export
|
|
4
|
-
export declare function setIdentifier(model: Model, id:
|
|
2
|
+
import Model from "./Model";
|
|
3
|
+
export type ModelConstructor<T extends Model = Model> = new (...args: any[]) => T;
|
|
4
|
+
export declare function setIdentifier(model: Model, id: IdType): void;
|
|
5
5
|
export declare function getIdentifier(model: Model): IdType | undefined;
|
|
6
|
-
export declare function getModelById(root: Model, id: IdType):
|
|
6
|
+
export declare function getModelById<T extends Model>(root: Model, Type: ModelConstructor<T>, id: IdType): T | undefined;
|
|
7
7
|
export declare function onModelAttached(model: Model): void;
|
|
8
8
|
export declare function onModelDetached(model: Model): void;
|
|
@@ -41,7 +41,7 @@ export declare function createSignal<T>(initialValue: T): SignalNode<T>;
|
|
|
41
41
|
export declare function createAtom(): AtomNode;
|
|
42
42
|
export { effect, batch, untracked, Signal };
|
|
43
43
|
export type { ReadonlySignal };
|
|
44
|
-
export declare function reaction<T>(fn: () => T, callback: (value: T) => void): () => void;
|
|
44
|
+
export declare function reaction<T>(fn: () => T, callback: (value: T, previousValue: T) => void): () => void;
|
|
45
45
|
export type Listener = {
|
|
46
46
|
dispose: () => void;
|
|
47
47
|
track: <T>(trackFn: () => T) => T;
|