@statelyai/sdk 0.27.1 → 0.29.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.
@@ -3487,10 +3487,16 @@ function singleOrArrayRecord(record) {
3487
3487
  * Remove empty arrays/objects/strings, unwrap single-element arrays.
3488
3488
  * Matches studio's simplifyAttributes behavior.
3489
3489
  */
3490
+ /**
3491
+ * Keys whose empty object value is authored, not incidental: `context: {}`
3492
+ * declares that the machine has context, so dropping it loses information.
3493
+ */
3494
+ const KEEP_WHEN_EMPTY = new Set(["context"]);
3490
3495
  function simplifyAttributes(obj) {
3491
3496
  for (const key of Object.keys(obj)) {
3492
3497
  const value = obj[key];
3493
3498
  if (value === void 0 || value === null) delete obj[key];
3499
+ else if (KEEP_WHEN_EMPTY.has(key)) continue;
3494
3500
  else if (Array.isArray(value)) {
3495
3501
  if (value.length === 0) delete obj[key];
3496
3502
  else if (value.length === 1) obj[key] = value[0];
@@ -3535,7 +3541,7 @@ function deepSimplify(config) {
3535
3541
  return config;
3536
3542
  }
3537
3543
  function buildMeta(meta, color) {
3538
- if (isCodeExpression$3(meta)) return meta;
3544
+ if (isCodeExpression$4(meta)) return meta;
3539
3545
  const result = {};
3540
3546
  if (meta) {
3541
3547
  for (const [k, v] of Object.entries(meta)) if (v !== void 0 && v !== null) result[k] = v;
@@ -3543,7 +3549,7 @@ function buildMeta(meta, color) {
3543
3549
  if (color) result["@statelyai.color"] = color;
3544
3550
  return Object.keys(result).length > 0 ? result : void 0;
3545
3551
  }
3546
- function isCodeExpression$3(value) {
3552
+ function isCodeExpression$4(value) {
3547
3553
  return Boolean(value && typeof value === "object" && !Array.isArray(value) && value["@type"] === "code" && typeof value.expr === "string");
3548
3554
  }
3549
3555
  /** Format event param — supports { type: string } (new) and plain string (legacy) */
@@ -3554,7 +3560,7 @@ function formatEventParam(event) {
3554
3560
  }
3555
3561
  function formatStringParam(value) {
3556
3562
  if (typeof value === "string") return `'${value}'`;
3557
- return isCodeExpression$3(value) ? serializeJS(value) : "undefined";
3563
+ return isCodeExpression$4(value) ? serializeJS(value) : "undefined";
3558
3564
  }
3559
3565
  function formatInlineObject(value) {
3560
3566
  return `{ ${Object.entries(value).filter(([, item]) => item !== void 0).map(([key, item]) => `${formatObjectKey(key)}: ${serializeJS(item)}`).join(", ")} }`;
@@ -3589,7 +3595,11 @@ const builtInActionParamSchemas = {
3589
3595
  }),
3590
3596
  "xstate.stopChild": object({ actorRef: string().optional() }),
3591
3597
  "xstate.log": object({ label: string().optional() }),
3592
- "xstate.assign": object({ assignment: record(string(), unknown()).optional() }).catchall(unknown())
3598
+ "xstate.assign": object({ assignment: record(string(), unknown()).optional() }).catchall(unknown()),
3599
+ "xstate.choose": object({ branches: array(object({
3600
+ guard: unknown().optional(),
3601
+ actions: array(unknown()).optional()
3602
+ })).optional() })
3593
3603
  };
3594
3604
  const XSTATE_BUILT_IN_ACTIONS = {
3595
3605
  "xstate.enqueue": {
@@ -3685,6 +3695,16 @@ const XSTATE_BUILT_IN_ACTIONS = {
3685
3695
  return `log(${(params?.label ? `'${params.label}'` : void 0) ?? ""})`;
3686
3696
  }
3687
3697
  },
3698
+ "xstate.choose": {
3699
+ package: "xstate",
3700
+ version: "^5",
3701
+ import: "enqueueActions",
3702
+ importKind: "named",
3703
+ paramsSchema: builtInActionParamSchemas["xstate.choose"],
3704
+ emit(params) {
3705
+ return emitChooseBranches(params?.branches ?? []);
3706
+ }
3707
+ },
3688
3708
  "xstate.assign": {
3689
3709
  package: "xstate",
3690
3710
  version: "^5",
@@ -3692,7 +3712,7 @@ const XSTATE_BUILT_IN_ACTIONS = {
3692
3712
  importKind: "named",
3693
3713
  paramsSchema: builtInActionParamSchemas["xstate.assign"],
3694
3714
  emit(params) {
3695
- if (isCodeExpression$3(params?.assignment)) return `assign(${serializeJS(params.assignment)})`;
3715
+ if (isCodeExpression$4(params?.assignment)) return `assign(${serializeJS(params.assignment)})`;
3696
3716
  const assignments = params?.assignment && typeof params.assignment === "object" && !Array.isArray(params.assignment) ? params.assignment : params;
3697
3717
  const entries = Object.entries(assignments ?? {}).filter(([k, v]) => k && v !== void 0);
3698
3718
  if (entries.length === 0) return "assign({})";
@@ -3703,6 +3723,35 @@ const XSTATE_BUILT_IN_ACTIONS = {
3703
3723
  function isBuiltInActionType(type) {
3704
3724
  return type in XSTATE_BUILT_IN_ACTIONS;
3705
3725
  }
3726
+ /** Lower `xstate.choose` branches to an `enqueueActions` if/else-if chain. */
3727
+ function emitChooseBranches(branches) {
3728
+ const lines = [];
3729
+ const indent = (depth) => " ".repeat(depth);
3730
+ const serializeEnqueued = (action, depth) => {
3731
+ if (action && typeof action === "object" && !Array.isArray(action) && Object.keys(action).length === 1 && typeof action.type === "string") return serializeJS(action.type);
3732
+ return serializeJS(action, depth * 2);
3733
+ };
3734
+ const body = (actions, depth) => (actions ?? []).map((action) => `${indent(depth)}enqueue(${serializeEnqueued(action, depth)});`);
3735
+ let closed = false;
3736
+ let opened = false;
3737
+ for (const branch of branches) {
3738
+ if (closed) break;
3739
+ if (branch.guard === void 0) {
3740
+ if (opened) {
3741
+ lines.push(` } else {`);
3742
+ lines.push(...body(branch.actions, 2));
3743
+ lines.push(" }");
3744
+ } else lines.push(...body(branch.actions, 1));
3745
+ closed = true;
3746
+ continue;
3747
+ }
3748
+ lines.push(` ${opened ? "} else if" : "if"} (check(${serializeJS(branch.guard)})) {`);
3749
+ lines.push(...body(branch.actions, 2));
3750
+ opened = true;
3751
+ }
3752
+ if (opened && !closed) lines.push(" }");
3753
+ return `enqueueActions(({ check, enqueue }) => {\n${lines.join("\n")}\n})`;
3754
+ }
3706
3755
  function emitBuiltInAction(type, params) {
3707
3756
  return XSTATE_BUILT_IN_ACTIONS[type].emit(params);
3708
3757
  }
@@ -3743,8 +3792,12 @@ function serializeGuard(guard, asTypeRef) {
3743
3792
  * Converts a built-in xstate ActionItem to a code expression directive,
3744
3793
  * or returns a plain { type, params } object for user-defined actions.
3745
3794
  */
3746
- function serializeActionItem(action) {
3795
+ function serializeActionItem(action, keepChooseStructured = false) {
3747
3796
  const { type, params } = action;
3797
+ if (keepChooseStructured && type === "xstate.choose") return {
3798
+ type,
3799
+ params
3800
+ };
3748
3801
  if (type === "xstate.enqueue" && typeof params?.code === "string") return inlineCodeExpression$1(params.code);
3749
3802
  const exprCode = type === "xstate.expr" && typeof params?.code === "string" ? params.code : void 0;
3750
3803
  if (isBuiltInActionType(type)) {
@@ -3770,7 +3823,8 @@ function tagToString(tag) {
3770
3823
  }
3771
3824
  function graphToMachineConfig(graph, options = {}) {
3772
3825
  const v6 = isXStateV6Profile(graph.data.profile);
3773
- const { showDescriptions = true, showMeta = true, inlineGuardsAsTypeRef = false } = options;
3826
+ const { showDescriptions = true, showMeta = true, inlineGuardsAsTypeRef = false, keepChooseStructured = false } = options;
3827
+ const serializeAction = (action) => serializeActionItem(action, keepChooseStructured);
3774
3828
  const config = {};
3775
3829
  function getNodeConfig(node) {
3776
3830
  const nodeConfig = node.parentId ? {} : config;
@@ -3790,11 +3844,11 @@ function graphToMachineConfig(graph, options = {}) {
3790
3844
  target: initialNode.data.key,
3791
3845
  input: node.data.initialInput
3792
3846
  } : initialNode.data.key : void 0,
3793
- target: nodeType === "history" && initialNode ? initialNode.data.key : void 0,
3847
+ target: nodeType === "history" && initialNode ? resolveTransitionTarget(graph, node, initialNode) : void 0,
3794
3848
  ...node.data.timeout !== void 0 ? { timeout: node.data.timeout } : void 0,
3795
3849
  ...node.data.route !== void 0 ? { route: node.data.route } : void 0,
3796
- ...node.data.entry?.length ? { entry: node.data.entry.map(serializeActionItem) } : void 0,
3797
- ...node.data.exit?.length ? { exit: node.data.exit.map(serializeActionItem) } : void 0,
3850
+ ...node.data.entry?.length ? { entry: node.data.entry.map(serializeAction) } : void 0,
3851
+ ...node.data.exit?.length ? { exit: node.data.exit.map(serializeAction) } : void 0,
3798
3852
  ...node.data.invokes?.length ? { invoke: node.data.invokes.map((inv) => ({
3799
3853
  src: inv.srcExpression ?? inv.src,
3800
3854
  id: inv.invocationId ?? inv.id,
@@ -3833,7 +3887,7 @@ function graphToMachineConfig(graph, options = {}) {
3833
3887
  guard: edge.data.guard ? serializeGuard(edge.data.guard, inlineGuardsAsTypeRef) : void 0,
3834
3888
  ...edge.data.context !== void 0 ? { context: edge.data.context } : void 0,
3835
3889
  ...edge.data.input !== void 0 ? { input: edge.data.input } : void 0,
3836
- actions: edge.data.actions?.length ? edge.data.actions.map(serializeActionItem) : void 0,
3890
+ actions: edge.data.actions?.length ? edge.data.actions.map(serializeAction) : void 0,
3837
3891
  description: edge.data.description ?? void 0,
3838
3892
  ...transitionMeta ? { meta: transitionMeta } : void 0
3839
3893
  };
@@ -4212,7 +4266,8 @@ function isShadowedWithinExpression(node, expression) {
4212
4266
  }
4213
4267
  return false;
4214
4268
  }
4215
- function replacementText(node, expression) {
4269
+ function replacementText(node, expression, nested = true) {
4270
+ if (!nested) return expression;
4216
4271
  if (ts.isShorthandPropertyAssignment(node.parent) && node.parent.name === node) return `${node.text}: (${expression})`;
4217
4272
  return `(${expression})`;
4218
4273
  }
@@ -4254,7 +4309,7 @@ function resolvedExpressionText(expression, bindings, resolving = /* @__PURE__ *
4254
4309
  replacements.push({
4255
4310
  start: node.getStart(source) - start,
4256
4311
  end: node.getEnd() - start,
4257
- text: replacementText(node, resolvedExpressionText(binding, bindings, nextResolving))
4312
+ text: replacementText(node, resolvedExpressionText(binding, bindings, nextResolving), node !== expression)
4258
4313
  });
4259
4314
  return;
4260
4315
  }
@@ -4359,6 +4414,15 @@ function schemasObjectToValue(node) {
4359
4414
  }
4360
4415
  function propertyContext(parent, key) {
4361
4416
  const inherited = parent.imports ? { imports: parent.imports } : {};
4417
+ if (parent.statesMap) return {
4418
+ ...inherited,
4419
+ v6: parent.v6
4420
+ };
4421
+ if (key === "states") return {
4422
+ ...inherited,
4423
+ v6: parent.v6,
4424
+ statesMap: true
4425
+ };
4362
4426
  if (parent.machineValue && (key === "actors" || key === "actorSources")) return {
4363
4427
  ...inherited,
4364
4428
  v6: parent.v6,
@@ -4497,9 +4561,40 @@ function hashString(value) {
4497
4561
  function inlineGuardCode(params, condition) {
4498
4562
  return `${params} => ${condition.trimStart().startsWith("{") ? `(${condition})` : condition}`;
4499
4563
  }
4564
+ function namedReferenceName(node, objectName) {
4565
+ if (!node) return null;
4566
+ const target = unwrapExpression(node);
4567
+ if (ts.isElementAccessExpression(target) && ts.isIdentifier(target.expression) && target.expression.text === objectName && ts.isStringLiteralLike(target.argumentExpression)) return target.argumentExpression.text;
4568
+ if (ts.isPropertyAccessExpression(target) && ts.isIdentifier(target.expression) && target.expression.text === objectName) return target.name.text;
4569
+ return null;
4570
+ }
4571
+ function namedReferenceParams(node, bindings) {
4572
+ if (!node) return {};
4573
+ const target = unwrapExpression(node);
4574
+ if (!ts.isObjectLiteralExpression(target) && !ts.isArrayLiteralExpression(target)) return {};
4575
+ const value = expressionToValue(target, bindings, { effectArgumentValue: true }, 0);
4576
+ return value && typeof value === "object" ? value : {};
4577
+ }
4578
+ function namedGuardFromCondition(text) {
4579
+ const [statement] = ts.createSourceFile("guard.ts", text, ts.ScriptTarget.Latest, true).statements;
4580
+ if (!statement || !ts.isExpressionStatement(statement)) return void 0;
4581
+ const call = unwrapExpression(statement.expression);
4582
+ if (!ts.isCallExpression(call)) return void 0;
4583
+ const name = namedReferenceName(call.expression, "guards");
4584
+ if (!name) return void 0;
4585
+ return {
4586
+ type: name,
4587
+ params: namedReferenceParams(call.arguments[1], /* @__PURE__ */ new Map())
4588
+ };
4589
+ }
4500
4590
  function guardFromConditions(conds, params) {
4501
4591
  const simplified = simplifyConditions(conds);
4502
4592
  if (simplified.length === 0) return void 0;
4593
+ const only = simplified.length === 1 ? simplified[0] : void 0;
4594
+ if (only) {
4595
+ const named = namedGuardFromCondition(conditionText(only));
4596
+ if (named) return named;
4597
+ }
4503
4598
  const code = inlineGuardCode(params, simplified.map(conditionText).join(" && "));
4504
4599
  return {
4505
4600
  type: `inline:${hashString(code)}`,
@@ -4599,13 +4694,20 @@ function expressionStatementAction(statement, enqName, bindings) {
4599
4694
  const expression = unwrapExpression(statement.expression);
4600
4695
  if (!ts.isCallExpression(expression)) return null;
4601
4696
  const callee = expression.expression;
4602
- if (ts.isIdentifier(callee) && callee.text === enqName) return {
4603
- type: "xstate.expr",
4604
- params: {
4605
- code: resolvedExpressionText(expression, bindings),
4606
- lang: "ts"
4607
- }
4608
- };
4697
+ if (ts.isIdentifier(callee) && callee.text === enqName) {
4698
+ const actionName = namedReferenceName(expression.arguments[0], "actions");
4699
+ if (actionName) return {
4700
+ type: actionName,
4701
+ params: namedReferenceParams(expression.arguments[1], bindings)
4702
+ };
4703
+ return {
4704
+ type: "xstate.expr",
4705
+ params: {
4706
+ code: resolvedExpressionText(expression, bindings),
4707
+ lang: "ts"
4708
+ }
4709
+ };
4710
+ }
4609
4711
  if (!ts.isPropertyAccessExpression(callee)) return null;
4610
4712
  if (!ts.isIdentifier(callee.expression) || callee.expression.text !== enqName) return null;
4611
4713
  const method = callee.name.text;
@@ -4813,6 +4915,79 @@ function normalizeFunctionTransition(fn, bindings, depth) {
4813
4915
  if (transitions.length > 1) return transitions;
4814
4916
  return fallbackFunctionTransition(fn);
4815
4917
  }
4918
+ /**
4919
+ * XState v5 has no `choose()`, so `xstate.choose` is exported as the canonical
4920
+ * `enqueueActions(({ check, enqueue }) => { if (check(g)) { enqueue(a); } ... })`
4921
+ * if/else-if chain. Read exactly that shape back into structured branches so
4922
+ * the action round-trips; anything else stays an opaque inline action.
4923
+ */
4924
+ function chooseActionFromEnqueueActions(node, bindings) {
4925
+ if (!ts.isIdentifier(node.expression) || node.expression.text !== "enqueueActions" || node.arguments.length !== 1) return null;
4926
+ const fn = unwrapExpression(node.arguments[0]);
4927
+ if (!ts.isArrowFunction(fn) && !ts.isFunctionExpression(fn)) return null;
4928
+ if (fn.parameters.length !== 1) return null;
4929
+ const pattern = fn.parameters[0].name;
4930
+ if (!ts.isObjectBindingPattern(pattern)) return null;
4931
+ const bound = /* @__PURE__ */ new Map();
4932
+ for (const element of pattern.elements) {
4933
+ if (element.dotDotDotToken || !ts.isIdentifier(element.name)) return null;
4934
+ const key = element.propertyName ? propName(element.propertyName) : element.name.text;
4935
+ if (!key) return null;
4936
+ bound.set(key, element.name.text);
4937
+ }
4938
+ const checkName = bound.get("check");
4939
+ const enqueueName = bound.get("enqueue");
4940
+ if (!checkName || !enqueueName || bound.size !== 2) return null;
4941
+ const body = fn.body;
4942
+ if (!body || !ts.isBlock(body)) return null;
4943
+ const enqueuedAction = (statement) => {
4944
+ if (!ts.isExpressionStatement(statement)) return null;
4945
+ const call = unwrapExpression(statement.expression);
4946
+ if (!ts.isCallExpression(call) || !ts.isIdentifier(call.expression) || call.expression.text !== enqueueName || call.arguments.length !== 1) return null;
4947
+ const value = expressionToValue(call.arguments[0], bindings, { effectArgumentValue: true }, 0);
4948
+ return typeof value === "string" ? { type: value } : value;
4949
+ };
4950
+ const blockActions = (statements) => {
4951
+ const actions = [];
4952
+ for (const statement of statements) {
4953
+ const action = enqueuedAction(statement);
4954
+ if (action === null) return null;
4955
+ actions.push(action);
4956
+ }
4957
+ return actions;
4958
+ };
4959
+ const branches = [];
4960
+ const readChain = (statement) => {
4961
+ const condition = unwrapExpression(statement.expression);
4962
+ if (!ts.isCallExpression(condition) || !ts.isIdentifier(condition.expression) || condition.expression.text !== checkName || condition.arguments.length !== 1) return false;
4963
+ if (!ts.isBlock(statement.thenStatement)) return false;
4964
+ const actions = blockActions(statement.thenStatement.statements);
4965
+ if (!actions) return false;
4966
+ branches.push({
4967
+ guard: expressionToValue(condition.arguments[0], bindings, { effectArgumentValue: true }, 0),
4968
+ actions
4969
+ });
4970
+ const alternate = statement.elseStatement;
4971
+ if (!alternate) return true;
4972
+ if (ts.isIfStatement(alternate)) return readChain(alternate);
4973
+ if (!ts.isBlock(alternate)) return false;
4974
+ const elseActions = blockActions(alternate.statements);
4975
+ if (!elseActions) return false;
4976
+ branches.push({ actions: elseActions });
4977
+ return true;
4978
+ };
4979
+ if (body.statements.length === 1 && ts.isIfStatement(body.statements[0])) {
4980
+ if (!readChain(body.statements[0])) return null;
4981
+ } else {
4982
+ const actions = blockActions(body.statements);
4983
+ if (!actions || actions.length === 0) return null;
4984
+ branches.push({ actions });
4985
+ }
4986
+ return {
4987
+ type: "xstate.choose",
4988
+ params: { branches }
4989
+ };
4990
+ }
4816
4991
  function inlineAction(fn) {
4817
4992
  return {
4818
4993
  type: "xstate.expr",
@@ -4859,7 +5034,34 @@ function codeImportsForExpression(expression, imports) {
4859
5034
  visit(file);
4860
5035
  return found.size ? [...found.values()] : void 0;
4861
5036
  }
4862
- function normalizeFunctionAction(fn, _bindings) {
5037
+ /**
5038
+ * `entry: ({ actions }, enq) => { enq(actions['NAME'], params); ... }` is the
5039
+ * shape the exporter writes for a plain list of *named* actions, so it is
5040
+ * decomposed back into those actions instead of surviving as one opaque
5041
+ * `xstate.enqueue` code action. Direct `enq.raise(...)` / `enq(() => ...)`
5042
+ * bodies are deliberately left alone: they are authored code, not a list.
5043
+ */
5044
+ function enqueuedNamedActions(fn, bindings) {
5045
+ const body = fn.body;
5046
+ if (!body || !ts.isBlock(body) || body.statements.length === 0) return null;
5047
+ const enqName = enqueueParamName(fn);
5048
+ const actions = [];
5049
+ for (const statement of body.statements) {
5050
+ if (!ts.isExpressionStatement(statement)) return null;
5051
+ const expression = unwrapExpression(statement.expression);
5052
+ if (!ts.isCallExpression(expression) || !ts.isIdentifier(expression.expression) || expression.expression.text !== enqName) return null;
5053
+ const name = namedReferenceName(expression.arguments[0], "actions");
5054
+ if (!name) return null;
5055
+ actions.push({
5056
+ type: name,
5057
+ params: namedReferenceParams(expression.arguments[1], bindings)
5058
+ });
5059
+ }
5060
+ return actions;
5061
+ }
5062
+ function normalizeFunctionAction(fn, bindings) {
5063
+ const actions = enqueuedNamedActions(fn, bindings);
5064
+ if (actions) return actions.length === 1 ? actions[0] : actions;
4863
5065
  return enqueueAction(fn);
4864
5066
  }
4865
5067
  function objectLiteralToValue(node, bindings, context, depth, overrides = /* @__PURE__ */ new Map()) {
@@ -4934,6 +5136,7 @@ function expressionToValue(expression, bindings, context = {}, depth = 0) {
4934
5136
  if (context.machineContextValue && (ts.isArrowFunction(node) || ts.isFunctionExpression(node))) return inlineCodeExpression(node.getText());
4935
5137
  if (context.targetValue) {
4936
5138
  if (ts.isStringLiteral(node) || ts.isNoSubstitutionTemplateLiteral(node)) return node.text;
5139
+ if (ts.isArrayLiteralExpression(node) && node.elements.length > 0 && node.elements.every((element) => ts.isStringLiteral(element) || ts.isNoSubstitutionTemplateLiteral(element))) return node.elements.map((element) => element.text);
4937
5140
  if (ts.isIdentifier(node)) {
4938
5141
  const binding = bindings.get(node.text);
4939
5142
  if (binding && !ts.isFunctionDeclaration(binding)) return expressionToValue(binding, bindings, context, depth + 1);
@@ -4956,11 +5159,11 @@ function expressionToValue(expression, bindings, context = {}, depth = 0) {
4956
5159
  return inlineCodeExpression(node.getText());
4957
5160
  }
4958
5161
  if (context.timeoutValue && (ts.isArrowFunction(node) || ts.isFunctionExpression(node) || ts.isCallExpression(node))) return inlineCodeExpression(node.getText());
4959
- if (ts.isStringLiteral(node) || ts.isNoSubstitutionTemplateLiteral(node)) return context.ioValue ? inlineCodeExpression(JSON.stringify(node.text)) : node.text;
4960
- if (ts.isNumericLiteral(node)) return context.ioValue ? inlineCodeExpression(node.text) : Number(node.text);
4961
- if (node.kind === ts.SyntaxKind.TrueKeyword) return context.ioValue ? inlineCodeExpression("true") : true;
4962
- if (node.kind === ts.SyntaxKind.FalseKeyword) return context.ioValue ? inlineCodeExpression("false") : false;
4963
- if (node.kind === ts.SyntaxKind.NullKeyword) return context.ioValue ? inlineCodeExpression("null") : null;
5162
+ if (ts.isStringLiteral(node) || ts.isNoSubstitutionTemplateLiteral(node)) return node.text;
5163
+ if (ts.isNumericLiteral(node)) return Number(node.text);
5164
+ if (node.kind === ts.SyntaxKind.TrueKeyword) return true;
5165
+ if (node.kind === ts.SyntaxKind.FalseKeyword) return false;
5166
+ if (node.kind === ts.SyntaxKind.NullKeyword) return null;
4964
5167
  if (context.effectArgumentValue && !ts.isObjectLiteralExpression(node) && !ts.isArrayLiteralExpression(node)) {
4965
5168
  if (ts.isIdentifier(node) && node.text === "undefined") return void 0;
4966
5169
  return inlineCodeExpression(resolvedExpressionText(node, bindings));
@@ -5020,7 +5223,11 @@ function expressionToValue(expression, bindings, context = {}, depth = 0) {
5020
5223
  const configArg = node.arguments.length > 1 ? node.arguments[1] : node.arguments[0];
5021
5224
  return configArg ? expressionToValue(configArg, bindings, { v6: context.v6 }, depth + 1) : {};
5022
5225
  }
5023
- if (context.actionValue) return inlineAction(node);
5226
+ if (context.actionValue) {
5227
+ const choose = chooseActionFromEnqueueActions(node, bindings);
5228
+ if (choose) return choose;
5229
+ return inlineAction(node);
5230
+ }
5024
5231
  const callee = node.expression.getText();
5025
5232
  const type = callee.includes(".") ? callee.split(".").pop() : callee;
5026
5233
  return { type: type === "assign" ? "xstate.assign" : type };
@@ -5499,7 +5706,7 @@ function graphToXStateTS(graph, options = {}) {
5499
5706
  const inferredXStateVersion = isXStateV6ProfileRef(graph.data.profile ?? "xstate-v5") ? 6 : 5;
5500
5707
  const { exportStyle = "named", targetLanguage = "typescript", xstateVersion = inferredXStateVersion, xstateV6SchemaFormat = "types", ...configOptions } = options;
5501
5708
  const schemas = graph.data.schemas;
5502
- const impls = filterInlineImplementations(graph.data.implementations);
5709
+ const impls = filterInlineImplementations$1(graph.data.implementations);
5503
5710
  const supportsTypeSyntax = targetLanguage === "typescript";
5504
5711
  const hasSchemas = !!(schemas && (schemas.context || schemas.events || schemas.input || schemas.output));
5505
5712
  const hasStateSchemas = graph.nodes.some((node) => node.data.schemas);
@@ -5511,8 +5718,8 @@ function graphToXStateTS(graph, options = {}) {
5511
5718
  const builtInActions = getUsedBuiltInActions(graph, xstateVersion);
5512
5719
  const actorSourceImports = getActorSourceImports(graph);
5513
5720
  const implementationImports = getImplementationImports(impls);
5514
- const codeImports = getCodeExpressionImports(graph);
5515
- const imports = buildImports({
5721
+ const codeImports = getCodeExpressionImports$1(graph);
5722
+ const imports = buildImports$1({
5516
5723
  hasSetup,
5517
5724
  hasActors,
5518
5725
  actors: impls?.actors ?? [],
@@ -5524,7 +5731,10 @@ function graphToXStateTS(graph, options = {}) {
5524
5731
  usesTypes: xstateVersion === 6 && supportsTypeSyntax && (hasSchemas || hasStateSchemas) && xstateV6SchemaFormat === "types",
5525
5732
  usesZod: xstateVersion === 6 && (hasSchemas || hasStateSchemas) && xstateV6SchemaFormat === "zod"
5526
5733
  });
5527
- const machineConfig = xstateVersion === 6 ? toV6MachineConfig(graphToMachineConfig(graph, configOptions)) : toV5MachineConfig(graphToMachineConfig(graph, configOptions));
5734
+ const machineConfig = xstateVersion === 6 ? toV6MachineConfig(graphToMachineConfig(graph, {
5735
+ ...configOptions,
5736
+ keepChooseStructured: true
5737
+ })) : toV5MachineConfig(graphToMachineConfig(graph, configOptions));
5528
5738
  if (xstateVersion === 6) stripStateSchemas(machineConfig);
5529
5739
  let machineExpr;
5530
5740
  if (hasSetup) {
@@ -5601,7 +5811,7 @@ function buildV6StateSchemasBlock(schemas, options) {
5601
5811
  }
5602
5812
  return Object.keys(result).length ? result : void 0;
5603
5813
  }
5604
- function filterInlineImplementations(impls) {
5814
+ function filterInlineImplementations$1(impls) {
5605
5815
  if (!impls) return impls;
5606
5816
  return {
5607
5817
  ...impls,
@@ -5619,7 +5829,8 @@ const BUILTIN_ACTION_IMPORTS = {
5619
5829
  "xstate.spawnChild": "spawnChild",
5620
5830
  "xstate.stopChild": "stopChild",
5621
5831
  "xstate.log": "log",
5622
- "xstate.assign": "assign"
5832
+ "xstate.assign": "assign",
5833
+ "xstate.choose": "enqueueActions"
5623
5834
  };
5624
5835
  /** Check inline action/entry/exit code for references to xstate builtins */
5625
5836
  function scanInlineCodeForBuiltins(code, used) {
@@ -5661,6 +5872,10 @@ function mapV6MachineConfig(value, context = {}) {
5661
5872
  if (!value || typeof value !== "object") return value;
5662
5873
  const result = {};
5663
5874
  for (const [key, item] of Object.entries(value)) {
5875
+ if (key === "states") {
5876
+ result[key] = mapV6StatesMap(item);
5877
+ continue;
5878
+ }
5664
5879
  if (key === "entry" || key === "exit" || key === "actions") {
5665
5880
  result[key] = toV6ActionField(Array.isArray(item) ? item : item === void 0 ? [] : [item]);
5666
5881
  continue;
@@ -5677,6 +5892,13 @@ function mapV6MachineConfig(value, context = {}) {
5677
5892
  }
5678
5893
  return result;
5679
5894
  }
5895
+ /** Walks a `states` map, treating every entry as a state node. */
5896
+ function mapV6StatesMap(value) {
5897
+ if (!value || typeof value !== "object" || Array.isArray(value)) return value;
5898
+ const result = {};
5899
+ for (const [key, item] of Object.entries(value)) result[key] = mapV6MachineConfig(item);
5900
+ return result;
5901
+ }
5680
5902
  function mapV6TransitionMap(value) {
5681
5903
  if (!value || typeof value !== "object" || Array.isArray(value)) return value;
5682
5904
  const result = {};
@@ -5863,6 +6085,7 @@ function buildV6TransitionFunction(transitions) {
5863
6085
  });
5864
6086
  }
5865
6087
  if (branches.length === 0) return;
6088
+ if (branches.slice(0, -1).some((branch) => branch.condition === "true")) return;
5866
6089
  const generated = branches.flatMap((branch) => [branch.condition, ...branch.body]).join("\n");
5867
6090
  let renderedBranches = branches;
5868
6091
  let merged = mergeV6FirstParam(authoredFirstParam, inferV6ArgBindings(generated));
@@ -5904,19 +6127,21 @@ function buildV6ActionFunction(actions, transition) {
5904
6127
  return raw(`(${bindings.length ? `{ ${bindings.join(", ")} }` : "_"}, enq) => {\n${[...statements.map((statement) => ` ${formatV6Statement(statement)}`), ...returnValue ? [` return ${returnValue};`] : []].join("\n")}\n}`);
5905
6128
  }
5906
6129
  function formatV6Statement(statement) {
5907
- return statement === "{" || statement === "}" || statement.endsWith(";") ? statement : `${statement};`;
6130
+ const trimmed = statement.trim();
6131
+ return trimmed.endsWith("{") || trimmed.startsWith("}") || trimmed.endsWith(";") ? statement : `${statement};`;
5908
6132
  }
5909
6133
  function renderV6Effects(effects, finalContext) {
5910
- if (!(finalContext !== void 0 || effects.some((effect) => effect.contextValue))) return { statements: effects.flatMap((effect) => effect.statements ?? []) };
6134
+ if (!(finalContext !== void 0 || effects.some((effect) => effect.contextValue || effect.mutatesContext))) return { statements: effects.flatMap((effect) => effect.statements ?? []) };
5911
6135
  const statements = ["let nextContext = context"];
5912
- const inCurrentContext = (statement) => {
5913
- statements.push("{", " const context = nextContext", ` ${statement}`, "}");
6136
+ const inCurrentContext = (body) => {
6137
+ if (body.length === 0) return;
6138
+ statements.push("{", " const context = nextContext", ...body.map((line) => ` ${line}`), "}");
5914
6139
  };
5915
6140
  for (const effect of effects) {
5916
- for (const statement of effect.statements ?? []) inCurrentContext(statement);
5917
- if (effect.contextValue) inCurrentContext(`nextContext = { ...nextContext, ...(${effect.contextValue}) }`);
6141
+ inCurrentContext(effect.statements ?? []);
6142
+ if (effect.contextValue) inCurrentContext([`nextContext = { ...nextContext, ...(${effect.contextValue}) }`]);
5918
6143
  }
5919
- if (finalContext !== void 0) inCurrentContext(`nextContext = { ...nextContext, ...(${finalContext}) }`);
6144
+ if (finalContext !== void 0) inCurrentContext([`nextContext = { ...nextContext, ...(${finalContext}) }`]);
5920
6145
  return {
5921
6146
  statements,
5922
6147
  contextValue: "nextContext"
@@ -5946,6 +6171,10 @@ function mapMachineActionFields(value, mapActions) {
5946
6171
  if (!value || typeof value !== "object") return value;
5947
6172
  const result = {};
5948
6173
  for (const [key, item] of Object.entries(value)) {
6174
+ if (key === "states" && item && typeof item === "object" && !Array.isArray(item)) {
6175
+ result[key] = Object.fromEntries(Object.entries(item).map(([stateKey, state]) => [stateKey, mapMachineActionFields(state, mapActions)]));
6176
+ continue;
6177
+ }
5949
6178
  if (key === "entry" || key === "exit" || key === "actions") {
5950
6179
  const wasArray = Array.isArray(item);
5951
6180
  result[key] = mapActions(wasArray ? item : item === void 0 ? [] : [item], wasArray);
@@ -5984,6 +6213,7 @@ function actionToV6Effect(action) {
5984
6213
  const type = record.type;
5985
6214
  if (typeof type !== "string") return null;
5986
6215
  const params = record.params && typeof record.params === "object" && !Array.isArray(record.params) ? record.params : {};
6216
+ const rawParams = record.params;
5987
6217
  if (type === "xstate.raise") {
5988
6218
  const options = actionOptions(params, ["event"]);
5989
6219
  return { statements: [`enq.raise(${serializeJS(params.event)}${options})`] };
@@ -6000,8 +6230,49 @@ function actionToV6Effect(action) {
6000
6230
  return { statements: [`enq.spawn(${serializeJS(params.src)}${options})`] };
6001
6231
  }
6002
6232
  if (type === "xstate.stopChild") return { statements: [`enq.stop(${serializeJS(params.actorRef)})`] };
6003
- if (type === "xstate.assign") return { contextValue: serializeJS(params.assignment ?? params) };
6004
- 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)}` : ""})`] };
6233
+ if (type === "xstate.choose") {
6234
+ const branches = Array.isArray(params.branches) ? params.branches : [];
6235
+ const statements = [];
6236
+ let mutatesContext = false;
6237
+ let opened = false;
6238
+ for (const raw of branches) {
6239
+ if (!raw || typeof raw !== "object" || Array.isArray(raw)) return null;
6240
+ const branch = raw;
6241
+ const effects = (Array.isArray(branch.actions) ? branch.actions : []).map(actionToV6Effect);
6242
+ if (effects.some((effect) => !effect)) return null;
6243
+ const body = effects.flatMap((effect) => {
6244
+ const lines = [...effect.statements ?? []];
6245
+ if (effect.mutatesContext) mutatesContext = true;
6246
+ if (effect.contextValue) {
6247
+ mutatesContext = true;
6248
+ lines.push(`nextContext = { ...nextContext, ...(${effect.contextValue}) }`);
6249
+ }
6250
+ return lines;
6251
+ });
6252
+ if (branch.guard === void 0) {
6253
+ if (opened) {
6254
+ statements.push("} else {");
6255
+ statements.push(...body.map((line) => ` ${line}`));
6256
+ statements.push("}");
6257
+ } else statements.push(...body);
6258
+ opened = false;
6259
+ break;
6260
+ }
6261
+ const guard = guardCondition(typeof branch.guard === "string" ? { type: branch.guard } : branch.guard);
6262
+ if (!guard) return null;
6263
+ statements.push(`${opened ? "} else if" : "if"} (${guard.condition}) {`);
6264
+ statements.push(...body.map((line) => ` ${line}`));
6265
+ opened = true;
6266
+ }
6267
+ if (opened) statements.push("}");
6268
+ if (statements.length === 0) return null;
6269
+ return mutatesContext ? {
6270
+ statements,
6271
+ mutatesContext
6272
+ } : { statements };
6273
+ }
6274
+ if (type === "xstate.assign") return { contextValue: serializeJS(unwrapTemplateExpressions(params.assignment ?? params)) };
6275
+ if (!type.startsWith("xstate.")) return { statements: [`enq(${/^[A-Za-z_$][A-Za-z0-9_$]*$/.test(type) ? `actions.${type}` : `actions[${serializeJS(type)}]`}${(Array.isArray(rawParams) ? rawParams.length > 0 : Object.keys(params).length > 0) ? `, ${serializeJS(rawParams)}` : ""})`] };
6005
6276
  return null;
6006
6277
  }
6007
6278
  function getV6AssignmentArgs(code, includeAll = false) {
@@ -6061,7 +6332,7 @@ function actionOptions(params, consumedKeys) {
6061
6332
  const rest = Object.fromEntries(Object.entries(params).filter(([key, value]) => !consumedKeys.includes(key) && value !== void 0));
6062
6333
  return Object.keys(rest).length ? `, ${serializeJS(rest)}` : "";
6063
6334
  }
6064
- function buildImports({ hasSetup, hasActors, actors, builtInActions, actorSourceImports, implementationImports, codeImports, xstateVersion, usesTypes, usesZod }) {
6335
+ function buildImports$1({ hasSetup, hasActors, actors, builtInActions, actorSourceImports, implementationImports, codeImports, xstateVersion, usesTypes, usesZod }) {
6065
6336
  const xstateImports = [];
6066
6337
  if (hasSetup) xstateImports.push("setup");
6067
6338
  else xstateImports.push("createMachine");
@@ -6089,7 +6360,7 @@ function buildImports({ hasSetup, hasActors, actors, builtInActions, actorSource
6089
6360
  if (usesZod && !externalImports.get("zod")?.has("z")) imports.push("import { z } from 'zod';");
6090
6361
  return imports.join("\n");
6091
6362
  }
6092
- function getCodeExpressionImports(graph) {
6363
+ function getCodeExpressionImports$1(graph) {
6093
6364
  const imports = /* @__PURE__ */ new Map();
6094
6365
  function visit(value) {
6095
6366
  if (!value || typeof value !== "object") return;
@@ -6238,7 +6509,7 @@ function hasSchemaProperties(schema) {
6238
6509
  function buildActionsBlock(actions, options) {
6239
6510
  const block = {};
6240
6511
  for (const implementation of actions) if (implementation.code?.body) {
6241
- const inlineExpression = getInlineExpression(implementation.code.body);
6512
+ const inlineExpression = getInlineExpression$1(implementation.code.body);
6242
6513
  if (inlineExpression) {
6243
6514
  block[implementation.name] = raw(inlineExpression);
6244
6515
  continue;
@@ -6251,7 +6522,7 @@ function buildActionsBlock(actions, options) {
6251
6522
  function buildGuardsBlock(guards, options) {
6252
6523
  const block = {};
6253
6524
  for (const guard of guards) if (guard.code?.body) {
6254
- const inlineExpression = getInlineExpression(guard.code.body);
6525
+ const inlineExpression = getInlineExpression$1(guard.code.body);
6255
6526
  if (inlineExpression) {
6256
6527
  block[guard.name] = raw(inlineExpression);
6257
6528
  continue;
@@ -6289,7 +6560,7 @@ function getActorLogicExpression(code) {
6289
6560
  function buildDelaysBlock(delays) {
6290
6561
  const block = {};
6291
6562
  for (const delay of delays) if (delay.code?.body) {
6292
- const inlineExpression = getInlineExpression(delay.code.body);
6563
+ const inlineExpression = getInlineExpression$1(delay.code.body);
6293
6564
  if (inlineExpression) {
6294
6565
  block[delay.name] = raw(inlineExpression);
6295
6566
  continue;
@@ -6312,7 +6583,7 @@ function buildDelaysBlock(delays) {
6312
6583
  * on import) → the expression itself.
6313
6584
  * Returns undefined for a plain statement body, which still needs wrapping.
6314
6585
  */
6315
- function getInlineExpression(code) {
6586
+ function getInlineExpression$1(code) {
6316
6587
  const stripped = stripExportDefault(code);
6317
6588
  if (stripped !== code.trim()) return stripped;
6318
6589
  return isCompleteFunctionExpression(stripped) || isCompleteXStateHelperExpression(stripped) ? stripped : void 0;
@@ -6348,6 +6619,624 @@ function isCompleteFunctionExpression(code) {
6348
6619
  if (!expression) return false;
6349
6620
  return ts.isFunctionExpression(expression) || ts.isArrowFunction(expression);
6350
6621
  }
6622
+ /**
6623
+ * Escapes text that is interpolated into a `/* ... *\/` marker so it cannot
6624
+ * close the comment early.
6625
+ */
6626
+ function escapeMarkerText(text) {
6627
+ return text.replace(/\*\//g, "*\\/");
6628
+ }
6629
+ /** Builds a `TODO: v5-only` block comment around untrusted text. */
6630
+ function v5OnlyMarker(detail) {
6631
+ return `/* TODO: v5-only (${escapeMarkerText(detail)}); no XState v4 equivalent */`;
6632
+ }
6633
+ /**
6634
+ * Emits XState **v4** (deprecated) TypeScript for a graph.
6635
+ *
6636
+ * The v4 surface differs from v5 in ways this emitter downgrades:
6637
+ * `createMachine(config, options)` instead of `setup().createMachine()`,
6638
+ * `cond` instead of `guard`, `services` instead of `actors`, `internal: false`
6639
+ * instead of `reenter: true`, `done.invoke.X` / `error.platform.X` /
6640
+ * `done.state.X` event names, and positional `(context, event)` implementation
6641
+ * arguments (enabled by `predictableActionArguments`).
6642
+ *
6643
+ * Concepts with no v4 equivalent (`emit`, `spawnChild`, `enqueueActions`,
6644
+ * actor-logic creators such as `fromPromise`) are emitted verbatim with a
6645
+ * `// TODO: v5-only` marker rather than silently dropped.
6646
+ */
6647
+ function graphToXStateV4TS(graph, options = {}) {
6648
+ const { exportStyle = "named", targetLanguage = "typescript", ...configOptions } = options;
6649
+ const supportsTypeSyntax = targetLanguage === "typescript";
6650
+ const schemas = graph.data.schemas;
6651
+ const impls = filterInlineImplementations(graph.data.implementations);
6652
+ const rawConfig = graphToMachineConfig(graph, configOptions);
6653
+ const services = {};
6654
+ const config = transformState(rawConfig, { services });
6655
+ const machineConfig = {};
6656
+ if (config.id !== void 0) machineConfig.id = config.id;
6657
+ machineConfig.predictableActionArguments = true;
6658
+ machineConfig.preserveActionOrder = true;
6659
+ const schemaBlock = supportsTypeSyntax ? buildSchemaBlock(schemas) : void 0;
6660
+ if (schemaBlock) machineConfig.schema = schemaBlock;
6661
+ for (const [key, value] of Object.entries(config)) {
6662
+ if (key === "id") continue;
6663
+ machineConfig[key] = value;
6664
+ }
6665
+ const machineOptions = buildMachineOptions(impls, services);
6666
+ const configStr = serializeJS(machineConfig, 0);
6667
+ const optionsStr = Object.keys(machineOptions).length ? serializeJS(machineOptions, 0) : void 0;
6668
+ const machineExpr = optionsStr ? `createMachine(${configStr}, ${optionsStr})` : `createMachine(${configStr})`;
6669
+ const lines = [
6670
+ buildImports(machineExpr, getCodeExpressionImports(graph)),
6671
+ "",
6672
+ `const machine = ${machineExpr};`
6673
+ ];
6674
+ if (exportStyle === "named") lines.push("", "export { machine };");
6675
+ else if (exportStyle === "default") lines.push("", "export default machine;");
6676
+ return lines.join("\n") + "\n";
6677
+ }
6678
+ /** Keys emitted by the shared config builder that v4 has no place for. */
6679
+ const DROPPED_STATE_KEYS = new Set([
6680
+ "schemas",
6681
+ "timeout",
6682
+ "route",
6683
+ "onTimeout",
6684
+ "onSnapshot",
6685
+ "version",
6686
+ "options"
6687
+ ]);
6688
+ function transformState(state, ctx, sourceKey) {
6689
+ const result = {};
6690
+ let choiceBranches;
6691
+ for (const [key, value] of Object.entries(state)) {
6692
+ if (value === void 0 || DROPPED_STATE_KEYS.has(key)) continue;
6693
+ switch (key) {
6694
+ case "type":
6695
+ if (value !== "choice") result.type = value;
6696
+ break;
6697
+ case "choice":
6698
+ choiceBranches = transformTransitionValue(value, sourceKey);
6699
+ break;
6700
+ case "initial":
6701
+ result.initial = value && typeof value === "object" && !Array.isArray(value) ? value.target : value;
6702
+ break;
6703
+ case "output":
6704
+ result.data = transformCodeValues(value);
6705
+ break;
6706
+ case "entry":
6707
+ case "exit":
6708
+ result[key] = transformActions(value);
6709
+ break;
6710
+ case "invoke":
6711
+ result.invoke = transformInvoke(value, ctx, sourceKey);
6712
+ break;
6713
+ case "on":
6714
+ case "after":
6715
+ result[key] = transformTransitionMap(value, key === "on", sourceKey);
6716
+ break;
6717
+ case "always":
6718
+ case "onDone":
6719
+ case "onError":
6720
+ result[key] = transformTransitionValue(value, sourceKey);
6721
+ break;
6722
+ case "states": {
6723
+ const states = value;
6724
+ result.states = Object.fromEntries(Object.entries(states).map(([stateKey, child]) => [stateKey, transformState(child, ctx, stateKey)]));
6725
+ break;
6726
+ }
6727
+ default: result[key] = value;
6728
+ }
6729
+ }
6730
+ if (choiceBranches !== void 0) {
6731
+ const existing = result.always === void 0 ? [] : Array.isArray(result.always) ? result.always : [result.always];
6732
+ const branches = Array.isArray(choiceBranches) ? choiceBranches : [choiceBranches];
6733
+ result.always = [...existing, ...branches];
6734
+ }
6735
+ return result;
6736
+ }
6737
+ /** Rewrites embedded code expressions of a plain data value for v4. */
6738
+ function transformCodeValues(value) {
6739
+ if (isCodeExpression$3(value)) return raw(toV4Code(value.expr));
6740
+ if (Array.isArray(value)) return value.map(transformCodeValues);
6741
+ if (value && typeof value === "object") return Object.fromEntries(Object.entries(value).map(([key, item]) => [key, transformCodeValues(item)]));
6742
+ return value;
6743
+ }
6744
+ /** v5 event names → their v4 spellings. */
6745
+ function toV4EventName(eventName) {
6746
+ if (eventName.startsWith("xstate.done.actor.")) return `done.invoke.${eventName.slice(18)}`;
6747
+ if (eventName.startsWith("xstate.error.actor.")) return `error.platform.${eventName.slice(19)}`;
6748
+ if (eventName.startsWith("xstate.done.state.")) return `done.state.${eventName.slice(18)}`;
6749
+ return eventName;
6750
+ }
6751
+ function transformTransitionMap(value, renameEvents, sourceKey) {
6752
+ if (!value || typeof value !== "object" || Array.isArray(value)) return value;
6753
+ return Object.fromEntries(Object.entries(value).map(([key, item]) => [renameEvents ? toV4EventName(key) : key, transformTransitionValue(item, sourceKey)]));
6754
+ }
6755
+ /**
6756
+ * True when a resolved v4 target points at the source state itself or one of
6757
+ * its descendants — the only targets for which `internal` changes behaviour.
6758
+ * Targets resolve against the source's parent, so a descendant of the source
6759
+ * is spelled `<sourceKey>.<child>` (or `.<child>` for root transitions).
6760
+ */
6761
+ function targetsSelfOrDescendant(target, sourceKey) {
6762
+ if (typeof target !== "string" || !target) return false;
6763
+ if (sourceKey === void 0) return target.startsWith(".");
6764
+ return target === sourceKey || target.startsWith(`${sourceKey}.`);
6765
+ }
6766
+ /** Renders a v6 `matches` guard as readable text for the TODO marker. */
6767
+ function describeMatches(matches) {
6768
+ if (typeof matches === "string") return matches;
6769
+ if (isCodeExpression$3(matches)) return matches.expr;
6770
+ try {
6771
+ return serializeJS(matches, 0).replace(/\s+/g, " ");
6772
+ } catch {
6773
+ return String(matches);
6774
+ }
6775
+ }
6776
+ function transformTransitionValue(value, sourceKey) {
6777
+ if (Array.isArray(value)) return value.map((item) => transformTransitionValue(item, sourceKey));
6778
+ if (!value || typeof value !== "object") return value;
6779
+ if (isCodeExpression$3(value)) return raw(toV4Code(value.expr));
6780
+ const transition = value;
6781
+ const result = {};
6782
+ let reenter;
6783
+ let contextUpdate;
6784
+ let matches;
6785
+ for (const [key, item] of Object.entries(transition)) {
6786
+ if (item === void 0) continue;
6787
+ switch (key) {
6788
+ case "guard":
6789
+ result.cond = transformGuard(item);
6790
+ break;
6791
+ case "reenter":
6792
+ reenter = item;
6793
+ break;
6794
+ case "actions":
6795
+ result.actions = transformActions(item);
6796
+ break;
6797
+ case "context":
6798
+ contextUpdate = item;
6799
+ break;
6800
+ case "matches":
6801
+ matches = item;
6802
+ break;
6803
+ case "input": break;
6804
+ default: result[key] = item;
6805
+ }
6806
+ }
6807
+ if (reenter === true) result.internal = false;
6808
+ else if (targetsSelfOrDescendant(result.target, sourceKey)) result.internal = true;
6809
+ if (matches !== void 0) {
6810
+ const marker = v5OnlyMarker(`matches guard: ${describeMatches(matches)}`);
6811
+ result.cond = result.cond === void 0 ? raw(`undefined ${marker}`) : raw(`${serializeJS(result.cond, 0)} ${marker}`);
6812
+ }
6813
+ if (contextUpdate !== void 0) {
6814
+ const assignAction = raw(`assign(${serializeJS(transformCodeValues(contextUpdate), 0)})`);
6815
+ result.actions = [...result.actions === void 0 ? [] : Array.isArray(result.actions) ? result.actions : [result.actions], assignAction];
6816
+ }
6817
+ return result;
6818
+ }
6819
+ /** v4 reads parameters off the action/cond object itself, so they are spread. */
6820
+ function toV4ParameterizedObject(value) {
6821
+ const { type, params } = value;
6822
+ if (typeof type !== "string") return value;
6823
+ if (!params || typeof params !== "object") return type;
6824
+ const v4Params = transformCodeValues(params);
6825
+ const name = "type" in v4Params ? raw(`'${type}' ${v5OnlyMarker(`param named \`type\` collides with the ${JSON.stringify(type)} name`)}`) : type;
6826
+ return {
6827
+ ...v4Params,
6828
+ type: name
6829
+ };
6830
+ }
6831
+ function transformGuard(guard) {
6832
+ if (isCodeExpression$3(guard)) return raw(toV4Code(guard.expr));
6833
+ if (guard && typeof guard === "object" && !Array.isArray(guard)) return toV4ParameterizedObject(guard);
6834
+ return guard;
6835
+ }
6836
+ function transformActions(value) {
6837
+ const wasArray = Array.isArray(value);
6838
+ const mapped = (wasArray ? value : [value]).map(transformAction);
6839
+ return wasArray ? mapped : mapped[0];
6840
+ }
6841
+ function transformAction(action) {
6842
+ if (isCodeExpression$3(action)) return raw(toV4Code(action.expr));
6843
+ if (action && typeof action === "object" && !Array.isArray(action)) return toV4ParameterizedObject(action);
6844
+ return action;
6845
+ }
6846
+ function transformInvoke(value, ctx, sourceKey) {
6847
+ if (Array.isArray(value)) return value.map((item) => transformInvoke(item, ctx, sourceKey));
6848
+ if (!value || typeof value !== "object") return value;
6849
+ const invoke = value;
6850
+ const result = {};
6851
+ for (const [key, item] of Object.entries(invoke)) {
6852
+ if (item === void 0) continue;
6853
+ switch (key) {
6854
+ case "src":
6855
+ if (isCodeExpression$3(item)) {
6856
+ const name = typeof invoke.id === "string" && invoke.id ? invoke.id : `service${Object.keys(ctx.services).length + 1}`;
6857
+ ctx.services[name] = raw(toV4Code(item.expr));
6858
+ result.src = name;
6859
+ } else result.src = item;
6860
+ break;
6861
+ case "input":
6862
+ result.data = transformCodeValues(item);
6863
+ break;
6864
+ case "onDone":
6865
+ case "onError":
6866
+ result[key] = transformTransitionValue(item, sourceKey);
6867
+ break;
6868
+ case "output":
6869
+ case "timeout":
6870
+ case "registryKey":
6871
+ case "onSnapshot":
6872
+ case "onTimeout": break;
6873
+ default: result[key] = item;
6874
+ }
6875
+ }
6876
+ return result;
6877
+ }
6878
+ /** v5 helpers that exist in v4 under a different name. */
6879
+ const RENAMED_HELPERS = { stopChild: "stop" };
6880
+ /**
6881
+ * v4 helpers that are not root exports of `xstate@4`; they live on the
6882
+ * `actions` namespace export.
6883
+ */
6884
+ const V4_ACTIONS_NAMESPACE_HELPERS = ["respond", "escalate"];
6885
+ /** v5-only helpers with no v4 equivalent. */
6886
+ const V5_ONLY_HELPERS = [
6887
+ "emit",
6888
+ "spawnChild",
6889
+ "enqueueActions",
6890
+ "fromPromise",
6891
+ "fromCallback",
6892
+ "fromObservable",
6893
+ "fromEventObservable",
6894
+ "fromTransition",
6895
+ "createAsyncLogic"
6896
+ ];
6897
+ /**
6898
+ * Bindings the emitter re-binds itself, so dropping them from a destructured
6899
+ * parameter list is not a loss the user has to act on.
6900
+ */
6901
+ const REBOUND_BINDINGS = new Set(["params", "input"]);
6902
+ /** Bindings v4 passes positionally, so they survive the rewrite. */
6903
+ const V4_BOUND_BINDINGS = new Set(["context", "event"]);
6904
+ /**
6905
+ * Names that mark a destructured parameter list as a v5 implementation
6906
+ * signature rather than an object literal argument.
6907
+ */
6908
+ const V5_DESTRUCTURED_BINDINGS = new Set([
6909
+ "context",
6910
+ "event",
6911
+ "params",
6912
+ "input",
6913
+ "self",
6914
+ "system",
6915
+ "enqueue",
6916
+ "spawn",
6917
+ "emit",
6918
+ "check",
6919
+ "signal"
6920
+ ]);
6921
+ /** Parses a snippet permissively so positions can be read off the AST. */
6922
+ function parseSnippet(source) {
6923
+ return ts.createSourceFile("snippet.tsx", source, ts.ScriptTarget.Latest, true, ts.ScriptKind.TSX);
6924
+ }
6925
+ /** True when the snippet parsed without syntax errors. */
6926
+ function parsedCleanly(sourceFile) {
6927
+ const diagnostics = sourceFile.parseDiagnostics;
6928
+ return !diagnostics || diagnostics.length === 0;
6929
+ }
6930
+ /**
6931
+ * The positional v4 parameter list for a v5 destructured binding list, or
6932
+ * `undefined` when the bindings are not a v5 implementation signature.
6933
+ */
6934
+ function v4ParameterList(names) {
6935
+ if (!names.length) return void 0;
6936
+ if (!names.some((name) => V5_DESTRUCTURED_BINDINGS.has(name))) return;
6937
+ if (names.includes("context")) return names.includes("event") ? "context, event" : "context";
6938
+ return names.includes("event") ? "_, event" : "";
6939
+ }
6940
+ /**
6941
+ * Rewrites v5 destructured *parameter* lists (`({ context, event }) => ...`)
6942
+ * to positional v4 ones. Only parameter positions of functions and arrows are
6943
+ * touched, so a shorthand object *argument* such as `send({ context, event })`
6944
+ * is left alone. Bindings v4 cannot supply are collected into `dropped`.
6945
+ */
6946
+ function rewriteDestructuredParameters(code, dropped) {
6947
+ const sourceFile = parseSnippet(code);
6948
+ const edits = [];
6949
+ const visit = (node) => {
6950
+ if (ts.isArrowFunction(node) || ts.isFunctionExpression(node) || ts.isFunctionDeclaration(node) || ts.isMethodDeclaration(node)) {
6951
+ const [parameter] = node.parameters;
6952
+ if (parameter && node.parameters.length === 1 && !parameter.type && !parameter.initializer && !parameter.dotDotDotToken && ts.isObjectBindingPattern(parameter.name)) {
6953
+ const elements = parameter.name.elements;
6954
+ if (elements.every((element) => !element.propertyName && !element.initializer && !element.dotDotDotToken && ts.isIdentifier(element.name))) {
6955
+ const names = elements.map((element) => element.name.getText());
6956
+ const replacement = v4ParameterList(names);
6957
+ if (replacement !== void 0) {
6958
+ for (const name of names) if (!V4_BOUND_BINDINGS.has(name) && !REBOUND_BINDINGS.has(name)) dropped.add(name);
6959
+ edits.push({
6960
+ start: parameter.getStart(sourceFile),
6961
+ end: parameter.getEnd(),
6962
+ text: replacement
6963
+ });
6964
+ }
6965
+ }
6966
+ }
6967
+ }
6968
+ ts.forEachChild(node, visit);
6969
+ };
6970
+ ts.forEachChild(sourceFile, visit);
6971
+ let result = code;
6972
+ for (const edit of edits.sort((a, b) => b.start - a.start)) result = result.slice(0, edit.start) + edit.text + result.slice(edit.end);
6973
+ return result;
6974
+ }
6975
+ /**
6976
+ * Rewrites a v5 implementation expression for v4: positional implementation
6977
+ * arguments, renamed helpers, and a marker on anything v4 cannot express.
6978
+ */
6979
+ function toV4Code(code) {
6980
+ const dropped = /* @__PURE__ */ new Set();
6981
+ let result = rewriteDestructuredParameters(stripExportDefault(code), dropped);
6982
+ for (const [from, to] of Object.entries(RENAMED_HELPERS)) result = result.replace(new RegExp(`\\b${from}\\(`, "g"), `${to}(`);
6983
+ for (const helper of V4_ACTIONS_NAMESPACE_HELPERS) result = result.replace(new RegExp(`(?<!\\.)\\b${helper}\\(`, "g"), `actions.${helper}(`);
6984
+ const unsupported = [...V5_ONLY_HELPERS.filter((helper) => new RegExp(`\\b${helper}\\s*\\(`).test(result)), ...dropped];
6985
+ if (unsupported.length) result = `${result} ${v5OnlyMarker(unsupported.join(", "))}`;
6986
+ return result;
6987
+ }
6988
+ /**
6989
+ * True when a body is a single expression, so `return` can be prefixed. Parsed
6990
+ * as `(body)`: a statement such as `if (x) run()` fails to parse that way, and
6991
+ * an object literal such as `{ a: 1 }` parses as an expression rather than a
6992
+ * block.
6993
+ */
6994
+ function isBareExpression(body) {
6995
+ const trimmed = body.trim();
6996
+ if (!trimmed) return false;
6997
+ const sourceFile = parseSnippet(`(${trimmed})`);
6998
+ if (!parsedCleanly(sourceFile)) return false;
6999
+ if (sourceFile.statements.length !== 1) return false;
7000
+ const statement = sourceFile.statements[0];
7001
+ return !!statement && ts.isExpressionStatement(statement) && ts.isParenthesizedExpression(statement.expression);
7002
+ }
7003
+ /** True when an implementation body reads a re-bound v5 binding. */
7004
+ function referencesBinding(body, name) {
7005
+ return new RegExp(`\\b${name}\\b`).test(body);
7006
+ }
7007
+ /**
7008
+ * True when `name` is referenced free in a block body: it is read somewhere
7009
+ * that no enclosing declaration inside the body binds. Declarations tracked
7010
+ * are variable declarations, function/arrow/catch parameters, function and
7011
+ * class names, so a nested `(params) => params.id` shadows without suppressing
7012
+ * an outer read.
7013
+ */
7014
+ function referencesFreeBinding(body, name) {
7015
+ const sourceFile = parseSnippet(body);
7016
+ const scopes = [/* @__PURE__ */ new Set()];
7017
+ let found = false;
7018
+ const declare = (bindingName) => {
7019
+ if (ts.isIdentifier(bindingName)) {
7020
+ scopes[scopes.length - 1]?.add(bindingName.text);
7021
+ return;
7022
+ }
7023
+ for (const element of bindingName.elements) if (ts.isBindingElement(element)) declare(element.name);
7024
+ };
7025
+ const isDeclared = () => scopes.some((scope) => scope.has(name));
7026
+ /** True when an identifier node is a value reference, not a name position. */
7027
+ const isReference = (node) => {
7028
+ const parent = node.parent;
7029
+ if (!parent) return true;
7030
+ if (ts.isPropertyAccessExpression(parent) && parent.name === node) return false;
7031
+ if (ts.isQualifiedName(parent) && parent.right === node) return false;
7032
+ if ((ts.isPropertyAssignment(parent) || ts.isMethodDeclaration(parent) || ts.isPropertyDeclaration(parent) || ts.isEnumMember(parent)) && parent.name === node) return false;
7033
+ if (ts.isBindingElement(parent) && parent.propertyName === node) return false;
7034
+ if (ts.isJsxAttribute(parent) && parent.name === node) return false;
7035
+ if (ts.isImportSpecifier(parent) || ts.isExportSpecifier(parent)) return false;
7036
+ if ((ts.isVariableDeclaration(parent) || ts.isParameter(parent) || ts.isFunctionDeclaration(parent) || ts.isFunctionExpression(parent) || ts.isClassDeclaration(parent) || ts.isClassExpression(parent) || ts.isBindingElement(parent)) && parent.name === node) return false;
7037
+ if (ts.isLabeledStatement(parent) && parent.label === node) return false;
7038
+ return true;
7039
+ };
7040
+ const withScope = (run) => {
7041
+ scopes.push(/* @__PURE__ */ new Set());
7042
+ run();
7043
+ scopes.pop();
7044
+ };
7045
+ const visit = (node) => {
7046
+ if (found) return;
7047
+ if (ts.isIdentifier(node)) {
7048
+ if (node.text === name && isReference(node) && !isDeclared()) found = true;
7049
+ return;
7050
+ }
7051
+ if (ts.isFunctionDeclaration(node) || ts.isFunctionExpression(node) || ts.isArrowFunction(node) || ts.isMethodDeclaration(node) || ts.isConstructorDeclaration(node) || ts.isGetAccessor(node) || ts.isSetAccessor(node)) {
7052
+ if (ts.isFunctionDeclaration(node) && node.name) declare(node.name);
7053
+ withScope(() => {
7054
+ for (const parameter of node.parameters) declare(parameter.name);
7055
+ if (ts.isFunctionExpression(node) && node.name) declare(node.name);
7056
+ for (const parameter of node.parameters) if (parameter.initializer) visit(parameter.initializer);
7057
+ if (node.body) visit(node.body);
7058
+ });
7059
+ return;
7060
+ }
7061
+ if (ts.isBlock(node) || ts.isCaseBlock(node)) {
7062
+ withScope(() => ts.forEachChild(node, visit));
7063
+ return;
7064
+ }
7065
+ if (ts.isCatchClause(node)) {
7066
+ withScope(() => {
7067
+ if (node.variableDeclaration) declare(node.variableDeclaration.name);
7068
+ visit(node.block);
7069
+ });
7070
+ return;
7071
+ }
7072
+ if (ts.isVariableDeclaration(node)) {
7073
+ if (node.initializer) visit(node.initializer);
7074
+ declare(node.name);
7075
+ return;
7076
+ }
7077
+ if ((ts.isClassDeclaration(node) || ts.isClassExpression(node)) && node.name) declare(node.name);
7078
+ ts.forEachChild(node, visit);
7079
+ };
7080
+ ts.forEachChild(sourceFile, visit);
7081
+ return found;
7082
+ }
7083
+ /**
7084
+ * True when the emitter should re-bind `name` around a block body: the body
7085
+ * reads it free and does not declare it itself.
7086
+ */
7087
+ function needsRebind(body, name) {
7088
+ return referencesFreeBinding(body, name);
7089
+ }
7090
+ function filterInlineImplementations(impls) {
7091
+ if (!impls) return impls;
7092
+ return {
7093
+ ...impls,
7094
+ actions: impls.actions.filter((action) => !action.name.startsWith("inline:")),
7095
+ guards: impls.guards.filter((guard) => !guard.name.startsWith("inline:")),
7096
+ delays: impls.delays.filter((delay) => !delay.name.startsWith("inline:"))
7097
+ };
7098
+ }
7099
+ function buildMachineOptions(impls, liftedServices) {
7100
+ const result = {};
7101
+ if (impls?.actions.length) result.actions = Object.fromEntries(impls.actions.map((action) => [action.name, raw(implementationFunction(action, "// TODO: implement"))]));
7102
+ if (impls?.guards.length) result.guards = Object.fromEntries(impls.guards.map((guard) => [guard.name, raw(implementationFunction(guard, "// TODO: implement\n return false;", "cond"))]));
7103
+ const services = { ...liftedServices };
7104
+ for (const actor of impls?.actors ?? []) services[actor.name] = raw(serviceImplementation(actor));
7105
+ if (Object.keys(services).length) result.services = services;
7106
+ if (impls?.delays.length) result.delays = Object.fromEntries(impls.delays.map((delay) => [delay.name, raw(implementationFunction(delay, "// TODO: implement\n return 1000;", "delay"))]));
7107
+ return result;
7108
+ }
7109
+ /**
7110
+ * Emits a v4 implementation. v4 calls actions/guards with
7111
+ * `(context, event, meta)`, where `meta.action` (actions, delays) and
7112
+ * `meta.cond` (guards) carry the action/cond object that parameters were
7113
+ * spread onto, so `params` is re-bound from there when the body reads it.
7114
+ */
7115
+ function implementationFunction(implementation, todo, kind = "action") {
7116
+ const body = implementation.code?.body;
7117
+ if (!body) return `function (context, event) {\n ${todo}\n}`;
7118
+ const inline = getInlineExpression(body);
7119
+ const canRebind = kind !== "delay";
7120
+ const metaKey = kind === "cond" ? "cond" : "action";
7121
+ const readsParams = inline ? referencesBinding(body, "params") : needsRebind(body, "params");
7122
+ const usesParams = readsParams && canRebind;
7123
+ const marker = readsParams && !canRebind ? ` ${PARAMS_IN_DELAY_MARKER}` : "";
7124
+ if (inline) {
7125
+ const converted = toV4Code(inline);
7126
+ if (!usesParams) return `${converted}${marker}`;
7127
+ return `function (context, event, meta) {\n const params = meta.${metaKey};\n return (${converted})(context, event);\n}`;
7128
+ }
7129
+ const code = toV4Code(dedent(body));
7130
+ const statement = isBareExpression(code) ? `return ${code};` : code;
7131
+ if (!usesParams) return `function (context, event) {\n ${statement}\n}${marker}`;
7132
+ return `function (context, event, meta) {\n const params = meta.${metaKey};\n ${statement}\n}`;
7133
+ }
7134
+ /** Marks a delay body that reads `params`, which v4 cannot supply. */
7135
+ const PARAMS_IN_DELAY_MARKER = "/* TODO: v5-only (params in delay); no XState v4 equivalent */";
7136
+ /**
7137
+ * Emits a v4 service. v4 invoke creators are called with
7138
+ * `(context, event, { data, src, meta })`, so a body reading v5 `input` gets it
7139
+ * re-bound from `meta.data` (what `invoke.data` resolves to).
7140
+ */
7141
+ function serviceImplementation(actor) {
7142
+ const body = actor.code?.body;
7143
+ if (!body) return `async function (context, event) {\n // TODO: implement ${actor.name}\n}`;
7144
+ const inline = getInlineExpression(body);
7145
+ const usesInput = inline ? referencesBinding(body, "input") : needsRebind(body, "input");
7146
+ if (inline) {
7147
+ if (!usesInput) return toV4Code(inline);
7148
+ return `async function (context, event, meta) {\n return (${stripExportDefault(inline)})({ context, event, input: meta.data });\n}`;
7149
+ }
7150
+ const code = toV4Code(dedent(body));
7151
+ const statement = isBareExpression(code) ? `return ${code};` : code;
7152
+ if (!usesInput) return `async function (context, event) {\n ${statement}\n}`;
7153
+ return `async function (context, event, meta) {\n const input = meta.data;\n ${statement}\n}`;
7154
+ }
7155
+ /** A body that is already a complete expression is emitted verbatim. */
7156
+ function getInlineExpression(code) {
7157
+ const stripped = stripExportDefault(code);
7158
+ if (stripped !== code.trim()) return stripped;
7159
+ return /^\s*(async\s+)?(function\b|\(|[A-Za-z_$][\w$]*\s*=>)/.test(stripped) && !/;\s*\n/.test(stripped) ? stripped : void 0;
7160
+ }
7161
+ function buildSchemaBlock(schemas) {
7162
+ if (!schemas) return void 0;
7163
+ const result = {};
7164
+ const contextType = contextSchemaToTSType(schemas.context);
7165
+ if (contextType) result.context = raw(`{} as ${contextType}`);
7166
+ const eventsType = eventsSchemaToTSType(schemas.events);
7167
+ if (eventsType) result.events = raw(`{} as\n | ${eventsType}`);
7168
+ return Object.keys(result).length ? result : void 0;
7169
+ }
7170
+ /** Named exports of `xstate` v4 that generated code may reference. */
7171
+ const V4_XSTATE_HELPERS = [
7172
+ "assign",
7173
+ "raise",
7174
+ "send",
7175
+ "sendTo",
7176
+ "sendParent",
7177
+ "sendUpdate",
7178
+ "forwardTo",
7179
+ "log",
7180
+ "cancel",
7181
+ "stop",
7182
+ "choose",
7183
+ "pure",
7184
+ "spawn",
7185
+ "actions",
7186
+ "doneInvoke",
7187
+ "interpret"
7188
+ ];
7189
+ function buildImports(machineExpr, codeImports) {
7190
+ const xstateImports = new Set(["createMachine"]);
7191
+ for (const helper of V4_XSTATE_HELPERS) if (new RegExp(`\\b${helper}\\s*\\(`).test(machineExpr)) xstateImports.add(helper);
7192
+ if (/\bactions\s*\./.test(machineExpr)) xstateImports.add("actions");
7193
+ const externalImports = /* @__PURE__ */ new Map();
7194
+ for (const codeImport of codeImports) {
7195
+ if ((codeImport.importKind ?? "named") !== "named") continue;
7196
+ const specifier = codeImport.local && codeImport.local !== codeImport.import ? `${codeImport.import} as ${codeImport.local}` : codeImport.import;
7197
+ if (codeImport.package === "xstate") {
7198
+ if (V4_ACTIONS_NAMESPACE_HELPERS.includes(codeImport.import)) xstateImports.add("actions");
7199
+ else if (V4_XSTATE_HELPERS.includes(codeImport.import)) xstateImports.add(specifier);
7200
+ continue;
7201
+ }
7202
+ const names = externalImports.get(codeImport.package) ?? /* @__PURE__ */ new Set();
7203
+ names.add(specifier);
7204
+ externalImports.set(codeImport.package, names);
7205
+ }
7206
+ const imports = [`import { ${[...xstateImports].join(", ")} } from 'xstate';`];
7207
+ for (const [packageName, names] of externalImports) imports.push(`import { ${[...names].sort().join(", ")} } from '${packageName}';`);
7208
+ return imports.join("\n");
7209
+ }
7210
+ function getCodeExpressionImports(graph) {
7211
+ const imports = /* @__PURE__ */ new Map();
7212
+ function visit(value) {
7213
+ if (!value || typeof value !== "object") return;
7214
+ if (Array.isArray(value)) {
7215
+ value.forEach(visit);
7216
+ return;
7217
+ }
7218
+ const record = value;
7219
+ if (Array.isArray(record.imports)) for (const item of record.imports) {
7220
+ if (!item || typeof item !== "object") continue;
7221
+ const candidate = item;
7222
+ if (typeof candidate.package !== "string" || typeof candidate.import !== "string") continue;
7223
+ const key = `${candidate.package}:${candidate.import}:${candidate.local ?? ""}:${candidate.importKind ?? "named"}`;
7224
+ imports.set(key, {
7225
+ package: candidate.package,
7226
+ import: candidate.import,
7227
+ local: candidate.local,
7228
+ importKind: candidate.importKind,
7229
+ version: candidate.version
7230
+ });
7231
+ }
7232
+ Object.values(record).forEach(visit);
7233
+ }
7234
+ visit(graph);
7235
+ return [...imports.values()];
7236
+ }
7237
+ function isCodeExpression$3(value) {
7238
+ return !!value && typeof value === "object" && value["@type"] === "code" && typeof value.expr === "string";
7239
+ }
6351
7240
  function getXStateFSMCompatibilityIssues(graph) {
6352
7241
  const root = graph.nodes.find((node) => node.parentId == null);
6353
7242
  if (!root) return ["missing root state"];
@@ -6831,4 +7720,4 @@ function getScriptKind(fileName) {
6831
7720
  }
6832
7721
 
6833
7722
  //#endregion
6834
- export { normalizeMachineProfile as _, RawCode as a, xstateSourceToConfig as b, detectXStateSourceProfile as c, getXStateFSMCompatibilityIssues as d, graphChangeToPatchesResult as f, jsonSchemaToTSType as g, graphToXStateTS as h, INLINE_EXPRESSION_DIRECTIVE_FIELDS as i, diffGraphsSemantically as l, graphToXStateFSM as m, getStatelyPragma as n, alignCompareGraphIds as o, graphToMachineConfig as p, upsertStatelyPragma as r, contextSchemaToTSType as s, findStatelyPragmaAttachments as t, eventsSchemaToTSType as u, raw as v, serializeJS as y };
7723
+ export { jsonSchemaToTSType as _, RawCode as a, serializeJS as b, detectXStateSourceProfile as c, getXStateFSMCompatibilityIssues as d, graphChangeToPatchesResult as f, graphToXStateV4TS as g, graphToXStateTS as h, INLINE_EXPRESSION_DIRECTIVE_FIELDS as i, diffGraphsSemantically as l, graphToXStateFSM as m, getStatelyPragma as n, alignCompareGraphIds as o, graphToMachineConfig as p, upsertStatelyPragma as r, contextSchemaToTSType as s, findStatelyPragmaAttachments as t, eventsSchemaToTSType as u, normalizeMachineProfile as v, xstateSourceToConfig as x, raw as y };