@pyreon/state-tree 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +249 -0
- package/lib/analysis/devtools.js.html +5406 -0
- package/lib/analysis/index.js.html +5406 -0
- package/lib/devtools.js +111 -0
- package/lib/devtools.js.map +1 -0
- package/lib/index.js +353 -0
- package/lib/index.js.map +1 -0
- package/lib/types/devtools.d.ts +104 -0
- package/lib/types/devtools.d.ts.map +1 -0
- package/lib/types/devtools2.d.ts +40 -0
- package/lib/types/devtools2.d.ts.map +1 -0
- package/lib/types/index.d.ts +316 -0
- package/lib/types/index.d.ts.map +1 -0
- package/lib/types/index2.d.ts +198 -0
- package/lib/types/index2.d.ts.map +1 -0
- package/package.json +54 -0
- package/src/devtools.ts +87 -0
- package/src/index.ts +29 -0
- package/src/instance.ts +128 -0
- package/src/middleware.ts +57 -0
- package/src/model.ts +117 -0
- package/src/patch.ts +173 -0
- package/src/registry.ts +16 -0
- package/src/snapshot.ts +66 -0
- package/src/tests/devtools.test.ts +163 -0
- package/src/tests/model.test.ts +718 -0
- package/src/types.ts +98 -0
package/src/types.ts
ADDED
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
import type { Computed, Signal } from '@pyreon/reactivity'
|
|
2
|
+
|
|
3
|
+
// ─── Model brand ──────────────────────────────────────────────────────────────
|
|
4
|
+
|
|
5
|
+
/** Property key stamped on every ModelDefinition to distinguish it from plain objects. */
|
|
6
|
+
export const MODEL_BRAND = '__pyreonMod' as const
|
|
7
|
+
|
|
8
|
+
// ─── State type helpers ───────────────────────────────────────────────────────
|
|
9
|
+
|
|
10
|
+
export type StateShape = Record<string, unknown>
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Resolve a state field type:
|
|
14
|
+
* - ModelDefinition → the instance type it produces
|
|
15
|
+
* - Anything else → as-is
|
|
16
|
+
*/
|
|
17
|
+
export type ResolveField<T> = T extends {
|
|
18
|
+
readonly __pyreonMod: true
|
|
19
|
+
create(initial?: any): infer I
|
|
20
|
+
}
|
|
21
|
+
? I
|
|
22
|
+
: T
|
|
23
|
+
|
|
24
|
+
/** Map state shape to per-field signals. */
|
|
25
|
+
export type StateSignals<TState extends StateShape> = {
|
|
26
|
+
readonly [K in keyof TState]: Signal<ResolveField<TState[K]>>
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* `self` type inside actions / views:
|
|
31
|
+
* strongly typed for state signals, `any` for actions and views so that
|
|
32
|
+
* actions can call each other without circular type issues.
|
|
33
|
+
*/
|
|
34
|
+
export type ModelSelf<TState extends StateShape> = StateSignals<TState> &
|
|
35
|
+
Record<string, any>
|
|
36
|
+
|
|
37
|
+
/** The public instance type returned by `.create()` and hooks. */
|
|
38
|
+
export type ModelInstance<
|
|
39
|
+
TState extends StateShape,
|
|
40
|
+
TActions extends Record<string, (...args: any[]) => any>,
|
|
41
|
+
TViews extends Record<string, Signal<any> | Computed<any>>,
|
|
42
|
+
> = StateSignals<TState> & TActions & TViews
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Extract the state type from a ModelDefinition.
|
|
46
|
+
* Used by Snapshot to recursively resolve nested model types.
|
|
47
|
+
*/
|
|
48
|
+
type ExtractModelState<T> = T extends {
|
|
49
|
+
readonly __pyreonMod: true
|
|
50
|
+
readonly _config: { state: infer S extends StateShape }
|
|
51
|
+
}
|
|
52
|
+
? S
|
|
53
|
+
: never
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Snapshot type: plain JS values (no signals, no model instances).
|
|
57
|
+
* Nested model fields recursively produce their own typed snapshot.
|
|
58
|
+
*/
|
|
59
|
+
export type Snapshot<TState extends StateShape> = {
|
|
60
|
+
[K in keyof TState]: TState[K] extends { readonly __pyreonMod: true }
|
|
61
|
+
? Snapshot<ExtractModelState<TState[K]>>
|
|
62
|
+
: TState[K]
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
// ─── Patch ────────────────────────────────────────────────────────────────────
|
|
66
|
+
|
|
67
|
+
export interface Patch {
|
|
68
|
+
op: 'replace'
|
|
69
|
+
path: string
|
|
70
|
+
value: unknown
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
export type PatchListener = (patch: Patch) => void
|
|
74
|
+
|
|
75
|
+
// ─── Middleware ───────────────────────────────────────────────────────────────
|
|
76
|
+
|
|
77
|
+
export interface ActionCall {
|
|
78
|
+
/** Action name. */
|
|
79
|
+
name: string
|
|
80
|
+
/** Arguments passed to the action. */
|
|
81
|
+
args: unknown[]
|
|
82
|
+
/** JSON-pointer-style path, e.g. `"/inc"`. */
|
|
83
|
+
path: string
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
export type MiddlewareFn = (
|
|
87
|
+
call: ActionCall,
|
|
88
|
+
next: (nextCall: ActionCall) => unknown,
|
|
89
|
+
) => unknown
|
|
90
|
+
|
|
91
|
+
// ─── Instance metadata ────────────────────────────────────────────────────────
|
|
92
|
+
|
|
93
|
+
export interface InstanceMeta {
|
|
94
|
+
stateKeys: string[]
|
|
95
|
+
patchListeners: Set<PatchListener>
|
|
96
|
+
middlewares: MiddlewareFn[]
|
|
97
|
+
emitPatch(patch: Patch): void
|
|
98
|
+
}
|