@statelyai/sdk 0.10.2 → 0.12.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +37 -5
- package/dist/auth-DO1-eQcU.d.mts +15 -0
- package/dist/auth.d.mts +2 -0
- package/dist/auth.mjs +11 -0
- package/dist/embed.d.mts +3 -2
- package/dist/embed.mjs +9 -1
- package/dist/{graph-GeuH-mFK.d.mts → graph-CszT5J6W.d.mts} +3 -1
- package/dist/graph.d.mts +1 -1
- package/dist/{graphToXStateTS-DOaLOySy.mjs → graphToXStateTS-D12GTMBp.mjs} +26 -1
- package/dist/index.d.mts +6 -4
- package/dist/index.mjs +5 -3
- package/dist/{inspect-BLlM3qKf.d.mts → inspect-BibyPhFj.d.mts} +10 -11
- package/dist/inspect.d.mts +3 -3
- package/dist/inspect.mjs +52 -35
- package/dist/oauth.d.mts +60 -0
- package/dist/oauth.mjs +98 -0
- package/dist/protocol.d.mts +30 -2
- package/dist/studio.d.mts +8 -1
- package/dist/studio.mjs +21 -7
- package/dist/sync.d.mts +1 -1
- package/dist/sync.mjs +549 -47
- package/dist/{transport-CVZGF0w9.mjs → transport-D0nlFaLn.mjs} +2 -0
- package/package.json +9 -1
package/dist/sync.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { createStatelyClient } from "./studio.mjs";
|
|
2
|
-
import { S as upsertStatelyPragma, _ as string, b as findStatelyPragmaAttachments, d as boolean, f as discriminatedUnion, g as record, h as object, l as _enum, m as number, p as literal, t as graphToXStateTS, u as array, v as union, x as getStatelyPragma, y as unknown } from "./graphToXStateTS-
|
|
2
|
+
import { S as upsertStatelyPragma, _ as string, b as findStatelyPragmaAttachments, d as boolean, f as discriminatedUnion, g as record, h as object, l as _enum, m as number, p as literal, t as graphToXStateTS, u as array, v as union, x as getStatelyPragma, y as unknown } from "./graphToXStateTS-D12GTMBp.mjs";
|
|
3
3
|
import { fromStudioMachine, toStudioMachine } from "./graph.mjs";
|
|
4
4
|
import * as ts$1 from "typescript";
|
|
5
5
|
import ts from "typescript";
|
|
@@ -111,9 +111,346 @@ function getLineStarts(text) {
|
|
|
111
111
|
|
|
112
112
|
//#endregion
|
|
113
113
|
//#region ../graph-tools/dist/index.mjs
|
|
114
|
+
/**
|
|
115
|
+
* Converts a graph to an adjacency list representation.
|
|
116
|
+
*
|
|
117
|
+
* @example
|
|
118
|
+
* ```ts
|
|
119
|
+
* import { createGraph, toAdjacencyList } from '@statelyai/graph';
|
|
120
|
+
*
|
|
121
|
+
* const graph = createGraph({
|
|
122
|
+
* nodes: { a: {}, b: {}, c: {} },
|
|
123
|
+
* edges: [{ source: 'a', target: 'b' }, { source: 'a', target: 'c' }],
|
|
124
|
+
* });
|
|
125
|
+
*
|
|
126
|
+
* toAdjacencyList(graph);
|
|
127
|
+
* // { a: ['b', 'c'], b: [], c: [] }
|
|
128
|
+
* ```
|
|
129
|
+
*/
|
|
130
|
+
function toAdjacencyList(graph) {
|
|
131
|
+
const adj = {};
|
|
132
|
+
for (const node of graph.nodes) adj[node.id] = [];
|
|
133
|
+
for (const edge of graph.edges) {
|
|
134
|
+
adj[edge.sourceId]?.push(edge.targetId);
|
|
135
|
+
if (graph.mode !== "directed") adj[edge.targetId]?.push(edge.sourceId);
|
|
136
|
+
}
|
|
137
|
+
return adj;
|
|
138
|
+
}
|
|
139
|
+
/**
|
|
140
|
+
* Parses an adjacency list into a graph.
|
|
141
|
+
*
|
|
142
|
+
* @example
|
|
143
|
+
* ```ts
|
|
144
|
+
* import { fromAdjacencyList } from '@statelyai/graph';
|
|
145
|
+
*
|
|
146
|
+
* const graph = fromAdjacencyList({
|
|
147
|
+
* a: ['b', 'c'],
|
|
148
|
+
* b: ['c'],
|
|
149
|
+
* c: [],
|
|
150
|
+
* });
|
|
151
|
+
*
|
|
152
|
+
* graph.nodes; // [{id: 'a', ...}, {id: 'b', ...}, {id: 'c', ...}]
|
|
153
|
+
* graph.edges; // [{sourceId: 'a', targetId: 'b', ...}, ...]
|
|
154
|
+
* ```
|
|
155
|
+
*/
|
|
156
|
+
function fromAdjacencyList(adj, options) {
|
|
157
|
+
const directed = options?.directed ?? true;
|
|
158
|
+
const seen = /* @__PURE__ */ new Set();
|
|
159
|
+
const nodes = Object.keys(adj).map((id) => ({
|
|
160
|
+
type: "node",
|
|
161
|
+
id,
|
|
162
|
+
parentId: null,
|
|
163
|
+
initialNodeId: null,
|
|
164
|
+
label: "",
|
|
165
|
+
data: void 0
|
|
166
|
+
}));
|
|
167
|
+
const edges = [];
|
|
168
|
+
let edgeIdx = 0;
|
|
169
|
+
for (const [sourceId, targets] of Object.entries(adj)) for (const targetId of targets) {
|
|
170
|
+
const key = directed ? `${sourceId}->${targetId}` : [sourceId, targetId].sort().join("<->");
|
|
171
|
+
if (!seen.has(key)) {
|
|
172
|
+
seen.add(key);
|
|
173
|
+
edges.push({
|
|
174
|
+
type: "edge",
|
|
175
|
+
id: `e${edgeIdx++}`,
|
|
176
|
+
sourceId,
|
|
177
|
+
targetId,
|
|
178
|
+
label: "",
|
|
179
|
+
data: void 0
|
|
180
|
+
});
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
return {
|
|
184
|
+
id: options?.id ?? "",
|
|
185
|
+
mode: directed ? "directed" : "undirected",
|
|
186
|
+
initialNodeId: null,
|
|
187
|
+
nodes,
|
|
188
|
+
edges,
|
|
189
|
+
data: void 0
|
|
190
|
+
};
|
|
191
|
+
}
|
|
192
|
+
/**
|
|
193
|
+
* Converts a graph to an edge list of `[source, target]` tuples.
|
|
194
|
+
*
|
|
195
|
+
* @example
|
|
196
|
+
* ```ts
|
|
197
|
+
* import { createGraph, toEdgeList } from '@statelyai/graph';
|
|
198
|
+
*
|
|
199
|
+
* const graph = createGraph({
|
|
200
|
+
* nodes: { a: {}, b: {}, c: {} },
|
|
201
|
+
* edges: [{ source: 'a', target: 'b' }, { source: 'b', target: 'c' }],
|
|
202
|
+
* });
|
|
203
|
+
*
|
|
204
|
+
* toEdgeList(graph);
|
|
205
|
+
* // [['a', 'b'], ['b', 'c']]
|
|
206
|
+
* ```
|
|
207
|
+
*/
|
|
208
|
+
function toEdgeList(graph) {
|
|
209
|
+
return graph.edges.map((e) => [e.sourceId, e.targetId]);
|
|
210
|
+
}
|
|
211
|
+
/**
|
|
212
|
+
* Parses an edge list of `[source, target]` tuples into a graph.
|
|
213
|
+
*
|
|
214
|
+
* @example
|
|
215
|
+
* ```ts
|
|
216
|
+
* import { fromEdgeList } from '@statelyai/graph';
|
|
217
|
+
*
|
|
218
|
+
* const graph = fromEdgeList([
|
|
219
|
+
* ['a', 'b'],
|
|
220
|
+
* ['b', 'c'],
|
|
221
|
+
* ]);
|
|
222
|
+
*
|
|
223
|
+
* graph.nodes; // [{id: 'a', ...}, {id: 'b', ...}, {id: 'c', ...}]
|
|
224
|
+
* graph.edges; // [{sourceId: 'a', targetId: 'b', ...}, ...]
|
|
225
|
+
* ```
|
|
226
|
+
*/
|
|
227
|
+
function fromEdgeList(edges, options) {
|
|
228
|
+
const directed = options?.directed ?? true;
|
|
229
|
+
const nodeIds = /* @__PURE__ */ new Set();
|
|
230
|
+
for (const [source, target] of edges) {
|
|
231
|
+
nodeIds.add(source);
|
|
232
|
+
nodeIds.add(target);
|
|
233
|
+
}
|
|
234
|
+
const nodes = [...nodeIds].map((id) => ({
|
|
235
|
+
type: "node",
|
|
236
|
+
id,
|
|
237
|
+
parentId: null,
|
|
238
|
+
initialNodeId: null,
|
|
239
|
+
label: "",
|
|
240
|
+
data: void 0
|
|
241
|
+
}));
|
|
242
|
+
const edgeObjects = edges.map(([sourceId, targetId], i) => ({
|
|
243
|
+
type: "edge",
|
|
244
|
+
id: `e${i}`,
|
|
245
|
+
sourceId,
|
|
246
|
+
targetId,
|
|
247
|
+
label: "",
|
|
248
|
+
data: void 0
|
|
249
|
+
}));
|
|
250
|
+
return {
|
|
251
|
+
id: options?.id ?? "",
|
|
252
|
+
mode: directed ? "directed" : "undirected",
|
|
253
|
+
initialNodeId: null,
|
|
254
|
+
nodes,
|
|
255
|
+
edges: edgeObjects,
|
|
256
|
+
data: void 0
|
|
257
|
+
};
|
|
258
|
+
}
|
|
259
|
+
/**
|
|
260
|
+
* Create a `GraphFormatConverter` from a pair of `to`/`from` functions.
|
|
261
|
+
*
|
|
262
|
+
* @example
|
|
263
|
+
* ```ts
|
|
264
|
+
* import { createFormatConverter } from '@statelyai/graph';
|
|
265
|
+
*
|
|
266
|
+
* const yamlConverter = createFormatConverter(
|
|
267
|
+
* (graph) => toYAML(graph),
|
|
268
|
+
* (yaml) => fromYAML(yaml),
|
|
269
|
+
* );
|
|
270
|
+
*
|
|
271
|
+
* const yaml = yamlConverter.to(graph);
|
|
272
|
+
* const graph = yamlConverter.from(yaml);
|
|
273
|
+
* ```
|
|
274
|
+
*/
|
|
275
|
+
function createFormatConverter$1(to, from) {
|
|
276
|
+
return {
|
|
277
|
+
to,
|
|
278
|
+
from
|
|
279
|
+
};
|
|
280
|
+
}
|
|
281
|
+
createFormatConverter$1(toAdjacencyList, fromAdjacencyList);
|
|
282
|
+
createFormatConverter$1(toEdgeList, fromEdgeList);
|
|
283
|
+
const LAYOUT_KEYS = {
|
|
284
|
+
node: [
|
|
285
|
+
"x",
|
|
286
|
+
"y",
|
|
287
|
+
"width",
|
|
288
|
+
"height",
|
|
289
|
+
"style",
|
|
290
|
+
"color",
|
|
291
|
+
"shape"
|
|
292
|
+
],
|
|
293
|
+
edge: [
|
|
294
|
+
"x",
|
|
295
|
+
"y",
|
|
296
|
+
"width",
|
|
297
|
+
"height",
|
|
298
|
+
"style",
|
|
299
|
+
"color"
|
|
300
|
+
]
|
|
301
|
+
};
|
|
302
|
+
new Set(LAYOUT_KEYS.node), new Set(LAYOUT_KEYS.edge);
|
|
303
|
+
function nodeToConfig$1(node) {
|
|
304
|
+
const config = { id: node.id };
|
|
305
|
+
if (node.parentId) config.parentId = node.parentId;
|
|
306
|
+
if (node.initialNodeId) config.initialNodeId = node.initialNodeId;
|
|
307
|
+
if (node.label !== "") config.label = node.label;
|
|
308
|
+
if (node.data !== void 0) config.data = node.data;
|
|
309
|
+
if (node.x !== void 0) config.x = node.x;
|
|
310
|
+
if (node.y !== void 0) config.y = node.y;
|
|
311
|
+
if (node.width !== void 0) config.width = node.width;
|
|
312
|
+
if (node.height !== void 0) config.height = node.height;
|
|
313
|
+
if (node.shape !== void 0) config.shape = node.shape;
|
|
314
|
+
if (node.color !== void 0) config.color = node.color;
|
|
315
|
+
if (node.style !== void 0) config.style = node.style;
|
|
316
|
+
return config;
|
|
317
|
+
}
|
|
318
|
+
function edgeToConfig$1(edge) {
|
|
319
|
+
const config = {
|
|
320
|
+
id: edge.id,
|
|
321
|
+
sourceId: edge.sourceId,
|
|
322
|
+
targetId: edge.targetId
|
|
323
|
+
};
|
|
324
|
+
if (edge.label !== "") config.label = edge.label;
|
|
325
|
+
if (edge.data !== void 0) config.data = edge.data;
|
|
326
|
+
if (edge.x !== void 0) config.x = edge.x;
|
|
327
|
+
if (edge.y !== void 0) config.y = edge.y;
|
|
328
|
+
if (edge.width !== void 0) config.width = edge.width;
|
|
329
|
+
if (edge.height !== void 0) config.height = edge.height;
|
|
330
|
+
if (edge.color !== void 0) config.color = edge.color;
|
|
331
|
+
if (edge.style !== void 0) config.style = edge.style;
|
|
332
|
+
return config;
|
|
333
|
+
}
|
|
334
|
+
/** Shallow-compare two values, returning true if they differ. */
|
|
335
|
+
function differs(a, b) {
|
|
336
|
+
if (a === b) return false;
|
|
337
|
+
if (a == null || b == null) return a !== b;
|
|
338
|
+
if (typeof a === "object" && typeof b === "object") return JSON.stringify(a) !== JSON.stringify(b);
|
|
339
|
+
return true;
|
|
340
|
+
}
|
|
341
|
+
const NODE_COMPARE_KEYS = [
|
|
342
|
+
"parentId",
|
|
343
|
+
"initialNodeId",
|
|
344
|
+
"label",
|
|
345
|
+
"data",
|
|
346
|
+
"x",
|
|
347
|
+
"y",
|
|
348
|
+
"width",
|
|
349
|
+
"height",
|
|
350
|
+
"shape",
|
|
351
|
+
"color",
|
|
352
|
+
"style"
|
|
353
|
+
];
|
|
354
|
+
const EDGE_COMPARE_KEYS = [
|
|
355
|
+
"sourceId",
|
|
356
|
+
"targetId",
|
|
357
|
+
"label",
|
|
358
|
+
"data",
|
|
359
|
+
"x",
|
|
360
|
+
"y",
|
|
361
|
+
"width",
|
|
362
|
+
"height",
|
|
363
|
+
"color",
|
|
364
|
+
"style"
|
|
365
|
+
];
|
|
366
|
+
/**
|
|
367
|
+
* Compute a structured diff from graph `a` to graph `b` by matching IDs.
|
|
368
|
+
*
|
|
369
|
+
* @example
|
|
370
|
+
* ```ts
|
|
371
|
+
* import { createGraph, getDiff } from '@statelyai/graph';
|
|
372
|
+
*
|
|
373
|
+
* const a = createGraph({ nodes: [{ id: 'n1' }], edges: [] });
|
|
374
|
+
* const b = createGraph({ nodes: [{ id: 'n1', label: 'hello' }, { id: 'n2' }], edges: [] });
|
|
375
|
+
*
|
|
376
|
+
* const diff = getDiff(a, b);
|
|
377
|
+
* // diff.nodes.added → [{ id: 'n2' }]
|
|
378
|
+
* // diff.nodes.updated → [{ id: 'n1', old: { label: '' }, new: { label: 'hello' } }]
|
|
379
|
+
* ```
|
|
380
|
+
*/
|
|
381
|
+
function getDiff$1(a, b) {
|
|
382
|
+
const aNodeMap = new Map(a.nodes.map((n) => [n.id, n]));
|
|
383
|
+
const bNodeMap = new Map(b.nodes.map((n) => [n.id, n]));
|
|
384
|
+
const aEdgeMap = new Map(a.edges.map((e) => [e.id, e]));
|
|
385
|
+
const bEdgeMap = new Map(b.edges.map((e) => [e.id, e]));
|
|
386
|
+
const diff = {
|
|
387
|
+
nodes: {
|
|
388
|
+
added: [],
|
|
389
|
+
removed: [],
|
|
390
|
+
updated: []
|
|
391
|
+
},
|
|
392
|
+
edges: {
|
|
393
|
+
added: [],
|
|
394
|
+
removed: [],
|
|
395
|
+
updated: []
|
|
396
|
+
}
|
|
397
|
+
};
|
|
398
|
+
for (const [id, nodeB] of bNodeMap) {
|
|
399
|
+
const nodeA = aNodeMap.get(id);
|
|
400
|
+
if (!nodeA) diff.nodes.added.push(nodeToConfig$1(nodeB));
|
|
401
|
+
else {
|
|
402
|
+
const oldPartial = {};
|
|
403
|
+
const newPartial = {};
|
|
404
|
+
for (const key of NODE_COMPARE_KEYS) if (differs(nodeA[key], nodeB[key])) {
|
|
405
|
+
oldPartial[key] = nodeA[key];
|
|
406
|
+
newPartial[key] = nodeB[key];
|
|
407
|
+
}
|
|
408
|
+
if (Object.keys(oldPartial).length > 0) diff.nodes.updated.push({
|
|
409
|
+
id,
|
|
410
|
+
old: oldPartial,
|
|
411
|
+
new: newPartial
|
|
412
|
+
});
|
|
413
|
+
}
|
|
414
|
+
}
|
|
415
|
+
for (const [id, nodeA] of aNodeMap) if (!bNodeMap.has(id)) diff.nodes.removed.push(nodeToConfig$1(nodeA));
|
|
416
|
+
for (const [id, edgeB] of bEdgeMap) {
|
|
417
|
+
const edgeA = aEdgeMap.get(id);
|
|
418
|
+
if (!edgeA) diff.edges.added.push(edgeToConfig$1(edgeB));
|
|
419
|
+
else {
|
|
420
|
+
const oldPartial = {};
|
|
421
|
+
const newPartial = {};
|
|
422
|
+
for (const key of EDGE_COMPARE_KEYS) if (differs(edgeA[key], edgeB[key])) {
|
|
423
|
+
oldPartial[key] = edgeA[key];
|
|
424
|
+
newPartial[key] = edgeB[key];
|
|
425
|
+
}
|
|
426
|
+
if (Object.keys(oldPartial).length > 0) diff.edges.updated.push({
|
|
427
|
+
id,
|
|
428
|
+
old: oldPartial,
|
|
429
|
+
new: newPartial
|
|
430
|
+
});
|
|
431
|
+
}
|
|
432
|
+
}
|
|
433
|
+
for (const [id, edgeA] of aEdgeMap) if (!bEdgeMap.has(id)) diff.edges.removed.push(edgeToConfig$1(edgeA));
|
|
434
|
+
return diff;
|
|
435
|
+
}
|
|
436
|
+
/**
|
|
437
|
+
* Check if a diff has zero changes.
|
|
438
|
+
*
|
|
439
|
+
* @example
|
|
440
|
+
* ```ts
|
|
441
|
+
* import { createGraph, getDiff, isEmptyDiff } from '@statelyai/graph';
|
|
442
|
+
*
|
|
443
|
+
* const g = createGraph({ nodes: [{ id: 'n1' }], edges: [] });
|
|
444
|
+
* const diff = getDiff(g, g);
|
|
445
|
+
* isEmptyDiff(diff); // true
|
|
446
|
+
* ```
|
|
447
|
+
*/
|
|
448
|
+
function isEmptyDiff$1(diff) {
|
|
449
|
+
return diff.nodes.added.length === 0 && diff.nodes.removed.length === 0 && diff.nodes.updated.length === 0 && diff.edges.added.length === 0 && diff.edges.removed.length === 0 && diff.edges.updated.length === 0;
|
|
450
|
+
}
|
|
114
451
|
function summarizeGraphDiff(diff) {
|
|
115
452
|
return {
|
|
116
|
-
hasChanges: !isEmptyDiff(diff),
|
|
453
|
+
hasChanges: !isEmptyDiff$1(diff),
|
|
117
454
|
nodeChanges: diff.nodes.added.length + diff.nodes.removed.length + diff.nodes.updated.length,
|
|
118
455
|
edgeChanges: diff.edges.added.length + diff.edges.removed.length + diff.edges.updated.length
|
|
119
456
|
};
|
|
@@ -180,7 +517,7 @@ function normalizeGraphForSemanticDiff(graph) {
|
|
|
180
517
|
function diffGraphsSemantically(baseGraph, compareGraph) {
|
|
181
518
|
const base = normalizeGraphForSemanticDiff(baseGraph);
|
|
182
519
|
const compare = normalizeGraphForSemanticDiff(compareGraph);
|
|
183
|
-
const diff = getDiff(base, compare);
|
|
520
|
+
const diff = getDiff$1(base, compare);
|
|
184
521
|
return {
|
|
185
522
|
base,
|
|
186
523
|
compare,
|
|
@@ -839,6 +1176,7 @@ function deepSimplify(config) {
|
|
|
839
1176
|
return config;
|
|
840
1177
|
}
|
|
841
1178
|
function buildMeta(meta, color) {
|
|
1179
|
+
if (isCodeExpression(meta)) return meta;
|
|
842
1180
|
const result = {};
|
|
843
1181
|
if (meta) {
|
|
844
1182
|
for (const [k, v] of Object.entries(meta)) if (v !== void 0 && v !== null) result[k] = v;
|
|
@@ -846,6 +1184,9 @@ function buildMeta(meta, color) {
|
|
|
846
1184
|
if (color) result["@statelyai.color"] = color;
|
|
847
1185
|
return Object.keys(result).length > 0 ? result : void 0;
|
|
848
1186
|
}
|
|
1187
|
+
function isCodeExpression(value) {
|
|
1188
|
+
return Boolean(value && typeof value === "object" && !Array.isArray(value) && value["@type"] === "code" && typeof value.expr === "string");
|
|
1189
|
+
}
|
|
849
1190
|
/** Format event param — supports { type: string } (new) and plain string (legacy) */
|
|
850
1191
|
function formatEventParam(event) {
|
|
851
1192
|
if (event && typeof event === "object" && "type" in event) return formatInlineObject(event);
|
|
@@ -864,6 +1205,10 @@ function formatObjectKey(key) {
|
|
|
864
1205
|
const eventParamSchema = union([string(), object({ type: string() }).catchall(unknown())]);
|
|
865
1206
|
const delayParamSchema = union([number(), string()]);
|
|
866
1207
|
const builtInActionParamSchemas = {
|
|
1208
|
+
"xstate.enqueue": object({
|
|
1209
|
+
code: string().optional(),
|
|
1210
|
+
lang: string().optional()
|
|
1211
|
+
}),
|
|
867
1212
|
"xstate.raise": object({
|
|
868
1213
|
event: eventParamSchema.optional(),
|
|
869
1214
|
id: string().optional(),
|
|
@@ -887,6 +1232,16 @@ const builtInActionParamSchemas = {
|
|
|
887
1232
|
"xstate.assign": object({ assignment: record(string(), unknown()).optional() }).catchall(unknown())
|
|
888
1233
|
};
|
|
889
1234
|
const XSTATE_BUILT_IN_ACTIONS = {
|
|
1235
|
+
"xstate.enqueue": {
|
|
1236
|
+
package: "xstate",
|
|
1237
|
+
version: "^6",
|
|
1238
|
+
import: "enqueue",
|
|
1239
|
+
importKind: "named",
|
|
1240
|
+
paramsSchema: builtInActionParamSchemas["xstate.enqueue"],
|
|
1241
|
+
emit(params) {
|
|
1242
|
+
return typeof params?.code === "string" ? stripExportDefault(params.code) : "";
|
|
1243
|
+
}
|
|
1244
|
+
},
|
|
890
1245
|
"xstate.raise": {
|
|
891
1246
|
package: "xstate",
|
|
892
1247
|
version: "^5",
|
|
@@ -1003,7 +1358,7 @@ function actionCodeExpression(expr, source) {
|
|
|
1003
1358
|
}]
|
|
1004
1359
|
};
|
|
1005
1360
|
}
|
|
1006
|
-
function inlineCodeExpression(expr) {
|
|
1361
|
+
function inlineCodeExpression$1(expr) {
|
|
1007
1362
|
return {
|
|
1008
1363
|
"@type": "code",
|
|
1009
1364
|
lang: "ts",
|
|
@@ -1021,7 +1376,7 @@ function serializeGuard(guard, asTypeRef) {
|
|
|
1021
1376
|
type: guard.type,
|
|
1022
1377
|
params: guard.params
|
|
1023
1378
|
} : { type: guard.type };
|
|
1024
|
-
return guard.code ? inlineCodeExpression(guard.code) : guard;
|
|
1379
|
+
return guard.code ? inlineCodeExpression$1(guard.code) : guard;
|
|
1025
1380
|
}
|
|
1026
1381
|
/**
|
|
1027
1382
|
* Converts a built-in xstate ActionItem to a code expression directive,
|
|
@@ -1029,12 +1384,13 @@ function serializeGuard(guard, asTypeRef) {
|
|
|
1029
1384
|
*/
|
|
1030
1385
|
function serializeActionItem(action) {
|
|
1031
1386
|
const { type, params } = action;
|
|
1387
|
+
if (type === "xstate.enqueue" && typeof params?.code === "string") return inlineCodeExpression$1(params.code);
|
|
1032
1388
|
const exprCode = type === "xstate.expr" && typeof params?.code === "string" ? params.code : void 0;
|
|
1033
1389
|
if (isBuiltInActionType(type)) {
|
|
1034
1390
|
const builtInAction = XSTATE_BUILT_IN_ACTIONS[type];
|
|
1035
1391
|
return actionCodeExpression(emitBuiltInAction(type, params), builtInAction);
|
|
1036
1392
|
}
|
|
1037
|
-
if (exprCode) return inlineCodeExpression(exprCode);
|
|
1393
|
+
if (exprCode) return inlineCodeExpression$1(exprCode);
|
|
1038
1394
|
if (!params || Object.keys(params).length === 0) return { type };
|
|
1039
1395
|
return {
|
|
1040
1396
|
type,
|
|
@@ -1061,7 +1417,8 @@ function graphToMachineConfig(graph, options = {}) {
|
|
|
1061
1417
|
const nodeType = [
|
|
1062
1418
|
"final",
|
|
1063
1419
|
"history",
|
|
1064
|
-
"parallel"
|
|
1420
|
+
"parallel",
|
|
1421
|
+
"choice"
|
|
1065
1422
|
].includes(node.data.type) ? node.data.type : void 0;
|
|
1066
1423
|
const tags = node.data.tags;
|
|
1067
1424
|
Object.assign(nodeConfig, {
|
|
@@ -1076,6 +1433,7 @@ function graphToMachineConfig(graph, options = {}) {
|
|
|
1076
1433
|
...inv.input ? { input: inv.input } : void 0,
|
|
1077
1434
|
...inv.output ? { output: inv.output } : void 0
|
|
1078
1435
|
})) } : void 0,
|
|
1436
|
+
...node.data.output !== void 0 ? { output: node.data.output } : void 0,
|
|
1079
1437
|
...tags?.length ? { tags: tags.map(tagToString) } : void 0,
|
|
1080
1438
|
...showDescriptions && node.data.description ? { description: node.data.description } : void 0,
|
|
1081
1439
|
...showMeta && node.data.meta && Object.keys(node.data.meta).length > 0 ? { meta: node.data.meta } : void 0,
|
|
@@ -1087,6 +1445,7 @@ function graphToMachineConfig(graph, options = {}) {
|
|
|
1087
1445
|
const on = {};
|
|
1088
1446
|
const after = {};
|
|
1089
1447
|
const alwaysArr = [];
|
|
1448
|
+
const choiceArr = [];
|
|
1090
1449
|
const onDone = {};
|
|
1091
1450
|
const invokeMap = {};
|
|
1092
1451
|
for (const edge of edges) {
|
|
@@ -1098,6 +1457,7 @@ function graphToMachineConfig(graph, options = {}) {
|
|
|
1098
1457
|
target: edge.data.transitionType === "targetless" ? void 0 : `${resolvedTarget}`,
|
|
1099
1458
|
...edge.data.transitionType === "reenter" ? { reenter: true } : void 0,
|
|
1100
1459
|
guard: edge.data.guard ? serializeGuard(edge.data.guard, inlineGuardsAsTypeRef) : void 0,
|
|
1460
|
+
...edge.data.context !== void 0 ? { context: edge.data.context } : void 0,
|
|
1101
1461
|
actions: edge.data.actions?.length ? edge.data.actions.map(serializeActionItem) : void 0,
|
|
1102
1462
|
description: edge.data.description ?? void 0,
|
|
1103
1463
|
...transitionMeta ? { meta: transitionMeta } : void 0
|
|
@@ -1120,6 +1480,7 @@ function graphToMachineConfig(graph, options = {}) {
|
|
|
1120
1480
|
if (!onDone[type]) onDone[type] = [];
|
|
1121
1481
|
onDone[type].push(transitionObject);
|
|
1122
1482
|
} else pushOn(`xstate.${ref.kind === "actionDone" ? "done" : "error"}.actor.${resolveSpawnActorId$1(node, ref.blockId)}`);
|
|
1483
|
+
else if (type === "" && node.data.type === "choice") choiceArr.push(transitionObject);
|
|
1123
1484
|
else if (type === "") alwaysArr.push(transitionObject);
|
|
1124
1485
|
else if (type.startsWith("xstate.after.")) {
|
|
1125
1486
|
const delayKey = type.slice(13).split(".")[0];
|
|
@@ -1139,6 +1500,7 @@ function graphToMachineConfig(graph, options = {}) {
|
|
|
1139
1500
|
if (Object.keys(on).length > 0) nodeConfig.on = singleOrArrayRecord(on);
|
|
1140
1501
|
if (Object.keys(after).length > 0) nodeConfig.after = singleOrArrayRecord(after);
|
|
1141
1502
|
if (alwaysArr.length > 0) nodeConfig.always = singleOrArray(alwaysArr);
|
|
1503
|
+
if (choiceArr.length > 0) nodeConfig.choice = singleOrArray(choiceArr);
|
|
1142
1504
|
if (Object.keys(onDone).length > 0) nodeConfig.onDone = singleOrArray(Object.values(onDone).flat());
|
|
1143
1505
|
if (Object.keys(invokeMap).length > 0 && Array.isArray(nodeConfig.invoke)) nodeConfig.invoke = nodeConfig.invoke.map((inv, index) => {
|
|
1144
1506
|
const mapped = invokeMap[node.data.invokes?.[index]?.id ?? inv.id];
|
|
@@ -1517,6 +1879,7 @@ function guardObject(value) {
|
|
|
1517
1879
|
const guard = value;
|
|
1518
1880
|
return {
|
|
1519
1881
|
type: guard.type,
|
|
1882
|
+
code: guard.code,
|
|
1520
1883
|
params: guard.params
|
|
1521
1884
|
};
|
|
1522
1885
|
}
|
|
@@ -1547,9 +1910,10 @@ function machineConfigToGraph(config) {
|
|
|
1547
1910
|
parentId,
|
|
1548
1911
|
data: {
|
|
1549
1912
|
key,
|
|
1550
|
-
type: state.type === "parallel" || state.type === "final" || state.type === "history" ? state.type : null,
|
|
1913
|
+
type: state.type === "parallel" || state.type === "final" || state.type === "history" || state.type === "choice" ? state.type : null,
|
|
1551
1914
|
initialId,
|
|
1552
1915
|
history: state.history ?? false,
|
|
1916
|
+
...state.output !== void 0 ? { output: state.output } : {},
|
|
1553
1917
|
entry: actionItems(state.entry),
|
|
1554
1918
|
exit: actionItems(state.exit),
|
|
1555
1919
|
invokes: invokeItems(state.invoke),
|
|
@@ -1568,6 +1932,7 @@ function machineConfigToGraph(config) {
|
|
|
1568
1932
|
eventType,
|
|
1569
1933
|
transitionType: target ? transition.reenter ? "reenter" : "normal" : "targetless",
|
|
1570
1934
|
guard: guardObject(transition.guard),
|
|
1935
|
+
...transition.context !== void 0 ? { context: transition.context } : {},
|
|
1571
1936
|
actions: actionItems(transition.actions),
|
|
1572
1937
|
description: typeof transition.description === "string" ? transition.description : null,
|
|
1573
1938
|
meta: transition.meta && typeof transition.meta === "object" ? transition.meta : null
|
|
@@ -1584,6 +1949,7 @@ function machineConfigToGraph(config) {
|
|
|
1584
1949
|
eventType: `xstate.after.${delay}.${id}`,
|
|
1585
1950
|
transitionType: target ? "normal" : "targetless",
|
|
1586
1951
|
guard: guardObject(transition.guard),
|
|
1952
|
+
...transition.context !== void 0 ? { context: transition.context } : {},
|
|
1587
1953
|
actions: actionItems(transition.actions),
|
|
1588
1954
|
description: typeof transition.description === "string" ? transition.description : null,
|
|
1589
1955
|
meta: null
|
|
@@ -1600,12 +1966,30 @@ function machineConfigToGraph(config) {
|
|
|
1600
1966
|
eventType: "",
|
|
1601
1967
|
transitionType: target ? "normal" : "targetless",
|
|
1602
1968
|
guard: guardObject(transition.guard),
|
|
1969
|
+
...transition.context !== void 0 ? { context: transition.context } : {},
|
|
1603
1970
|
actions: actionItems(transition.actions),
|
|
1604
1971
|
description: typeof transition.description === "string" ? transition.description : null,
|
|
1605
1972
|
meta: null
|
|
1606
1973
|
}
|
|
1607
1974
|
});
|
|
1608
1975
|
}
|
|
1976
|
+
for (const [index, transition] of transitionObjects(state.choice).entries()) {
|
|
1977
|
+
const target = transitionTargets(transition.target)[0];
|
|
1978
|
+
graph.edges.push({
|
|
1979
|
+
id: `${id}-choice-${index}`,
|
|
1980
|
+
sourceId: id,
|
|
1981
|
+
targetId: targetToNodeId(id, target, rootKey),
|
|
1982
|
+
data: {
|
|
1983
|
+
eventType: "",
|
|
1984
|
+
transitionType: target ? "normal" : "targetless",
|
|
1985
|
+
guard: guardObject(transition.guard),
|
|
1986
|
+
...transition.context !== void 0 ? { context: transition.context } : {},
|
|
1987
|
+
actions: actionItems(transition.actions),
|
|
1988
|
+
description: typeof transition.description === "string" ? transition.description : null,
|
|
1989
|
+
meta: transition.meta && typeof transition.meta === "object" ? transition.meta : null
|
|
1990
|
+
}
|
|
1991
|
+
});
|
|
1992
|
+
}
|
|
1609
1993
|
for (const [childKey, child] of Object.entries(state.states ?? {})) visit(child, childKey, id);
|
|
1610
1994
|
}
|
|
1611
1995
|
visit(config, rootKey, null);
|
|
@@ -1633,6 +2017,19 @@ function propertyContext(parent, key) {
|
|
|
1633
2017
|
v6: parent.v6,
|
|
1634
2018
|
actionValue: true
|
|
1635
2019
|
};
|
|
2020
|
+
if (parent.transitionValue && key === "context") return {
|
|
2021
|
+
v6: parent.v6,
|
|
2022
|
+
assignmentMap: true,
|
|
2023
|
+
transitionContext: true
|
|
2024
|
+
};
|
|
2025
|
+
if (parent.assignmentMap) return {
|
|
2026
|
+
v6: parent.v6,
|
|
2027
|
+
assignmentValue: true
|
|
2028
|
+
};
|
|
2029
|
+
if (key === "meta") return {
|
|
2030
|
+
v6: parent.v6,
|
|
2031
|
+
metaValue: true
|
|
2032
|
+
};
|
|
1636
2033
|
if (parent.transitionValue && key === "to") return {
|
|
1637
2034
|
v6: parent.v6,
|
|
1638
2035
|
transitionValue: true
|
|
@@ -1641,21 +2038,28 @@ function propertyContext(parent, key) {
|
|
|
1641
2038
|
v6: parent.v6,
|
|
1642
2039
|
actionValue: true
|
|
1643
2040
|
};
|
|
2041
|
+
if (key === "input" || key === "output") return {
|
|
2042
|
+
v6: parent.v6,
|
|
2043
|
+
ioValue: true
|
|
2044
|
+
};
|
|
1644
2045
|
if (key === "on" || key === "after") return {
|
|
1645
2046
|
v6: parent.v6,
|
|
1646
2047
|
transitionMap: true
|
|
1647
2048
|
};
|
|
1648
|
-
if (key === "always" || key === "onDone" || key === "onError" || key === "onSnapshot" || key === "onTimeout") return {
|
|
2049
|
+
if (key === "always" || key === "choice" || key === "onDone" || key === "onError" || key === "onSnapshot" || key === "onTimeout") return {
|
|
1649
2050
|
v6: parent.v6,
|
|
1650
2051
|
transitionValue: true
|
|
1651
2052
|
};
|
|
1652
2053
|
return { v6: parent.v6 };
|
|
1653
2054
|
}
|
|
1654
|
-
function fallbackFunctionTransition(fn) {
|
|
1655
|
-
return {
|
|
1656
|
-
|
|
1657
|
-
|
|
1658
|
-
|
|
2055
|
+
function fallbackFunctionTransition(fn, actions = []) {
|
|
2056
|
+
return {
|
|
2057
|
+
...actions.length ? { actions } : void 0,
|
|
2058
|
+
meta: {
|
|
2059
|
+
[XSTATE_V6_FN_TRANSITION_META]: true,
|
|
2060
|
+
[XSTATE_V6_FN_SOURCE_META]: fn.getText()
|
|
2061
|
+
}
|
|
2062
|
+
};
|
|
1659
2063
|
}
|
|
1660
2064
|
function conditionText(cond) {
|
|
1661
2065
|
return cond.negated ? `!(${cond.text})` : cond.text;
|
|
@@ -1670,10 +2074,28 @@ function simplifyConditions(conds) {
|
|
|
1670
2074
|
return true;
|
|
1671
2075
|
});
|
|
1672
2076
|
}
|
|
1673
|
-
function
|
|
2077
|
+
function hashString(value) {
|
|
2078
|
+
let hash = 5381;
|
|
2079
|
+
for (let i = 0; i < value.length; i++) hash = hash * 33 ^ value.charCodeAt(i);
|
|
2080
|
+
return (hash >>> 0).toString(36);
|
|
2081
|
+
}
|
|
2082
|
+
function inlineGuardCode(params, condition) {
|
|
2083
|
+
return `${params} => ${condition}`;
|
|
2084
|
+
}
|
|
2085
|
+
function guardFromConditions(conds, params) {
|
|
1674
2086
|
const simplified = simplifyConditions(conds);
|
|
1675
2087
|
if (simplified.length === 0) return void 0;
|
|
1676
|
-
|
|
2088
|
+
const code = inlineGuardCode(params, simplified.map(conditionText).join(" && "));
|
|
2089
|
+
return {
|
|
2090
|
+
type: `inline:${hashString(code)}`,
|
|
2091
|
+
code
|
|
2092
|
+
};
|
|
2093
|
+
}
|
|
2094
|
+
function wrapAssignExpression(expr) {
|
|
2095
|
+
return `{{ ${expr.trim()} }}`;
|
|
2096
|
+
}
|
|
2097
|
+
function hasSpreadAssignment(node) {
|
|
2098
|
+
return node.properties.some((property) => ts.isSpreadAssignment(property));
|
|
1677
2099
|
}
|
|
1678
2100
|
function mergeActions(left, right) {
|
|
1679
2101
|
return [...left ?? [], ...right];
|
|
@@ -1688,12 +2110,6 @@ function transitionFromValue(value, actions) {
|
|
|
1688
2110
|
}
|
|
1689
2111
|
if (!value || typeof value !== "object" || Array.isArray(value)) return actions.length ? { actions } : null;
|
|
1690
2112
|
const record = { ...value };
|
|
1691
|
-
const context = record.context;
|
|
1692
|
-
delete record.context;
|
|
1693
|
-
if (context !== void 0) record.actions = mergeActions(Array.isArray(record.actions) ? record.actions : record.actions ? [record.actions] : void 0, [{
|
|
1694
|
-
type: "xstate.assign",
|
|
1695
|
-
params: { assignment: context }
|
|
1696
|
-
}]);
|
|
1697
2113
|
if (actions.length) record.actions = mergeActions(Array.isArray(record.actions) ? record.actions : record.actions ? [record.actions] : void 0, actions);
|
|
1698
2114
|
return record;
|
|
1699
2115
|
}
|
|
@@ -1741,13 +2157,19 @@ function expressionBranches(expression, bindings, depth) {
|
|
|
1741
2157
|
const target = targetProperty ? unwrapExpression$2(targetProperty.initializer) : null;
|
|
1742
2158
|
if (target && (ts.isConditionalExpression(target) || ts.isBinaryExpression(target) && (target.operatorToken.kind === ts.SyntaxKind.AmpersandAmpersandToken || target.operatorToken.kind === ts.SyntaxKind.BarBarToken))) return expressionBranches(target, bindings, depth + 1).map((branch) => ({
|
|
1743
2159
|
...branch,
|
|
1744
|
-
result: objectLiteralToValue(node, bindings, {
|
|
2160
|
+
result: objectLiteralToValue(node, bindings, {
|
|
2161
|
+
v6: true,
|
|
2162
|
+
transitionValue: true
|
|
2163
|
+
}, depth + 1, new Map([["target", branch.result]]))
|
|
1745
2164
|
}));
|
|
1746
2165
|
}
|
|
1747
2166
|
return [{
|
|
1748
2167
|
conds: [],
|
|
1749
2168
|
actions: [],
|
|
1750
|
-
result: expressionToValue(node, bindings, {
|
|
2169
|
+
result: expressionToValue(node, bindings, {
|
|
2170
|
+
v6: true,
|
|
2171
|
+
transitionValue: true
|
|
2172
|
+
}, depth + 1)
|
|
1751
2173
|
}];
|
|
1752
2174
|
}
|
|
1753
2175
|
function mergeBranchPrefix(prefix, branch) {
|
|
@@ -1833,9 +2255,15 @@ function statementBranches(statements, bindings, enqName, prefixes = [{
|
|
|
1833
2255
|
}]) {
|
|
1834
2256
|
let open = prefixes;
|
|
1835
2257
|
const done = [];
|
|
2258
|
+
const scopedBindings = new Map(bindings);
|
|
1836
2259
|
for (const statement of statements) {
|
|
1837
2260
|
const nextOpen = [];
|
|
1838
2261
|
for (const prefix of open) {
|
|
2262
|
+
if (ts.isVariableStatement(statement)) {
|
|
2263
|
+
for (const declaration of statement.declarationList.declarations) if (ts.isIdentifier(declaration.name) && declaration.initializer) scopedBindings.set(declaration.name.text, declaration.initializer);
|
|
2264
|
+
nextOpen.push(prefix);
|
|
2265
|
+
continue;
|
|
2266
|
+
}
|
|
1839
2267
|
if (ts.isReturnStatement(statement)) {
|
|
1840
2268
|
if (!statement.expression) {
|
|
1841
2269
|
done.push({
|
|
@@ -1844,11 +2272,11 @@ function statementBranches(statements, bindings, enqName, prefixes = [{
|
|
|
1844
2272
|
});
|
|
1845
2273
|
continue;
|
|
1846
2274
|
}
|
|
1847
|
-
for (const branch of expressionBranches(statement.expression,
|
|
2275
|
+
for (const branch of expressionBranches(statement.expression, scopedBindings, 0)) done.push(mergeBranchPrefix(prefix, branch));
|
|
1848
2276
|
continue;
|
|
1849
2277
|
}
|
|
1850
2278
|
if (ts.isExpressionStatement(statement)) {
|
|
1851
|
-
const action = expressionStatementAction(statement, enqName,
|
|
2279
|
+
const action = expressionStatementAction(statement, enqName, scopedBindings);
|
|
1852
2280
|
if (action) {
|
|
1853
2281
|
nextOpen.push({
|
|
1854
2282
|
...prefix,
|
|
@@ -1859,12 +2287,12 @@ function statementBranches(statements, bindings, enqName, prefixes = [{
|
|
|
1859
2287
|
}
|
|
1860
2288
|
if (ts.isIfStatement(statement)) {
|
|
1861
2289
|
const cond = statement.expression.getText();
|
|
1862
|
-
const thenBranches = statementBranches(ts.isBlock(statement.thenStatement) ? statement.thenStatement.statements : [statement.thenStatement],
|
|
2290
|
+
const thenBranches = statementBranches(ts.isBlock(statement.thenStatement) ? statement.thenStatement.statements : [statement.thenStatement], scopedBindings, enqName, [{
|
|
1863
2291
|
...prefix,
|
|
1864
2292
|
conds: [...prefix.conds, { text: cond }]
|
|
1865
2293
|
}]);
|
|
1866
2294
|
const elseStatements = statement.elseStatement ? ts.isBlock(statement.elseStatement) ? statement.elseStatement.statements : [statement.elseStatement] : [];
|
|
1867
|
-
const elseBranches = elseStatements.length > 0 ? statementBranches(elseStatements,
|
|
2295
|
+
const elseBranches = elseStatements.length > 0 ? statementBranches(elseStatements, scopedBindings, enqName, [{
|
|
1868
2296
|
...prefix,
|
|
1869
2297
|
conds: [...prefix.conds, {
|
|
1870
2298
|
text: cond,
|
|
@@ -1887,7 +2315,7 @@ function statementBranches(statements, bindings, enqName, prefixes = [{
|
|
|
1887
2315
|
for (const clause of statement.caseBlock.clauses) {
|
|
1888
2316
|
const ownCond = ts.isCaseClause(clause) ? { text: `${expr} === ${clause.expression.getText()}` } : null;
|
|
1889
2317
|
const conds = ownCond ? [...prior, ownCond] : prior.length ? [...prior] : [];
|
|
1890
|
-
const branches = statementBranches(clause.statements,
|
|
2318
|
+
const branches = statementBranches(clause.statements, scopedBindings, enqName, [{
|
|
1891
2319
|
...prefix,
|
|
1892
2320
|
conds: [...prefix.conds, ...conds]
|
|
1893
2321
|
}]);
|
|
@@ -1913,18 +2341,24 @@ function enqueueParamName(fn) {
|
|
|
1913
2341
|
const param = fn.parameters[1];
|
|
1914
2342
|
return param && ts.isIdentifier(param.name) ? param.name.text : "enq";
|
|
1915
2343
|
}
|
|
2344
|
+
function guardParams(fn) {
|
|
2345
|
+
const param = fn.parameters[0];
|
|
2346
|
+
if (!param) return "()";
|
|
2347
|
+
return `(${param.getText()})`;
|
|
2348
|
+
}
|
|
1916
2349
|
function normalizeFunctionTransition(fn, bindings, depth) {
|
|
2350
|
+
const preservedActions = fn.body && ts.isBlock(fn.body) && fn.body.statements.some((statement) => ts.isExpressionStatement(statement)) ? [enqueueAction(fn)] : [];
|
|
1917
2351
|
const transitions = (ts.isArrowFunction(fn) && !ts.isBlock(fn.body) ? expressionBranches(fn.body, bindings, depth + 1) : fn.body && ts.isBlock(fn.body) ? statementBranches(fn.body.statements, bindings, enqueueParamName(fn)) : []).filter((branch) => !branch.unknown).map((branch) => {
|
|
1918
|
-
const transition = transitionFromValue(branch.result, branch.actions);
|
|
2352
|
+
const transition = transitionFromValue(branch.result, branch.actions.length ? preservedActions : []);
|
|
1919
2353
|
if (!transition) return null;
|
|
1920
2354
|
if (typeof transition === "string") {
|
|
1921
|
-
const guard = guardFromConditions(branch.conds);
|
|
2355
|
+
const guard = guardFromConditions(branch.conds, guardParams(fn));
|
|
1922
2356
|
return guard ? {
|
|
1923
2357
|
target: transition,
|
|
1924
2358
|
guard
|
|
1925
2359
|
} : transition;
|
|
1926
2360
|
}
|
|
1927
|
-
const guard = guardFromConditions(branch.conds);
|
|
2361
|
+
const guard = guardFromConditions(branch.conds, guardParams(fn));
|
|
1928
2362
|
return guard ? {
|
|
1929
2363
|
...transition,
|
|
1930
2364
|
guard
|
|
@@ -1932,7 +2366,7 @@ function normalizeFunctionTransition(fn, bindings, depth) {
|
|
|
1932
2366
|
}).filter((transition) => Boolean(transition));
|
|
1933
2367
|
if (transitions.length === 1) return transitions[0];
|
|
1934
2368
|
if (transitions.length > 1) return transitions;
|
|
1935
|
-
return fallbackFunctionTransition(fn);
|
|
2369
|
+
return fallbackFunctionTransition(fn, preservedActions);
|
|
1936
2370
|
}
|
|
1937
2371
|
function inlineAction(fn) {
|
|
1938
2372
|
return {
|
|
@@ -1943,12 +2377,24 @@ function inlineAction(fn) {
|
|
|
1943
2377
|
}
|
|
1944
2378
|
};
|
|
1945
2379
|
}
|
|
1946
|
-
function
|
|
1947
|
-
|
|
1948
|
-
|
|
1949
|
-
|
|
1950
|
-
|
|
1951
|
-
|
|
2380
|
+
function enqueueAction(fn) {
|
|
2381
|
+
return {
|
|
2382
|
+
type: "xstate.enqueue",
|
|
2383
|
+
params: {
|
|
2384
|
+
code: fn.getText(),
|
|
2385
|
+
lang: "ts"
|
|
2386
|
+
}
|
|
2387
|
+
};
|
|
2388
|
+
}
|
|
2389
|
+
function inlineCodeExpression(expr) {
|
|
2390
|
+
return {
|
|
2391
|
+
"@type": "code",
|
|
2392
|
+
lang: "ts",
|
|
2393
|
+
expr
|
|
2394
|
+
};
|
|
2395
|
+
}
|
|
2396
|
+
function normalizeFunctionAction(fn, _bindings) {
|
|
2397
|
+
return enqueueAction(fn);
|
|
1952
2398
|
}
|
|
1953
2399
|
function objectLiteralToValue(node, bindings, context, depth, overrides = /* @__PURE__ */ new Map()) {
|
|
1954
2400
|
const result = {};
|
|
@@ -1995,15 +2441,22 @@ function objectLiteralToValue(node, bindings, context, depth, overrides = /* @__
|
|
|
1995
2441
|
function expressionToValue(expression, bindings, context = {}, depth = 0) {
|
|
1996
2442
|
if (depth > 30) return void 0;
|
|
1997
2443
|
const node = unwrapExpression$2(expression);
|
|
1998
|
-
if (ts.isStringLiteral(node) || ts.isNoSubstitutionTemplateLiteral(node)) return node.text;
|
|
1999
|
-
if (ts.isNumericLiteral(node)) return Number(node.text);
|
|
2000
|
-
if (node.kind === ts.SyntaxKind.TrueKeyword) return true;
|
|
2001
|
-
if (node.kind === ts.SyntaxKind.FalseKeyword) return false;
|
|
2002
|
-
if (node.kind === ts.SyntaxKind.NullKeyword) return null;
|
|
2444
|
+
if (ts.isStringLiteral(node) || ts.isNoSubstitutionTemplateLiteral(node)) return context.ioValue ? inlineCodeExpression(JSON.stringify(node.text)) : node.text;
|
|
2445
|
+
if (ts.isNumericLiteral(node)) return context.ioValue ? inlineCodeExpression(node.text) : Number(node.text);
|
|
2446
|
+
if (node.kind === ts.SyntaxKind.TrueKeyword) return context.ioValue ? inlineCodeExpression("true") : true;
|
|
2447
|
+
if (node.kind === ts.SyntaxKind.FalseKeyword) return context.ioValue ? inlineCodeExpression("false") : false;
|
|
2448
|
+
if (node.kind === ts.SyntaxKind.NullKeyword) return context.ioValue ? inlineCodeExpression("null") : null;
|
|
2449
|
+
if (context.assignmentValue) {
|
|
2450
|
+
if (ts.isIdentifier(node) && node.text === "undefined") return void 0;
|
|
2451
|
+
return wrapAssignExpression(node.getText());
|
|
2452
|
+
}
|
|
2453
|
+
if (context.transitionContext && !ts.isObjectLiteralExpression(node)) return inlineCodeExpression(node.getText());
|
|
2454
|
+
if (context.ioValue && !ts.isObjectLiteralExpression(node)) return inlineCodeExpression(node.getText());
|
|
2455
|
+
if (context.transitionContext && ts.isObjectLiteralExpression(node) && hasSpreadAssignment(node)) return inlineCodeExpression(node.getText());
|
|
2003
2456
|
if (ts.isIdentifier(node)) {
|
|
2004
2457
|
if (node.text === "undefined") return void 0;
|
|
2005
2458
|
const binding = bindings.get(node.text);
|
|
2006
|
-
return binding ? expressionToValue(binding, bindings, context, depth + 1) : node.text;
|
|
2459
|
+
return binding ? expressionToValue(binding, bindings, context, depth + 1) : context.metaValue ? inlineCodeExpression(node.getText()) : node.text;
|
|
2007
2460
|
}
|
|
2008
2461
|
if (ts.isObjectLiteralExpression(node)) return objectLiteralToValue(node, bindings, context, depth);
|
|
2009
2462
|
if (ts.isArrayLiteralExpression(node)) {
|
|
@@ -2011,17 +2464,19 @@ function expressionToValue(expression, bindings, context = {}, depth = 0) {
|
|
|
2011
2464
|
return context.actionValue ? values.flat() : values;
|
|
2012
2465
|
}
|
|
2013
2466
|
if (ts.isArrowFunction(node) || ts.isFunctionExpression(node)) {
|
|
2467
|
+
if (context.metaValue) return inlineCodeExpression(node.getText());
|
|
2014
2468
|
if (context.v6 && context.transitionValue) return normalizeFunctionTransition(node, bindings, depth);
|
|
2015
2469
|
if (context.v6 && context.actionValue) return normalizeFunctionAction(node, bindings);
|
|
2016
2470
|
return node.getText();
|
|
2017
2471
|
}
|
|
2018
2472
|
if (ts.isCallExpression(node)) {
|
|
2473
|
+
if (context.metaValue) return inlineCodeExpression(node.getText());
|
|
2019
2474
|
if (context.actionValue) return inlineAction(node);
|
|
2020
2475
|
const callee = node.expression.getText();
|
|
2021
2476
|
const type = callee.includes(".") ? callee.split(".").pop() : callee;
|
|
2022
2477
|
return { type: type === "assign" ? "xstate.assign" : type };
|
|
2023
2478
|
}
|
|
2024
|
-
return node.getText();
|
|
2479
|
+
return context.metaValue ? inlineCodeExpression(node.getText()) : node.getText();
|
|
2025
2480
|
}
|
|
2026
2481
|
function collectBindings$1(file) {
|
|
2027
2482
|
const bindings = /* @__PURE__ */ new Map();
|
|
@@ -2048,7 +2503,7 @@ function hasV6Syntax(source) {
|
|
|
2048
2503
|
found = true;
|
|
2049
2504
|
return;
|
|
2050
2505
|
}
|
|
2051
|
-
if ((key === "on" || key === "after" || key === "always" || key === "entry" || key === "exit" || key === "actions" && !ts.isObjectLiteralExpression(node.initializer)) && node.initializer.getText().includes("=>")) {
|
|
2506
|
+
if ((key === "on" || key === "after" || key === "always" || key === "choice" || key === "onDone" || key === "onError" || key === "onSnapshot" || key === "onTimeout" || key === "entry" || key === "exit" || key === "actions" && !ts.isObjectLiteralExpression(node.initializer)) && node.initializer.getText().includes("=>")) {
|
|
2052
2507
|
found = true;
|
|
2053
2508
|
return;
|
|
2054
2509
|
}
|
|
@@ -2402,6 +2857,7 @@ const validationIssueCodeSchema = _enum([
|
|
|
2402
2857
|
"transition_never_taken",
|
|
2403
2858
|
"missing_guard",
|
|
2404
2859
|
"redundant_transition",
|
|
2860
|
+
"eventless_cycle",
|
|
2405
2861
|
"missing_delay_implementation",
|
|
2406
2862
|
"invalid_final_transition",
|
|
2407
2863
|
"invalid_history_transition",
|
|
@@ -2698,6 +3154,51 @@ function getOnDoneWarnings(graph, reachableNodes) {
|
|
|
2698
3154
|
}
|
|
2699
3155
|
return results;
|
|
2700
3156
|
}
|
|
3157
|
+
function getEventlessCycleErrors(graph) {
|
|
3158
|
+
const eventlessEdges = graph.edges.filter((edge) => edge.data.eventType === "" && !edge.data.guard);
|
|
3159
|
+
const bySource = /* @__PURE__ */ new Map();
|
|
3160
|
+
for (const edge of eventlessEdges) {
|
|
3161
|
+
const edges = bySource.get(edge.sourceId) ?? [];
|
|
3162
|
+
edges.push(edge);
|
|
3163
|
+
bySource.set(edge.sourceId, edges);
|
|
3164
|
+
}
|
|
3165
|
+
const results = [];
|
|
3166
|
+
const reported = /* @__PURE__ */ new Set();
|
|
3167
|
+
for (const startEdge of eventlessEdges) {
|
|
3168
|
+
const stack = [{
|
|
3169
|
+
nodeId: startEdge.targetId,
|
|
3170
|
+
path: [startEdge]
|
|
3171
|
+
}];
|
|
3172
|
+
const seen = /* @__PURE__ */ new Set();
|
|
3173
|
+
while (stack.length > 0) {
|
|
3174
|
+
const current = stack.pop();
|
|
3175
|
+
if (current.nodeId === startEdge.sourceId) {
|
|
3176
|
+
const edgeIds = current.path.map((edge) => edge.id);
|
|
3177
|
+
const key = [...edgeIds].sort().join("|");
|
|
3178
|
+
if (!reported.has(key)) {
|
|
3179
|
+
reported.add(key);
|
|
3180
|
+
results.push(issue({
|
|
3181
|
+
code: "eventless_cycle",
|
|
3182
|
+
kind: "correctness",
|
|
3183
|
+
level: "error",
|
|
3184
|
+
edgeIds,
|
|
3185
|
+
nodeIds: Array.from(new Set(current.path.flatMap((edge) => [edge.sourceId, edge.targetId]))),
|
|
3186
|
+
message: "Unguarded eventless transitions form an infinite transition loop",
|
|
3187
|
+
metadata: { edgeIds }
|
|
3188
|
+
}));
|
|
3189
|
+
}
|
|
3190
|
+
continue;
|
|
3191
|
+
}
|
|
3192
|
+
if (seen.has(current.nodeId)) continue;
|
|
3193
|
+
seen.add(current.nodeId);
|
|
3194
|
+
for (const nextEdge of bySource.get(current.nodeId) ?? []) stack.push({
|
|
3195
|
+
nodeId: nextEdge.targetId,
|
|
3196
|
+
path: [...current.path, nextEdge]
|
|
3197
|
+
});
|
|
3198
|
+
}
|
|
3199
|
+
}
|
|
3200
|
+
return results;
|
|
3201
|
+
}
|
|
2701
3202
|
function getEdgeErrors(graph, edge) {
|
|
2702
3203
|
const errors = [];
|
|
2703
3204
|
const duplicates = findDuplicateEdges(graph, edge);
|
|
@@ -2929,6 +3430,7 @@ function validateGraph(graph, sourceAllowed) {
|
|
|
2929
3430
|
pushMessages(results, getEdgeWarnings(nonTempGraph, edge), "warning", [], [edge.id]);
|
|
2930
3431
|
}
|
|
2931
3432
|
results.push(...getOnDoneWarnings(nonTempGraph, reachableNodes));
|
|
3433
|
+
results.push(...getEventlessCycleErrors(nonTempGraph));
|
|
2932
3434
|
results.push(...getSourceWarnings(nonTempGraph));
|
|
2933
3435
|
results.push(...getSourceRestrictionErrors(nonTempGraph, sourceAllowed));
|
|
2934
3436
|
return results;
|