r-state-tree 0.6.3 → 0.7.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 CHANGED
@@ -14,7 +14,10 @@ pnpm add r-state-tree
14
14
 
15
15
  ### Requirements
16
16
 
17
- This library uses [TC39 Stage 3 Decorators](https://github.com/tc39/proposal-decorators) and requires TypeScript 5.0+ with `target: "es2022"` or higher.
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": {
@@ -60,7 +65,7 @@ export default defineConfig({
60
65
  - 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()`.
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,6 +110,31 @@ 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.
@@ -270,6 +300,35 @@ const profile = mount(createStore(ProfileStore, { models: { user } }));
270
300
  profile.user.name; // "Ada"
271
301
  ```
272
302
 
303
+ Fallback (no decorators) using `static types`:
304
+
305
+ ```ts
306
+ import {
307
+ Model,
308
+ Store,
309
+ createStore,
310
+ mount,
311
+ model,
312
+ id,
313
+ state,
314
+ } from "r-state-tree";
315
+
316
+ class User extends Model {
317
+ id = 0;
318
+ name = "";
319
+ static types = { id, name: state };
320
+ }
321
+
322
+ class ProfileStore extends Store {
323
+ user!: User;
324
+ static types = { user: model };
325
+ }
326
+
327
+ const user = User.create({ id: 1, name: "Ada" });
328
+ const profile = mount(createStore(ProfileStore, { models: { user } }));
329
+ profile.user.name;
330
+ ```
331
+
273
332
  Type stores as `Store<Props>` and explicitly type `@model` fields for clarity. The `models` prop may also provide arrays of models.
274
333
 
275
334
  ## Modeling guide
@@ -807,9 +866,11 @@ When to use each:
807
866
  - `modelDidAttach`: link to other models or read context after the model is part of a tree.
808
867
  - `modelWillDetach`: cleanup before the model is removed or replaced.
809
868
 
810
- ### Model decorators
869
+ ### Model configuration
870
+
871
+ Recommended: configure model properties with decorators.
811
872
 
812
- Use decorators to configure model properties:
873
+ Fallback: if you can't or don't want to use decorators, use `static types`.
813
874
 
814
875
  ```ts
815
876
  import { Model, state, id, child, modelRef } from "r-state-tree";
@@ -828,7 +889,35 @@ class TodoModel extends Model {
828
889
  }
829
890
  ```
830
891
 
831
- The `@child` and `@modelRef` decorators support both single values and arrays. You can also specify the child type using `@child(ChildType)`:
892
+ Fallback (no decorators) using `static types`:
893
+
894
+ ```ts
895
+ import { Model, id, state, child, modelRef } from "r-state-tree";
896
+
897
+ class User extends Model {
898
+ id = 0;
899
+ name = "";
900
+ static types = { id, name: state };
901
+ }
902
+
903
+ class TodoModel extends Model {
904
+ id = 0;
905
+ title = "";
906
+ assignee?: User;
907
+ metadata = MetadataModel.create();
908
+ tags: TagModel[] = [];
909
+
910
+ static types = {
911
+ id,
912
+ title: state,
913
+ assignee: modelRef(User),
914
+ metadata: child(MetadataModel),
915
+ tags: child(TagModel),
916
+ };
917
+ }
918
+ ```
919
+
920
+ 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
921
 
833
922
  ```ts
834
923
  class TodoModel extends Model {
@@ -839,7 +928,7 @@ class TodoModel extends Model {
839
928
 
840
929
  ### Model references
841
930
 
842
- Reference models by ID using `@modelRef`:
931
+ Reference models by ID using `@modelRef` (or `static types`):
843
932
 
844
933
  ```ts
845
934
  class ProjectModel extends Model {
@@ -896,7 +985,9 @@ class ContainerModel extends Model {
896
985
  - Stores
897
986
  - `Store`, `createStore`, `mount`, `unmount`, `updateStore`
898
987
  - Models
899
- - `Model`, decorators: `@state`, `@id`, `@child`, `@modelRef`
988
+ - - `Model`, configuration: decorators (`@state`, `@id`, `@child`, `@modelRef`) or `static types` with `state`, `id`, `child`, `modelRef`
989
+ - Store configuration
990
+ - decorators (`@child`, `@model`) or `static types` with `child`, `model`
900
991
  - Snapshots
901
992
  - `onSnapshot`, `toSnapshot`, `applySnapshot`, `onSnapshotDiff`
902
993
  - Types: `Snapshot`, `SnapshotDiff`, `IdType`, `Configuration`
@@ -1132,7 +1223,7 @@ When child stores are created during mount with `models` that point back into th
1132
1223
  - Avoid barrel files if they cause import confusion; prefer direct imports.
1133
1224
  - Keep file boundaries clean: one model per file; avoid piling multiple models together.
1134
1225
  - Do not shadow `props` or use constructors for work better suited to `storeDidMount`.
1135
- - Use `@model` for injected models; `@child` for child stores; stable keys for arrays.
1226
+ - Use `@model`/`model` for injected models; `@child`/`child` for child stores; stable keys for arrays.
1136
1227
 
1137
1228
  ## Typing recipes
1138
1229
 
@@ -1142,6 +1233,7 @@ When child stores are created during mount with `models` that point back into th
1142
1233
 
1143
1234
  ## Cheat sheet
1144
1235
 
1236
+ - Configuration (no decorators): `static types = { ... }` with `state`, `id`, `child`, `modelRef`, `model`, `computed`
1145
1237
  - Decorators (Models): `@state`, `@id`, `@child`, `@modelRef`
1146
1238
  - Decorators (Stores): `@child`, `@model`
1147
1239
  - Core: `createStore`, `mount`, `unmount`, `updateStore`
@@ -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 {};
@@ -3,7 +3,7 @@ type ExtractModelDidInitArgs<T extends Model> = T extends {
3
3
  modelDidInit(...args: infer Args): unknown;
4
4
  } ? Args extends [infer Snapshot, ...infer Rest] ? Rest : [] : [];
5
5
  export default class Model {
6
- static get types(): ModelConfiguration<unknown>;
6
+ static types?: ModelConfiguration<unknown>;
7
7
  static childTypes: object;
8
8
  static create<T extends Model = Model>(this: {
9
9
  new (...args: unknown[]): T;
@@ -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;
@@ -25,6 +27,7 @@ export declare class ModelAdministration extends PreactObjectAdministration<any>
25
27
  private get configuration();
26
28
  private getReferencedAtom;
27
29
  private setState;
30
+ private hydrateStateValue;
28
31
  private setId;
29
32
  private setModel;
30
33
  private setModels;