xstate 6.0.0-alpha.8 → 6.0.0-beta.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.
Files changed (235) hide show
  1. package/README.md +223 -78
  2. package/bin/agent.js +347 -0
  3. package/bin/xstate.js +52 -0
  4. package/dist/createActor-25900f76.cjs.js +7015 -0
  5. package/dist/createActor-551369be.development.esm.js +7175 -0
  6. package/dist/createActor-a49ae0ce.development.cjs.js +7289 -0
  7. package/dist/createActor-cbe3abac.esm.js +6902 -0
  8. package/dist/declarations/src/SimulatedClock.d.ts +2 -1
  9. package/dist/declarations/src/State.d.ts +66 -5
  10. package/dist/declarations/src/StateMachine.d.ts +107 -32
  11. package/dist/declarations/src/StateNode.d.ts +21 -16
  12. package/dist/declarations/src/actions.d.ts +11 -6
  13. package/dist/declarations/src/actors/callback.d.ts +11 -2
  14. package/dist/declarations/src/actors/index.d.ts +6 -5
  15. package/dist/declarations/src/actors/listener.d.ts +8 -3
  16. package/dist/declarations/src/actors/logic.d.ts +42 -52
  17. package/dist/declarations/src/actors/observable.d.ts +15 -2
  18. package/dist/declarations/src/actors/promise.d.ts +90 -22
  19. package/dist/declarations/src/actors/subscription.d.ts +9 -3
  20. package/dist/declarations/src/assert.d.ts +1 -0
  21. package/dist/declarations/src/base.types.d.ts +102 -0
  22. package/dist/declarations/src/createActor.d.ts +101 -27
  23. package/dist/declarations/src/createMachine.d.ts +38 -17
  24. package/dist/declarations/src/delay.d.ts +8 -0
  25. package/dist/declarations/src/durable/index.d.ts +231 -0
  26. package/dist/declarations/src/effectDescriptor.d.ts +95 -0
  27. package/dist/declarations/src/eventTypes.d.ts +9 -0
  28. package/dist/declarations/src/fsm/index.d.ts +2 -0
  29. package/dist/declarations/src/fsm.d.ts +169 -0
  30. package/dist/declarations/src/graph/adjacency.d.ts +6 -3
  31. package/dist/declarations/src/graph/graph.d.ts +6 -3
  32. package/dist/declarations/src/graph/index.d.ts +2 -3
  33. package/dist/declarations/src/graph/pathFromEvents.d.ts +5 -2
  34. package/dist/declarations/src/graph/shortestPaths.d.ts +5 -3
  35. package/dist/declarations/src/graph/simplePaths.d.ts +5 -3
  36. package/dist/declarations/src/graph/types.d.ts +113 -59
  37. package/dist/declarations/src/hotSwap.d.ts +18 -0
  38. package/dist/declarations/src/index.d.ts +28 -19
  39. package/dist/declarations/src/inspection.d.ts +24 -1
  40. package/dist/declarations/src/machineFromJSON.d.ts +171 -0
  41. package/dist/declarations/src/machineSchemas.d.ts +27 -0
  42. package/dist/declarations/src/machineVersion.types.d.ts +53 -0
  43. package/dist/declarations/src/machineVersions.d.ts +103 -0
  44. package/dist/declarations/src/mapState.d.ts +2 -0
  45. package/dist/declarations/src/persist/index.d.ts +36 -0
  46. package/dist/declarations/src/persistedSnapshotValidation.d.ts +18 -0
  47. package/dist/declarations/src/runtimeHelpers.d.ts +43 -0
  48. package/dist/declarations/src/schema.types.d.ts +31 -4
  49. package/dist/declarations/src/serialize.d.ts +39 -28
  50. package/dist/declarations/src/setup.d.ts +1086 -147
  51. package/dist/declarations/src/spawn.d.ts +6 -4
  52. package/dist/declarations/src/stateUtils.d.ts +57 -14
  53. package/dist/declarations/src/system.d.ts +178 -17
  54. package/dist/declarations/src/systemTransition.d.ts +108 -0
  55. package/dist/declarations/src/toPromise.d.ts +1 -0
  56. package/dist/declarations/src/transition.d.ts +48 -10
  57. package/dist/declarations/src/transitionActions.d.ts +22 -4
  58. package/dist/declarations/src/typeUtils.d.ts +51 -0
  59. package/dist/declarations/src/types.d.ts +835 -318
  60. package/dist/declarations/src/types.v6.d.ts +547 -104
  61. package/dist/declarations/src/utils.d.ts +38 -8
  62. package/dist/declarations/src/validation/index.d.ts +49 -0
  63. package/dist/declarations/src/validation.types.d.ts +29 -0
  64. package/dist/declarations/src/waitFor.d.ts +1 -0
  65. package/dist/effectDescriptor-2fa27c54.cjs.js +351 -0
  66. package/dist/effectDescriptor-321a8ce9.development.esm.js +343 -0
  67. package/dist/effectDescriptor-d8b0f749.esm.js +343 -0
  68. package/dist/effectDescriptor-f73da4ec.development.cjs.js +351 -0
  69. package/dist/machineSchemas-45c21bc2.esm.js +1292 -0
  70. package/dist/machineSchemas-6d96bef4.development.cjs.js +1379 -0
  71. package/dist/machineSchemas-88d01821.cjs.js +1300 -0
  72. package/dist/machineSchemas-b5736804.development.esm.js +1371 -0
  73. package/dist/schema.types-0ecd17b8.esm.js +71 -0
  74. package/dist/schema.types-15a68ddc.cjs.js +74 -0
  75. package/dist/schema.types-1c16f035.development.cjs.js +74 -0
  76. package/dist/schema.types-1cd4652e.development.esm.js +71 -0
  77. package/dist/validation-05f1d517.esm.js +8 -0
  78. package/dist/validation-4561b43c.cjs.js +10 -0
  79. package/dist/validation-e69470ad.development.esm.js +8 -0
  80. package/dist/validation-f2714a35.development.cjs.js +10 -0
  81. package/dist/xstate-actors.cjs.js +1068 -12
  82. package/dist/xstate-actors.cjs.mjs +2 -4
  83. package/dist/xstate-actors.development.cjs.js +1068 -12
  84. package/dist/xstate-actors.development.cjs.mjs +2 -4
  85. package/dist/xstate-actors.development.esm.js +1064 -1
  86. package/dist/xstate-actors.esm.js +1064 -1
  87. package/dist/xstate-actors.umd.min.js +1 -1
  88. package/dist/xstate-actors.umd.min.js.map +1 -1
  89. package/dist/xstate-durable.cjs.d.mts +2 -0
  90. package/dist/xstate-durable.cjs.d.ts +2 -0
  91. package/dist/xstate-durable.cjs.js +513 -0
  92. package/dist/xstate-durable.cjs.mjs +5 -0
  93. package/dist/xstate-durable.development.cjs.js +513 -0
  94. package/dist/xstate-durable.development.cjs.mjs +5 -0
  95. package/dist/xstate-durable.development.esm.js +507 -0
  96. package/dist/xstate-durable.esm.js +507 -0
  97. package/dist/xstate-durable.umd.min.js +2 -0
  98. package/dist/xstate-durable.umd.min.js.map +1 -0
  99. package/dist/xstate-fsm.cjs.d.mts +2 -0
  100. package/dist/xstate-fsm.cjs.d.ts +2 -0
  101. package/dist/xstate-fsm.cjs.js +111 -0
  102. package/dist/xstate-fsm.cjs.mjs +5 -0
  103. package/dist/xstate-fsm.development.cjs.js +111 -0
  104. package/dist/xstate-fsm.development.cjs.mjs +5 -0
  105. package/dist/xstate-fsm.development.esm.js +105 -0
  106. package/dist/xstate-fsm.esm.js +105 -0
  107. package/dist/xstate-fsm.umd.min.js +2 -0
  108. package/dist/xstate-fsm.umd.min.js.map +1 -0
  109. package/dist/xstate-graph.cjs.js +173 -457
  110. package/dist/xstate-graph.cjs.mjs +2 -5
  111. package/dist/xstate-graph.development.cjs.js +173 -457
  112. package/dist/xstate-graph.development.cjs.mjs +2 -5
  113. package/dist/xstate-graph.development.esm.js +171 -451
  114. package/dist/xstate-graph.esm.js +171 -451
  115. package/dist/xstate-graph.umd.min.js +1 -1
  116. package/dist/xstate-graph.umd.min.js.map +1 -1
  117. package/dist/xstate-persist.cjs.d.mts +2 -0
  118. package/dist/xstate-persist.cjs.d.ts +2 -0
  119. package/dist/xstate-persist.cjs.js +314 -0
  120. package/dist/xstate-persist.cjs.mjs +6 -0
  121. package/dist/xstate-persist.development.cjs.js +325 -0
  122. package/dist/xstate-persist.development.cjs.mjs +6 -0
  123. package/dist/xstate-persist.development.esm.js +319 -0
  124. package/dist/xstate-persist.esm.js +308 -0
  125. package/dist/xstate-persist.umd.min.js +2 -0
  126. package/dist/xstate-persist.umd.min.js.map +1 -0
  127. package/dist/xstate-validation.cjs.d.mts +2 -0
  128. package/dist/xstate-validation.cjs.d.ts +2 -0
  129. package/dist/xstate-validation.cjs.js +330 -0
  130. package/dist/xstate-validation.cjs.mjs +5 -0
  131. package/dist/xstate-validation.development.cjs.js +330 -0
  132. package/dist/xstate-validation.development.cjs.mjs +5 -0
  133. package/dist/xstate-validation.development.esm.js +324 -0
  134. package/dist/xstate-validation.esm.js +324 -0
  135. package/dist/xstate-validation.umd.min.js +2 -0
  136. package/dist/xstate-validation.umd.min.js.map +1 -0
  137. package/dist/xstate.cjs.js +2486 -1430
  138. package/dist/xstate.cjs.mjs +23 -13
  139. package/dist/xstate.development.cjs.js +2486 -1430
  140. package/dist/xstate.development.cjs.mjs +23 -13
  141. package/dist/xstate.development.esm.js +2445 -1398
  142. package/dist/xstate.esm.js +2445 -1398
  143. package/dist/xstate.umd.min.js +1 -1
  144. package/dist/xstate.umd.min.js.map +1 -1
  145. package/docs/actions.md +75 -0
  146. package/docs/actor-logic.md +250 -0
  147. package/docs/actors.md +64 -0
  148. package/docs/agents.md +132 -0
  149. package/docs/api-stability.json +4287 -0
  150. package/docs/async-logic.md +75 -0
  151. package/docs/async-requests.md +157 -0
  152. package/docs/backend-workflows.md +124 -0
  153. package/docs/cancellation.md +42 -0
  154. package/docs/cheatsheet.md +563 -0
  155. package/docs/choice-states.md +109 -0
  156. package/docs/choose-xstate.md +47 -0
  157. package/docs/configuration.md +161 -0
  158. package/docs/context.md +67 -0
  159. package/docs/create-actor.md +159 -0
  160. package/docs/data-and-effects.md +48 -0
  161. package/docs/delays.md +81 -0
  162. package/docs/durable-execution.md +520 -0
  163. package/docs/emitted-events.md +146 -0
  164. package/docs/errors.md +812 -0
  165. package/docs/examples.md +75 -0
  166. package/docs/faq.md +60 -0
  167. package/docs/final-states.md +149 -0
  168. package/docs/forms-and-wizards.md +166 -0
  169. package/docs/frameworks.md +69 -0
  170. package/docs/fsm.md +164 -0
  171. package/docs/glossary.md +68 -0
  172. package/docs/guards.md +137 -0
  173. package/docs/history-states.md +161 -0
  174. package/docs/how-xstate-runs-machines.md +86 -0
  175. package/docs/index.md +74 -0
  176. package/docs/input-output.md +69 -0
  177. package/docs/inspect-actor-systems.md +118 -0
  178. package/docs/inspection.md +75 -0
  179. package/docs/internal-events.md +156 -0
  180. package/docs/invoke.md +371 -0
  181. package/docs/lifecycle-and-errors.md +48 -0
  182. package/docs/listen-and-subscribe.md +126 -0
  183. package/docs/model-based-testing.md +321 -0
  184. package/docs/modeling.md +40 -0
  185. package/docs/parallel-states.md +182 -0
  186. package/docs/persist-and-restore-actors.md +120 -0
  187. package/docs/persistence.md +312 -0
  188. package/docs/quick-start.md +55 -0
  189. package/docs/retries-and-timeouts.md +122 -0
  190. package/docs/route-states.md +104 -0
  191. package/docs/scxml.md +92 -0
  192. package/docs/selectors.md +99 -0
  193. package/docs/serialization.md +127 -0
  194. package/docs/setup-and-provide.md +273 -0
  195. package/docs/snapshots.md +134 -0
  196. package/docs/spawn.md +212 -0
  197. package/docs/state-input.md +162 -0
  198. package/docs/statecharts.md +54 -0
  199. package/docs/states-events-transitions.md +82 -0
  200. package/docs/states.md +168 -0
  201. package/docs/system-transitions.md +172 -0
  202. package/docs/systems.md +166 -0
  203. package/docs/testing.md +152 -0
  204. package/docs/timeouts.md +125 -0
  205. package/docs/transition-functions.md +89 -0
  206. package/docs/transitions.md +187 -0
  207. package/docs/troubleshooting.md +56 -0
  208. package/docs/tutorial.md +481 -0
  209. package/docs/typescript.md +213 -0
  210. package/docs/typestates.md +112 -0
  211. package/docs/utilities.md +39 -0
  212. package/docs/why-state-machines.md +59 -0
  213. package/docs/xstate-v5-to-v6.md +1923 -0
  214. package/docs/your-first-machine.md +79 -0
  215. package/durable/package.json +8 -0
  216. package/fsm/package.json +8 -0
  217. package/package.json +72 -10
  218. package/persist/package.json +8 -0
  219. package/validation/package.json +8 -0
  220. package/actions/package.json +0 -8
  221. package/dev/package.json +0 -8
  222. package/dist/StateMachine-0aa98f54.development.esm.js +0 -746
  223. package/dist/StateMachine-aef700df.cjs.js +0 -732
  224. package/dist/StateMachine-d4931336.esm.js +0 -729
  225. package/dist/StateMachine-da872dde.development.cjs.js +0 -749
  226. package/dist/declarations/src/createMachineFromConfig.d.ts +0 -177
  227. package/dist/declarations/src/getNextSnapshot.d.ts +0 -37
  228. package/dist/declarations/src/graph/TestModel.d.ts +0 -70
  229. package/dist/declarations/src/graph/pathGenerators.d.ts +0 -4
  230. package/dist/index-219cb621.development.cjs.js +0 -4476
  231. package/dist/index-2f2fbd9b.development.esm.js +0 -4421
  232. package/dist/index-559ceab3.cjs.js +0 -4437
  233. package/dist/index-8828376f.esm.js +0 -4382
  234. package/guards/package.json +0 -8
  235. package/invoke/package.json +0 -4
