@statelyai/sdk 0.20.2 → 0.21.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.
@@ -1,6 +1,5 @@
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";
4
3
  import "xstate/graph";
5
4
 
6
5
  //#region ../../node_modules/.pnpm/js-yaml@4.2.0/node_modules/js-yaml/dist/js-yaml.mjs
@@ -2636,7 +2635,8 @@ function formatEventParam(event) {
2636
2635
  return "undefined";
2637
2636
  }
2638
2637
  function formatStringParam(value) {
2639
- return typeof value === "string" ? `'${value}'` : "undefined";
2638
+ if (typeof value === "string") return `'${value}'`;
2639
+ return isCodeExpression$1(value) ? serializeJS(value) : "undefined";
2640
2640
  }
2641
2641
  function formatInlineObject(value) {
2642
2642
  return `{ ${Object.entries(value).filter(([, item]) => item !== void 0).map(([key, item]) => `${formatObjectKey(key)}: ${serializeJS(item)}`).join(", ")} }`;
@@ -3013,6 +3013,123 @@ const INLINE_EXPRESSION_DIRECTIVE_FIELDS = [
3013
3013
  "initialInput",
3014
3014
  "route"
3015
3015
  ];
3016
+ const EXACT_SEMVER$1 = /^\d+\.\d+\.\d+(?:-[0-9A-Za-z-]+(?:\.[0-9A-Za-z-]+)*)?(?:\+[0-9A-Za-z-]+(?:\.[0-9A-Za-z-]+)*)?$/;
3017
+ function parseProfileSpecifier(specifier) {
3018
+ const separator = specifier.lastIndexOf("@");
3019
+ const name = specifier.slice(0, separator);
3020
+ const version = specifier.slice(separator + 1);
3021
+ if (separator <= 0 || !/^@[^/]+\/[^@/]+$/.test(name) || !version) throw new Error(`Invalid profile specifier: ${specifier}`);
3022
+ return {
3023
+ name,
3024
+ version,
3025
+ kind: EXACT_SEMVER$1.test(version) ? "exact" : "range"
3026
+ };
3027
+ }
3028
+ function normalizeProfileRef(profile) {
3029
+ return profile === "xstate-v5" || profile === "xstate-v6-alpha" ? normalizeMachineProfile(profile) : profile;
3030
+ }
3031
+ /** Stately's semantic projection of the LangGraph 1.x APIs across runtimes. */
3032
+ const LANGGRAPH_PROFILE = "@statelyai/langgraph@1.0.0";
3033
+ const LANGGRAPH_PROFILE_MANIFEST = {
3034
+ profile: LANGGRAPH_PROFILE,
3035
+ name: "LangGraph",
3036
+ description: "LangGraph 1.x graph semantics for Python and JavaScript/TypeScript source.",
3037
+ restrictFormatsToListed: true,
3038
+ authoring: {
3039
+ terminology: {
3040
+ node: "node",
3041
+ edge: "edge",
3042
+ graph: "graph"
3043
+ },
3044
+ nodeTypes: [
3045
+ {
3046
+ kind: "node",
3047
+ label: "Node",
3048
+ description: "Graph API node",
3049
+ authorable: true
3050
+ },
3051
+ {
3052
+ kind: "task",
3053
+ label: "Task",
3054
+ description: "Functional API task",
3055
+ authorable: true
3056
+ },
3057
+ {
3058
+ kind: "entrypoint",
3059
+ label: "Entrypoint",
3060
+ description: "Functional API entrypoint",
3061
+ authorable: true
3062
+ },
3063
+ {
3064
+ kind: "agent",
3065
+ label: "Agent",
3066
+ description: "Prebuilt agent",
3067
+ authorable: true
3068
+ },
3069
+ {
3070
+ kind: "end",
3071
+ label: "END",
3072
+ description: "Terminal sentinel",
3073
+ authorable: true,
3074
+ terminal: true
3075
+ }
3076
+ ],
3077
+ edgeTypes: [
3078
+ {
3079
+ kind: "edge",
3080
+ label: "Edge",
3081
+ description: "Direct route",
3082
+ authorable: true
3083
+ },
3084
+ {
3085
+ kind: "conditional",
3086
+ label: "Conditional edge",
3087
+ description: "Runtime-routed branch",
3088
+ authorable: true
3089
+ },
3090
+ {
3091
+ kind: "call",
3092
+ label: "Call",
3093
+ description: "Functional API call",
3094
+ authorable: true
3095
+ }
3096
+ ],
3097
+ attachments: {},
3098
+ supportsInitialNode: false,
3099
+ supportsTargetlessEdges: false,
3100
+ supportsReenterEdges: false
3101
+ },
3102
+ operations: {
3103
+ simulate: false,
3104
+ validate: false,
3105
+ export: false
3106
+ },
3107
+ formats: [
3108
+ {
3109
+ format: "python",
3110
+ import: true,
3111
+ export: false,
3112
+ sourcePreserving: true
3113
+ },
3114
+ {
3115
+ format: "typescript",
3116
+ import: true,
3117
+ export: false,
3118
+ sourcePreserving: true
3119
+ },
3120
+ {
3121
+ format: "javascript",
3122
+ import: true,
3123
+ export: false,
3124
+ sourcePreserving: true
3125
+ }
3126
+ ],
3127
+ features: {
3128
+ graphApi: true,
3129
+ functionalApi: true,
3130
+ prebuiltAgents: true
3131
+ }
3132
+ };
3016
3133
  const XSTATE_FORMATS = [
3017
3134
  {
3018
3135
  format: "typescript",
@@ -3037,16 +3154,99 @@ const XSTATE_FORMATS = [
3037
3154
  export: true
3038
3155
  }
3039
3156
  ];
3157
+ const XSTATE_AUTHORING = {
3158
+ terminology: {
3159
+ node: "state",
3160
+ edge: "transition",
3161
+ graph: "machine"
3162
+ },
3163
+ nodeTypes: [
3164
+ {
3165
+ kind: "normal",
3166
+ label: "Normal",
3167
+ description: "Basic state",
3168
+ authorable: true,
3169
+ canContain: true
3170
+ },
3171
+ {
3172
+ kind: "parallel",
3173
+ label: "Parallel",
3174
+ description: "Concurrent child states",
3175
+ authorable: true,
3176
+ canContain: true
3177
+ },
3178
+ {
3179
+ kind: "final",
3180
+ label: "Final",
3181
+ description: "Terminal state",
3182
+ authorable: true,
3183
+ terminal: true
3184
+ },
3185
+ {
3186
+ kind: "history",
3187
+ label: "History",
3188
+ description: "Restores previous state",
3189
+ authorable: true
3190
+ },
3191
+ {
3192
+ kind: "choice",
3193
+ label: "Choice",
3194
+ description: "Guarded eventless routing",
3195
+ authorable: true
3196
+ }
3197
+ ],
3198
+ edgeTypes: [{
3199
+ kind: "transition",
3200
+ label: "Transition",
3201
+ authorable: true
3202
+ }],
3203
+ attachments: {
3204
+ actions: true,
3205
+ guards: true,
3206
+ invokes: true,
3207
+ tags: true
3208
+ },
3209
+ supportsInitialNode: true,
3210
+ supportsTargetlessEdges: true,
3211
+ supportsReenterEdges: true
3212
+ };
3040
3213
  const XSTATE_PROFILE_MANIFESTS = [{
3041
3214
  profile: XSTATE_V5_PROFILE,
3042
3215
  name: "XState v5",
3043
- formats: [...XSTATE_FORMATS]
3216
+ formats: [...XSTATE_FORMATS],
3217
+ authoring: XSTATE_AUTHORING,
3218
+ operations: {
3219
+ simulate: true,
3220
+ validate: true,
3221
+ export: true
3222
+ }
3044
3223
  }, {
3045
3224
  profile: XSTATE_V6_PROFILE,
3046
3225
  name: "XState v6",
3047
- formats: [...XSTATE_FORMATS]
3226
+ formats: [...XSTATE_FORMATS],
3227
+ authoring: XSTATE_AUTHORING,
3228
+ operations: {
3229
+ simulate: true,
3230
+ validate: true,
3231
+ export: true
3232
+ }
3048
3233
  }];
3049
- const PROFILE_MANIFESTS = new Map(XSTATE_PROFILE_MANIFESTS.map((manifest) => [manifest.profile, manifest]));
3234
+ const PROFILE_MANIFESTS = new Map([...XSTATE_PROFILE_MANIFESTS, LANGGRAPH_PROFILE_MANIFEST].map((manifest) => [manifest.profile, manifest]));
3235
+ function getProfileManifest(profile) {
3236
+ return PROFILE_MANIFESTS.get(profile);
3237
+ }
3238
+ function isXStateV6ProfileRef(profile) {
3239
+ let current = normalizeProfileRef(profile);
3240
+ const seen = /* @__PURE__ */ new Set();
3241
+ while (!seen.has(current)) {
3242
+ if (isXStateV6Profile(current)) return true;
3243
+ seen.add(current);
3244
+ const parent = getProfileManifest(current)?.extends;
3245
+ if (!parent || parseProfileSpecifier(parent).kind !== "exact") return false;
3246
+ current = parent;
3247
+ }
3248
+ return false;
3249
+ }
3050
3250
  const XSTATE_V6_FN_TRANSITION_META = "@statelyai.xstate.v6.fnTransition";
3051
3251
  const XSTATE_V6_FN_SOURCE_META = "@statelyai.xstate.v6.fnSource";
3052
3252
  function sourceFile(source) {
@@ -3060,7 +3260,193 @@ function unwrapExpression(node) {
3060
3260
  if (ts.isAsExpression(node) || ts.isSatisfiesExpression(node) || ts.isNonNullExpression(node) || ts.isParenthesizedExpression(node)) return unwrapExpression(node.expression);
3061
3261
  return node;
3062
3262
  }
3263
+ function canReplaceIdentifier(node) {
3264
+ const parent = node.parent;
3265
+ if (ts.isPropertyAccessExpression(parent) && parent.name === node) return false;
3266
+ if (ts.isPropertyAssignment(parent) && parent.name === node) return false;
3267
+ if (ts.isMethodDeclaration(parent) && parent.name === node) return false;
3268
+ return true;
3269
+ }
3270
+ function bindingNameContains(name, identifier) {
3271
+ if (ts.isIdentifier(name)) return name.text === identifier;
3272
+ return name.elements.some((element) => ts.isBindingElement(element) && bindingNameContains(element.name, identifier));
3273
+ }
3274
+ function scopeBindsName(node, identifier) {
3275
+ if ((ts.isArrowFunction(node) || ts.isFunctionExpression(node) || ts.isFunctionDeclaration(node)) && node.parameters.some((parameter) => bindingNameContains(parameter.name, identifier))) return true;
3276
+ if (ts.isCatchClause(node) && node.variableDeclaration) return bindingNameContains(node.variableDeclaration.name, identifier);
3277
+ if (ts.isBlock(node)) return node.statements.some((statement) => {
3278
+ if (ts.isVariableStatement(statement)) return statement.declarationList.declarations.some((declaration) => bindingNameContains(declaration.name, identifier));
3279
+ return ts.isFunctionDeclaration(statement) && statement.name?.text === identifier;
3280
+ });
3281
+ 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));
3282
+ return false;
3283
+ }
3284
+ function isShadowedWithinExpression(node, expression) {
3285
+ let ancestor = node.parent;
3286
+ while (ancestor && ancestor !== expression.parent) {
3287
+ if (scopeBindsName(ancestor, node.text)) return true;
3288
+ ancestor = ancestor.parent;
3289
+ }
3290
+ return false;
3291
+ }
3292
+ function replacementText(node, expression) {
3293
+ if (ts.isShorthandPropertyAssignment(node.parent) && node.parent.name === node) return `${node.text}: (${expression})`;
3294
+ return `(${expression})`;
3295
+ }
3296
+ function isSafeInlineExpression(expression) {
3297
+ let safe = true;
3298
+ function visit(node) {
3299
+ 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) {
3300
+ safe = false;
3301
+ return;
3302
+ }
3303
+ ts.forEachChild(node, visit);
3304
+ }
3305
+ visit(expression);
3306
+ return safe;
3307
+ }
3308
+ function hasUnsafeVariableInitializer(node) {
3309
+ let unsafe = false;
3310
+ function visit(current) {
3311
+ if (unsafe) return;
3312
+ if (current !== node && (ts.isArrowFunction(current) || ts.isFunctionExpression(current) || ts.isFunctionDeclaration(current))) return;
3313
+ if (ts.isVariableDeclaration(current) && current.initializer && !isSafeInlineExpression(current.initializer)) {
3314
+ unsafe = true;
3315
+ return;
3316
+ }
3317
+ ts.forEachChild(current, visit);
3318
+ }
3319
+ visit(node);
3320
+ return unsafe;
3321
+ }
3322
+ function resolvedExpressionText(expression, bindings, resolving = /* @__PURE__ */ new Set()) {
3323
+ const source = expression.getSourceFile();
3324
+ const start = expression.getStart(source);
3325
+ const replacements = [];
3326
+ function visit(node) {
3327
+ if (ts.isIdentifier(node) && canReplaceIdentifier(node) && !isShadowedWithinExpression(node, expression)) {
3328
+ const binding = bindings.get(node.text);
3329
+ if (binding && !ts.isFunctionDeclaration(binding) && isSafeInlineExpression(binding) && binding !== expression && !resolving.has(node.text)) {
3330
+ const nextResolving = new Set(resolving).add(node.text);
3331
+ replacements.push({
3332
+ start: node.getStart(source) - start,
3333
+ end: node.getEnd() - start,
3334
+ text: replacementText(node, resolvedExpressionText(binding, bindings, nextResolving))
3335
+ });
3336
+ return;
3337
+ }
3338
+ }
3339
+ ts.forEachChild(node, visit);
3340
+ }
3341
+ visit(expression);
3342
+ let result = expression.getText(source);
3343
+ for (const replacement of replacements.sort((a, b) => b.start - a.start)) result = result.slice(0, replacement.start) + replacement.text + result.slice(replacement.end);
3344
+ return result;
3345
+ }
3346
+ function typeNodeToJsonSchema(node) {
3347
+ if (ts.isParenthesizedTypeNode(node)) return typeNodeToJsonSchema(node.type);
3348
+ if (ts.isLiteralTypeNode(node)) {
3349
+ const literal = node.literal;
3350
+ if (ts.isStringLiteral(literal) || ts.isNumericLiteral(literal)) return { const: ts.isNumericLiteral(literal) ? Number(literal.text) : literal.text };
3351
+ if (literal.kind === ts.SyntaxKind.TrueKeyword) return { const: true };
3352
+ if (literal.kind === ts.SyntaxKind.FalseKeyword) return { const: false };
3353
+ return null;
3354
+ }
3355
+ if (ts.isUnionTypeNode(node)) {
3356
+ const members = node.types.map(typeNodeToJsonSchema);
3357
+ if (members.some((member) => !member)) return null;
3358
+ const constants = members.map((member) => member?.const);
3359
+ if (constants.every((value) => value !== void 0)) return { enum: constants };
3360
+ return { anyOf: members };
3361
+ }
3362
+ if (ts.isArrayTypeNode(node)) {
3363
+ const items = typeNodeToJsonSchema(node.elementType);
3364
+ return items ? {
3365
+ type: "array",
3366
+ items
3367
+ } : null;
3368
+ }
3369
+ if (ts.isTupleTypeNode(node)) {
3370
+ const items = node.elements.map((element) => typeNodeToJsonSchema(element));
3371
+ if (items.some((item) => !item)) return null;
3372
+ return {
3373
+ type: "array",
3374
+ items,
3375
+ minItems: items.length,
3376
+ maxItems: items.length
3377
+ };
3378
+ }
3379
+ if (ts.isTypeLiteralNode(node)) {
3380
+ const properties = {};
3381
+ const required = [];
3382
+ for (const member of node.members) {
3383
+ if (!ts.isPropertySignature(member) || !member.type || !member.name) return null;
3384
+ const name = propName(member.name);
3385
+ const schema = typeNodeToJsonSchema(member.type);
3386
+ if (!name || !schema) return null;
3387
+ properties[name] = schema;
3388
+ if (!member.questionToken) required.push(name);
3389
+ }
3390
+ return {
3391
+ type: "object",
3392
+ properties,
3393
+ ...required.length ? { required } : void 0,
3394
+ additionalProperties: false
3395
+ };
3396
+ }
3397
+ switch (node.kind) {
3398
+ case ts.SyntaxKind.StringKeyword: return { type: "string" };
3399
+ case ts.SyntaxKind.NumberKeyword: return { type: "number" };
3400
+ case ts.SyntaxKind.BooleanKeyword: return { type: "boolean" };
3401
+ case ts.SyntaxKind.NullKeyword: return { type: "null" };
3402
+ case ts.SyntaxKind.UnknownKeyword:
3403
+ case ts.SyntaxKind.AnyKeyword: return {};
3404
+ default: return null;
3405
+ }
3406
+ }
3407
+ function typesCallSchema(node) {
3408
+ const value = unwrapExpression(node);
3409
+ if (!ts.isCallExpression(value) || value.expression.getText() !== "types" || value.typeArguments?.length !== 1) return null;
3410
+ return typeNodeToJsonSchema(value.typeArguments[0]);
3411
+ }
3412
+ function schemasObjectToValue(node) {
3413
+ const value = unwrapExpression(node);
3414
+ if (!ts.isObjectLiteralExpression(value)) return null;
3415
+ const result = {};
3416
+ for (const property of value.properties) {
3417
+ if (!ts.isPropertyAssignment(property)) continue;
3418
+ const key = propName(property.name);
3419
+ if (!key) continue;
3420
+ if (key === "events" && ts.isObjectLiteralExpression(property.initializer)) {
3421
+ const events = {};
3422
+ for (const eventProperty of property.initializer.properties) {
3423
+ if (!ts.isPropertyAssignment(eventProperty)) continue;
3424
+ const eventType = propName(eventProperty.name);
3425
+ const schema = typesCallSchema(eventProperty.initializer);
3426
+ if (eventType && schema) events[eventType] = schema;
3427
+ }
3428
+ result.events = events;
3429
+ continue;
3430
+ }
3431
+ const schema = typesCallSchema(property.initializer);
3432
+ if (!schema) continue;
3433
+ result[key] = key === "context" ? schema.properties ?? {} : schema;
3434
+ }
3435
+ return result;
3436
+ }
3063
3437
  function propertyContext(parent, key) {
3438
+ if (parent.setupValue && (key === "actions" || key === "guards" || key === "actors" || key === "delays")) return {
3439
+ v6: parent.v6,
3440
+ implementationMap: true
3441
+ };
3442
+ if (parent.implementationMap) return {
3443
+ v6: parent.v6,
3444
+ implementationValue: true
3445
+ };
3446
+ if (parent.effectArgumentValue) return {
3447
+ v6: parent.v6,
3448
+ effectArgumentValue: true
3449
+ };
3064
3450
  if (parent.invokeValue && key === "src") return {
3065
3451
  v6: parent.v6,
3066
3452
  actorSourceValue: true
@@ -3078,6 +3464,14 @@ function propertyContext(parent, key) {
3078
3464
  assignmentMap: true,
3079
3465
  transitionContext: true
3080
3466
  };
3467
+ if (key === "context") return {
3468
+ v6: parent.v6,
3469
+ machineContextValue: true
3470
+ };
3471
+ if (parent.transitionValue && key === "target") return {
3472
+ v6: parent.v6,
3473
+ targetValue: true
3474
+ };
3081
3475
  if (parent.assignmentMap) return {
3082
3476
  v6: parent.v6,
3083
3477
  assignmentValue: true
@@ -3124,14 +3518,11 @@ function propertyContext(parent, key) {
3124
3518
  };
3125
3519
  return { v6: parent.v6 };
3126
3520
  }
3127
- function fallbackFunctionTransition(fn, actions = []) {
3128
- return {
3129
- ...actions.length ? { actions } : void 0,
3130
- meta: {
3131
- [XSTATE_V6_FN_TRANSITION_META]: true,
3132
- [XSTATE_V6_FN_SOURCE_META]: fn.getText()
3133
- }
3134
- };
3521
+ function fallbackFunctionTransition(fn) {
3522
+ return { meta: {
3523
+ [XSTATE_V6_FN_TRANSITION_META]: true,
3524
+ [XSTATE_V6_FN_SOURCE_META]: fn.getText()
3525
+ } };
3135
3526
  }
3136
3527
  function conditionText(cond) {
3137
3528
  return cond.negated ? `!(${cond.text})` : cond.text;
@@ -3152,7 +3543,7 @@ function hashString(value) {
3152
3543
  return (hash >>> 0).toString(36);
3153
3544
  }
3154
3545
  function inlineGuardCode(params, condition) {
3155
- return `${params} => ${condition}`;
3546
+ return `${params} => ${condition.trimStart().startsWith("{") ? `(${condition})` : condition}`;
3156
3547
  }
3157
3548
  function guardFromConditions(conds, params) {
3158
3549
  const simplified = simplifyConditions(conds);
@@ -3188,7 +3579,7 @@ function transitionFromValue(value, actions) {
3188
3579
  function expressionBranches(expression, bindings, depth) {
3189
3580
  const node = unwrapExpression(expression);
3190
3581
  if (ts.isConditionalExpression(node)) {
3191
- const cond = node.condition.getText();
3582
+ const cond = resolvedExpressionText(node.condition, bindings);
3192
3583
  return [...expressionBranches(node.whenTrue, bindings, depth + 1).map((branch) => ({
3193
3584
  ...branch,
3194
3585
  conds: [{ text: cond }, ...branch.conds]
@@ -3201,7 +3592,7 @@ function expressionBranches(expression, bindings, depth) {
3201
3592
  }))];
3202
3593
  }
3203
3594
  if (ts.isBinaryExpression(node) && (node.operatorToken.kind === ts.SyntaxKind.AmpersandAmpersandToken || node.operatorToken.kind === ts.SyntaxKind.BarBarToken)) {
3204
- const cond = node.left.getText();
3595
+ const cond = resolvedExpressionText(node.left, bindings);
3205
3596
  if (node.operatorToken.kind === ts.SyntaxKind.AmpersandAmpersandToken) return [...expressionBranches(node.right, bindings, depth + 1).map((branch) => ({
3206
3597
  ...branch,
3207
3598
  conds: [{ text: cond }, ...branch.conds]
@@ -3259,7 +3650,7 @@ function expressionStatementAction(statement, enqName, bindings) {
3259
3650
  if (ts.isIdentifier(callee) && callee.text === enqName) return {
3260
3651
  type: "xstate.expr",
3261
3652
  params: {
3262
- code: expression.getText(),
3653
+ code: resolvedExpressionText(expression, bindings),
3263
3654
  lang: "ts"
3264
3655
  }
3265
3656
  };
@@ -3269,7 +3660,7 @@ function expressionStatementAction(statement, enqName, bindings) {
3269
3660
  const args = expression.arguments;
3270
3661
  const value = (index) => {
3271
3662
  const arg = args[index];
3272
- return arg && ts.isExpression(arg) ? expressionToValue(arg, bindings, {}, 0) : void 0;
3663
+ return arg && ts.isExpression(arg) ? expressionToValue(arg, bindings, { effectArgumentValue: true }, 0) : void 0;
3273
3664
  };
3274
3665
  const spreadOpts = (index) => {
3275
3666
  const opts = value(index);
@@ -3358,7 +3749,7 @@ function statementBranches(statements, bindings, enqName, prefixes = [{
3358
3749
  }
3359
3750
  }
3360
3751
  if (ts.isIfStatement(statement)) {
3361
- const cond = statement.expression.getText();
3752
+ const cond = resolvedExpressionText(statement.expression, scopedBindings);
3362
3753
  const thenBranches = statementBranches(ts.isBlock(statement.thenStatement) ? statement.thenStatement.statements : [statement.thenStatement], scopedBindings, enqName, [{
3363
3754
  ...prefix,
3364
3755
  conds: [...prefix.conds, { text: cond }]
@@ -3382,7 +3773,14 @@ function statementBranches(statements, bindings, enqName, prefixes = [{
3382
3773
  continue;
3383
3774
  }
3384
3775
  if (ts.isSwitchStatement(statement)) {
3385
- const expr = statement.expression.getText();
3776
+ if (statement.caseBlock.clauses.some((clause) => clause.statements.length === 0)) {
3777
+ nextOpen.push({
3778
+ ...prefix,
3779
+ unknown: true
3780
+ });
3781
+ continue;
3782
+ }
3783
+ const expr = resolvedExpressionText(statement.expression, scopedBindings);
3386
3784
  const prior = [];
3387
3785
  for (const clause of statement.caseBlock.clauses) {
3388
3786
  const ownCond = ts.isCaseClause(clause) ? { text: `${expr} === ${clause.expression.getText()}` } : null;
@@ -3419,9 +3817,11 @@ function guardParams(fn) {
3419
3817
  return `(${param.getText()})`;
3420
3818
  }
3421
3819
  function normalizeFunctionTransition(fn, bindings, depth) {
3422
- const preservedActions = fn.body && ts.isBlock(fn.body) && fn.body.statements.some((statement) => ts.isExpressionStatement(statement)) ? [enqueueAction(fn)] : [];
3423
- 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) => {
3424
- const transition = transitionFromValue(branch.result, branch.actions.length ? preservedActions : []);
3820
+ if (fn.body && ts.isBlock(fn.body) && hasUnsafeVariableInitializer(fn.body)) return fallbackFunctionTransition(fn);
3821
+ 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)) : [];
3822
+ if (branches.some((branch) => branch.unknown)) return fallbackFunctionTransition(fn);
3823
+ const transitions = branches.map((branch) => {
3824
+ const transition = transitionFromValue(branch.result, branch.actions);
3425
3825
  if (!transition) return null;
3426
3826
  if (typeof transition === "string") {
3427
3827
  const guard = guardFromConditions(branch.conds, guardParams(fn));
@@ -3438,7 +3838,7 @@ function normalizeFunctionTransition(fn, bindings, depth) {
3438
3838
  }).filter((transition) => Boolean(transition));
3439
3839
  if (transitions.length === 1) return transitions[0];
3440
3840
  if (transitions.length > 1) return transitions;
3441
- return fallbackFunctionTransition(fn, preservedActions);
3841
+ return fallbackFunctionTransition(fn);
3442
3842
  }
3443
3843
  function inlineAction(fn) {
3444
3844
  return {
@@ -3483,11 +3883,24 @@ function objectLiteralToValue(node, bindings, context, depth, overrides = /* @__
3483
3883
  result[key] = overrides.get(key);
3484
3884
  continue;
3485
3885
  }
3886
+ if (context.v6 && key === "schemas" && ts.isPropertyAssignment(property)) {
3887
+ const schemas = schemasObjectToValue(property.initializer);
3888
+ if (schemas) {
3889
+ result[key] = schemas;
3890
+ continue;
3891
+ }
3892
+ }
3486
3893
  if (ts.isShorthandPropertyAssignment(property)) {
3487
- result[key] = expressionToValue(property.name, bindings, propertyContext(context, key), depth + 1);
3894
+ const childContext = propertyContext(context, key);
3895
+ const childValue = expressionToValue(property.name, bindings, childContext, depth + 1);
3896
+ if (childContext.implementationValue && childValue === void 0) continue;
3897
+ result[key] = childValue;
3488
3898
  continue;
3489
3899
  }
3490
- result[key] = expressionToValue(property.initializer, bindings, propertyContext(context, key), depth + 1);
3900
+ const childContext = propertyContext(context, key);
3901
+ const childValue = expressionToValue(property.initializer, bindings, childContext, depth + 1);
3902
+ if (childContext.implementationValue && childValue === void 0) continue;
3903
+ result[key] = childValue;
3491
3904
  }
3492
3905
  if (context.transitionValue && "to" in result) {
3493
3906
  const to = result.to;
@@ -3513,6 +3926,23 @@ function objectLiteralToValue(node, bindings, context, depth, overrides = /* @__
3513
3926
  function expressionToValue(expression, bindings, context = {}, depth = 0) {
3514
3927
  if (depth > 30) return void 0;
3515
3928
  const node = unwrapExpression(expression);
3929
+ if (context.implementationValue) {
3930
+ if (ts.isIdentifier(node)) {
3931
+ const binding = bindings.get(node.text);
3932
+ if (binding) return inlineCodeExpression(ts.isFunctionDeclaration(binding) ? binding.getText() : unwrapExpression(binding).getText());
3933
+ return;
3934
+ }
3935
+ return inlineCodeExpression(node.getText());
3936
+ }
3937
+ if (context.machineContextValue && (ts.isArrowFunction(node) || ts.isFunctionExpression(node))) return inlineCodeExpression(node.getText());
3938
+ if (context.targetValue) {
3939
+ if (ts.isStringLiteral(node) || ts.isNoSubstitutionTemplateLiteral(node)) return node.text;
3940
+ if (ts.isIdentifier(node)) {
3941
+ const binding = bindings.get(node.text);
3942
+ if (binding && !ts.isFunctionDeclaration(binding)) return expressionToValue(binding, bindings, context, depth + 1);
3943
+ }
3944
+ return inlineCodeExpression(resolvedExpressionText(node, bindings));
3945
+ }
3516
3946
  if (context.actorSourceValue) {
3517
3947
  if (ts.isStringLiteral(node) || ts.isNoSubstitutionTemplateLiteral(node)) return node.text;
3518
3948
  if (ts.isIdentifier(node)) {
@@ -3534,6 +3964,10 @@ function expressionToValue(expression, bindings, context = {}, depth = 0) {
3534
3964
  if (node.kind === ts.SyntaxKind.TrueKeyword) return context.ioValue ? inlineCodeExpression("true") : true;
3535
3965
  if (node.kind === ts.SyntaxKind.FalseKeyword) return context.ioValue ? inlineCodeExpression("false") : false;
3536
3966
  if (node.kind === ts.SyntaxKind.NullKeyword) return context.ioValue ? inlineCodeExpression("null") : null;
3967
+ if (context.effectArgumentValue && !ts.isObjectLiteralExpression(node) && !ts.isArrayLiteralExpression(node)) {
3968
+ if (ts.isIdentifier(node) && node.text === "undefined") return void 0;
3969
+ return inlineCodeExpression(resolvedExpressionText(node, bindings));
3970
+ }
3537
3971
  if (context.ioPropertyValue) {
3538
3972
  if (ts.isIdentifier(node) && node.text === "undefined") return void 0;
3539
3973
  if (ts.isIdentifier(node)) {
@@ -3548,7 +3982,7 @@ function expressionToValue(expression, bindings, context = {}, depth = 0) {
3548
3982
  const binding = bindings.get(node.text);
3549
3983
  if (binding && !ts.isFunctionDeclaration(binding)) return expressionToValue(binding, bindings, context, depth + 1);
3550
3984
  }
3551
- return wrapAssignExpression(node.getText());
3985
+ return wrapAssignExpression(resolvedExpressionText(node, bindings));
3552
3986
  }
3553
3987
  if (context.transitionContext && !ts.isObjectLiteralExpression(node)) return inlineCodeExpression(node.getText());
3554
3988
  if (context.ioValue && !ts.isObjectLiteralExpression(node)) return inlineCodeExpression(node.getText());
@@ -3628,10 +4062,20 @@ function isCreateMachineCall(node) {
3628
4062
  if (ts.isPropertyAccessExpression(expression)) return expression.name.text === "createMachine";
3629
4063
  return false;
3630
4064
  }
4065
+ function setupCallForCreateMachine(node, bindings) {
4066
+ if (!ts.isPropertyAccessExpression(node.expression)) return null;
4067
+ let receiver = unwrapExpression(node.expression.expression);
4068
+ if (ts.isIdentifier(receiver)) {
4069
+ const binding = bindings.get(receiver.text);
4070
+ if (binding && !ts.isFunctionDeclaration(binding)) receiver = unwrapExpression(binding);
4071
+ }
4072
+ return ts.isCallExpression(receiver) && ts.isIdentifier(receiver.expression) && receiver.expression.text === "setup" ? receiver : null;
4073
+ }
3631
4074
  function hasV6Syntax(source) {
3632
4075
  const file = sourceFile(source);
3633
4076
  const bindings = collectBindings(file);
3634
4077
  let found = false;
4078
+ const visitedSyntaxBindings = /* @__PURE__ */ new Set();
3635
4079
  function containsFunction(expression, seenBindings = /* @__PURE__ */ new Set()) {
3636
4080
  if (ts.isFunctionDeclaration(expression)) return true;
3637
4081
  const node = unwrapExpression(expression);
@@ -3652,8 +4096,16 @@ function hasV6Syntax(source) {
3652
4096
  if (ts.isCallExpression(node)) return ts.isIdentifier(node.expression) && containsFunction(node.expression, seenBindings) || node.arguments.some((argument) => ts.isExpression(argument) && containsFunction(argument, seenBindings));
3653
4097
  return false;
3654
4098
  }
3655
- function visit(node) {
4099
+ function visitSyntax(node) {
3656
4100
  if (found) return;
4101
+ if (ts.isIdentifier(node)) {
4102
+ const binding = bindings.get(node.text);
4103
+ if (binding && !visitedSyntaxBindings.has(binding)) {
4104
+ visitedSyntaxBindings.add(binding);
4105
+ visitSyntax(binding);
4106
+ }
4107
+ if (found) return;
4108
+ }
3657
4109
  if (ts.isPropertyAssignment(node) && (ts.isIdentifier(node.name) || ts.isStringLiteral(node.name))) {
3658
4110
  const key = node.name.text;
3659
4111
  if (key === "triggers" || key === "internalEvents" || key === "matches" || key === "actorSources" || key === "timeout" || key === "onTimeout" || key === "choice" || key === "route") {
@@ -3665,9 +4117,19 @@ function hasV6Syntax(source) {
3665
4117
  return;
3666
4118
  }
3667
4119
  }
3668
- ts.forEachChild(node, visit);
4120
+ ts.forEachChild(node, visitSyntax);
3669
4121
  }
3670
- visit(file);
4122
+ function visitMachineCalls(node) {
4123
+ if (ts.isCallExpression(node) && isCreateMachineCall(node)) {
4124
+ const config = node.arguments[0];
4125
+ if (config) visitSyntax(config);
4126
+ const setupConfig = setupCallForCreateMachine(node, bindings)?.arguments[0];
4127
+ if (setupConfig) visitSyntax(setupConfig);
4128
+ return;
4129
+ }
4130
+ ts.forEachChild(node, visitMachineCalls);
4131
+ }
4132
+ visitMachineCalls(file);
3671
4133
  return found;
3672
4134
  }
3673
4135
  function detectXStateSourceProfile(source) {
@@ -3695,7 +4157,18 @@ function extractXStateMachineConfigs(source, options = {}) {
3695
4157
  const arg = node.arguments[0];
3696
4158
  if (!arg) return;
3697
4159
  const value = expressionToValue(arg, bindings, { v6: profile === "xstate-v6-alpha" });
3698
- if (value && typeof value === "object" && !Array.isArray(value)) found.push(value);
4160
+ if (value && typeof value === "object" && !Array.isArray(value)) {
4161
+ const setupArg = setupCallForCreateMachine(node, bindings)?.arguments[0];
4162
+ const setupValue = setupArg ? expressionToValue(setupArg, bindings, {
4163
+ v6: profile === "xstate-v6-alpha",
4164
+ setupValue: true
4165
+ }) : null;
4166
+ 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))) : {};
4167
+ found.push({
4168
+ ...setupRecord,
4169
+ ...value
4170
+ });
4171
+ }
3699
4172
  }
3700
4173
  visit(file);
3701
4174
  return found;
@@ -3777,7 +4250,8 @@ function isRequiredProperty(key, def, required) {
3777
4250
  return typeof def === "object" && def !== null && def.required === true;
3778
4251
  }
3779
4252
  function graphToXStateTS(graph, options = {}) {
3780
- const { exportStyle = "named", targetLanguage = "typescript", xstateVersion = 5, ...configOptions } = options;
4253
+ const inferredXStateVersion = isXStateV6ProfileRef(graph.data.profile ?? "xstate-v5") ? 6 : 5;
4254
+ const { exportStyle = "named", targetLanguage = "typescript", xstateVersion = inferredXStateVersion, ...configOptions } = options;
3781
4255
  const schemas = graph.data.schemas;
3782
4256
  const impls = filterInlineImplementations(graph.data.implementations);
3783
4257
  const supportsTypeSyntax = targetLanguage === "typescript";
@@ -3789,12 +4263,14 @@ function graphToXStateTS(graph, options = {}) {
3789
4263
  const hasSetup = hasSchemas || hasActions || hasGuards || hasActors || hasDelays;
3790
4264
  const builtInActions = getUsedBuiltInActions(graph, xstateVersion);
3791
4265
  const actorSourceImports = getActorSourceImports(graph);
4266
+ const implementationImports = getImplementationImports(impls);
3792
4267
  const imports = buildImports({
3793
4268
  hasSetup,
3794
4269
  hasActors,
3795
4270
  actors: impls?.actors ?? [],
3796
4271
  builtInActions,
3797
4272
  actorSourceImports,
4273
+ implementationImports,
3798
4274
  usesTypes: xstateVersion === 6 && supportsTypeSyntax && hasSchemas
3799
4275
  });
3800
4276
  const machineConfig = xstateVersion === 6 ? toV6MachineConfig(graphToMachineConfig(graph, configOptions)) : toV5MachineConfig(graphToMachineConfig(graph, configOptions));
@@ -3875,9 +4351,9 @@ function toV6MachineConfig(machineConfig) {
3875
4351
  return mapV6MachineConfig(machineConfig);
3876
4352
  }
3877
4353
  function mapV6MachineConfig(value, context = {}) {
4354
+ if (context.transitionValue) return toV6TransitionValue(value);
3878
4355
  if (Array.isArray(value)) return value.map((item) => mapV6MachineConfig(item, context));
3879
4356
  if (!value || typeof value !== "object") return value;
3880
- if (context.transitionValue) return toV6TransitionValue(value);
3881
4357
  const result = {};
3882
4358
  for (const [key, item] of Object.entries(value)) {
3883
4359
  if (key === "entry" || key === "exit" || key === "actions") {
@@ -3903,7 +4379,7 @@ function mapV6TransitionMap(value) {
3903
4379
  return result;
3904
4380
  }
3905
4381
  function toV6TransitionValue(value) {
3906
- if (Array.isArray(value)) return value.map((item) => toV6TransitionValue(item));
4382
+ if (Array.isArray(value)) return buildV6TransitionFunction(value) ?? value.map((item) => toV6TransitionValue(item));
3907
4383
  if (!value || typeof value !== "object") return value;
3908
4384
  const transition = value;
3909
4385
  if (transition.guard || transition.description || transition.input !== void 0) return mapV6MachineConfig(transition);
@@ -3920,6 +4396,148 @@ function toV6TransitionValue(value) {
3920
4396
  context
3921
4397
  }) ?? mapV6MachineConfig(transition);
3922
4398
  }
4399
+ function guardCondition(value) {
4400
+ const expression = inlineExpr(value);
4401
+ if (!expression) return value === void 0 ? { condition: "true" } : null;
4402
+ const arrow = expression.indexOf("=>");
4403
+ if (arrow < 0) return null;
4404
+ const params = expression.slice(0, arrow).trim();
4405
+ const body = expression.slice(arrow + 2).trim();
4406
+ if (body.startsWith("{")) return null;
4407
+ return {
4408
+ condition: body,
4409
+ firstParam: params.startsWith("(") && params.endsWith(")") ? params.slice(1, -1).trim() : params
4410
+ };
4411
+ }
4412
+ const V6_ARG_BINDINGS = [
4413
+ "context",
4414
+ "event",
4415
+ "actions",
4416
+ "children",
4417
+ "self",
4418
+ "system"
4419
+ ];
4420
+ const V6_IDENTIFIER = /^[A-Za-z_$][A-Za-z0-9_$]*$/;
4421
+ function inferV6ArgBindings(code) {
4422
+ return V6_ARG_BINDINGS.filter((name) => new RegExp(`\\b${name}\\b`).test(code));
4423
+ }
4424
+ /** Splits a destructuring pattern body on its top-level commas. */
4425
+ function splitV6PatternEntries(body) {
4426
+ const entries = [];
4427
+ let depth = 0;
4428
+ let start = 0;
4429
+ let quote;
4430
+ for (let index = 0; index < body.length; index++) {
4431
+ const char = body[index];
4432
+ if (quote) {
4433
+ if (char === "\\") index++;
4434
+ else if (char === quote) quote = void 0;
4435
+ continue;
4436
+ }
4437
+ if (char === "\"" || char === "'" || char === "`") quote = char;
4438
+ else if (char === "{" || char === "[" || char === "(") depth++;
4439
+ else if (char === "}" || char === "]" || char === ")") {
4440
+ depth--;
4441
+ if (depth < 0) return void 0;
4442
+ } else if (char === "," && depth === 0) {
4443
+ entries.push(body.slice(start, index));
4444
+ start = index + 1;
4445
+ }
4446
+ }
4447
+ if (depth !== 0 || quote) return void 0;
4448
+ entries.push(body.slice(start));
4449
+ return entries.map((entry) => entry.trim()).filter(Boolean);
4450
+ }
4451
+ /** Local name a destructuring entry binds, or `undefined` if not a plain one. */
4452
+ function getV6PatternBinding(entry) {
4453
+ const colon = entry.indexOf(":");
4454
+ const name = (colon < 0 ? entry : entry.slice(colon + 1)).split("=")[0].trim();
4455
+ return V6_IDENTIFIER.test(name) ? name : void 0;
4456
+ }
4457
+ /**
4458
+ * Unions the bindings referenced by generated code into the parameter authored
4459
+ * on a guard, so a collapsed transition function never references unbound
4460
+ * variables. Returns `undefined` when the authored parameter cannot be
4461
+ * extended safely, in which case the transition array is kept as-is.
4462
+ */
4463
+ function mergeV6FirstParam(authoredFirstParam, inferred) {
4464
+ if (!authoredFirstParam) return {
4465
+ firstParam: inferred.length ? `{ ${inferred.join(", ")} }` : "_",
4466
+ prelude: []
4467
+ };
4468
+ if (inferred.length === 0) return {
4469
+ firstParam: authoredFirstParam,
4470
+ prelude: []
4471
+ };
4472
+ if (V6_IDENTIFIER.test(authoredFirstParam)) {
4473
+ if (inferred.includes(authoredFirstParam)) return void 0;
4474
+ return {
4475
+ firstParam: authoredFirstParam,
4476
+ prelude: [`const { ${inferred.join(", ")} } = ${authoredFirstParam};`]
4477
+ };
4478
+ }
4479
+ if (!authoredFirstParam.startsWith("{") || !authoredFirstParam.endsWith("}")) return;
4480
+ const entries = splitV6PatternEntries(authoredFirstParam.slice(1, -1));
4481
+ if (!entries) return void 0;
4482
+ const bound = new Set(entries.map(getV6PatternBinding).filter((name) => name !== void 0));
4483
+ const missing = inferred.filter((name) => !bound.has(name));
4484
+ if (missing.length === 0) return {
4485
+ firstParam: authoredFirstParam,
4486
+ prelude: []
4487
+ };
4488
+ const restIndex = entries.findIndex((entry) => entry.startsWith("..."));
4489
+ return {
4490
+ firstParam: `{ ${(restIndex < 0 ? [...entries, ...missing] : [
4491
+ ...entries.slice(0, restIndex),
4492
+ ...missing,
4493
+ ...entries.slice(restIndex)
4494
+ ]).join(", ")} }`,
4495
+ prelude: []
4496
+ };
4497
+ }
4498
+ function buildV6TransitionFunction(transitions) {
4499
+ const branches = [];
4500
+ let authoredFirstParam;
4501
+ for (const item of transitions) {
4502
+ if (!item || typeof item !== "object" || Array.isArray(item)) return;
4503
+ const transition = item;
4504
+ if (transition.description !== void 0 || transition.input !== void 0 || transition.matches !== void 0) return;
4505
+ const guard = guardCondition(transition.guard);
4506
+ if (!guard) return;
4507
+ if (guard.firstParam) {
4508
+ if (authoredFirstParam && authoredFirstParam !== guard.firstParam) return;
4509
+ authoredFirstParam = guard.firstParam;
4510
+ }
4511
+ const actionValue = transition.actions;
4512
+ const effects = (Array.isArray(actionValue) ? actionValue : actionValue === void 0 ? [] : [actionValue]).map(actionToV6Effect);
4513
+ if (effects.some((effect) => !effect)) return;
4514
+ const rendered = renderV6Effects(effects.filter((effect) => Boolean(effect)), transition.context === void 0 ? void 0 : serializeJS(unwrapTemplateExpressions(transition.context)));
4515
+ const returnValue = buildV6TransitionReturnValue({
4516
+ target: typeof transition.target === "string" ? transition.target : void 0,
4517
+ reenter: transition.reenter === true,
4518
+ meta: transition.meta
4519
+ }, rendered.contextValue);
4520
+ if (!returnValue) return;
4521
+ const body = [...rendered.statements.map(formatV6Statement), `return ${returnValue};`];
4522
+ if (body.length === 0) return;
4523
+ branches.push({
4524
+ condition: guard.condition,
4525
+ body
4526
+ });
4527
+ }
4528
+ if (branches.length === 0) return;
4529
+ const generated = branches.flatMap((branch) => branch.body).join("\n");
4530
+ const merged = mergeV6FirstParam(authoredFirstParam, inferV6ArgBindings(generated));
4531
+ if (!merged) return;
4532
+ const lines = merged.prelude.map((statement) => ` ${statement}`);
4533
+ for (const branch of branches) if (branch.condition === "true") lines.push(...branch.body.map((line) => ` ${line}`));
4534
+ else {
4535
+ lines.push(` if (${branch.condition}) {`);
4536
+ lines.push(...branch.body.map((line) => ` ${line}`));
4537
+ lines.push(" }");
4538
+ }
4539
+ return raw(`(${merged.firstParam}, enq) => {\n${lines.join("\n")}\n}`);
4540
+ }
3923
4541
  function toV6ActionField(actions) {
3924
4542
  if (actions.length === 1) {
3925
4543
  const expr = inlineExpr(actions[0]);
@@ -3930,16 +4548,33 @@ function toV6ActionField(actions) {
3930
4548
  function buildV6ActionFunction(actions, transition) {
3931
4549
  const effects = actions.map(actionToV6Effect);
3932
4550
  if (effects.some((effect) => !effect)) return void 0;
3933
- const statements = effects.flatMap((effect) => effect?.statements ?? []);
3934
- let returnValue;
3935
- let contextValue;
4551
+ const explicitContext = transition?.context === void 0 ? void 0 : serializeJS(unwrapTemplateExpressions(transition.context));
4552
+ const rendered = renderV6Effects(effects.filter((effect) => Boolean(effect)), explicitContext);
4553
+ const statements = rendered.statements;
4554
+ let returnValue = rendered.contextValue ? `{ context: ${rendered.contextValue} }` : void 0;
4555
+ if (transition) returnValue = buildV6TransitionReturnValue(transition, rendered.contextValue);
4556
+ if (statements.length === 0 && !returnValue) return void 0;
4557
+ const bindings = inferV6ArgBindings([...statements, returnValue ?? ""].join("\n"));
4558
+ return raw(`(${bindings.length ? `{ ${bindings.join(", ")} }` : "_"}, enq) => {\n${[...statements.map((statement) => ` ${formatV6Statement(statement)}`), ...returnValue ? [` return ${returnValue};`] : []].join("\n")}\n}`);
4559
+ }
4560
+ function formatV6Statement(statement) {
4561
+ return statement === "{" || statement === "}" || statement.endsWith(";") ? statement : `${statement};`;
4562
+ }
4563
+ function renderV6Effects(effects, finalContext) {
4564
+ if (!(finalContext !== void 0 || effects.some((effect) => effect.contextValue))) return { statements: effects.flatMap((effect) => effect.statements ?? []) };
4565
+ const statements = ["let nextContext = context"];
4566
+ const inCurrentContext = (statement) => {
4567
+ statements.push("{", " const context = nextContext", ` ${statement}`, "}");
4568
+ };
3936
4569
  for (const effect of effects) {
3937
- returnValue = effect?.returnValue ?? returnValue;
3938
- contextValue = effect?.contextValue ?? contextValue;
4570
+ for (const statement of effect.statements ?? []) inCurrentContext(statement);
4571
+ if (effect.contextValue) inCurrentContext(`nextContext = { ...nextContext, ...(${effect.contextValue}) }`);
3939
4572
  }
3940
- if (transition) returnValue = buildV6TransitionReturnValue(transition, transition.context === void 0 ? contextValue : serializeJS(unwrapTemplateExpressions(transition.context)));
3941
- if (statements.length === 0 && !returnValue) return void 0;
3942
- return raw(`(_, enq) => {\n${[...statements.map((statement) => ` ${statement};`), ...returnValue ? [` return ${returnValue};`] : []].join("\n")}\n}`);
4573
+ if (finalContext !== void 0) inCurrentContext(`nextContext = { ...nextContext, ...(${finalContext}) }`);
4574
+ return {
4575
+ statements,
4576
+ contextValue: "nextContext"
4577
+ };
3943
4578
  }
3944
4579
  function unwrapTemplateExpressions(value) {
3945
4580
  if (typeof value === "string") {
@@ -3987,6 +4622,8 @@ function inlineExpr(value) {
3987
4622
  function actionToV6Effect(action) {
3988
4623
  const expr = inlineExpr(action);
3989
4624
  if (expr) {
4625
+ const assignment = getV6AssignmentContextValue(expr);
4626
+ if (assignment) return { contextValue: assignment };
3990
4627
  if (expr.startsWith("enq(") || expr.startsWith("enq.")) return { statements: [expr] };
3991
4628
  const builtIn = expr.match(/^(raise|emit|sendTo|cancel|log|spawnChild|stopChild)\(([\s\S]*)\)$/);
3992
4629
  if (builtIn) {
@@ -4016,45 +4653,127 @@ function actionToV6Effect(action) {
4016
4653
  return { statements: [`enq.spawn(${serializeJS(params.src)}${options})`] };
4017
4654
  }
4018
4655
  if (type === "xstate.stopChild") return { statements: [`enq.stop(${serializeJS(params.actorRef)})`] };
4019
- if (type === "xstate.assign") {
4020
- const contextValue = serializeJS(params.assignment ?? params);
4021
- return {
4022
- contextValue,
4023
- returnValue: `{ context: ${contextValue} }`
4024
- };
4025
- }
4656
+ if (type === "xstate.assign") return { contextValue: serializeJS(params.assignment ?? params) };
4657
+ 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)}` : ""})`] };
4026
4658
  return null;
4027
4659
  }
4660
+ function getV6AssignmentArgs(code, includeAll = false) {
4661
+ const entries = [
4662
+ "context",
4663
+ "event",
4664
+ "self",
4665
+ "children",
4666
+ "system"
4667
+ ].filter((name) => includeAll || new RegExp(`\\b${name}\\b`).test(code));
4668
+ if (includeAll || /\bspawn\b/.test(code)) entries.push("spawn: enq.spawn");
4669
+ return `{ ${entries.join(", ")} }`;
4670
+ }
4671
+ function getV6AssignmentContextValue(code) {
4672
+ const parsed = parseSingleExpression(code);
4673
+ const expression = parsed?.expression;
4674
+ if (!expression || !ts.isCallExpression(expression) || !ts.isIdentifier(expression.expression) || expression.expression.text !== "assign" || expression.arguments.length !== 1) return;
4675
+ const [assignment] = expression.arguments;
4676
+ if (!assignment) return;
4677
+ if (ts.isArrowFunction(assignment) || ts.isFunctionExpression(assignment)) {
4678
+ const source = assignment.getText(parsed.source);
4679
+ return `(${source})(${getV6AssignmentArgs(source)})`;
4680
+ }
4681
+ if (!ts.isObjectLiteralExpression(assignment)) return getDynamicV6AssignmentContextValue(assignment.getText(parsed.source));
4682
+ const properties = [];
4683
+ for (const property of assignment.properties) {
4684
+ if (ts.isPropertyAssignment(property)) {
4685
+ const value = property.initializer;
4686
+ const source = value.getText(parsed.source);
4687
+ properties.push(`${property.name.getText(parsed.source)}: ${ts.isArrowFunction(value) || ts.isFunctionExpression(value) ? `(${source})(${getV6AssignmentArgs(source)})` : source}`);
4688
+ continue;
4689
+ }
4690
+ if (ts.isMethodDeclaration(property) && property.body) {
4691
+ const source = property.getText(parsed.source);
4692
+ const params = property.parameters.map((param) => param.getText(parsed.source)).join(", ");
4693
+ properties.push(`${property.name.getText(parsed.source)}: (function (${params}) ${property.body.getText(parsed.source)})(${getV6AssignmentArgs(source)})`);
4694
+ continue;
4695
+ }
4696
+ if (ts.isShorthandPropertyAssignment(property)) {
4697
+ properties.push(property.getText(parsed.source));
4698
+ continue;
4699
+ }
4700
+ return getDynamicV6AssignmentContextValue(assignment.getText(parsed.source));
4701
+ }
4702
+ return `{ ${properties.join(", ")} }`;
4703
+ }
4704
+ function getDynamicV6AssignmentContextValue(assignment) {
4705
+ const args = getV6AssignmentArgs(assignment, true);
4706
+ return `((assignment) => typeof assignment === 'function'
4707
+ ? assignment(${args})
4708
+ : Object.fromEntries(Object.entries(assignment).map(([key, value]) => [
4709
+ key,
4710
+ typeof value === 'function' ? value(${args}) : value,
4711
+ ])))(${assignment})`;
4712
+ }
4028
4713
  function actionOptions(params, consumedKeys) {
4029
4714
  const rest = Object.fromEntries(Object.entries(params).filter(([key, value]) => !consumedKeys.includes(key) && value !== void 0));
4030
4715
  return Object.keys(rest).length ? `, ${serializeJS(rest)}` : "";
4031
4716
  }
4032
- function buildImports({ hasSetup, hasActors, actors, builtInActions, actorSourceImports, usesTypes }) {
4717
+ function buildImports({ hasSetup, hasActors, actors, builtInActions, actorSourceImports, implementationImports, usesTypes }) {
4033
4718
  const xstateImports = [];
4034
4719
  if (hasSetup) xstateImports.push("setup");
4035
4720
  else xstateImports.push("createMachine");
4036
4721
  for (const name of builtInActions) xstateImports.push(name);
4037
4722
  for (const name of actorSourceImports) xstateImports.push(name);
4723
+ for (const name of implementationImports) xstateImports.push(name);
4038
4724
  if (usesTypes) xstateImports.push("types");
4039
4725
  if (hasActors) {
4040
4726
  if (actors.length > 0) xstateImports.push("fromPromise");
4041
4727
  }
4042
4728
  return `import { ${[...new Set(xstateImports)].join(", ")} } from 'xstate';`;
4043
4729
  }
4730
+ const XSTATE_ACTOR_LOGIC_HELPERS = new Set([
4731
+ "createMachine",
4732
+ "createAsyncLogic",
4733
+ "fromPromise",
4734
+ "fromCallback",
4735
+ "fromObservable",
4736
+ "fromEventObservable",
4737
+ "fromTransition"
4738
+ ]);
4739
+ const XSTATE_IMPLEMENTATION_HELPERS = new Set([
4740
+ ...Object.values(BUILTIN_ACTION_IMPORTS),
4741
+ "enqueueActions",
4742
+ "sendParent",
4743
+ "forwardTo",
4744
+ "stop",
4745
+ "and",
4746
+ "or",
4747
+ "not",
4748
+ "stateIn",
4749
+ ...XSTATE_ACTOR_LOGIC_HELPERS
4750
+ ]);
4751
+ function getImplementationImports(impls) {
4752
+ const imports = /* @__PURE__ */ new Set();
4753
+ if (!impls) return imports;
4754
+ for (const implementation of [
4755
+ ...impls.actions,
4756
+ ...impls.guards,
4757
+ ...impls.actors,
4758
+ ...impls.delays
4759
+ ]) {
4760
+ const code = implementation.code?.body;
4761
+ if (!code) continue;
4762
+ const source = ts.createSourceFile("implementation.ts", code, ts.ScriptTarget.Latest, true, ts.ScriptKind.TS);
4763
+ function visit(node) {
4764
+ if (ts.isCallExpression(node) && ts.isIdentifier(node.expression) && XSTATE_IMPLEMENTATION_HELPERS.has(node.expression.text)) imports.add(node.expression.text);
4765
+ ts.forEachChild(node, visit);
4766
+ }
4767
+ visit(source);
4768
+ }
4769
+ return imports;
4770
+ }
4044
4771
  function getActorSourceImports(graph) {
4045
4772
  const imports = /* @__PURE__ */ new Set();
4046
- const candidates = [
4047
- "createAsyncLogic",
4048
- "fromPromise",
4049
- "fromCallback",
4050
- "fromObservable",
4051
- "fromEventObservable",
4052
- "fromTransition"
4053
- ];
4054
4773
  for (const node of graph.nodes) for (const invoke of node.data.invokes ?? []) {
4055
4774
  const expression = invoke.srcExpression?.expr;
4056
4775
  if (!expression) continue;
4057
- for (const candidate of candidates) if (new RegExp(`\\b${candidate}\\b`).test(expression)) imports.add(candidate);
4776
+ for (const candidate of XSTATE_ACTOR_LOGIC_HELPERS) if (new RegExp(`\\b${candidate}\\b`).test(expression)) imports.add(candidate);
4058
4777
  }
4059
4778
  return imports;
4060
4779
  }
@@ -4141,11 +4860,27 @@ function buildGuardsBlock(guards, options) {
4141
4860
  function buildActorsBlock(actors, options) {
4142
4861
  const block = {};
4143
4862
  for (const actor of actors) if (actor.code?.body) {
4863
+ const inlineExpression = getActorLogicExpression(actor.code.body);
4864
+ if (inlineExpression) {
4865
+ block[actor.name] = raw(inlineExpression);
4866
+ continue;
4867
+ }
4868
+ const functionExpression = stripExportDefault(actor.code.body);
4869
+ if (isCompleteFunctionExpression(functionExpression)) {
4870
+ block[actor.name] = raw(`fromPromise(${functionExpression})`);
4871
+ continue;
4872
+ }
4144
4873
  const inputType = options.includeTypeSyntax && hasSchemaProperties(actor.inputSchema) ? `: ${jsonSchemaToTSType(actor.inputSchema)}` : "";
4145
4874
  block[actor.name] = raw(`fromPromise(async ({ input }${inputType ? `: { input${inputType} }` : ""}) => {\n ${dedent(actor.code.body)}\n})`);
4146
4875
  } else block[actor.name] = raw(`fromPromise(async ({ input }) => {\n // TODO: implement ${actor.name}\n})`);
4147
4876
  return block;
4148
4877
  }
4878
+ function getActorLogicExpression(code) {
4879
+ const parsed = parseSingleExpression(stripExportDefault(code));
4880
+ const expression = parsed?.expression;
4881
+ if (!parsed || !expression || !ts.isCallExpression(expression) || !ts.isIdentifier(expression.expression) || !XSTATE_ACTOR_LOGIC_HELPERS.has(expression.expression.text)) return;
4882
+ return parsed.candidate;
4883
+ }
4149
4884
  function buildDelaysBlock(delays) {
4150
4885
  const block = {};
4151
4886
  for (const delay of delays) if (delay.code?.body) {
@@ -4154,6 +4889,11 @@ function buildDelaysBlock(delays) {
4154
4889
  block[delay.name] = raw(inlineExpression);
4155
4890
  continue;
4156
4891
  }
4892
+ const constantExpression = getConstantImplementationExpression(delay.code.body);
4893
+ if (constantExpression) {
4894
+ block[delay.name] = raw(constantExpression);
4895
+ continue;
4896
+ }
4157
4897
  block[delay.name] = raw(`function ({ context, event }) {\n ${dedent(delay.code.body)}\n}`);
4158
4898
  } else block[delay.name] = raw(`function () {\n // TODO: implement ${delay.name}\n return 1000;\n}`);
4159
4899
  return block;
@@ -4170,17 +4910,37 @@ function buildDelaysBlock(delays) {
4170
4910
  function getInlineExpression(code) {
4171
4911
  const stripped = stripExportDefault(code);
4172
4912
  if (stripped !== code.trim()) return stripped;
4173
- return isCompleteFunctionExpression(stripped) ? stripped : void 0;
4913
+ return isCompleteFunctionExpression(stripped) || isCompleteXStateHelperExpression(stripped) ? stripped : void 0;
4174
4914
  }
4175
- /** True when `code` is a single function or arrow-function expression. */
4176
- function isCompleteFunctionExpression(code) {
4915
+ function parseSingleExpression(code) {
4177
4916
  const candidate = code.trim().replace(/;$/, "");
4178
- const source = ts.createSourceFile("impl.ts", `(${candidate})`, ts.ScriptTarget.Latest, false, ts.ScriptKind.TS);
4179
- if ((source.parseDiagnostics ?? []).length > 0 || source.statements.length !== 1) return false;
4917
+ const source = ts.createSourceFile("implementation.ts", `(${candidate})`, ts.ScriptTarget.Latest, false, ts.ScriptKind.TS);
4918
+ if ((source.parseDiagnostics ?? []).length > 0 || source.statements.length !== 1) return;
4180
4919
  const [statement] = source.statements;
4181
- if (!statement || !ts.isExpressionStatement(statement)) return false;
4920
+ if (!statement || !ts.isExpressionStatement(statement)) return;
4182
4921
  let expression = statement.expression;
4183
4922
  if (ts.isParenthesizedExpression(expression)) expression = expression.expression;
4923
+ return {
4924
+ candidate,
4925
+ expression,
4926
+ source
4927
+ };
4928
+ }
4929
+ function getConstantImplementationExpression(code) {
4930
+ const parsed = parseSingleExpression(code);
4931
+ if (!parsed) return;
4932
+ const { candidate, expression } = parsed;
4933
+ 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;
4934
+ }
4935
+ function isCompleteXStateHelperExpression(code) {
4936
+ const expression = parseSingleExpression(code)?.expression;
4937
+ if (!expression) return false;
4938
+ return ts.isCallExpression(expression) && ts.isIdentifier(expression.expression) && XSTATE_IMPLEMENTATION_HELPERS.has(expression.expression.text);
4939
+ }
4940
+ /** True when `code` is a single function or arrow-function expression. */
4941
+ function isCompleteFunctionExpression(code) {
4942
+ const expression = parseSingleExpression(code)?.expression;
4943
+ if (!expression) return false;
4184
4944
  return ts.isFunctionExpression(expression) || ts.isArrowFunction(expression);
4185
4945
  }
4186
4946
  const colorSchema = _enum([