jotai-state-tree 0.1.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/LICENSE +21 -0
- package/README.md +168 -0
- package/dist/chunk-XXZK62DD.mjs +931 -0
- package/dist/index.d.mts +1109 -0
- package/dist/index.d.ts +1109 -0
- package/dist/index.js +3579 -0
- package/dist/index.mjs +2625 -0
- package/dist/react.d.mts +144 -0
- package/dist/react.d.ts +144 -0
- package/dist/react.js +1259 -0
- package/dist/react.mjs +372 -0
- package/package.json +77 -0
- package/src/__tests__/index.test.ts +1371 -0
- package/src/__tests__/memory.test.ts +681 -0
- package/src/__tests__/performance.test.ts +667 -0
- package/src/__tests__/react.react.test.tsx +811 -0
- package/src/__tests__/registry.test.ts +589 -0
- package/src/array.ts +335 -0
- package/src/compat.ts +294 -0
- package/src/index.ts +647 -0
- package/src/lifecycle.ts +580 -0
- package/src/map.ts +276 -0
- package/src/model.ts +832 -0
- package/src/primitives.ts +400 -0
- package/src/react.ts +626 -0
- package/src/registry.ts +741 -0
- package/src/tree.ts +1275 -0
- package/src/types.ts +520 -0
- package/src/undo.ts +566 -0
- package/src/utilities.ts +616 -0
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,1109 @@
|
|
|
1
|
+
import * as jotai_vanilla_internals from 'jotai/vanilla/internals';
|
|
2
|
+
import { WritableAtom, createStore } from 'jotai';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Core types for jotai-state-tree
|
|
6
|
+
* These types mirror the MobX-State-Tree API
|
|
7
|
+
*/
|
|
8
|
+
type SnapshotIn<T> = T extends IModelType<infer P, any, any, any> ? {
|
|
9
|
+
[K in keyof P]?: SnapshotInOfProperty<P[K]>;
|
|
10
|
+
} : T extends IArrayType<infer I> ? SnapshotIn<I>[] : T extends IMapType<infer V> ? Record<string, SnapshotIn<V>> : T extends IReferenceType<any> ? string | number : T extends IType<infer C, any, any> ? C : T;
|
|
11
|
+
type SnapshotInOfProperty<T> = T extends IType<infer C, any, any> ? C : never;
|
|
12
|
+
type SnapshotOut<T> = T extends IModelType<infer P, any, any, any> ? {
|
|
13
|
+
[K in keyof P]: SnapshotOutOfProperty<P[K]>;
|
|
14
|
+
} : T extends IArrayType<infer I> ? SnapshotOut<I>[] : T extends IMapType<infer V> ? Record<string, SnapshotOut<V>> : T extends IReferenceType<any> ? string | number : T extends IType<any, infer S, any> ? S : T;
|
|
15
|
+
type SnapshotOutOfProperty<T> = T extends IType<any, infer S, any> ? S : never;
|
|
16
|
+
type Instance<T> = T extends IType<any, any, infer O> ? O : never;
|
|
17
|
+
interface IType<C, S, T> {
|
|
18
|
+
/** Name of this type */
|
|
19
|
+
readonly name: string;
|
|
20
|
+
/** The identifier attribute if this type has one */
|
|
21
|
+
readonly identifierAttribute?: string;
|
|
22
|
+
/** Create an instance of this type */
|
|
23
|
+
create(snapshot?: C, env?: unknown): T;
|
|
24
|
+
/** Check if a value is an instance of this type */
|
|
25
|
+
is(value: unknown): value is T;
|
|
26
|
+
/** Validate a value against this type */
|
|
27
|
+
validate(value: unknown, context: IValidationContext[]): IValidationResult;
|
|
28
|
+
/** Type discriminator */
|
|
29
|
+
readonly _kind: string;
|
|
30
|
+
readonly _C: C;
|
|
31
|
+
readonly _S: S;
|
|
32
|
+
readonly _T: T;
|
|
33
|
+
}
|
|
34
|
+
interface IValidationContext {
|
|
35
|
+
path: string;
|
|
36
|
+
type: IType<unknown, unknown, unknown>;
|
|
37
|
+
parent: unknown;
|
|
38
|
+
}
|
|
39
|
+
interface IValidationResult {
|
|
40
|
+
valid: boolean;
|
|
41
|
+
errors: IValidationError[];
|
|
42
|
+
}
|
|
43
|
+
interface IValidationError {
|
|
44
|
+
context: IValidationContext[];
|
|
45
|
+
value: unknown;
|
|
46
|
+
message: string;
|
|
47
|
+
}
|
|
48
|
+
interface ISimpleType<T> extends IType<T, T, T> {
|
|
49
|
+
readonly _kind: "simple";
|
|
50
|
+
}
|
|
51
|
+
type ModelProperties = Record<string, IType<unknown, unknown, unknown>>;
|
|
52
|
+
type ModelCreationType<P extends ModelProperties> = {
|
|
53
|
+
[K in keyof P]?: P[K] extends IType<infer C, unknown, unknown> ? C : never;
|
|
54
|
+
};
|
|
55
|
+
type ModelSnapshotType<P extends ModelProperties> = {
|
|
56
|
+
[K in keyof P]: P[K] extends IType<unknown, infer S, unknown> ? S : never;
|
|
57
|
+
};
|
|
58
|
+
type ModelInstanceType<P extends ModelProperties> = {
|
|
59
|
+
[K in keyof P]: P[K] extends IType<unknown, unknown, infer T> ? T : never;
|
|
60
|
+
};
|
|
61
|
+
/** Represents a node in the state tree */
|
|
62
|
+
interface IStateTreeNode<S = unknown> {
|
|
63
|
+
readonly $id: string;
|
|
64
|
+
readonly $type: IType<unknown, unknown, unknown>;
|
|
65
|
+
readonly $parent: IStateTreeNode | null;
|
|
66
|
+
readonly $path: string;
|
|
67
|
+
readonly $env: unknown;
|
|
68
|
+
readonly $isAlive: boolean;
|
|
69
|
+
}
|
|
70
|
+
type ModelInstance<P extends ModelProperties, V extends object, A extends object, Vol extends object> = ModelInstanceType<P> & {
|
|
71
|
+
/** Access to the tree node metadata */
|
|
72
|
+
readonly $treenode: IStateTreeNode;
|
|
73
|
+
};
|
|
74
|
+
type ModelViews<Self, V> = (self: Self) => V;
|
|
75
|
+
type ModelActions<Self, A> = (self: Self) => A;
|
|
76
|
+
type ModelVolatile<Self, Vol> = (self: Self) => Vol;
|
|
77
|
+
interface IModelType<P extends ModelProperties, V extends object, A extends object, Vol extends object> extends IType<ModelCreationType<P>, ModelSnapshotType<P>, ModelInstance<P, V, A, Vol> & V & A & Vol> {
|
|
78
|
+
readonly _kind: "model";
|
|
79
|
+
readonly properties: P;
|
|
80
|
+
/** Create a new model type with a different name */
|
|
81
|
+
named(name: string): IModelType<P, V, A, Vol>;
|
|
82
|
+
/** Add properties to the model */
|
|
83
|
+
props<P2 extends ModelProperties>(properties: P2): IModelType<P & P2, V, A, Vol>;
|
|
84
|
+
/** Add computed views to the model */
|
|
85
|
+
views<V2 extends object>(fn: ModelViews<ModelInstance<P, V, A, Vol> & V & A & Vol, V2>): IModelType<P, V & V2, A, Vol>;
|
|
86
|
+
/** Add actions to the model */
|
|
87
|
+
actions<A2 extends object>(fn: ModelActions<ModelInstance<P, V, A, Vol> & V & A & Vol, A2>): IModelType<P, V, A & A2, Vol>;
|
|
88
|
+
/** Add volatile (non-serialized) state */
|
|
89
|
+
volatile<Vol2 extends object>(fn: ModelVolatile<ModelInstance<P, V, A, Vol> & V & A & Vol, Vol2>): IModelType<P, V, A, Vol & Vol2>;
|
|
90
|
+
/** Transform snapshot before creating instance */
|
|
91
|
+
preProcessSnapshot<NewC>(fn: (snapshot: NewC) => ModelCreationType<P>): IModelType<P, V, A, Vol>;
|
|
92
|
+
/** Transform snapshot after getting it */
|
|
93
|
+
postProcessSnapshot<NewS>(fn: (snapshot: ModelSnapshotType<P>) => NewS): IModelType<P, V, A, Vol>;
|
|
94
|
+
/** Extend the model with views, actions, and state in one call */
|
|
95
|
+
extend<V2 extends object = object, A2 extends object = object, Vol2 extends object = object>(fn: (self: ModelInstance<P, V, A, Vol> & V & A & Vol) => {
|
|
96
|
+
views?: V2;
|
|
97
|
+
actions?: A2;
|
|
98
|
+
state?: Vol2;
|
|
99
|
+
}): IModelType<P, V & V2, A & A2, Vol & Vol2>;
|
|
100
|
+
/** Add afterCreate lifecycle hook */
|
|
101
|
+
afterCreate(fn: (self: ModelInstance<P, V, A, Vol> & V & A & Vol) => void): IModelType<P, V, A, Vol>;
|
|
102
|
+
/** Add afterAttach lifecycle hook (called when node is attached to tree) */
|
|
103
|
+
afterAttach(fn: (self: ModelInstance<P, V, A, Vol> & V & A & Vol) => void): IModelType<P, V, A, Vol>;
|
|
104
|
+
/** Add beforeDetach lifecycle hook (called before node is detached from tree) */
|
|
105
|
+
beforeDetach(fn: (self: ModelInstance<P, V, A, Vol> & V & A & Vol) => void): IModelType<P, V, A, Vol>;
|
|
106
|
+
/** Add beforeDestroy lifecycle hook (called before node is destroyed) */
|
|
107
|
+
beforeDestroy(fn: (self: ModelInstance<P, V, A, Vol> & V & A & Vol) => void): IModelType<P, V, A, Vol>;
|
|
108
|
+
}
|
|
109
|
+
/**
|
|
110
|
+
* MST Array interface that allows both instance types and snapshot/creation types
|
|
111
|
+
* for mutation methods like push(), unshift(), splice(), etc.
|
|
112
|
+
*
|
|
113
|
+
* @template T - The instance type of array items
|
|
114
|
+
* @template C - The creation/snapshot type of array items (defaults to T)
|
|
115
|
+
*/
|
|
116
|
+
interface IMSTArray<T, C = T> extends Omit<Array<T>, "push" | "unshift" | "splice" | "fill"> {
|
|
117
|
+
/** Array length */
|
|
118
|
+
readonly length: number;
|
|
119
|
+
/** Push items (accepts both instances and snapshots) */
|
|
120
|
+
push(...items: (T | C)[]): number;
|
|
121
|
+
/** Unshift items (accepts both instances and snapshots) */
|
|
122
|
+
unshift(...items: (T | C)[]): number;
|
|
123
|
+
/** Splice items (accepts both instances and snapshots for new items) */
|
|
124
|
+
splice(start: number, deleteCount?: number, ...items: (T | C)[]): T[];
|
|
125
|
+
/** Fill with value */
|
|
126
|
+
fill(value: T | C, start?: number, end?: number): this;
|
|
127
|
+
/** Replace all items */
|
|
128
|
+
replace(items: (T | C)[]): void;
|
|
129
|
+
/** Remove all items */
|
|
130
|
+
clear(): void;
|
|
131
|
+
/** Remove a specific item */
|
|
132
|
+
remove(item: T): boolean;
|
|
133
|
+
/** Splice with array argument */
|
|
134
|
+
spliceWithArray(index: number, deleteCount?: number, newItems?: (T | C)[]): T[];
|
|
135
|
+
/** Convert to JSON */
|
|
136
|
+
toJSON(): T[];
|
|
137
|
+
/** Index access */
|
|
138
|
+
[index: number]: T;
|
|
139
|
+
/** Iterator */
|
|
140
|
+
[Symbol.iterator](): IterableIterator<T>;
|
|
141
|
+
}
|
|
142
|
+
interface IArrayType<T extends IType<unknown, unknown, unknown>> extends IType<Array<T extends IType<infer C, unknown, unknown> ? C : never>, Array<T extends IType<unknown, infer S, unknown> ? S : never>, IMSTArray<T extends IType<unknown, unknown, infer I> ? I : never, T extends IType<infer C, unknown, unknown> ? C : never>> {
|
|
143
|
+
readonly _kind: "array";
|
|
144
|
+
readonly _subType: T;
|
|
145
|
+
}
|
|
146
|
+
interface IMSTMap<V> extends Map<string, V> {
|
|
147
|
+
/** Put a value, returning it */
|
|
148
|
+
put(value: V): V;
|
|
149
|
+
/** Merge values into the map */
|
|
150
|
+
merge(values: Record<string, V> | Map<string, V>): this;
|
|
151
|
+
/** Replace all values */
|
|
152
|
+
replace(values: Record<string, V> | Map<string, V>): this;
|
|
153
|
+
/** Convert to JSON */
|
|
154
|
+
toJSON(): Record<string, V>;
|
|
155
|
+
}
|
|
156
|
+
interface IMapType<T extends IType<unknown, unknown, unknown>> extends IType<Record<string, T extends IType<infer C, unknown, unknown> ? C : never>, Record<string, T extends IType<unknown, infer S, unknown> ? S : never>, IMSTMap<T extends IType<unknown, unknown, infer I> ? I : never>> {
|
|
157
|
+
readonly _kind: "map";
|
|
158
|
+
readonly _subType: T;
|
|
159
|
+
}
|
|
160
|
+
interface IOptionalType<T extends IType<unknown, unknown, unknown>, Default> extends IType<(T extends IType<infer C, unknown, unknown> ? C : never) | undefined, T extends IType<unknown, infer S, unknown> ? S : never, T extends IType<unknown, unknown, infer I> ? I : never> {
|
|
161
|
+
readonly _kind: "optional";
|
|
162
|
+
readonly _subType: T;
|
|
163
|
+
readonly _defaultValue: Default | (() => Default);
|
|
164
|
+
}
|
|
165
|
+
interface IMaybeType<T extends IType<unknown, unknown, unknown>> extends IType<(T extends IType<infer C, unknown, unknown> ? C : never) | undefined, (T extends IType<unknown, infer S, unknown> ? S : never) | undefined, (T extends IType<unknown, unknown, infer I> ? I : never) | undefined> {
|
|
166
|
+
readonly _kind: "maybe";
|
|
167
|
+
readonly _subType: T;
|
|
168
|
+
}
|
|
169
|
+
interface IMaybeNullType<T extends IType<unknown, unknown, unknown>> extends IType<(T extends IType<infer C, unknown, unknown> ? C : never) | null, (T extends IType<unknown, infer S, unknown> ? S : never) | null, (T extends IType<unknown, unknown, infer I> ? I : never) | null> {
|
|
170
|
+
readonly _kind: "maybeNull";
|
|
171
|
+
readonly _subType: T;
|
|
172
|
+
}
|
|
173
|
+
interface IReferenceType<T extends IAnyModelType> extends IType<string | number, string | number, Instance<T>> {
|
|
174
|
+
readonly _kind: "reference";
|
|
175
|
+
readonly _targetType: T;
|
|
176
|
+
}
|
|
177
|
+
interface ReferenceOptions<T extends IAnyModelType> {
|
|
178
|
+
get?(identifier: string | number, parent: unknown): Instance<T> | undefined;
|
|
179
|
+
set?(value: Instance<T>, parent: unknown): string | number;
|
|
180
|
+
onInvalidated?: (event: {
|
|
181
|
+
parent: unknown;
|
|
182
|
+
invalidId: string | number;
|
|
183
|
+
replaceRef: (newRef: Instance<T> | null) => void;
|
|
184
|
+
removeRef: () => void;
|
|
185
|
+
cause: "destroy" | "invalidSnapshotReference" | "detach";
|
|
186
|
+
}) => void;
|
|
187
|
+
}
|
|
188
|
+
interface ISafeReferenceType<T extends IAnyModelType> extends IType<string | number | undefined, string | number | undefined, Instance<T> | undefined> {
|
|
189
|
+
readonly _kind: "safeReference";
|
|
190
|
+
readonly _targetType: T;
|
|
191
|
+
}
|
|
192
|
+
type UnionOptions = {
|
|
193
|
+
dispatcher?: (snapshot: unknown) => IType<unknown, unknown, unknown>;
|
|
194
|
+
eager?: boolean;
|
|
195
|
+
};
|
|
196
|
+
interface IUnionType<Types extends IType<unknown, unknown, unknown>[]> extends IType<Types[number] extends IType<infer C, unknown, unknown> ? C : never, Types[number] extends IType<unknown, infer S, unknown> ? S : never, Types[number] extends IType<unknown, unknown, infer T> ? T : never> {
|
|
197
|
+
readonly _kind: "union";
|
|
198
|
+
readonly _types: Types;
|
|
199
|
+
}
|
|
200
|
+
interface ILiteralType<T extends string | number | boolean> extends IType<T, T, T> {
|
|
201
|
+
readonly _kind: "literal";
|
|
202
|
+
readonly _value: T;
|
|
203
|
+
}
|
|
204
|
+
interface IEnumerationType<E extends string> extends IType<E, E, E> {
|
|
205
|
+
readonly _kind: "enumeration";
|
|
206
|
+
readonly _options: readonly E[];
|
|
207
|
+
}
|
|
208
|
+
interface IFrozenType<T> extends IType<T, T, T> {
|
|
209
|
+
readonly _kind: "frozen";
|
|
210
|
+
}
|
|
211
|
+
interface ILateType<T extends IType<unknown, unknown, unknown>> extends IType<T extends IType<infer C, unknown, unknown> ? C : never, T extends IType<unknown, infer S, unknown> ? S : never, T extends IType<unknown, unknown, infer I> ? I : never> {
|
|
212
|
+
readonly _kind: "late";
|
|
213
|
+
readonly _definition: () => T;
|
|
214
|
+
}
|
|
215
|
+
interface IRefinementType<T extends IType<unknown, unknown, unknown>> extends IType<T extends IType<infer C, unknown, unknown> ? C : never, T extends IType<unknown, infer S, unknown> ? S : never, T extends IType<unknown, unknown, infer I> ? I : never> {
|
|
216
|
+
readonly _kind: "refinement";
|
|
217
|
+
readonly _subType: T;
|
|
218
|
+
readonly _predicate: (value: unknown) => boolean;
|
|
219
|
+
}
|
|
220
|
+
interface CustomTypeOptions$1<C, S, T> {
|
|
221
|
+
name: string;
|
|
222
|
+
fromSnapshot(snapshot: S): T;
|
|
223
|
+
toSnapshot(value: T): S;
|
|
224
|
+
isTargetType(value: unknown): boolean;
|
|
225
|
+
getValidationMessage(value: unknown): string;
|
|
226
|
+
}
|
|
227
|
+
interface IIdentifierType extends IType<string, string, string> {
|
|
228
|
+
readonly _kind: "identifier";
|
|
229
|
+
readonly identifierAttribute: string;
|
|
230
|
+
}
|
|
231
|
+
interface IIdentifierNumberType extends IType<number, number, number> {
|
|
232
|
+
readonly _kind: "identifierNumber";
|
|
233
|
+
readonly identifierAttribute: string;
|
|
234
|
+
}
|
|
235
|
+
interface IJsonPatch {
|
|
236
|
+
op: "replace" | "add" | "remove";
|
|
237
|
+
path: string;
|
|
238
|
+
value?: unknown;
|
|
239
|
+
}
|
|
240
|
+
interface IReversibleJsonPatch extends IJsonPatch {
|
|
241
|
+
oldValue?: unknown;
|
|
242
|
+
}
|
|
243
|
+
type IAnyType = IType<unknown, unknown, unknown>;
|
|
244
|
+
type IAnyModelType = IModelType<ModelProperties, object, object, object>;
|
|
245
|
+
type IAnyComplexType = IAnyModelType | IArrayType<IAnyType> | IMapType<IAnyType>;
|
|
246
|
+
interface IDisposer {
|
|
247
|
+
(): void;
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
/**
|
|
251
|
+
* Primitive types implementation
|
|
252
|
+
* string, number, boolean, integer, Date, identifier, etc.
|
|
253
|
+
*/
|
|
254
|
+
|
|
255
|
+
/** String type */
|
|
256
|
+
declare const string: ISimpleType<string>;
|
|
257
|
+
/** Number type (includes floats) */
|
|
258
|
+
declare const number: ISimpleType<number>;
|
|
259
|
+
/** Integer type */
|
|
260
|
+
declare const integer: ISimpleType<number>;
|
|
261
|
+
/** Boolean type */
|
|
262
|
+
declare const boolean: ISimpleType<boolean>;
|
|
263
|
+
/** Date type - stores as number, exposes as Date */
|
|
264
|
+
declare const DatePrimitive: IType<number | Date, number, Date>;
|
|
265
|
+
/** Null type */
|
|
266
|
+
declare const nullType: ISimpleType<null>;
|
|
267
|
+
/** Undefined type */
|
|
268
|
+
declare const undefinedType: ISimpleType<undefined>;
|
|
269
|
+
/** String identifier type */
|
|
270
|
+
declare const identifier: IIdentifierType;
|
|
271
|
+
/** Number identifier type */
|
|
272
|
+
declare const identifierNumber: IIdentifierNumberType;
|
|
273
|
+
declare function literal<T extends string | number | boolean>(value: T): ILiteralType<T>;
|
|
274
|
+
declare function enumeration<E extends string>(name: string, options: readonly E[]): IEnumerationType<E>;
|
|
275
|
+
declare function enumeration<E extends string>(options: readonly E[]): IEnumerationType<E>;
|
|
276
|
+
declare function frozen<T = unknown>(): IFrozenType<T>;
|
|
277
|
+
declare function frozen<T>(defaultValue: T): IFrozenType<T>;
|
|
278
|
+
interface CustomTypeOptions<C, S, T> {
|
|
279
|
+
name: string;
|
|
280
|
+
fromSnapshot(snapshot: S): T;
|
|
281
|
+
toSnapshot(value: T): S;
|
|
282
|
+
isTargetType(value: unknown): value is T;
|
|
283
|
+
getValidationMessage(value: unknown): string;
|
|
284
|
+
}
|
|
285
|
+
declare function custom<C, S, T>(options: CustomTypeOptions<C, S, T>): IType<C, S, T>;
|
|
286
|
+
/** Finite number type (excludes Infinity and -Infinity) */
|
|
287
|
+
declare const finite: ISimpleType<number>;
|
|
288
|
+
/** Float type (alias for number) */
|
|
289
|
+
declare const float: ISimpleType<number>;
|
|
290
|
+
|
|
291
|
+
/**
|
|
292
|
+
* Model type implementation
|
|
293
|
+
* This is the core of jotai-state-tree
|
|
294
|
+
*
|
|
295
|
+
* MEMORY MANAGEMENT:
|
|
296
|
+
* - View and action caches are bounded with LRU eviction
|
|
297
|
+
* - Caches are instance-scoped, so they're GC'd with the instance
|
|
298
|
+
* - No global caches that could accumulate entries
|
|
299
|
+
*/
|
|
300
|
+
|
|
301
|
+
declare function model<P extends ModelProperties>(name: string, properties: P): IModelType<P, object, object, object>;
|
|
302
|
+
declare function model<P extends ModelProperties>(properties: P): IModelType<P, object, object, object>;
|
|
303
|
+
declare function compose<PA extends ModelProperties, PB extends ModelProperties, VA extends object, VB extends object, AA extends object, AB extends object, VolA extends object, VolB extends object>(name: string, a: IModelType<PA, VA, AA, VolA>, b: IModelType<PB, VB, AB, VolB>): IModelType<PA & PB, VA & VB, AA & AB, VolA & VolB>;
|
|
304
|
+
declare function compose<PA extends ModelProperties, PB extends ModelProperties, VA extends object, VB extends object, AA extends object, AB extends object, VolA extends object, VolB extends object>(a: IModelType<PA, VA, AA, VolA>, b: IModelType<PB, VB, AB, VolB>): IModelType<PA & PB, VA & VB, AA & AB, VolA & VolB>;
|
|
305
|
+
|
|
306
|
+
/**
|
|
307
|
+
* Array type implementation
|
|
308
|
+
*/
|
|
309
|
+
|
|
310
|
+
declare function array<T extends IAnyType>(itemType: T): IArrayType<T>;
|
|
311
|
+
|
|
312
|
+
/**
|
|
313
|
+
* Map type implementation
|
|
314
|
+
*/
|
|
315
|
+
|
|
316
|
+
declare function map<T extends IAnyType>(valueType: T): IMapType<T>;
|
|
317
|
+
|
|
318
|
+
/**
|
|
319
|
+
* Utility types implementation
|
|
320
|
+
* optional, maybe, maybeNull, union, late, refinement, reference, safeReference
|
|
321
|
+
*/
|
|
322
|
+
|
|
323
|
+
declare function optional<T extends IAnyType, D extends T extends IType<infer C, unknown, unknown> ? C : never>(type: T, defaultValue: D | (() => D)): IOptionalType<T, D>;
|
|
324
|
+
declare function maybe<T extends IAnyType>(type: T): IMaybeType<T>;
|
|
325
|
+
declare function maybeNull<T extends IAnyType>(type: T): IMaybeNullType<T>;
|
|
326
|
+
declare function union<Types extends IAnyType[]>(...types: Types): IUnionType<Types>;
|
|
327
|
+
declare function union<Types extends IAnyType[]>(options: UnionOptions, ...types: Types): IUnionType<Types>;
|
|
328
|
+
declare function late<T extends IAnyType>(definition: () => T): ILateType<T>;
|
|
329
|
+
declare function late<T extends IAnyType>(name: string, definition: () => T): ILateType<T>;
|
|
330
|
+
declare function refinement<T extends IAnyType>(type: T, predicate: (value: T extends IType<unknown, unknown, infer I> ? I : never) => boolean, message?: string | ((value: unknown) => string)): IRefinementType<T>;
|
|
331
|
+
declare function reference<T extends IAnyModelType>(targetType: T, options?: ReferenceOptions<T>): IReferenceType<T>;
|
|
332
|
+
declare function safeReference<T extends IAnyModelType>(targetType: T, options?: ReferenceOptions<T> & {
|
|
333
|
+
acceptsUndefined?: boolean;
|
|
334
|
+
}): ISafeReferenceType<T>;
|
|
335
|
+
declare function snapshotProcessor<IT extends IAnyType, CustomC = IT extends IType<infer C, unknown, unknown> ? C : never, CustomS = IT extends IType<unknown, infer S, unknown> ? S : never>(type: IT, processors: {
|
|
336
|
+
preProcessor?: (snapshot: CustomC) => IT extends IType<infer C, unknown, unknown> ? C : never;
|
|
337
|
+
postProcessor?: (snapshot: IT extends IType<unknown, infer S, unknown> ? S : never) => CustomS;
|
|
338
|
+
}): IType<CustomC, CustomS, IT extends IType<unknown, unknown, infer T> ? T : never>;
|
|
339
|
+
|
|
340
|
+
/**
|
|
341
|
+
* Model Registry for Dynamic Model Registration
|
|
342
|
+
*
|
|
343
|
+
* Enables plugin architectures, code splitting, and lazy loading of models.
|
|
344
|
+
* Models can be registered at runtime and resolved dynamically.
|
|
345
|
+
*
|
|
346
|
+
* @example
|
|
347
|
+
* // In a plugin or lazy-loaded module:
|
|
348
|
+
* registerModel("UserProfile", UserProfileModel);
|
|
349
|
+
*
|
|
350
|
+
* // In main app, before plugin loads:
|
|
351
|
+
* const LazyUserProfile = types.lateModel("UserProfile");
|
|
352
|
+
*
|
|
353
|
+
* // Reference that resolves dynamically:
|
|
354
|
+
* const ref = types.dynamicReference("UserProfile", userId);
|
|
355
|
+
*/
|
|
356
|
+
|
|
357
|
+
/**
|
|
358
|
+
* Register a model type with a name for dynamic resolution.
|
|
359
|
+
*
|
|
360
|
+
* @param name - Unique name for the model
|
|
361
|
+
* @param type - The model type to register
|
|
362
|
+
* @param metadata - Optional metadata to associate with the model
|
|
363
|
+
* @throws Error if a model with the same name is already registered
|
|
364
|
+
*
|
|
365
|
+
* @example
|
|
366
|
+
* const UserModel = types.model("User", { id: types.identifier, name: types.string });
|
|
367
|
+
* registerModel("User", UserModel);
|
|
368
|
+
*
|
|
369
|
+
* // Later, in a plugin:
|
|
370
|
+
* registerModel("UserProfile", types.model("UserProfile", {
|
|
371
|
+
* user: types.reference(resolveModel("User")),
|
|
372
|
+
* bio: types.string
|
|
373
|
+
* }));
|
|
374
|
+
*/
|
|
375
|
+
declare function registerModel(name: string, type: IAnyType, metadata?: Record<string, unknown>): void;
|
|
376
|
+
/**
|
|
377
|
+
* Unregister a model type.
|
|
378
|
+
*
|
|
379
|
+
* @param name - Name of the model to unregister
|
|
380
|
+
* @returns true if the model was unregistered, false if it wasn't registered
|
|
381
|
+
*
|
|
382
|
+
* @example
|
|
383
|
+
* unregisterModel("UserProfile");
|
|
384
|
+
*/
|
|
385
|
+
declare function unregisterModel(name: string): boolean;
|
|
386
|
+
/**
|
|
387
|
+
* Check if a model is registered.
|
|
388
|
+
*
|
|
389
|
+
* @param name - Name of the model to check
|
|
390
|
+
* @returns true if the model is registered
|
|
391
|
+
*/
|
|
392
|
+
declare function isModelRegistered(name: string): boolean;
|
|
393
|
+
/**
|
|
394
|
+
* Resolve a model type by name (synchronous).
|
|
395
|
+
*
|
|
396
|
+
* @param name - Name of the model to resolve
|
|
397
|
+
* @returns The registered model type
|
|
398
|
+
* @throws Error if the model is not registered
|
|
399
|
+
*
|
|
400
|
+
* @example
|
|
401
|
+
* const UserModel = resolveModel("User");
|
|
402
|
+
* const instance = UserModel.create({ id: "1", name: "John" });
|
|
403
|
+
*/
|
|
404
|
+
declare function resolveModel<T extends IAnyType = IAnyType>(name: string): T;
|
|
405
|
+
/**
|
|
406
|
+
* Try to resolve a model type by name (returns undefined if not registered).
|
|
407
|
+
*
|
|
408
|
+
* @param name - Name of the model to resolve
|
|
409
|
+
* @returns The registered model type or undefined
|
|
410
|
+
*
|
|
411
|
+
* @example
|
|
412
|
+
* const UserModel = tryResolveModel("User");
|
|
413
|
+
* if (UserModel) {
|
|
414
|
+
* const instance = UserModel.create({ id: "1", name: "John" });
|
|
415
|
+
* }
|
|
416
|
+
*/
|
|
417
|
+
declare function tryResolveModel<T extends IAnyType = IAnyType>(name: string): T | undefined;
|
|
418
|
+
/**
|
|
419
|
+
* Resolve a model type by name (asynchronous).
|
|
420
|
+
* Waits for the model to be registered if it isn't already.
|
|
421
|
+
*
|
|
422
|
+
* @param name - Name of the model to resolve
|
|
423
|
+
* @param timeout - Optional timeout in milliseconds (default: 30000)
|
|
424
|
+
* @returns Promise that resolves to the model type
|
|
425
|
+
* @throws Error if timeout is reached
|
|
426
|
+
*
|
|
427
|
+
* @example
|
|
428
|
+
* // Wait for a plugin to register its model
|
|
429
|
+
* const UserProfileModel = await resolveModelAsync("UserProfile");
|
|
430
|
+
*/
|
|
431
|
+
declare function resolveModelAsync<T extends IAnyType = IAnyType>(name: string, timeout?: number): Promise<T>;
|
|
432
|
+
/**
|
|
433
|
+
* Get metadata for a registered model.
|
|
434
|
+
*
|
|
435
|
+
* @param name - Name of the model
|
|
436
|
+
* @returns The metadata or undefined
|
|
437
|
+
*/
|
|
438
|
+
declare function getModelMetadata(name: string): Record<string, unknown> | undefined;
|
|
439
|
+
/**
|
|
440
|
+
* Get all registered model names.
|
|
441
|
+
*
|
|
442
|
+
* @returns Array of registered model names
|
|
443
|
+
*/
|
|
444
|
+
declare function getRegisteredModelNames(): string[];
|
|
445
|
+
/**
|
|
446
|
+
* Listen for model registration events.
|
|
447
|
+
*
|
|
448
|
+
* @param listener - Callback invoked when a model is registered
|
|
449
|
+
* @returns Disposer function to remove the listener
|
|
450
|
+
*
|
|
451
|
+
* @example
|
|
452
|
+
* const disposer = onModelRegistered((name, type) => {
|
|
453
|
+
* console.log(`Model ${name} was registered`);
|
|
454
|
+
* });
|
|
455
|
+
* // Later:
|
|
456
|
+
* disposer();
|
|
457
|
+
*/
|
|
458
|
+
declare function onModelRegistered(listener: (name: string, type: IAnyType) => void): () => void;
|
|
459
|
+
/**
|
|
460
|
+
* Clear all registered models.
|
|
461
|
+
* Primarily useful for testing.
|
|
462
|
+
*/
|
|
463
|
+
declare function clearModelRegistry(): void;
|
|
464
|
+
/**
|
|
465
|
+
* Create a late-resolving type that looks up the model from the registry.
|
|
466
|
+
* This allows you to reference models that may not be registered yet.
|
|
467
|
+
*
|
|
468
|
+
* @param modelName - Name of the model in the registry
|
|
469
|
+
* @returns A type that resolves from the registry when used
|
|
470
|
+
*
|
|
471
|
+
* @example
|
|
472
|
+
* // Define a type that references a model not yet registered
|
|
473
|
+
* const PostStore = types.model("PostStore", {
|
|
474
|
+
* posts: types.array(types.lateModel("Post")),
|
|
475
|
+
* author: types.reference(types.lateModel("User"))
|
|
476
|
+
* });
|
|
477
|
+
*
|
|
478
|
+
* // Later, register the models (e.g., from a plugin)
|
|
479
|
+
* registerModel("Post", PostModel);
|
|
480
|
+
* registerModel("User", UserModel);
|
|
481
|
+
*
|
|
482
|
+
* // Now PostStore.create() will work
|
|
483
|
+
*/
|
|
484
|
+
declare function lateModel<T extends IAnyType = IAnyType>(modelName: string): IType<T extends IType<infer C, unknown, unknown> ? C : unknown, T extends IType<unknown, infer S, unknown> ? S : unknown, T extends IType<unknown, unknown, infer I> ? I : unknown>;
|
|
485
|
+
/** Options for dynamic references */
|
|
486
|
+
interface DynamicReferenceOptions<T extends IAnyType> {
|
|
487
|
+
/**
|
|
488
|
+
* Custom getter to resolve the reference.
|
|
489
|
+
* If not provided, uses the default identifier-based resolution.
|
|
490
|
+
*
|
|
491
|
+
* @param identifier - The stored identifier value
|
|
492
|
+
* @param parent - The parent node containing the reference
|
|
493
|
+
* @returns The resolved instance or undefined
|
|
494
|
+
*/
|
|
495
|
+
get?: (identifier: string | number, parent: unknown) => (T extends IType<unknown, unknown, infer I> ? I : unknown) | undefined;
|
|
496
|
+
/**
|
|
497
|
+
* Custom setter to extract the identifier from a value.
|
|
498
|
+
* If not provided, uses the identifier property of the value.
|
|
499
|
+
*
|
|
500
|
+
* @param value - The value being set
|
|
501
|
+
* @param parent - The parent node containing the reference
|
|
502
|
+
* @returns The identifier to store
|
|
503
|
+
*/
|
|
504
|
+
set?: (value: T extends IType<unknown, unknown, infer I> ? I : unknown, parent: unknown) => string | number;
|
|
505
|
+
/**
|
|
506
|
+
* Called when resolution fails.
|
|
507
|
+
* Can return a fallback value or throw an error.
|
|
508
|
+
*/
|
|
509
|
+
onInvalidated?: (identifier: string | number, parent: unknown) => (T extends IType<unknown, unknown, infer I> ? I : unknown) | undefined;
|
|
510
|
+
}
|
|
511
|
+
/**
|
|
512
|
+
* Create a dynamic reference that resolves from the model registry.
|
|
513
|
+
* Supports custom get/set resolvers for advanced use cases like API fetching.
|
|
514
|
+
*
|
|
515
|
+
* @param modelName - Name of the model in the registry
|
|
516
|
+
* @param options - Optional custom resolution options
|
|
517
|
+
* @returns A reference type
|
|
518
|
+
*
|
|
519
|
+
* @example
|
|
520
|
+
* // Basic usage - resolves from registry
|
|
521
|
+
* const PostStore = types.model("PostStore", {
|
|
522
|
+
* author: types.dynamicReference("User")
|
|
523
|
+
* });
|
|
524
|
+
*
|
|
525
|
+
* // With custom resolver (e.g., API fetching)
|
|
526
|
+
* const PostStore = types.model("PostStore", {
|
|
527
|
+
* author: types.dynamicReference("User", {
|
|
528
|
+
* get(id, parent) {
|
|
529
|
+
* return userCache.get(id) ?? fetchUserSync(id);
|
|
530
|
+
* },
|
|
531
|
+
* set(user) {
|
|
532
|
+
* return user.id;
|
|
533
|
+
* },
|
|
534
|
+
* onInvalidated(id) {
|
|
535
|
+
* console.warn(`User ${id} not found`);
|
|
536
|
+
* return undefined;
|
|
537
|
+
* }
|
|
538
|
+
* })
|
|
539
|
+
* });
|
|
540
|
+
*/
|
|
541
|
+
declare function dynamicReference<T extends IAnyType = IAnyType>(modelName: string, options?: DynamicReferenceOptions<T>): IType<string | number, string | number, T extends IType<unknown, unknown, infer I> ? I : unknown>;
|
|
542
|
+
/**
|
|
543
|
+
* Create a safe dynamic reference that returns undefined instead of throwing.
|
|
544
|
+
*
|
|
545
|
+
* @param modelName - Name of the model in the registry
|
|
546
|
+
* @param options - Optional custom resolution options
|
|
547
|
+
* @returns A safe reference type
|
|
548
|
+
*/
|
|
549
|
+
declare function safeDynamicReference<T extends IAnyType = IAnyType>(modelName: string, options?: DynamicReferenceOptions<T>): IType<string | number | undefined, string | number | undefined, (T extends IType<unknown, unknown, infer I> ? I : unknown) | undefined>;
|
|
550
|
+
|
|
551
|
+
/** Get the global store */
|
|
552
|
+
declare function getGlobalStore(): jotai_vanilla_internals.INTERNAL_Store;
|
|
553
|
+
/** Set a custom global store (useful for testing) */
|
|
554
|
+
declare function setGlobalStore(store: ReturnType<typeof createStore>): void;
|
|
555
|
+
/** Reset the global store (useful for testing) */
|
|
556
|
+
declare function resetGlobalStore(): void;
|
|
557
|
+
/** Subscribe to lifecycle changes of a node */
|
|
558
|
+
declare function onLifecycleChange(node: StateTreeNode, listener: (isAlive: boolean) => void): IDisposer;
|
|
559
|
+
declare class StateTreeNode implements IStateTreeNode {
|
|
560
|
+
readonly $id: string;
|
|
561
|
+
readonly $type: IAnyType;
|
|
562
|
+
$parent: StateTreeNode | null;
|
|
563
|
+
$path: string;
|
|
564
|
+
$env: unknown;
|
|
565
|
+
$isAlive: boolean;
|
|
566
|
+
/** Child nodes - uses Map but children are explicitly destroyed */
|
|
567
|
+
private children;
|
|
568
|
+
/** Atom storing the raw value/snapshot */
|
|
569
|
+
valueAtom: WritableAtom<unknown, [unknown], void>;
|
|
570
|
+
/** Snapshot listeners */
|
|
571
|
+
private snapshotListeners;
|
|
572
|
+
/** Patch listeners */
|
|
573
|
+
private patchListeners;
|
|
574
|
+
/** Volatile state (non-serialized) */
|
|
575
|
+
volatileState: Record<string, unknown>;
|
|
576
|
+
/** Pre/post process snapshot functions */
|
|
577
|
+
preProcessor?: (snapshot: unknown) => unknown;
|
|
578
|
+
postProcessor?: (snapshot: unknown) => unknown;
|
|
579
|
+
/** Identifier value if this node has one */
|
|
580
|
+
identifierValue?: string | number;
|
|
581
|
+
/** Type name for identifier registry */
|
|
582
|
+
identifierTypeName?: string;
|
|
583
|
+
constructor(type: IAnyType, initialValue: unknown, env?: unknown, parent?: StateTreeNode, pathSegment?: string);
|
|
584
|
+
/** Set the instance reference */
|
|
585
|
+
setInstance(instance: unknown): void;
|
|
586
|
+
/** Get the instance */
|
|
587
|
+
getInstance(): unknown;
|
|
588
|
+
/** Get current value from atom */
|
|
589
|
+
getValue(): unknown;
|
|
590
|
+
/** Set value on atom */
|
|
591
|
+
setValue(value: unknown): void;
|
|
592
|
+
/** Add a child node */
|
|
593
|
+
addChild(key: string, child: StateTreeNode): void;
|
|
594
|
+
/** Recursively update the path of a node and all its children */
|
|
595
|
+
private updatePathRecursively;
|
|
596
|
+
/** Remove a child node */
|
|
597
|
+
removeChild(key: string): void;
|
|
598
|
+
/** Get a child node */
|
|
599
|
+
getChild(key: string): StateTreeNode | undefined;
|
|
600
|
+
/** Get all children */
|
|
601
|
+
getChildren(): Map<string, StateTreeNode>;
|
|
602
|
+
/** Register identifier */
|
|
603
|
+
registerIdentifier(typeName: string, identifier: string | number): void;
|
|
604
|
+
/** Unregister identifier */
|
|
605
|
+
unregisterIdentifier(): void;
|
|
606
|
+
/** Subscribe to snapshot changes */
|
|
607
|
+
onSnapshot(listener: (snapshot: unknown) => void): IDisposer;
|
|
608
|
+
/** Subscribe to patches */
|
|
609
|
+
onPatch(listener: (patch: IJsonPatch, reversePatch: IReversibleJsonPatch) => void): IDisposer;
|
|
610
|
+
/** Notify patch listeners */
|
|
611
|
+
private notifyPatch;
|
|
612
|
+
/** Notify snapshot listeners */
|
|
613
|
+
private notifySnapshotChange;
|
|
614
|
+
/** Notify about a property change (for use by model proxy) */
|
|
615
|
+
notifyPropertyChange(propName: string, newValue: unknown, oldValue: unknown): void;
|
|
616
|
+
/** Get root node */
|
|
617
|
+
getRoot(): StateTreeNode;
|
|
618
|
+
/** Destroy this node and all children */
|
|
619
|
+
destroy(): void;
|
|
620
|
+
/** Detach from parent */
|
|
621
|
+
detach(): void;
|
|
622
|
+
}
|
|
623
|
+
/** Look up a node by identifier */
|
|
624
|
+
declare function resolveIdentifier(typeName: string, identifier: string | number): StateTreeNode | undefined;
|
|
625
|
+
/** Get statistics about the registries - useful for debugging memory issues */
|
|
626
|
+
declare function getRegistryStats(): {
|
|
627
|
+
nodeRegistrySize: number;
|
|
628
|
+
identifierRegistrySize: number;
|
|
629
|
+
identifierTypeCount: number;
|
|
630
|
+
liveNodeCount: number;
|
|
631
|
+
staleNodeCount: number;
|
|
632
|
+
};
|
|
633
|
+
/** Clean up stale entries from registries - call periodically if needed */
|
|
634
|
+
declare function cleanupStaleEntries(): number;
|
|
635
|
+
/** Clear all registries - useful for testing */
|
|
636
|
+
declare function clearAllRegistries(): void;
|
|
637
|
+
/** Get the root of the tree */
|
|
638
|
+
declare function getRoot<T>(target: T): T;
|
|
639
|
+
/** Get the parent of a node */
|
|
640
|
+
declare function getParent<T = unknown>(target: unknown, depth?: number): T;
|
|
641
|
+
/** Try to get the parent, returns undefined if at root */
|
|
642
|
+
declare function tryGetParent<T = unknown>(target: unknown, depth?: number): T | undefined;
|
|
643
|
+
/** Check if a node has a parent */
|
|
644
|
+
declare function hasParent(target: unknown, depth?: number): boolean;
|
|
645
|
+
/** Get parent of specific type */
|
|
646
|
+
declare function getParentOfType<T extends IAnyModelType>(target: unknown, type: T): T extends IType<unknown, unknown, infer I> ? I : never;
|
|
647
|
+
/** Get the path of a node */
|
|
648
|
+
declare function getPath(target: unknown): string;
|
|
649
|
+
/** Get path parts as array */
|
|
650
|
+
declare function getPathParts(target: unknown): string[];
|
|
651
|
+
/** Get the environment */
|
|
652
|
+
declare function getEnv<E = unknown>(target: unknown): E;
|
|
653
|
+
/** Check if node is alive */
|
|
654
|
+
declare function isAlive(target: unknown): boolean;
|
|
655
|
+
/** Check if node is root */
|
|
656
|
+
declare function isRoot(target: unknown): boolean;
|
|
657
|
+
/** Get the type of a node */
|
|
658
|
+
declare function getType(target: unknown): IAnyType;
|
|
659
|
+
/** Check if value is a state tree node */
|
|
660
|
+
declare function isStateTreeNode(value: unknown): boolean;
|
|
661
|
+
/** Get identifier of a node */
|
|
662
|
+
declare function getIdentifier(target: unknown): string | number | null;
|
|
663
|
+
/** Destroy a node */
|
|
664
|
+
declare function destroy(target: unknown): void;
|
|
665
|
+
/** Detach a node from its parent */
|
|
666
|
+
declare function detach<T>(target: T): T;
|
|
667
|
+
/** Clone a node */
|
|
668
|
+
declare function clone<T>(target: T, keepEnvironment?: boolean): T;
|
|
669
|
+
/** Get snapshot from an instance */
|
|
670
|
+
declare function getSnapshot<S>(target: unknown): S;
|
|
671
|
+
/** Apply snapshot to an instance */
|
|
672
|
+
declare function applySnapshot<S>(target: unknown, snapshot: S): void;
|
|
673
|
+
/** Subscribe to snapshots */
|
|
674
|
+
declare function onSnapshot<S>(target: unknown, listener: (snapshot: S) => void): IDisposer;
|
|
675
|
+
/** Subscribe to patches */
|
|
676
|
+
declare function onPatch(target: unknown, listener: (patch: IJsonPatch, reversePatch: IReversibleJsonPatch) => void): IDisposer;
|
|
677
|
+
/** Apply a single patch */
|
|
678
|
+
declare function applyPatch(target: unknown, patch: IJsonPatch | IJsonPatch[]): void;
|
|
679
|
+
/** Record patches during a function execution */
|
|
680
|
+
declare function recordPatches(target: unknown): {
|
|
681
|
+
patches: IJsonPatch[];
|
|
682
|
+
inversePatches: IReversibleJsonPatch[];
|
|
683
|
+
stop: () => void;
|
|
684
|
+
resume: () => void;
|
|
685
|
+
replay: (target: unknown) => void;
|
|
686
|
+
undo: (target: unknown) => void;
|
|
687
|
+
};
|
|
688
|
+
interface ActionCall {
|
|
689
|
+
name: string;
|
|
690
|
+
path: string;
|
|
691
|
+
args: unknown[];
|
|
692
|
+
}
|
|
693
|
+
/** Subscribe to action calls */
|
|
694
|
+
declare function onAction(target: unknown, listener: (call: ActionCall) => void): IDisposer;
|
|
695
|
+
/** Walk the tree */
|
|
696
|
+
declare function walk(target: unknown, visitor: (node: unknown) => void): void;
|
|
697
|
+
/** Get all members (properties) of a node */
|
|
698
|
+
declare function getMembers(target: unknown): {
|
|
699
|
+
name: string;
|
|
700
|
+
type: "view" | "action" | "property" | "volatile";
|
|
701
|
+
value: unknown;
|
|
702
|
+
}[];
|
|
703
|
+
/** Resolve a path to a node */
|
|
704
|
+
declare function resolvePath(target: unknown, path: string): unknown;
|
|
705
|
+
/** Try to resolve a path */
|
|
706
|
+
declare function tryResolve(target: unknown, path: string): unknown | undefined;
|
|
707
|
+
/** Get the relative path from one node to another */
|
|
708
|
+
declare function getRelativePath(from: unknown, to: unknown): string;
|
|
709
|
+
/** Check if a node is an ancestor of another */
|
|
710
|
+
declare function isAncestor(ancestor: unknown, descendant: unknown): boolean;
|
|
711
|
+
/** Check if two nodes share a common root */
|
|
712
|
+
declare function haveSameRoot(a: unknown, b: unknown): boolean;
|
|
713
|
+
/** Get all nodes of a specific type in the tree */
|
|
714
|
+
declare function findAll<T>(target: unknown, predicate: (node: unknown) => node is T): T[];
|
|
715
|
+
/** Get the first node matching a predicate */
|
|
716
|
+
declare function findFirst<T>(target: unknown, predicate: (node: unknown) => node is T): T | undefined;
|
|
717
|
+
/** Check if a value is a valid reference target */
|
|
718
|
+
declare function isValidReference(target: unknown, identifier: string | number): boolean;
|
|
719
|
+
/** Get statistics about the tree */
|
|
720
|
+
declare function getTreeStats(target: unknown): {
|
|
721
|
+
nodeCount: number;
|
|
722
|
+
depth: number;
|
|
723
|
+
types: Record<string, number>;
|
|
724
|
+
};
|
|
725
|
+
/** Create a deep observable copy of a tree */
|
|
726
|
+
declare function cloneDeep<T>(target: T): T;
|
|
727
|
+
/** Get or create a node by path */
|
|
728
|
+
declare function getOrCreatePath(target: unknown, path: string, creator: () => unknown): unknown;
|
|
729
|
+
/** Freeze a node, making it read-only */
|
|
730
|
+
declare function freeze(target: unknown): void;
|
|
731
|
+
/** Check if a node is frozen */
|
|
732
|
+
declare function isFrozen(target: unknown): boolean;
|
|
733
|
+
/** Unfreeze a node */
|
|
734
|
+
declare function unfreeze(target: unknown): void;
|
|
735
|
+
|
|
736
|
+
/**
|
|
737
|
+
* Lifecycle hooks and middleware system
|
|
738
|
+
* Implements afterCreate, beforeDestroy, afterAttach, beforeDetach, etc.
|
|
739
|
+
*
|
|
740
|
+
* MEMORY MANAGEMENT:
|
|
741
|
+
* - Uses WeakMap for all node-keyed registries to allow GC
|
|
742
|
+
* - Action recorders are stored in WeakMap to prevent memory leaks
|
|
743
|
+
* - All registries automatically clean up when nodes are garbage collected
|
|
744
|
+
*/
|
|
745
|
+
|
|
746
|
+
interface IMiddlewareEvent {
|
|
747
|
+
type: "action" | "flow_spawn" | "flow_resume" | "flow_resume_error" | "flow_return" | "flow_throw";
|
|
748
|
+
name: string;
|
|
749
|
+
id: number;
|
|
750
|
+
parentId: number;
|
|
751
|
+
rootId: number;
|
|
752
|
+
context: unknown;
|
|
753
|
+
tree: unknown;
|
|
754
|
+
args: unknown[];
|
|
755
|
+
parentEvent?: IMiddlewareEvent;
|
|
756
|
+
}
|
|
757
|
+
interface IMiddlewareHandler {
|
|
758
|
+
(call: IMiddlewareEvent, next: (call: IMiddlewareEvent, callback?: (value: unknown) => unknown) => unknown, abort: (value: unknown) => unknown): unknown;
|
|
759
|
+
}
|
|
760
|
+
/**
|
|
761
|
+
* Add middleware to the global stack
|
|
762
|
+
*/
|
|
763
|
+
declare function addMiddleware(target: unknown, handler: IMiddlewareHandler, includeHooks?: boolean): IDisposer;
|
|
764
|
+
interface ISerializedActionCall {
|
|
765
|
+
name: string;
|
|
766
|
+
path: string;
|
|
767
|
+
args: unknown[];
|
|
768
|
+
}
|
|
769
|
+
/**
|
|
770
|
+
* Record all actions on a subtree
|
|
771
|
+
*
|
|
772
|
+
* MEMORY SAFETY: Uses WeakMap so nodes can be garbage collected
|
|
773
|
+
* even while recording is active. The stop() function properly
|
|
774
|
+
* cleans up the recorder from the Set.
|
|
775
|
+
*/
|
|
776
|
+
declare function recordActions(target: unknown): {
|
|
777
|
+
actions: ISerializedActionCall[];
|
|
778
|
+
stop: () => void;
|
|
779
|
+
replay: (target: unknown) => void;
|
|
780
|
+
};
|
|
781
|
+
/**
|
|
782
|
+
* Protect a node from direct mutations outside of actions
|
|
783
|
+
*/
|
|
784
|
+
declare function protect(target: unknown): void;
|
|
785
|
+
/**
|
|
786
|
+
* Unprotect a node to allow direct mutations
|
|
787
|
+
*/
|
|
788
|
+
declare function unprotect(target: unknown): void;
|
|
789
|
+
/**
|
|
790
|
+
* Check if a node is protected
|
|
791
|
+
*/
|
|
792
|
+
declare function isProtected(target: unknown): boolean;
|
|
793
|
+
/**
|
|
794
|
+
* Apply an action call to a target
|
|
795
|
+
*/
|
|
796
|
+
declare function applyAction(target: unknown, action: ISerializedActionCall): unknown;
|
|
797
|
+
/**
|
|
798
|
+
* Escape a JSON pointer segment
|
|
799
|
+
*/
|
|
800
|
+
declare function escapeJsonPath(path: string): string;
|
|
801
|
+
/**
|
|
802
|
+
* Unescape a JSON pointer segment
|
|
803
|
+
*/
|
|
804
|
+
declare function unescapeJsonPath(path: string): string;
|
|
805
|
+
/**
|
|
806
|
+
* Split a path into segments
|
|
807
|
+
*/
|
|
808
|
+
declare function splitJsonPath(path: string): string[];
|
|
809
|
+
/**
|
|
810
|
+
* Join path segments
|
|
811
|
+
*/
|
|
812
|
+
declare function joinJsonPath(parts: string[]): string;
|
|
813
|
+
|
|
814
|
+
/**
|
|
815
|
+
* Additional MST compatibility utilities
|
|
816
|
+
* These utilities help with edge cases and compatibility
|
|
817
|
+
*/
|
|
818
|
+
|
|
819
|
+
/**
|
|
820
|
+
* Check if the given value looks like a type (has the type interface)
|
|
821
|
+
*/
|
|
822
|
+
declare function isType(value: unknown): value is IAnyType;
|
|
823
|
+
/**
|
|
824
|
+
* Check if a value is a primitive type
|
|
825
|
+
*/
|
|
826
|
+
declare function isPrimitiveType(type: unknown): boolean;
|
|
827
|
+
/**
|
|
828
|
+
* Get the string name of a type
|
|
829
|
+
*/
|
|
830
|
+
declare function getTypeName(type: IAnyType): string;
|
|
831
|
+
/**
|
|
832
|
+
* Check if value could be a valid snapshot for the given type
|
|
833
|
+
*/
|
|
834
|
+
declare function isValidSnapshot<T extends IAnyType>(type: T, value: unknown): value is SnapshotIn<T>;
|
|
835
|
+
/**
|
|
836
|
+
* Get a human-readable validation error message
|
|
837
|
+
*/
|
|
838
|
+
declare function getValidationError(type: IAnyType, value: unknown): string | null;
|
|
839
|
+
/**
|
|
840
|
+
* Check if value is an instance of a specific model type
|
|
841
|
+
*/
|
|
842
|
+
declare function isInstanceOf<T extends IAnyModelType>(value: unknown, type: T): value is Instance<T>;
|
|
843
|
+
/**
|
|
844
|
+
* Get the live instance from a snapshot, or create one if needed
|
|
845
|
+
*/
|
|
846
|
+
declare function getOrCreate<T extends IAnyType>(type: T, snapshotOrInstance: SnapshotIn<T> | Instance<T>, env?: unknown): Instance<T>;
|
|
847
|
+
/**
|
|
848
|
+
* Get a debug-friendly representation of a state tree node
|
|
849
|
+
*/
|
|
850
|
+
declare function getDebugInfo(target: unknown): {
|
|
851
|
+
typeName: string;
|
|
852
|
+
path: string;
|
|
853
|
+
identifier: string | number | null;
|
|
854
|
+
isAlive: boolean;
|
|
855
|
+
snapshot: unknown;
|
|
856
|
+
};
|
|
857
|
+
/**
|
|
858
|
+
* Print a tree structure for debugging
|
|
859
|
+
*/
|
|
860
|
+
declare function printTree(target: unknown, indent?: number): string;
|
|
861
|
+
/**
|
|
862
|
+
* Check if a model type has an identifier
|
|
863
|
+
*/
|
|
864
|
+
declare function hasIdentifier(type: IAnyModelType): boolean;
|
|
865
|
+
/**
|
|
866
|
+
* Get the identifier attribute name for a model type
|
|
867
|
+
*/
|
|
868
|
+
declare function getIdentifierAttribute(type: IAnyModelType): string | undefined;
|
|
869
|
+
/**
|
|
870
|
+
* Create a type that is a union of all provided types
|
|
871
|
+
* but where null/undefined are always valid
|
|
872
|
+
*/
|
|
873
|
+
declare function nullable<T extends IAnyType>(type: T): IType<(T extends IType<infer C, unknown, unknown> ? C : never) | null | undefined, (T extends IType<unknown, infer S, unknown> ? S : never) | null | undefined, (T extends IType<unknown, unknown, infer I> ? I : never) | null | undefined>;
|
|
874
|
+
/**
|
|
875
|
+
* Deep clone a frozen value
|
|
876
|
+
*/
|
|
877
|
+
declare function cloneFrozen<T>(value: T): T;
|
|
878
|
+
/**
|
|
879
|
+
* Safely create an instance, returning undefined on failure
|
|
880
|
+
*/
|
|
881
|
+
declare function safeCreate<T extends IAnyType>(type: T, snapshot: unknown, env?: unknown): Instance<T> | undefined;
|
|
882
|
+
/**
|
|
883
|
+
* Create an instance with defaults for missing values
|
|
884
|
+
*/
|
|
885
|
+
declare function createWithDefaults<T extends IAnyType>(type: T, snapshot?: Partial<SnapshotIn<T>>, env?: unknown): Instance<T>;
|
|
886
|
+
|
|
887
|
+
/**
|
|
888
|
+
* Undo/Redo Manager for jotai-state-tree
|
|
889
|
+
* Provides time-travel debugging capabilities
|
|
890
|
+
*/
|
|
891
|
+
|
|
892
|
+
interface IUndoManagerOptions {
|
|
893
|
+
/** Maximum number of history entries to keep */
|
|
894
|
+
maxHistoryLength?: number;
|
|
895
|
+
/** Whether to group rapid changes together */
|
|
896
|
+
groupByTime?: boolean;
|
|
897
|
+
/** Time window for grouping changes (ms) */
|
|
898
|
+
groupingWindow?: number;
|
|
899
|
+
}
|
|
900
|
+
interface IHistoryEntry {
|
|
901
|
+
/** Patches to apply to undo this entry */
|
|
902
|
+
patches: IReversibleJsonPatch[];
|
|
903
|
+
/** Patches to apply to redo this entry */
|
|
904
|
+
inversePatches: IReversibleJsonPatch[];
|
|
905
|
+
/** Timestamp when this entry was created */
|
|
906
|
+
timestamp: number;
|
|
907
|
+
}
|
|
908
|
+
interface IUndoManager {
|
|
909
|
+
/** Whether there are entries that can be undone */
|
|
910
|
+
readonly canUndo: boolean;
|
|
911
|
+
/** Whether there are entries that can be redone */
|
|
912
|
+
readonly canRedo: boolean;
|
|
913
|
+
/** Number of undo entries available */
|
|
914
|
+
readonly undoLevels: number;
|
|
915
|
+
/** Number of redo entries available */
|
|
916
|
+
readonly redoLevels: number;
|
|
917
|
+
/** The full history */
|
|
918
|
+
readonly history: IHistoryEntry[];
|
|
919
|
+
/** Current position in history */
|
|
920
|
+
readonly historyIndex: number;
|
|
921
|
+
/** Undo the last change */
|
|
922
|
+
undo(): void;
|
|
923
|
+
/** Redo the last undone change */
|
|
924
|
+
redo(): void;
|
|
925
|
+
/** Clear all history */
|
|
926
|
+
clear(): void;
|
|
927
|
+
/** Start grouping changes */
|
|
928
|
+
startGroup(): void;
|
|
929
|
+
/** End grouping changes */
|
|
930
|
+
endGroup(): void;
|
|
931
|
+
/** Execute a function without recording history */
|
|
932
|
+
withoutUndo<T>(fn: () => T): T;
|
|
933
|
+
/** Stop tracking changes */
|
|
934
|
+
dispose(): void;
|
|
935
|
+
}
|
|
936
|
+
/**
|
|
937
|
+
* Create an undo manager for a state tree
|
|
938
|
+
*/
|
|
939
|
+
declare function createUndoManager(target: unknown, options?: IUndoManagerOptions): IUndoManager;
|
|
940
|
+
interface ITimeTravelManager {
|
|
941
|
+
/** Current snapshot index */
|
|
942
|
+
readonly currentIndex: number;
|
|
943
|
+
/** Total number of snapshots */
|
|
944
|
+
readonly snapshotCount: number;
|
|
945
|
+
/** Whether we can go back */
|
|
946
|
+
readonly canGoBack: boolean;
|
|
947
|
+
/** Whether we can go forward */
|
|
948
|
+
readonly canGoForward: boolean;
|
|
949
|
+
/** Record the current snapshot */
|
|
950
|
+
record(): void;
|
|
951
|
+
/** Go back to previous snapshot */
|
|
952
|
+
goBack(): void;
|
|
953
|
+
/** Go forward to next snapshot */
|
|
954
|
+
goForward(): void;
|
|
955
|
+
/** Go to a specific snapshot index */
|
|
956
|
+
goTo(index: number): void;
|
|
957
|
+
/** Get snapshot at index */
|
|
958
|
+
getSnapshot(index: number): unknown;
|
|
959
|
+
/** Clear all snapshots */
|
|
960
|
+
clear(): void;
|
|
961
|
+
/** Dispose and clean up */
|
|
962
|
+
dispose(): void;
|
|
963
|
+
}
|
|
964
|
+
/**
|
|
965
|
+
* Create a time travel manager for snapshot-based history
|
|
966
|
+
*/
|
|
967
|
+
declare function createTimeTravelManager(target: unknown, options?: {
|
|
968
|
+
maxSnapshots?: number;
|
|
969
|
+
autoRecord?: boolean;
|
|
970
|
+
}): ITimeTravelManager;
|
|
971
|
+
interface IActionRecording {
|
|
972
|
+
/** Name of the action */
|
|
973
|
+
name: string;
|
|
974
|
+
/** Path to the node where action was called */
|
|
975
|
+
path: string;
|
|
976
|
+
/** Arguments passed to the action */
|
|
977
|
+
args: unknown[];
|
|
978
|
+
/** Timestamp */
|
|
979
|
+
timestamp: number;
|
|
980
|
+
}
|
|
981
|
+
interface IActionRecorder {
|
|
982
|
+
/** Whether currently recording */
|
|
983
|
+
readonly isRecording: boolean;
|
|
984
|
+
/** All recorded actions */
|
|
985
|
+
readonly actions: IActionRecording[];
|
|
986
|
+
/** Start recording */
|
|
987
|
+
start(): void;
|
|
988
|
+
/** Stop recording */
|
|
989
|
+
stop(): void;
|
|
990
|
+
/** Clear recorded actions */
|
|
991
|
+
clear(): void;
|
|
992
|
+
/** Replay actions on a target */
|
|
993
|
+
replay(target: unknown): void;
|
|
994
|
+
/** Export actions as JSON */
|
|
995
|
+
export(): string;
|
|
996
|
+
/** Import actions from JSON */
|
|
997
|
+
import(json: string): void;
|
|
998
|
+
/** Dispose and clean up */
|
|
999
|
+
dispose(): void;
|
|
1000
|
+
}
|
|
1001
|
+
/**
|
|
1002
|
+
* Create an action recorder for debugging and testing
|
|
1003
|
+
*/
|
|
1004
|
+
declare function createActionRecorder(target: unknown): IActionRecorder;
|
|
1005
|
+
|
|
1006
|
+
/**
|
|
1007
|
+
* The `types` namespace contains all type constructors.
|
|
1008
|
+
* This matches the MobX-State-Tree API.
|
|
1009
|
+
*/
|
|
1010
|
+
declare const types: {
|
|
1011
|
+
string: ISimpleType<string>;
|
|
1012
|
+
number: ISimpleType<number>;
|
|
1013
|
+
integer: ISimpleType<number>;
|
|
1014
|
+
boolean: ISimpleType<boolean>;
|
|
1015
|
+
Date: IType<number | Date, number, Date>;
|
|
1016
|
+
null: ISimpleType<null>;
|
|
1017
|
+
undefined: ISimpleType<undefined>;
|
|
1018
|
+
finite: ISimpleType<number>;
|
|
1019
|
+
float: ISimpleType<number>;
|
|
1020
|
+
identifier: IIdentifierType;
|
|
1021
|
+
identifierNumber: IIdentifierNumberType;
|
|
1022
|
+
literal: typeof literal;
|
|
1023
|
+
enumeration: typeof enumeration;
|
|
1024
|
+
frozen: typeof frozen;
|
|
1025
|
+
custom: typeof custom;
|
|
1026
|
+
model: typeof model;
|
|
1027
|
+
compose: typeof compose;
|
|
1028
|
+
array: typeof array;
|
|
1029
|
+
map: typeof map;
|
|
1030
|
+
optional: typeof optional;
|
|
1031
|
+
maybe: typeof maybe;
|
|
1032
|
+
maybeNull: typeof maybeNull;
|
|
1033
|
+
union: typeof union;
|
|
1034
|
+
late: typeof late;
|
|
1035
|
+
reference: typeof reference;
|
|
1036
|
+
safeReference: typeof safeReference;
|
|
1037
|
+
refinement: typeof refinement;
|
|
1038
|
+
snapshotProcessor: typeof snapshotProcessor;
|
|
1039
|
+
lateModel: typeof lateModel;
|
|
1040
|
+
dynamicReference: typeof dynamicReference;
|
|
1041
|
+
safeDynamicReference: typeof safeDynamicReference;
|
|
1042
|
+
};
|
|
1043
|
+
|
|
1044
|
+
/**
|
|
1045
|
+
* Creates an async action (generator function) that can be yielded.
|
|
1046
|
+
* Compatible with MST's flow().
|
|
1047
|
+
*/
|
|
1048
|
+
declare function flow<Args extends unknown[], R>(generator: (...args: Args) => Generator<Promise<unknown>, R, unknown>): (...args: Args) => Promise<R>;
|
|
1049
|
+
/**
|
|
1050
|
+
* Cast a value to a different type.
|
|
1051
|
+
* Useful for working around TypeScript limitations.
|
|
1052
|
+
*/
|
|
1053
|
+
declare function cast<T>(value: unknown): T;
|
|
1054
|
+
/**
|
|
1055
|
+
* Cast a value to a snapshot type.
|
|
1056
|
+
*/
|
|
1057
|
+
declare function castToSnapshot<T>(value: T): T;
|
|
1058
|
+
/**
|
|
1059
|
+
* Cast a value to a reference snapshot (identifier).
|
|
1060
|
+
*/
|
|
1061
|
+
declare function castToReferenceSnapshot<T>(value: T): string | number;
|
|
1062
|
+
/**
|
|
1063
|
+
* Check if a value is a valid identifier.
|
|
1064
|
+
*/
|
|
1065
|
+
declare function isIdentifierType(type: unknown): type is typeof identifier | typeof identifierNumber;
|
|
1066
|
+
/**
|
|
1067
|
+
* Check if a type is a model type.
|
|
1068
|
+
*/
|
|
1069
|
+
declare function isModelType(type: unknown): boolean;
|
|
1070
|
+
/**
|
|
1071
|
+
* Check if a type is an array type.
|
|
1072
|
+
*/
|
|
1073
|
+
declare function isArrayType(type: unknown): boolean;
|
|
1074
|
+
/**
|
|
1075
|
+
* Check if a type is a map type.
|
|
1076
|
+
*/
|
|
1077
|
+
declare function isMapType(type: unknown): boolean;
|
|
1078
|
+
/**
|
|
1079
|
+
* Check if a type is a reference type.
|
|
1080
|
+
*/
|
|
1081
|
+
declare function isReferenceType(type: unknown): boolean;
|
|
1082
|
+
/**
|
|
1083
|
+
* Check if a type is a union type.
|
|
1084
|
+
*/
|
|
1085
|
+
declare function isUnionType(type: unknown): boolean;
|
|
1086
|
+
/**
|
|
1087
|
+
* Check if a type is an optional type.
|
|
1088
|
+
*/
|
|
1089
|
+
declare function isOptionalType(type: unknown): boolean;
|
|
1090
|
+
/**
|
|
1091
|
+
* Check if a type is a late type.
|
|
1092
|
+
*/
|
|
1093
|
+
declare function isLateType(type: unknown): boolean;
|
|
1094
|
+
/**
|
|
1095
|
+
* Check if a type is a frozen type.
|
|
1096
|
+
*/
|
|
1097
|
+
declare function isFrozenType(type: unknown): boolean;
|
|
1098
|
+
/**
|
|
1099
|
+
* Check if a type is a literal type.
|
|
1100
|
+
*/
|
|
1101
|
+
declare function isLiteralType(type: unknown): boolean;
|
|
1102
|
+
/**
|
|
1103
|
+
* Get the type of a value, or undefined if not a state tree node.
|
|
1104
|
+
*/
|
|
1105
|
+
declare function typecheck<T>(type: {
|
|
1106
|
+
is(v: unknown): v is T;
|
|
1107
|
+
}, value: unknown): void;
|
|
1108
|
+
|
|
1109
|
+
export { type CustomTypeOptions$1 as CustomTypeOptions, DatePrimitive as Date, type DynamicReferenceOptions, type IActionRecorder, type IActionRecording, type IAnyComplexType, type IAnyModelType, type IAnyType, type IArrayType, type IDisposer, type IEnumerationType, type IFrozenType, type IHistoryEntry, type IIdentifierNumberType, type IIdentifierType, type IJsonPatch, type ILateType, type ILiteralType, type IMSTArray, type IMSTMap, type IMapType, type IMaybeNullType, type IMaybeType, type IMiddlewareEvent, type IMiddlewareHandler, type IModelType, type IOptionalType, type IReferenceType, type IRefinementType, type IReversibleJsonPatch, type ISafeReferenceType, type ISerializedActionCall, type ISimpleType, type IStateTreeNode, type ITimeTravelManager, type IType, type IUndoManager, type IUndoManagerOptions, type IUnionType, type IValidationContext, type IValidationError, type IValidationResult, type Instance, type ModelInstance, type ModelProperties, type ReferenceOptions, type SnapshotIn, type SnapshotOut, type UnionOptions, addMiddleware, applyAction, applyPatch, applySnapshot, array, boolean, cast, castToReferenceSnapshot, castToSnapshot, cleanupStaleEntries, clearAllRegistries, clearModelRegistry, clone, cloneDeep, cloneFrozen, compose, createActionRecorder, createTimeTravelManager, createUndoManager, createWithDefaults, custom, types as default, destroy, detach, dynamicReference, enumeration, escapeJsonPath, findAll, findFirst, finite, float, flow, freeze, frozen, getDebugInfo, getEnv, getGlobalStore, getIdentifier, getIdentifierAttribute, getMembers, getModelMetadata, getOrCreate, getOrCreatePath, getParent, getParentOfType, getPath, getPathParts, getRegisteredModelNames, getRegistryStats, getRelativePath, getRoot, getSnapshot, getTreeStats, getType, getTypeName, getValidationError, hasIdentifier, hasParent, haveSameRoot, identifier, identifierNumber, integer, isAlive, isAncestor, isArrayType, isFrozen, isFrozenType, isIdentifierType, isInstanceOf, isLateType, isLiteralType, isMapType, isModelRegistered, isModelType, isOptionalType, isPrimitiveType, isProtected, isReferenceType, isRoot, isStateTreeNode, isType, isUnionType, isValidReference, isValidSnapshot, joinJsonPath, late, lateModel, literal, map, maybe, maybeNull, model, nullType, nullable, number, onAction, onLifecycleChange, onModelRegistered, onPatch, onSnapshot, optional, printTree, protect, recordActions, recordPatches, reference, refinement, registerModel, resetGlobalStore, resolveIdentifier, resolveModel, resolveModelAsync, resolvePath, safeCreate, safeDynamicReference, safeReference, setGlobalStore, snapshotProcessor, splitJsonPath, string, tryGetParent, tryResolve, tryResolveModel, typecheck, types, undefinedType, unescapeJsonPath, unfreeze, union, unprotect, unregisterModel, walk };
|