@doeixd/machine 0.0.4 → 0.0.5
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 +952 -13
- package/dist/cjs/development/index.js +691 -0
- package/dist/cjs/development/index.js.map +4 -4
- package/dist/cjs/production/index.js +5 -1
- package/dist/esm/development/index.js +698 -0
- package/dist/esm/development/index.js.map +4 -4
- package/dist/esm/production/index.js +5 -1
- package/dist/types/extract.d.ts +71 -0
- package/dist/types/extract.d.ts.map +1 -0
- package/dist/types/index.d.ts +5 -0
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/multi.d.ts +838 -0
- package/dist/types/multi.d.ts.map +1 -0
- package/dist/types/primitives.d.ts +202 -0
- package/dist/types/primitives.d.ts.map +1 -0
- package/dist/types/runtime-extract.d.ts +53 -0
- package/dist/types/runtime-extract.d.ts.map +1 -0
- package/package.json +6 -2
- package/src/extract.ts +452 -67
- package/src/index.ts +49 -0
- package/src/multi.ts +1145 -0
- package/src/primitives.ts +134 -0
- package/src/react.ts +349 -28
- package/src/runtime-extract.ts +141 -0
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file Runtime statechart extraction utilities
|
|
3
|
+
* @description Extract statecharts from running machine instances using Symbol-based metadata
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { RUNTIME_META, type RuntimeTransitionMeta } from './primitives';
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Extract metadata from a single function if it has runtime metadata attached
|
|
10
|
+
*
|
|
11
|
+
* @param fn - Function to extract from
|
|
12
|
+
* @returns Metadata object or null if no metadata
|
|
13
|
+
*/
|
|
14
|
+
export function extractFunctionMetadata(fn: any): RuntimeTransitionMeta | null {
|
|
15
|
+
if (typeof fn !== 'function') {
|
|
16
|
+
return null;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
const meta = fn[RUNTIME_META];
|
|
20
|
+
return meta || null;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Extract state node from a machine class instance
|
|
25
|
+
*
|
|
26
|
+
* @param stateInstance - Instance of a machine state class
|
|
27
|
+
* @returns State node with transitions
|
|
28
|
+
*/
|
|
29
|
+
export function extractStateNode(stateInstance: any): any {
|
|
30
|
+
const stateNode: any = { on: {} };
|
|
31
|
+
const invoke: any[] = [];
|
|
32
|
+
|
|
33
|
+
// Iterate over all properties
|
|
34
|
+
for (const key in stateInstance) {
|
|
35
|
+
const value = stateInstance[key];
|
|
36
|
+
|
|
37
|
+
if (typeof value !== 'function') {
|
|
38
|
+
continue;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
const meta = extractFunctionMetadata(value);
|
|
42
|
+
if (!meta) {
|
|
43
|
+
continue;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
// Separate invoke from transitions
|
|
47
|
+
if (meta.invoke) {
|
|
48
|
+
invoke.push({
|
|
49
|
+
src: meta.invoke.src,
|
|
50
|
+
onDone: { target: meta.invoke.onDone },
|
|
51
|
+
onError: { target: meta.invoke.onError },
|
|
52
|
+
description: meta.invoke.description
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
// If has target, it's a transition
|
|
57
|
+
if (meta.target) {
|
|
58
|
+
const transition: any = { target: meta.target };
|
|
59
|
+
|
|
60
|
+
if (meta.description) {
|
|
61
|
+
transition.description = meta.description;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
if (meta.guards && meta.guards.length > 0) {
|
|
65
|
+
transition.cond = meta.guards.map(g => g.name).join(' && ');
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
if (meta.actions && meta.actions.length > 0) {
|
|
69
|
+
transition.actions = meta.actions.map(a => a.name);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
stateNode.on[key] = transition;
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
if (invoke.length > 0) {
|
|
77
|
+
stateNode.invoke = invoke;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
return stateNode;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* Generate a complete statechart from multiple state class instances
|
|
85
|
+
*
|
|
86
|
+
* @param states - Object mapping state names to state instances
|
|
87
|
+
* @param config - Chart configuration
|
|
88
|
+
* @returns XState-compatible statechart JSON
|
|
89
|
+
*
|
|
90
|
+
* @example
|
|
91
|
+
* const chart = generateStatechart({
|
|
92
|
+
* 'LoggedOut': new LoggedOutMachine(),
|
|
93
|
+
* 'LoggedIn': new LoggedInMachine()
|
|
94
|
+
* }, {
|
|
95
|
+
* id: 'auth',
|
|
96
|
+
* initial: 'LoggedOut'
|
|
97
|
+
* });
|
|
98
|
+
*/
|
|
99
|
+
export function generateStatechart(
|
|
100
|
+
states: Record<string, any>,
|
|
101
|
+
config: { id: string; initial: string; description?: string }
|
|
102
|
+
): any {
|
|
103
|
+
const chart: any = {
|
|
104
|
+
id: config.id,
|
|
105
|
+
initial: config.initial,
|
|
106
|
+
states: {}
|
|
107
|
+
};
|
|
108
|
+
|
|
109
|
+
if (config.description) {
|
|
110
|
+
chart.description = config.description;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
for (const [stateName, stateInstance] of Object.entries(states)) {
|
|
114
|
+
chart.states[stateName] = extractStateNode(stateInstance);
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
return chart;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
/**
|
|
121
|
+
* Convenience function to extract statechart from a single machine instance
|
|
122
|
+
* Useful for simple machines with a single context but multiple transitions
|
|
123
|
+
*
|
|
124
|
+
* @param machineInstance - Machine instance
|
|
125
|
+
* @param config - Chart configuration
|
|
126
|
+
* @returns XState-compatible statechart JSON
|
|
127
|
+
*/
|
|
128
|
+
export function extractFromInstance(
|
|
129
|
+
machineInstance: any,
|
|
130
|
+
config: { id: string; stateName?: string }
|
|
131
|
+
): any {
|
|
132
|
+
const stateName = config.stateName || machineInstance.constructor.name || 'State';
|
|
133
|
+
|
|
134
|
+
return {
|
|
135
|
+
id: config.id,
|
|
136
|
+
initial: stateName,
|
|
137
|
+
states: {
|
|
138
|
+
[stateName]: extractStateNode(machineInstance)
|
|
139
|
+
}
|
|
140
|
+
};
|
|
141
|
+
}
|