@statelyai/sdk 0.18.0 → 0.20.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +33 -2
- package/dist/auth.d.mts +1 -1
- package/dist/editor-sync-types-C-zWaaVk.d.mts +95 -0
- package/dist/editorHostProtocol-D_h4y3rX.mjs +5 -0
- package/dist/editorHostSession-CCTwvUOB.mjs +479 -0
- package/dist/editorHostSession-lL7wPLnL.d.mts +184 -0
- package/dist/editorHostSession.d.mts +2 -0
- package/dist/editorHostSession.mjs +4 -0
- package/dist/embed.d.mts +1 -1
- package/dist/embed.mjs +31 -3
- package/dist/{graph-DuOeLGvh.d.mts → graph-yDK-MM3G.d.mts} +6 -4
- package/dist/graph.d.mts +1 -1
- package/dist/{index-ag6K2iAS.d.mts → index-BAkQThnl.d.mts} +9 -9
- package/dist/index.d.mts +7 -6
- package/dist/index.mjs +7 -5
- package/dist/{inspect-BZFzyeew.d.mts → inspect-CGJR4iZK.d.mts} +13 -3
- package/dist/{inspect-llcqYpZ1.mjs → inspect-DWu20a8g.mjs} +58 -31
- package/dist/inspect.d.mts +1 -1
- package/dist/inspect.mjs +2 -2
- package/dist/patchTypes.d.mts +1 -1
- package/dist/protocol.d.mts +44 -50
- package/dist/protocol.mjs +2 -2
- package/dist/{studio-txdyJHD7.mjs → schemas-b9wG-zYl.mjs} +15 -396
- package/dist/{statelyPragma-Bm9O4XV6.mjs → statelyPragma-CIzsR_Sx.mjs} +977 -934
- package/dist/studio-DHGspwII.mjs +397 -0
- package/dist/{studio-Bk_u41gu.d.mts → studio-YSppd-am.d.mts} +2 -2
- package/dist/studio.d.mts +1 -1
- package/dist/studio.mjs +1 -1
- package/dist/sync.d.mts +2 -2
- package/dist/sync.mjs +12 -5
- package/dist/{transport-CyCrdKyz.mjs → version-YJizbJxR.mjs} +14 -4
- package/package.json +7 -3
- /package/dist/{auth-2Thaw42j.d.mts → auth-B0ZTKri2.d.mts} +0 -0
|
@@ -1,6 +1,5 @@
|
|
|
1
|
-
import { a as
|
|
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
|
|
@@ -2638,9 +2637,14 @@ function stripExportDefault(code) {
|
|
|
2638
2637
|
if (trimmed.startsWith("export default ")) return trimmed.slice(15).replace(/;$/, "");
|
|
2639
2638
|
return trimmed;
|
|
2640
2639
|
}
|
|
2641
|
-
const
|
|
2640
|
+
const XSTATE_V5_PROFILE = "@statelyai/xstate@5.30.0";
|
|
2641
|
+
const XSTATE_V6_PROFILE = "@statelyai/xstate@6.0.0-alpha.24";
|
|
2642
|
+
const LEGACY_MACHINE_PROFILES = ["xstate-v5", "xstate-v6-alpha"];
|
|
2643
|
+
function normalizeMachineProfile(profile) {
|
|
2644
|
+
return profile === "xstate-v5" ? XSTATE_V5_PROFILE : profile === "xstate-v6-alpha" ? XSTATE_V6_PROFILE : profile;
|
|
2645
|
+
}
|
|
2642
2646
|
function isXStateV6Profile(profile) {
|
|
2643
|
-
return profile === "xstate-v6-alpha";
|
|
2647
|
+
return (profile === "xstate-v5" || profile === "xstate-v6-alpha" ? normalizeMachineProfile(profile) : profile ?? XSTATE_V5_PROFILE).startsWith("@statelyai/xstate@6.");
|
|
2644
2648
|
}
|
|
2645
2649
|
/**
|
|
2646
2650
|
* Graph-native transition references. Transitions point at invoke/action/state
|
|
@@ -3175,610 +3179,161 @@ const INLINE_EXPRESSION_DIRECTIVE_FIELDS = [
|
|
|
3175
3179
|
"initialInput",
|
|
3176
3180
|
"route"
|
|
3177
3181
|
];
|
|
3178
|
-
|
|
3179
|
-
|
|
3180
|
-
|
|
3181
|
-
|
|
3182
|
-
|
|
3183
|
-
|
|
3184
|
-
|
|
3185
|
-
|
|
3186
|
-
|
|
3187
|
-
|
|
3188
|
-
|
|
3189
|
-
|
|
3190
|
-
}
|
|
3191
|
-
|
|
3192
|
-
|
|
3193
|
-
|
|
3194
|
-
|
|
3195
|
-
|
|
3196
|
-
|
|
3197
|
-
|
|
3198
|
-
|
|
3199
|
-
|
|
3200
|
-
}
|
|
3201
|
-
function objectType(schema) {
|
|
3202
|
-
const props = schema.properties;
|
|
3203
|
-
if (!props || Object.keys(props).length === 0) {
|
|
3204
|
-
if (schema.additionalProperties) return `Record<string, ${jsonSchemaToTSType(resolveDef(schema.additionalProperties))}>`;
|
|
3205
|
-
return "Record<string, unknown>";
|
|
3182
|
+
const XSTATE_FORMATS = [
|
|
3183
|
+
{
|
|
3184
|
+
format: "typescript",
|
|
3185
|
+
import: true,
|
|
3186
|
+
export: true,
|
|
3187
|
+
sourcePreserving: true
|
|
3188
|
+
},
|
|
3189
|
+
{
|
|
3190
|
+
format: "javascript",
|
|
3191
|
+
import: true,
|
|
3192
|
+
export: true,
|
|
3193
|
+
sourcePreserving: true
|
|
3194
|
+
},
|
|
3195
|
+
{
|
|
3196
|
+
format: "json",
|
|
3197
|
+
import: true,
|
|
3198
|
+
export: true
|
|
3199
|
+
},
|
|
3200
|
+
{
|
|
3201
|
+
format: "yaml",
|
|
3202
|
+
import: true,
|
|
3203
|
+
export: true
|
|
3206
3204
|
}
|
|
3207
|
-
|
|
3208
|
-
|
|
3209
|
-
|
|
3210
|
-
|
|
3211
|
-
|
|
3205
|
+
];
|
|
3206
|
+
const XSTATE_PROFILE_MANIFESTS = [{
|
|
3207
|
+
profile: XSTATE_V5_PROFILE,
|
|
3208
|
+
name: "XState v5",
|
|
3209
|
+
formats: [...XSTATE_FORMATS]
|
|
3210
|
+
}, {
|
|
3211
|
+
profile: XSTATE_V6_PROFILE,
|
|
3212
|
+
name: "XState v6",
|
|
3213
|
+
formats: [...XSTATE_FORMATS]
|
|
3214
|
+
}];
|
|
3215
|
+
const PROFILE_MANIFESTS = new Map(XSTATE_PROFILE_MANIFESTS.map((manifest) => [manifest.profile, manifest]));
|
|
3216
|
+
const XSTATE_V6_FN_TRANSITION_META = "@statelyai.xstate.v6.fnTransition";
|
|
3217
|
+
const XSTATE_V6_FN_SOURCE_META = "@statelyai.xstate.v6.fnSource";
|
|
3218
|
+
function sourceFile(source) {
|
|
3219
|
+
return ts.createSourceFile("machine.ts", source, ts.ScriptTarget.Latest, true, ts.ScriptKind.TSX);
|
|
3212
3220
|
}
|
|
3213
|
-
function
|
|
3214
|
-
if (
|
|
3215
|
-
|
|
3216
|
-
if (typeof def === "boolean") return void 0;
|
|
3217
|
-
return def;
|
|
3221
|
+
function propName(name) {
|
|
3222
|
+
if (ts.isIdentifier(name) || ts.isStringLiteral(name) || ts.isNumericLiteral(name)) return name.text;
|
|
3223
|
+
return null;
|
|
3218
3224
|
}
|
|
3219
|
-
|
|
3220
|
-
|
|
3221
|
-
|
|
3222
|
-
*/
|
|
3223
|
-
function contextSchemaToTSType(context) {
|
|
3224
|
-
if (!context || Object.keys(context).length === 0) return null;
|
|
3225
|
-
return `{ ${Object.entries(context).map(([key, schema]) => {
|
|
3226
|
-
return `${key}: ${jsonSchemaToTSType(schema)}`;
|
|
3227
|
-
}).join("; ")} }`;
|
|
3225
|
+
function unwrapExpression(node) {
|
|
3226
|
+
if (ts.isAsExpression(node) || ts.isSatisfiesExpression(node) || ts.isNonNullExpression(node) || ts.isParenthesizedExpression(node)) return unwrapExpression(node.expression);
|
|
3227
|
+
return node;
|
|
3228
3228
|
}
|
|
3229
|
-
|
|
3230
|
-
|
|
3231
|
-
|
|
3232
|
-
|
|
3233
|
-
|
|
3234
|
-
if (
|
|
3235
|
-
|
|
3236
|
-
|
|
3237
|
-
|
|
3238
|
-
|
|
3239
|
-
|
|
3240
|
-
|
|
3241
|
-
|
|
3242
|
-
|
|
3243
|
-
|
|
3244
|
-
|
|
3245
|
-
|
|
3229
|
+
function propertyContext(parent, key) {
|
|
3230
|
+
if (parent.invokeValue && key === "src") return {
|
|
3231
|
+
v6: parent.v6,
|
|
3232
|
+
actorSourceValue: true
|
|
3233
|
+
};
|
|
3234
|
+
if (parent.transitionMap) return {
|
|
3235
|
+
v6: parent.v6,
|
|
3236
|
+
transitionValue: true
|
|
3237
|
+
};
|
|
3238
|
+
if (parent.transitionValue && key === "actions") return {
|
|
3239
|
+
v6: parent.v6,
|
|
3240
|
+
actionValue: true
|
|
3241
|
+
};
|
|
3242
|
+
if (parent.transitionValue && key === "context") return {
|
|
3243
|
+
v6: parent.v6,
|
|
3244
|
+
assignmentMap: true,
|
|
3245
|
+
transitionContext: true
|
|
3246
|
+
};
|
|
3247
|
+
if (parent.assignmentMap) return {
|
|
3248
|
+
v6: parent.v6,
|
|
3249
|
+
assignmentValue: true
|
|
3250
|
+
};
|
|
3251
|
+
if (key === "meta") return {
|
|
3252
|
+
v6: parent.v6,
|
|
3253
|
+
metaValue: true
|
|
3254
|
+
};
|
|
3255
|
+
if (parent.transitionValue && key === "to") return {
|
|
3256
|
+
v6: parent.v6,
|
|
3257
|
+
transitionValue: true
|
|
3258
|
+
};
|
|
3259
|
+
if (key === "entry" || key === "exit") return {
|
|
3260
|
+
v6: parent.v6,
|
|
3261
|
+
actionValue: true
|
|
3262
|
+
};
|
|
3263
|
+
if (key === "input" || key === "output") return {
|
|
3264
|
+
v6: parent.v6,
|
|
3265
|
+
ioValue: true
|
|
3266
|
+
};
|
|
3267
|
+
if (parent.ioValue || parent.ioPropertyValue) return {
|
|
3268
|
+
v6: parent.v6,
|
|
3269
|
+
ioPropertyValue: true
|
|
3270
|
+
};
|
|
3271
|
+
if (key === "invoke") return {
|
|
3272
|
+
v6: parent.v6,
|
|
3273
|
+
invokeValue: true
|
|
3274
|
+
};
|
|
3275
|
+
if (key === "timeout") return {
|
|
3276
|
+
v6: parent.v6,
|
|
3277
|
+
timeoutValue: true
|
|
3278
|
+
};
|
|
3279
|
+
if (key === "route") return {
|
|
3280
|
+
v6: parent.v6,
|
|
3281
|
+
routeValue: true
|
|
3282
|
+
};
|
|
3283
|
+
if (key === "on" || key === "after") return {
|
|
3284
|
+
v6: parent.v6,
|
|
3285
|
+
transitionMap: true
|
|
3286
|
+
};
|
|
3287
|
+
if (key === "always" || key === "choice" || key === "onDone" || key === "onError" || key === "onSnapshot" || key === "onTimeout") return {
|
|
3288
|
+
v6: parent.v6,
|
|
3289
|
+
transitionValue: true
|
|
3290
|
+
};
|
|
3291
|
+
return { v6: parent.v6 };
|
|
3246
3292
|
}
|
|
3247
|
-
function
|
|
3248
|
-
return
|
|
3293
|
+
function fallbackFunctionTransition(fn, actions = []) {
|
|
3294
|
+
return {
|
|
3295
|
+
...actions.length ? { actions } : void 0,
|
|
3296
|
+
meta: {
|
|
3297
|
+
[XSTATE_V6_FN_TRANSITION_META]: true,
|
|
3298
|
+
[XSTATE_V6_FN_SOURCE_META]: fn.getText()
|
|
3299
|
+
}
|
|
3300
|
+
};
|
|
3249
3301
|
}
|
|
3250
|
-
function
|
|
3251
|
-
|
|
3252
|
-
return typeof def === "object" && def !== null && def.required === true;
|
|
3302
|
+
function conditionText(cond) {
|
|
3303
|
+
return cond.negated ? `!(${cond.text})` : cond.text;
|
|
3253
3304
|
}
|
|
3254
|
-
function
|
|
3255
|
-
const
|
|
3256
|
-
|
|
3257
|
-
|
|
3258
|
-
|
|
3259
|
-
|
|
3260
|
-
|
|
3261
|
-
|
|
3262
|
-
const hasActors = !!impls?.actors.length;
|
|
3263
|
-
const hasDelays = !!impls?.delays.length;
|
|
3264
|
-
const hasSetup = hasSchemas || hasActions || hasGuards || hasActors || hasDelays;
|
|
3265
|
-
const builtInActions = getUsedBuiltInActions(graph, xstateVersion);
|
|
3266
|
-
const actorSourceImports = getActorSourceImports(graph);
|
|
3267
|
-
const imports = buildImports({
|
|
3268
|
-
hasSetup,
|
|
3269
|
-
hasActors,
|
|
3270
|
-
actors: impls?.actors ?? [],
|
|
3271
|
-
builtInActions,
|
|
3272
|
-
actorSourceImports,
|
|
3273
|
-
usesTypes: xstateVersion === 6 && supportsTypeSyntax && hasSchemas
|
|
3305
|
+
function simplifyConditions(conds) {
|
|
3306
|
+
const seen = /* @__PURE__ */ new Set();
|
|
3307
|
+
return conds.filter((cond) => {
|
|
3308
|
+
if (cond.negated) return false;
|
|
3309
|
+
const key = conditionText(cond);
|
|
3310
|
+
if (seen.has(key)) return false;
|
|
3311
|
+
seen.add(key);
|
|
3312
|
+
return true;
|
|
3274
3313
|
});
|
|
3275
|
-
const machineConfig = xstateVersion === 6 ? toV6MachineConfig(graphToMachineConfig(graph, configOptions)) : toV5MachineConfig(graphToMachineConfig(graph, configOptions));
|
|
3276
|
-
let machineExpr;
|
|
3277
|
-
if (hasSetup) {
|
|
3278
|
-
const setupObj = buildSetupObject(schemas, impls, {
|
|
3279
|
-
includeTypeSyntax: supportsTypeSyntax,
|
|
3280
|
-
xstateVersion
|
|
3281
|
-
});
|
|
3282
|
-
const configStr = serializeJS(machineConfig, 2);
|
|
3283
|
-
machineExpr = `setup(${serializeJS(setupObj, 0)}).createMachine(${configStr})`;
|
|
3284
|
-
} else machineExpr = `createMachine(${serializeJS(machineConfig, 0)})`;
|
|
3285
|
-
const lines = [];
|
|
3286
|
-
lines.push(imports);
|
|
3287
|
-
lines.push("");
|
|
3288
|
-
lines.push(`const machine = ${machineExpr};`);
|
|
3289
|
-
if (exportStyle === "named") {
|
|
3290
|
-
lines.push("");
|
|
3291
|
-
lines.push("export { machine };");
|
|
3292
|
-
} else if (exportStyle === "default") {
|
|
3293
|
-
lines.push("");
|
|
3294
|
-
lines.push("export default machine;");
|
|
3295
|
-
}
|
|
3296
|
-
return lines.join("\n") + "\n";
|
|
3297
3314
|
}
|
|
3298
|
-
function
|
|
3299
|
-
|
|
3315
|
+
function hashString(value) {
|
|
3316
|
+
let hash = 5381;
|
|
3317
|
+
for (let i = 0; i < value.length; i++) hash = hash * 33 ^ value.charCodeAt(i);
|
|
3318
|
+
return (hash >>> 0).toString(36);
|
|
3319
|
+
}
|
|
3320
|
+
function inlineGuardCode(params, condition) {
|
|
3321
|
+
return `${params} => ${condition}`;
|
|
3322
|
+
}
|
|
3323
|
+
function guardFromConditions(conds, params) {
|
|
3324
|
+
const simplified = simplifyConditions(conds);
|
|
3325
|
+
if (simplified.length === 0) return void 0;
|
|
3326
|
+
const code = inlineGuardCode(params, simplified.map(conditionText).join(" && "));
|
|
3300
3327
|
return {
|
|
3301
|
-
|
|
3302
|
-
|
|
3303
|
-
guards: impls.guards.filter((guard) => !guard.name.startsWith("inline:")),
|
|
3304
|
-
delays: impls.delays.filter((delay) => !delay.name.startsWith("inline:"))
|
|
3328
|
+
type: `inline:${hashString(code)}`,
|
|
3329
|
+
code
|
|
3305
3330
|
};
|
|
3306
3331
|
}
|
|
3307
|
-
|
|
3308
|
-
|
|
3309
|
-
"xstate.raise": "raise",
|
|
3310
|
-
"xstate.sendTo": "sendTo",
|
|
3311
|
-
"xstate.cancel": "cancel",
|
|
3312
|
-
"xstate.emit": "emit",
|
|
3313
|
-
"xstate.spawnChild": "spawnChild",
|
|
3314
|
-
"xstate.stopChild": "stopChild",
|
|
3315
|
-
"xstate.log": "log",
|
|
3316
|
-
"xstate.assign": "assign"
|
|
3317
|
-
};
|
|
3318
|
-
/** Check inline action/entry/exit code for references to xstate builtins */
|
|
3319
|
-
function scanInlineCodeForBuiltins(code, used) {
|
|
3320
|
-
const expr = stripExportDefault(code);
|
|
3321
|
-
for (const importName of Object.values(BUILTIN_ACTION_IMPORTS)) if (new RegExp(`\\b${importName}\\b`).test(expr)) used.add(importName);
|
|
3332
|
+
function wrapAssignExpression(expr) {
|
|
3333
|
+
return `{{ ${expr.trim()} }}`;
|
|
3322
3334
|
}
|
|
3323
|
-
function
|
|
3324
|
-
return
|
|
3325
|
-
}
|
|
3326
|
-
function getUsedBuiltInActions(graph, xstateVersion) {
|
|
3327
|
-
const used = /* @__PURE__ */ new Set();
|
|
3328
|
-
if (xstateVersion === 6) return used;
|
|
3329
|
-
for (const node of graph.nodes) for (const action of [...node.data.entry ?? [], ...node.data.exit ?? []]) {
|
|
3330
|
-
const imp = BUILTIN_ACTION_IMPORTS[action.type];
|
|
3331
|
-
if (imp) used.add(imp);
|
|
3332
|
-
const exprCode = getExprActionCode(action);
|
|
3333
|
-
if (exprCode) scanInlineCodeForBuiltins(exprCode, used);
|
|
3334
|
-
}
|
|
3335
|
-
for (const edge of graph.edges) for (const action of edge.data.actions ?? []) {
|
|
3336
|
-
const imp = BUILTIN_ACTION_IMPORTS[action.type];
|
|
3337
|
-
if (imp) used.add(imp);
|
|
3338
|
-
const exprCode = getExprActionCode(action);
|
|
3339
|
-
if (exprCode) scanInlineCodeForBuiltins(exprCode, used);
|
|
3340
|
-
}
|
|
3341
|
-
return used;
|
|
3342
|
-
}
|
|
3343
|
-
function toV5MachineConfig(machineConfig) {
|
|
3344
|
-
return mapMachineActionFields(machineConfig, (actions, wasArray) => {
|
|
3345
|
-
const mapped = actions.map(unwrapDirectEnqExpression);
|
|
3346
|
-
return wasArray ? mapped : mapped[0];
|
|
3347
|
-
});
|
|
3348
|
-
}
|
|
3349
|
-
function toV6MachineConfig(machineConfig) {
|
|
3350
|
-
return mapV6MachineConfig(machineConfig);
|
|
3351
|
-
}
|
|
3352
|
-
function mapV6MachineConfig(value, context = {}) {
|
|
3353
|
-
if (Array.isArray(value)) return value.map((item) => mapV6MachineConfig(item, context));
|
|
3354
|
-
if (!value || typeof value !== "object") return value;
|
|
3355
|
-
if (context.transitionValue) return toV6TransitionValue(value);
|
|
3356
|
-
const result = {};
|
|
3357
|
-
for (const [key, item] of Object.entries(value)) {
|
|
3358
|
-
if (key === "entry" || key === "exit" || key === "actions") {
|
|
3359
|
-
result[key] = toV6ActionField(Array.isArray(item) ? item : item === void 0 ? [] : [item]);
|
|
3360
|
-
continue;
|
|
3361
|
-
}
|
|
3362
|
-
if (key === "on" || key === "after") {
|
|
3363
|
-
result[key] = mapV6TransitionMap(item);
|
|
3364
|
-
continue;
|
|
3365
|
-
}
|
|
3366
|
-
if (key === "always" || key === "onDone" || key === "onError" || key === "onSnapshot" || key === "onTimeout") {
|
|
3367
|
-
result[key] = mapV6MachineConfig(item, { transitionValue: true });
|
|
3368
|
-
continue;
|
|
3369
|
-
}
|
|
3370
|
-
result[key] = mapV6MachineConfig(item);
|
|
3371
|
-
}
|
|
3372
|
-
return result;
|
|
3373
|
-
}
|
|
3374
|
-
function mapV6TransitionMap(value) {
|
|
3375
|
-
if (!value || typeof value !== "object" || Array.isArray(value)) return value;
|
|
3376
|
-
const result = {};
|
|
3377
|
-
for (const [key, item] of Object.entries(value)) result[key] = mapV6MachineConfig(item, { transitionValue: true });
|
|
3378
|
-
return result;
|
|
3379
|
-
}
|
|
3380
|
-
function toV6TransitionValue(value) {
|
|
3381
|
-
if (Array.isArray(value)) return value.map((item) => toV6TransitionValue(item));
|
|
3382
|
-
if (!value || typeof value !== "object") return value;
|
|
3383
|
-
const transition = value;
|
|
3384
|
-
if (transition.guard || transition.description || transition.input !== void 0) return mapV6MachineConfig(transition);
|
|
3385
|
-
const target = transition.target;
|
|
3386
|
-
const context = transition.context;
|
|
3387
|
-
const actionsValue = transition.actions;
|
|
3388
|
-
const actions = Array.isArray(actionsValue) ? actionsValue : actionsValue === void 0 ? [] : [actionsValue];
|
|
3389
|
-
if (actions.length === 0 && typeof target === "string" && context === void 0 && !transition.reenter && !transition.meta) return target;
|
|
3390
|
-
if (actions.length === 0 && target === void 0 && context === void 0) return mapV6MachineConfig(transition);
|
|
3391
|
-
return buildV6ActionFunction(actions, {
|
|
3392
|
-
target: typeof target === "string" ? target : void 0,
|
|
3393
|
-
reenter: transition.reenter === true,
|
|
3394
|
-
meta: transition.meta,
|
|
3395
|
-
context
|
|
3396
|
-
}) ?? mapV6MachineConfig(transition);
|
|
3397
|
-
}
|
|
3398
|
-
function toV6ActionField(actions) {
|
|
3399
|
-
if (actions.length === 1) {
|
|
3400
|
-
const expr = inlineExpr(actions[0]);
|
|
3401
|
-
if (expr && isCompleteFunctionExpression(stripExportDefault(expr))) return raw(stripExportDefault(expr));
|
|
3402
|
-
}
|
|
3403
|
-
return buildV6ActionFunction(actions) ?? actions;
|
|
3404
|
-
}
|
|
3405
|
-
function buildV6ActionFunction(actions, transition) {
|
|
3406
|
-
const effects = actions.map(actionToV6Effect);
|
|
3407
|
-
if (effects.some((effect) => !effect)) return void 0;
|
|
3408
|
-
const statements = effects.flatMap((effect) => effect?.statements ?? []);
|
|
3409
|
-
let returnValue;
|
|
3410
|
-
let contextValue;
|
|
3411
|
-
for (const effect of effects) {
|
|
3412
|
-
returnValue = effect?.returnValue ?? returnValue;
|
|
3413
|
-
contextValue = effect?.contextValue ?? contextValue;
|
|
3414
|
-
}
|
|
3415
|
-
if (transition) returnValue = buildV6TransitionReturnValue(transition, transition.context === void 0 ? contextValue : serializeJS(unwrapTemplateExpressions(transition.context)));
|
|
3416
|
-
if (statements.length === 0 && !returnValue) return void 0;
|
|
3417
|
-
return raw(`(_, enq) => {\n${[...statements.map((statement) => ` ${statement};`), ...returnValue ? [` return ${returnValue};`] : []].join("\n")}\n}`);
|
|
3418
|
-
}
|
|
3419
|
-
function unwrapTemplateExpressions(value) {
|
|
3420
|
-
if (typeof value === "string") {
|
|
3421
|
-
const match = value.match(/^\{\{\s*([\s\S]*?)\s*\}\}$/);
|
|
3422
|
-
return match?.[1] ? raw(match[1]) : value;
|
|
3423
|
-
}
|
|
3424
|
-
if (Array.isArray(value)) return value.map(unwrapTemplateExpressions);
|
|
3425
|
-
if (!value || typeof value !== "object") return value;
|
|
3426
|
-
return Object.fromEntries(Object.entries(value).map(([key, item]) => [key, unwrapTemplateExpressions(item)]));
|
|
3427
|
-
}
|
|
3428
|
-
function buildV6TransitionReturnValue(transition, contextValue) {
|
|
3429
|
-
if (!transition.reenter && !transition.meta && !contextValue) return transition.target ? `{ target: ${serializeJS(transition.target)} }` : void 0;
|
|
3430
|
-
return serializeJS({
|
|
3431
|
-
target: transition.target,
|
|
3432
|
-
reenter: transition.reenter ? true : void 0,
|
|
3433
|
-
meta: transition.meta,
|
|
3434
|
-
context: contextValue ? raw(contextValue) : void 0
|
|
3435
|
-
});
|
|
3436
|
-
}
|
|
3437
|
-
function mapMachineActionFields(value, mapActions) {
|
|
3438
|
-
if (Array.isArray(value)) return value.map((item) => mapMachineActionFields(item, mapActions));
|
|
3439
|
-
if (!value || typeof value !== "object") return value;
|
|
3440
|
-
const result = {};
|
|
3441
|
-
for (const [key, item] of Object.entries(value)) {
|
|
3442
|
-
if (key === "entry" || key === "exit" || key === "actions") {
|
|
3443
|
-
const wasArray = Array.isArray(item);
|
|
3444
|
-
result[key] = mapActions(wasArray ? item : item === void 0 ? [] : [item], wasArray);
|
|
3445
|
-
continue;
|
|
3446
|
-
}
|
|
3447
|
-
result[key] = mapMachineActionFields(item, mapActions);
|
|
3448
|
-
}
|
|
3449
|
-
return result;
|
|
3450
|
-
}
|
|
3451
|
-
function unwrapDirectEnqExpression(action) {
|
|
3452
|
-
const expr = inlineExpr(action);
|
|
3453
|
-
if (!expr) return action;
|
|
3454
|
-
const match = expr.match(/^enq\(([\s\S]*)\)$/);
|
|
3455
|
-
return match?.[1] ? raw(match[1]) : action;
|
|
3456
|
-
}
|
|
3457
|
-
function inlineExpr(value) {
|
|
3458
|
-
if (!value || typeof value !== "object" || Array.isArray(value)) return;
|
|
3459
|
-
const directive = value;
|
|
3460
|
-
return directive["@type"] === "code" && typeof directive.expr === "string" ? directive.expr : void 0;
|
|
3461
|
-
}
|
|
3462
|
-
function actionToV6Effect(action) {
|
|
3463
|
-
const expr = inlineExpr(action);
|
|
3464
|
-
if (expr) {
|
|
3465
|
-
if (expr.startsWith("enq(") || expr.startsWith("enq.")) return { statements: [expr] };
|
|
3466
|
-
const builtIn = expr.match(/^(raise|emit|sendTo|cancel|log|spawnChild|stopChild)\(([\s\S]*)\)$/);
|
|
3467
|
-
if (builtIn) {
|
|
3468
|
-
const [, name, args] = builtIn;
|
|
3469
|
-
return { statements: [`enq.${name === "spawnChild" ? "spawn" : name === "stopChild" ? "stop" : name}(${args})`] };
|
|
3470
|
-
}
|
|
3471
|
-
return { statements: [`enq(${expr})`] };
|
|
3472
|
-
}
|
|
3473
|
-
if (!action || typeof action !== "object" || Array.isArray(action)) return null;
|
|
3474
|
-
const record = action;
|
|
3475
|
-
const type = record.type;
|
|
3476
|
-
if (typeof type !== "string") return null;
|
|
3477
|
-
const params = record.params && typeof record.params === "object" && !Array.isArray(record.params) ? record.params : {};
|
|
3478
|
-
if (type === "xstate.raise") {
|
|
3479
|
-
const options = actionOptions(params, ["event"]);
|
|
3480
|
-
return { statements: [`enq.raise(${serializeJS(params.event)}${options})`] };
|
|
3481
|
-
}
|
|
3482
|
-
if (type === "xstate.emit") return { statements: [`enq.emit(${serializeJS(params.event)})`] };
|
|
3483
|
-
if (type === "xstate.sendTo") {
|
|
3484
|
-
const options = actionOptions(params, ["to", "event"]);
|
|
3485
|
-
return { statements: [`enq.sendTo(${serializeJS(params.to)}, ${serializeJS(params.event)}${options})`] };
|
|
3486
|
-
}
|
|
3487
|
-
if (type === "xstate.cancel") return { statements: [`enq.cancel(${serializeJS(params.sendId)})`] };
|
|
3488
|
-
if (type === "xstate.log") return { statements: [`enq.log(${serializeJS(params.label)})`] };
|
|
3489
|
-
if (type === "xstate.spawnChild") {
|
|
3490
|
-
const options = actionOptions(params, ["src"]);
|
|
3491
|
-
return { statements: [`enq.spawn(${serializeJS(params.src)}${options})`] };
|
|
3492
|
-
}
|
|
3493
|
-
if (type === "xstate.stopChild") return { statements: [`enq.stop(${serializeJS(params.actorRef)})`] };
|
|
3494
|
-
if (type === "xstate.assign") {
|
|
3495
|
-
const contextValue = serializeJS(params.assignment ?? params);
|
|
3496
|
-
return {
|
|
3497
|
-
contextValue,
|
|
3498
|
-
returnValue: `{ context: ${contextValue} }`
|
|
3499
|
-
};
|
|
3500
|
-
}
|
|
3501
|
-
return null;
|
|
3502
|
-
}
|
|
3503
|
-
function actionOptions(params, consumedKeys) {
|
|
3504
|
-
const rest = Object.fromEntries(Object.entries(params).filter(([key, value]) => !consumedKeys.includes(key) && value !== void 0));
|
|
3505
|
-
return Object.keys(rest).length ? `, ${serializeJS(rest)}` : "";
|
|
3506
|
-
}
|
|
3507
|
-
function buildImports({ hasSetup, hasActors, actors, builtInActions, actorSourceImports, usesTypes }) {
|
|
3508
|
-
const xstateImports = [];
|
|
3509
|
-
if (hasSetup) xstateImports.push("setup");
|
|
3510
|
-
else xstateImports.push("createMachine");
|
|
3511
|
-
for (const name of builtInActions) xstateImports.push(name);
|
|
3512
|
-
for (const name of actorSourceImports) xstateImports.push(name);
|
|
3513
|
-
if (usesTypes) xstateImports.push("types");
|
|
3514
|
-
if (hasActors) {
|
|
3515
|
-
if (actors.length > 0) xstateImports.push("fromPromise");
|
|
3516
|
-
}
|
|
3517
|
-
return `import { ${[...new Set(xstateImports)].join(", ")} } from 'xstate';`;
|
|
3518
|
-
}
|
|
3519
|
-
function getActorSourceImports(graph) {
|
|
3520
|
-
const imports = /* @__PURE__ */ new Set();
|
|
3521
|
-
const candidates = [
|
|
3522
|
-
"createAsyncLogic",
|
|
3523
|
-
"fromPromise",
|
|
3524
|
-
"fromCallback",
|
|
3525
|
-
"fromObservable",
|
|
3526
|
-
"fromEventObservable",
|
|
3527
|
-
"fromTransition"
|
|
3528
|
-
];
|
|
3529
|
-
for (const node of graph.nodes) for (const invoke of node.data.invokes ?? []) {
|
|
3530
|
-
const expression = invoke.srcExpression?.expr;
|
|
3531
|
-
if (!expression) continue;
|
|
3532
|
-
for (const candidate of candidates) if (new RegExp(`\\b${candidate}\\b`).test(expression)) imports.add(candidate);
|
|
3533
|
-
}
|
|
3534
|
-
return imports;
|
|
3535
|
-
}
|
|
3536
|
-
function buildSetupObject(schemas, impls, options) {
|
|
3537
|
-
const setup = {};
|
|
3538
|
-
if (options.xstateVersion === 6) {
|
|
3539
|
-
const schemasBlock = buildV6SchemasBlock(schemas, options);
|
|
3540
|
-
if (schemasBlock) setup.schemas = schemasBlock;
|
|
3541
|
-
} else {
|
|
3542
|
-
const types = buildTypesBlock(schemas, options);
|
|
3543
|
-
if (types) setup.types = types;
|
|
3544
|
-
}
|
|
3545
|
-
if (impls?.actions.length) setup.actions = buildActionsBlock(impls.actions, options);
|
|
3546
|
-
if (impls?.guards.length) setup.guards = buildGuardsBlock(impls.guards, options);
|
|
3547
|
-
if (impls?.actors.length) setup.actors = buildActorsBlock(impls.actors, options);
|
|
3548
|
-
if (impls?.delays.length) setup.delays = buildDelaysBlock(impls.delays);
|
|
3549
|
-
return setup;
|
|
3550
|
-
}
|
|
3551
|
-
function buildTypesBlock(schemas, options) {
|
|
3552
|
-
if (!schemas || !options.includeTypeSyntax) return void 0;
|
|
3553
|
-
const types = {};
|
|
3554
|
-
const contextType = contextSchemaToTSType(schemas.context);
|
|
3555
|
-
if (contextType) types.context = raw(`{} as ${contextType}`);
|
|
3556
|
-
const eventsType = eventsSchemaToTSType(schemas.events);
|
|
3557
|
-
if (eventsType) types.events = raw(`{} as\n | ${eventsType}`);
|
|
3558
|
-
if (schemas.input) types.input = raw(`{} as ${jsonSchemaToTSType(schemas.input)}`);
|
|
3559
|
-
if (schemas.output) types.output = raw(`{} as ${jsonSchemaToTSType(schemas.output)}`);
|
|
3560
|
-
return Object.keys(types).length > 0 ? types : void 0;
|
|
3561
|
-
}
|
|
3562
|
-
function buildV6SchemasBlock(schemas, options) {
|
|
3563
|
-
if (!schemas || !options.includeTypeSyntax) return void 0;
|
|
3564
|
-
const result = {};
|
|
3565
|
-
const contextType = contextSchemaToTSType(schemas.context);
|
|
3566
|
-
if (contextType) result.context = raw(`types<${contextType}>()`);
|
|
3567
|
-
if (schemas.events && Object.keys(schemas.events).length > 0) result.events = Object.fromEntries(Object.entries(schemas.events).map(([eventType, schema]) => [eventType, raw(`types<${eventPayloadSchemaToTSType(schema)}>()`)]));
|
|
3568
|
-
if (schemas.input) result.input = raw(`types<${jsonSchemaToTSType(schemas.input)}>()`);
|
|
3569
|
-
if (schemas.output) result.output = raw(`types<${jsonSchemaToTSType(schemas.output)}>()`);
|
|
3570
|
-
return Object.keys(result).length > 0 ? result : void 0;
|
|
3571
|
-
}
|
|
3572
|
-
function eventPayloadSchemaToTSType(schema) {
|
|
3573
|
-
const props = schema.properties ?? {};
|
|
3574
|
-
const payloadProps = Object.fromEntries(Object.entries(props).filter(([key]) => key !== "type"));
|
|
3575
|
-
if (Object.keys(payloadProps).length === 0) return "{}";
|
|
3576
|
-
return jsonSchemaToTSType({
|
|
3577
|
-
...schema,
|
|
3578
|
-
properties: payloadProps,
|
|
3579
|
-
required: Array.isArray(schema.required) ? schema.required.filter((key) => key !== "type") : void 0
|
|
3580
|
-
});
|
|
3581
|
-
}
|
|
3582
|
-
function hasSchemaProperties(schema) {
|
|
3583
|
-
if (!schema) return false;
|
|
3584
|
-
if (schema.type === "object" || schema.properties) {
|
|
3585
|
-
const props = schema.properties;
|
|
3586
|
-
return !!props && Object.keys(props).length > 0;
|
|
3587
|
-
}
|
|
3588
|
-
return true;
|
|
3589
|
-
}
|
|
3590
|
-
function buildActionsBlock(actions, options) {
|
|
3591
|
-
const block = {};
|
|
3592
|
-
for (const implementation of actions) if (implementation.code?.body) {
|
|
3593
|
-
const inlineExpression = getInlineExpression(implementation.code.body);
|
|
3594
|
-
if (inlineExpression) {
|
|
3595
|
-
block[implementation.name] = raw(inlineExpression);
|
|
3596
|
-
continue;
|
|
3597
|
-
}
|
|
3598
|
-
const params = hasSchemaProperties(implementation.paramsSchema) ? options.includeTypeSyntax ? `, params: ${jsonSchemaToTSType(implementation.paramsSchema)}` : ", params" : "";
|
|
3599
|
-
block[implementation.name] = raw(`function ({ context, event }${params ? params : ""}) {\n ${dedent(implementation.code.body)}\n}`);
|
|
3600
|
-
} else block[implementation.name] = raw(`function ({ context, event }) {\n // TODO: implement ${implementation.name}\n}`);
|
|
3601
|
-
return block;
|
|
3602
|
-
}
|
|
3603
|
-
function buildGuardsBlock(guards, options) {
|
|
3604
|
-
const block = {};
|
|
3605
|
-
for (const guard of guards) if (guard.code?.body) {
|
|
3606
|
-
const inlineExpression = getInlineExpression(guard.code.body);
|
|
3607
|
-
if (inlineExpression) {
|
|
3608
|
-
block[guard.name] = raw(inlineExpression);
|
|
3609
|
-
continue;
|
|
3610
|
-
}
|
|
3611
|
-
const params = hasSchemaProperties(guard.paramsSchema) ? options.includeTypeSyntax ? `, params: ${jsonSchemaToTSType(guard.paramsSchema)}` : ", params" : "";
|
|
3612
|
-
block[guard.name] = raw(`function ({ context, event }${params ? params : ""}) {\n ${dedent(guard.code.body)}\n}`);
|
|
3613
|
-
} else block[guard.name] = raw(`function ({ context, event }) {\n // TODO: implement ${guard.name}\n return false;\n}`);
|
|
3614
|
-
return block;
|
|
3615
|
-
}
|
|
3616
|
-
function buildActorsBlock(actors, options) {
|
|
3617
|
-
const block = {};
|
|
3618
|
-
for (const actor of actors) if (actor.code?.body) {
|
|
3619
|
-
const inputType = options.includeTypeSyntax && hasSchemaProperties(actor.inputSchema) ? `: ${jsonSchemaToTSType(actor.inputSchema)}` : "";
|
|
3620
|
-
block[actor.name] = raw(`fromPromise(async ({ input }${inputType ? `: { input${inputType} }` : ""}) => {\n ${dedent(actor.code.body)}\n})`);
|
|
3621
|
-
} else block[actor.name] = raw(`fromPromise(async ({ input }) => {\n // TODO: implement ${actor.name}\n})`);
|
|
3622
|
-
return block;
|
|
3623
|
-
}
|
|
3624
|
-
function buildDelaysBlock(delays) {
|
|
3625
|
-
const block = {};
|
|
3626
|
-
for (const delay of delays) if (delay.code?.body) {
|
|
3627
|
-
const inlineExpression = getInlineExpression(delay.code.body);
|
|
3628
|
-
if (inlineExpression) {
|
|
3629
|
-
block[delay.name] = raw(inlineExpression);
|
|
3630
|
-
continue;
|
|
3631
|
-
}
|
|
3632
|
-
block[delay.name] = raw(`function ({ context, event }) {\n ${dedent(delay.code.body)}\n}`);
|
|
3633
|
-
} else block[delay.name] = raw(`function () {\n // TODO: implement ${delay.name}\n return 1000;\n}`);
|
|
3634
|
-
return block;
|
|
3635
|
-
}
|
|
3636
|
-
/**
|
|
3637
|
-
* Returns the implementation to emit verbatim when `body` is already a complete
|
|
3638
|
-
* expression, so it is NOT wrapped in another `function ({ context, event }) { ... }`.
|
|
3639
|
-
* Handles two cases:
|
|
3640
|
-
* - `export default <expr>` → the inner expression.
|
|
3641
|
-
* - a bare function/arrow expression (e.g. a guard captured via `fn.toString()`
|
|
3642
|
-
* on import) → the expression itself.
|
|
3643
|
-
* Returns undefined for a plain statement body, which still needs wrapping.
|
|
3644
|
-
*/
|
|
3645
|
-
function getInlineExpression(code) {
|
|
3646
|
-
const stripped = stripExportDefault(code);
|
|
3647
|
-
if (stripped !== code.trim()) return stripped;
|
|
3648
|
-
return isCompleteFunctionExpression(stripped) ? stripped : void 0;
|
|
3649
|
-
}
|
|
3650
|
-
/** True when `code` is a single function or arrow-function expression. */
|
|
3651
|
-
function isCompleteFunctionExpression(code) {
|
|
3652
|
-
const candidate = code.trim().replace(/;$/, "");
|
|
3653
|
-
const source = ts.createSourceFile("impl.ts", `(${candidate})`, ts.ScriptTarget.Latest, false, ts.ScriptKind.TS);
|
|
3654
|
-
if ((source.parseDiagnostics ?? []).length > 0 || source.statements.length !== 1) return false;
|
|
3655
|
-
const [statement] = source.statements;
|
|
3656
|
-
if (!statement || !ts.isExpressionStatement(statement)) return false;
|
|
3657
|
-
let expression = statement.expression;
|
|
3658
|
-
if (ts.isParenthesizedExpression(expression)) expression = expression.expression;
|
|
3659
|
-
return ts.isFunctionExpression(expression) || ts.isArrowFunction(expression);
|
|
3660
|
-
}
|
|
3661
|
-
const XSTATE_V6_FN_TRANSITION_META = "@statelyai.xstate.v6.fnTransition";
|
|
3662
|
-
const XSTATE_V6_FN_SOURCE_META = "@statelyai.xstate.v6.fnSource";
|
|
3663
|
-
function sourceFile(source) {
|
|
3664
|
-
return ts.createSourceFile("machine.ts", source, ts.ScriptTarget.Latest, true, ts.ScriptKind.TSX);
|
|
3665
|
-
}
|
|
3666
|
-
function propName(name) {
|
|
3667
|
-
if (ts.isIdentifier(name) || ts.isStringLiteral(name) || ts.isNumericLiteral(name)) return name.text;
|
|
3668
|
-
return null;
|
|
3669
|
-
}
|
|
3670
|
-
function unwrapExpression(node) {
|
|
3671
|
-
if (ts.isAsExpression(node) || ts.isSatisfiesExpression(node) || ts.isNonNullExpression(node) || ts.isParenthesizedExpression(node)) return unwrapExpression(node.expression);
|
|
3672
|
-
return node;
|
|
3673
|
-
}
|
|
3674
|
-
function propertyContext(parent, key) {
|
|
3675
|
-
if (parent.invokeValue && key === "src") return {
|
|
3676
|
-
v6: parent.v6,
|
|
3677
|
-
actorSourceValue: true
|
|
3678
|
-
};
|
|
3679
|
-
if (parent.transitionMap) return {
|
|
3680
|
-
v6: parent.v6,
|
|
3681
|
-
transitionValue: true
|
|
3682
|
-
};
|
|
3683
|
-
if (parent.transitionValue && key === "actions") return {
|
|
3684
|
-
v6: parent.v6,
|
|
3685
|
-
actionValue: true
|
|
3686
|
-
};
|
|
3687
|
-
if (parent.transitionValue && key === "context") return {
|
|
3688
|
-
v6: parent.v6,
|
|
3689
|
-
assignmentMap: true,
|
|
3690
|
-
transitionContext: true
|
|
3691
|
-
};
|
|
3692
|
-
if (parent.assignmentMap) return {
|
|
3693
|
-
v6: parent.v6,
|
|
3694
|
-
assignmentValue: true
|
|
3695
|
-
};
|
|
3696
|
-
if (key === "meta") return {
|
|
3697
|
-
v6: parent.v6,
|
|
3698
|
-
metaValue: true
|
|
3699
|
-
};
|
|
3700
|
-
if (parent.transitionValue && key === "to") return {
|
|
3701
|
-
v6: parent.v6,
|
|
3702
|
-
transitionValue: true
|
|
3703
|
-
};
|
|
3704
|
-
if (key === "entry" || key === "exit") return {
|
|
3705
|
-
v6: parent.v6,
|
|
3706
|
-
actionValue: true
|
|
3707
|
-
};
|
|
3708
|
-
if (key === "input" || key === "output") return {
|
|
3709
|
-
v6: parent.v6,
|
|
3710
|
-
ioValue: true
|
|
3711
|
-
};
|
|
3712
|
-
if (parent.ioValue || parent.ioPropertyValue) return {
|
|
3713
|
-
v6: parent.v6,
|
|
3714
|
-
ioPropertyValue: true
|
|
3715
|
-
};
|
|
3716
|
-
if (key === "invoke") return {
|
|
3717
|
-
v6: parent.v6,
|
|
3718
|
-
invokeValue: true
|
|
3719
|
-
};
|
|
3720
|
-
if (key === "timeout") return {
|
|
3721
|
-
v6: parent.v6,
|
|
3722
|
-
timeoutValue: true
|
|
3723
|
-
};
|
|
3724
|
-
if (key === "route") return {
|
|
3725
|
-
v6: parent.v6,
|
|
3726
|
-
routeValue: true
|
|
3727
|
-
};
|
|
3728
|
-
if (key === "on" || key === "after") return {
|
|
3729
|
-
v6: parent.v6,
|
|
3730
|
-
transitionMap: true
|
|
3731
|
-
};
|
|
3732
|
-
if (key === "always" || key === "choice" || key === "onDone" || key === "onError" || key === "onSnapshot" || key === "onTimeout") return {
|
|
3733
|
-
v6: parent.v6,
|
|
3734
|
-
transitionValue: true
|
|
3735
|
-
};
|
|
3736
|
-
return { v6: parent.v6 };
|
|
3737
|
-
}
|
|
3738
|
-
function fallbackFunctionTransition(fn, actions = []) {
|
|
3739
|
-
return {
|
|
3740
|
-
...actions.length ? { actions } : void 0,
|
|
3741
|
-
meta: {
|
|
3742
|
-
[XSTATE_V6_FN_TRANSITION_META]: true,
|
|
3743
|
-
[XSTATE_V6_FN_SOURCE_META]: fn.getText()
|
|
3744
|
-
}
|
|
3745
|
-
};
|
|
3746
|
-
}
|
|
3747
|
-
function conditionText(cond) {
|
|
3748
|
-
return cond.negated ? `!(${cond.text})` : cond.text;
|
|
3749
|
-
}
|
|
3750
|
-
function simplifyConditions(conds) {
|
|
3751
|
-
const seen = /* @__PURE__ */ new Set();
|
|
3752
|
-
return conds.filter((cond) => {
|
|
3753
|
-
if (cond.negated) return false;
|
|
3754
|
-
const key = conditionText(cond);
|
|
3755
|
-
if (seen.has(key)) return false;
|
|
3756
|
-
seen.add(key);
|
|
3757
|
-
return true;
|
|
3758
|
-
});
|
|
3759
|
-
}
|
|
3760
|
-
function hashString(value) {
|
|
3761
|
-
let hash = 5381;
|
|
3762
|
-
for (let i = 0; i < value.length; i++) hash = hash * 33 ^ value.charCodeAt(i);
|
|
3763
|
-
return (hash >>> 0).toString(36);
|
|
3764
|
-
}
|
|
3765
|
-
function inlineGuardCode(params, condition) {
|
|
3766
|
-
return `${params} => ${condition}`;
|
|
3767
|
-
}
|
|
3768
|
-
function guardFromConditions(conds, params) {
|
|
3769
|
-
const simplified = simplifyConditions(conds);
|
|
3770
|
-
if (simplified.length === 0) return void 0;
|
|
3771
|
-
const code = inlineGuardCode(params, simplified.map(conditionText).join(" && "));
|
|
3772
|
-
return {
|
|
3773
|
-
type: `inline:${hashString(code)}`,
|
|
3774
|
-
code
|
|
3775
|
-
};
|
|
3776
|
-
}
|
|
3777
|
-
function wrapAssignExpression(expr) {
|
|
3778
|
-
return `{{ ${expr.trim()} }}`;
|
|
3779
|
-
}
|
|
3780
|
-
function hasSpreadAssignment(node) {
|
|
3781
|
-
return node.properties.some((property) => ts.isSpreadAssignment(property));
|
|
3335
|
+
function hasSpreadAssignment(node) {
|
|
3336
|
+
return node.properties.some((property) => ts.isSpreadAssignment(property));
|
|
3782
3337
|
}
|
|
3783
3338
|
function mergeActions(left, right) {
|
|
3784
3339
|
return [...left ?? [], ...right];
|
|
@@ -3916,400 +3471,883 @@ function expressionStatementAction(statement, enqName, bindings) {
|
|
|
3916
3471
|
if (method === "spawn") return {
|
|
3917
3472
|
type: "xstate.spawnChild",
|
|
3918
3473
|
params: {
|
|
3919
|
-
src: value(0),
|
|
3920
|
-
...spreadOpts(1)
|
|
3474
|
+
src: value(0),
|
|
3475
|
+
...spreadOpts(1)
|
|
3476
|
+
}
|
|
3477
|
+
};
|
|
3478
|
+
if (method === "stop") return {
|
|
3479
|
+
type: "xstate.stopChild",
|
|
3480
|
+
params: { actorRef: value(0) }
|
|
3481
|
+
};
|
|
3482
|
+
return {
|
|
3483
|
+
type: "xstate.expr",
|
|
3484
|
+
params: {
|
|
3485
|
+
code: expression.getText(),
|
|
3486
|
+
lang: "ts"
|
|
3487
|
+
}
|
|
3488
|
+
};
|
|
3489
|
+
}
|
|
3490
|
+
function statementBranches(statements, bindings, enqName, prefixes = [{
|
|
3491
|
+
conds: [],
|
|
3492
|
+
actions: []
|
|
3493
|
+
}]) {
|
|
3494
|
+
let open = prefixes;
|
|
3495
|
+
const done = [];
|
|
3496
|
+
const scopedBindings = new Map(bindings);
|
|
3497
|
+
for (const statement of statements) {
|
|
3498
|
+
const nextOpen = [];
|
|
3499
|
+
for (const prefix of open) {
|
|
3500
|
+
if (ts.isVariableStatement(statement)) {
|
|
3501
|
+
for (const declaration of statement.declarationList.declarations) if (ts.isIdentifier(declaration.name) && declaration.initializer) scopedBindings.set(declaration.name.text, declaration.initializer);
|
|
3502
|
+
nextOpen.push(prefix);
|
|
3503
|
+
continue;
|
|
3504
|
+
}
|
|
3505
|
+
if (ts.isReturnStatement(statement)) {
|
|
3506
|
+
if (!statement.expression) {
|
|
3507
|
+
done.push({
|
|
3508
|
+
...prefix,
|
|
3509
|
+
result: void 0
|
|
3510
|
+
});
|
|
3511
|
+
continue;
|
|
3512
|
+
}
|
|
3513
|
+
for (const branch of expressionBranches(statement.expression, scopedBindings, 0)) done.push(mergeBranchPrefix(prefix, branch));
|
|
3514
|
+
continue;
|
|
3515
|
+
}
|
|
3516
|
+
if (ts.isExpressionStatement(statement)) {
|
|
3517
|
+
const action = expressionStatementAction(statement, enqName, scopedBindings);
|
|
3518
|
+
if (action) {
|
|
3519
|
+
nextOpen.push({
|
|
3520
|
+
...prefix,
|
|
3521
|
+
actions: [...prefix.actions, action]
|
|
3522
|
+
});
|
|
3523
|
+
continue;
|
|
3524
|
+
}
|
|
3525
|
+
}
|
|
3526
|
+
if (ts.isIfStatement(statement)) {
|
|
3527
|
+
const cond = statement.expression.getText();
|
|
3528
|
+
const thenBranches = statementBranches(ts.isBlock(statement.thenStatement) ? statement.thenStatement.statements : [statement.thenStatement], scopedBindings, enqName, [{
|
|
3529
|
+
...prefix,
|
|
3530
|
+
conds: [...prefix.conds, { text: cond }]
|
|
3531
|
+
}]);
|
|
3532
|
+
const elseStatements = statement.elseStatement ? ts.isBlock(statement.elseStatement) ? statement.elseStatement.statements : [statement.elseStatement] : [];
|
|
3533
|
+
const elseBranches = elseStatements.length > 0 ? statementBranches(elseStatements, scopedBindings, enqName, [{
|
|
3534
|
+
...prefix,
|
|
3535
|
+
conds: [...prefix.conds, {
|
|
3536
|
+
text: cond,
|
|
3537
|
+
negated: true
|
|
3538
|
+
}]
|
|
3539
|
+
}]) : [{
|
|
3540
|
+
...prefix,
|
|
3541
|
+
conds: [...prefix.conds, {
|
|
3542
|
+
text: cond,
|
|
3543
|
+
negated: true
|
|
3544
|
+
}]
|
|
3545
|
+
}];
|
|
3546
|
+
for (const branch of [...thenBranches, ...elseBranches]) if ("result" in branch) done.push(branch);
|
|
3547
|
+
else nextOpen.push(branch);
|
|
3548
|
+
continue;
|
|
3549
|
+
}
|
|
3550
|
+
if (ts.isSwitchStatement(statement)) {
|
|
3551
|
+
const expr = statement.expression.getText();
|
|
3552
|
+
const prior = [];
|
|
3553
|
+
for (const clause of statement.caseBlock.clauses) {
|
|
3554
|
+
const ownCond = ts.isCaseClause(clause) ? { text: `${expr} === ${clause.expression.getText()}` } : null;
|
|
3555
|
+
const conds = ownCond ? [...prior, ownCond] : prior.length ? [...prior] : [];
|
|
3556
|
+
const branches = statementBranches(clause.statements, scopedBindings, enqName, [{
|
|
3557
|
+
...prefix,
|
|
3558
|
+
conds: [...prefix.conds, ...conds]
|
|
3559
|
+
}]);
|
|
3560
|
+
for (const branch of branches) if ("result" in branch) done.push(branch);
|
|
3561
|
+
else nextOpen.push(branch);
|
|
3562
|
+
if (ownCond) prior.push({
|
|
3563
|
+
...ownCond,
|
|
3564
|
+
negated: true
|
|
3565
|
+
});
|
|
3566
|
+
}
|
|
3567
|
+
continue;
|
|
3568
|
+
}
|
|
3569
|
+
nextOpen.push({
|
|
3570
|
+
...prefix,
|
|
3571
|
+
unknown: true
|
|
3572
|
+
});
|
|
3573
|
+
}
|
|
3574
|
+
open = nextOpen;
|
|
3575
|
+
}
|
|
3576
|
+
return [...done, ...open];
|
|
3577
|
+
}
|
|
3578
|
+
function enqueueParamName(fn) {
|
|
3579
|
+
const param = fn.parameters[1];
|
|
3580
|
+
return param && ts.isIdentifier(param.name) ? param.name.text : "enq";
|
|
3581
|
+
}
|
|
3582
|
+
function guardParams(fn) {
|
|
3583
|
+
const param = fn.parameters[0];
|
|
3584
|
+
if (!param) return "()";
|
|
3585
|
+
return `(${param.getText()})`;
|
|
3586
|
+
}
|
|
3587
|
+
function normalizeFunctionTransition(fn, bindings, depth) {
|
|
3588
|
+
const preservedActions = fn.body && ts.isBlock(fn.body) && fn.body.statements.some((statement) => ts.isExpressionStatement(statement)) ? [enqueueAction(fn)] : [];
|
|
3589
|
+
const transitions = (ts.isArrowFunction(fn) && !ts.isBlock(fn.body) ? expressionBranches(fn.body, bindings, depth + 1) : fn.body && ts.isBlock(fn.body) ? statementBranches(fn.body.statements, bindings, enqueueParamName(fn)) : []).filter((branch) => !branch.unknown).map((branch) => {
|
|
3590
|
+
const transition = transitionFromValue(branch.result, branch.actions.length ? preservedActions : []);
|
|
3591
|
+
if (!transition) return null;
|
|
3592
|
+
if (typeof transition === "string") {
|
|
3593
|
+
const guard = guardFromConditions(branch.conds, guardParams(fn));
|
|
3594
|
+
return guard ? {
|
|
3595
|
+
target: transition,
|
|
3596
|
+
guard
|
|
3597
|
+
} : transition;
|
|
3598
|
+
}
|
|
3599
|
+
const guard = guardFromConditions(branch.conds, guardParams(fn));
|
|
3600
|
+
return guard ? {
|
|
3601
|
+
...transition,
|
|
3602
|
+
guard
|
|
3603
|
+
} : transition;
|
|
3604
|
+
}).filter((transition) => Boolean(transition));
|
|
3605
|
+
if (transitions.length === 1) return transitions[0];
|
|
3606
|
+
if (transitions.length > 1) return transitions;
|
|
3607
|
+
return fallbackFunctionTransition(fn, preservedActions);
|
|
3608
|
+
}
|
|
3609
|
+
function inlineAction(fn) {
|
|
3610
|
+
return {
|
|
3611
|
+
type: "xstate.expr",
|
|
3612
|
+
params: {
|
|
3613
|
+
code: fn.getText(),
|
|
3614
|
+
lang: "ts"
|
|
3921
3615
|
}
|
|
3922
3616
|
};
|
|
3923
|
-
|
|
3924
|
-
|
|
3925
|
-
params: { actorRef: value(0) }
|
|
3926
|
-
};
|
|
3617
|
+
}
|
|
3618
|
+
function enqueueAction(fn) {
|
|
3927
3619
|
return {
|
|
3928
|
-
type: "xstate.
|
|
3620
|
+
type: "xstate.enqueue",
|
|
3929
3621
|
params: {
|
|
3930
|
-
code:
|
|
3622
|
+
code: fn.getText(),
|
|
3931
3623
|
lang: "ts"
|
|
3932
3624
|
}
|
|
3933
3625
|
};
|
|
3934
3626
|
}
|
|
3935
|
-
function
|
|
3936
|
-
|
|
3937
|
-
|
|
3938
|
-
|
|
3939
|
-
|
|
3940
|
-
|
|
3941
|
-
|
|
3942
|
-
|
|
3943
|
-
|
|
3944
|
-
|
|
3945
|
-
|
|
3946
|
-
|
|
3947
|
-
|
|
3948
|
-
|
|
3949
|
-
|
|
3950
|
-
if (
|
|
3951
|
-
|
|
3952
|
-
|
|
3953
|
-
|
|
3954
|
-
|
|
3955
|
-
|
|
3956
|
-
|
|
3957
|
-
|
|
3958
|
-
|
|
3959
|
-
|
|
3960
|
-
|
|
3961
|
-
|
|
3962
|
-
|
|
3963
|
-
|
|
3964
|
-
|
|
3965
|
-
|
|
3966
|
-
|
|
3967
|
-
|
|
3968
|
-
|
|
3969
|
-
|
|
3627
|
+
function inlineCodeExpression(expr) {
|
|
3628
|
+
return {
|
|
3629
|
+
"@type": "code",
|
|
3630
|
+
lang: "ts",
|
|
3631
|
+
expr
|
|
3632
|
+
};
|
|
3633
|
+
}
|
|
3634
|
+
function normalizeFunctionAction(fn, _bindings) {
|
|
3635
|
+
return enqueueAction(fn);
|
|
3636
|
+
}
|
|
3637
|
+
function objectLiteralToValue(node, bindings, context, depth, overrides = /* @__PURE__ */ new Map()) {
|
|
3638
|
+
const result = {};
|
|
3639
|
+
for (const property of node.properties) {
|
|
3640
|
+
if (ts.isSpreadAssignment(property)) {
|
|
3641
|
+
const spread = expressionToValue(property.expression, bindings, context, depth + 1);
|
|
3642
|
+
if (spread && typeof spread === "object" && !Array.isArray(spread)) Object.assign(result, spread);
|
|
3643
|
+
continue;
|
|
3644
|
+
}
|
|
3645
|
+
if (!ts.isPropertyAssignment(property) && !ts.isShorthandPropertyAssignment(property)) continue;
|
|
3646
|
+
const key = propName(property.name);
|
|
3647
|
+
if (!key) continue;
|
|
3648
|
+
if (overrides.has(key)) {
|
|
3649
|
+
result[key] = overrides.get(key);
|
|
3650
|
+
continue;
|
|
3651
|
+
}
|
|
3652
|
+
if (ts.isShorthandPropertyAssignment(property)) {
|
|
3653
|
+
result[key] = expressionToValue(property.name, bindings, propertyContext(context, key), depth + 1);
|
|
3654
|
+
continue;
|
|
3655
|
+
}
|
|
3656
|
+
result[key] = expressionToValue(property.initializer, bindings, propertyContext(context, key), depth + 1);
|
|
3657
|
+
}
|
|
3658
|
+
if (context.transitionValue && "to" in result) {
|
|
3659
|
+
const to = result.to;
|
|
3660
|
+
const { to: _to, ...rest } = result;
|
|
3661
|
+
if (typeof to === "string") return {
|
|
3662
|
+
...rest,
|
|
3663
|
+
target: to
|
|
3664
|
+
};
|
|
3665
|
+
if (Array.isArray(to)) return to.map((item) => typeof item === "string" ? {
|
|
3666
|
+
...rest,
|
|
3667
|
+
target: item
|
|
3668
|
+
} : item && typeof item === "object" ? {
|
|
3669
|
+
...rest,
|
|
3670
|
+
...item
|
|
3671
|
+
} : rest);
|
|
3672
|
+
if (to && typeof to === "object" && !Array.isArray(to)) return {
|
|
3673
|
+
...rest,
|
|
3674
|
+
...to
|
|
3675
|
+
};
|
|
3676
|
+
}
|
|
3677
|
+
return result;
|
|
3678
|
+
}
|
|
3679
|
+
function expressionToValue(expression, bindings, context = {}, depth = 0) {
|
|
3680
|
+
if (depth > 30) return void 0;
|
|
3681
|
+
const node = unwrapExpression(expression);
|
|
3682
|
+
if (context.actorSourceValue) {
|
|
3683
|
+
if (ts.isStringLiteral(node) || ts.isNoSubstitutionTemplateLiteral(node)) return node.text;
|
|
3684
|
+
if (ts.isIdentifier(node)) {
|
|
3685
|
+
const binding = bindings.get(node.text);
|
|
3686
|
+
if (binding && !ts.isFunctionDeclaration(binding)) return inlineCodeExpression(unwrapExpression(binding).getText());
|
|
3687
|
+
}
|
|
3688
|
+
return inlineCodeExpression(node.getText());
|
|
3689
|
+
}
|
|
3690
|
+
if (context.routeValue && !ts.isObjectLiteralExpression(node)) {
|
|
3691
|
+
if (ts.isIdentifier(node)) {
|
|
3692
|
+
const binding = bindings.get(node.text);
|
|
3693
|
+
if (binding && !ts.isFunctionDeclaration(binding)) return expressionToValue(binding, bindings, context, depth + 1);
|
|
3694
|
+
}
|
|
3695
|
+
return inlineCodeExpression(node.getText());
|
|
3696
|
+
}
|
|
3697
|
+
if (context.timeoutValue && (ts.isArrowFunction(node) || ts.isFunctionExpression(node) || ts.isCallExpression(node))) return inlineCodeExpression(node.getText());
|
|
3698
|
+
if (ts.isStringLiteral(node) || ts.isNoSubstitutionTemplateLiteral(node)) return context.ioValue ? inlineCodeExpression(JSON.stringify(node.text)) : node.text;
|
|
3699
|
+
if (ts.isNumericLiteral(node)) return context.ioValue ? inlineCodeExpression(node.text) : Number(node.text);
|
|
3700
|
+
if (node.kind === ts.SyntaxKind.TrueKeyword) return context.ioValue ? inlineCodeExpression("true") : true;
|
|
3701
|
+
if (node.kind === ts.SyntaxKind.FalseKeyword) return context.ioValue ? inlineCodeExpression("false") : false;
|
|
3702
|
+
if (node.kind === ts.SyntaxKind.NullKeyword) return context.ioValue ? inlineCodeExpression("null") : null;
|
|
3703
|
+
if (context.ioPropertyValue) {
|
|
3704
|
+
if (ts.isIdentifier(node) && node.text === "undefined") return void 0;
|
|
3705
|
+
if (ts.isIdentifier(node)) {
|
|
3706
|
+
const binding = bindings.get(node.text);
|
|
3707
|
+
if (binding && !ts.isFunctionDeclaration(binding)) return expressionToValue(binding, bindings, context, depth + 1);
|
|
3708
|
+
}
|
|
3709
|
+
if (!ts.isObjectLiteralExpression(node) && !ts.isArrayLiteralExpression(node)) return inlineCodeExpression(node.getText());
|
|
3710
|
+
}
|
|
3711
|
+
if (context.assignmentValue) {
|
|
3712
|
+
if (ts.isIdentifier(node) && node.text === "undefined") return void 0;
|
|
3713
|
+
if (ts.isIdentifier(node)) {
|
|
3714
|
+
const binding = bindings.get(node.text);
|
|
3715
|
+
if (binding && !ts.isFunctionDeclaration(binding)) return expressionToValue(binding, bindings, context, depth + 1);
|
|
3716
|
+
}
|
|
3717
|
+
return wrapAssignExpression(node.getText());
|
|
3718
|
+
}
|
|
3719
|
+
if (context.transitionContext && !ts.isObjectLiteralExpression(node)) return inlineCodeExpression(node.getText());
|
|
3720
|
+
if (context.ioValue && !ts.isObjectLiteralExpression(node)) return inlineCodeExpression(node.getText());
|
|
3721
|
+
if (context.transitionContext && ts.isObjectLiteralExpression(node) && hasSpreadAssignment(node)) return inlineCodeExpression(node.getText());
|
|
3722
|
+
if (ts.isIdentifier(node)) {
|
|
3723
|
+
if (node.text === "undefined") return void 0;
|
|
3724
|
+
const binding = bindings.get(node.text);
|
|
3725
|
+
if (binding) {
|
|
3726
|
+
if (ts.isFunctionDeclaration(binding)) {
|
|
3727
|
+
if (context.metaValue) return inlineCodeExpression(binding.name?.text ?? node.getText());
|
|
3728
|
+
if (context.v6 && context.transitionValue) return normalizeFunctionTransition(binding, bindings, depth + 1);
|
|
3729
|
+
if (context.v6 && context.actionValue) return normalizeFunctionAction(binding, bindings);
|
|
3730
|
+
return binding.name?.text ?? node.text;
|
|
3970
3731
|
}
|
|
3971
|
-
|
|
3972
|
-
|
|
3973
|
-
|
|
3974
|
-
|
|
3975
|
-
|
|
3976
|
-
|
|
3977
|
-
|
|
3978
|
-
|
|
3979
|
-
|
|
3980
|
-
|
|
3981
|
-
|
|
3982
|
-
|
|
3983
|
-
|
|
3984
|
-
|
|
3985
|
-
|
|
3986
|
-
|
|
3987
|
-
|
|
3988
|
-
|
|
3989
|
-
|
|
3990
|
-
|
|
3991
|
-
|
|
3992
|
-
|
|
3993
|
-
|
|
3732
|
+
return expressionToValue(binding, bindings, context, depth + 1);
|
|
3733
|
+
}
|
|
3734
|
+
return context.metaValue ? inlineCodeExpression(node.getText()) : node.text;
|
|
3735
|
+
}
|
|
3736
|
+
if (ts.isObjectLiteralExpression(node)) return objectLiteralToValue(node, bindings, context, depth);
|
|
3737
|
+
if (ts.isArrayLiteralExpression(node)) {
|
|
3738
|
+
const values = node.elements.map((element) => expressionToValue(element, bindings, context, depth + 1));
|
|
3739
|
+
return context.actionValue ? values.flat() : values;
|
|
3740
|
+
}
|
|
3741
|
+
if (ts.isArrowFunction(node) || ts.isFunctionExpression(node)) {
|
|
3742
|
+
if (context.metaValue) return inlineCodeExpression(node.getText());
|
|
3743
|
+
if (context.v6 && context.transitionValue) return normalizeFunctionTransition(node, bindings, depth);
|
|
3744
|
+
if (context.v6 && context.actionValue) return normalizeFunctionAction(node, bindings);
|
|
3745
|
+
return node.getText();
|
|
3746
|
+
}
|
|
3747
|
+
if (ts.isCallExpression(node)) {
|
|
3748
|
+
if (context.metaValue) return inlineCodeExpression(node.getText());
|
|
3749
|
+
if (ts.isIdentifier(node.expression)) {
|
|
3750
|
+
const binding = bindings.get(node.expression.text);
|
|
3751
|
+
if (binding && isFunctionBinding(binding)) return evaluateFunctionCall(binding, node.arguments, bindings, context, depth + 1);
|
|
3752
|
+
}
|
|
3753
|
+
if (ts.isPropertyAccessExpression(node.expression) && node.expression.name.text === "createStateConfig") {
|
|
3754
|
+
const configArg = node.arguments.length > 1 ? node.arguments[1] : node.arguments[0];
|
|
3755
|
+
return configArg ? expressionToValue(configArg, bindings, { v6: context.v6 }, depth + 1) : {};
|
|
3756
|
+
}
|
|
3757
|
+
if (context.actionValue) return inlineAction(node);
|
|
3758
|
+
const callee = node.expression.getText();
|
|
3759
|
+
const type = callee.includes(".") ? callee.split(".").pop() : callee;
|
|
3760
|
+
return { type: type === "assign" ? "xstate.assign" : type };
|
|
3761
|
+
}
|
|
3762
|
+
return context.metaValue ? inlineCodeExpression(node.getText()) : node.getText();
|
|
3763
|
+
}
|
|
3764
|
+
function isFunctionBinding(binding) {
|
|
3765
|
+
return ts.isArrowFunction(binding) || ts.isFunctionExpression(binding) || ts.isFunctionDeclaration(binding);
|
|
3766
|
+
}
|
|
3767
|
+
function evaluateFunctionCall(fn, args, bindings, context, depth) {
|
|
3768
|
+
const scopedBindings = new Map(bindings);
|
|
3769
|
+
for (const [index, parameter] of fn.parameters.entries()) {
|
|
3770
|
+
if (!ts.isIdentifier(parameter.name)) continue;
|
|
3771
|
+
const argument = args[index];
|
|
3772
|
+
if (argument) scopedBindings.set(parameter.name.text, argument);
|
|
3773
|
+
else if (parameter.initializer) scopedBindings.set(parameter.name.text, parameter.initializer);
|
|
3774
|
+
}
|
|
3775
|
+
if (ts.isArrowFunction(fn) && !ts.isBlock(fn.body)) return expressionToValue(fn.body, scopedBindings, context, depth + 1);
|
|
3776
|
+
if (context.v6 && context.transitionValue) return normalizeFunctionTransition(fn, scopedBindings, depth + 1);
|
|
3777
|
+
if (context.v6 && context.actionValue) return normalizeFunctionAction(fn, scopedBindings);
|
|
3778
|
+
return context.metaValue ? inlineCodeExpression(fn.getText()) : fn.name?.getText() ?? fn.getText();
|
|
3779
|
+
}
|
|
3780
|
+
function collectBindings(file) {
|
|
3781
|
+
const bindings = /* @__PURE__ */ new Map();
|
|
3782
|
+
for (const statement of file.statements) {
|
|
3783
|
+
if (ts.isVariableStatement(statement)) {
|
|
3784
|
+
for (const declaration of statement.declarationList.declarations) if (ts.isIdentifier(declaration.name) && declaration.initializer) bindings.set(declaration.name.text, declaration.initializer);
|
|
3785
|
+
continue;
|
|
3786
|
+
}
|
|
3787
|
+
if (ts.isFunctionDeclaration(statement) && statement.name) bindings.set(statement.name.text, statement);
|
|
3788
|
+
}
|
|
3789
|
+
return bindings;
|
|
3790
|
+
}
|
|
3791
|
+
function isCreateMachineCall(node) {
|
|
3792
|
+
const expression = node.expression;
|
|
3793
|
+
if (ts.isIdentifier(expression)) return expression.text === "createMachine";
|
|
3794
|
+
if (ts.isPropertyAccessExpression(expression)) return expression.name.text === "createMachine";
|
|
3795
|
+
return false;
|
|
3796
|
+
}
|
|
3797
|
+
function hasV6Syntax(source) {
|
|
3798
|
+
const file = sourceFile(source);
|
|
3799
|
+
const bindings = collectBindings(file);
|
|
3800
|
+
let found = false;
|
|
3801
|
+
function containsFunction(expression, seenBindings = /* @__PURE__ */ new Set()) {
|
|
3802
|
+
if (ts.isFunctionDeclaration(expression)) return true;
|
|
3803
|
+
const node = unwrapExpression(expression);
|
|
3804
|
+
if (ts.isArrowFunction(node) || ts.isFunctionExpression(node)) return true;
|
|
3805
|
+
if (ts.isIdentifier(node)) {
|
|
3806
|
+
if (seenBindings.has(node.text)) return false;
|
|
3807
|
+
const binding = bindings.get(node.text);
|
|
3808
|
+
if (!binding) return false;
|
|
3809
|
+
return containsFunction(binding, new Set([...seenBindings, node.text]));
|
|
3810
|
+
}
|
|
3811
|
+
if (ts.isObjectLiteralExpression(node)) return node.properties.some((property) => {
|
|
3812
|
+
if (ts.isPropertyAssignment(property)) return containsFunction(property.initializer, seenBindings);
|
|
3813
|
+
if (ts.isShorthandPropertyAssignment(property)) return containsFunction(property.name, seenBindings);
|
|
3814
|
+
if (ts.isSpreadAssignment(property)) return containsFunction(property.expression, seenBindings);
|
|
3815
|
+
return false;
|
|
3816
|
+
});
|
|
3817
|
+
if (ts.isArrayLiteralExpression(node)) return node.elements.some((element) => ts.isExpression(element) && containsFunction(element, seenBindings));
|
|
3818
|
+
if (ts.isCallExpression(node)) return ts.isIdentifier(node.expression) && containsFunction(node.expression, seenBindings) || node.arguments.some((argument) => ts.isExpression(argument) && containsFunction(argument, seenBindings));
|
|
3819
|
+
return false;
|
|
3820
|
+
}
|
|
3821
|
+
function visit(node) {
|
|
3822
|
+
if (found) return;
|
|
3823
|
+
if (ts.isPropertyAssignment(node) && (ts.isIdentifier(node.name) || ts.isStringLiteral(node.name))) {
|
|
3824
|
+
const key = node.name.text;
|
|
3825
|
+
if (key === "triggers" || key === "internalEvents" || key === "matches" || key === "actorSources" || key === "timeout" || key === "onTimeout" || key === "choice" || key === "route") {
|
|
3826
|
+
found = true;
|
|
3827
|
+
return;
|
|
3994
3828
|
}
|
|
3995
|
-
if (ts.
|
|
3996
|
-
|
|
3997
|
-
|
|
3998
|
-
for (const clause of statement.caseBlock.clauses) {
|
|
3999
|
-
const ownCond = ts.isCaseClause(clause) ? { text: `${expr} === ${clause.expression.getText()}` } : null;
|
|
4000
|
-
const conds = ownCond ? [...prior, ownCond] : prior.length ? [...prior] : [];
|
|
4001
|
-
const branches = statementBranches(clause.statements, scopedBindings, enqName, [{
|
|
4002
|
-
...prefix,
|
|
4003
|
-
conds: [...prefix.conds, ...conds]
|
|
4004
|
-
}]);
|
|
4005
|
-
for (const branch of branches) if ("result" in branch) done.push(branch);
|
|
4006
|
-
else nextOpen.push(branch);
|
|
4007
|
-
if (ownCond) prior.push({
|
|
4008
|
-
...ownCond,
|
|
4009
|
-
negated: true
|
|
4010
|
-
});
|
|
4011
|
-
}
|
|
4012
|
-
continue;
|
|
3829
|
+
if ((key === "on" || key === "after" || key === "always" || key === "choice" || key === "onDone" || key === "onError" || key === "onSnapshot" || key === "onTimeout" || key === "entry" || key === "exit" || key === "actions" && !ts.isObjectLiteralExpression(node.initializer)) && containsFunction(node.initializer)) {
|
|
3830
|
+
found = true;
|
|
3831
|
+
return;
|
|
4013
3832
|
}
|
|
4014
|
-
nextOpen.push({
|
|
4015
|
-
...prefix,
|
|
4016
|
-
unknown: true
|
|
4017
|
-
});
|
|
4018
3833
|
}
|
|
4019
|
-
|
|
3834
|
+
ts.forEachChild(node, visit);
|
|
4020
3835
|
}
|
|
4021
|
-
|
|
3836
|
+
visit(file);
|
|
3837
|
+
return found;
|
|
4022
3838
|
}
|
|
4023
|
-
function
|
|
4024
|
-
|
|
4025
|
-
return param && ts.isIdentifier(param.name) ? param.name.text : "enq";
|
|
3839
|
+
function detectXStateSourceProfile(source) {
|
|
3840
|
+
return hasV6Syntax(source) ? "xstate-v6-alpha" : "xstate-v5";
|
|
4026
3841
|
}
|
|
4027
|
-
function
|
|
4028
|
-
const
|
|
4029
|
-
if (!
|
|
4030
|
-
return
|
|
3842
|
+
function xstateSourceToConfig(source, options = {}) {
|
|
3843
|
+
const [config] = extractXStateMachineConfigs(source, options);
|
|
3844
|
+
if (!config) throw new Error("No createMachine(...) or setup(...).createMachine(...) call found.");
|
|
3845
|
+
return config;
|
|
4031
3846
|
}
|
|
4032
|
-
|
|
4033
|
-
|
|
4034
|
-
|
|
4035
|
-
|
|
4036
|
-
|
|
4037
|
-
|
|
4038
|
-
|
|
4039
|
-
|
|
4040
|
-
|
|
4041
|
-
|
|
4042
|
-
|
|
3847
|
+
/**
|
|
3848
|
+
* Extract every XState machine config from source without executing code.
|
|
3849
|
+
* XState 5/6 syntax is inferred structurally unless a profile is supplied.
|
|
3850
|
+
*/
|
|
3851
|
+
function extractXStateMachineConfigs(source, options = {}) {
|
|
3852
|
+
const file = sourceFile(source);
|
|
3853
|
+
const bindings = collectBindings(file);
|
|
3854
|
+
const found = [];
|
|
3855
|
+
const profile = options.profile === "auto" || !options.profile ? detectXStateSourceProfile(source) : options.profile;
|
|
3856
|
+
function visit(node) {
|
|
3857
|
+
if (!ts.isCallExpression(node) || !isCreateMachineCall(node)) {
|
|
3858
|
+
ts.forEachChild(node, visit);
|
|
3859
|
+
return;
|
|
4043
3860
|
}
|
|
4044
|
-
const
|
|
4045
|
-
|
|
4046
|
-
|
|
4047
|
-
|
|
4048
|
-
|
|
4049
|
-
|
|
4050
|
-
|
|
4051
|
-
if (transitions.length > 1) return transitions;
|
|
4052
|
-
return fallbackFunctionTransition(fn, preservedActions);
|
|
3861
|
+
const arg = node.arguments[0];
|
|
3862
|
+
if (!arg) return;
|
|
3863
|
+
const value = expressionToValue(arg, bindings, { v6: profile === "xstate-v6-alpha" });
|
|
3864
|
+
if (value && typeof value === "object" && !Array.isArray(value)) found.push(value);
|
|
3865
|
+
}
|
|
3866
|
+
visit(file);
|
|
3867
|
+
return found;
|
|
4053
3868
|
}
|
|
4054
|
-
function
|
|
4055
|
-
return
|
|
4056
|
-
|
|
4057
|
-
|
|
4058
|
-
|
|
4059
|
-
|
|
4060
|
-
|
|
4061
|
-
}
|
|
3869
|
+
function jsonSchemaToTSType(schema) {
|
|
3870
|
+
if (!schema) return "unknown";
|
|
3871
|
+
if (schema.enum) return schema.enum.map((v) => typeof v === "string" ? `'${v}'` : String(v)).join(" | ");
|
|
3872
|
+
if (schema.const !== void 0) return typeof schema.const === "string" ? `'${schema.const}'` : String(schema.const);
|
|
3873
|
+
if (schema.oneOf) return schema.oneOf.map((s) => jsonSchemaToTSType(resolveDef(s))).join(" | ");
|
|
3874
|
+
if (schema.anyOf) return schema.anyOf.map((s) => jsonSchemaToTSType(resolveDef(s))).join(" | ");
|
|
3875
|
+
if (schema.allOf) return schema.allOf.map((s) => jsonSchemaToTSType(resolveDef(s))).join(" & ");
|
|
3876
|
+
if (schema.type === "array") return `Array<${jsonSchemaToTSType(resolveDef(schema.items))}>`;
|
|
3877
|
+
if (Array.isArray(schema.type)) return schema.type.map((t) => primitiveType(t)).join(" | ");
|
|
3878
|
+
if (schema.type === "object" || schema.properties) return objectType(schema);
|
|
3879
|
+
if (schema.type) return primitiveType(schema.type);
|
|
3880
|
+
return "unknown";
|
|
4062
3881
|
}
|
|
4063
|
-
function
|
|
3882
|
+
function primitiveType(type) {
|
|
3883
|
+
switch (type) {
|
|
3884
|
+
case "string": return "string";
|
|
3885
|
+
case "number":
|
|
3886
|
+
case "integer": return "number";
|
|
3887
|
+
case "boolean": return "boolean";
|
|
3888
|
+
case "null": return "null";
|
|
3889
|
+
default: return "unknown";
|
|
3890
|
+
}
|
|
3891
|
+
}
|
|
3892
|
+
function objectType(schema) {
|
|
3893
|
+
const props = schema.properties;
|
|
3894
|
+
if (!props || Object.keys(props).length === 0) {
|
|
3895
|
+
if (schema.additionalProperties) return `Record<string, ${jsonSchemaToTSType(resolveDef(schema.additionalProperties))}>`;
|
|
3896
|
+
return "Record<string, unknown>";
|
|
3897
|
+
}
|
|
3898
|
+
const required = getRequiredKeys(schema);
|
|
3899
|
+
return `{ ${Object.entries(props).map(([key, def]) => {
|
|
3900
|
+
const type = jsonSchemaToTSType(resolveDef(def));
|
|
3901
|
+
return `${key}${isRequiredProperty(key, def, required) ? "" : "?"}: ${type}`;
|
|
3902
|
+
}).join("; ")} }`;
|
|
3903
|
+
}
|
|
3904
|
+
function resolveDef(def) {
|
|
3905
|
+
if (!def) return void 0;
|
|
3906
|
+
if (Array.isArray(def)) return resolveDef(def[0]);
|
|
3907
|
+
if (typeof def === "boolean") return void 0;
|
|
3908
|
+
return def;
|
|
3909
|
+
}
|
|
3910
|
+
/**
|
|
3911
|
+
* Build an inline context type string from the schemas.context record.
|
|
3912
|
+
* Each key is a context property name, value is its JSONSchema7.
|
|
3913
|
+
*/
|
|
3914
|
+
function contextSchemaToTSType(context) {
|
|
3915
|
+
if (!context || Object.keys(context).length === 0) return null;
|
|
3916
|
+
return `{ ${Object.entries(context).map(([key, schema]) => {
|
|
3917
|
+
return `${key}: ${jsonSchemaToTSType(schema)}`;
|
|
3918
|
+
}).join("; ")} }`;
|
|
3919
|
+
}
|
|
3920
|
+
/**
|
|
3921
|
+
* Build an event union type from the schemas.events record.
|
|
3922
|
+
* Each key is the event type name, value describes the payload properties.
|
|
3923
|
+
*/
|
|
3924
|
+
function eventsSchemaToTSType(events) {
|
|
3925
|
+
if (!events || Object.keys(events).length === 0) return null;
|
|
3926
|
+
return Object.entries(events).map(([eventType, schema]) => {
|
|
3927
|
+
const props = schema.properties;
|
|
3928
|
+
if (!props || Object.keys(props).length === 0) return `{ type: '${eventType}' }`;
|
|
3929
|
+
const required = getRequiredKeys(schema);
|
|
3930
|
+
const extraProps = Object.entries(props).filter(([k]) => k !== "type").map(([key, def]) => {
|
|
3931
|
+
const type = jsonSchemaToTSType(resolveDef(def));
|
|
3932
|
+
return `${key}${isRequiredProperty(key, def, required) ? "" : "?"}: ${type}`;
|
|
3933
|
+
});
|
|
3934
|
+
if (extraProps.length === 0) return `{ type: '${eventType}' }`;
|
|
3935
|
+
return `{ type: '${eventType}'; ${extraProps.join("; ")} }`;
|
|
3936
|
+
}).join("\n | ");
|
|
3937
|
+
}
|
|
3938
|
+
function getRequiredKeys(schema) {
|
|
3939
|
+
return new Set(Array.isArray(schema.required) ? schema.required : []);
|
|
3940
|
+
}
|
|
3941
|
+
function isRequiredProperty(key, def, required) {
|
|
3942
|
+
if (required.has(key)) return true;
|
|
3943
|
+
return typeof def === "object" && def !== null && def.required === true;
|
|
3944
|
+
}
|
|
3945
|
+
function graphToXStateTS(graph, options = {}) {
|
|
3946
|
+
const { exportStyle = "named", targetLanguage = "typescript", xstateVersion = 5, ...configOptions } = options;
|
|
3947
|
+
const schemas = graph.data.schemas;
|
|
3948
|
+
const impls = filterInlineImplementations(graph.data.implementations);
|
|
3949
|
+
const supportsTypeSyntax = targetLanguage === "typescript";
|
|
3950
|
+
const hasSchemas = !!(schemas && (schemas.context || schemas.events || schemas.input || schemas.output));
|
|
3951
|
+
const hasActions = !!impls?.actions.length;
|
|
3952
|
+
const hasGuards = !!impls?.guards.length;
|
|
3953
|
+
const hasActors = !!impls?.actors.length;
|
|
3954
|
+
const hasDelays = !!impls?.delays.length;
|
|
3955
|
+
const hasSetup = hasSchemas || hasActions || hasGuards || hasActors || hasDelays;
|
|
3956
|
+
const builtInActions = getUsedBuiltInActions(graph, xstateVersion);
|
|
3957
|
+
const actorSourceImports = getActorSourceImports(graph);
|
|
3958
|
+
const imports = buildImports({
|
|
3959
|
+
hasSetup,
|
|
3960
|
+
hasActors,
|
|
3961
|
+
actors: impls?.actors ?? [],
|
|
3962
|
+
builtInActions,
|
|
3963
|
+
actorSourceImports,
|
|
3964
|
+
usesTypes: xstateVersion === 6 && supportsTypeSyntax && hasSchemas
|
|
3965
|
+
});
|
|
3966
|
+
const machineConfig = xstateVersion === 6 ? toV6MachineConfig(graphToMachineConfig(graph, configOptions)) : toV5MachineConfig(graphToMachineConfig(graph, configOptions));
|
|
3967
|
+
let machineExpr;
|
|
3968
|
+
if (hasSetup) {
|
|
3969
|
+
const setupObj = buildSetupObject(schemas, impls, {
|
|
3970
|
+
includeTypeSyntax: supportsTypeSyntax,
|
|
3971
|
+
xstateVersion
|
|
3972
|
+
});
|
|
3973
|
+
const configStr = serializeJS(machineConfig, 2);
|
|
3974
|
+
machineExpr = `setup(${serializeJS(setupObj, 0)}).createMachine(${configStr})`;
|
|
3975
|
+
} else machineExpr = `createMachine(${serializeJS(machineConfig, 0)})`;
|
|
3976
|
+
const lines = [];
|
|
3977
|
+
lines.push(imports);
|
|
3978
|
+
lines.push("");
|
|
3979
|
+
lines.push(`const machine = ${machineExpr};`);
|
|
3980
|
+
if (exportStyle === "named") {
|
|
3981
|
+
lines.push("");
|
|
3982
|
+
lines.push("export { machine };");
|
|
3983
|
+
} else if (exportStyle === "default") {
|
|
3984
|
+
lines.push("");
|
|
3985
|
+
lines.push("export default machine;");
|
|
3986
|
+
}
|
|
3987
|
+
return lines.join("\n") + "\n";
|
|
3988
|
+
}
|
|
3989
|
+
function filterInlineImplementations(impls) {
|
|
3990
|
+
if (!impls) return impls;
|
|
4064
3991
|
return {
|
|
4065
|
-
|
|
4066
|
-
|
|
4067
|
-
|
|
4068
|
-
|
|
4069
|
-
}
|
|
3992
|
+
...impls,
|
|
3993
|
+
actions: impls.actions.filter((action) => !action.name.startsWith("inline:")),
|
|
3994
|
+
guards: impls.guards.filter((guard) => !guard.name.startsWith("inline:")),
|
|
3995
|
+
delays: impls.delays.filter((delay) => !delay.name.startsWith("inline:"))
|
|
4070
3996
|
};
|
|
4071
3997
|
}
|
|
4072
|
-
|
|
4073
|
-
|
|
4074
|
-
|
|
4075
|
-
|
|
4076
|
-
|
|
4077
|
-
|
|
3998
|
+
/** Map from xstate action type to the import name */
|
|
3999
|
+
const BUILTIN_ACTION_IMPORTS = {
|
|
4000
|
+
"xstate.raise": "raise",
|
|
4001
|
+
"xstate.sendTo": "sendTo",
|
|
4002
|
+
"xstate.cancel": "cancel",
|
|
4003
|
+
"xstate.emit": "emit",
|
|
4004
|
+
"xstate.spawnChild": "spawnChild",
|
|
4005
|
+
"xstate.stopChild": "stopChild",
|
|
4006
|
+
"xstate.log": "log",
|
|
4007
|
+
"xstate.assign": "assign"
|
|
4008
|
+
};
|
|
4009
|
+
/** Check inline action/entry/exit code for references to xstate builtins */
|
|
4010
|
+
function scanInlineCodeForBuiltins(code, used) {
|
|
4011
|
+
const expr = stripExportDefault(code);
|
|
4012
|
+
for (const importName of Object.values(BUILTIN_ACTION_IMPORTS)) if (new RegExp(`\\b${importName}\\b`).test(expr)) used.add(importName);
|
|
4013
|
+
}
|
|
4014
|
+
function getExprActionCode(action) {
|
|
4015
|
+
return action.type === "xstate.expr" && typeof action.params?.code === "string" ? action.params.code : void 0;
|
|
4078
4016
|
}
|
|
4079
|
-
function
|
|
4080
|
-
|
|
4017
|
+
function getUsedBuiltInActions(graph, xstateVersion) {
|
|
4018
|
+
const used = /* @__PURE__ */ new Set();
|
|
4019
|
+
if (xstateVersion === 6) return used;
|
|
4020
|
+
for (const node of graph.nodes) for (const action of [...node.data.entry ?? [], ...node.data.exit ?? []]) {
|
|
4021
|
+
const imp = BUILTIN_ACTION_IMPORTS[action.type];
|
|
4022
|
+
if (imp) used.add(imp);
|
|
4023
|
+
const exprCode = getExprActionCode(action);
|
|
4024
|
+
if (exprCode) scanInlineCodeForBuiltins(exprCode, used);
|
|
4025
|
+
}
|
|
4026
|
+
for (const edge of graph.edges) for (const action of edge.data.actions ?? []) {
|
|
4027
|
+
const imp = BUILTIN_ACTION_IMPORTS[action.type];
|
|
4028
|
+
if (imp) used.add(imp);
|
|
4029
|
+
const exprCode = getExprActionCode(action);
|
|
4030
|
+
if (exprCode) scanInlineCodeForBuiltins(exprCode, used);
|
|
4031
|
+
}
|
|
4032
|
+
return used;
|
|
4081
4033
|
}
|
|
4082
|
-
function
|
|
4034
|
+
function toV5MachineConfig(machineConfig) {
|
|
4035
|
+
return mapMachineActionFields(machineConfig, (actions, wasArray) => {
|
|
4036
|
+
const mapped = actions.map(unwrapDirectEnqExpression);
|
|
4037
|
+
return wasArray ? mapped : mapped[0];
|
|
4038
|
+
});
|
|
4039
|
+
}
|
|
4040
|
+
function toV6MachineConfig(machineConfig) {
|
|
4041
|
+
return mapV6MachineConfig(machineConfig);
|
|
4042
|
+
}
|
|
4043
|
+
function mapV6MachineConfig(value, context = {}) {
|
|
4044
|
+
if (Array.isArray(value)) return value.map((item) => mapV6MachineConfig(item, context));
|
|
4045
|
+
if (!value || typeof value !== "object") return value;
|
|
4046
|
+
if (context.transitionValue) return toV6TransitionValue(value);
|
|
4083
4047
|
const result = {};
|
|
4084
|
-
for (const
|
|
4085
|
-
if (
|
|
4086
|
-
|
|
4087
|
-
if (spread && typeof spread === "object" && !Array.isArray(spread)) Object.assign(result, spread);
|
|
4048
|
+
for (const [key, item] of Object.entries(value)) {
|
|
4049
|
+
if (key === "entry" || key === "exit" || key === "actions") {
|
|
4050
|
+
result[key] = toV6ActionField(Array.isArray(item) ? item : item === void 0 ? [] : [item]);
|
|
4088
4051
|
continue;
|
|
4089
4052
|
}
|
|
4090
|
-
if (
|
|
4091
|
-
|
|
4092
|
-
if (!key) continue;
|
|
4093
|
-
if (overrides.has(key)) {
|
|
4094
|
-
result[key] = overrides.get(key);
|
|
4053
|
+
if (key === "on" || key === "after") {
|
|
4054
|
+
result[key] = mapV6TransitionMap(item);
|
|
4095
4055
|
continue;
|
|
4096
4056
|
}
|
|
4097
|
-
if (
|
|
4098
|
-
result[key] =
|
|
4057
|
+
if (key === "always" || key === "onDone" || key === "onError" || key === "onSnapshot" || key === "onTimeout") {
|
|
4058
|
+
result[key] = mapV6MachineConfig(item, { transitionValue: true });
|
|
4099
4059
|
continue;
|
|
4100
4060
|
}
|
|
4101
|
-
result[key] =
|
|
4102
|
-
}
|
|
4103
|
-
if (context.transitionValue && "to" in result) {
|
|
4104
|
-
const to = result.to;
|
|
4105
|
-
const { to: _to, ...rest } = result;
|
|
4106
|
-
if (typeof to === "string") return {
|
|
4107
|
-
...rest,
|
|
4108
|
-
target: to
|
|
4109
|
-
};
|
|
4110
|
-
if (Array.isArray(to)) return to.map((item) => typeof item === "string" ? {
|
|
4111
|
-
...rest,
|
|
4112
|
-
target: item
|
|
4113
|
-
} : item && typeof item === "object" ? {
|
|
4114
|
-
...rest,
|
|
4115
|
-
...item
|
|
4116
|
-
} : rest);
|
|
4117
|
-
if (to && typeof to === "object" && !Array.isArray(to)) return {
|
|
4118
|
-
...rest,
|
|
4119
|
-
...to
|
|
4120
|
-
};
|
|
4061
|
+
result[key] = mapV6MachineConfig(item);
|
|
4121
4062
|
}
|
|
4122
4063
|
return result;
|
|
4123
4064
|
}
|
|
4124
|
-
function
|
|
4125
|
-
if (
|
|
4126
|
-
const
|
|
4127
|
-
|
|
4128
|
-
|
|
4129
|
-
|
|
4130
|
-
|
|
4131
|
-
|
|
4132
|
-
|
|
4133
|
-
|
|
4065
|
+
function mapV6TransitionMap(value) {
|
|
4066
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) return value;
|
|
4067
|
+
const result = {};
|
|
4068
|
+
for (const [key, item] of Object.entries(value)) result[key] = mapV6MachineConfig(item, { transitionValue: true });
|
|
4069
|
+
return result;
|
|
4070
|
+
}
|
|
4071
|
+
function toV6TransitionValue(value) {
|
|
4072
|
+
if (Array.isArray(value)) return value.map((item) => toV6TransitionValue(item));
|
|
4073
|
+
if (!value || typeof value !== "object") return value;
|
|
4074
|
+
const transition = value;
|
|
4075
|
+
if (transition.guard || transition.description || transition.input !== void 0) return mapV6MachineConfig(transition);
|
|
4076
|
+
const target = transition.target;
|
|
4077
|
+
const context = transition.context;
|
|
4078
|
+
const actionsValue = transition.actions;
|
|
4079
|
+
const actions = Array.isArray(actionsValue) ? actionsValue : actionsValue === void 0 ? [] : [actionsValue];
|
|
4080
|
+
if (actions.length === 0 && typeof target === "string" && context === void 0 && !transition.reenter && !transition.meta) return target;
|
|
4081
|
+
if (actions.length === 0 && target === void 0 && context === void 0) return mapV6MachineConfig(transition);
|
|
4082
|
+
return buildV6ActionFunction(actions, {
|
|
4083
|
+
target: typeof target === "string" ? target : void 0,
|
|
4084
|
+
reenter: transition.reenter === true,
|
|
4085
|
+
meta: transition.meta,
|
|
4086
|
+
context
|
|
4087
|
+
}) ?? mapV6MachineConfig(transition);
|
|
4088
|
+
}
|
|
4089
|
+
function toV6ActionField(actions) {
|
|
4090
|
+
if (actions.length === 1) {
|
|
4091
|
+
const expr = inlineExpr(actions[0]);
|
|
4092
|
+
if (expr && isCompleteFunctionExpression(stripExportDefault(expr))) return raw(stripExportDefault(expr));
|
|
4134
4093
|
}
|
|
4135
|
-
|
|
4136
|
-
|
|
4137
|
-
|
|
4138
|
-
|
|
4139
|
-
|
|
4140
|
-
|
|
4094
|
+
return buildV6ActionFunction(actions) ?? actions;
|
|
4095
|
+
}
|
|
4096
|
+
function buildV6ActionFunction(actions, transition) {
|
|
4097
|
+
const effects = actions.map(actionToV6Effect);
|
|
4098
|
+
if (effects.some((effect) => !effect)) return void 0;
|
|
4099
|
+
const statements = effects.flatMap((effect) => effect?.statements ?? []);
|
|
4100
|
+
let returnValue;
|
|
4101
|
+
let contextValue;
|
|
4102
|
+
for (const effect of effects) {
|
|
4103
|
+
returnValue = effect?.returnValue ?? returnValue;
|
|
4104
|
+
contextValue = effect?.contextValue ?? contextValue;
|
|
4141
4105
|
}
|
|
4142
|
-
if (
|
|
4143
|
-
if (
|
|
4144
|
-
|
|
4145
|
-
|
|
4146
|
-
|
|
4147
|
-
if (
|
|
4148
|
-
|
|
4149
|
-
|
|
4150
|
-
if (ts.isIdentifier(node)) {
|
|
4151
|
-
const binding = bindings.get(node.text);
|
|
4152
|
-
if (binding && !ts.isFunctionDeclaration(binding)) return expressionToValue(binding, bindings, context, depth + 1);
|
|
4153
|
-
}
|
|
4154
|
-
if (!ts.isObjectLiteralExpression(node) && !ts.isArrayLiteralExpression(node)) return inlineCodeExpression(node.getText());
|
|
4106
|
+
if (transition) returnValue = buildV6TransitionReturnValue(transition, transition.context === void 0 ? contextValue : serializeJS(unwrapTemplateExpressions(transition.context)));
|
|
4107
|
+
if (statements.length === 0 && !returnValue) return void 0;
|
|
4108
|
+
return raw(`(_, enq) => {\n${[...statements.map((statement) => ` ${statement};`), ...returnValue ? [` return ${returnValue};`] : []].join("\n")}\n}`);
|
|
4109
|
+
}
|
|
4110
|
+
function unwrapTemplateExpressions(value) {
|
|
4111
|
+
if (typeof value === "string") {
|
|
4112
|
+
const match = value.match(/^\{\{\s*([\s\S]*?)\s*\}\}$/);
|
|
4113
|
+
return match?.[1] ? raw(match[1]) : value;
|
|
4155
4114
|
}
|
|
4156
|
-
if (
|
|
4157
|
-
|
|
4158
|
-
|
|
4159
|
-
|
|
4160
|
-
|
|
4115
|
+
if (Array.isArray(value)) return value.map(unwrapTemplateExpressions);
|
|
4116
|
+
if (!value || typeof value !== "object") return value;
|
|
4117
|
+
return Object.fromEntries(Object.entries(value).map(([key, item]) => [key, unwrapTemplateExpressions(item)]));
|
|
4118
|
+
}
|
|
4119
|
+
function buildV6TransitionReturnValue(transition, contextValue) {
|
|
4120
|
+
if (!transition.reenter && !transition.meta && !contextValue) return transition.target ? `{ target: ${serializeJS(transition.target)} }` : void 0;
|
|
4121
|
+
return serializeJS({
|
|
4122
|
+
target: transition.target,
|
|
4123
|
+
reenter: transition.reenter ? true : void 0,
|
|
4124
|
+
meta: transition.meta,
|
|
4125
|
+
context: contextValue ? raw(contextValue) : void 0
|
|
4126
|
+
});
|
|
4127
|
+
}
|
|
4128
|
+
function mapMachineActionFields(value, mapActions) {
|
|
4129
|
+
if (Array.isArray(value)) return value.map((item) => mapMachineActionFields(item, mapActions));
|
|
4130
|
+
if (!value || typeof value !== "object") return value;
|
|
4131
|
+
const result = {};
|
|
4132
|
+
for (const [key, item] of Object.entries(value)) {
|
|
4133
|
+
if (key === "entry" || key === "exit" || key === "actions") {
|
|
4134
|
+
const wasArray = Array.isArray(item);
|
|
4135
|
+
result[key] = mapActions(wasArray ? item : item === void 0 ? [] : [item], wasArray);
|
|
4136
|
+
continue;
|
|
4161
4137
|
}
|
|
4162
|
-
|
|
4138
|
+
result[key] = mapMachineActionFields(item, mapActions);
|
|
4163
4139
|
}
|
|
4164
|
-
|
|
4165
|
-
|
|
4166
|
-
|
|
4167
|
-
|
|
4168
|
-
|
|
4169
|
-
|
|
4170
|
-
|
|
4171
|
-
|
|
4172
|
-
|
|
4173
|
-
|
|
4174
|
-
|
|
4175
|
-
|
|
4176
|
-
|
|
4177
|
-
|
|
4140
|
+
return result;
|
|
4141
|
+
}
|
|
4142
|
+
function unwrapDirectEnqExpression(action) {
|
|
4143
|
+
const expr = inlineExpr(action);
|
|
4144
|
+
if (!expr) return action;
|
|
4145
|
+
const match = expr.match(/^enq\(([\s\S]*)\)$/);
|
|
4146
|
+
return match?.[1] ? raw(match[1]) : action;
|
|
4147
|
+
}
|
|
4148
|
+
function inlineExpr(value) {
|
|
4149
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) return;
|
|
4150
|
+
const directive = value;
|
|
4151
|
+
return directive["@type"] === "code" && typeof directive.expr === "string" ? directive.expr : void 0;
|
|
4152
|
+
}
|
|
4153
|
+
function actionToV6Effect(action) {
|
|
4154
|
+
const expr = inlineExpr(action);
|
|
4155
|
+
if (expr) {
|
|
4156
|
+
if (expr.startsWith("enq(") || expr.startsWith("enq.")) return { statements: [expr] };
|
|
4157
|
+
const builtIn = expr.match(/^(raise|emit|sendTo|cancel|log|spawnChild|stopChild)\(([\s\S]*)\)$/);
|
|
4158
|
+
if (builtIn) {
|
|
4159
|
+
const [, name, args] = builtIn;
|
|
4160
|
+
return { statements: [`enq.${name === "spawnChild" ? "spawn" : name === "stopChild" ? "stop" : name}(${args})`] };
|
|
4178
4161
|
}
|
|
4179
|
-
return
|
|
4162
|
+
return { statements: [`enq(${expr})`] };
|
|
4180
4163
|
}
|
|
4181
|
-
if (
|
|
4182
|
-
|
|
4183
|
-
|
|
4184
|
-
|
|
4164
|
+
if (!action || typeof action !== "object" || Array.isArray(action)) return null;
|
|
4165
|
+
const record = action;
|
|
4166
|
+
const type = record.type;
|
|
4167
|
+
if (typeof type !== "string") return null;
|
|
4168
|
+
const params = record.params && typeof record.params === "object" && !Array.isArray(record.params) ? record.params : {};
|
|
4169
|
+
if (type === "xstate.raise") {
|
|
4170
|
+
const options = actionOptions(params, ["event"]);
|
|
4171
|
+
return { statements: [`enq.raise(${serializeJS(params.event)}${options})`] };
|
|
4172
|
+
}
|
|
4173
|
+
if (type === "xstate.emit") return { statements: [`enq.emit(${serializeJS(params.event)})`] };
|
|
4174
|
+
if (type === "xstate.sendTo") {
|
|
4175
|
+
const options = actionOptions(params, ["to", "event"]);
|
|
4176
|
+
return { statements: [`enq.sendTo(${serializeJS(params.to)}, ${serializeJS(params.event)}${options})`] };
|
|
4177
|
+
}
|
|
4178
|
+
if (type === "xstate.cancel") return { statements: [`enq.cancel(${serializeJS(params.sendId)})`] };
|
|
4179
|
+
if (type === "xstate.log") return { statements: [`enq.log(${serializeJS(params.label)})`] };
|
|
4180
|
+
if (type === "xstate.spawnChild") {
|
|
4181
|
+
const options = actionOptions(params, ["src"]);
|
|
4182
|
+
return { statements: [`enq.spawn(${serializeJS(params.src)}${options})`] };
|
|
4183
|
+
}
|
|
4184
|
+
if (type === "xstate.stopChild") return { statements: [`enq.stop(${serializeJS(params.actorRef)})`] };
|
|
4185
|
+
if (type === "xstate.assign") {
|
|
4186
|
+
const contextValue = serializeJS(params.assignment ?? params);
|
|
4187
|
+
return {
|
|
4188
|
+
contextValue,
|
|
4189
|
+
returnValue: `{ context: ${contextValue} }`
|
|
4190
|
+
};
|
|
4191
|
+
}
|
|
4192
|
+
return null;
|
|
4193
|
+
}
|
|
4194
|
+
function actionOptions(params, consumedKeys) {
|
|
4195
|
+
const rest = Object.fromEntries(Object.entries(params).filter(([key, value]) => !consumedKeys.includes(key) && value !== void 0));
|
|
4196
|
+
return Object.keys(rest).length ? `, ${serializeJS(rest)}` : "";
|
|
4197
|
+
}
|
|
4198
|
+
function buildImports({ hasSetup, hasActors, actors, builtInActions, actorSourceImports, usesTypes }) {
|
|
4199
|
+
const xstateImports = [];
|
|
4200
|
+
if (hasSetup) xstateImports.push("setup");
|
|
4201
|
+
else xstateImports.push("createMachine");
|
|
4202
|
+
for (const name of builtInActions) xstateImports.push(name);
|
|
4203
|
+
for (const name of actorSourceImports) xstateImports.push(name);
|
|
4204
|
+
if (usesTypes) xstateImports.push("types");
|
|
4205
|
+
if (hasActors) {
|
|
4206
|
+
if (actors.length > 0) xstateImports.push("fromPromise");
|
|
4185
4207
|
}
|
|
4186
|
-
|
|
4187
|
-
|
|
4188
|
-
|
|
4189
|
-
|
|
4190
|
-
|
|
4208
|
+
return `import { ${[...new Set(xstateImports)].join(", ")} } from 'xstate';`;
|
|
4209
|
+
}
|
|
4210
|
+
function getActorSourceImports(graph) {
|
|
4211
|
+
const imports = /* @__PURE__ */ new Set();
|
|
4212
|
+
const candidates = [
|
|
4213
|
+
"createAsyncLogic",
|
|
4214
|
+
"fromPromise",
|
|
4215
|
+
"fromCallback",
|
|
4216
|
+
"fromObservable",
|
|
4217
|
+
"fromEventObservable",
|
|
4218
|
+
"fromTransition"
|
|
4219
|
+
];
|
|
4220
|
+
for (const node of graph.nodes) for (const invoke of node.data.invokes ?? []) {
|
|
4221
|
+
const expression = invoke.srcExpression?.expr;
|
|
4222
|
+
if (!expression) continue;
|
|
4223
|
+
for (const candidate of candidates) if (new RegExp(`\\b${candidate}\\b`).test(expression)) imports.add(candidate);
|
|
4191
4224
|
}
|
|
4192
|
-
|
|
4193
|
-
|
|
4194
|
-
|
|
4195
|
-
|
|
4196
|
-
|
|
4197
|
-
|
|
4198
|
-
if (
|
|
4199
|
-
|
|
4200
|
-
|
|
4201
|
-
|
|
4202
|
-
if (context.actionValue) return inlineAction(node);
|
|
4203
|
-
const callee = node.expression.getText();
|
|
4204
|
-
const type = callee.includes(".") ? callee.split(".").pop() : callee;
|
|
4205
|
-
return { type: type === "assign" ? "xstate.assign" : type };
|
|
4225
|
+
return imports;
|
|
4226
|
+
}
|
|
4227
|
+
function buildSetupObject(schemas, impls, options) {
|
|
4228
|
+
const setup = {};
|
|
4229
|
+
if (options.xstateVersion === 6) {
|
|
4230
|
+
const schemasBlock = buildV6SchemasBlock(schemas, options);
|
|
4231
|
+
if (schemasBlock) setup.schemas = schemasBlock;
|
|
4232
|
+
} else {
|
|
4233
|
+
const types = buildTypesBlock(schemas, options);
|
|
4234
|
+
if (types) setup.types = types;
|
|
4206
4235
|
}
|
|
4207
|
-
|
|
4236
|
+
if (impls?.actions.length) setup.actions = buildActionsBlock(impls.actions, options);
|
|
4237
|
+
if (impls?.guards.length) setup.guards = buildGuardsBlock(impls.guards, options);
|
|
4238
|
+
if (impls?.actors.length) setup.actors = buildActorsBlock(impls.actors, options);
|
|
4239
|
+
if (impls?.delays.length) setup.delays = buildDelaysBlock(impls.delays);
|
|
4240
|
+
return setup;
|
|
4208
4241
|
}
|
|
4209
|
-
function
|
|
4210
|
-
|
|
4242
|
+
function buildTypesBlock(schemas, options) {
|
|
4243
|
+
if (!schemas || !options.includeTypeSyntax) return void 0;
|
|
4244
|
+
const types = {};
|
|
4245
|
+
const contextType = contextSchemaToTSType(schemas.context);
|
|
4246
|
+
if (contextType) types.context = raw(`{} as ${contextType}`);
|
|
4247
|
+
const eventsType = eventsSchemaToTSType(schemas.events);
|
|
4248
|
+
if (eventsType) types.events = raw(`{} as\n | ${eventsType}`);
|
|
4249
|
+
if (schemas.input) types.input = raw(`{} as ${jsonSchemaToTSType(schemas.input)}`);
|
|
4250
|
+
if (schemas.output) types.output = raw(`{} as ${jsonSchemaToTSType(schemas.output)}`);
|
|
4251
|
+
return Object.keys(types).length > 0 ? types : void 0;
|
|
4211
4252
|
}
|
|
4212
|
-
function
|
|
4213
|
-
|
|
4214
|
-
|
|
4215
|
-
|
|
4216
|
-
|
|
4217
|
-
|
|
4218
|
-
|
|
4253
|
+
function buildV6SchemasBlock(schemas, options) {
|
|
4254
|
+
if (!schemas || !options.includeTypeSyntax) return void 0;
|
|
4255
|
+
const result = {};
|
|
4256
|
+
const contextType = contextSchemaToTSType(schemas.context);
|
|
4257
|
+
if (contextType) result.context = raw(`types<${contextType}>()`);
|
|
4258
|
+
if (schemas.events && Object.keys(schemas.events).length > 0) result.events = Object.fromEntries(Object.entries(schemas.events).map(([eventType, schema]) => [eventType, raw(`types<${eventPayloadSchemaToTSType(schema)}>()`)]));
|
|
4259
|
+
if (schemas.input) result.input = raw(`types<${jsonSchemaToTSType(schemas.input)}>()`);
|
|
4260
|
+
if (schemas.output) result.output = raw(`types<${jsonSchemaToTSType(schemas.output)}>()`);
|
|
4261
|
+
return Object.keys(result).length > 0 ? result : void 0;
|
|
4262
|
+
}
|
|
4263
|
+
function eventPayloadSchemaToTSType(schema) {
|
|
4264
|
+
const props = schema.properties ?? {};
|
|
4265
|
+
const payloadProps = Object.fromEntries(Object.entries(props).filter(([key]) => key !== "type"));
|
|
4266
|
+
if (Object.keys(payloadProps).length === 0) return "{}";
|
|
4267
|
+
return jsonSchemaToTSType({
|
|
4268
|
+
...schema,
|
|
4269
|
+
properties: payloadProps,
|
|
4270
|
+
required: Array.isArray(schema.required) ? schema.required.filter((key) => key !== "type") : void 0
|
|
4271
|
+
});
|
|
4272
|
+
}
|
|
4273
|
+
function hasSchemaProperties(schema) {
|
|
4274
|
+
if (!schema) return false;
|
|
4275
|
+
if (schema.type === "object" || schema.properties) {
|
|
4276
|
+
const props = schema.properties;
|
|
4277
|
+
return !!props && Object.keys(props).length > 0;
|
|
4219
4278
|
}
|
|
4220
|
-
|
|
4221
|
-
if (context.v6 && context.transitionValue) return normalizeFunctionTransition(fn, scopedBindings, depth + 1);
|
|
4222
|
-
if (context.v6 && context.actionValue) return normalizeFunctionAction(fn, scopedBindings);
|
|
4223
|
-
return context.metaValue ? inlineCodeExpression(fn.getText()) : fn.name?.getText() ?? fn.getText();
|
|
4279
|
+
return true;
|
|
4224
4280
|
}
|
|
4225
|
-
function
|
|
4226
|
-
const
|
|
4227
|
-
for (const
|
|
4228
|
-
|
|
4229
|
-
|
|
4281
|
+
function buildActionsBlock(actions, options) {
|
|
4282
|
+
const block = {};
|
|
4283
|
+
for (const implementation of actions) if (implementation.code?.body) {
|
|
4284
|
+
const inlineExpression = getInlineExpression(implementation.code.body);
|
|
4285
|
+
if (inlineExpression) {
|
|
4286
|
+
block[implementation.name] = raw(inlineExpression);
|
|
4230
4287
|
continue;
|
|
4231
4288
|
}
|
|
4232
|
-
|
|
4233
|
-
|
|
4234
|
-
|
|
4235
|
-
|
|
4236
|
-
function isCreateMachineCall(node) {
|
|
4237
|
-
const expression = node.expression;
|
|
4238
|
-
if (ts.isIdentifier(expression)) return expression.text === "createMachine";
|
|
4239
|
-
if (ts.isPropertyAccessExpression(expression)) return expression.name.text === "createMachine";
|
|
4240
|
-
return false;
|
|
4289
|
+
const params = hasSchemaProperties(implementation.paramsSchema) ? options.includeTypeSyntax ? `, params: ${jsonSchemaToTSType(implementation.paramsSchema)}` : ", params" : "";
|
|
4290
|
+
block[implementation.name] = raw(`function ({ context, event }${params ? params : ""}) {\n ${dedent(implementation.code.body)}\n}`);
|
|
4291
|
+
} else block[implementation.name] = raw(`function ({ context, event }) {\n // TODO: implement ${implementation.name}\n}`);
|
|
4292
|
+
return block;
|
|
4241
4293
|
}
|
|
4242
|
-
function
|
|
4243
|
-
const
|
|
4244
|
-
const
|
|
4245
|
-
|
|
4246
|
-
|
|
4247
|
-
|
|
4248
|
-
|
|
4249
|
-
if (ts.isArrowFunction(node) || ts.isFunctionExpression(node)) return true;
|
|
4250
|
-
if (ts.isIdentifier(node)) {
|
|
4251
|
-
if (seenBindings.has(node.text)) return false;
|
|
4252
|
-
const binding = bindings.get(node.text);
|
|
4253
|
-
if (!binding) return false;
|
|
4254
|
-
return containsFunction(binding, new Set([...seenBindings, node.text]));
|
|
4255
|
-
}
|
|
4256
|
-
if (ts.isObjectLiteralExpression(node)) return node.properties.some((property) => {
|
|
4257
|
-
if (ts.isPropertyAssignment(property)) return containsFunction(property.initializer, seenBindings);
|
|
4258
|
-
if (ts.isShorthandPropertyAssignment(property)) return containsFunction(property.name, seenBindings);
|
|
4259
|
-
if (ts.isSpreadAssignment(property)) return containsFunction(property.expression, seenBindings);
|
|
4260
|
-
return false;
|
|
4261
|
-
});
|
|
4262
|
-
if (ts.isArrayLiteralExpression(node)) return node.elements.some((element) => ts.isExpression(element) && containsFunction(element, seenBindings));
|
|
4263
|
-
if (ts.isCallExpression(node)) return ts.isIdentifier(node.expression) && containsFunction(node.expression, seenBindings) || node.arguments.some((argument) => ts.isExpression(argument) && containsFunction(argument, seenBindings));
|
|
4264
|
-
return false;
|
|
4265
|
-
}
|
|
4266
|
-
function visit(node) {
|
|
4267
|
-
if (found) return;
|
|
4268
|
-
if (ts.isPropertyAssignment(node) && (ts.isIdentifier(node.name) || ts.isStringLiteral(node.name))) {
|
|
4269
|
-
const key = node.name.text;
|
|
4270
|
-
if (key === "triggers" || key === "internalEvents" || key === "matches" || key === "actorSources" || key === "timeout" || key === "onTimeout" || key === "choice" || key === "route") {
|
|
4271
|
-
found = true;
|
|
4272
|
-
return;
|
|
4273
|
-
}
|
|
4274
|
-
if ((key === "on" || key === "after" || key === "always" || key === "choice" || key === "onDone" || key === "onError" || key === "onSnapshot" || key === "onTimeout" || key === "entry" || key === "exit" || key === "actions" && !ts.isObjectLiteralExpression(node.initializer)) && containsFunction(node.initializer)) {
|
|
4275
|
-
found = true;
|
|
4276
|
-
return;
|
|
4277
|
-
}
|
|
4294
|
+
function buildGuardsBlock(guards, options) {
|
|
4295
|
+
const block = {};
|
|
4296
|
+
for (const guard of guards) if (guard.code?.body) {
|
|
4297
|
+
const inlineExpression = getInlineExpression(guard.code.body);
|
|
4298
|
+
if (inlineExpression) {
|
|
4299
|
+
block[guard.name] = raw(inlineExpression);
|
|
4300
|
+
continue;
|
|
4278
4301
|
}
|
|
4279
|
-
|
|
4280
|
-
|
|
4281
|
-
|
|
4282
|
-
return
|
|
4302
|
+
const params = hasSchemaProperties(guard.paramsSchema) ? options.includeTypeSyntax ? `, params: ${jsonSchemaToTSType(guard.paramsSchema)}` : ", params" : "";
|
|
4303
|
+
block[guard.name] = raw(`function ({ context, event }${params ? params : ""}) {\n ${dedent(guard.code.body)}\n}`);
|
|
4304
|
+
} else block[guard.name] = raw(`function ({ context, event }) {\n // TODO: implement ${guard.name}\n return false;\n}`);
|
|
4305
|
+
return block;
|
|
4283
4306
|
}
|
|
4284
|
-
function
|
|
4285
|
-
|
|
4307
|
+
function buildActorsBlock(actors, options) {
|
|
4308
|
+
const block = {};
|
|
4309
|
+
for (const actor of actors) if (actor.code?.body) {
|
|
4310
|
+
const inputType = options.includeTypeSyntax && hasSchemaProperties(actor.inputSchema) ? `: ${jsonSchemaToTSType(actor.inputSchema)}` : "";
|
|
4311
|
+
block[actor.name] = raw(`fromPromise(async ({ input }${inputType ? `: { input${inputType} }` : ""}) => {\n ${dedent(actor.code.body)}\n})`);
|
|
4312
|
+
} else block[actor.name] = raw(`fromPromise(async ({ input }) => {\n // TODO: implement ${actor.name}\n})`);
|
|
4313
|
+
return block;
|
|
4286
4314
|
}
|
|
4287
|
-
function
|
|
4288
|
-
const
|
|
4289
|
-
|
|
4290
|
-
|
|
4315
|
+
function buildDelaysBlock(delays) {
|
|
4316
|
+
const block = {};
|
|
4317
|
+
for (const delay of delays) if (delay.code?.body) {
|
|
4318
|
+
const inlineExpression = getInlineExpression(delay.code.body);
|
|
4319
|
+
if (inlineExpression) {
|
|
4320
|
+
block[delay.name] = raw(inlineExpression);
|
|
4321
|
+
continue;
|
|
4322
|
+
}
|
|
4323
|
+
block[delay.name] = raw(`function ({ context, event }) {\n ${dedent(delay.code.body)}\n}`);
|
|
4324
|
+
} else block[delay.name] = raw(`function () {\n // TODO: implement ${delay.name}\n return 1000;\n}`);
|
|
4325
|
+
return block;
|
|
4291
4326
|
}
|
|
4292
4327
|
/**
|
|
4293
|
-
*
|
|
4294
|
-
*
|
|
4328
|
+
* Returns the implementation to emit verbatim when `body` is already a complete
|
|
4329
|
+
* expression, so it is NOT wrapped in another `function ({ context, event }) { ... }`.
|
|
4330
|
+
* Handles two cases:
|
|
4331
|
+
* - `export default <expr>` → the inner expression.
|
|
4332
|
+
* - a bare function/arrow expression (e.g. a guard captured via `fn.toString()`
|
|
4333
|
+
* on import) → the expression itself.
|
|
4334
|
+
* Returns undefined for a plain statement body, which still needs wrapping.
|
|
4295
4335
|
*/
|
|
4296
|
-
function
|
|
4297
|
-
const
|
|
4298
|
-
|
|
4299
|
-
|
|
4300
|
-
|
|
4301
|
-
|
|
4302
|
-
|
|
4303
|
-
|
|
4304
|
-
|
|
4305
|
-
|
|
4306
|
-
|
|
4307
|
-
|
|
4308
|
-
|
|
4309
|
-
|
|
4310
|
-
|
|
4311
|
-
visit(file);
|
|
4312
|
-
return found;
|
|
4336
|
+
function getInlineExpression(code) {
|
|
4337
|
+
const stripped = stripExportDefault(code);
|
|
4338
|
+
if (stripped !== code.trim()) return stripped;
|
|
4339
|
+
return isCompleteFunctionExpression(stripped) ? stripped : void 0;
|
|
4340
|
+
}
|
|
4341
|
+
/** True when `code` is a single function or arrow-function expression. */
|
|
4342
|
+
function isCompleteFunctionExpression(code) {
|
|
4343
|
+
const candidate = code.trim().replace(/;$/, "");
|
|
4344
|
+
const source = ts.createSourceFile("impl.ts", `(${candidate})`, ts.ScriptTarget.Latest, false, ts.ScriptKind.TS);
|
|
4345
|
+
if ((source.parseDiagnostics ?? []).length > 0 || source.statements.length !== 1) return false;
|
|
4346
|
+
const [statement] = source.statements;
|
|
4347
|
+
if (!statement || !ts.isExpressionStatement(statement)) return false;
|
|
4348
|
+
let expression = statement.expression;
|
|
4349
|
+
if (ts.isParenthesizedExpression(expression)) expression = expression.expression;
|
|
4350
|
+
return ts.isFunctionExpression(expression) || ts.isArrowFunction(expression);
|
|
4313
4351
|
}
|
|
4314
4352
|
const colorSchema = _enum([
|
|
4315
4353
|
"green",
|
|
@@ -4553,7 +4591,12 @@ const machineFormatSchema = _enum([
|
|
|
4553
4591
|
"scxml",
|
|
4554
4592
|
"mermaid"
|
|
4555
4593
|
]);
|
|
4556
|
-
const
|
|
4594
|
+
const canonicalMachineProfileSchema = custom((value) => typeof value === "string" && /^@statelyai\/xstate@\d+\.\d+\.\d+(?:-[0-9A-Za-z.-]+)?(?:\+[0-9A-Za-z.-]+)?$/.test(value), "Expected an exact @statelyai/xstate profile reference.");
|
|
4595
|
+
const xstateSourceProfileSchema = union([
|
|
4596
|
+
literal("auto"),
|
|
4597
|
+
_enum(LEGACY_MACHINE_PROFILES),
|
|
4598
|
+
canonicalMachineProfileSchema
|
|
4599
|
+
]);
|
|
4557
4600
|
const machineInputSchema = object({
|
|
4558
4601
|
machine: union([record(string(), unknown()), string()]),
|
|
4559
4602
|
format: machineFormatSchema.optional(),
|
|
@@ -5078,4 +5121,4 @@ function getScriptKind(fileName) {
|
|
|
5078
5121
|
}
|
|
5079
5122
|
|
|
5080
5123
|
//#endregion
|
|
5081
|
-
export { RawCode as a, eventsSchemaToTSType as c, jsonSchemaToTSType as d,
|
|
5124
|
+
export { RawCode as a, eventsSchemaToTSType as c, jsonSchemaToTSType as d, normalizeMachineProfile as f, xstateSourceToConfig as h, INLINE_EXPRESSION_DIRECTIVE_FIELDS as i, graphToMachineConfig as l, serializeJS as m, getStatelyPragma as n, contextSchemaToTSType as o, raw as p, upsertStatelyPragma as r, detectXStateSourceProfile as s, findStatelyPragmaAttachments as t, graphToXStateTS as u };
|