package/bin/agent.js ADDED
@@ -0,0 +1,347 @@
1
+ // Data-only agent operations. No application module loading, code evaluation or effect
2
+ // execution is needed to inspect and explore a JSON machine definition.
3
+ const { readFileSync } = require('node:fs');
4
+ const { join } = require('node:path');
5
+ const { createHash } = require('node:crypto');
6
+ const core = require('../dist/xstate.cjs.js');
7
+ const graph = require('../dist/xstate-graph.cjs.js');
8
+ const { version } = require('../package.json');
9
+
10
+ function fail(code, message, details) {
11
+ const error = new Error(message);
12
+ error.code = code;
13
+ error.details = details;
14
+ throw error;
15
+ }
16
+
17
+ function readJSON(file) {
18
+ if (!file) fail('MISSING_ARGUMENT', 'Expected a JSON file path.');
19
+ try {
20
+ return JSON.parse(readFileSync(file, 'utf8'));
21
+ } catch (error) {
22
+ fail('INVALID_JSON', `Cannot read JSON from ${file}: ${error.message}`);
23
+ }
24
+ }
25
+
26
+ function expressions(value, path = '') {
27
+ if (!value || typeof value !== 'object') return [];
28
+ if (Object.hasOwn(value, '@code')) return [path];
29
+ return Object.entries(value).flatMap(([key, entry]) =>
30
+ expressions(
31
+ entry,
32
+ `${path}/${key.replaceAll('~', '~0').replaceAll('/', '~1')}`
33
+ )
34
+ );
35
+ }
36
+
37
+ function loadMachine(file) {
38
+ const definition = readJSON(file);
39
+ if (
40
+ !definition ||
41
+ typeof definition !== 'object' ||
42
+ Array.isArray(definition)
43
+ ) {
44
+ fail('INVALID_MACHINE', 'Expected a machine definition object.');
45
+ }
46
+ const paths = expressions(definition);
47
+ if (paths.length) {
48
+ fail(
49
+ 'EVALUATOR_REQUIRED',
50
+ 'The data-only CLI does not evaluate code expressions. Use the library with explicit runtime sources.',
51
+ { paths }
52
+ );
53
+ }
54
+ try {
55
+ return {
56
+ definition,
57
+ machine: core.machineFromJSON(definition),
58
+ hash: createHash('sha256')
59
+ .update(JSON.stringify(definition))
60
+ .digest('hex')
61
+ };
62
+ } catch (error) {
63
+ fail('INVALID_MACHINE', error.message);
64
+ }
65
+ }
66
+
67
+ function view(snapshot) {
68
+ return {
69
+ value: snapshot.value,
70
+ context: snapshot.context,
71
+ stateInputs: snapshot.getInputs(),
72
+ status: snapshot.status,
73
+ output: snapshot.output,
74
+ error:
75
+ snapshot.error instanceof Error
76
+ ? { name: snapshot.error.name, message: snapshot.error.message }
77
+ : snapshot.error
78
+ };
79
+ }
80
+
81
+ function effectView(effect) {
82
+ return {
83
+ type: effect.type,
84
+ kind: effect.kind,
85
+ params: effect.params,
86
+ event: effect.event
87
+ };
88
+ }
89
+
90
+ function eventList(value) {
91
+ const events = Array.isArray(value) ? value : value?.events;
92
+ if (
93
+ !Array.isArray(events) ||
94
+ events.some((event) => !event || typeof event.type !== 'string')
95
+ ) {
96
+ fail(
97
+ 'INVALID_EVENTS',
98
+ 'Expected an array of event objects with string type fields.'
99
+ );
100
+ }
101
+ return events;
102
+ }
103
+
104
+ function replay(machine, events, input) {
105
+ let [snapshot, effects] = core.initialTransition(machine, input);
106
+ const trace = [
107
+ { event: null, snapshot: view(snapshot), effects: effects.map(effectView) }
108
+ ];
109
+ const snapshots = [snapshot];
110
+ for (const event of events) {
111
+ [snapshot, effects] = core.transition(machine, snapshot, event);
112
+ snapshots.push(snapshot);
113
+ trace.push({
114
+ event,
115
+ snapshot: view(snapshot),
116
+ effects: effects.map(effectView)
117
+ });
118
+ }
119
+ return { trace, snapshots };
120
+ }
121
+
122
+ function assertions(machine, options) {
123
+ const states = new Set([
124
+ machine.root.id,
125
+ ...graph.getDescendantStateNodes(machine.root).map((node) => node.id)
126
+ ]);
127
+ for (const kind of ['never', 'reachable']) {
128
+ if (options[kind] === undefined) continue;
129
+ if (
130
+ !Array.isArray(options[kind]) ||
131
+ options[kind].some(
132
+ (id) =>
133
+ typeof id !== 'string' ||
134
+ !id.startsWith('#') ||
135
+ !states.has(id.slice(1))
136
+ )
137
+ ) {
138
+ fail(
139
+ 'INVALID_ASSERTION',
140
+ `${kind} must list existing state IDs prefixed with #.`
141
+ );
142
+ }
143
+ }
144
+ }
145
+
146
+ function violation(snapshots, never = []) {
147
+ for (const snapshot of snapshots) {
148
+ for (const state of never) {
149
+ if (snapshot.matches(state)) return { state, snapshot: view(snapshot) };
150
+ }
151
+ }
152
+ }
153
+
154
+ function difference(before, after, path = '') {
155
+ if (JSON.stringify(before) === JSON.stringify(after)) return [];
156
+ if (
157
+ before &&
158
+ after &&
159
+ typeof before === 'object' &&
160
+ typeof after === 'object' &&
161
+ !Array.isArray(before) &&
162
+ !Array.isArray(after)
163
+ ) {
164
+ return [...new Set([...Object.keys(before), ...Object.keys(after)])]
165
+ .sort()
166
+ .flatMap((key) => {
167
+ const pointer = `${path}/${key.replaceAll('~', '~0').replaceAll('/', '~1')}`;
168
+ if (!Object.hasOwn(before, key))
169
+ return [{ op: 'add', path: pointer, after: after[key] }];
170
+ if (!Object.hasOwn(after, key))
171
+ return [{ op: 'remove', path: pointer, before: before[key] }];
172
+ return difference(before[key], after[key], pointer);
173
+ });
174
+ }
175
+ return [{ op: 'replace', path, before, after }];
176
+ }
177
+
178
+ function run(command, rawArgs) {
179
+ const args = rawArgs.filter((arg) => arg !== '--json');
180
+ if (command === 'docs') {
181
+ return {
182
+ index: join(__dirname, '../docs/index.md'),
183
+ agentGuide: join(__dirname, '../docs/agents.md'),
184
+ stability: readJSON(join(__dirname, '../docs/api-stability.json'))
185
+ };
186
+ }
187
+ if (command === 'diff') {
188
+ const changes = difference(readJSON(args[0]), readJSON(args[1]));
189
+ return {
190
+ changed: changes.length > 0,
191
+ changes,
192
+ compatibility: 'notChecked'
193
+ };
194
+ }
195
+ const { machine, definition, hash } = loadMachine(args[0]);
196
+ if (command === 'validate')
197
+ return {
198
+ valid: true,
199
+ scope: 'definition',
200
+ runtimePayloadValidation: false
201
+ };
202
+ if (command === 'inspect') {
203
+ return {
204
+ definition,
205
+ graph: graph.toDirectedGraph(machine),
206
+ serializationDiagnostics:
207
+ core.getMachineSerializationDiagnostics(machine),
208
+ runtimePayloadValidation: false
209
+ };
210
+ }
211
+ if (command === 'simulate') {
212
+ const request = readJSON(args[1]);
213
+ return {
214
+ effectsExecuted: false,
215
+ ...omitSnapshots(replay(machine, eventList(request), request.input))
216
+ };
217
+ }
218
+ if (command === 'replay') {
219
+ const fixture = readJSON(args[1]);
220
+ if (
221
+ fixture.schemaVersion !== 1 ||
222
+ fixture.machineHash !== hash ||
223
+ fixture.xstateVersion !== version
224
+ ) {
225
+ fail(
226
+ 'FIXTURE_MISMATCH',
227
+ 'The fixture must match this definition, XState version and fixture format.'
228
+ );
229
+ }
230
+ assertions(machine, fixture);
231
+ const result = replay(machine, eventList(fixture), fixture.input);
232
+ const failure = violation(result.snapshots, fixture.never);
233
+ if (failure)
234
+ fail('PROPERTY_VIOLATION', 'A forbidden stable state was reached.', {
235
+ ...failure,
236
+ trace: result.trace,
237
+ fixture
238
+ });
239
+ return { effectsExecuted: false, trace: result.trace };
240
+ }
241
+ if (command === 'test') {
242
+ const options = readJSON(args[1]);
243
+ assertions(machine, options);
244
+ if (!(options.never?.length || options.reachable?.length)) {
245
+ fail(
246
+ 'MISSING_ASSERTION',
247
+ 'Supply at least one never or reachable state assertion.'
248
+ );
249
+ }
250
+ if (
251
+ options.limit !== undefined &&
252
+ (!Number.isSafeInteger(options.limit) || options.limit <= 0)
253
+ ) {
254
+ fail('INVALID_LIMIT', 'limit must be a positive safe integer.');
255
+ }
256
+ const paths = graph.getShortestPaths(machine, {
257
+ events: options.events,
258
+ input: options.input,
259
+ limit: options.limit ?? 10000
260
+ });
261
+ const visited = paths.map((path) => path.state);
262
+ const errored = visited.find((snapshot) => snapshot.status === 'error');
263
+ if (errored)
264
+ fail(
265
+ 'MODEL_EXECUTION_FAILED',
266
+ 'Model exploration entered an error snapshot.',
267
+ { snapshot: view(errored) }
268
+ );
269
+ for (const path of paths) {
270
+ const failure = violation(
271
+ path.steps.map((step) => step.state),
272
+ options.never
273
+ );
274
+ if (failure) {
275
+ const fixture = {
276
+ schemaVersion: 1,
277
+ xstateVersion: version,
278
+ machineHash: hash,
279
+ events: path.steps.slice(1).map((step) => step.event),
280
+ input: options.input,
281
+ never: options.never
282
+ };
283
+ fail('PROPERTY_VIOLATION', 'A forbidden stable state was reached.', {
284
+ ...failure,
285
+ fixture
286
+ });
287
+ }
288
+ }
289
+ const missing = (options.reachable ?? []).filter(
290
+ (state) => !visited.some((snapshot) => snapshot.matches(state))
291
+ );
292
+ if (missing.length)
293
+ fail(
294
+ 'REACHABILITY_NOT_WITNESSED',
295
+ 'No supplied event representative reached these states.',
296
+ { states: missing }
297
+ );
298
+ return {
299
+ passed: true,
300
+ scope: 'stableSnapshots',
301
+ effectsExecuted: false,
302
+ proof: false,
303
+ representativeEvents: options.events ?? null,
304
+ eventMode: Array.isArray(options.events)
305
+ ? 'replaceDefaults'
306
+ : 'augmentDefaults',
307
+ limit: options.limit ?? 10000,
308
+ paths: paths.length,
309
+ states: visited.map(view)
310
+ };
311
+ }
312
+ fail('UNKNOWN_COMMAND', `Unknown agent command: ${command}`);
313
+ }
314
+
315
+ function omitSnapshots({ trace }) {
316
+ return { trace };
317
+ }
318
+
319
+ module.exports = (command, args) => {
320
+ try {
321
+ const result = run(command, args);
322
+ console.log(
323
+ JSON.stringify({
324
+ schemaVersion: 1,
325
+ xstateVersion: version,
326
+ command,
327
+ ok: true,
328
+ result
329
+ })
330
+ );
331
+ } catch (error) {
332
+ console.log(
333
+ JSON.stringify({
334
+ schemaVersion: 1,
335
+ xstateVersion: version,
336
+ command,
337
+ ok: false,
338
+ error: {
339
+ code: error.code ?? 'OPERATION_FAILED',
340
+ message: error.message,
341
+ details: error.details
342
+ }
343
+ })
344
+ );
345
+ process.exitCode = 1;
346
+ }
347
+ };
package/bin/xstate.js ADDED
@@ -0,0 +1,52 @@
1
+ #!/usr/bin/env node
2
+ // Lightweight `xstate` CLI. Heavy commands are delegated to dedicated
3
+ // packages fetched on demand so the core package stays dependency-free.
4
+ const { spawnSync } = require('child_process');
5
+
6
+ const [command, ...rest] = process.argv.slice(2);
7
+
8
+ switch (command) {
9
+ case 'docs':
10
+ case 'inspect':
11
+ case 'validate':
12
+ case 'simulate':
13
+ case 'test':
14
+ case 'replay':
15
+ case 'diff':
16
+ require('./agent.js')(command, rest);
17
+ break;
18
+ case 'migrate': {
19
+ // Delegates to @xstate/codemod (ts-morph based v5 → v6 codemods).
20
+ const result = spawnSync(
21
+ process.platform === 'win32' ? 'npx.cmd' : 'npx',
22
+ ['-y', '@xstate/codemod', 'migrate', ...rest],
23
+ { stdio: 'inherit' }
24
+ );
25
+ process.exit(result.status ?? 1);
26
+ break;
27
+ }
28
+ case '--help':
29
+ case 'help':
30
+ case undefined:
31
+ console.log(
32
+ [
33
+ 'Usage: xstate <command>',
34
+ '',
35
+ 'Commands:',
36
+ ' docs Installed docs and export stability (JSON)',
37
+ ' inspect <machine.json> Definition and graph completeness (JSON)',
38
+ ' validate <machine.json> Validate a data-only definition (JSON)',
39
+ ' simulate <machine> <events> Calculate transitions without effects (JSON)',
40
+ ' test <machine> <options> Check sampled stable-state properties (JSON)',
41
+ ' replay <machine> <fixture> Replay a matching counterexample (JSON)',
42
+ ' diff <before> <after> Structural definition changes (JSON)',
43
+ ' migrate [globs...] [--dry] Migrate source files to the current XState version',
44
+ ' (delegates to @xstate/codemod)'
45
+ ].join('\n')
46
+ );
47
+ process.exit(command ? 0 : 1);
48
+ break;
49
+ default:
50
+ console.error(`Unknown command: ${command}`);
51
+ process.exit(1);
52
+ }