@statelyai/sdk 0.11.0 → 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 +32 -1
- 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-DV62vO_d.mjs → graphToXStateTS-D12GTMBp.mjs} +22 -1
- package/dist/index.d.mts +6 -4
- package/dist/index.mjs +5 -3
- package/dist/{inspect-CZ8iLJR7.d.mts → inspect-BibyPhFj.d.mts} +2 -1
- package/dist/inspect.d.mts +3 -3
- package/dist/inspect.mjs +3 -2
- 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 +527 -42
- 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,
|
|
@@ -868,6 +1205,10 @@ function formatObjectKey(key) {
|
|
|
868
1205
|
const eventParamSchema = union([string(), object({ type: string() }).catchall(unknown())]);
|
|
869
1206
|
const delayParamSchema = union([number(), string()]);
|
|
870
1207
|
const builtInActionParamSchemas = {
|
|
1208
|
+
"xstate.enqueue": object({
|
|
1209
|
+
code: string().optional(),
|
|
1210
|
+
lang: string().optional()
|
|
1211
|
+
}),
|
|
871
1212
|
"xstate.raise": object({
|
|
872
1213
|
event: eventParamSchema.optional(),
|
|
873
1214
|
id: string().optional(),
|
|
@@ -891,6 +1232,16 @@ const builtInActionParamSchemas = {
|
|
|
891
1232
|
"xstate.assign": object({ assignment: record(string(), unknown()).optional() }).catchall(unknown())
|
|
892
1233
|
};
|
|
893
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
|
+
},
|
|
894
1245
|
"xstate.raise": {
|
|
895
1246
|
package: "xstate",
|
|
896
1247
|
version: "^5",
|
|
@@ -1033,6 +1384,7 @@ function serializeGuard(guard, asTypeRef) {
|
|
|
1033
1384
|
*/
|
|
1034
1385
|
function serializeActionItem(action) {
|
|
1035
1386
|
const { type, params } = action;
|
|
1387
|
+
if (type === "xstate.enqueue" && typeof params?.code === "string") return inlineCodeExpression$1(params.code);
|
|
1036
1388
|
const exprCode = type === "xstate.expr" && typeof params?.code === "string" ? params.code : void 0;
|
|
1037
1389
|
if (isBuiltInActionType(type)) {
|
|
1038
1390
|
const builtInAction = XSTATE_BUILT_IN_ACTIONS[type];
|
|
@@ -1065,7 +1417,8 @@ function graphToMachineConfig(graph, options = {}) {
|
|
|
1065
1417
|
const nodeType = [
|
|
1066
1418
|
"final",
|
|
1067
1419
|
"history",
|
|
1068
|
-
"parallel"
|
|
1420
|
+
"parallel",
|
|
1421
|
+
"choice"
|
|
1069
1422
|
].includes(node.data.type) ? node.data.type : void 0;
|
|
1070
1423
|
const tags = node.data.tags;
|
|
1071
1424
|
Object.assign(nodeConfig, {
|
|
@@ -1080,6 +1433,7 @@ function graphToMachineConfig(graph, options = {}) {
|
|
|
1080
1433
|
...inv.input ? { input: inv.input } : void 0,
|
|
1081
1434
|
...inv.output ? { output: inv.output } : void 0
|
|
1082
1435
|
})) } : void 0,
|
|
1436
|
+
...node.data.output !== void 0 ? { output: node.data.output } : void 0,
|
|
1083
1437
|
...tags?.length ? { tags: tags.map(tagToString) } : void 0,
|
|
1084
1438
|
...showDescriptions && node.data.description ? { description: node.data.description } : void 0,
|
|
1085
1439
|
...showMeta && node.data.meta && Object.keys(node.data.meta).length > 0 ? { meta: node.data.meta } : void 0,
|
|
@@ -1091,6 +1445,7 @@ function graphToMachineConfig(graph, options = {}) {
|
|
|
1091
1445
|
const on = {};
|
|
1092
1446
|
const after = {};
|
|
1093
1447
|
const alwaysArr = [];
|
|
1448
|
+
const choiceArr = [];
|
|
1094
1449
|
const onDone = {};
|
|
1095
1450
|
const invokeMap = {};
|
|
1096
1451
|
for (const edge of edges) {
|
|
@@ -1102,6 +1457,7 @@ function graphToMachineConfig(graph, options = {}) {
|
|
|
1102
1457
|
target: edge.data.transitionType === "targetless" ? void 0 : `${resolvedTarget}`,
|
|
1103
1458
|
...edge.data.transitionType === "reenter" ? { reenter: true } : void 0,
|
|
1104
1459
|
guard: edge.data.guard ? serializeGuard(edge.data.guard, inlineGuardsAsTypeRef) : void 0,
|
|
1460
|
+
...edge.data.context !== void 0 ? { context: edge.data.context } : void 0,
|
|
1105
1461
|
actions: edge.data.actions?.length ? edge.data.actions.map(serializeActionItem) : void 0,
|
|
1106
1462
|
description: edge.data.description ?? void 0,
|
|
1107
1463
|
...transitionMeta ? { meta: transitionMeta } : void 0
|
|
@@ -1124,6 +1480,7 @@ function graphToMachineConfig(graph, options = {}) {
|
|
|
1124
1480
|
if (!onDone[type]) onDone[type] = [];
|
|
1125
1481
|
onDone[type].push(transitionObject);
|
|
1126
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);
|
|
1127
1484
|
else if (type === "") alwaysArr.push(transitionObject);
|
|
1128
1485
|
else if (type.startsWith("xstate.after.")) {
|
|
1129
1486
|
const delayKey = type.slice(13).split(".")[0];
|
|
@@ -1143,6 +1500,7 @@ function graphToMachineConfig(graph, options = {}) {
|
|
|
1143
1500
|
if (Object.keys(on).length > 0) nodeConfig.on = singleOrArrayRecord(on);
|
|
1144
1501
|
if (Object.keys(after).length > 0) nodeConfig.after = singleOrArrayRecord(after);
|
|
1145
1502
|
if (alwaysArr.length > 0) nodeConfig.always = singleOrArray(alwaysArr);
|
|
1503
|
+
if (choiceArr.length > 0) nodeConfig.choice = singleOrArray(choiceArr);
|
|
1146
1504
|
if (Object.keys(onDone).length > 0) nodeConfig.onDone = singleOrArray(Object.values(onDone).flat());
|
|
1147
1505
|
if (Object.keys(invokeMap).length > 0 && Array.isArray(nodeConfig.invoke)) nodeConfig.invoke = nodeConfig.invoke.map((inv, index) => {
|
|
1148
1506
|
const mapped = invokeMap[node.data.invokes?.[index]?.id ?? inv.id];
|
|
@@ -1521,6 +1879,7 @@ function guardObject(value) {
|
|
|
1521
1879
|
const guard = value;
|
|
1522
1880
|
return {
|
|
1523
1881
|
type: guard.type,
|
|
1882
|
+
code: guard.code,
|
|
1524
1883
|
params: guard.params
|
|
1525
1884
|
};
|
|
1526
1885
|
}
|
|
@@ -1551,9 +1910,10 @@ function machineConfigToGraph(config) {
|
|
|
1551
1910
|
parentId,
|
|
1552
1911
|
data: {
|
|
1553
1912
|
key,
|
|
1554
|
-
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,
|
|
1555
1914
|
initialId,
|
|
1556
1915
|
history: state.history ?? false,
|
|
1916
|
+
...state.output !== void 0 ? { output: state.output } : {},
|
|
1557
1917
|
entry: actionItems(state.entry),
|
|
1558
1918
|
exit: actionItems(state.exit),
|
|
1559
1919
|
invokes: invokeItems(state.invoke),
|
|
@@ -1572,6 +1932,7 @@ function machineConfigToGraph(config) {
|
|
|
1572
1932
|
eventType,
|
|
1573
1933
|
transitionType: target ? transition.reenter ? "reenter" : "normal" : "targetless",
|
|
1574
1934
|
guard: guardObject(transition.guard),
|
|
1935
|
+
...transition.context !== void 0 ? { context: transition.context } : {},
|
|
1575
1936
|
actions: actionItems(transition.actions),
|
|
1576
1937
|
description: typeof transition.description === "string" ? transition.description : null,
|
|
1577
1938
|
meta: transition.meta && typeof transition.meta === "object" ? transition.meta : null
|
|
@@ -1588,6 +1949,7 @@ function machineConfigToGraph(config) {
|
|
|
1588
1949
|
eventType: `xstate.after.${delay}.${id}`,
|
|
1589
1950
|
transitionType: target ? "normal" : "targetless",
|
|
1590
1951
|
guard: guardObject(transition.guard),
|
|
1952
|
+
...transition.context !== void 0 ? { context: transition.context } : {},
|
|
1591
1953
|
actions: actionItems(transition.actions),
|
|
1592
1954
|
description: typeof transition.description === "string" ? transition.description : null,
|
|
1593
1955
|
meta: null
|
|
@@ -1604,12 +1966,30 @@ function machineConfigToGraph(config) {
|
|
|
1604
1966
|
eventType: "",
|
|
1605
1967
|
transitionType: target ? "normal" : "targetless",
|
|
1606
1968
|
guard: guardObject(transition.guard),
|
|
1969
|
+
...transition.context !== void 0 ? { context: transition.context } : {},
|
|
1607
1970
|
actions: actionItems(transition.actions),
|
|
1608
1971
|
description: typeof transition.description === "string" ? transition.description : null,
|
|
1609
1972
|
meta: null
|
|
1610
1973
|
}
|
|
1611
1974
|
});
|
|
1612
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
|
+
}
|
|
1613
1993
|
for (const [childKey, child] of Object.entries(state.states ?? {})) visit(child, childKey, id);
|
|
1614
1994
|
}
|
|
1615
1995
|
visit(config, rootKey, null);
|
|
@@ -1637,6 +2017,15 @@ function propertyContext(parent, key) {
|
|
|
1637
2017
|
v6: parent.v6,
|
|
1638
2018
|
actionValue: true
|
|
1639
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
|
+
};
|
|
1640
2029
|
if (key === "meta") return {
|
|
1641
2030
|
v6: parent.v6,
|
|
1642
2031
|
metaValue: true
|
|
@@ -1649,21 +2038,28 @@ function propertyContext(parent, key) {
|
|
|
1649
2038
|
v6: parent.v6,
|
|
1650
2039
|
actionValue: true
|
|
1651
2040
|
};
|
|
2041
|
+
if (key === "input" || key === "output") return {
|
|
2042
|
+
v6: parent.v6,
|
|
2043
|
+
ioValue: true
|
|
2044
|
+
};
|
|
1652
2045
|
if (key === "on" || key === "after") return {
|
|
1653
2046
|
v6: parent.v6,
|
|
1654
2047
|
transitionMap: true
|
|
1655
2048
|
};
|
|
1656
|
-
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 {
|
|
1657
2050
|
v6: parent.v6,
|
|
1658
2051
|
transitionValue: true
|
|
1659
2052
|
};
|
|
1660
2053
|
return { v6: parent.v6 };
|
|
1661
2054
|
}
|
|
1662
|
-
function fallbackFunctionTransition(fn) {
|
|
1663
|
-
return {
|
|
1664
|
-
|
|
1665
|
-
|
|
1666
|
-
|
|
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
|
+
};
|
|
1667
2063
|
}
|
|
1668
2064
|
function conditionText(cond) {
|
|
1669
2065
|
return cond.negated ? `!(${cond.text})` : cond.text;
|
|
@@ -1678,10 +2074,28 @@ function simplifyConditions(conds) {
|
|
|
1678
2074
|
return true;
|
|
1679
2075
|
});
|
|
1680
2076
|
}
|
|
1681
|
-
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) {
|
|
1682
2086
|
const simplified = simplifyConditions(conds);
|
|
1683
2087
|
if (simplified.length === 0) return void 0;
|
|
1684
|
-
|
|
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));
|
|
1685
2099
|
}
|
|
1686
2100
|
function mergeActions(left, right) {
|
|
1687
2101
|
return [...left ?? [], ...right];
|
|
@@ -1696,12 +2110,6 @@ function transitionFromValue(value, actions) {
|
|
|
1696
2110
|
}
|
|
1697
2111
|
if (!value || typeof value !== "object" || Array.isArray(value)) return actions.length ? { actions } : null;
|
|
1698
2112
|
const record = { ...value };
|
|
1699
|
-
const context = record.context;
|
|
1700
|
-
delete record.context;
|
|
1701
|
-
if (context !== void 0) record.actions = mergeActions(Array.isArray(record.actions) ? record.actions : record.actions ? [record.actions] : void 0, [{
|
|
1702
|
-
type: "xstate.assign",
|
|
1703
|
-
params: { assignment: context }
|
|
1704
|
-
}]);
|
|
1705
2113
|
if (actions.length) record.actions = mergeActions(Array.isArray(record.actions) ? record.actions : record.actions ? [record.actions] : void 0, actions);
|
|
1706
2114
|
return record;
|
|
1707
2115
|
}
|
|
@@ -1749,13 +2157,19 @@ function expressionBranches(expression, bindings, depth) {
|
|
|
1749
2157
|
const target = targetProperty ? unwrapExpression$2(targetProperty.initializer) : null;
|
|
1750
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) => ({
|
|
1751
2159
|
...branch,
|
|
1752
|
-
result: objectLiteralToValue(node, bindings, {
|
|
2160
|
+
result: objectLiteralToValue(node, bindings, {
|
|
2161
|
+
v6: true,
|
|
2162
|
+
transitionValue: true
|
|
2163
|
+
}, depth + 1, new Map([["target", branch.result]]))
|
|
1753
2164
|
}));
|
|
1754
2165
|
}
|
|
1755
2166
|
return [{
|
|
1756
2167
|
conds: [],
|
|
1757
2168
|
actions: [],
|
|
1758
|
-
result: expressionToValue(node, bindings, {
|
|
2169
|
+
result: expressionToValue(node, bindings, {
|
|
2170
|
+
v6: true,
|
|
2171
|
+
transitionValue: true
|
|
2172
|
+
}, depth + 1)
|
|
1759
2173
|
}];
|
|
1760
2174
|
}
|
|
1761
2175
|
function mergeBranchPrefix(prefix, branch) {
|
|
@@ -1841,9 +2255,15 @@ function statementBranches(statements, bindings, enqName, prefixes = [{
|
|
|
1841
2255
|
}]) {
|
|
1842
2256
|
let open = prefixes;
|
|
1843
2257
|
const done = [];
|
|
2258
|
+
const scopedBindings = new Map(bindings);
|
|
1844
2259
|
for (const statement of statements) {
|
|
1845
2260
|
const nextOpen = [];
|
|
1846
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
|
+
}
|
|
1847
2267
|
if (ts.isReturnStatement(statement)) {
|
|
1848
2268
|
if (!statement.expression) {
|
|
1849
2269
|
done.push({
|
|
@@ -1852,11 +2272,11 @@ function statementBranches(statements, bindings, enqName, prefixes = [{
|
|
|
1852
2272
|
});
|
|
1853
2273
|
continue;
|
|
1854
2274
|
}
|
|
1855
|
-
for (const branch of expressionBranches(statement.expression,
|
|
2275
|
+
for (const branch of expressionBranches(statement.expression, scopedBindings, 0)) done.push(mergeBranchPrefix(prefix, branch));
|
|
1856
2276
|
continue;
|
|
1857
2277
|
}
|
|
1858
2278
|
if (ts.isExpressionStatement(statement)) {
|
|
1859
|
-
const action = expressionStatementAction(statement, enqName,
|
|
2279
|
+
const action = expressionStatementAction(statement, enqName, scopedBindings);
|
|
1860
2280
|
if (action) {
|
|
1861
2281
|
nextOpen.push({
|
|
1862
2282
|
...prefix,
|
|
@@ -1867,12 +2287,12 @@ function statementBranches(statements, bindings, enqName, prefixes = [{
|
|
|
1867
2287
|
}
|
|
1868
2288
|
if (ts.isIfStatement(statement)) {
|
|
1869
2289
|
const cond = statement.expression.getText();
|
|
1870
|
-
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, [{
|
|
1871
2291
|
...prefix,
|
|
1872
2292
|
conds: [...prefix.conds, { text: cond }]
|
|
1873
2293
|
}]);
|
|
1874
2294
|
const elseStatements = statement.elseStatement ? ts.isBlock(statement.elseStatement) ? statement.elseStatement.statements : [statement.elseStatement] : [];
|
|
1875
|
-
const elseBranches = elseStatements.length > 0 ? statementBranches(elseStatements,
|
|
2295
|
+
const elseBranches = elseStatements.length > 0 ? statementBranches(elseStatements, scopedBindings, enqName, [{
|
|
1876
2296
|
...prefix,
|
|
1877
2297
|
conds: [...prefix.conds, {
|
|
1878
2298
|
text: cond,
|
|
@@ -1895,7 +2315,7 @@ function statementBranches(statements, bindings, enqName, prefixes = [{
|
|
|
1895
2315
|
for (const clause of statement.caseBlock.clauses) {
|
|
1896
2316
|
const ownCond = ts.isCaseClause(clause) ? { text: `${expr} === ${clause.expression.getText()}` } : null;
|
|
1897
2317
|
const conds = ownCond ? [...prior, ownCond] : prior.length ? [...prior] : [];
|
|
1898
|
-
const branches = statementBranches(clause.statements,
|
|
2318
|
+
const branches = statementBranches(clause.statements, scopedBindings, enqName, [{
|
|
1899
2319
|
...prefix,
|
|
1900
2320
|
conds: [...prefix.conds, ...conds]
|
|
1901
2321
|
}]);
|
|
@@ -1921,18 +2341,24 @@ function enqueueParamName(fn) {
|
|
|
1921
2341
|
const param = fn.parameters[1];
|
|
1922
2342
|
return param && ts.isIdentifier(param.name) ? param.name.text : "enq";
|
|
1923
2343
|
}
|
|
2344
|
+
function guardParams(fn) {
|
|
2345
|
+
const param = fn.parameters[0];
|
|
2346
|
+
if (!param) return "()";
|
|
2347
|
+
return `(${param.getText()})`;
|
|
2348
|
+
}
|
|
1924
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)] : [];
|
|
1925
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) => {
|
|
1926
|
-
const transition = transitionFromValue(branch.result, branch.actions);
|
|
2352
|
+
const transition = transitionFromValue(branch.result, branch.actions.length ? preservedActions : []);
|
|
1927
2353
|
if (!transition) return null;
|
|
1928
2354
|
if (typeof transition === "string") {
|
|
1929
|
-
const guard = guardFromConditions(branch.conds);
|
|
2355
|
+
const guard = guardFromConditions(branch.conds, guardParams(fn));
|
|
1930
2356
|
return guard ? {
|
|
1931
2357
|
target: transition,
|
|
1932
2358
|
guard
|
|
1933
2359
|
} : transition;
|
|
1934
2360
|
}
|
|
1935
|
-
const guard = guardFromConditions(branch.conds);
|
|
2361
|
+
const guard = guardFromConditions(branch.conds, guardParams(fn));
|
|
1936
2362
|
return guard ? {
|
|
1937
2363
|
...transition,
|
|
1938
2364
|
guard
|
|
@@ -1940,7 +2366,7 @@ function normalizeFunctionTransition(fn, bindings, depth) {
|
|
|
1940
2366
|
}).filter((transition) => Boolean(transition));
|
|
1941
2367
|
if (transitions.length === 1) return transitions[0];
|
|
1942
2368
|
if (transitions.length > 1) return transitions;
|
|
1943
|
-
return fallbackFunctionTransition(fn);
|
|
2369
|
+
return fallbackFunctionTransition(fn, preservedActions);
|
|
1944
2370
|
}
|
|
1945
2371
|
function inlineAction(fn) {
|
|
1946
2372
|
return {
|
|
@@ -1951,6 +2377,15 @@ function inlineAction(fn) {
|
|
|
1951
2377
|
}
|
|
1952
2378
|
};
|
|
1953
2379
|
}
|
|
2380
|
+
function enqueueAction(fn) {
|
|
2381
|
+
return {
|
|
2382
|
+
type: "xstate.enqueue",
|
|
2383
|
+
params: {
|
|
2384
|
+
code: fn.getText(),
|
|
2385
|
+
lang: "ts"
|
|
2386
|
+
}
|
|
2387
|
+
};
|
|
2388
|
+
}
|
|
1954
2389
|
function inlineCodeExpression(expr) {
|
|
1955
2390
|
return {
|
|
1956
2391
|
"@type": "code",
|
|
@@ -1958,12 +2393,8 @@ function inlineCodeExpression(expr) {
|
|
|
1958
2393
|
expr
|
|
1959
2394
|
};
|
|
1960
2395
|
}
|
|
1961
|
-
function normalizeFunctionAction(fn,
|
|
1962
|
-
|
|
1963
|
-
if (!fn.body || !ts.isBlock(fn.body)) return inlineAction(fn);
|
|
1964
|
-
const branches = statementBranches(fn.body.statements, bindings, enqueueParamName(fn));
|
|
1965
|
-
if (branches.length === 1 && !branches[0].unknown && branches[0].conds.length === 0 && branches[0].actions.length > 0 && !("result" in branches[0])) return branches[0].actions;
|
|
1966
|
-
return inlineAction(fn);
|
|
2396
|
+
function normalizeFunctionAction(fn, _bindings) {
|
|
2397
|
+
return enqueueAction(fn);
|
|
1967
2398
|
}
|
|
1968
2399
|
function objectLiteralToValue(node, bindings, context, depth, overrides = /* @__PURE__ */ new Map()) {
|
|
1969
2400
|
const result = {};
|
|
@@ -2010,11 +2441,18 @@ function objectLiteralToValue(node, bindings, context, depth, overrides = /* @__
|
|
|
2010
2441
|
function expressionToValue(expression, bindings, context = {}, depth = 0) {
|
|
2011
2442
|
if (depth > 30) return void 0;
|
|
2012
2443
|
const node = unwrapExpression$2(expression);
|
|
2013
|
-
if (ts.isStringLiteral(node) || ts.isNoSubstitutionTemplateLiteral(node)) return node.text;
|
|
2014
|
-
if (ts.isNumericLiteral(node)) return Number(node.text);
|
|
2015
|
-
if (node.kind === ts.SyntaxKind.TrueKeyword) return true;
|
|
2016
|
-
if (node.kind === ts.SyntaxKind.FalseKeyword) return false;
|
|
2017
|
-
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());
|
|
2018
2456
|
if (ts.isIdentifier(node)) {
|
|
2019
2457
|
if (node.text === "undefined") return void 0;
|
|
2020
2458
|
const binding = bindings.get(node.text);
|
|
@@ -2065,7 +2503,7 @@ function hasV6Syntax(source) {
|
|
|
2065
2503
|
found = true;
|
|
2066
2504
|
return;
|
|
2067
2505
|
}
|
|
2068
|
-
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("=>")) {
|
|
2069
2507
|
found = true;
|
|
2070
2508
|
return;
|
|
2071
2509
|
}
|
|
@@ -2419,6 +2857,7 @@ const validationIssueCodeSchema = _enum([
|
|
|
2419
2857
|
"transition_never_taken",
|
|
2420
2858
|
"missing_guard",
|
|
2421
2859
|
"redundant_transition",
|
|
2860
|
+
"eventless_cycle",
|
|
2422
2861
|
"missing_delay_implementation",
|
|
2423
2862
|
"invalid_final_transition",
|
|
2424
2863
|
"invalid_history_transition",
|
|
@@ -2715,6 +3154,51 @@ function getOnDoneWarnings(graph, reachableNodes) {
|
|
|
2715
3154
|
}
|
|
2716
3155
|
return results;
|
|
2717
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
|
+
}
|
|
2718
3202
|
function getEdgeErrors(graph, edge) {
|
|
2719
3203
|
const errors = [];
|
|
2720
3204
|
const duplicates = findDuplicateEdges(graph, edge);
|
|
@@ -2946,6 +3430,7 @@ function validateGraph(graph, sourceAllowed) {
|
|
|
2946
3430
|
pushMessages(results, getEdgeWarnings(nonTempGraph, edge), "warning", [], [edge.id]);
|
|
2947
3431
|
}
|
|
2948
3432
|
results.push(...getOnDoneWarnings(nonTempGraph, reachableNodes));
|
|
3433
|
+
results.push(...getEventlessCycleErrors(nonTempGraph));
|
|
2949
3434
|
results.push(...getSourceWarnings(nonTempGraph));
|
|
2950
3435
|
results.push(...getSourceRestrictionErrors(nonTempGraph, sourceAllowed));
|
|
2951
3436
|
return results;
|