@statelyai/sdk 0.20.1 → 0.20.3

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.
@@ -1,5 +1,6 @@
1
1
  import { a as discriminatedUnion, c as object, d as union, f as unknown, i as custom, l as record, n as array, o as literal, r as boolean, s as number, t as _enum, u as string } from "./schemas-b9wG-zYl.mjs";
2
2
  import ts from "typescript";
3
+ import "xstate";
3
4
  import "xstate/graph";
4
5
 
5
6
  //#region ../../node_modules/.pnpm/js-yaml@4.2.0/node_modules/js-yaml/dist/js-yaml.mjs
@@ -2333,175 +2334,6 @@ var index_vite_proxy_tmp_default = import_js_yaml.default;
2333
2334
 
2334
2335
  //#endregion
2335
2336
  //#region ../graph-tools/dist/index.mjs
2336
- /**
2337
- * Converts a graph to an adjacency list representation.
2338
- *
2339
- * @example
2340
- * ```ts
2341
- * import { createGraph, toAdjacencyList } from '@statelyai/graph';
2342
- *
2343
- * const graph = createGraph({
2344
- * nodes: { a: {}, b: {}, c: {} },
2345
- * edges: [{ source: 'a', target: 'b' }, { source: 'a', target: 'c' }],
2346
- * });
2347
- *
2348
- * toAdjacencyList(graph);
2349
- * // { a: ['b', 'c'], b: [], c: [] }
2350
- * ```
2351
- */
2352
- function toAdjacencyList(graph) {
2353
- const adj = {};
2354
- for (const node of graph.nodes) adj[node.id] = [];
2355
- for (const edge of graph.edges) {
2356
- adj[edge.sourceId]?.push(edge.targetId);
2357
- if (graph.mode !== "directed") adj[edge.targetId]?.push(edge.sourceId);
2358
- }
2359
- return adj;
2360
- }
2361
- /**
2362
- * Parses an adjacency list into a graph.
2363
- *
2364
- * @example
2365
- * ```ts
2366
- * import { fromAdjacencyList } from '@statelyai/graph';
2367
- *
2368
- * const graph = fromAdjacencyList({
2369
- * a: ['b', 'c'],
2370
- * b: ['c'],
2371
- * c: [],
2372
- * });
2373
- *
2374
- * graph.nodes; // [{id: 'a', ...}, {id: 'b', ...}, {id: 'c', ...}]
2375
- * graph.edges; // [{sourceId: 'a', targetId: 'b', ...}, ...]
2376
- * ```
2377
- */
2378
- function fromAdjacencyList(adj, options) {
2379
- const directed = options?.directed ?? true;
2380
- const seen = /* @__PURE__ */ new Set();
2381
- const nodes = Object.keys(adj).map((id) => ({
2382
- type: "node",
2383
- id,
2384
- parentId: null,
2385
- initialNodeId: null,
2386
- label: "",
2387
- data: void 0
2388
- }));
2389
- const edges = [];
2390
- let edgeIdx = 0;
2391
- for (const [sourceId, targets] of Object.entries(adj)) for (const targetId of targets) {
2392
- const key = directed ? `${sourceId}->${targetId}` : [sourceId, targetId].sort().join("<->");
2393
- if (!seen.has(key)) {
2394
- seen.add(key);
2395
- edges.push({
2396
- type: "edge",
2397
- id: `e${edgeIdx++}`,
2398
- sourceId,
2399
- targetId,
2400
- label: "",
2401
- data: void 0
2402
- });
2403
- }
2404
- }
2405
- return {
2406
- id: options?.id ?? "",
2407
- mode: directed ? "directed" : "undirected",
2408
- initialNodeId: null,
2409
- nodes,
2410
- edges,
2411
- data: void 0
2412
- };
2413
- }
2414
- /**
2415
- * Converts a graph to an edge list of `[source, target]` tuples.
2416
- *
2417
- * @example
2418
- * ```ts
2419
- * import { createGraph, toEdgeList } from '@statelyai/graph';
2420
- *
2421
- * const graph = createGraph({
2422
- * nodes: { a: {}, b: {}, c: {} },
2423
- * edges: [{ source: 'a', target: 'b' }, { source: 'b', target: 'c' }],
2424
- * });
2425
- *
2426
- * toEdgeList(graph);
2427
- * // [['a', 'b'], ['b', 'c']]
2428
- * ```
2429
- */
2430
- function toEdgeList(graph) {
2431
- return graph.edges.map((e) => [e.sourceId, e.targetId]);
2432
- }
2433
- /**
2434
- * Parses an edge list of `[source, target]` tuples into a graph.
2435
- *
2436
- * @example
2437
- * ```ts
2438
- * import { fromEdgeList } from '@statelyai/graph';
2439
- *
2440
- * const graph = fromEdgeList([
2441
- * ['a', 'b'],
2442
- * ['b', 'c'],
2443
- * ]);
2444
- *
2445
- * graph.nodes; // [{id: 'a', ...}, {id: 'b', ...}, {id: 'c', ...}]
2446
- * graph.edges; // [{sourceId: 'a', targetId: 'b', ...}, ...]
2447
- * ```
2448
- */
2449
- function fromEdgeList(edges, options) {
2450
- const directed = options?.directed ?? true;
2451
- const nodeIds = /* @__PURE__ */ new Set();
2452
- for (const [source, target] of edges) {
2453
- nodeIds.add(source);
2454
- nodeIds.add(target);
2455
- }
2456
- const nodes = [...nodeIds].map((id) => ({
2457
- type: "node",
2458
- id,
2459
- parentId: null,
2460
- initialNodeId: null,
2461
- label: "",
2462
- data: void 0
2463
- }));
2464
- const edgeObjects = edges.map(([sourceId, targetId], i) => ({
2465
- type: "edge",
2466
- id: `e${i}`,
2467
- sourceId,
2468
- targetId,
2469
- label: "",
2470
- data: void 0
2471
- }));
2472
- return {
2473
- id: options?.id ?? "",
2474
- mode: directed ? "directed" : "undirected",
2475
- initialNodeId: null,
2476
- nodes,
2477
- edges: edgeObjects,
2478
- data: void 0
2479
- };
2480
- }
2481
- /**
2482
- * Create a `GraphFormatConverter` from a pair of `to`/`from` functions.
2483
- *
2484
- * @example
2485
- * ```ts
2486
- * import { createFormatConverter } from '@statelyai/graph';
2487
- *
2488
- * const yamlConverter = createFormatConverter(
2489
- * (graph) => toYAML(graph),
2490
- * (yaml) => fromYAML(yaml),
2491
- * );
2492
- *
2493
- * const yaml = yamlConverter.to(graph);
2494
- * const graph = yamlConverter.from(yaml);
2495
- * ```
2496
- */
2497
- function createFormatConverter(to, from) {
2498
- return {
2499
- to,
2500
- from
2501
- };
2502
- }
2503
- createFormatConverter(toAdjacencyList, fromAdjacencyList);
2504
- createFormatConverter(toEdgeList, fromEdgeList);
2505
2337
  const LAYOUT_KEYS = {
2506
2338
  node: [
2507
2339
  "x",
@@ -2517,6 +2349,8 @@ const LAYOUT_KEYS = {
2517
2349
  "y",
2518
2350
  "width",
2519
2351
  "height",
2352
+ "points",
2353
+ "routing",
2520
2354
  "style",
2521
2355
  "color"
2522
2356
  ]
@@ -2802,7 +2636,8 @@ function formatEventParam(event) {
2802
2636
  return "undefined";
2803
2637
  }
2804
2638
  function formatStringParam(value) {
2805
- return typeof value === "string" ? `'${value}'` : "undefined";
2639
+ if (typeof value === "string") return `'${value}'`;
2640
+ return isCodeExpression$1(value) ? serializeJS(value) : "undefined";
2806
2641
  }
2807
2642
  function formatInlineObject(value) {
2808
2643
  return `{ ${Object.entries(value).filter(([, item]) => item !== void 0).map(([key, item]) => `${formatObjectKey(key)}: ${serializeJS(item)}`).join(", ")} }`;
@@ -3165,7 +3000,7 @@ function graphToMachineConfig(graph, options = {}) {
3165
3000
  }
3166
3001
  return nodeConfig;
3167
3002
  }
3168
- const rootNode = graph.nodes.find((node) => node.data.parentId === null || node.parentId == null);
3003
+ const rootNode = graph.nodes.find((node) => node.parentId === null || node.parentId == null);
3169
3004
  if (!rootNode) throw new Error("No root node found");
3170
3005
  getNodeConfig(rootNode);
3171
3006
  if (graph.data.context !== void 0 && graph.data.context !== null) config.context = graph.data.context;
@@ -3179,6 +3014,123 @@ const INLINE_EXPRESSION_DIRECTIVE_FIELDS = [
3179
3014
  "initialInput",
3180
3015
  "route"
3181
3016
  ];
3017
+ const EXACT_SEMVER$1 = /^\d+\.\d+\.\d+(?:-[0-9A-Za-z-]+(?:\.[0-9A-Za-z-]+)*)?(?:\+[0-9A-Za-z-]+(?:\.[0-9A-Za-z-]+)*)?$/;
3018
+ function parseProfileSpecifier(specifier) {
3019
+ const separator = specifier.lastIndexOf("@");
3020
+ const name = specifier.slice(0, separator);
3021
+ const version = specifier.slice(separator + 1);
3022
+ if (separator <= 0 || !/^@[^/]+\/[^@/]+$/.test(name) || !version) throw new Error(`Invalid profile specifier: ${specifier}`);
3023
+ return {
3024
+ name,
3025
+ version,
3026
+ kind: EXACT_SEMVER$1.test(version) ? "exact" : "range"
3027
+ };
3028
+ }
3029
+ function normalizeProfileRef(profile) {
3030
+ return profile === "xstate-v5" || profile === "xstate-v6-alpha" ? normalizeMachineProfile(profile) : profile;
3031
+ }
3032
+ /** Stately's semantic projection of the LangGraph 1.x APIs across runtimes. */
3033
+ const LANGGRAPH_PROFILE = "@statelyai/langgraph@1.0.0";
3034
+ const LANGGRAPH_PROFILE_MANIFEST = {
3035
+ profile: LANGGRAPH_PROFILE,
3036
+ name: "LangGraph",
3037
+ description: "LangGraph 1.x graph semantics for Python and JavaScript/TypeScript source.",
3038
+ restrictFormatsToListed: true,
3039
+ authoring: {
3040
+ terminology: {
3041
+ node: "node",
3042
+ edge: "edge",
3043
+ graph: "graph"
3044
+ },
3045
+ nodeTypes: [
3046
+ {
3047
+ kind: "node",
3048
+ label: "Node",
3049
+ description: "Graph API node",
3050
+ authorable: true
3051
+ },
3052
+ {
3053
+ kind: "task",
3054
+ label: "Task",
3055
+ description: "Functional API task",
3056
+ authorable: true
3057
+ },
3058
+ {
3059
+ kind: "entrypoint",
3060
+ label: "Entrypoint",
3061
+ description: "Functional API entrypoint",
3062
+ authorable: true
3063
+ },
3064
+ {
3065
+ kind: "agent",
3066
+ label: "Agent",
3067
+ description: "Prebuilt agent",
3068
+ authorable: true
3069
+ },
3070
+ {
3071
+ kind: "end",
3072
+ label: "END",
3073
+ description: "Terminal sentinel",
3074
+ authorable: true,
3075
+ terminal: true
3076
+ }
3077
+ ],
3078
+ edgeTypes: [
3079
+ {
3080
+ kind: "edge",
3081
+ label: "Edge",
3082
+ description: "Direct route",
3083
+ authorable: true
3084
+ },
3085
+ {
3086
+ kind: "conditional",
3087
+ label: "Conditional edge",
3088
+ description: "Runtime-routed branch",
3089
+ authorable: true
3090
+ },
3091
+ {
3092
+ kind: "call",
3093
+ label: "Call",
3094
+ description: "Functional API call",
3095
+ authorable: true
3096
+ }
3097
+ ],
3098
+ attachments: {},
3099
+ supportsInitialNode: false,
3100
+ supportsTargetlessEdges: false,
3101
+ supportsReenterEdges: false
3102
+ },
3103
+ operations: {
3104
+ simulate: false,
3105
+ validate: false,
3106
+ export: false
3107
+ },
3108
+ formats: [
3109
+ {
3110
+ format: "python",
3111
+ import: true,
3112
+ export: false,
3113
+ sourcePreserving: true
3114
+ },
3115
+ {
3116
+ format: "typescript",
3117
+ import: true,
3118
+ export: false,
3119
+ sourcePreserving: true
3120
+ },
3121
+ {
3122
+ format: "javascript",
3123
+ import: true,
3124
+ export: false,
3125
+ sourcePreserving: true
3126
+ }
3127
+ ],
3128
+ features: {
3129
+ graphApi: true,
3130
+ functionalApi: true,
3131
+ prebuiltAgents: true
3132
+ }
3133
+ };
3182
3134
  const XSTATE_FORMATS = [
3183
3135
  {
3184
3136
  format: "typescript",
@@ -3203,16 +3155,99 @@ const XSTATE_FORMATS = [
3203
3155
  export: true
3204
3156
  }
3205
3157
  ];
3158
+ const XSTATE_AUTHORING = {
3159
+ terminology: {
3160
+ node: "state",
3161
+ edge: "transition",
3162
+ graph: "machine"
3163
+ },
3164
+ nodeTypes: [
3165
+ {
3166
+ kind: "normal",
3167
+ label: "Normal",
3168
+ description: "Basic state",
3169
+ authorable: true,
3170
+ canContain: true
3171
+ },
3172
+ {
3173
+ kind: "parallel",
3174
+ label: "Parallel",
3175
+ description: "Concurrent child states",
3176
+ authorable: true,
3177
+ canContain: true
3178
+ },
3179
+ {
3180
+ kind: "final",
3181
+ label: "Final",
3182
+ description: "Terminal state",
3183
+ authorable: true,
3184
+ terminal: true
3185
+ },
3186
+ {
3187
+ kind: "history",
3188
+ label: "History",
3189
+ description: "Restores previous state",
3190
+ authorable: true
3191
+ },
3192
+ {
3193
+ kind: "choice",
3194
+ label: "Choice",
3195
+ description: "Guarded eventless routing",
3196
+ authorable: true
3197
+ }
3198
+ ],
3199
+ edgeTypes: [{
3200
+ kind: "transition",
3201
+ label: "Transition",
3202
+ authorable: true
3203
+ }],
3204
+ attachments: {
3205
+ actions: true,
3206
+ guards: true,
3207
+ invokes: true,
3208
+ tags: true
3209
+ },
3210
+ supportsInitialNode: true,
3211
+ supportsTargetlessEdges: true,
3212
+ supportsReenterEdges: true
3213
+ };
3206
3214
  const XSTATE_PROFILE_MANIFESTS = [{
3207
3215
  profile: XSTATE_V5_PROFILE,
3208
3216
  name: "XState v5",
3209
- formats: [...XSTATE_FORMATS]
3217
+ formats: [...XSTATE_FORMATS],
3218
+ authoring: XSTATE_AUTHORING,
3219
+ operations: {
3220
+ simulate: true,
3221
+ validate: true,
3222
+ export: true
3223
+ }
3210
3224
  }, {
3211
3225
  profile: XSTATE_V6_PROFILE,
3212
3226
  name: "XState v6",
3213
- formats: [...XSTATE_FORMATS]
3227
+ formats: [...XSTATE_FORMATS],
3228
+ authoring: XSTATE_AUTHORING,
3229
+ operations: {
3230
+ simulate: true,
3231
+ validate: true,
3232
+ export: true
3233
+ }
3214
3234
  }];
3215
- const PROFILE_MANIFESTS = new Map(XSTATE_PROFILE_MANIFESTS.map((manifest) => [manifest.profile, manifest]));
3235
+ const PROFILE_MANIFESTS = new Map([...XSTATE_PROFILE_MANIFESTS, LANGGRAPH_PROFILE_MANIFEST].map((manifest) => [manifest.profile, manifest]));
3236
+ function getProfileManifest(profile) {
3237
+ return PROFILE_MANIFESTS.get(profile);
3238
+ }
3239
+ function isXStateV6ProfileRef(profile) {
3240
+ let current = normalizeProfileRef(profile);
3241
+ const seen = /* @__PURE__ */ new Set();
3242
+ while (!seen.has(current)) {
3243
+ if (isXStateV6Profile(current)) return true;
3244
+ seen.add(current);
3245
+ const parent = getProfileManifest(current)?.extends;
3246
+ if (!parent || parseProfileSpecifier(parent).kind !== "exact") return false;
3247
+ current = parent;
3248
+ }
3249
+ return false;
3250
+ }
3216
3251
  const XSTATE_V6_FN_TRANSITION_META = "@statelyai.xstate.v6.fnTransition";
3217
3252
  const XSTATE_V6_FN_SOURCE_META = "@statelyai.xstate.v6.fnSource";
3218
3253
  function sourceFile(source) {
@@ -3226,7 +3261,193 @@ function unwrapExpression(node) {
3226
3261
  if (ts.isAsExpression(node) || ts.isSatisfiesExpression(node) || ts.isNonNullExpression(node) || ts.isParenthesizedExpression(node)) return unwrapExpression(node.expression);
3227
3262
  return node;
3228
3263
  }
3264
+ function canReplaceIdentifier(node) {
3265
+ const parent = node.parent;
3266
+ if (ts.isPropertyAccessExpression(parent) && parent.name === node) return false;
3267
+ if (ts.isPropertyAssignment(parent) && parent.name === node) return false;
3268
+ if (ts.isMethodDeclaration(parent) && parent.name === node) return false;
3269
+ return true;
3270
+ }
3271
+ function bindingNameContains(name, identifier) {
3272
+ if (ts.isIdentifier(name)) return name.text === identifier;
3273
+ return name.elements.some((element) => ts.isBindingElement(element) && bindingNameContains(element.name, identifier));
3274
+ }
3275
+ function scopeBindsName(node, identifier) {
3276
+ if ((ts.isArrowFunction(node) || ts.isFunctionExpression(node) || ts.isFunctionDeclaration(node)) && node.parameters.some((parameter) => bindingNameContains(parameter.name, identifier))) return true;
3277
+ if (ts.isCatchClause(node) && node.variableDeclaration) return bindingNameContains(node.variableDeclaration.name, identifier);
3278
+ if (ts.isBlock(node)) return node.statements.some((statement) => {
3279
+ if (ts.isVariableStatement(statement)) return statement.declarationList.declarations.some((declaration) => bindingNameContains(declaration.name, identifier));
3280
+ return ts.isFunctionDeclaration(statement) && statement.name?.text === identifier;
3281
+ });
3282
+ if ((ts.isForStatement(node) || ts.isForInStatement(node) || ts.isForOfStatement(node)) && node.initializer && ts.isVariableDeclarationList(node.initializer)) return node.initializer.declarations.some((declaration) => bindingNameContains(declaration.name, identifier));
3283
+ return false;
3284
+ }
3285
+ function isShadowedWithinExpression(node, expression) {
3286
+ let ancestor = node.parent;
3287
+ while (ancestor && ancestor !== expression.parent) {
3288
+ if (scopeBindsName(ancestor, node.text)) return true;
3289
+ ancestor = ancestor.parent;
3290
+ }
3291
+ return false;
3292
+ }
3293
+ function replacementText(node, expression) {
3294
+ if (ts.isShorthandPropertyAssignment(node.parent) && node.parent.name === node) return `${node.text}: (${expression})`;
3295
+ return `(${expression})`;
3296
+ }
3297
+ function isSafeInlineExpression(expression) {
3298
+ let safe = true;
3299
+ function visit(node) {
3300
+ if (ts.isCallExpression(node) || ts.isNewExpression(node) || ts.isAwaitExpression(node) || ts.isYieldExpression(node) || ts.isDeleteExpression(node) || ts.isPostfixUnaryExpression(node) || ts.isPrefixUnaryExpression(node) && (node.operator === ts.SyntaxKind.PlusPlusToken || node.operator === ts.SyntaxKind.MinusMinusToken) || ts.isBinaryExpression(node) && node.operatorToken.kind >= ts.SyntaxKind.FirstAssignment && node.operatorToken.kind <= ts.SyntaxKind.LastAssignment) {
3301
+ safe = false;
3302
+ return;
3303
+ }
3304
+ ts.forEachChild(node, visit);
3305
+ }
3306
+ visit(expression);
3307
+ return safe;
3308
+ }
3309
+ function hasUnsafeVariableInitializer(node) {
3310
+ let unsafe = false;
3311
+ function visit(current) {
3312
+ if (unsafe) return;
3313
+ if (current !== node && (ts.isArrowFunction(current) || ts.isFunctionExpression(current) || ts.isFunctionDeclaration(current))) return;
3314
+ if (ts.isVariableDeclaration(current) && current.initializer && !isSafeInlineExpression(current.initializer)) {
3315
+ unsafe = true;
3316
+ return;
3317
+ }
3318
+ ts.forEachChild(current, visit);
3319
+ }
3320
+ visit(node);
3321
+ return unsafe;
3322
+ }
3323
+ function resolvedExpressionText(expression, bindings, resolving = /* @__PURE__ */ new Set()) {
3324
+ const source = expression.getSourceFile();
3325
+ const start = expression.getStart(source);
3326
+ const replacements = [];
3327
+ function visit(node) {
3328
+ if (ts.isIdentifier(node) && canReplaceIdentifier(node) && !isShadowedWithinExpression(node, expression)) {
3329
+ const binding = bindings.get(node.text);
3330
+ if (binding && !ts.isFunctionDeclaration(binding) && isSafeInlineExpression(binding) && binding !== expression && !resolving.has(node.text)) {
3331
+ const nextResolving = new Set(resolving).add(node.text);
3332
+ replacements.push({
3333
+ start: node.getStart(source) - start,
3334
+ end: node.getEnd() - start,
3335
+ text: replacementText(node, resolvedExpressionText(binding, bindings, nextResolving))
3336
+ });
3337
+ return;
3338
+ }
3339
+ }
3340
+ ts.forEachChild(node, visit);
3341
+ }
3342
+ visit(expression);
3343
+ let result = expression.getText(source);
3344
+ for (const replacement of replacements.sort((a, b) => b.start - a.start)) result = result.slice(0, replacement.start) + replacement.text + result.slice(replacement.end);
3345
+ return result;
3346
+ }
3347
+ function typeNodeToJsonSchema(node) {
3348
+ if (ts.isParenthesizedTypeNode(node)) return typeNodeToJsonSchema(node.type);
3349
+ if (ts.isLiteralTypeNode(node)) {
3350
+ const literal = node.literal;
3351
+ if (ts.isStringLiteral(literal) || ts.isNumericLiteral(literal)) return { const: ts.isNumericLiteral(literal) ? Number(literal.text) : literal.text };
3352
+ if (literal.kind === ts.SyntaxKind.TrueKeyword) return { const: true };
3353
+ if (literal.kind === ts.SyntaxKind.FalseKeyword) return { const: false };
3354
+ return null;
3355
+ }
3356
+ if (ts.isUnionTypeNode(node)) {
3357
+ const members = node.types.map(typeNodeToJsonSchema);
3358
+ if (members.some((member) => !member)) return null;
3359
+ const constants = members.map((member) => member?.const);
3360
+ if (constants.every((value) => value !== void 0)) return { enum: constants };
3361
+ return { anyOf: members };
3362
+ }
3363
+ if (ts.isArrayTypeNode(node)) {
3364
+ const items = typeNodeToJsonSchema(node.elementType);
3365
+ return items ? {
3366
+ type: "array",
3367
+ items
3368
+ } : null;
3369
+ }
3370
+ if (ts.isTupleTypeNode(node)) {
3371
+ const items = node.elements.map((element) => typeNodeToJsonSchema(element));
3372
+ if (items.some((item) => !item)) return null;
3373
+ return {
3374
+ type: "array",
3375
+ items,
3376
+ minItems: items.length,
3377
+ maxItems: items.length
3378
+ };
3379
+ }
3380
+ if (ts.isTypeLiteralNode(node)) {
3381
+ const properties = {};
3382
+ const required = [];
3383
+ for (const member of node.members) {
3384
+ if (!ts.isPropertySignature(member) || !member.type || !member.name) return null;
3385
+ const name = propName(member.name);
3386
+ const schema = typeNodeToJsonSchema(member.type);
3387
+ if (!name || !schema) return null;
3388
+ properties[name] = schema;
3389
+ if (!member.questionToken) required.push(name);
3390
+ }
3391
+ return {
3392
+ type: "object",
3393
+ properties,
3394
+ ...required.length ? { required } : void 0,
3395
+ additionalProperties: false
3396
+ };
3397
+ }
3398
+ switch (node.kind) {
3399
+ case ts.SyntaxKind.StringKeyword: return { type: "string" };
3400
+ case ts.SyntaxKind.NumberKeyword: return { type: "number" };
3401
+ case ts.SyntaxKind.BooleanKeyword: return { type: "boolean" };
3402
+ case ts.SyntaxKind.NullKeyword: return { type: "null" };
3403
+ case ts.SyntaxKind.UnknownKeyword:
3404
+ case ts.SyntaxKind.AnyKeyword: return {};
3405
+ default: return null;
3406
+ }
3407
+ }
3408
+ function typesCallSchema(node) {
3409
+ const value = unwrapExpression(node);
3410
+ if (!ts.isCallExpression(value) || value.expression.getText() !== "types" || value.typeArguments?.length !== 1) return null;
3411
+ return typeNodeToJsonSchema(value.typeArguments[0]);
3412
+ }
3413
+ function schemasObjectToValue(node) {
3414
+ const value = unwrapExpression(node);
3415
+ if (!ts.isObjectLiteralExpression(value)) return null;
3416
+ const result = {};
3417
+ for (const property of value.properties) {
3418
+ if (!ts.isPropertyAssignment(property)) continue;
3419
+ const key = propName(property.name);
3420
+ if (!key) continue;
3421
+ if (key === "events" && ts.isObjectLiteralExpression(property.initializer)) {
3422
+ const events = {};
3423
+ for (const eventProperty of property.initializer.properties) {
3424
+ if (!ts.isPropertyAssignment(eventProperty)) continue;
3425
+ const eventType = propName(eventProperty.name);
3426
+ const schema = typesCallSchema(eventProperty.initializer);
3427
+ if (eventType && schema) events[eventType] = schema;
3428
+ }
3429
+ result.events = events;
3430
+ continue;
3431
+ }
3432
+ const schema = typesCallSchema(property.initializer);
3433
+ if (!schema) continue;
3434
+ result[key] = key === "context" ? schema.properties ?? {} : schema;
3435
+ }
3436
+ return result;
3437
+ }
3229
3438
  function propertyContext(parent, key) {
3439
+ if (parent.setupValue && (key === "actions" || key === "guards" || key === "actors" || key === "delays")) return {
3440
+ v6: parent.v6,
3441
+ implementationMap: true
3442
+ };
3443
+ if (parent.implementationMap) return {
3444
+ v6: parent.v6,
3445
+ implementationValue: true
3446
+ };
3447
+ if (parent.effectArgumentValue) return {
3448
+ v6: parent.v6,
3449
+ effectArgumentValue: true
3450
+ };
3230
3451
  if (parent.invokeValue && key === "src") return {
3231
3452
  v6: parent.v6,
3232
3453
  actorSourceValue: true
@@ -3244,6 +3465,14 @@ function propertyContext(parent, key) {
3244
3465
  assignmentMap: true,
3245
3466
  transitionContext: true
3246
3467
  };
3468
+ if (key === "context") return {
3469
+ v6: parent.v6,
3470
+ machineContextValue: true
3471
+ };
3472
+ if (parent.transitionValue && key === "target") return {
3473
+ v6: parent.v6,
3474
+ targetValue: true
3475
+ };
3247
3476
  if (parent.assignmentMap) return {
3248
3477
  v6: parent.v6,
3249
3478
  assignmentValue: true
@@ -3290,14 +3519,11 @@ function propertyContext(parent, key) {
3290
3519
  };
3291
3520
  return { v6: parent.v6 };
3292
3521
  }
3293
- function fallbackFunctionTransition(fn, actions = []) {
3294
- return {
3295
- ...actions.length ? { actions } : void 0,
3296
- meta: {
3297
- [XSTATE_V6_FN_TRANSITION_META]: true,
3298
- [XSTATE_V6_FN_SOURCE_META]: fn.getText()
3299
- }
3300
- };
3522
+ function fallbackFunctionTransition(fn) {
3523
+ return { meta: {
3524
+ [XSTATE_V6_FN_TRANSITION_META]: true,
3525
+ [XSTATE_V6_FN_SOURCE_META]: fn.getText()
3526
+ } };
3301
3527
  }
3302
3528
  function conditionText(cond) {
3303
3529
  return cond.negated ? `!(${cond.text})` : cond.text;
@@ -3318,7 +3544,7 @@ function hashString(value) {
3318
3544
  return (hash >>> 0).toString(36);
3319
3545
  }
3320
3546
  function inlineGuardCode(params, condition) {
3321
- return `${params} => ${condition}`;
3547
+ return `${params} => ${condition.trimStart().startsWith("{") ? `(${condition})` : condition}`;
3322
3548
  }
3323
3549
  function guardFromConditions(conds, params) {
3324
3550
  const simplified = simplifyConditions(conds);
@@ -3354,7 +3580,7 @@ function transitionFromValue(value, actions) {
3354
3580
  function expressionBranches(expression, bindings, depth) {
3355
3581
  const node = unwrapExpression(expression);
3356
3582
  if (ts.isConditionalExpression(node)) {
3357
- const cond = node.condition.getText();
3583
+ const cond = resolvedExpressionText(node.condition, bindings);
3358
3584
  return [...expressionBranches(node.whenTrue, bindings, depth + 1).map((branch) => ({
3359
3585
  ...branch,
3360
3586
  conds: [{ text: cond }, ...branch.conds]
@@ -3367,7 +3593,7 @@ function expressionBranches(expression, bindings, depth) {
3367
3593
  }))];
3368
3594
  }
3369
3595
  if (ts.isBinaryExpression(node) && (node.operatorToken.kind === ts.SyntaxKind.AmpersandAmpersandToken || node.operatorToken.kind === ts.SyntaxKind.BarBarToken)) {
3370
- const cond = node.left.getText();
3596
+ const cond = resolvedExpressionText(node.left, bindings);
3371
3597
  if (node.operatorToken.kind === ts.SyntaxKind.AmpersandAmpersandToken) return [...expressionBranches(node.right, bindings, depth + 1).map((branch) => ({
3372
3598
  ...branch,
3373
3599
  conds: [{ text: cond }, ...branch.conds]
@@ -3425,7 +3651,7 @@ function expressionStatementAction(statement, enqName, bindings) {
3425
3651
  if (ts.isIdentifier(callee) && callee.text === enqName) return {
3426
3652
  type: "xstate.expr",
3427
3653
  params: {
3428
- code: expression.getText(),
3654
+ code: resolvedExpressionText(expression, bindings),
3429
3655
  lang: "ts"
3430
3656
  }
3431
3657
  };
@@ -3435,7 +3661,7 @@ function expressionStatementAction(statement, enqName, bindings) {
3435
3661
  const args = expression.arguments;
3436
3662
  const value = (index) => {
3437
3663
  const arg = args[index];
3438
- return arg && ts.isExpression(arg) ? expressionToValue(arg, bindings, {}, 0) : void 0;
3664
+ return arg && ts.isExpression(arg) ? expressionToValue(arg, bindings, { effectArgumentValue: true }, 0) : void 0;
3439
3665
  };
3440
3666
  const spreadOpts = (index) => {
3441
3667
  const opts = value(index);
@@ -3524,7 +3750,7 @@ function statementBranches(statements, bindings, enqName, prefixes = [{
3524
3750
  }
3525
3751
  }
3526
3752
  if (ts.isIfStatement(statement)) {
3527
- const cond = statement.expression.getText();
3753
+ const cond = resolvedExpressionText(statement.expression, scopedBindings);
3528
3754
  const thenBranches = statementBranches(ts.isBlock(statement.thenStatement) ? statement.thenStatement.statements : [statement.thenStatement], scopedBindings, enqName, [{
3529
3755
  ...prefix,
3530
3756
  conds: [...prefix.conds, { text: cond }]
@@ -3548,7 +3774,14 @@ function statementBranches(statements, bindings, enqName, prefixes = [{
3548
3774
  continue;
3549
3775
  }
3550
3776
  if (ts.isSwitchStatement(statement)) {
3551
- const expr = statement.expression.getText();
3777
+ if (statement.caseBlock.clauses.some((clause) => clause.statements.length === 0)) {
3778
+ nextOpen.push({
3779
+ ...prefix,
3780
+ unknown: true
3781
+ });
3782
+ continue;
3783
+ }
3784
+ const expr = resolvedExpressionText(statement.expression, scopedBindings);
3552
3785
  const prior = [];
3553
3786
  for (const clause of statement.caseBlock.clauses) {
3554
3787
  const ownCond = ts.isCaseClause(clause) ? { text: `${expr} === ${clause.expression.getText()}` } : null;
@@ -3585,9 +3818,11 @@ function guardParams(fn) {
3585
3818
  return `(${param.getText()})`;
3586
3819
  }
3587
3820
  function normalizeFunctionTransition(fn, bindings, depth) {
3588
- const preservedActions = fn.body && ts.isBlock(fn.body) && fn.body.statements.some((statement) => ts.isExpressionStatement(statement)) ? [enqueueAction(fn)] : [];
3589
- 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) => {
3590
- const transition = transitionFromValue(branch.result, branch.actions.length ? preservedActions : []);
3821
+ if (fn.body && ts.isBlock(fn.body) && hasUnsafeVariableInitializer(fn.body)) return fallbackFunctionTransition(fn);
3822
+ const branches = 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)) : [];
3823
+ if (branches.some((branch) => branch.unknown)) return fallbackFunctionTransition(fn);
3824
+ const transitions = branches.map((branch) => {
3825
+ const transition = transitionFromValue(branch.result, branch.actions);
3591
3826
  if (!transition) return null;
3592
3827
  if (typeof transition === "string") {
3593
3828
  const guard = guardFromConditions(branch.conds, guardParams(fn));
@@ -3604,7 +3839,7 @@ function normalizeFunctionTransition(fn, bindings, depth) {
3604
3839
  }).filter((transition) => Boolean(transition));
3605
3840
  if (transitions.length === 1) return transitions[0];
3606
3841
  if (transitions.length > 1) return transitions;
3607
- return fallbackFunctionTransition(fn, preservedActions);
3842
+ return fallbackFunctionTransition(fn);
3608
3843
  }
3609
3844
  function inlineAction(fn) {
3610
3845
  return {
@@ -3649,11 +3884,24 @@ function objectLiteralToValue(node, bindings, context, depth, overrides = /* @__
3649
3884
  result[key] = overrides.get(key);
3650
3885
  continue;
3651
3886
  }
3887
+ if (context.v6 && key === "schemas" && ts.isPropertyAssignment(property)) {
3888
+ const schemas = schemasObjectToValue(property.initializer);
3889
+ if (schemas) {
3890
+ result[key] = schemas;
3891
+ continue;
3892
+ }
3893
+ }
3652
3894
  if (ts.isShorthandPropertyAssignment(property)) {
3653
- result[key] = expressionToValue(property.name, bindings, propertyContext(context, key), depth + 1);
3895
+ const childContext = propertyContext(context, key);
3896
+ const childValue = expressionToValue(property.name, bindings, childContext, depth + 1);
3897
+ if (childContext.implementationValue && childValue === void 0) continue;
3898
+ result[key] = childValue;
3654
3899
  continue;
3655
3900
  }
3656
- result[key] = expressionToValue(property.initializer, bindings, propertyContext(context, key), depth + 1);
3901
+ const childContext = propertyContext(context, key);
3902
+ const childValue = expressionToValue(property.initializer, bindings, childContext, depth + 1);
3903
+ if (childContext.implementationValue && childValue === void 0) continue;
3904
+ result[key] = childValue;
3657
3905
  }
3658
3906
  if (context.transitionValue && "to" in result) {
3659
3907
  const to = result.to;
@@ -3679,6 +3927,23 @@ function objectLiteralToValue(node, bindings, context, depth, overrides = /* @__
3679
3927
  function expressionToValue(expression, bindings, context = {}, depth = 0) {
3680
3928
  if (depth > 30) return void 0;
3681
3929
  const node = unwrapExpression(expression);
3930
+ if (context.implementationValue) {
3931
+ if (ts.isIdentifier(node)) {
3932
+ const binding = bindings.get(node.text);
3933
+ if (binding) return inlineCodeExpression(ts.isFunctionDeclaration(binding) ? binding.getText() : unwrapExpression(binding).getText());
3934
+ return;
3935
+ }
3936
+ return inlineCodeExpression(node.getText());
3937
+ }
3938
+ if (context.machineContextValue && (ts.isArrowFunction(node) || ts.isFunctionExpression(node))) return inlineCodeExpression(node.getText());
3939
+ if (context.targetValue) {
3940
+ if (ts.isStringLiteral(node) || ts.isNoSubstitutionTemplateLiteral(node)) return node.text;
3941
+ if (ts.isIdentifier(node)) {
3942
+ const binding = bindings.get(node.text);
3943
+ if (binding && !ts.isFunctionDeclaration(binding)) return expressionToValue(binding, bindings, context, depth + 1);
3944
+ }
3945
+ return inlineCodeExpression(resolvedExpressionText(node, bindings));
3946
+ }
3682
3947
  if (context.actorSourceValue) {
3683
3948
  if (ts.isStringLiteral(node) || ts.isNoSubstitutionTemplateLiteral(node)) return node.text;
3684
3949
  if (ts.isIdentifier(node)) {
@@ -3700,6 +3965,10 @@ function expressionToValue(expression, bindings, context = {}, depth = 0) {
3700
3965
  if (node.kind === ts.SyntaxKind.TrueKeyword) return context.ioValue ? inlineCodeExpression("true") : true;
3701
3966
  if (node.kind === ts.SyntaxKind.FalseKeyword) return context.ioValue ? inlineCodeExpression("false") : false;
3702
3967
  if (node.kind === ts.SyntaxKind.NullKeyword) return context.ioValue ? inlineCodeExpression("null") : null;
3968
+ if (context.effectArgumentValue && !ts.isObjectLiteralExpression(node) && !ts.isArrayLiteralExpression(node)) {
3969
+ if (ts.isIdentifier(node) && node.text === "undefined") return void 0;
3970
+ return inlineCodeExpression(resolvedExpressionText(node, bindings));
3971
+ }
3703
3972
  if (context.ioPropertyValue) {
3704
3973
  if (ts.isIdentifier(node) && node.text === "undefined") return void 0;
3705
3974
  if (ts.isIdentifier(node)) {
@@ -3714,7 +3983,7 @@ function expressionToValue(expression, bindings, context = {}, depth = 0) {
3714
3983
  const binding = bindings.get(node.text);
3715
3984
  if (binding && !ts.isFunctionDeclaration(binding)) return expressionToValue(binding, bindings, context, depth + 1);
3716
3985
  }
3717
- return wrapAssignExpression(node.getText());
3986
+ return wrapAssignExpression(resolvedExpressionText(node, bindings));
3718
3987
  }
3719
3988
  if (context.transitionContext && !ts.isObjectLiteralExpression(node)) return inlineCodeExpression(node.getText());
3720
3989
  if (context.ioValue && !ts.isObjectLiteralExpression(node)) return inlineCodeExpression(node.getText());
@@ -3794,10 +4063,20 @@ function isCreateMachineCall(node) {
3794
4063
  if (ts.isPropertyAccessExpression(expression)) return expression.name.text === "createMachine";
3795
4064
  return false;
3796
4065
  }
4066
+ function setupCallForCreateMachine(node, bindings) {
4067
+ if (!ts.isPropertyAccessExpression(node.expression)) return null;
4068
+ let receiver = unwrapExpression(node.expression.expression);
4069
+ if (ts.isIdentifier(receiver)) {
4070
+ const binding = bindings.get(receiver.text);
4071
+ if (binding && !ts.isFunctionDeclaration(binding)) receiver = unwrapExpression(binding);
4072
+ }
4073
+ return ts.isCallExpression(receiver) && ts.isIdentifier(receiver.expression) && receiver.expression.text === "setup" ? receiver : null;
4074
+ }
3797
4075
  function hasV6Syntax(source) {
3798
4076
  const file = sourceFile(source);
3799
4077
  const bindings = collectBindings(file);
3800
4078
  let found = false;
4079
+ const visitedSyntaxBindings = /* @__PURE__ */ new Set();
3801
4080
  function containsFunction(expression, seenBindings = /* @__PURE__ */ new Set()) {
3802
4081
  if (ts.isFunctionDeclaration(expression)) return true;
3803
4082
  const node = unwrapExpression(expression);
@@ -3818,8 +4097,16 @@ function hasV6Syntax(source) {
3818
4097
  if (ts.isCallExpression(node)) return ts.isIdentifier(node.expression) && containsFunction(node.expression, seenBindings) || node.arguments.some((argument) => ts.isExpression(argument) && containsFunction(argument, seenBindings));
3819
4098
  return false;
3820
4099
  }
3821
- function visit(node) {
4100
+ function visitSyntax(node) {
3822
4101
  if (found) return;
4102
+ if (ts.isIdentifier(node)) {
4103
+ const binding = bindings.get(node.text);
4104
+ if (binding && !visitedSyntaxBindings.has(binding)) {
4105
+ visitedSyntaxBindings.add(binding);
4106
+ visitSyntax(binding);
4107
+ }
4108
+ if (found) return;
4109
+ }
3823
4110
  if (ts.isPropertyAssignment(node) && (ts.isIdentifier(node.name) || ts.isStringLiteral(node.name))) {
3824
4111
  const key = node.name.text;
3825
4112
  if (key === "triggers" || key === "internalEvents" || key === "matches" || key === "actorSources" || key === "timeout" || key === "onTimeout" || key === "choice" || key === "route") {
@@ -3831,9 +4118,19 @@ function hasV6Syntax(source) {
3831
4118
  return;
3832
4119
  }
3833
4120
  }
3834
- ts.forEachChild(node, visit);
4121
+ ts.forEachChild(node, visitSyntax);
3835
4122
  }
3836
- visit(file);
4123
+ function visitMachineCalls(node) {
4124
+ if (ts.isCallExpression(node) && isCreateMachineCall(node)) {
4125
+ const config = node.arguments[0];
4126
+ if (config) visitSyntax(config);
4127
+ const setupConfig = setupCallForCreateMachine(node, bindings)?.arguments[0];
4128
+ if (setupConfig) visitSyntax(setupConfig);
4129
+ return;
4130
+ }
4131
+ ts.forEachChild(node, visitMachineCalls);
4132
+ }
4133
+ visitMachineCalls(file);
3837
4134
  return found;
3838
4135
  }
3839
4136
  function detectXStateSourceProfile(source) {
@@ -3861,7 +4158,18 @@ function extractXStateMachineConfigs(source, options = {}) {
3861
4158
  const arg = node.arguments[0];
3862
4159
  if (!arg) return;
3863
4160
  const value = expressionToValue(arg, bindings, { v6: profile === "xstate-v6-alpha" });
3864
- if (value && typeof value === "object" && !Array.isArray(value)) found.push(value);
4161
+ if (value && typeof value === "object" && !Array.isArray(value)) {
4162
+ const setupArg = setupCallForCreateMachine(node, bindings)?.arguments[0];
4163
+ const setupValue = setupArg ? expressionToValue(setupArg, bindings, {
4164
+ v6: profile === "xstate-v6-alpha",
4165
+ setupValue: true
4166
+ }) : null;
4167
+ const setupRecord = setupValue && typeof setupValue === "object" && !Array.isArray(setupValue) ? Object.fromEntries(Object.entries(setupValue).filter(([, item]) => !(item && typeof item === "object" && !Array.isArray(item) && Object.keys(item).length === 0))) : {};
4168
+ found.push({
4169
+ ...setupRecord,
4170
+ ...value
4171
+ });
4172
+ }
3865
4173
  }
3866
4174
  visit(file);
3867
4175
  return found;
@@ -3943,7 +4251,8 @@ function isRequiredProperty(key, def, required) {
3943
4251
  return typeof def === "object" && def !== null && def.required === true;
3944
4252
  }
3945
4253
  function graphToXStateTS(graph, options = {}) {
3946
- const { exportStyle = "named", targetLanguage = "typescript", xstateVersion = 5, ...configOptions } = options;
4254
+ const inferredXStateVersion = isXStateV6ProfileRef(graph.data.profile ?? "xstate-v5") ? 6 : 5;
4255
+ const { exportStyle = "named", targetLanguage = "typescript", xstateVersion = inferredXStateVersion, ...configOptions } = options;
3947
4256
  const schemas = graph.data.schemas;
3948
4257
  const impls = filterInlineImplementations(graph.data.implementations);
3949
4258
  const supportsTypeSyntax = targetLanguage === "typescript";
@@ -3955,12 +4264,14 @@ function graphToXStateTS(graph, options = {}) {
3955
4264
  const hasSetup = hasSchemas || hasActions || hasGuards || hasActors || hasDelays;
3956
4265
  const builtInActions = getUsedBuiltInActions(graph, xstateVersion);
3957
4266
  const actorSourceImports = getActorSourceImports(graph);
4267
+ const implementationImports = getImplementationImports(impls);
3958
4268
  const imports = buildImports({
3959
4269
  hasSetup,
3960
4270
  hasActors,
3961
4271
  actors: impls?.actors ?? [],
3962
4272
  builtInActions,
3963
4273
  actorSourceImports,
4274
+ implementationImports,
3964
4275
  usesTypes: xstateVersion === 6 && supportsTypeSyntax && hasSchemas
3965
4276
  });
3966
4277
  const machineConfig = xstateVersion === 6 ? toV6MachineConfig(graphToMachineConfig(graph, configOptions)) : toV5MachineConfig(graphToMachineConfig(graph, configOptions));
@@ -4041,9 +4352,9 @@ function toV6MachineConfig(machineConfig) {
4041
4352
  return mapV6MachineConfig(machineConfig);
4042
4353
  }
4043
4354
  function mapV6MachineConfig(value, context = {}) {
4355
+ if (context.transitionValue) return toV6TransitionValue(value);
4044
4356
  if (Array.isArray(value)) return value.map((item) => mapV6MachineConfig(item, context));
4045
4357
  if (!value || typeof value !== "object") return value;
4046
- if (context.transitionValue) return toV6TransitionValue(value);
4047
4358
  const result = {};
4048
4359
  for (const [key, item] of Object.entries(value)) {
4049
4360
  if (key === "entry" || key === "exit" || key === "actions") {
@@ -4069,7 +4380,7 @@ function mapV6TransitionMap(value) {
4069
4380
  return result;
4070
4381
  }
4071
4382
  function toV6TransitionValue(value) {
4072
- if (Array.isArray(value)) return value.map((item) => toV6TransitionValue(item));
4383
+ if (Array.isArray(value)) return buildV6TransitionFunction(value) ?? value.map((item) => toV6TransitionValue(item));
4073
4384
  if (!value || typeof value !== "object") return value;
4074
4385
  const transition = value;
4075
4386
  if (transition.guard || transition.description || transition.input !== void 0) return mapV6MachineConfig(transition);
@@ -4086,6 +4397,63 @@ function toV6TransitionValue(value) {
4086
4397
  context
4087
4398
  }) ?? mapV6MachineConfig(transition);
4088
4399
  }
4400
+ function guardCondition(value) {
4401
+ const expression = inlineExpr(value);
4402
+ if (!expression) return value === void 0 ? { condition: "true" } : null;
4403
+ const arrow = expression.indexOf("=>");
4404
+ if (arrow < 0) return null;
4405
+ const params = expression.slice(0, arrow).trim();
4406
+ const body = expression.slice(arrow + 2).trim();
4407
+ if (body.startsWith("{")) return null;
4408
+ return {
4409
+ condition: body,
4410
+ firstParam: params.startsWith("(") && params.endsWith(")") ? params.slice(1, -1).trim() : params
4411
+ };
4412
+ }
4413
+ function buildV6TransitionFunction(transitions) {
4414
+ const branches = [];
4415
+ let authoredFirstParam;
4416
+ for (const item of transitions) {
4417
+ if (!item || typeof item !== "object" || Array.isArray(item)) return;
4418
+ const transition = item;
4419
+ if (transition.description !== void 0 || transition.input !== void 0 || transition.matches !== void 0) return;
4420
+ const guard = guardCondition(transition.guard);
4421
+ if (!guard) return;
4422
+ if (guard.firstParam) {
4423
+ if (authoredFirstParam && authoredFirstParam !== guard.firstParam) return;
4424
+ authoredFirstParam = guard.firstParam;
4425
+ }
4426
+ const actionValue = transition.actions;
4427
+ const effects = (Array.isArray(actionValue) ? actionValue : actionValue === void 0 ? [] : [actionValue]).map(actionToV6Effect);
4428
+ if (effects.some((effect) => !effect)) return;
4429
+ const rendered = renderV6Effects(effects.filter((effect) => Boolean(effect)), transition.context === void 0 ? void 0 : serializeJS(unwrapTemplateExpressions(transition.context)));
4430
+ const returnValue = buildV6TransitionReturnValue({
4431
+ target: typeof transition.target === "string" ? transition.target : void 0,
4432
+ reenter: transition.reenter === true,
4433
+ meta: transition.meta
4434
+ }, rendered.contextValue);
4435
+ if (!returnValue) return;
4436
+ const body = [...rendered.statements.map(formatV6Statement), `return ${returnValue};`];
4437
+ if (body.length === 0) return;
4438
+ if (guard.condition === "true") branches.push(...body.map((line) => ` ${line}`));
4439
+ else {
4440
+ branches.push(` if (${guard.condition}) {`);
4441
+ branches.push(...body.map((line) => ` ${line}`));
4442
+ branches.push(" }");
4443
+ }
4444
+ }
4445
+ if (branches.length === 0) return;
4446
+ const referenced = branches.join("\n");
4447
+ const inferredBindings = [
4448
+ "context",
4449
+ "event",
4450
+ "actions",
4451
+ "children",
4452
+ "self",
4453
+ "system"
4454
+ ].filter((name) => new RegExp(`\\b${name}\\b`).test(referenced));
4455
+ return raw(`(${authoredFirstParam ?? (inferredBindings.length ? `{ ${inferredBindings.join(", ")} }` : "_")}, enq) => {\n${branches.join("\n")}\n}`);
4456
+ }
4089
4457
  function toV6ActionField(actions) {
4090
4458
  if (actions.length === 1) {
4091
4459
  const expr = inlineExpr(actions[0]);
@@ -4096,16 +4464,41 @@ function toV6ActionField(actions) {
4096
4464
  function buildV6ActionFunction(actions, transition) {
4097
4465
  const effects = actions.map(actionToV6Effect);
4098
4466
  if (effects.some((effect) => !effect)) return void 0;
4099
- const statements = effects.flatMap((effect) => effect?.statements ?? []);
4100
- let returnValue;
4101
- let contextValue;
4467
+ const explicitContext = transition?.context === void 0 ? void 0 : serializeJS(unwrapTemplateExpressions(transition.context));
4468
+ const rendered = renderV6Effects(effects.filter((effect) => Boolean(effect)), explicitContext);
4469
+ const statements = rendered.statements;
4470
+ let returnValue = rendered.contextValue ? `{ context: ${rendered.contextValue} }` : void 0;
4471
+ if (transition) returnValue = buildV6TransitionReturnValue(transition, rendered.contextValue);
4472
+ if (statements.length === 0 && !returnValue) return void 0;
4473
+ const referenced = [...statements, returnValue ?? ""].join("\n");
4474
+ const bindings = [
4475
+ "context",
4476
+ "event",
4477
+ "actions",
4478
+ "children",
4479
+ "self",
4480
+ "system"
4481
+ ].filter((name) => new RegExp(`\\b${name}\\b`).test(referenced));
4482
+ return raw(`(${bindings.length ? `{ ${bindings.join(", ")} }` : "_"}, enq) => {\n${[...statements.map((statement) => ` ${formatV6Statement(statement)}`), ...returnValue ? [` return ${returnValue};`] : []].join("\n")}\n}`);
4483
+ }
4484
+ function formatV6Statement(statement) {
4485
+ return statement === "{" || statement === "}" || statement.endsWith(";") ? statement : `${statement};`;
4486
+ }
4487
+ function renderV6Effects(effects, finalContext) {
4488
+ if (!(finalContext !== void 0 || effects.some((effect) => effect.contextValue))) return { statements: effects.flatMap((effect) => effect.statements ?? []) };
4489
+ const statements = ["let nextContext = context"];
4490
+ const inCurrentContext = (statement) => {
4491
+ statements.push("{", " const context = nextContext", ` ${statement}`, "}");
4492
+ };
4102
4493
  for (const effect of effects) {
4103
- returnValue = effect?.returnValue ?? returnValue;
4104
- contextValue = effect?.contextValue ?? contextValue;
4494
+ for (const statement of effect.statements ?? []) inCurrentContext(statement);
4495
+ if (effect.contextValue) inCurrentContext(`nextContext = { ...nextContext, ...(${effect.contextValue}) }`);
4105
4496
  }
4106
- if (transition) returnValue = buildV6TransitionReturnValue(transition, transition.context === void 0 ? contextValue : serializeJS(unwrapTemplateExpressions(transition.context)));
4107
- if (statements.length === 0 && !returnValue) return void 0;
4108
- return raw(`(_, enq) => {\n${[...statements.map((statement) => ` ${statement};`), ...returnValue ? [` return ${returnValue};`] : []].join("\n")}\n}`);
4497
+ if (finalContext !== void 0) inCurrentContext(`nextContext = { ...nextContext, ...(${finalContext}) }`);
4498
+ return {
4499
+ statements,
4500
+ contextValue: "nextContext"
4501
+ };
4109
4502
  }
4110
4503
  function unwrapTemplateExpressions(value) {
4111
4504
  if (typeof value === "string") {
@@ -4153,6 +4546,8 @@ function inlineExpr(value) {
4153
4546
  function actionToV6Effect(action) {
4154
4547
  const expr = inlineExpr(action);
4155
4548
  if (expr) {
4549
+ const assignment = getV6AssignmentContextValue(expr);
4550
+ if (assignment) return { contextValue: assignment };
4156
4551
  if (expr.startsWith("enq(") || expr.startsWith("enq.")) return { statements: [expr] };
4157
4552
  const builtIn = expr.match(/^(raise|emit|sendTo|cancel|log|spawnChild|stopChild)\(([\s\S]*)\)$/);
4158
4553
  if (builtIn) {
@@ -4182,45 +4577,127 @@ function actionToV6Effect(action) {
4182
4577
  return { statements: [`enq.spawn(${serializeJS(params.src)}${options})`] };
4183
4578
  }
4184
4579
  if (type === "xstate.stopChild") return { statements: [`enq.stop(${serializeJS(params.actorRef)})`] };
4185
- if (type === "xstate.assign") {
4186
- const contextValue = serializeJS(params.assignment ?? params);
4187
- return {
4188
- contextValue,
4189
- returnValue: `{ context: ${contextValue} }`
4190
- };
4191
- }
4580
+ if (type === "xstate.assign") return { contextValue: serializeJS(params.assignment ?? params) };
4581
+ if (!type.startsWith("xstate.")) return { statements: [`enq(${/^[A-Za-z_$][A-Za-z0-9_$]*$/.test(type) ? `actions.${type}` : `actions[${serializeJS(type)}]`}${Object.keys(params).length > 0 ? `, ${serializeJS(params)}` : ""})`] };
4192
4582
  return null;
4193
4583
  }
4584
+ function getV6AssignmentArgs(code, includeAll = false) {
4585
+ const entries = [
4586
+ "context",
4587
+ "event",
4588
+ "self",
4589
+ "children",
4590
+ "system"
4591
+ ].filter((name) => includeAll || new RegExp(`\\b${name}\\b`).test(code));
4592
+ if (includeAll || /\bspawn\b/.test(code)) entries.push("spawn: enq.spawn");
4593
+ return `{ ${entries.join(", ")} }`;
4594
+ }
4595
+ function getV6AssignmentContextValue(code) {
4596
+ const parsed = parseSingleExpression(code);
4597
+ const expression = parsed?.expression;
4598
+ if (!expression || !ts.isCallExpression(expression) || !ts.isIdentifier(expression.expression) || expression.expression.text !== "assign" || expression.arguments.length !== 1) return;
4599
+ const [assignment] = expression.arguments;
4600
+ if (!assignment) return;
4601
+ if (ts.isArrowFunction(assignment) || ts.isFunctionExpression(assignment)) {
4602
+ const source = assignment.getText(parsed.source);
4603
+ return `(${source})(${getV6AssignmentArgs(source)})`;
4604
+ }
4605
+ if (!ts.isObjectLiteralExpression(assignment)) return getDynamicV6AssignmentContextValue(assignment.getText(parsed.source));
4606
+ const properties = [];
4607
+ for (const property of assignment.properties) {
4608
+ if (ts.isPropertyAssignment(property)) {
4609
+ const value = property.initializer;
4610
+ const source = value.getText(parsed.source);
4611
+ properties.push(`${property.name.getText(parsed.source)}: ${ts.isArrowFunction(value) || ts.isFunctionExpression(value) ? `(${source})(${getV6AssignmentArgs(source)})` : source}`);
4612
+ continue;
4613
+ }
4614
+ if (ts.isMethodDeclaration(property) && property.body) {
4615
+ const source = property.getText(parsed.source);
4616
+ const params = property.parameters.map((param) => param.getText(parsed.source)).join(", ");
4617
+ properties.push(`${property.name.getText(parsed.source)}: (function (${params}) ${property.body.getText(parsed.source)})(${getV6AssignmentArgs(source)})`);
4618
+ continue;
4619
+ }
4620
+ if (ts.isShorthandPropertyAssignment(property)) {
4621
+ properties.push(property.getText(parsed.source));
4622
+ continue;
4623
+ }
4624
+ return getDynamicV6AssignmentContextValue(assignment.getText(parsed.source));
4625
+ }
4626
+ return `{ ${properties.join(", ")} }`;
4627
+ }
4628
+ function getDynamicV6AssignmentContextValue(assignment) {
4629
+ const args = getV6AssignmentArgs(assignment, true);
4630
+ return `((assignment) => typeof assignment === 'function'
4631
+ ? assignment(${args})
4632
+ : Object.fromEntries(Object.entries(assignment).map(([key, value]) => [
4633
+ key,
4634
+ typeof value === 'function' ? value(${args}) : value,
4635
+ ])))(${assignment})`;
4636
+ }
4194
4637
  function actionOptions(params, consumedKeys) {
4195
4638
  const rest = Object.fromEntries(Object.entries(params).filter(([key, value]) => !consumedKeys.includes(key) && value !== void 0));
4196
4639
  return Object.keys(rest).length ? `, ${serializeJS(rest)}` : "";
4197
4640
  }
4198
- function buildImports({ hasSetup, hasActors, actors, builtInActions, actorSourceImports, usesTypes }) {
4641
+ function buildImports({ hasSetup, hasActors, actors, builtInActions, actorSourceImports, implementationImports, usesTypes }) {
4199
4642
  const xstateImports = [];
4200
4643
  if (hasSetup) xstateImports.push("setup");
4201
4644
  else xstateImports.push("createMachine");
4202
4645
  for (const name of builtInActions) xstateImports.push(name);
4203
4646
  for (const name of actorSourceImports) xstateImports.push(name);
4647
+ for (const name of implementationImports) xstateImports.push(name);
4204
4648
  if (usesTypes) xstateImports.push("types");
4205
4649
  if (hasActors) {
4206
4650
  if (actors.length > 0) xstateImports.push("fromPromise");
4207
4651
  }
4208
4652
  return `import { ${[...new Set(xstateImports)].join(", ")} } from 'xstate';`;
4209
4653
  }
4654
+ const XSTATE_ACTOR_LOGIC_HELPERS = new Set([
4655
+ "createMachine",
4656
+ "createAsyncLogic",
4657
+ "fromPromise",
4658
+ "fromCallback",
4659
+ "fromObservable",
4660
+ "fromEventObservable",
4661
+ "fromTransition"
4662
+ ]);
4663
+ const XSTATE_IMPLEMENTATION_HELPERS = new Set([
4664
+ ...Object.values(BUILTIN_ACTION_IMPORTS),
4665
+ "enqueueActions",
4666
+ "sendParent",
4667
+ "forwardTo",
4668
+ "stop",
4669
+ "and",
4670
+ "or",
4671
+ "not",
4672
+ "stateIn",
4673
+ ...XSTATE_ACTOR_LOGIC_HELPERS
4674
+ ]);
4675
+ function getImplementationImports(impls) {
4676
+ const imports = /* @__PURE__ */ new Set();
4677
+ if (!impls) return imports;
4678
+ for (const implementation of [
4679
+ ...impls.actions,
4680
+ ...impls.guards,
4681
+ ...impls.actors,
4682
+ ...impls.delays
4683
+ ]) {
4684
+ const code = implementation.code?.body;
4685
+ if (!code) continue;
4686
+ const source = ts.createSourceFile("implementation.ts", code, ts.ScriptTarget.Latest, true, ts.ScriptKind.TS);
4687
+ function visit(node) {
4688
+ if (ts.isCallExpression(node) && ts.isIdentifier(node.expression) && XSTATE_IMPLEMENTATION_HELPERS.has(node.expression.text)) imports.add(node.expression.text);
4689
+ ts.forEachChild(node, visit);
4690
+ }
4691
+ visit(source);
4692
+ }
4693
+ return imports;
4694
+ }
4210
4695
  function getActorSourceImports(graph) {
4211
4696
  const imports = /* @__PURE__ */ new Set();
4212
- const candidates = [
4213
- "createAsyncLogic",
4214
- "fromPromise",
4215
- "fromCallback",
4216
- "fromObservable",
4217
- "fromEventObservable",
4218
- "fromTransition"
4219
- ];
4220
4697
  for (const node of graph.nodes) for (const invoke of node.data.invokes ?? []) {
4221
4698
  const expression = invoke.srcExpression?.expr;
4222
4699
  if (!expression) continue;
4223
- for (const candidate of candidates) if (new RegExp(`\\b${candidate}\\b`).test(expression)) imports.add(candidate);
4700
+ for (const candidate of XSTATE_ACTOR_LOGIC_HELPERS) if (new RegExp(`\\b${candidate}\\b`).test(expression)) imports.add(candidate);
4224
4701
  }
4225
4702
  return imports;
4226
4703
  }
@@ -4307,11 +4784,27 @@ function buildGuardsBlock(guards, options) {
4307
4784
  function buildActorsBlock(actors, options) {
4308
4785
  const block = {};
4309
4786
  for (const actor of actors) if (actor.code?.body) {
4787
+ const inlineExpression = getActorLogicExpression(actor.code.body);
4788
+ if (inlineExpression) {
4789
+ block[actor.name] = raw(inlineExpression);
4790
+ continue;
4791
+ }
4792
+ const functionExpression = stripExportDefault(actor.code.body);
4793
+ if (isCompleteFunctionExpression(functionExpression)) {
4794
+ block[actor.name] = raw(`fromPromise(${functionExpression})`);
4795
+ continue;
4796
+ }
4310
4797
  const inputType = options.includeTypeSyntax && hasSchemaProperties(actor.inputSchema) ? `: ${jsonSchemaToTSType(actor.inputSchema)}` : "";
4311
4798
  block[actor.name] = raw(`fromPromise(async ({ input }${inputType ? `: { input${inputType} }` : ""}) => {\n ${dedent(actor.code.body)}\n})`);
4312
4799
  } else block[actor.name] = raw(`fromPromise(async ({ input }) => {\n // TODO: implement ${actor.name}\n})`);
4313
4800
  return block;
4314
4801
  }
4802
+ function getActorLogicExpression(code) {
4803
+ const parsed = parseSingleExpression(stripExportDefault(code));
4804
+ const expression = parsed?.expression;
4805
+ if (!parsed || !expression || !ts.isCallExpression(expression) || !ts.isIdentifier(expression.expression) || !XSTATE_ACTOR_LOGIC_HELPERS.has(expression.expression.text)) return;
4806
+ return parsed.candidate;
4807
+ }
4315
4808
  function buildDelaysBlock(delays) {
4316
4809
  const block = {};
4317
4810
  for (const delay of delays) if (delay.code?.body) {
@@ -4320,6 +4813,11 @@ function buildDelaysBlock(delays) {
4320
4813
  block[delay.name] = raw(inlineExpression);
4321
4814
  continue;
4322
4815
  }
4816
+ const constantExpression = getConstantImplementationExpression(delay.code.body);
4817
+ if (constantExpression) {
4818
+ block[delay.name] = raw(constantExpression);
4819
+ continue;
4820
+ }
4323
4821
  block[delay.name] = raw(`function ({ context, event }) {\n ${dedent(delay.code.body)}\n}`);
4324
4822
  } else block[delay.name] = raw(`function () {\n // TODO: implement ${delay.name}\n return 1000;\n}`);
4325
4823
  return block;
@@ -4336,17 +4834,37 @@ function buildDelaysBlock(delays) {
4336
4834
  function getInlineExpression(code) {
4337
4835
  const stripped = stripExportDefault(code);
4338
4836
  if (stripped !== code.trim()) return stripped;
4339
- return isCompleteFunctionExpression(stripped) ? stripped : void 0;
4837
+ return isCompleteFunctionExpression(stripped) || isCompleteXStateHelperExpression(stripped) ? stripped : void 0;
4340
4838
  }
4341
- /** True when `code` is a single function or arrow-function expression. */
4342
- function isCompleteFunctionExpression(code) {
4839
+ function parseSingleExpression(code) {
4343
4840
  const candidate = code.trim().replace(/;$/, "");
4344
- const source = ts.createSourceFile("impl.ts", `(${candidate})`, ts.ScriptTarget.Latest, false, ts.ScriptKind.TS);
4345
- if ((source.parseDiagnostics ?? []).length > 0 || source.statements.length !== 1) return false;
4841
+ const source = ts.createSourceFile("implementation.ts", `(${candidate})`, ts.ScriptTarget.Latest, false, ts.ScriptKind.TS);
4842
+ if ((source.parseDiagnostics ?? []).length > 0 || source.statements.length !== 1) return;
4346
4843
  const [statement] = source.statements;
4347
- if (!statement || !ts.isExpressionStatement(statement)) return false;
4844
+ if (!statement || !ts.isExpressionStatement(statement)) return;
4348
4845
  let expression = statement.expression;
4349
4846
  if (ts.isParenthesizedExpression(expression)) expression = expression.expression;
4847
+ return {
4848
+ candidate,
4849
+ expression,
4850
+ source
4851
+ };
4852
+ }
4853
+ function getConstantImplementationExpression(code) {
4854
+ const parsed = parseSingleExpression(code);
4855
+ if (!parsed) return;
4856
+ const { candidate, expression } = parsed;
4857
+ if (ts.isStringLiteral(expression) || ts.isNumericLiteral(expression) || ts.isNoSubstitutionTemplateLiteral(expression) || expression.kind === ts.SyntaxKind.TrueKeyword || expression.kind === ts.SyntaxKind.FalseKeyword || expression.kind === ts.SyntaxKind.NullKeyword || ts.isPrefixUnaryExpression(expression) && ts.isNumericLiteral(expression.operand)) return candidate;
4858
+ }
4859
+ function isCompleteXStateHelperExpression(code) {
4860
+ const expression = parseSingleExpression(code)?.expression;
4861
+ if (!expression) return false;
4862
+ return ts.isCallExpression(expression) && ts.isIdentifier(expression.expression) && XSTATE_IMPLEMENTATION_HELPERS.has(expression.expression.text);
4863
+ }
4864
+ /** True when `code` is a single function or arrow-function expression. */
4865
+ function isCompleteFunctionExpression(code) {
4866
+ const expression = parseSingleExpression(code)?.expression;
4867
+ if (!expression) return false;
4350
4868
  return ts.isFunctionExpression(expression) || ts.isArrowFunction(expression);
4351
4869
  }
4352
4870
  const colorSchema = _enum([