@statelyai/sdk 0.29.1 → 0.31.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 +15 -0
- package/dist/assetStorage.d.mts +1 -1
- package/dist/auth.d.mts +1 -1
- package/dist/{statelyPragma-p1vu8PmH.mjs → dist-wbhkeGh6.mjs} +468 -204
- package/dist/{editor-sync-types-DB1N6QUK.d.mts → editor-sync-types-CPpzTSnT.d.mts} +4 -0
- package/dist/{editorHostSession-vSt07IJV.d.mts → editorHostSession-Bo-YhDEG.d.mts} +105 -6
- package/dist/{editorHostSession-DNpXPNAc.mjs → editorHostSession-CT8y0yzG.mjs} +380 -20
- package/dist/editorHostSession.d.mts +2 -2
- package/dist/editorHostSession.mjs +3 -2
- package/dist/embed.d.mts +3 -4
- package/dist/embed.mjs +5 -2
- package/dist/{graph-C8E1Exad.d.mts → graph-CR_g-mOq.d.mts} +1 -1
- package/dist/graph.d.mts +1 -1
- package/dist/{index-D4pdeDpT.d.mts → index-DlOZxzrW.d.mts} +92 -2
- package/dist/index.d.mts +8 -9
- package/dist/index.mjs +6 -5
- package/dist/{inspect-D61HS-t7.d.mts → inspect-BoWXrB-V.d.mts} +3 -2
- package/dist/{inspect-dmCvrIl1.mjs → inspect-DoDj7iWa.mjs} +25 -1
- package/dist/inspect.d.mts +2 -2
- package/dist/inspect.mjs +2 -2
- package/dist/patchTypes.d.mts +1 -1
- package/dist/protocol-2cvzJtGN.d.mts +846 -0
- package/dist/protocol.d.mts +2 -821
- package/dist/relay.d.mts +1 -1
- package/dist/statelyPragma-D46lczJR.mjs +102 -0
- package/dist/{studio-D-yqFd0u.d.mts → studio-DV5IIGhV.d.mts} +2 -2
- package/dist/studio.d.mts +1 -1
- package/dist/sync.d.mts +2 -2
- package/dist/sync.mjs +411 -30
- package/dist/{version-DC3yW9Dk.mjs → version-B6OHpDiz.mjs} +1 -1
- package/package.json +3 -3
- package/schemas/statelyai.schema.json +6 -0
- package/dist/embedPanel-Bpbq4sfJ.d.mts +0 -13
- /package/dist/{auth-BPyCCHYo.d.mts → auth-Dg7prjeL.d.mts} +0 -0
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { a as discriminatedUnion, c as object, d as union, f as unknown, i as custom, l as record, n as array, o as literal, r as boolean, s as number, t as _enum, u as string } from "./openapi-BTDjYWXd.mjs";
|
|
2
2
|
import ts from "typescript";
|
|
3
|
+
import "xstate";
|
|
3
4
|
import "xstate/graph";
|
|
4
5
|
|
|
5
6
|
//#region ../../node_modules/.pnpm/js-yaml@4.2.0/node_modules/js-yaml/dist/js-yaml.mjs
|
|
@@ -3166,6 +3167,10 @@ function graphChangeToPatchesResult(prevGraph, nextGraph) {
|
|
|
3166
3167
|
op: "deleteTransition",
|
|
3167
3168
|
transitionId: edge.id
|
|
3168
3169
|
});
|
|
3170
|
+
if (prevGraph.data.profile !== nextGraph.data.profile) patches.push({
|
|
3171
|
+
op: "setProfile",
|
|
3172
|
+
profile: nextGraph.data.profile ?? "xstate-v5"
|
|
3173
|
+
});
|
|
3169
3174
|
if (!isEqual(prevGraph.data.context, nextGraph.data.context)) patches.push({
|
|
3170
3175
|
op: "setContext",
|
|
3171
3176
|
context: nextGraph.data.context ?? null
|
|
@@ -3272,6 +3277,40 @@ function alignCompareGraphIds(base, compare, semanticBase, semanticCompare) {
|
|
|
3272
3277
|
}
|
|
3273
3278
|
return aligned;
|
|
3274
3279
|
}
|
|
3280
|
+
const XSTATE_V5_PROFILE = "@statelyai/xstate@5.30.0";
|
|
3281
|
+
const XSTATE_V6_PROFILE = "@statelyai/xstate@6.0.0-alpha.51";
|
|
3282
|
+
const XSTATE_V6_BRANCH_DESCRIPTION_META = "@statelyai.branchDescription";
|
|
3283
|
+
const LEGACY_MACHINE_PROFILES = ["xstate-v5", "xstate-v6-alpha"];
|
|
3284
|
+
function normalizeMachineProfile(profile) {
|
|
3285
|
+
return profile === "xstate-v5" ? XSTATE_V5_PROFILE : profile === "xstate-v6-alpha" ? XSTATE_V6_PROFILE : profile;
|
|
3286
|
+
}
|
|
3287
|
+
function isXStateV6Profile(profile) {
|
|
3288
|
+
return (profile === "xstate-v5" || profile === "xstate-v6-alpha" ? normalizeMachineProfile(profile) : profile ?? XSTATE_V5_PROFILE).startsWith("@statelyai/xstate@6.");
|
|
3289
|
+
}
|
|
3290
|
+
const EXACT_SEMVER$1 = /^\d+\.\d+\.\d+(?:-[0-9A-Za-z-]+(?:\.[0-9A-Za-z-]+)*)?(?:\+[0-9A-Za-z-]+(?:\.[0-9A-Za-z-]+)*)?$/;
|
|
3291
|
+
function parseProfileSpecifier(specifier) {
|
|
3292
|
+
const separator = specifier.lastIndexOf("@");
|
|
3293
|
+
const name = specifier.slice(0, separator);
|
|
3294
|
+
const version = specifier.slice(separator + 1);
|
|
3295
|
+
if (separator <= 0 || !/^@[^/]+\/[^@/]+$/.test(name) || !version) throw new Error(`Invalid profile specifier: ${specifier}`);
|
|
3296
|
+
return {
|
|
3297
|
+
name,
|
|
3298
|
+
version,
|
|
3299
|
+
kind: EXACT_SEMVER$1.test(version) ? "exact" : "range"
|
|
3300
|
+
};
|
|
3301
|
+
}
|
|
3302
|
+
function normalizeProfileRef(profile) {
|
|
3303
|
+
return profile === "xstate-v5" || profile === "xstate-v6-alpha" ? normalizeMachineProfile(profile) : profile;
|
|
3304
|
+
}
|
|
3305
|
+
const AFTER_EVENT_PREFIX = "xstate.after.";
|
|
3306
|
+
/** Recovers an authored delay key from an internal after-event type. */
|
|
3307
|
+
function getDelayKeyFromEventType(eventType, sourceId) {
|
|
3308
|
+
if (!eventType.startsWith(AFTER_EVENT_PREFIX)) return null;
|
|
3309
|
+
const encoded = eventType.slice(13);
|
|
3310
|
+
const sourceSuffix = sourceId ? `.${sourceId}` : null;
|
|
3311
|
+
if (sourceSuffix && encoded.endsWith(sourceSuffix)) return encoded.slice(0, -sourceSuffix.length);
|
|
3312
|
+
return encoded.split(".")[0] ?? encoded;
|
|
3313
|
+
}
|
|
3275
3314
|
function isAutoGeneratedId(id) {
|
|
3276
3315
|
return !!id && id.startsWith("$auto-");
|
|
3277
3316
|
}
|
|
@@ -3387,15 +3426,6 @@ function stripExportDefault(code) {
|
|
|
3387
3426
|
if (trimmed.startsWith("export default ")) return trimmed.slice(15).replace(/;$/, "");
|
|
3388
3427
|
return trimmed;
|
|
3389
3428
|
}
|
|
3390
|
-
const XSTATE_V5_PROFILE = "@statelyai/xstate@5.30.0";
|
|
3391
|
-
const XSTATE_V6_PROFILE = "@statelyai/xstate@6.0.0-alpha.51";
|
|
3392
|
-
const LEGACY_MACHINE_PROFILES = ["xstate-v5", "xstate-v6-alpha"];
|
|
3393
|
-
function normalizeMachineProfile(profile) {
|
|
3394
|
-
return profile === "xstate-v5" ? XSTATE_V5_PROFILE : profile === "xstate-v6-alpha" ? XSTATE_V6_PROFILE : profile;
|
|
3395
|
-
}
|
|
3396
|
-
function isXStateV6Profile(profile) {
|
|
3397
|
-
return (profile === "xstate-v5" || profile === "xstate-v6-alpha" ? normalizeMachineProfile(profile) : profile ?? XSTATE_V5_PROFILE).startsWith("@statelyai/xstate@6.");
|
|
3398
|
-
}
|
|
3399
3429
|
/**
|
|
3400
3430
|
* Graph-native transition references. Transitions point at invoke/action/state
|
|
3401
3431
|
* blocks by graph id (`@statelyai.*`); the literal `xstate.*` event is produced
|
|
@@ -3491,6 +3521,7 @@ function singleOrArrayRecord(record) {
|
|
|
3491
3521
|
* declares that the machine has context, so dropping it loses information.
|
|
3492
3522
|
*/
|
|
3493
3523
|
const KEEP_WHEN_EMPTY = new Set(["context"]);
|
|
3524
|
+
const KEEP_SINGLETON_ARRAY = new Set(["internalEvents", "tags"]);
|
|
3494
3525
|
function simplifyAttributes(obj) {
|
|
3495
3526
|
for (const key of Object.keys(obj)) {
|
|
3496
3527
|
const value = obj[key];
|
|
@@ -3498,7 +3529,7 @@ function simplifyAttributes(obj) {
|
|
|
3498
3529
|
else if (KEEP_WHEN_EMPTY.has(key)) continue;
|
|
3499
3530
|
else if (Array.isArray(value)) {
|
|
3500
3531
|
if (value.length === 0) delete obj[key];
|
|
3501
|
-
else if (value.length === 1) obj[key] = value[0];
|
|
3532
|
+
else if (value.length === 1 && !KEEP_SINGLETON_ARRAY.has(key)) obj[key] = value[0];
|
|
3502
3533
|
} else if (typeof value === "object" && Object.keys(value).length === 0) delete obj[key];
|
|
3503
3534
|
else if (typeof value === "string" && value === "") delete obj[key];
|
|
3504
3535
|
}
|
|
@@ -3877,11 +3908,15 @@ function graphToMachineConfig(graph, options = {}) {
|
|
|
3877
3908
|
for (const edge of edges) {
|
|
3878
3909
|
const targetNode = graph.nodes.find((n) => n.id === edge.targetId);
|
|
3879
3910
|
const resolvedTarget = targetNode ? resolveTransitionTarget(graph, node, targetNode) : "";
|
|
3911
|
+
const resolvedTargets = [resolvedTarget, ...(edge.data.additionalTargetIds ?? []).flatMap((targetId) => {
|
|
3912
|
+
const additionalTarget = graph.nodes.find((n) => n.id === targetId);
|
|
3913
|
+
return additionalTarget ? [resolveTransitionTarget(graph, node, additionalTarget)] : [];
|
|
3914
|
+
})].filter(Boolean);
|
|
3880
3915
|
const type = edge.data.eventType ?? "";
|
|
3881
3916
|
const transitionMeta = showMeta ? buildMeta(edge.data.meta, edge.data.color) : void 0;
|
|
3882
3917
|
const transitionObject = {
|
|
3883
3918
|
...edge.data.matches ? { matches: edge.data.matches } : void 0,
|
|
3884
|
-
target: edge.data.transitionType === "targetless" ? void 0 : `${resolvedTarget}`,
|
|
3919
|
+
target: edge.data.transitionType === "targetless" ? void 0 : resolvedTargets.length > 1 ? resolvedTargets : `${resolvedTarget}`,
|
|
3885
3920
|
...edge.data.transitionType === "reenter" ? { reenter: true } : void 0,
|
|
3886
3921
|
guard: edge.data.guard ? serializeGuard(edge.data.guard, inlineGuardsAsTypeRef) : void 0,
|
|
3887
3922
|
...edge.data.context !== void 0 ? { context: edge.data.context } : void 0,
|
|
@@ -3929,16 +3964,16 @@ function graphToMachineConfig(graph, options = {}) {
|
|
|
3929
3964
|
else if (type === "" && node.data.type === "choice") choiceArr.push(transitionObject);
|
|
3930
3965
|
else if (type === "") alwaysArr.push(transitionObject);
|
|
3931
3966
|
else if (type.startsWith("xstate.after.")) {
|
|
3932
|
-
const delayKey = type.
|
|
3967
|
+
const delayKey = getDelayKeyFromEventType(type, edge.sourceId);
|
|
3933
3968
|
if (!after[delayKey]) after[delayKey] = [];
|
|
3934
3969
|
after[delayKey].push(transitionObject);
|
|
3935
3970
|
} else if (type === "*") pushOn("*");
|
|
3936
3971
|
else if (type.startsWith("xstate.done.state")) {
|
|
3937
3972
|
if (!onDone[type]) onDone[type] = [];
|
|
3938
3973
|
onDone[type].push(transitionObject);
|
|
3939
|
-
} else if (type.startsWith("xstate.done.actor.") || type.startsWith("xstate.error.actor.") || type.startsWith("xstate.snapshot.actor.")) {
|
|
3974
|
+
} else if (type.startsWith("xstate.done.actor.") || type.startsWith("xstate.error.actor.") || type.startsWith("xstate.snapshot.actor.") || type.startsWith("xstate.snapshot.")) {
|
|
3940
3975
|
const verb = type.startsWith("xstate.done.actor.") ? "onDone" : type.startsWith("xstate.error.actor.") ? "onError" : "onSnapshot";
|
|
3941
|
-
const invoke = findInvokeByActorId(node, type.slice(type.lastIndexOf(".actor.") + 7));
|
|
3976
|
+
const invoke = findInvokeByActorId(node, type.startsWith("xstate.snapshot.") ? type.slice(16).replace(/^actor\./, "") : type.slice(type.lastIndexOf(".actor.") + 7));
|
|
3942
3977
|
if (invoke) nestInvoke(invoke.id, verb);
|
|
3943
3978
|
else pushOn(type);
|
|
3944
3979
|
} else pushOn(type);
|
|
@@ -3979,6 +4014,7 @@ function graphToMachineConfig(graph, options = {}) {
|
|
|
3979
4014
|
if (graph.data.context !== void 0 && graph.data.context !== null) config.context = graph.data.context;
|
|
3980
4015
|
if (graph.data.version) config.version = graph.data.version;
|
|
3981
4016
|
if (graph.data.options?.maxIterations !== void 0) config.options = { maxIterations: graph.data.options.maxIterations };
|
|
4017
|
+
if (graph.data.internalEvents?.length) config.internalEvents = graph.data.internalEvents;
|
|
3982
4018
|
return deepSimplify(config);
|
|
3983
4019
|
}
|
|
3984
4020
|
const INLINE_EXPRESSION_DIRECTIVE_FIELDS = [
|
|
@@ -3989,25 +4025,79 @@ const INLINE_EXPRESSION_DIRECTIVE_FIELDS = [
|
|
|
3989
4025
|
"initialInput",
|
|
3990
4026
|
"route"
|
|
3991
4027
|
];
|
|
3992
|
-
|
|
3993
|
-
|
|
3994
|
-
const
|
|
3995
|
-
|
|
3996
|
-
|
|
3997
|
-
|
|
3998
|
-
|
|
3999
|
-
|
|
4000
|
-
|
|
4001
|
-
|
|
4002
|
-
|
|
4003
|
-
|
|
4004
|
-
|
|
4005
|
-
|
|
4006
|
-
|
|
4028
|
+
function analyzeXStateV5Compatibility(graph) {
|
|
4029
|
+
const issues = [];
|
|
4030
|
+
const graphPaths = [
|
|
4031
|
+
["data.version", graph.data.version],
|
|
4032
|
+
["data.options", graph.data.options],
|
|
4033
|
+
["data.schemas.input", graph.data.schemas?.input],
|
|
4034
|
+
["data.schemas.output", graph.data.schemas?.output]
|
|
4035
|
+
].filter(([, value]) => value != null);
|
|
4036
|
+
if (graphPaths.length) issues.push({
|
|
4037
|
+
level: "warning",
|
|
4038
|
+
message: "XState v6 machine fields are retained but read-only in XState v5.",
|
|
4039
|
+
readOnlyPaths: graphPaths.map(([path]) => path)
|
|
4040
|
+
});
|
|
4041
|
+
for (const node of graph.nodes) {
|
|
4042
|
+
const paths = [
|
|
4043
|
+
["data.initialInput", node.data.initialInput],
|
|
4044
|
+
["data.timeout", node.data.timeout],
|
|
4045
|
+
["data.route", node.data.route],
|
|
4046
|
+
["data.schemas", node.data.schemas]
|
|
4047
|
+
].filter(([, value]) => value != null);
|
|
4048
|
+
if (paths.length) issues.push({
|
|
4049
|
+
level: "warning",
|
|
4050
|
+
message: `XState v6 fields on ${node.data.key ?? node.id} are retained but read-only in XState v5.`,
|
|
4051
|
+
nodeIds: [node.id],
|
|
4052
|
+
readOnlyPaths: paths.map(([path]) => `nodes.${node.id}.${path}`)
|
|
4053
|
+
});
|
|
4054
|
+
}
|
|
4055
|
+
for (const edge of graph.edges) {
|
|
4056
|
+
const paths = [["data.matches", edge.data.matches], ["data.input", edge.data.input]].filter(([, value]) => value != null);
|
|
4057
|
+
if (paths.length) issues.push({
|
|
4058
|
+
level: "warning",
|
|
4059
|
+
message: "XState v6 transition fields are retained but read-only in XState v5.",
|
|
4060
|
+
edgeIds: [edge.id],
|
|
4061
|
+
readOnlyPaths: paths.map(([path]) => `edges.${edge.id}.${path}`)
|
|
4062
|
+
});
|
|
4063
|
+
}
|
|
4064
|
+
return issues;
|
|
4065
|
+
}
|
|
4066
|
+
const XSTATE_V5_PROJECTION = {
|
|
4067
|
+
readOnlyPaths: [
|
|
4068
|
+
"data.version",
|
|
4069
|
+
"data.options",
|
|
4070
|
+
"data.schemas.input",
|
|
4071
|
+
"data.schemas.output",
|
|
4072
|
+
"nodes.*.data.initialInput",
|
|
4073
|
+
"nodes.*.data.timeout",
|
|
4074
|
+
"nodes.*.data.route",
|
|
4075
|
+
"nodes.*.data.schemas",
|
|
4076
|
+
"edges.*.data.matches",
|
|
4077
|
+
"edges.*.data.input"
|
|
4078
|
+
],
|
|
4079
|
+
analyzeCompatibility: analyzeXStateV5Compatibility
|
|
4080
|
+
};
|
|
4081
|
+
const XSTATE_V6_PROJECTION = {};
|
|
4082
|
+
/**
|
|
4083
|
+
* Derive LangGraph authoring kinds into its namespace. Canonical fields and
|
|
4084
|
+
* graph topology are never returned, so the adapter cannot rewrite them.
|
|
4085
|
+
*/
|
|
4086
|
+
const LANGGRAPH_PROJECTION = { adapt: (graph) => ({ data: {
|
|
4087
|
+
nodes: Object.fromEntries(graph.nodes.map((node) => [node.id, { kind: node.data.type === "final" ? "end" : node.data.kind === "agent" || node.data.kind === "task" || node.data.kind === "entrypoint" ? node.data.kind : "node" }])),
|
|
4088
|
+
edges: Object.fromEntries(graph.edges.map((edge) => {
|
|
4089
|
+
const source = graph.nodes.find((node) => node.id === edge.sourceId);
|
|
4090
|
+
return [edge.id, { kind: edge.data.kind === "call" ? "call" : edge.data.kind === "conditional" || edge.data.guard != null || source?.data.type === "choice" ? "conditional" : "edge" }];
|
|
4091
|
+
}))
|
|
4092
|
+
} }) };
|
|
4007
4093
|
/** Stately's semantic projection of the LangGraph 1.x APIs across runtimes. */
|
|
4008
4094
|
const LANGGRAPH_PROFILE = "@statelyai/langgraph@1.0.0";
|
|
4009
4095
|
const LANGGRAPH_PROFILE_MANIFEST = {
|
|
4010
4096
|
profile: LANGGRAPH_PROFILE,
|
|
4097
|
+
namespace: "@statelyai.langgraph",
|
|
4098
|
+
lineage: "@statelyai/langgraph",
|
|
4099
|
+
projection: LANGGRAPH_PROJECTION,
|
|
4100
|
+
selectable: false,
|
|
4011
4101
|
name: "LangGraph",
|
|
4012
4102
|
description: "LangGraph 1.x graph semantics for Python and JavaScript/TypeScript source.",
|
|
4013
4103
|
restrictFormatsToListed: true,
|
|
@@ -4188,6 +4278,9 @@ const XSTATE_AUTHORING = {
|
|
|
4188
4278
|
};
|
|
4189
4279
|
const XSTATE_PROFILE_MANIFESTS = [{
|
|
4190
4280
|
profile: XSTATE_V5_PROFILE,
|
|
4281
|
+
namespace: "@statelyai.xstate",
|
|
4282
|
+
lineage: "@statelyai/xstate",
|
|
4283
|
+
projection: XSTATE_V5_PROJECTION,
|
|
4191
4284
|
name: "XState v5",
|
|
4192
4285
|
formats: [...XSTATE_FORMATS],
|
|
4193
4286
|
authoring: XSTATE_AUTHORING,
|
|
@@ -4198,7 +4291,10 @@ const XSTATE_PROFILE_MANIFESTS = [{
|
|
|
4198
4291
|
}
|
|
4199
4292
|
}, {
|
|
4200
4293
|
profile: XSTATE_V6_PROFILE,
|
|
4201
|
-
|
|
4294
|
+
namespace: "@statelyai.xstate",
|
|
4295
|
+
lineage: "@statelyai/xstate",
|
|
4296
|
+
projection: XSTATE_V6_PROJECTION,
|
|
4297
|
+
name: "XState v6 alpha",
|
|
4202
4298
|
formats: [...XSTATE_FORMATS],
|
|
4203
4299
|
authoring: XSTATE_AUTHORING,
|
|
4204
4300
|
operations: {
|
|
@@ -4320,31 +4416,32 @@ function resolvedExpressionText(expression, bindings, resolving = /* @__PURE__ *
|
|
|
4320
4416
|
for (const replacement of replacements.sort((a, b) => b.start - a.start)) result = result.slice(0, replacement.start) + replacement.text + result.slice(replacement.end);
|
|
4321
4417
|
return result;
|
|
4322
4418
|
}
|
|
4323
|
-
function typeNodeToJsonSchema(node) {
|
|
4324
|
-
if (ts.isParenthesizedTypeNode(node)) return typeNodeToJsonSchema(node.type);
|
|
4419
|
+
function typeNodeToJsonSchema(node, bindings = /* @__PURE__ */ new Map(), resolving = /* @__PURE__ */ new Set()) {
|
|
4420
|
+
if (ts.isParenthesizedTypeNode(node)) return typeNodeToJsonSchema(node.type, bindings, resolving);
|
|
4325
4421
|
if (ts.isLiteralTypeNode(node)) {
|
|
4326
4422
|
const literal = node.literal;
|
|
4327
4423
|
if (ts.isStringLiteral(literal) || ts.isNumericLiteral(literal)) return { const: ts.isNumericLiteral(literal) ? Number(literal.text) : literal.text };
|
|
4328
4424
|
if (literal.kind === ts.SyntaxKind.TrueKeyword) return { const: true };
|
|
4329
4425
|
if (literal.kind === ts.SyntaxKind.FalseKeyword) return { const: false };
|
|
4426
|
+
if (literal.kind === ts.SyntaxKind.NullKeyword) return { type: "null" };
|
|
4330
4427
|
return null;
|
|
4331
4428
|
}
|
|
4332
4429
|
if (ts.isUnionTypeNode(node)) {
|
|
4333
|
-
const members = node.types.map(typeNodeToJsonSchema);
|
|
4430
|
+
const members = node.types.map((member) => typeNodeToJsonSchema(member, bindings, resolving));
|
|
4334
4431
|
if (members.some((member) => !member)) return null;
|
|
4335
4432
|
const constants = members.map((member) => member?.const);
|
|
4336
4433
|
if (constants.every((value) => value !== void 0)) return { enum: constants };
|
|
4337
4434
|
return { anyOf: members };
|
|
4338
4435
|
}
|
|
4339
4436
|
if (ts.isArrayTypeNode(node)) {
|
|
4340
|
-
const items = typeNodeToJsonSchema(node.elementType);
|
|
4437
|
+
const items = typeNodeToJsonSchema(node.elementType, bindings, resolving);
|
|
4341
4438
|
return items ? {
|
|
4342
4439
|
type: "array",
|
|
4343
4440
|
items
|
|
4344
4441
|
} : null;
|
|
4345
4442
|
}
|
|
4346
4443
|
if (ts.isTupleTypeNode(node)) {
|
|
4347
|
-
const items = node.elements.map((element) => typeNodeToJsonSchema(element));
|
|
4444
|
+
const items = node.elements.map((element) => typeNodeToJsonSchema(element, bindings, resolving));
|
|
4348
4445
|
if (items.some((item) => !item)) return null;
|
|
4349
4446
|
return {
|
|
4350
4447
|
type: "array",
|
|
@@ -4359,7 +4456,7 @@ function typeNodeToJsonSchema(node) {
|
|
|
4359
4456
|
for (const member of node.members) {
|
|
4360
4457
|
if (!ts.isPropertySignature(member) || !member.type || !member.name) return null;
|
|
4361
4458
|
const name = propName(member.name);
|
|
4362
|
-
const schema = typeNodeToJsonSchema(member.type);
|
|
4459
|
+
const schema = typeNodeToJsonSchema(member.type, bindings, resolving);
|
|
4363
4460
|
if (!name || !schema) return null;
|
|
4364
4461
|
properties[name] = schema;
|
|
4365
4462
|
if (!member.questionToken) required.push(name);
|
|
@@ -4372,21 +4469,77 @@ function typeNodeToJsonSchema(node) {
|
|
|
4372
4469
|
};
|
|
4373
4470
|
}
|
|
4374
4471
|
switch (node.kind) {
|
|
4472
|
+
case ts.SyntaxKind.VoidKeyword: return {
|
|
4473
|
+
type: "object",
|
|
4474
|
+
properties: {},
|
|
4475
|
+
required: []
|
|
4476
|
+
};
|
|
4375
4477
|
case ts.SyntaxKind.StringKeyword: return { type: "string" };
|
|
4376
4478
|
case ts.SyntaxKind.NumberKeyword: return { type: "number" };
|
|
4377
4479
|
case ts.SyntaxKind.BooleanKeyword: return { type: "boolean" };
|
|
4378
4480
|
case ts.SyntaxKind.NullKeyword: return { type: "null" };
|
|
4481
|
+
case ts.SyntaxKind.VoidKeyword: return {
|
|
4482
|
+
type: "object",
|
|
4483
|
+
properties: {},
|
|
4484
|
+
required: [],
|
|
4485
|
+
additionalProperties: false
|
|
4486
|
+
};
|
|
4379
4487
|
case ts.SyntaxKind.UnknownKeyword:
|
|
4380
4488
|
case ts.SyntaxKind.AnyKeyword: return {};
|
|
4381
|
-
default:
|
|
4489
|
+
default: break;
|
|
4490
|
+
}
|
|
4491
|
+
if (ts.isTypeReferenceNode(node) && ts.isIdentifier(node.typeName)) {
|
|
4492
|
+
const name = node.typeName.text;
|
|
4493
|
+
if (name === "Array" && node.typeArguments?.length === 1) {
|
|
4494
|
+
const items = typeNodeToJsonSchema(node.typeArguments[0], bindings, resolving);
|
|
4495
|
+
return items ? {
|
|
4496
|
+
type: "array",
|
|
4497
|
+
items
|
|
4498
|
+
} : null;
|
|
4499
|
+
}
|
|
4500
|
+
const binding = bindings.get(name);
|
|
4501
|
+
if (!binding || resolving.has(name)) return null;
|
|
4502
|
+
const nextResolving = new Set(resolving).add(name);
|
|
4503
|
+
if (ts.isTypeAliasDeclaration(binding)) return typeNodeToJsonSchema(binding.type, bindings, nextResolving);
|
|
4504
|
+
const properties = {};
|
|
4505
|
+
const required = /* @__PURE__ */ new Set();
|
|
4506
|
+
for (const heritageClause of binding.heritageClauses ?? []) {
|
|
4507
|
+
if (heritageClause.token !== ts.SyntaxKind.ExtendsKeyword) return null;
|
|
4508
|
+
for (const heritage of heritageClause.types) {
|
|
4509
|
+
if (!ts.isIdentifier(heritage.expression) || (heritage.typeArguments?.length ?? 0) > 0) return null;
|
|
4510
|
+
const baseName = heritage.expression.text;
|
|
4511
|
+
const baseBinding = bindings.get(baseName);
|
|
4512
|
+
if (!baseBinding || !ts.isInterfaceDeclaration(baseBinding)) return null;
|
|
4513
|
+
const baseSchema = typeNodeToJsonSchema(ts.factory.createTypeReferenceNode(heritage.expression, heritage.typeArguments), bindings, nextResolving);
|
|
4514
|
+
if (!baseSchema || baseSchema.type !== "object" || !baseSchema.properties) return null;
|
|
4515
|
+
Object.assign(properties, baseSchema.properties);
|
|
4516
|
+
for (const name of baseSchema.required ?? []) required.add(name);
|
|
4517
|
+
}
|
|
4518
|
+
}
|
|
4519
|
+
for (const member of binding.members) {
|
|
4520
|
+
if (!ts.isPropertySignature(member) || !member.type || !member.name) return null;
|
|
4521
|
+
const propertyName = propName(member.name);
|
|
4522
|
+
const schema = typeNodeToJsonSchema(member.type, bindings, nextResolving);
|
|
4523
|
+
if (!propertyName || !schema) return null;
|
|
4524
|
+
properties[propertyName] = schema;
|
|
4525
|
+
if (member.questionToken) required.delete(propertyName);
|
|
4526
|
+
else required.add(propertyName);
|
|
4527
|
+
}
|
|
4528
|
+
return {
|
|
4529
|
+
type: "object",
|
|
4530
|
+
properties,
|
|
4531
|
+
...required.size ? { required: [...required] } : void 0,
|
|
4532
|
+
additionalProperties: false
|
|
4533
|
+
};
|
|
4382
4534
|
}
|
|
4535
|
+
return null;
|
|
4383
4536
|
}
|
|
4384
|
-
function typesCallSchema(node) {
|
|
4537
|
+
function typesCallSchema(node, bindings) {
|
|
4385
4538
|
const value = unwrapExpression(node);
|
|
4386
4539
|
if (!ts.isCallExpression(value) || value.expression.getText() !== "types" || value.typeArguments?.length !== 1) return null;
|
|
4387
|
-
return typeNodeToJsonSchema(value.typeArguments[0]);
|
|
4540
|
+
return typeNodeToJsonSchema(value.typeArguments[0], bindings);
|
|
4388
4541
|
}
|
|
4389
|
-
function schemasObjectToValue(node) {
|
|
4542
|
+
function schemasObjectToValue(node, bindings) {
|
|
4390
4543
|
const value = unwrapExpression(node);
|
|
4391
4544
|
if (!ts.isObjectLiteralExpression(value)) return null;
|
|
4392
4545
|
const result = {};
|
|
@@ -4394,25 +4547,46 @@ function schemasObjectToValue(node) {
|
|
|
4394
4547
|
if (!ts.isPropertyAssignment(property)) continue;
|
|
4395
4548
|
const key = propName(property.name);
|
|
4396
4549
|
if (!key) continue;
|
|
4397
|
-
if (
|
|
4550
|
+
if ([
|
|
4551
|
+
"events",
|
|
4552
|
+
"internalEvents",
|
|
4553
|
+
"emitted",
|
|
4554
|
+
"children"
|
|
4555
|
+
].includes(key) && ts.isObjectLiteralExpression(property.initializer)) {
|
|
4398
4556
|
const events = {};
|
|
4399
4557
|
for (const eventProperty of property.initializer.properties) {
|
|
4400
4558
|
if (!ts.isPropertyAssignment(eventProperty)) continue;
|
|
4401
4559
|
const eventType = propName(eventProperty.name);
|
|
4402
|
-
const schema = typesCallSchema(eventProperty.initializer);
|
|
4560
|
+
const schema = typesCallSchema(eventProperty.initializer, bindings);
|
|
4403
4561
|
if (eventType && schema) events[eventType] = schema;
|
|
4404
4562
|
}
|
|
4405
|
-
result
|
|
4563
|
+
result[key] = events;
|
|
4406
4564
|
continue;
|
|
4407
4565
|
}
|
|
4408
|
-
|
|
4566
|
+
if (["actions", "guards"].includes(key) && ts.isObjectLiteralExpression(property.initializer)) {
|
|
4567
|
+
const implementations = {};
|
|
4568
|
+
for (const implementation of property.initializer.properties) {
|
|
4569
|
+
if (!ts.isPropertyAssignment(implementation)) continue;
|
|
4570
|
+
const name = propName(implementation.name);
|
|
4571
|
+
if (!name || !ts.isObjectLiteralExpression(implementation.initializer)) continue;
|
|
4572
|
+
const params = implementation.initializer.properties.find((candidate) => ts.isPropertyAssignment(candidate) && propName(candidate.name) === "params");
|
|
4573
|
+
const schema = params ? typesCallSchema(params.initializer, bindings) : null;
|
|
4574
|
+
implementations[name] = schema ? { params: schema } : {};
|
|
4575
|
+
}
|
|
4576
|
+
result[key] = implementations;
|
|
4577
|
+
continue;
|
|
4578
|
+
}
|
|
4579
|
+
const schema = typesCallSchema(property.initializer, bindings);
|
|
4409
4580
|
if (!schema) continue;
|
|
4410
4581
|
result[key] = key === "context" ? schema.properties ?? {} : schema;
|
|
4411
4582
|
}
|
|
4412
4583
|
return result;
|
|
4413
4584
|
}
|
|
4414
4585
|
function propertyContext(parent, key) {
|
|
4415
|
-
const inherited =
|
|
4586
|
+
const inherited = {
|
|
4587
|
+
...parent.imports ? { imports: parent.imports } : {},
|
|
4588
|
+
...parent.typeBindings ? { typeBindings: parent.typeBindings } : {}
|
|
4589
|
+
};
|
|
4416
4590
|
if (parent.statesMap) return {
|
|
4417
4591
|
...inherited,
|
|
4418
4592
|
v6: parent.v6
|
|
@@ -4422,12 +4596,17 @@ function propertyContext(parent, key) {
|
|
|
4422
4596
|
v6: parent.v6,
|
|
4423
4597
|
statesMap: true
|
|
4424
4598
|
};
|
|
4599
|
+
if (key === "schemas") return {
|
|
4600
|
+
...inherited,
|
|
4601
|
+
v6: parent.v6,
|
|
4602
|
+
schemasValue: true
|
|
4603
|
+
};
|
|
4425
4604
|
if (parent.machineValue && (key === "actors" || key === "actorSources")) return {
|
|
4426
4605
|
...inherited,
|
|
4427
4606
|
v6: parent.v6,
|
|
4428
4607
|
implementationMap: true
|
|
4429
4608
|
};
|
|
4430
|
-
if (parent.setupValue && (key === "actions" || key === "guards" || key === "actors" || key === "delays")) return {
|
|
4609
|
+
if (parent.setupValue && (key === "actions" || key === "guards" || key === "actors" || key === "actorSources" || key === "delays")) return {
|
|
4431
4610
|
...inherited,
|
|
4432
4611
|
v6: parent.v6,
|
|
4433
4612
|
implementationMap: true
|
|
@@ -4685,6 +4864,10 @@ function mergeBranchPrefix(prefix, branch) {
|
|
|
4685
4864
|
return {
|
|
4686
4865
|
conds: [...prefix.conds, ...branch.conds],
|
|
4687
4866
|
actions: [...prefix.actions, ...branch.actions],
|
|
4867
|
+
...prefix.contextUpdates || branch.contextUpdates ? { contextUpdates: {
|
|
4868
|
+
...prefix.contextUpdates,
|
|
4869
|
+
...branch.contextUpdates
|
|
4870
|
+
} } : {},
|
|
4688
4871
|
result: branch.result,
|
|
4689
4872
|
unknown: prefix.unknown || branch.unknown
|
|
4690
4873
|
};
|
|
@@ -4765,6 +4948,31 @@ function expressionStatementAction(statement, enqName, bindings) {
|
|
|
4765
4948
|
}
|
|
4766
4949
|
};
|
|
4767
4950
|
}
|
|
4951
|
+
/**
|
|
4952
|
+
* The v6 exporter uses a local accumulator when a transition has multiple
|
|
4953
|
+
* context updates or queued effects. Recover the partial context update from
|
|
4954
|
+
* that canonical form so import -> graph -> export remains targetable.
|
|
4955
|
+
*/
|
|
4956
|
+
function generatedContextUpdate(statement, bindings) {
|
|
4957
|
+
const expression = unwrapExpression(statement.expression);
|
|
4958
|
+
if (!ts.isBinaryExpression(expression) || expression.operatorToken.kind !== ts.SyntaxKind.EqualsToken || !ts.isIdentifier(expression.left) || expression.left.text !== "nextContext") return;
|
|
4959
|
+
const right = unwrapExpression(expression.right);
|
|
4960
|
+
if (!ts.isObjectLiteralExpression(right)) return null;
|
|
4961
|
+
const updates = {};
|
|
4962
|
+
for (const property of right.properties) {
|
|
4963
|
+
if (!ts.isSpreadAssignment(property)) return null;
|
|
4964
|
+
const spread = unwrapExpression(property.expression);
|
|
4965
|
+
if (ts.isIdentifier(spread) && spread.text === "nextContext") continue;
|
|
4966
|
+
if (!ts.isObjectLiteralExpression(spread)) return null;
|
|
4967
|
+
const value = objectLiteralToValue(spread, bindings, {
|
|
4968
|
+
v6: true,
|
|
4969
|
+
assignmentMap: true
|
|
4970
|
+
}, 0);
|
|
4971
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) return null;
|
|
4972
|
+
Object.assign(updates, value);
|
|
4973
|
+
}
|
|
4974
|
+
return updates;
|
|
4975
|
+
}
|
|
4768
4976
|
function statementBranches(statements, bindings, enqName, prefixes = [{
|
|
4769
4977
|
conds: [],
|
|
4770
4978
|
actions: []
|
|
@@ -4780,6 +4988,12 @@ function statementBranches(statements, bindings, enqName, prefixes = [{
|
|
|
4780
4988
|
nextOpen.push(prefix);
|
|
4781
4989
|
continue;
|
|
4782
4990
|
}
|
|
4991
|
+
if (ts.isBlock(statement)) {
|
|
4992
|
+
const nestedBranches = statementBranches(statement.statements, scopedBindings, enqName, [prefix]);
|
|
4993
|
+
for (const branch of nestedBranches) if ("result" in branch) done.push(branch);
|
|
4994
|
+
else nextOpen.push(branch);
|
|
4995
|
+
continue;
|
|
4996
|
+
}
|
|
4783
4997
|
if (ts.isReturnStatement(statement)) {
|
|
4784
4998
|
if (!statement.expression) {
|
|
4785
4999
|
done.push({
|
|
@@ -4792,6 +5006,21 @@ function statementBranches(statements, bindings, enqName, prefixes = [{
|
|
|
4792
5006
|
continue;
|
|
4793
5007
|
}
|
|
4794
5008
|
if (ts.isExpressionStatement(statement)) {
|
|
5009
|
+
const contextUpdate = generatedContextUpdate(statement, scopedBindings);
|
|
5010
|
+
if (contextUpdate !== void 0) {
|
|
5011
|
+
if (contextUpdate === null) nextOpen.push({
|
|
5012
|
+
...prefix,
|
|
5013
|
+
unknown: true
|
|
5014
|
+
});
|
|
5015
|
+
else nextOpen.push({
|
|
5016
|
+
...prefix,
|
|
5017
|
+
contextUpdates: {
|
|
5018
|
+
...prefix.contextUpdates,
|
|
5019
|
+
...contextUpdate
|
|
5020
|
+
}
|
|
5021
|
+
});
|
|
5022
|
+
continue;
|
|
5023
|
+
}
|
|
4795
5024
|
const action = expressionStatementAction(statement, enqName, scopedBindings);
|
|
4796
5025
|
if (action) {
|
|
4797
5026
|
nextOpen.push({
|
|
@@ -4895,15 +5124,34 @@ function normalizeFunctionTransition(fn, bindings, depth) {
|
|
|
4895
5124
|
if (branches.some((branch) => branch.unknown)) return fallbackFunctionTransition(fn);
|
|
4896
5125
|
const contextIdentity = transitionContextIdentity(fn);
|
|
4897
5126
|
const transitions = branches.map((branch) => {
|
|
4898
|
-
|
|
5127
|
+
let result = branch.result;
|
|
5128
|
+
if (branch.contextUpdates && result && typeof result === "object" && !Array.isArray(result)) {
|
|
5129
|
+
const record = result;
|
|
5130
|
+
const context = record.context;
|
|
5131
|
+
const contextRecord = context && typeof context === "object" && !Array.isArray(context) ? context : null;
|
|
5132
|
+
if (contextRecord?.["@type"] === "code" && contextRecord.expr === "nextContext") result = {
|
|
5133
|
+
...record,
|
|
5134
|
+
context: branch.contextUpdates
|
|
5135
|
+
};
|
|
5136
|
+
}
|
|
5137
|
+
const transition = transitionFromValue(result, branch.actions);
|
|
4899
5138
|
if (!transition) return null;
|
|
5139
|
+
const matches = matchesFromConditions(branch.conds);
|
|
4900
5140
|
if (typeof transition === "string") {
|
|
5141
|
+
if (matches) return {
|
|
5142
|
+
target: transition,
|
|
5143
|
+
matches
|
|
5144
|
+
};
|
|
4901
5145
|
const guard = guardFromConditions(branch.conds, guardParams(fn));
|
|
4902
5146
|
return guard ? {
|
|
4903
5147
|
target: transition,
|
|
4904
5148
|
guard
|
|
4905
5149
|
} : transition;
|
|
4906
5150
|
}
|
|
5151
|
+
if (matches) return omitIdentityTransitionContext({
|
|
5152
|
+
...transition,
|
|
5153
|
+
matches
|
|
5154
|
+
}, contextIdentity);
|
|
4907
5155
|
const guard = guardFromConditions(branch.conds, guardParams(fn));
|
|
4908
5156
|
return omitIdentityTransitionContext(guard ? {
|
|
4909
5157
|
...transition,
|
|
@@ -4914,6 +5162,26 @@ function normalizeFunctionTransition(fn, bindings, depth) {
|
|
|
4914
5162
|
if (transitions.length > 1) return transitions;
|
|
4915
5163
|
return fallbackFunctionTransition(fn);
|
|
4916
5164
|
}
|
|
5165
|
+
function matchesFromConditions(conditions) {
|
|
5166
|
+
const positives = conditions.filter((condition) => !condition.negated);
|
|
5167
|
+
if (positives.length !== 1) return null;
|
|
5168
|
+
const match = positives[0].text.match(/^Object\.is\(event\[['"]([^'"]+)['"]\],\s*(.+)\)$/);
|
|
5169
|
+
if (!match) return null;
|
|
5170
|
+
const [, key, rawValue] = match;
|
|
5171
|
+
if (!key || !rawValue) return null;
|
|
5172
|
+
for (const condition of conditions) {
|
|
5173
|
+
if (!condition.negated) continue;
|
|
5174
|
+
const negative = condition.text.match(/^Object\.is\(event\[['"]([^'"]+)['"]\],\s*(.+)\)$/);
|
|
5175
|
+
if (!negative || negative[1] !== key) return null;
|
|
5176
|
+
}
|
|
5177
|
+
const value = rawValue.trim();
|
|
5178
|
+
if (value.startsWith("'") && value.endsWith("'") || value.startsWith("\"") && value.endsWith("\"")) return { [key]: value.slice(1, -1) };
|
|
5179
|
+
if (value === "true") return { [key]: true };
|
|
5180
|
+
if (value === "false") return { [key]: false };
|
|
5181
|
+
if (value === "null") return { [key]: null };
|
|
5182
|
+
const number = Number(value);
|
|
5183
|
+
return Number.isNaN(number) ? null : { [key]: number };
|
|
5184
|
+
}
|
|
4917
5185
|
/**
|
|
4918
5186
|
* XState v5 has no `choose()`, so `xstate.choose` is exported as the canonical
|
|
4919
5187
|
* `enqueueActions(({ check, enqueue }) => { if (check(g)) { enqueue(a); } ... })`
|
|
@@ -4996,15 +5264,6 @@ function inlineAction(fn) {
|
|
|
4996
5264
|
}
|
|
4997
5265
|
};
|
|
4998
5266
|
}
|
|
4999
|
-
function enqueueAction(fn) {
|
|
5000
|
-
return {
|
|
5001
|
-
type: "xstate.enqueue",
|
|
5002
|
-
params: {
|
|
5003
|
-
code: fn.getText(),
|
|
5004
|
-
lang: "ts"
|
|
5005
|
-
}
|
|
5006
|
-
};
|
|
5007
|
-
}
|
|
5008
5267
|
function inlineCodeExpression(expr, imports) {
|
|
5009
5268
|
return {
|
|
5010
5269
|
"@type": "code",
|
|
@@ -5037,8 +5296,8 @@ function codeImportsForExpression(expression, imports) {
|
|
|
5037
5296
|
* `entry: ({ actions }, enq) => { enq(actions['NAME'], params); ... }` is the
|
|
5038
5297
|
* shape the exporter writes for a plain list of *named* actions, so it is
|
|
5039
5298
|
* decomposed back into those actions instead of surviving as one opaque
|
|
5040
|
-
*
|
|
5041
|
-
*
|
|
5299
|
+
* inline code action. Direct `enq.raise(...)` / `enq(() => ...)` bodies are
|
|
5300
|
+
* authored code and remain one inline action.
|
|
5042
5301
|
*/
|
|
5043
5302
|
function enqueuedNamedActions(fn, bindings) {
|
|
5044
5303
|
const body = fn.body;
|
|
@@ -5061,7 +5320,7 @@ function enqueuedNamedActions(fn, bindings) {
|
|
|
5061
5320
|
function normalizeFunctionAction(fn, bindings) {
|
|
5062
5321
|
const actions = enqueuedNamedActions(fn, bindings);
|
|
5063
5322
|
if (actions) return actions.length === 1 ? actions[0] : actions;
|
|
5064
|
-
return
|
|
5323
|
+
return inlineAction(fn);
|
|
5065
5324
|
}
|
|
5066
5325
|
function objectLiteralToValue(node, bindings, context, depth, overrides = /* @__PURE__ */ new Map()) {
|
|
5067
5326
|
const result = {};
|
|
@@ -5079,7 +5338,7 @@ function objectLiteralToValue(node, bindings, context, depth, overrides = /* @__
|
|
|
5079
5338
|
continue;
|
|
5080
5339
|
}
|
|
5081
5340
|
if (context.v6 && key === "schemas" && ts.isPropertyAssignment(property)) {
|
|
5082
|
-
const schemas = schemasObjectToValue(property.initializer);
|
|
5341
|
+
const schemas = schemasObjectToValue(property.initializer, context.typeBindings ?? /* @__PURE__ */ new Map());
|
|
5083
5342
|
if (schemas) {
|
|
5084
5343
|
result[key] = schemas;
|
|
5085
5344
|
continue;
|
|
@@ -5132,6 +5391,14 @@ function expressionToValue(expression, bindings, context = {}, depth = 0) {
|
|
|
5132
5391
|
}
|
|
5133
5392
|
return inlineCodeExpression(node.getText(), codeImportsForExpression(node.getText(), context.imports));
|
|
5134
5393
|
}
|
|
5394
|
+
if (context.schemasValue) {
|
|
5395
|
+
if (ts.isIdentifier(node)) {
|
|
5396
|
+
const binding = bindings.get(node.text);
|
|
5397
|
+
if (binding && !ts.isFunctionDeclaration(binding)) return expressionToValue(binding, bindings, context, depth + 1);
|
|
5398
|
+
}
|
|
5399
|
+
const schemas = schemasObjectToValue(node, context.typeBindings ?? /* @__PURE__ */ new Map());
|
|
5400
|
+
if (schemas) return schemas;
|
|
5401
|
+
}
|
|
5135
5402
|
if (context.machineContextValue && (ts.isArrowFunction(node) || ts.isFunctionExpression(node))) return inlineCodeExpression(node.getText());
|
|
5136
5403
|
if (context.targetValue) {
|
|
5137
5404
|
if (ts.isStringLiteral(node) || ts.isNoSubstitutionTemplateLiteral(node)) return node.text;
|
|
@@ -5260,6 +5527,12 @@ function collectBindings(file) {
|
|
|
5260
5527
|
}
|
|
5261
5528
|
return bindings;
|
|
5262
5529
|
}
|
|
5530
|
+
function collectSchemaTypeBindings(file) {
|
|
5531
|
+
const bindings = /* @__PURE__ */ new Map();
|
|
5532
|
+
for (const statement of file.statements) if (ts.isTypeAliasDeclaration(statement) && statement.name) bindings.set(statement.name.text, statement);
|
|
5533
|
+
else if (ts.isInterfaceDeclaration(statement) && statement.name) bindings.set(statement.name.text, statement);
|
|
5534
|
+
return bindings;
|
|
5535
|
+
}
|
|
5263
5536
|
function collectSourceImports(file) {
|
|
5264
5537
|
const imports = /* @__PURE__ */ new Map();
|
|
5265
5538
|
for (const statement of file.statements) {
|
|
@@ -5362,10 +5635,15 @@ function hasV6Syntax(source) {
|
|
|
5362
5635
|
const binding = bindings.get(node.text);
|
|
5363
5636
|
return binding ? containsFunctionTransitionMap(binding, seen) : false;
|
|
5364
5637
|
}
|
|
5365
|
-
if (
|
|
5638
|
+
if (ts.isArrayLiteralExpression(node)) return node.elements.some((element) => ts.isExpression(element) && containsFunctionTransitionMap(element, seen));
|
|
5639
|
+
if (!ts.isObjectLiteralExpression(node)) return containsFunction(node);
|
|
5366
5640
|
return node.properties.some((property) => {
|
|
5367
5641
|
if (ts.isMethodDeclaration(property)) return true;
|
|
5368
|
-
if (ts.isPropertyAssignment(property))
|
|
5642
|
+
if (ts.isPropertyAssignment(property)) {
|
|
5643
|
+
const key = propName(property.name);
|
|
5644
|
+
if (key === "guard" || key === "cond" || key === "actions") return false;
|
|
5645
|
+
return containsFunctionTransitionMap(property.initializer, seen);
|
|
5646
|
+
}
|
|
5369
5647
|
if (ts.isShorthandPropertyAssignment(property)) return containsFunction(property.name);
|
|
5370
5648
|
if (ts.isSpreadAssignment(property)) return containsFunctionTransitionMap(property.expression, seen);
|
|
5371
5649
|
return false;
|
|
@@ -5431,11 +5709,6 @@ function hasV6Syntax(source) {
|
|
|
5431
5709
|
function detectXStateSourceProfile(source) {
|
|
5432
5710
|
return hasV6Syntax(source) ? "xstate-v6-alpha" : "xstate-v5";
|
|
5433
5711
|
}
|
|
5434
|
-
function xstateSourceToConfig(source, options = {}) {
|
|
5435
|
-
const [config] = extractXStateMachineConfigs(source, options);
|
|
5436
|
-
if (!config) throw new Error("No createMachine(...), createFSM(...), or setup factory call found.");
|
|
5437
|
-
return config;
|
|
5438
|
-
}
|
|
5439
5712
|
/**
|
|
5440
5713
|
* Extract every XState machine config from source without executing code.
|
|
5441
5714
|
* XState 5/6 syntax is inferred structurally unless a profile is supplied.
|
|
@@ -5444,6 +5717,7 @@ function extractXStateMachineConfigEntries(source, options = {}) {
|
|
|
5444
5717
|
const file = sourceFile(source);
|
|
5445
5718
|
const bindings = collectBindings(file);
|
|
5446
5719
|
const imports = collectSourceImports(file);
|
|
5720
|
+
const typeBindings = collectSchemaTypeBindings(file);
|
|
5447
5721
|
const found = [];
|
|
5448
5722
|
let machineIndex = 0;
|
|
5449
5723
|
const profile = options.profile === "auto" || !options.profile ? detectXStateSourceProfile(source) : options.profile;
|
|
@@ -5525,14 +5799,16 @@ function extractXStateMachineConfigEntries(source, options = {}) {
|
|
|
5525
5799
|
const value = expressionToValue(arg, bindings, {
|
|
5526
5800
|
v6: profile === "xstate-v6-alpha",
|
|
5527
5801
|
machineValue: true,
|
|
5528
|
-
imports
|
|
5802
|
+
imports,
|
|
5803
|
+
typeBindings
|
|
5529
5804
|
});
|
|
5530
5805
|
if (value && typeof value === "object" && !Array.isArray(value)) {
|
|
5531
5806
|
const { states: setupStates, ...setupWithoutStates } = setupConfigExpressionsForCreateMachine(node, bindings).reduce((merged, setupArg) => {
|
|
5532
5807
|
const setupValue = expressionToValue(setupArg, bindings, {
|
|
5533
5808
|
v6: profile === "xstate-v6-alpha",
|
|
5534
5809
|
setupValue: true,
|
|
5535
|
-
imports
|
|
5810
|
+
imports,
|
|
5811
|
+
typeBindings
|
|
5536
5812
|
});
|
|
5537
5813
|
if (!isRecordValue(setupValue)) return merged;
|
|
5538
5814
|
return mergeSetupRecords(merged, setupValue);
|
|
@@ -5551,9 +5827,6 @@ function extractXStateMachineConfigEntries(source, options = {}) {
|
|
|
5551
5827
|
visit(file);
|
|
5552
5828
|
return found;
|
|
5553
5829
|
}
|
|
5554
|
-
function extractXStateMachineConfigs(source, options = {}) {
|
|
5555
|
-
return extractXStateMachineConfigEntries(source, options).map(({ config }) => config);
|
|
5556
|
-
}
|
|
5557
5830
|
function jsonSchemaToTSType(schema) {
|
|
5558
5831
|
if (!schema) return "unknown";
|
|
5559
5832
|
if (schema.enum) return schema.enum.map((v) => typeof v === "string" ? `'${v}'` : String(v)).join(" | ");
|
|
@@ -5674,11 +5947,12 @@ function eventSchemaToZod(schema) {
|
|
|
5674
5947
|
function objectToZod(schema) {
|
|
5675
5948
|
const properties = schema.properties ?? {};
|
|
5676
5949
|
const required = new Set(Array.isArray(schema.required) ? schema.required : []);
|
|
5677
|
-
|
|
5950
|
+
const shape = Object.fromEntries(Object.entries(properties).map(([key, definition]) => {
|
|
5678
5951
|
return [key, raw(`${definitionToZod(definition)}${isRequiredProperty(key, definition, required) ? "" : ".optional()"}`)];
|
|
5679
|
-
}))
|
|
5952
|
+
}));
|
|
5953
|
+
let result = `z.object(${serializeJS(shape)})`;
|
|
5680
5954
|
if (schema.additionalProperties === false) result += ".strict()";
|
|
5681
|
-
else if (schema.additionalProperties === true || schema.additionalProperties === void 0) result
|
|
5955
|
+
else if (schema.additionalProperties === true || schema.additionalProperties === void 0) result = `z.looseObject(${serializeJS(shape)})`;
|
|
5682
5956
|
else if (schema.additionalProperties) result += `.catchall(${jsonSchemaToZod(schema.additionalProperties)})`;
|
|
5683
5957
|
return result;
|
|
5684
5958
|
}
|
|
@@ -5761,7 +6035,7 @@ function graphToXStateTS(graph, options = {}) {
|
|
|
5761
6035
|
const schemas = graph.data.schemas;
|
|
5762
6036
|
const impls = filterInlineImplementations$1(graph.data.implementations);
|
|
5763
6037
|
const supportsTypeSyntax = targetLanguage === "typescript";
|
|
5764
|
-
const hasSchemas = !!(schemas && (schemas.context || schemas.events || schemas.input || schemas.output));
|
|
6038
|
+
const hasSchemas = !!(schemas && (schemas.context || schemas.events || schemas.internalEvents || schemas.emitted || schemas.actions || schemas.guards || schemas.children || schemas.input || schemas.output || schemas.tags || schemas.meta));
|
|
5765
6039
|
const hasStateSchemas = graph.nodes.some((node) => node.data.schemas);
|
|
5766
6040
|
const hasActions = !!impls?.actions.length;
|
|
5767
6041
|
const hasGuards = !!impls?.guards.length;
|
|
@@ -5784,7 +6058,7 @@ function graphToXStateTS(graph, options = {}) {
|
|
|
5784
6058
|
usesTypes: xstateVersion === 6 && supportsTypeSyntax && (hasSchemas || hasStateSchemas) && xstateV6SchemaFormat === "types",
|
|
5785
6059
|
usesZod: xstateVersion === 6 && (hasSchemas || hasStateSchemas) && xstateV6SchemaFormat === "zod"
|
|
5786
6060
|
});
|
|
5787
|
-
const machineConfig = xstateVersion === 6 ?
|
|
6061
|
+
const machineConfig = xstateVersion === 6 ? toXStateV6MachineConfig(graphToMachineConfig(graph, {
|
|
5788
6062
|
...configOptions,
|
|
5789
6063
|
keepChooseStructured: true
|
|
5790
6064
|
})) : toV5MachineConfig(graphToMachineConfig(graph, configOptions));
|
|
@@ -5916,7 +6190,7 @@ function toV5MachineConfig(machineConfig) {
|
|
|
5916
6190
|
return wasArray ? mapped : mapped[0];
|
|
5917
6191
|
});
|
|
5918
6192
|
}
|
|
5919
|
-
function
|
|
6193
|
+
function toXStateV6MachineConfig(machineConfig) {
|
|
5920
6194
|
return mapV6MachineConfig(machineConfig);
|
|
5921
6195
|
}
|
|
5922
6196
|
function mapV6MachineConfig(value, context = {}) {
|
|
@@ -5929,6 +6203,10 @@ function mapV6MachineConfig(value, context = {}) {
|
|
|
5929
6203
|
result[key] = mapV6StatesMap(item);
|
|
5930
6204
|
continue;
|
|
5931
6205
|
}
|
|
6206
|
+
if (key === "choice") {
|
|
6207
|
+
result[key] = buildV6TransitionFunction(Array.isArray(item) ? item : [item]) ?? mapV6MachineConfig(item, { transitionValue: true });
|
|
6208
|
+
continue;
|
|
6209
|
+
}
|
|
5932
6210
|
if (key === "entry" || key === "exit" || key === "actions") {
|
|
5933
6211
|
result[key] = toV6ActionField(Array.isArray(item) ? item : item === void 0 ? [] : [item]);
|
|
5934
6212
|
continue;
|
|
@@ -5964,18 +6242,20 @@ function toV6TransitionValue(value) {
|
|
|
5964
6242
|
const transition = value;
|
|
5965
6243
|
if (transition.matches !== void 0) return buildV6TransitionFunction([transition]) ?? mapV6MachineConfig(transition);
|
|
5966
6244
|
if (transition.guard) return buildV6TransitionFunction([transition]) ?? mapV6MachineConfig(transition);
|
|
5967
|
-
if (transition.description || transition.input !== void 0) return mapV6MachineConfig(transition);
|
|
6245
|
+
if (transition.description || transition.input !== void 0 && !containsInlineExpression(transition.input)) return mapV6MachineConfig(transition);
|
|
5968
6246
|
const target = transition.target;
|
|
5969
6247
|
const context = transition.context;
|
|
5970
6248
|
const actionsValue = transition.actions;
|
|
5971
6249
|
const actions = Array.isArray(actionsValue) ? actionsValue : actionsValue === void 0 ? [] : [actionsValue];
|
|
5972
|
-
if (actions.length === 0 &&
|
|
5973
|
-
if (actions.length === 0 && target === void 0 &&
|
|
6250
|
+
if (actions.length === 0 && !containsInlineExpression(transition) && !containsTemplateExpression(transition)) return mapV6MachineConfig(transition);
|
|
6251
|
+
if (actions.length === 0 && typeof target === "string" && context === void 0 && transition.input === void 0 && !transition.reenter && !transition.meta) return { target };
|
|
6252
|
+
if (actions.length === 0 && target === void 0 && context === void 0 && transition.input === void 0) return mapV6MachineConfig(transition);
|
|
5974
6253
|
return buildV6ActionFunction(actions, {
|
|
5975
|
-
target: typeof target === "string" ? target : void 0,
|
|
6254
|
+
target: typeof target === "string" || Array.isArray(target) && target.every((item) => typeof item === "string") ? target : void 0,
|
|
5976
6255
|
reenter: transition.reenter === true,
|
|
5977
6256
|
meta: transition.meta,
|
|
5978
|
-
context
|
|
6257
|
+
context,
|
|
6258
|
+
input: transition.input
|
|
5979
6259
|
}) ?? mapV6MachineConfig(transition);
|
|
5980
6260
|
}
|
|
5981
6261
|
function guardCondition(value) {
|
|
@@ -5998,10 +6278,14 @@ function guardCondition(value) {
|
|
|
5998
6278
|
if (arrow < 0) return null;
|
|
5999
6279
|
const params = expression.slice(0, arrow).trim();
|
|
6000
6280
|
const body = expression.slice(arrow + 2).trim();
|
|
6001
|
-
|
|
6281
|
+
const callCondition = `(${expression})({ context, event, input, output, actions, guards, children, self, system })`;
|
|
6282
|
+
if (body.startsWith("{")) return {
|
|
6283
|
+
condition: callCondition,
|
|
6284
|
+
callCondition
|
|
6285
|
+
};
|
|
6002
6286
|
return {
|
|
6003
6287
|
condition: body,
|
|
6004
|
-
callCondition
|
|
6288
|
+
callCondition,
|
|
6005
6289
|
firstParam: params.startsWith("(") && params.endsWith(")") ? params.slice(1, -1).trim() : params
|
|
6006
6290
|
};
|
|
6007
6291
|
}
|
|
@@ -6029,7 +6313,8 @@ const V6_ARG_BINDINGS = [
|
|
|
6029
6313
|
];
|
|
6030
6314
|
const V6_IDENTIFIER = /^[A-Za-z_$][A-Za-z0-9_$]*$/;
|
|
6031
6315
|
function inferV6ArgBindings(code) {
|
|
6032
|
-
|
|
6316
|
+
const withoutPropertyKeys = code.replace(/\b(context|event|input|output|actions|guards|children|self|system)\s*:/g, "");
|
|
6317
|
+
return V6_ARG_BINDINGS.filter((name) => new RegExp(`\\b${name}\\b`).test(withoutPropertyKeys));
|
|
6033
6318
|
}
|
|
6034
6319
|
/** Splits a destructuring pattern body on its top-level commas. */
|
|
6035
6320
|
function splitV6PatternEntries(body) {
|
|
@@ -6106,11 +6391,15 @@ function mergeV6FirstParam(authoredFirstParam, inferred) {
|
|
|
6106
6391
|
};
|
|
6107
6392
|
}
|
|
6108
6393
|
function buildV6TransitionFunction(transitions) {
|
|
6394
|
+
const transitionObjects = transitions.every((item) => Boolean(item) && typeof item === "object" && !Array.isArray(item)) ? transitions : void 0;
|
|
6395
|
+
if (!transitionObjects?.length) return;
|
|
6396
|
+
const descriptions = transitionObjects.map((transition) => typeof transition.description === "string" ? transition.description : void 0);
|
|
6397
|
+
const hasBranchDescriptions = transitionObjects.some((transition) => Object.prototype.hasOwnProperty.call(transition.meta ?? {}, XSTATE_V6_BRANCH_DESCRIPTION_META)) || descriptions.some((description) => description !== descriptions[0]);
|
|
6109
6398
|
const branches = [];
|
|
6110
6399
|
let authoredFirstParam;
|
|
6111
|
-
|
|
6112
|
-
|
|
6113
|
-
const
|
|
6400
|
+
const commonDescription = descriptions[0];
|
|
6401
|
+
for (const transition of transitionObjects) {
|
|
6402
|
+
const description = typeof transition.description === "string" ? transition.description : void 0;
|
|
6114
6403
|
const match = transition.matches === void 0 ? void 0 : matchesCondition(transition.matches);
|
|
6115
6404
|
if (match === null) return;
|
|
6116
6405
|
const guard = guardCondition(transition.guard);
|
|
@@ -6124,9 +6413,12 @@ function buildV6TransitionFunction(transitions) {
|
|
|
6124
6413
|
if (effects.some((effect) => !effect)) return;
|
|
6125
6414
|
const rendered = renderV6Effects(effects.filter((effect) => Boolean(effect)), transition.context === void 0 ? void 0 : serializeJS(unwrapTemplateExpressions(transition.context)));
|
|
6126
6415
|
const effectiveReturnValue = buildV6TransitionReturnValue({
|
|
6127
|
-
target: typeof transition.target === "string" ? transition.target : void 0,
|
|
6416
|
+
target: typeof transition.target === "string" || Array.isArray(transition.target) && transition.target.every((target) => typeof target === "string") ? transition.target : void 0,
|
|
6128
6417
|
reenter: transition.reenter === true,
|
|
6129
|
-
meta:
|
|
6418
|
+
meta: hasBranchDescriptions ? {
|
|
6419
|
+
...transition.meta ?? {},
|
|
6420
|
+
[XSTATE_V6_BRANCH_DESCRIPTION_META]: description ?? null
|
|
6421
|
+
} : transition.meta,
|
|
6130
6422
|
input: transition.input
|
|
6131
6423
|
}, rendered.contextValue) ?? "{}";
|
|
6132
6424
|
const body = [...rendered.statements.map(formatV6Statement), `return ${effectiveReturnValue};`];
|
|
@@ -6143,22 +6435,25 @@ function buildV6TransitionFunction(transitions) {
|
|
|
6143
6435
|
let renderedBranches = branches;
|
|
6144
6436
|
let merged = mergeV6FirstParam(authoredFirstParam, inferV6ArgBindings(generated));
|
|
6145
6437
|
if (!merged) {
|
|
6146
|
-
if (branches.some((branch) => !branch.callCondition)) return;
|
|
6147
6438
|
renderedBranches = branches.map((branch) => ({
|
|
6148
6439
|
...branch,
|
|
6149
|
-
condition: branch.callCondition
|
|
6440
|
+
condition: branch.callCondition ?? branch.condition
|
|
6150
6441
|
}));
|
|
6151
6442
|
merged = mergeV6FirstParam(void 0, inferV6ArgBindings(`${renderedBranches.map((branch) => branch.condition).join("\n")}\n${generated}`));
|
|
6152
6443
|
}
|
|
6153
6444
|
if (!merged) return;
|
|
6154
|
-
const lines = merged.prelude.map((statement) =>
|
|
6155
|
-
for (const branch of renderedBranches) if (branch.condition === "true") lines.push(...branch.body.map((line) =>
|
|
6445
|
+
const lines = merged.prelude.map((statement) => indentV6Code(statement, 2));
|
|
6446
|
+
for (const branch of renderedBranches) if (branch.condition === "true") lines.push(...branch.body.map((line) => indentV6Code(line, 2)));
|
|
6156
6447
|
else {
|
|
6157
|
-
lines.push(`
|
|
6158
|
-
lines.push(...branch.body.map((line) =>
|
|
6448
|
+
lines.push(indentV6Code(`if (${branch.condition}) {`, 2));
|
|
6449
|
+
lines.push(...branch.body.map((line) => indentV6Code(line, 4)));
|
|
6159
6450
|
lines.push(" }");
|
|
6160
6451
|
}
|
|
6161
|
-
|
|
6452
|
+
const transitionFunction = raw(`(${merged.firstParam}, enq) => {\n${lines.join("\n")}\n}`);
|
|
6453
|
+
return commonDescription === void 0 || hasBranchDescriptions ? transitionFunction : {
|
|
6454
|
+
description: commonDescription,
|
|
6455
|
+
to: transitionFunction
|
|
6456
|
+
};
|
|
6162
6457
|
}
|
|
6163
6458
|
function toV6ActionField(actions) {
|
|
6164
6459
|
if (actions.length === 1) {
|
|
@@ -6177,7 +6472,11 @@ function buildV6ActionFunction(actions, transition) {
|
|
|
6177
6472
|
if (transition) returnValue = buildV6TransitionReturnValue(transition, rendered.contextValue);
|
|
6178
6473
|
if (statements.length === 0 && !returnValue) return void 0;
|
|
6179
6474
|
const bindings = inferV6ArgBindings([...statements, returnValue ?? ""].join("\n"));
|
|
6180
|
-
return raw(`(${bindings.length ? `{ ${bindings.join(", ")} }` : "_"}, enq) => {\n${[...statements.map((statement) =>
|
|
6475
|
+
return raw(`(${bindings.length ? `{ ${bindings.join(", ")} }` : "_"}, enq) => {\n${[...statements.map((statement) => indentV6Code(formatV6Statement(statement), 2)), ...returnValue ? [indentV6Code(`return ${returnValue};`, 2)] : []].join("\n")}\n}`);
|
|
6476
|
+
}
|
|
6477
|
+
function indentV6Code(code, spaces) {
|
|
6478
|
+
const indent = " ".repeat(spaces);
|
|
6479
|
+
return code.split("\n").map((line) => line ? `${indent}${line}` : line).join("\n");
|
|
6181
6480
|
}
|
|
6182
6481
|
function formatV6Statement(statement) {
|
|
6183
6482
|
const trimmed = statement.trim();
|
|
@@ -6188,7 +6487,7 @@ function renderV6Effects(effects, finalContext) {
|
|
|
6188
6487
|
const statements = ["let nextContext = context"];
|
|
6189
6488
|
const inCurrentContext = (body) => {
|
|
6190
6489
|
if (body.length === 0) return;
|
|
6191
|
-
statements.push("{", " const context = nextContext", ...body.map((line) =>
|
|
6490
|
+
statements.push("{", " const context = nextContext", ...body.map((line) => indentV6Code(line, 2)), "}");
|
|
6192
6491
|
};
|
|
6193
6492
|
for (const effect of effects) {
|
|
6194
6493
|
inCurrentContext(effect.statements ?? []);
|
|
@@ -6209,8 +6508,16 @@ function unwrapTemplateExpressions(value) {
|
|
|
6209
6508
|
if (!value || typeof value !== "object") return value;
|
|
6210
6509
|
return Object.fromEntries(Object.entries(value).map(([key, item]) => [key, unwrapTemplateExpressions(item)]));
|
|
6211
6510
|
}
|
|
6511
|
+
function containsTemplateExpression(value) {
|
|
6512
|
+
if (typeof value === "string") return /^\{\{[\s\S]*\}\}$/.test(value.trim());
|
|
6513
|
+
if (Array.isArray(value)) return value.some(containsTemplateExpression);
|
|
6514
|
+
return Boolean(value) && typeof value === "object" && Object.values(value).some(containsTemplateExpression);
|
|
6515
|
+
}
|
|
6212
6516
|
function buildV6TransitionReturnValue(transition, contextValue) {
|
|
6213
|
-
if (!transition.reenter && !transition.meta && !contextValue && transition.input === void 0)
|
|
6517
|
+
if (!transition.reenter && !transition.meta && !contextValue && transition.input === void 0) {
|
|
6518
|
+
const target = Array.isArray(transition.target) ? `[${transition.target.map((item) => serializeJS(item)).join(", ")}]` : serializeJS(transition.target);
|
|
6519
|
+
return transition.target ? `{ target: ${target} }` : void 0;
|
|
6520
|
+
}
|
|
6214
6521
|
return serializeJS({
|
|
6215
6522
|
target: transition.target,
|
|
6216
6523
|
reenter: transition.reenter ? true : void 0,
|
|
@@ -6248,6 +6555,13 @@ function inlineExpr(value) {
|
|
|
6248
6555
|
const directive = value;
|
|
6249
6556
|
return directive["@type"] === "code" && typeof directive.expr === "string" ? directive.expr : void 0;
|
|
6250
6557
|
}
|
|
6558
|
+
function containsInlineExpression(value) {
|
|
6559
|
+
if (!value || typeof value !== "object") return false;
|
|
6560
|
+
if (Array.isArray(value)) return value.some(containsInlineExpression);
|
|
6561
|
+
const record = value;
|
|
6562
|
+
if (record["@type"] === "code" && typeof record.expr === "string") return true;
|
|
6563
|
+
return Object.values(record).some(containsInlineExpression);
|
|
6564
|
+
}
|
|
6251
6565
|
function actionToV6Effect(action) {
|
|
6252
6566
|
const expr = inlineExpr(action);
|
|
6253
6567
|
if (expr) {
|
|
@@ -6443,6 +6757,12 @@ function getCodeExpressionImports$1(graph) {
|
|
|
6443
6757
|
const XSTATE_ACTOR_LOGIC_HELPERS = new Set([
|
|
6444
6758
|
"createMachine",
|
|
6445
6759
|
"createAsyncLogic",
|
|
6760
|
+
"createCallbackLogic",
|
|
6761
|
+
"createEventObservableLogic",
|
|
6762
|
+
"createListenerLogic",
|
|
6763
|
+
"createLogic",
|
|
6764
|
+
"createObservableLogic",
|
|
6765
|
+
"createSubscriptionLogic",
|
|
6446
6766
|
"fromPromise",
|
|
6447
6767
|
"fromCallback",
|
|
6448
6768
|
"fromObservable",
|
|
@@ -6527,8 +6847,17 @@ function buildV6SchemasBlock(schemas, options) {
|
|
|
6527
6847
|
const contextType = contextSchemaToTSType(schemas.context);
|
|
6528
6848
|
if (contextType) result.context = raw(`types<${contextType}>()`);
|
|
6529
6849
|
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)}>()`)]));
|
|
6850
|
+
if (schemas.emitted && Object.keys(schemas.emitted).length > 0) result.emitted = Object.fromEntries(Object.entries(schemas.emitted).map(([eventType, schema]) => [eventType, raw(`types<${eventPayloadSchemaToTSType(schema)}>()`)]));
|
|
6851
|
+
if (schemas.internalEvents && Object.keys(schemas.internalEvents).length > 0) result.internalEvents = Object.fromEntries(Object.entries(schemas.internalEvents).map(([eventType, schema]) => [eventType, raw(`types<${eventPayloadSchemaToTSType(schema)}>()`)]));
|
|
6852
|
+
if (schemas.children && Object.keys(schemas.children).length > 0) result.children = Object.fromEntries(Object.entries(schemas.children).map(([name, schema]) => [name, raw(`types<${jsonSchemaToTSType(schema)}>()`)]));
|
|
6853
|
+
for (const key of ["actions", "guards"]) {
|
|
6854
|
+
const map = schemas[key];
|
|
6855
|
+
if (map && Object.keys(map).length > 0) result[key] = Object.fromEntries(Object.entries(map).map(([name, value]) => [name, { ...value.params ? { params: raw(`types<${jsonSchemaToTSType(value.params)}>()`) } : {} }]));
|
|
6856
|
+
}
|
|
6530
6857
|
if (schemas.input) result.input = raw(`types<${jsonSchemaToTSType(schemas.input)}>()`);
|
|
6531
6858
|
if (schemas.output) result.output = raw(`types<${jsonSchemaToTSType(schemas.output)}>()`);
|
|
6859
|
+
if (schemas.tags && Object.keys(schemas.tags).length > 0) result.tags = raw(`types<${jsonSchemaToTSType(schemas.tags)}>()`);
|
|
6860
|
+
if (schemas.meta && Object.keys(schemas.meta).length > 0) result.meta = raw(`types<${jsonSchemaToTSType(schemas.meta)}>()`);
|
|
6532
6861
|
return Object.keys(result).length > 0 ? result : void 0;
|
|
6533
6862
|
}
|
|
6534
6863
|
function buildV6ZodSchemasBlock(schemas) {
|
|
@@ -6537,14 +6866,25 @@ function buildV6ZodSchemasBlock(schemas) {
|
|
|
6537
6866
|
const contextSchema = contextSchemaToZod(schemas.context);
|
|
6538
6867
|
if (contextSchema) result.context = raw(contextSchema);
|
|
6539
6868
|
if (schemas.events && Object.keys(schemas.events).length > 0) result.events = Object.fromEntries(Object.entries(schemas.events).map(([eventType, schema]) => [eventType, raw(eventSchemaToZod(schema))]));
|
|
6869
|
+
if (schemas.emitted && Object.keys(schemas.emitted).length > 0) result.emitted = Object.fromEntries(Object.entries(schemas.emitted).map(([eventType, schema]) => [eventType, raw(eventSchemaToZod(schema))]));
|
|
6870
|
+
for (const key of ["internalEvents", "children"]) {
|
|
6871
|
+
const map = schemas[key];
|
|
6872
|
+
if (map && Object.keys(map).length > 0) result[key] = Object.fromEntries(Object.entries(map).map(([name, schema]) => [name, raw(jsonSchemaToZod(schema))]));
|
|
6873
|
+
}
|
|
6874
|
+
for (const key of ["actions", "guards"]) {
|
|
6875
|
+
const map = schemas[key];
|
|
6876
|
+
if (map && Object.keys(map).length > 0) result[key] = Object.fromEntries(Object.entries(map).map(([name, value]) => [name, { ...value.params ? { params: raw(jsonSchemaToZod(value.params)) } : {} }]));
|
|
6877
|
+
}
|
|
6540
6878
|
if (schemas.input) result.input = raw(jsonSchemaToZod(schemas.input));
|
|
6541
6879
|
if (schemas.output) result.output = raw(jsonSchemaToZod(schemas.output));
|
|
6880
|
+
if (schemas.tags && Object.keys(schemas.tags).length > 0) result.tags = raw(jsonSchemaToZod(schemas.tags));
|
|
6881
|
+
if (schemas.meta && Object.keys(schemas.meta).length > 0) result.meta = raw(jsonSchemaToZod(schemas.meta));
|
|
6542
6882
|
return Object.keys(result).length > 0 ? result : void 0;
|
|
6543
6883
|
}
|
|
6544
6884
|
function eventPayloadSchemaToTSType(schema) {
|
|
6545
6885
|
const props = schema.properties ?? {};
|
|
6546
6886
|
const payloadProps = Object.fromEntries(Object.entries(props).filter(([key]) => key !== "type"));
|
|
6547
|
-
if (Object.keys(payloadProps).length === 0) return "
|
|
6887
|
+
if (Object.keys(payloadProps).length === 0) return "void";
|
|
6548
6888
|
return jsonSchemaToTSType({
|
|
6549
6889
|
...schema,
|
|
6550
6890
|
properties: payloadProps,
|
|
@@ -6562,14 +6902,16 @@ function hasSchemaProperties(schema) {
|
|
|
6562
6902
|
function buildActionsBlock(actions, options) {
|
|
6563
6903
|
const block = {};
|
|
6564
6904
|
for (const implementation of actions) if (implementation.code?.body) {
|
|
6905
|
+
if (options.xstateVersion === 6) assertV6NamedActionBody(implementation.name, implementation.code.body);
|
|
6565
6906
|
const inlineExpression = getInlineExpression$1(implementation.code.body);
|
|
6566
6907
|
if (inlineExpression) {
|
|
6567
6908
|
block[implementation.name] = raw(inlineExpression);
|
|
6568
6909
|
continue;
|
|
6569
6910
|
}
|
|
6570
|
-
const params = hasSchemaProperties(implementation.paramsSchema) ? options.includeTypeSyntax ? `, params: ${jsonSchemaToTSType(implementation.paramsSchema)}` : ", params" : "";
|
|
6571
|
-
|
|
6572
|
-
|
|
6911
|
+
const params = hasSchemaProperties(implementation.paramsSchema) ? options.xstateVersion === 6 ? options.includeTypeSyntax ? `params: ${jsonSchemaToTSType(implementation.paramsSchema)}` : "params" : options.includeTypeSyntax ? `, params: ${jsonSchemaToTSType(implementation.paramsSchema)}` : ", params" : "";
|
|
6912
|
+
const firstParam = options.xstateVersion === 6 ? params : `{ context, event }${params}`;
|
|
6913
|
+
block[implementation.name] = raw(`function (${firstParam}) {\n ${dedent(implementation.code.body)}\n}`);
|
|
6914
|
+
} else block[implementation.name] = raw(options.xstateVersion === 6 ? `function () {\n // TODO: implement ${implementation.name}\n}` : `function ({ context, event }) {\n // TODO: implement ${implementation.name}\n}`);
|
|
6573
6915
|
return block;
|
|
6574
6916
|
}
|
|
6575
6917
|
function buildGuardsBlock(guards, options) {
|
|
@@ -6641,6 +6983,23 @@ function getInlineExpression$1(code) {
|
|
|
6641
6983
|
if (stripped !== code.trim()) return stripped;
|
|
6642
6984
|
return isCompleteFunctionExpression(stripped) || isCompleteXStateHelperExpression(stripped) ? stripped : void 0;
|
|
6643
6985
|
}
|
|
6986
|
+
/**
|
|
6987
|
+
* A complete function expression is preserved verbatim when it came from an
|
|
6988
|
+
* imported implementation. Reject the XState v5 named-action signature here
|
|
6989
|
+
* instead of emitting a v6 action whose `context`/`event` references are free
|
|
6990
|
+
* at runtime. XState v6 named actions receive only their params argument.
|
|
6991
|
+
*/
|
|
6992
|
+
function assertV6NamedActionBody(name, code) {
|
|
6993
|
+
const expression = parseSingleExpression(stripExportDefault(code))?.expression;
|
|
6994
|
+
if (!expression || !ts.isArrowFunction(expression) && !ts.isFunctionExpression(expression)) return;
|
|
6995
|
+
const firstParameter = expression.parameters[0]?.name;
|
|
6996
|
+
if (!firstParameter || !ts.isObjectBindingPattern(firstParameter)) return;
|
|
6997
|
+
if (firstParameter.elements.some((element) => {
|
|
6998
|
+
if (element.dotDotDotToken) return false;
|
|
6999
|
+
const property = element.propertyName ?? element.name;
|
|
7000
|
+
return ts.isIdentifier(property) && (property.text === "context" || property.text === "event");
|
|
7001
|
+
})) throw new Error(`Cannot export named action "${name}" as XState v6: its implementation uses the XState v5 context/event signature. Rewrite it to receive params only.`);
|
|
7002
|
+
}
|
|
6644
7003
|
function parseSingleExpression(code) {
|
|
6645
7004
|
const candidate = code.trim().replace(/;$/, "");
|
|
6646
7005
|
const source = ts.createSourceFile("implementation.ts", `(${candidate})`, ts.ScriptTarget.Latest, false, ts.ScriptKind.TS);
|
|
@@ -6756,6 +7115,9 @@ function transformState(state, ctx, sourceKey) {
|
|
|
6756
7115
|
case "output":
|
|
6757
7116
|
result.data = transformCodeValues(value);
|
|
6758
7117
|
break;
|
|
7118
|
+
case "tags":
|
|
7119
|
+
result.tags = Array.isArray(value) && value.length === 1 ? value[0] : value;
|
|
7120
|
+
break;
|
|
6759
7121
|
case "entry":
|
|
6760
7122
|
case "exit":
|
|
6761
7123
|
result[key] = transformActions(value);
|
|
@@ -7676,102 +8038,4 @@ const simulateMachineStepInputSchema = machineInputSchema.extend({
|
|
|
7676
8038
|
});
|
|
7677
8039
|
|
|
7678
8040
|
//#endregion
|
|
7679
|
-
|
|
7680
|
-
function findStatelyPragmaAttachments(sourceText, fileName = "machine.ts") {
|
|
7681
|
-
const sourceFile = ts.createSourceFile(fileName, sourceText, ts.ScriptTarget.Latest, true, getScriptKind(fileName));
|
|
7682
|
-
const attachments = [];
|
|
7683
|
-
const visit = (node) => {
|
|
7684
|
-
if (ts.isCallExpression(node) && isCreateMachineExpression(node.expression)) {
|
|
7685
|
-
const attachNode = findAttachNode(node);
|
|
7686
|
-
if (attachNode) attachments.push({
|
|
7687
|
-
machineStart: getMachineExpressionStart(node.expression, sourceFile),
|
|
7688
|
-
attachStart: attachNode.getStart(sourceFile),
|
|
7689
|
-
pragma: findAttachedStatelyPragma(sourceText, attachNode)
|
|
7690
|
-
});
|
|
7691
|
-
}
|
|
7692
|
-
ts.forEachChild(node, visit);
|
|
7693
|
-
};
|
|
7694
|
-
visit(sourceFile);
|
|
7695
|
-
return attachments;
|
|
7696
|
-
}
|
|
7697
|
-
function getStatelyPragma(sourceText, fileName = "machine.ts", machineIndex = 0) {
|
|
7698
|
-
return findStatelyPragmaAttachments(sourceText, fileName)[machineIndex]?.pragma;
|
|
7699
|
-
}
|
|
7700
|
-
function upsertStatelyPragma(sourceText, id, options = {}) {
|
|
7701
|
-
const attachment = findStatelyPragmaAttachments(sourceText, options.fileName ?? "machine.ts")[options.machineIndex ?? 0];
|
|
7702
|
-
if (!attachment) return sourceText;
|
|
7703
|
-
const lineEnding = options.lineEnding ?? detectLineEnding(sourceText);
|
|
7704
|
-
const canonicalComment = `// @statelyai id=${id}`;
|
|
7705
|
-
if (attachment.pragma) return sourceText.slice(0, attachment.pragma.start) + canonicalComment + sourceText.slice(attachment.pragma.end);
|
|
7706
|
-
const insertText = `${getIndentationAtOffset(sourceText, attachment.attachStart)}${canonicalComment}${lineEnding}`;
|
|
7707
|
-
return sourceText.slice(0, attachment.attachStart) + insertText + sourceText.slice(attachment.attachStart);
|
|
7708
|
-
}
|
|
7709
|
-
function findAttachedStatelyPragma(sourceText, node) {
|
|
7710
|
-
const comments = ts.getLeadingCommentRanges(sourceText, node.getFullStart()) ?? [];
|
|
7711
|
-
for (let index = comments.length - 1; index >= 0; index -= 1) {
|
|
7712
|
-
const comment = comments[index];
|
|
7713
|
-
const parsed = parseStatelyPragma(sourceText, comment.pos, comment.end);
|
|
7714
|
-
if (parsed) return parsed;
|
|
7715
|
-
}
|
|
7716
|
-
}
|
|
7717
|
-
function parseStatelyPragma(sourceText, start, end) {
|
|
7718
|
-
const match = normalizeCommentContent(sourceText.slice(start, end)).match(/^@statelyai(?:\s+(.*))?$/s);
|
|
7719
|
-
if (!match) return;
|
|
7720
|
-
const fields = parseFields(match[1] ?? "");
|
|
7721
|
-
return {
|
|
7722
|
-
tag: "@statelyai",
|
|
7723
|
-
id: fields.id,
|
|
7724
|
-
fields,
|
|
7725
|
-
start,
|
|
7726
|
-
end
|
|
7727
|
-
};
|
|
7728
|
-
}
|
|
7729
|
-
function normalizeCommentContent(rawComment) {
|
|
7730
|
-
if (rawComment.startsWith("//")) return rawComment.slice(2).trim();
|
|
7731
|
-
if (rawComment.startsWith("/*")) return rawComment.slice(2, rawComment.endsWith("*/") ? -2 : void 0).split(/\r?\n/).map((line) => line.replace(/^\s*\*\s?/, "")).join(" ").trim();
|
|
7732
|
-
return rawComment.trim();
|
|
7733
|
-
}
|
|
7734
|
-
function parseFields(input) {
|
|
7735
|
-
const fields = {};
|
|
7736
|
-
for (const token of input.split(/\s+/)) {
|
|
7737
|
-
if (!token) continue;
|
|
7738
|
-
const equalsIndex = token.indexOf("=");
|
|
7739
|
-
if (equalsIndex <= 0) continue;
|
|
7740
|
-
const key = token.slice(0, equalsIndex);
|
|
7741
|
-
const value = token.slice(equalsIndex + 1);
|
|
7742
|
-
if (!key || !value) continue;
|
|
7743
|
-
fields[key] = value;
|
|
7744
|
-
}
|
|
7745
|
-
return fields;
|
|
7746
|
-
}
|
|
7747
|
-
function findAttachNode(node) {
|
|
7748
|
-
let current = node;
|
|
7749
|
-
while (current?.parent) {
|
|
7750
|
-
if (ts.isVariableStatement(current.parent) || ts.isExpressionStatement(current.parent) || ts.isExportAssignment(current.parent)) return current.parent;
|
|
7751
|
-
current = current.parent;
|
|
7752
|
-
}
|
|
7753
|
-
return current;
|
|
7754
|
-
}
|
|
7755
|
-
function isCreateMachineExpression(expression) {
|
|
7756
|
-
return ts.isIdentifier(expression) && expression.text === "createMachine" || ts.isPropertyAccessExpression(expression) && expression.name.text === "createMachine";
|
|
7757
|
-
}
|
|
7758
|
-
function getMachineExpressionStart(expression, sourceFile) {
|
|
7759
|
-
if (ts.isPropertyAccessExpression(expression)) return expression.name.getStart(sourceFile);
|
|
7760
|
-
return expression.getStart(sourceFile);
|
|
7761
|
-
}
|
|
7762
|
-
function getIndentationAtOffset(sourceText, offset) {
|
|
7763
|
-
const lineStart = sourceText.lastIndexOf("\n", Math.max(0, offset - 1)) + 1;
|
|
7764
|
-
return sourceText.slice(lineStart, offset).match(/^[ \t]*/)?.[0] ?? "";
|
|
7765
|
-
}
|
|
7766
|
-
function detectLineEnding(sourceText) {
|
|
7767
|
-
return sourceText.includes("\r\n") ? "\r\n" : "\n";
|
|
7768
|
-
}
|
|
7769
|
-
function getScriptKind(fileName) {
|
|
7770
|
-
if (fileName.endsWith(".tsx")) return ts.ScriptKind.TSX;
|
|
7771
|
-
if (fileName.endsWith(".jsx")) return ts.ScriptKind.JSX;
|
|
7772
|
-
if (fileName.endsWith(".js")) return ts.ScriptKind.JS;
|
|
7773
|
-
return ts.ScriptKind.TS;
|
|
7774
|
-
}
|
|
7775
|
-
|
|
7776
|
-
//#endregion
|
|
7777
|
-
export { jsonSchemaToTSType as _, RawCode as a, serializeJS as b, detectXStateSourceProfile as c, getXStateFSMCompatibilityIssues as d, graphChangeToPatchesResult as f, graphToXStateV4TS as g, graphToXStateTS as h, INLINE_EXPRESSION_DIRECTIVE_FIELDS as i, diffGraphsSemantically as l, graphToXStateFSM as m, getStatelyPragma as n, alignCompareGraphIds as o, graphToMachineConfig as p, upsertStatelyPragma as r, contextSchemaToTSType as s, findStatelyPragmaAttachments as t, eventsSchemaToTSType as u, normalizeMachineProfile as v, xstateSourceToConfig as x, raw as y };
|
|
8041
|
+
export { toXStateV6MachineConfig as S, graphToXStateV4TS as _, alignCompareGraphIds as a, raw as b, diffGraphsSemantically as c, getDelayKeyFromEventType as d, getXStateFSMCompatibilityIssues as f, graphToXStateTS as g, graphToXStateFSM as h, XSTATE_V6_FN_TRANSITION_META as i, eventsSchemaToTSType as l, graphToMachineConfig as m, RawCode as n, contextSchemaToTSType as o, graphChangeToPatchesResult as p, XSTATE_V6_BRANCH_DESCRIPTION_META as r, detectXStateSourceProfile as s, INLINE_EXPRESSION_DIRECTIVE_FIELDS as t, extractXStateMachineConfigEntries as u, jsonSchemaToTSType as v, serializeJS as x, normalizeMachineProfile as y };
|