statelyai 0.12.2 → 0.12.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +19 -3
- package/dist/bin.mjs +1 -1
- package/dist/{cli-DkgwcbvD.mjs → cli-RFjHJYb3.mjs} +466 -98
- package/dist/index.d.mts +2 -0
- package/dist/index.mjs +1 -1
- package/package.json +4 -4
|
@@ -6908,14 +6908,15 @@ function containsCodeExpression(value, seen = /* @__PURE__ */ new WeakSet()) {
|
|
|
6908
6908
|
*/
|
|
6909
6909
|
const VALID_IDENT = /^[a-zA-Z_$][a-zA-Z0-9_$]*$/;
|
|
6910
6910
|
var RawCode = class {
|
|
6911
|
-
constructor(code, sourceValue, sourceSlice) {
|
|
6911
|
+
constructor(code, sourceValue, sourceSlice, preserveWhitespace = false) {
|
|
6912
6912
|
this.code = code;
|
|
6913
6913
|
this.sourceValue = sourceValue;
|
|
6914
6914
|
this.sourceSlice = sourceSlice;
|
|
6915
|
+
this.preserveWhitespace = preserveWhitespace;
|
|
6915
6916
|
}
|
|
6916
6917
|
};
|
|
6917
|
-
function raw(code, sourceValue, sourceSlice) {
|
|
6918
|
-
return new RawCode(code, sourceValue, sourceSlice);
|
|
6918
|
+
function raw(code, sourceValue, sourceSlice, preserveWhitespace = false) {
|
|
6919
|
+
return new RawCode(code, sourceValue, sourceSlice, preserveWhitespace);
|
|
6919
6920
|
}
|
|
6920
6921
|
const SERIALIZED_SOURCE_ID = "__stately_source_id__";
|
|
6921
6922
|
function serializeJS(value, indent = 0, step = 2) {
|
|
@@ -6963,6 +6964,7 @@ function serializeObject(obj, indent, step) {
|
|
|
6963
6964
|
}
|
|
6964
6965
|
function preservesAuthoredWhitespace(value) {
|
|
6965
6966
|
if (isCodeExpression(value)) return true;
|
|
6967
|
+
if (value instanceof RawCode && value.preserveWhitespace) return true;
|
|
6966
6968
|
const sourceValue = value instanceof RawCode ? value.sourceValue : value;
|
|
6967
6969
|
return Boolean(sourceValue && typeof sourceValue === "object" && SERIALIZED_SOURCE_ID in sourceValue);
|
|
6968
6970
|
}
|
|
@@ -7142,13 +7144,13 @@ function deepSimplify(config) {
|
|
|
7142
7144
|
if (config.states && typeof config.states === "object") for (const stateConfig of Object.values(config.states)) deepSimplify(stateConfig);
|
|
7143
7145
|
return config;
|
|
7144
7146
|
}
|
|
7145
|
-
function buildMeta(meta, color) {
|
|
7147
|
+
function buildMeta(meta, color, showStatelyMeta = true) {
|
|
7146
7148
|
if (isCodeExpression(meta)) return meta;
|
|
7147
7149
|
const result = {};
|
|
7148
7150
|
if (meta) {
|
|
7149
|
-
for (const [k, v] of Object.entries(meta)) if (v !== void 0 && v !== null) result[k] = v;
|
|
7151
|
+
for (const [k, v] of Object.entries(meta)) if (v !== void 0 && v !== null && (showStatelyMeta || !k.startsWith("@statelyai"))) result[k] = v;
|
|
7150
7152
|
}
|
|
7151
|
-
if (color) result["@statelyai.color"] = color;
|
|
7153
|
+
if (color && showStatelyMeta) result["@statelyai.color"] = color;
|
|
7152
7154
|
return Object.keys(result).length > 0 ? result : void 0;
|
|
7153
7155
|
}
|
|
7154
7156
|
/** Format event param — supports { type: string } (new) and plain string (legacy) */
|
|
@@ -7444,7 +7446,7 @@ function tagToString(tag) {
|
|
|
7444
7446
|
}
|
|
7445
7447
|
function graphToMachineConfig(graph, options = {}) {
|
|
7446
7448
|
const v6 = isXStateV6Profile(graph.data.profile);
|
|
7447
|
-
const { showDescriptions = true, showMeta = true, inlineGuardsAsTypeRef = false, keepChooseStructured = false } = options;
|
|
7449
|
+
const { showDescriptions = true, showMeta = true, showStatelyMeta = true, inlineGuardsAsTypeRef = false, keepChooseStructured = false } = options;
|
|
7448
7450
|
const serializeAction = (action) => serializeActionItem(action, keepChooseStructured);
|
|
7449
7451
|
const config = {};
|
|
7450
7452
|
function getNodeConfig(node) {
|
|
@@ -7458,7 +7460,7 @@ function graphToMachineConfig(graph, options = {}) {
|
|
|
7458
7460
|
"choice"
|
|
7459
7461
|
].includes(node.data.type) ? node.data.type : void 0;
|
|
7460
7462
|
const tags = node.data.tags;
|
|
7461
|
-
const stateMeta = showMeta ? buildMeta(node.data.meta, node.data.color) : void 0;
|
|
7463
|
+
const stateMeta = showMeta ? buildMeta(node.data.meta, node.data.color, showStatelyMeta) : void 0;
|
|
7462
7464
|
Object.assign(nodeConfig, {
|
|
7463
7465
|
id: resolvedNodeId,
|
|
7464
7466
|
type: nodeType === "normal" ? void 0 : nodeType ?? void 0,
|
|
@@ -7505,7 +7507,7 @@ function graphToMachineConfig(graph, options = {}) {
|
|
|
7505
7507
|
return additionalTarget ? [resolveTransitionTarget(graph, node, additionalTarget)] : [];
|
|
7506
7508
|
})].filter(Boolean);
|
|
7507
7509
|
const type = edge.data.eventType ?? "";
|
|
7508
|
-
const transitionMeta = showMeta ? buildMeta(edge.data.meta, edge.data.color) : void 0;
|
|
7510
|
+
const transitionMeta = showMeta ? buildMeta(edge.data.meta, edge.data.color, showStatelyMeta) : void 0;
|
|
7509
7511
|
const transitionObject = {
|
|
7510
7512
|
...edge.data.matches ? { matches: edge.data.matches } : void 0,
|
|
7511
7513
|
target: edge.data.transitionType === "targetless" ? void 0 : resolvedTargets.length > 1 ? resolvedTargets : `${resolvedTarget}`,
|
|
@@ -7514,7 +7516,7 @@ function graphToMachineConfig(graph, options = {}) {
|
|
|
7514
7516
|
...edge.data.context !== void 0 ? { context: edge.data.context } : void 0,
|
|
7515
7517
|
...edge.data.input !== void 0 ? { input: edge.data.input } : void 0,
|
|
7516
7518
|
actions: edge.data.actions?.length ? edge.data.actions.map(serializeAction) : void 0,
|
|
7517
|
-
description: edge.data.description ?? void 0,
|
|
7519
|
+
description: showDescriptions ? edge.data.description ?? void 0 : void 0,
|
|
7518
7520
|
...transitionMeta ? { meta: transitionMeta } : void 0
|
|
7519
7521
|
};
|
|
7520
7522
|
const pushOn = (key) => {
|
|
@@ -8864,7 +8866,7 @@ function omitIdentityTransitionContext(transition, identity) {
|
|
|
8864
8866
|
function normalizeFunctionTransition(fn, bindings, depth) {
|
|
8865
8867
|
if (fn.body && ts.isBlock(fn.body) && hasUnsafeVariableInitializer(fn.body)) return fallbackFunctionTransition(fn);
|
|
8866
8868
|
const branches = ts.isArrowFunction(fn) && !ts.isBlock(fn.body) ? expressionBranches(fn.body, bindings, depth + 1) : fn.body && ts.isBlock(fn.body) ? statementBranches(fn.body.statements, bindings, enqueueParamName(fn)) : [];
|
|
8867
|
-
if (branches.some((branch) => branch.unknown)) return fallbackFunctionTransition(fn);
|
|
8869
|
+
if (branches.some((branch) => branch.unknown || isCodeExpression(branch.result))) return fallbackFunctionTransition(fn);
|
|
8868
8870
|
const contextIdentity = transitionContextIdentity(fn);
|
|
8869
8871
|
const transitions = branches.map((branch) => {
|
|
8870
8872
|
let result = branch.result;
|
|
@@ -9300,6 +9302,7 @@ function expressionToValue(expression, bindings, context = {}, depth = 0) {
|
|
|
9300
9302
|
if (builtIn) return builtIn;
|
|
9301
9303
|
return inlineAction(node);
|
|
9302
9304
|
}
|
|
9305
|
+
if (context.v6 && context.transitionValue) return inlineCodeExpression(resolvedExpressionText(node, bindings));
|
|
9303
9306
|
const callee = node.expression.getText();
|
|
9304
9307
|
const type = callee.includes(".") ? callee.split(".").pop() : callee;
|
|
9305
9308
|
return { type: type === "assign" ? "xstate.assign" : type };
|
|
@@ -10107,8 +10110,9 @@ function mapV6MachineConfig(value, context = {}) {
|
|
|
10107
10110
|
result[key] = mapV6StatesMap(item);
|
|
10108
10111
|
continue;
|
|
10109
10112
|
}
|
|
10110
|
-
if (key === "choice") {
|
|
10111
|
-
|
|
10113
|
+
if (key === "choice" && value.type === "choice") {
|
|
10114
|
+
const choices = Array.isArray(item) ? item : [item];
|
|
10115
|
+
result[key] = choices.length === 1 && opaqueTransitionSource(choices[0]) !== void 0 ? toV6TransitionValue(item) : buildV6TransitionFunction(choices.map(withoutOpaqueTransitionMeta), true) ?? toV6TransitionValue(item);
|
|
10112
10116
|
continue;
|
|
10113
10117
|
}
|
|
10114
10118
|
if (key === "entry" || key === "exit" || key === "actions") {
|
|
@@ -10140,10 +10144,44 @@ function mapV6TransitionMap(value) {
|
|
|
10140
10144
|
for (const [key, item] of Object.entries(value)) result[key] = mapV6MachineConfig(item, { transitionValue: true });
|
|
10141
10145
|
return result;
|
|
10142
10146
|
}
|
|
10147
|
+
/**
|
|
10148
|
+
* The authored source of a transition function the importer could not
|
|
10149
|
+
* analyze. It projects to one opaque edge, so the source is still exactly what
|
|
10150
|
+
* the edge represents.
|
|
10151
|
+
*/
|
|
10152
|
+
function opaqueTransitionSource(value) {
|
|
10153
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) return;
|
|
10154
|
+
const transition = value;
|
|
10155
|
+
const meta = transition.meta;
|
|
10156
|
+
const fnSource = meta?.[XSTATE_V6_FN_SOURCE_META];
|
|
10157
|
+
const hasGraphEdits = Object.entries(transition).some(([key, field]) => key !== "meta" && field !== void 0);
|
|
10158
|
+
return meta?.[XSTATE_V6_FN_TRANSITION_META] === true && typeof fnSource === "string" && !hasGraphEdits ? fnSource : void 0;
|
|
10159
|
+
}
|
|
10160
|
+
function withoutOpaqueTransitionMeta(value) {
|
|
10161
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) return value;
|
|
10162
|
+
const transition = value;
|
|
10163
|
+
const meta = transition.meta;
|
|
10164
|
+
if (!meta || typeof meta !== "object" || Array.isArray(meta)) return value;
|
|
10165
|
+
const { [XSTATE_V6_FN_TRANSITION_META]: _fnTransition, [XSTATE_V6_FN_SOURCE_META]: _fnSource, ...publicMeta } = meta;
|
|
10166
|
+
if (_fnTransition === void 0 && _fnSource === void 0) return value;
|
|
10167
|
+
return {
|
|
10168
|
+
...transition,
|
|
10169
|
+
meta: Object.keys(publicMeta).length > 0 ? publicMeta : void 0
|
|
10170
|
+
};
|
|
10171
|
+
}
|
|
10143
10172
|
function toV6TransitionValue(value) {
|
|
10144
|
-
|
|
10173
|
+
const opaqueSource = opaqueTransitionSource(value);
|
|
10174
|
+
if (opaqueSource !== void 0) return raw(opaqueSource, value, void 0, true);
|
|
10175
|
+
if (Array.isArray(value)) {
|
|
10176
|
+
if (value.length === 1) {
|
|
10177
|
+
const onlyOpaqueSource = opaqueTransitionSource(value[0]);
|
|
10178
|
+
if (onlyOpaqueSource !== void 0) return raw(onlyOpaqueSource, value[0], void 0, true);
|
|
10179
|
+
}
|
|
10180
|
+
const transitions = value.map(withoutOpaqueTransitionMeta);
|
|
10181
|
+
return buildV6TransitionFunction(transitions) ?? transitions.map((item) => toV6TransitionValue(item));
|
|
10182
|
+
}
|
|
10145
10183
|
if (!value || typeof value !== "object") return value;
|
|
10146
|
-
const transition = value;
|
|
10184
|
+
const transition = withoutOpaqueTransitionMeta(value);
|
|
10147
10185
|
if (transition.matches !== void 0) return buildV6TransitionFunction([transition]) ?? mapV6MachineConfig(transition);
|
|
10148
10186
|
if (transition.guard) return buildV6TransitionFunction([transition]) ?? mapV6MachineConfig(transition);
|
|
10149
10187
|
if (transition.description || transition.input !== void 0 && !containsCodeExpression(transition.input)) return mapV6MachineConfig(transition);
|
|
@@ -10294,11 +10332,11 @@ function mergeV6FirstParam(authoredFirstParam, inferred) {
|
|
|
10294
10332
|
prelude: []
|
|
10295
10333
|
};
|
|
10296
10334
|
}
|
|
10297
|
-
function buildV6TransitionFunction(transitions) {
|
|
10335
|
+
function buildV6TransitionFunction(transitions, choice = false) {
|
|
10298
10336
|
const transitionObjects = transitions.every((item) => Boolean(item) && typeof item === "object" && !Array.isArray(item)) ? transitions : void 0;
|
|
10299
10337
|
if (!transitionObjects?.length) return;
|
|
10300
10338
|
const descriptions = transitionObjects.map((transition) => typeof transition.description === "string" ? transition.description : void 0);
|
|
10301
|
-
const hasBranchDescriptions = transitionObjects.some((transition) => Object.prototype.hasOwnProperty.call(transition.meta ?? {}, XSTATE_V6_BRANCH_DESCRIPTION_META)) || descriptions.some((description) => description !== descriptions[0]);
|
|
10339
|
+
const hasBranchDescriptions = choice && descriptions.some((description) => description !== void 0) || transitionObjects.some((transition) => Object.prototype.hasOwnProperty.call(transition.meta ?? {}, XSTATE_V6_BRANCH_DESCRIPTION_META)) || descriptions.some((description) => description !== descriptions[0]);
|
|
10302
10340
|
const branches = [];
|
|
10303
10341
|
let authoredFirstParam;
|
|
10304
10342
|
const commonDescription = descriptions[0];
|
|
@@ -10334,7 +10372,7 @@ function buildV6TransitionFunction(transitions) {
|
|
|
10334
10372
|
});
|
|
10335
10373
|
}
|
|
10336
10374
|
if (branches.length === 0) return;
|
|
10337
|
-
if (branches.slice(0, -1).some((branch) => branch.condition === "true")) return;
|
|
10375
|
+
if (!choice && branches.slice(0, -1).some((branch) => branch.condition === "true")) return;
|
|
10338
10376
|
const generated = branches.flatMap((branch) => [branch.condition, ...branch.body]).join("\n");
|
|
10339
10377
|
let renderedBranches = branches;
|
|
10340
10378
|
let merged = mergeV6FirstParam(authoredFirstParam, inferV6ArgBindings(generated));
|
|
@@ -10347,7 +10385,7 @@ function buildV6TransitionFunction(transitions) {
|
|
|
10347
10385
|
}
|
|
10348
10386
|
if (!merged) return;
|
|
10349
10387
|
const lines = merged.prelude.map((statement) => indentV6Code(statement, 2));
|
|
10350
|
-
for (const branch of renderedBranches) if (branch.condition === "true") lines.push(...branch.body.map((line) => indentV6Code(line, 2)));
|
|
10388
|
+
for (const [index, branch] of renderedBranches.entries()) if (branch.condition === "true" && index === renderedBranches.length - 1) lines.push(...branch.body.map((line) => indentV6Code(line, 2)));
|
|
10351
10389
|
else {
|
|
10352
10390
|
lines.push(indentV6Code(`if (${branch.condition}) {`, 2));
|
|
10353
10391
|
lines.push(...branch.body.map((line) => indentV6Code(line, 4)));
|
|
@@ -13051,7 +13089,7 @@ function applyEdits(text, edits) {
|
|
|
13051
13089
|
}
|
|
13052
13090
|
|
|
13053
13091
|
//#endregion
|
|
13054
|
-
//#region ../editor-sync/dist/adapters-
|
|
13092
|
+
//#region ../editor-sync/dist/adapters-CL5NOglI.mjs
|
|
13055
13093
|
const sourceFileUris = /* @__PURE__ */ new WeakMap();
|
|
13056
13094
|
function collectXStateSourceLocations(sourceText, document, options = {}) {
|
|
13057
13095
|
const sourceFile = ts$1.createSourceFile(document.fileName, sourceText, ts$1.ScriptTarget.Latest, true, getScriptKind$2$1(document.fileName));
|
|
@@ -13237,11 +13275,21 @@ function addImportedStaticValueBindings(bindings, sourceFile, uri, fileName, opt
|
|
|
13237
13275
|
}, statement.moduleSpecifier.text);
|
|
13238
13276
|
if (!importedDocument) continue;
|
|
13239
13277
|
for (const element of namedBindings.elements) {
|
|
13240
|
-
const
|
|
13241
|
-
|
|
13242
|
-
|
|
13243
|
-
|
|
13244
|
-
|
|
13278
|
+
const importedName = element.propertyName?.text ?? element.name.text;
|
|
13279
|
+
const members = new Set([""]);
|
|
13280
|
+
const visit = (node) => {
|
|
13281
|
+
if (ts$1.isPropertyAccessExpression(node) && ts$1.isIdentifier(node.expression) && node.expression.text === element.name.text) members.add(`.${node.name.text}`);
|
|
13282
|
+
ts$1.forEachChild(node, visit);
|
|
13283
|
+
};
|
|
13284
|
+
visit(sourceFile);
|
|
13285
|
+
for (const member of members) {
|
|
13286
|
+
const binding = resolveExportedStaticValue(importedDocument, `${importedName}${member}`, resolver, /* @__PURE__ */ new Set());
|
|
13287
|
+
const symbol = `${element.name.text}${member}`;
|
|
13288
|
+
if (binding) bindings.set(symbol, {
|
|
13289
|
+
...binding,
|
|
13290
|
+
symbol
|
|
13291
|
+
});
|
|
13292
|
+
}
|
|
13245
13293
|
}
|
|
13246
13294
|
}
|
|
13247
13295
|
}
|
|
@@ -13254,15 +13302,21 @@ function resolveExportedStaticValue(document, exportName, resolver, visited) {
|
|
|
13254
13302
|
sourceFileUris.set(sourceFile, document.uri);
|
|
13255
13303
|
const localBindings = collectStaticValueBindings(sourceFile);
|
|
13256
13304
|
const localBinding = localBindings.get(exportName);
|
|
13257
|
-
|
|
13305
|
+
const [exportedSymbol] = exportName.split(".");
|
|
13306
|
+
const memberSuffix = exportName.slice(exportedSymbol.length);
|
|
13307
|
+
if (localBinding && sourceFile.statements.some((statement) => {
|
|
13308
|
+
if (!ts$1.isVariableStatement(statement) && !ts$1.isEnumDeclaration(statement)) return false;
|
|
13309
|
+
if (!statement.modifiers?.some((modifier) => modifier.kind === ts$1.SyntaxKind.ExportKeyword)) return false;
|
|
13310
|
+
return ts$1.isEnumDeclaration(statement) ? statement.name.text === exportedSymbol : statement.declarationList.declarations.some((declaration) => ts$1.isIdentifier(declaration.name) && declaration.name.text === exportName);
|
|
13311
|
+
})) return localBinding;
|
|
13258
13312
|
const exports = sourceFile.statements.filter(ts$1.isExportDeclaration);
|
|
13259
13313
|
for (const statement of exports) {
|
|
13260
13314
|
if (!statement.exportClause || !ts$1.isNamedExports(statement.exportClause)) continue;
|
|
13261
13315
|
const specifier = statement.moduleSpecifier && ts$1.isStringLiteral(statement.moduleSpecifier) ? statement.moduleSpecifier.text : null;
|
|
13262
13316
|
const exportedDocument = specifier?.startsWith(".") ? resolver.resolveImport(document, specifier) : null;
|
|
13263
13317
|
for (const element of statement.exportClause.elements) {
|
|
13264
|
-
if (element.name.text !==
|
|
13265
|
-
const localName = element.propertyName?.text ?? element.name.text
|
|
13318
|
+
if (element.name.text !== exportedSymbol) continue;
|
|
13319
|
+
const localName = `${element.propertyName?.text ?? element.name.text}${memberSuffix}`;
|
|
13266
13320
|
if (exportedDocument) {
|
|
13267
13321
|
const binding = resolveExportedStaticValue(exportedDocument, localName, resolver, visited);
|
|
13268
13322
|
return binding && {
|
|
@@ -13298,15 +13352,17 @@ function resolveExportedStaticValue(document, exportName, resolver, visited) {
|
|
|
13298
13352
|
}
|
|
13299
13353
|
}
|
|
13300
13354
|
function resolveImportedStaticValue(sourceFile, document, localName, resolver, visited) {
|
|
13355
|
+
const [localSymbol] = localName.split(".");
|
|
13356
|
+
const memberSuffix = localName.slice(localSymbol.length);
|
|
13301
13357
|
for (const statement of sourceFile.statements) {
|
|
13302
13358
|
if (!ts$1.isImportDeclaration(statement) || !ts$1.isStringLiteral(statement.moduleSpecifier) || !statement.moduleSpecifier.text.startsWith(".")) continue;
|
|
13303
13359
|
const namedBindings = statement.importClause?.namedBindings;
|
|
13304
13360
|
if (!namedBindings || !ts$1.isNamedImports(namedBindings)) continue;
|
|
13305
|
-
const imported = namedBindings.elements.find((element) => element.name.text ===
|
|
13361
|
+
const imported = namedBindings.elements.find((element) => element.name.text === localSymbol);
|
|
13306
13362
|
if (!imported) continue;
|
|
13307
13363
|
const importedDocument = resolver.resolveImport(document, statement.moduleSpecifier.text);
|
|
13308
13364
|
if (!importedDocument) return null;
|
|
13309
|
-
return resolveExportedStaticValue(importedDocument, imported.propertyName?.text ?? imported.name.text
|
|
13365
|
+
return resolveExportedStaticValue(importedDocument, `${imported.propertyName?.text ?? imported.name.text}${memberSuffix}`, resolver, visited);
|
|
13310
13366
|
}
|
|
13311
13367
|
return null;
|
|
13312
13368
|
}
|
|
@@ -14195,8 +14251,9 @@ async function applyMachineToSourceDocuments(machineConfig, document, options =
|
|
|
14195
14251
|
let semanticReplacements = semanticSplit?.replacements ?? [];
|
|
14196
14252
|
if (activePatches.length === 0) return finalize(semanticReplacements);
|
|
14197
14253
|
const transitionSplit = await tryCreateTransitionPatchSplitForDocuments(document, sourceFile, machineConfigNode, machineConfig, activePatches, prevGraph, nextGraph, activeSourceLocations, options.openTextDocument);
|
|
14198
|
-
|
|
14199
|
-
if (transitionSplit
|
|
14254
|
+
const transitionReplacements = transitionSplit ? combineSemanticAndTransitionReplacements(semanticReplacements, transitionSplit.replacements) : semanticReplacements;
|
|
14255
|
+
if (transitionSplit && transitionSplit.remainingPatches.length === 0) return finalize(transitionReplacements);
|
|
14256
|
+
if (transitionSplit) semanticReplacements = transitionReplacements;
|
|
14200
14257
|
const implementationSplit = tryCreateImplementationPatchSplit(document, sourceFile, transitionSplit?.remainingPatches ?? activePatches, nextGraph, options.machineIndex);
|
|
14201
14258
|
if (implementationSplit && implementationSplit.remainingPatches.length === 0) return finalize([...semanticReplacements, ...implementationSplit.replacements]);
|
|
14202
14259
|
if (implementationSplit) semanticReplacements = [...semanticReplacements, ...implementationSplit.replacements];
|
|
@@ -14673,7 +14730,17 @@ async function createTransitionReplacementForDocuments(document, sourceFile, mac
|
|
|
14673
14730
|
if (transitionSource && transitionTarget.previousEventType === transitionTarget.eventType) return [createPropertyValueReplacement(targetDocument, targetSourceFile, transitionSource.eventProperty, nextTransitionValue)];
|
|
14674
14731
|
if (transitionSource) return [createPropertyAssignmentReplacement(targetDocument, targetSourceFile, transitionSource.eventProperty, transitionTarget.eventType, nextTransitionValue)];
|
|
14675
14732
|
const onObject = getObjectLiteralProperty(stateObject, "on");
|
|
14676
|
-
if (onObject)
|
|
14733
|
+
if (onObject) {
|
|
14734
|
+
const nextOn = getStateConfigByPath(machineConfig, transitionTarget.sourcePath)?.on;
|
|
14735
|
+
if (isMachineConfig(nextOn) && !onObject.properties.some((property) => {
|
|
14736
|
+
const key = property.name && getPropertyNameText$2(property.name);
|
|
14737
|
+
return !key || nextOn[key] !== void 0;
|
|
14738
|
+
})) return [createObjectLiteralPropertiesInsertion(targetDocument, targetSourceFile, onObject, [{
|
|
14739
|
+
key: transitionTarget.eventType,
|
|
14740
|
+
config: nextTransitionValue
|
|
14741
|
+
}], false)];
|
|
14742
|
+
return createObjectLiteralPropertyInsertion(targetDocument, targetSourceFile, onObject, transitionTarget.eventType, nextTransitionValue);
|
|
14743
|
+
}
|
|
14677
14744
|
return createObjectLiteralPropertyInsertion(targetDocument, targetSourceFile, stateObject, "on", { [transitionTarget.eventType]: nextTransitionValue });
|
|
14678
14745
|
}
|
|
14679
14746
|
async function createV6BranchActionNameReplacementForDocuments(document, sourceFile, machineConfigNode, patch, transitionTarget, prevGraph, nextGraph, sourceLocations, openTextDocument) {
|
|
@@ -14820,7 +14887,10 @@ async function createStatePropertiesReplacementForDocuments(document, sourceFile
|
|
|
14820
14887
|
config: nextSlotValue
|
|
14821
14888
|
});
|
|
14822
14889
|
}
|
|
14823
|
-
if (insertedSlots.length > 0) replacements.push(createObjectLiteralPropertiesInsertion(targetDocument, targetSourceFile, existingMap, insertedSlots)
|
|
14890
|
+
if (insertedSlots.length > 0) replacements.push(createObjectLiteralPropertiesInsertion(targetDocument, targetSourceFile, existingMap, insertedSlots, existingMap.properties.some((property) => {
|
|
14891
|
+
const key = property.name && getPropertyNameText$2(property.name);
|
|
14892
|
+
return !key || !affectedSlots.has(key) || nextValue[key] !== void 0;
|
|
14893
|
+
})));
|
|
14824
14894
|
continue;
|
|
14825
14895
|
}
|
|
14826
14896
|
}
|
|
@@ -15499,7 +15569,7 @@ function createStateMembershipInitialReplacements(document, sourceFile, parentOb
|
|
|
15499
15569
|
config: nextInitial
|
|
15500
15570
|
}])];
|
|
15501
15571
|
}
|
|
15502
|
-
function createObjectLiteralPropertiesInsertion(document, sourceFile, objectLiteral, entries) {
|
|
15572
|
+
function createObjectLiteralPropertiesInsertion(document, sourceFile, objectLiteral, entries, hasRetainedProperties = objectLiteral.properties.length > 0) {
|
|
15503
15573
|
const formatting = getFormattingContext(document, sourceFile, objectLiteral);
|
|
15504
15574
|
const lineSeparator = formatting.newLineKind === ts$1.NewLineKind.CarriageReturnLineFeed ? "\r\n" : "\n";
|
|
15505
15575
|
const propertyTexts = entries.map((entry) => printObjectLiteralProperty(entry.key, entry.config, sourceFile, formatting));
|
|
@@ -15508,7 +15578,7 @@ function createObjectLiteralPropertiesInsertion(document, sourceFile, objectLite
|
|
|
15508
15578
|
const startOffset = existingProperties.length === 0 ? closeBraceOffset : existingProperties[existingProperties.length - 1].getEnd();
|
|
15509
15579
|
const start = document.positionAt(startOffset);
|
|
15510
15580
|
const end = document.positionAt(closeBraceOffset);
|
|
15511
|
-
const prefix =
|
|
15581
|
+
const prefix = hasRetainedProperties ? `,${lineSeparator}` : lineSeparator;
|
|
15512
15582
|
const suffix = `${lineSeparator}${formatting.baseIndent}`;
|
|
15513
15583
|
return {
|
|
15514
15584
|
uri: getDocumentUri(document),
|
|
@@ -16219,8 +16289,8 @@ function createStateKeyRenameReplacementsForTarget(document, sourceFile, parentO
|
|
|
16219
16289
|
}
|
|
16220
16290
|
const supportedScope = new Set([rename.parentPath.join("."), ...getDirectChildStatePaths(nodeKind === "statesObject" ? initialOwnerObject : parentObject, rename.parentPath).map((path) => path.join("."))]);
|
|
16221
16291
|
for (const target of targetLiterals) {
|
|
16222
|
-
if (!referencesRenamedState(target.
|
|
16223
|
-
if (!referencesRenamedAbsoluteState(target.
|
|
16292
|
+
if (!referencesRenamedState(target.value, rename)) continue;
|
|
16293
|
+
if (!referencesRenamedAbsoluteState(target.value, rename)) {
|
|
16224
16294
|
const initialSourcePaths = target.initialSourcePaths ?? [];
|
|
16225
16295
|
if (initialSourcePaths.length > 0) {
|
|
16226
16296
|
if (!target.sourcePaths.every((sourcePath) => arePathsEqual(sourcePath, rename.parentPath))) {
|
|
@@ -16232,7 +16302,7 @@ function createStateKeyRenameReplacementsForTarget(document, sourceFile, parentO
|
|
|
16232
16302
|
if (!(sourcePath.length === rename.parentPath.length || arePathsEqual(sourcePath.slice(0, -1), rename.parentPath)) || !supportedScope.has(sourceKey)) return null;
|
|
16233
16303
|
}
|
|
16234
16304
|
}
|
|
16235
|
-
const replacement = createStringLiteralReplacement(target.document, target.sourceFile, target.node, renameStateReference(target.
|
|
16305
|
+
const replacement = createStringLiteralReplacement(target.document, target.sourceFile, target.node, renameStateReference(target.value, rename));
|
|
16236
16306
|
replacements.push(replacement);
|
|
16237
16307
|
}
|
|
16238
16308
|
return replacements;
|
|
@@ -16367,21 +16437,25 @@ function getDirectChildStatePaths(stateObject, parentPath) {
|
|
|
16367
16437
|
return [[...parentPath, key]];
|
|
16368
16438
|
});
|
|
16369
16439
|
}
|
|
16370
|
-
function collectTargetStringLiterals(machineConfigNode) {
|
|
16440
|
+
function collectTargetStringLiterals(machineConfigNode, sourceLocations, documentUri) {
|
|
16371
16441
|
const literals = [];
|
|
16372
|
-
const bindings = collectTopLevelExpressionBindings(machineConfigNode.getSourceFile());
|
|
16442
|
+
const bindings = collectTopLevelExpressionBindings(machineConfigNode.getSourceFile(), sourceLocations, documentUri);
|
|
16373
16443
|
const visitStateObject = (stateObject, sourcePath) => {
|
|
16374
16444
|
collectInitialTargetStringLiterals(stateObject, sourcePath, literals, bindings);
|
|
16375
16445
|
for (const propertyName of [
|
|
16376
16446
|
"always",
|
|
16377
16447
|
"after",
|
|
16378
16448
|
"on",
|
|
16379
|
-
"onDone"
|
|
16449
|
+
"onDone",
|
|
16450
|
+
"onError",
|
|
16451
|
+
"onTimeout",
|
|
16452
|
+
"choice"
|
|
16380
16453
|
]) {
|
|
16381
16454
|
const property = getPropertyAssignment(stateObject, propertyName);
|
|
16382
16455
|
if (!property) continue;
|
|
16383
16456
|
collectTargetStringLiteralsFromExpression(property.initializer, sourcePath, literals, bindings);
|
|
16384
16457
|
}
|
|
16458
|
+
collectInvokeTargetStringLiterals(stateObject, sourcePath, literals, bindings);
|
|
16385
16459
|
const statesObject = getObjectLiteralProperty(stateObject, "states");
|
|
16386
16460
|
if (!statesObject) return;
|
|
16387
16461
|
for (const property of statesObject.properties) {
|
|
@@ -16402,11 +16476,11 @@ function collectInitialTargetStringLiterals(stateObject, sourcePath, literals, b
|
|
|
16402
16476
|
if (ts$1.isObjectLiteralExpression(initializer)) {
|
|
16403
16477
|
const initialLiterals = [];
|
|
16404
16478
|
collectTargetStringLiteralsFromExpression(initializer, sourcePath, initialLiterals, bindings);
|
|
16405
|
-
for (const literal of initialLiterals) for (const literalSourcePath of literal.sourcePaths) addTargetLiteral(literals, literal.node, literalSourcePath, true);
|
|
16479
|
+
for (const literal of initialLiterals) for (const literalSourcePath of literal.sourcePaths) addTargetLiteral(literals, literal.node, literalSourcePath, true, literal.value);
|
|
16406
16480
|
}
|
|
16407
16481
|
}
|
|
16408
16482
|
async function collectMappedTargetStringLiterals(rootDocument, rootSourceFile, machineConfigNode, sourceLocations, openTextDocument) {
|
|
16409
|
-
const literals = collectTargetStringLiterals(machineConfigNode).map((target) => ({
|
|
16483
|
+
const literals = collectTargetStringLiterals(machineConfigNode, sourceLocations, getDocumentUri(rootDocument)).map((target) => ({
|
|
16410
16484
|
...target,
|
|
16411
16485
|
document: rootDocument,
|
|
16412
16486
|
sourceFile: rootSourceFile
|
|
@@ -16421,7 +16495,7 @@ async function collectMappedTargetStringLiterals(rootDocument, rootSourceFile, m
|
|
|
16421
16495
|
const stateObject = findObjectLiteralByRange(targetSourceFile, location.range);
|
|
16422
16496
|
if (!stateObject) continue;
|
|
16423
16497
|
const stateLiterals = [];
|
|
16424
|
-
collectTargetStringLiteralsFromStateObject(stateObject, location.path, stateLiterals, collectTopLevelExpressionBindings(targetSourceFile));
|
|
16498
|
+
collectTargetStringLiteralsFromStateObject(stateObject, location.path, stateLiterals, collectTopLevelExpressionBindings(targetSourceFile, sourceLocations, getDocumentUri(targetDocument)));
|
|
16425
16499
|
for (const target of stateLiterals) {
|
|
16426
16500
|
const key = getTargetLiteralReplacementKey(targetDocument, targetSourceFile, target.node);
|
|
16427
16501
|
if (seen.has(key)) {
|
|
@@ -16472,7 +16546,7 @@ async function collectMappedTargetStringLiterals(rootDocument, rootSourceFile, m
|
|
|
16472
16546
|
}
|
|
16473
16547
|
}
|
|
16474
16548
|
const functionLiterals = [];
|
|
16475
|
-
const bindings = collectTopLevelExpressionBindings(targetSourceFile);
|
|
16549
|
+
const bindings = collectTopLevelExpressionBindings(targetSourceFile, sourceLocations, getDocumentUri(targetDocument));
|
|
16476
16550
|
for (const sourcePath of location.sourcePaths) collectTargetStringLiteralsFromFunction(fn, sourcePath, functionLiterals, bindings, new Set([location.symbol]));
|
|
16477
16551
|
for (const target of functionLiterals) {
|
|
16478
16552
|
const key = getTargetLiteralReplacementKey(targetDocument, targetSourceFile, target.node);
|
|
@@ -16558,7 +16632,10 @@ function collectTransitionCallArgumentLiterals(machineConfigNode, symbol, target
|
|
|
16558
16632
|
"always",
|
|
16559
16633
|
"after",
|
|
16560
16634
|
"on",
|
|
16561
|
-
"onDone"
|
|
16635
|
+
"onDone",
|
|
16636
|
+
"onError",
|
|
16637
|
+
"onTimeout",
|
|
16638
|
+
"choice"
|
|
16562
16639
|
]) {
|
|
16563
16640
|
const property = getPropertyAssignment(stateObject, propertyName);
|
|
16564
16641
|
if (property) visitExpression(property.initializer, sourcePath);
|
|
@@ -16584,12 +16661,16 @@ function collectTargetStringLiteralsFromStateObject(stateObject, sourcePath, lit
|
|
|
16584
16661
|
"always",
|
|
16585
16662
|
"after",
|
|
16586
16663
|
"on",
|
|
16587
|
-
"onDone"
|
|
16664
|
+
"onDone",
|
|
16665
|
+
"onError",
|
|
16666
|
+
"onTimeout",
|
|
16667
|
+
"choice"
|
|
16588
16668
|
]) {
|
|
16589
16669
|
const property = getPropertyAssignment(stateObject, propertyName);
|
|
16590
16670
|
if (!property) continue;
|
|
16591
16671
|
collectTargetStringLiteralsFromExpression(property.initializer, sourcePath, literals, bindings);
|
|
16592
16672
|
}
|
|
16673
|
+
collectInvokeTargetStringLiterals(stateObject, sourcePath, literals, bindings);
|
|
16593
16674
|
const statesObject = getObjectLiteralProperty(stateObject, "states");
|
|
16594
16675
|
if (!statesObject) return;
|
|
16595
16676
|
for (const property of statesObject.properties) {
|
|
@@ -16600,8 +16681,35 @@ function collectTargetStringLiteralsFromStateObject(stateObject, sourcePath, lit
|
|
|
16600
16681
|
collectTargetStringLiteralsFromStateObject(childState, [...sourcePath, key], literals, bindings);
|
|
16601
16682
|
}
|
|
16602
16683
|
}
|
|
16684
|
+
function collectInvokeTargetStringLiterals(stateObject, sourcePath, literals, bindings) {
|
|
16685
|
+
const invoke = getPropertyAssignment(stateObject, "invoke");
|
|
16686
|
+
if (!invoke) return;
|
|
16687
|
+
const visit = (expression, seen = /* @__PURE__ */ new Set()) => {
|
|
16688
|
+
const current = unwrapExpression$2(expression);
|
|
16689
|
+
if (ts$1.isIdentifier(current)) {
|
|
16690
|
+
const binding = bindings.get(current.text);
|
|
16691
|
+
if (binding && ts$1.isExpression(binding) && !seen.has(current.text)) visit(binding, new Set([...seen, current.text]));
|
|
16692
|
+
} else if (ts$1.isArrayLiteralExpression(current)) {
|
|
16693
|
+
for (const item of current.elements) if (ts$1.isExpression(item)) visit(item, seen);
|
|
16694
|
+
} else if (ts$1.isObjectLiteralExpression(current)) for (const name of [
|
|
16695
|
+
"onDone",
|
|
16696
|
+
"onError",
|
|
16697
|
+
"onSnapshot",
|
|
16698
|
+
"onTimeout"
|
|
16699
|
+
]) {
|
|
16700
|
+
const property = getPropertyAssignment(current, name);
|
|
16701
|
+
if (property) collectTargetStringLiteralsFromExpression(property.initializer, sourcePath, literals, bindings);
|
|
16702
|
+
}
|
|
16703
|
+
};
|
|
16704
|
+
visit(invoke.initializer);
|
|
16705
|
+
}
|
|
16603
16706
|
function collectTargetStringLiteralsFromExpression(expression, sourcePath, literals, bindings, seenBindings = /* @__PURE__ */ new Set()) {
|
|
16604
16707
|
const current = unwrapExpression$2(expression);
|
|
16708
|
+
const staticTarget = bindings.staticTargets?.get(`${current.getStart()}:${current.getEnd()}`);
|
|
16709
|
+
if (staticTarget !== void 0 && (ts$1.isIdentifier(current) || ts$1.isPropertyAccessExpression(current))) {
|
|
16710
|
+
addTargetLiteral(literals, current, sourcePath, false, staticTarget);
|
|
16711
|
+
return;
|
|
16712
|
+
}
|
|
16605
16713
|
if (ts$1.isStringLiteralLike(current)) {
|
|
16606
16714
|
addTargetLiteral(literals, current, sourcePath);
|
|
16607
16715
|
return;
|
|
@@ -16624,6 +16732,7 @@ function collectTargetStringLiteralsFromExpression(expression, sourcePath, liter
|
|
|
16624
16732
|
const binding = bindings.get(current.expression.text);
|
|
16625
16733
|
if (binding && isTransitionFunctionBinding(binding)) {
|
|
16626
16734
|
const scopedBindings = new Map(bindings);
|
|
16735
|
+
scopedBindings.staticTargets = bindings.staticTargets;
|
|
16627
16736
|
for (const [index, parameter] of binding.parameters.entries()) {
|
|
16628
16737
|
if (!ts$1.isIdentifier(parameter.name)) continue;
|
|
16629
16738
|
const argument = current.arguments[index];
|
|
@@ -16686,8 +16795,9 @@ function collectTargetStringLiteralsFromFunction(fn, sourcePath, literals, bindi
|
|
|
16686
16795
|
}
|
|
16687
16796
|
collectTargetStringLiteralsFromExpression(fn.body, sourcePath, literals, bindings, seenBindings);
|
|
16688
16797
|
}
|
|
16689
|
-
function collectTopLevelExpressionBindings(sourceFile) {
|
|
16798
|
+
function collectTopLevelExpressionBindings(sourceFile, sourceLocations, documentUri) {
|
|
16690
16799
|
const bindings = /* @__PURE__ */ new Map();
|
|
16800
|
+
bindings.staticTargets = new Map((sourceLocations?.staticValues ?? []).filter((location) => location.definitionUri && location.uri === documentUri).map((location) => [`${offsetAtRangePosition(sourceFile.text, location.range.startLine, location.range.startChar)}:${offsetAtRangePosition(sourceFile.text, location.range.endLine, location.range.endChar)}`, location.value]));
|
|
16691
16801
|
for (const statement of sourceFile.statements) {
|
|
16692
16802
|
if (ts$1.isFunctionDeclaration(statement) && statement.name) {
|
|
16693
16803
|
bindings.set(statement.name.text, statement);
|
|
@@ -16698,7 +16808,7 @@ function collectTopLevelExpressionBindings(sourceFile) {
|
|
|
16698
16808
|
}
|
|
16699
16809
|
return bindings;
|
|
16700
16810
|
}
|
|
16701
|
-
function addTargetLiteral(literals, node, sourcePath, isInitialTarget = false) {
|
|
16811
|
+
function addTargetLiteral(literals, node, sourcePath, isInitialTarget = false, value = node.text) {
|
|
16702
16812
|
const existing = literals.find((literal) => literal.node.getStart() === node.getStart() && literal.node.getEnd() === node.getEnd());
|
|
16703
16813
|
if (existing) {
|
|
16704
16814
|
mergeTargetSourcePaths(existing, [sourcePath]);
|
|
@@ -16707,6 +16817,7 @@ function addTargetLiteral(literals, node, sourcePath, isInitialTarget = false) {
|
|
|
16707
16817
|
}
|
|
16708
16818
|
literals.push({
|
|
16709
16819
|
node,
|
|
16820
|
+
value,
|
|
16710
16821
|
sourcePaths: [sourcePath],
|
|
16711
16822
|
...isInitialTarget ? { initialSourcePaths: [sourcePath] } : {}
|
|
16712
16823
|
});
|
|
@@ -16877,6 +16988,10 @@ function compareReplacementRangesDescending(a, b) {
|
|
|
16877
16988
|
function normalizeOverlappingReplacements(replacements) {
|
|
16878
16989
|
return planTextReplacements(replacements);
|
|
16879
16990
|
}
|
|
16991
|
+
function combineSemanticAndTransitionReplacements(semantic, transitions) {
|
|
16992
|
+
const compare = (leftLine, leftChar, rightLine, rightChar) => leftLine - rightLine || leftChar - rightChar;
|
|
16993
|
+
return [...semantic.filter((focused) => !transitions.some((owner) => owner.uri === focused.uri && compare(focused.range.startLine, focused.range.startChar, owner.range.startLine, owner.range.startChar) > 0 && compare(focused.range.endLine, focused.range.endChar, owner.range.endLine, owner.range.endChar) <= 0)), ...transitions];
|
|
16994
|
+
}
|
|
16880
16995
|
function appendWholeStateReplacement(replacements, wholeState) {
|
|
16881
16996
|
const compare = (leftLine, leftChar, rightLine, rightChar) => leftLine - rightLine || leftChar - rightChar;
|
|
16882
16997
|
for (let index = replacements.length - 1; index >= 0; index--) {
|
|
@@ -17821,7 +17936,7 @@ function diagnosticKey$1(diagnostic) {
|
|
|
17821
17936
|
}
|
|
17822
17937
|
|
|
17823
17938
|
//#endregion
|
|
17824
|
-
//#region ../editor-sync/dist/localBackend-
|
|
17939
|
+
//#region ../editor-sync/dist/localBackend-rcokEw-A.mjs
|
|
17825
17940
|
var LocalEditorSyncBackend = class {
|
|
17826
17941
|
constructor(access) {
|
|
17827
17942
|
this.access = access;
|
|
@@ -17960,7 +18075,7 @@ function toFileName(uriOrPath) {
|
|
|
17960
18075
|
}
|
|
17961
18076
|
|
|
17962
18077
|
//#endregion
|
|
17963
|
-
//#region ../editor-sync/dist/pushMerge-
|
|
18078
|
+
//#region ../editor-sync/dist/pushMerge-piN5M1Ej.mjs
|
|
17964
18079
|
const GEOMETRY_KEYS = [
|
|
17965
18080
|
"x",
|
|
17966
18081
|
"y",
|
|
@@ -17977,6 +18092,36 @@ const DEFAULT_ANNOTATION_SIZE = {
|
|
|
17977
18092
|
};
|
|
17978
18093
|
const NEW_NODE_GAP = 80;
|
|
17979
18094
|
const MAX_CONCURRENT_MERGE_ATTEMPTS = 3;
|
|
18095
|
+
/** Match presentation events independently of converter-specific entity IDs. */
|
|
18096
|
+
function presentationMatchingGraph(graph) {
|
|
18097
|
+
const nodes = new Map(graph.nodes.map((node) => [node.id, node]));
|
|
18098
|
+
return {
|
|
18099
|
+
...graph,
|
|
18100
|
+
edges: graph.edges.map((edge) => {
|
|
18101
|
+
let eventType = edge.data.eventType;
|
|
18102
|
+
if (typeof eventType !== "string") return edge;
|
|
18103
|
+
const sourceSuffix = `.${edge.sourceId}`;
|
|
18104
|
+
if (eventType.startsWith("xstate.after.") && eventType.endsWith(sourceSuffix)) eventType = eventType.slice(0, -sourceSuffix.length);
|
|
18105
|
+
else if (/^(?:@statelyai?\.state\.done\.|xstate\.done\.state(?:\.|$))/.test(eventType)) eventType = "xstate.done.state";
|
|
18106
|
+
else {
|
|
18107
|
+
const ref = /^@statelyai?\.invoke\.(done|error|snapshot|timeout)\.(.+)$/.exec(eventType);
|
|
18108
|
+
const literal = /^xstate\.(done|error|snapshot|timeout)\.actor\.(.+)$/.exec(eventType);
|
|
18109
|
+
const match = ref ?? literal;
|
|
18110
|
+
if (match) {
|
|
18111
|
+
const index = (nodes.get(edge.sourceId)?.data?.invokes ?? []).findIndex((invoke) => invoke.id === match[2] || "invocationId" in invoke && invoke.invocationId === match[2]);
|
|
18112
|
+
if (index >= 0) eventType = `@presentation.invoke.${match[1]}.${index}`;
|
|
18113
|
+
}
|
|
18114
|
+
}
|
|
18115
|
+
return {
|
|
18116
|
+
...edge,
|
|
18117
|
+
data: {
|
|
18118
|
+
...edge.data,
|
|
18119
|
+
eventType
|
|
18120
|
+
}
|
|
18121
|
+
};
|
|
18122
|
+
})
|
|
18123
|
+
};
|
|
18124
|
+
}
|
|
17980
18125
|
function indexBySemanticId(normalized, original) {
|
|
17981
18126
|
const bySemanticId = /* @__PURE__ */ new Map();
|
|
17982
18127
|
normalized.forEach((entity, index) => {
|
|
@@ -18014,6 +18159,7 @@ function restoreEdgeFields(edges, remoteEdgesById, remoteEdgeIdByLocalId) {
|
|
|
18014
18159
|
const remote = remoteId ? remoteEdgesById.get(remoteId) : void 0;
|
|
18015
18160
|
if (remote) {
|
|
18016
18161
|
if (remote.uniqueId !== void 0) edge.uniqueId = remote.uniqueId;
|
|
18162
|
+
edge.data.eventTypeData = structuredClone(remote.data.eventTypeData);
|
|
18017
18163
|
if (remote.data.assets !== void 0) edge.data.assets = structuredClone(remote.data.assets);
|
|
18018
18164
|
}
|
|
18019
18165
|
}
|
|
@@ -18058,7 +18204,7 @@ function mergePresentationIntoRemoteDefinition(editedDefinition, remoteDefinitio
|
|
|
18058
18204
|
remoteGraph.nodes = remoteGraph.nodes.filter((node) => !remoteAnnotationIds.has(node.id));
|
|
18059
18205
|
editedGraph.edges = editedGraph.edges.filter((edge) => !editedAnnotationIds.has(edge.sourceId) && !editedAnnotationIds.has(edge.targetId));
|
|
18060
18206
|
remoteGraph.edges = remoteGraph.edges.filter((edge) => !remoteAnnotationIds.has(edge.sourceId) && !remoteAnnotationIds.has(edge.targetId));
|
|
18061
|
-
const { base, compare } = diffGraphsSemantically(remoteGraph, editedGraph);
|
|
18207
|
+
const { base, compare } = diffGraphsSemantically(presentationMatchingGraph(remoteGraph), presentationMatchingGraph(editedGraph));
|
|
18062
18208
|
const remoteNodesBySemanticId = indexBySemanticId(base.nodes, remoteGraph.nodes);
|
|
18063
18209
|
const editedNodesBySemanticId = indexBySemanticId(compare.nodes, editedGraph.nodes);
|
|
18064
18210
|
const remoteEdgesBySemanticId = indexBySemanticId(base.edges, remoteGraph.edges);
|
|
@@ -18067,6 +18213,7 @@ function mergePresentationIntoRemoteDefinition(editedDefinition, remoteDefinitio
|
|
|
18067
18213
|
const mergedNodesById = collectDigraphNodes(merged.rootNode, /* @__PURE__ */ new Map());
|
|
18068
18214
|
const editedNodesById = collectDigraphNodes(editedDefinition.rootNode, /* @__PURE__ */ new Map());
|
|
18069
18215
|
const editedNodeIdToRemoteNodeId = /* @__PURE__ */ new Map();
|
|
18216
|
+
const editedEdgeIdToRemoteEdgeId = /* @__PURE__ */ new Map();
|
|
18070
18217
|
for (const [semanticId, remoteNode] of remoteNodesBySemanticId) {
|
|
18071
18218
|
const editedNode = editedNodesBySemanticId.get(semanticId);
|
|
18072
18219
|
const target = mergedNodesById.get(remoteNode.id);
|
|
@@ -18089,6 +18236,7 @@ function mergePresentationIntoRemoteDefinition(editedDefinition, remoteDefinitio
|
|
|
18089
18236
|
const target = mergedEdgesById.get(remoteEdge.id);
|
|
18090
18237
|
const source = editedEdge ? editedEdgesById.get(editedEdge.id) : void 0;
|
|
18091
18238
|
if (!editedEdge || !target || !source) continue;
|
|
18239
|
+
editedEdgeIdToRemoteEdgeId.set(editedEdge.id, remoteEdge.id);
|
|
18092
18240
|
for (const field of ["position", "size"]) replacePresentationField(target, source, field);
|
|
18093
18241
|
for (const field of ["color", "assets"]) replacePresentationField(target.data, source.data, field);
|
|
18094
18242
|
}
|
|
@@ -18097,7 +18245,10 @@ function mergePresentationIntoRemoteDefinition(editedDefinition, remoteDefinitio
|
|
|
18097
18245
|
collectAnnotations(editedDefinition.rootNode, null, editedAnnotations);
|
|
18098
18246
|
for (const annotation of editedAnnotations) {
|
|
18099
18247
|
const remoteParentId = annotation.parentId ? editedNodeIdToRemoteNodeId.get(annotation.parentId) : merged.rootNode.id;
|
|
18100
|
-
|
|
18248
|
+
const parent = remoteParentId ? mergedNodesById.get(remoteParentId) : void 0;
|
|
18249
|
+
const note = structuredClone(annotation.node);
|
|
18250
|
+
if (Array.isArray(note.data.data?.referenceIds)) note.data.data.referenceIds = note.data.data.referenceIds.map((id) => editedNodeIdToRemoteNodeId.get(id) ?? editedEdgeIdToRemoteEdgeId.get(id) ?? id);
|
|
18251
|
+
parent?.nodes.push(note);
|
|
18101
18252
|
}
|
|
18102
18253
|
return merged;
|
|
18103
18254
|
}
|
|
@@ -18141,7 +18292,7 @@ function mergeLocalGraphIntoRemoteDefinition(localGraph, remoteDefinition) {
|
|
|
18141
18292
|
const remoteGraph = fromStudioMachine(remoteDefinition);
|
|
18142
18293
|
remoteGraph.nodes = remoteGraph.nodes.filter((node) => !annotationIds.has(node.id));
|
|
18143
18294
|
remoteGraph.edges = remoteGraph.edges.filter((edge) => !annotationIds.has(edge.sourceId) && !annotationIds.has(edge.targetId));
|
|
18144
|
-
const { base, compare, summary } = diffGraphsSemantically(remoteGraph, localGraph);
|
|
18295
|
+
const { base, compare, summary } = diffGraphsSemantically(presentationMatchingGraph(remoteGraph), presentationMatchingGraph(localGraph));
|
|
18145
18296
|
const remoteNodesBySemanticId = indexBySemanticId(base.nodes, remoteGraph.nodes);
|
|
18146
18297
|
const remoteEdgesBySemanticId = indexBySemanticId(base.edges, remoteGraph.edges);
|
|
18147
18298
|
const merged = structuredClone(localGraph);
|
|
@@ -18165,7 +18316,10 @@ function mergeLocalGraphIntoRemoteDefinition(localGraph, remoteDefinition) {
|
|
|
18165
18316
|
});
|
|
18166
18317
|
const definition = toStudioMachine(merged);
|
|
18167
18318
|
restoreNodeFields(definition.rootNode, remoteNodesById, remoteNodeIdByLocalId);
|
|
18168
|
-
restoreEdgeFields(definition.edges, new Map(remoteDefinition.edges.map((edge) => [edge.id, edge])),
|
|
18319
|
+
restoreEdgeFields(definition.edges, new Map(remoteDefinition.edges.map((edge) => [edge.id, edge])), new Map(definition.edges.flatMap((edge, index) => {
|
|
18320
|
+
const remoteId = remoteEdgeIdByLocalId.get(merged.edges[index].id);
|
|
18321
|
+
return remoteId ? [[edge.id, remoteId]] : [];
|
|
18322
|
+
})));
|
|
18169
18323
|
ensureCompleteNodeGeometry(definition.rootNode);
|
|
18170
18324
|
return {
|
|
18171
18325
|
definition: {
|
|
@@ -18230,7 +18384,7 @@ async function updateMachineDefinition(client, machineId, localGraph) {
|
|
|
18230
18384
|
}
|
|
18231
18385
|
|
|
18232
18386
|
//#endregion
|
|
18233
|
-
//#region ../editor-sync/dist/presentationMetadata-
|
|
18387
|
+
//#region ../editor-sync/dist/presentationMetadata-YX6iRP4T.mjs
|
|
18234
18388
|
function createStudioPresentationMetadataStore(client, machineId) {
|
|
18235
18389
|
const load = async () => {
|
|
18236
18390
|
return {
|
|
@@ -18249,7 +18403,7 @@ function createStudioPresentationMetadataStore(client, machineId) {
|
|
|
18249
18403
|
},
|
|
18250
18404
|
async persist(_graph, context) {
|
|
18251
18405
|
const serialized = context?.serialized?.digraph;
|
|
18252
|
-
if (!serialized)
|
|
18406
|
+
if (!serialized) throw new Error("Studio presentation requires a serialized digraph. Presentation was not saved.");
|
|
18253
18407
|
const editedDefinition = JSON.parse(serialized);
|
|
18254
18408
|
const latest = await client.machines.get(machineId);
|
|
18255
18409
|
if (!latest.updatedAt) throw new Error(`Studio machine "${machineId}" did not provide an updatedAt guard. Presentation was not saved.`);
|
|
@@ -18310,10 +18464,29 @@ function createLocalPresentationMetadataRepository(file) {
|
|
|
18310
18464
|
};
|
|
18311
18465
|
} };
|
|
18312
18466
|
}
|
|
18313
|
-
function applyPresentationInitializer(initializer, current) {
|
|
18467
|
+
function applyPresentationInitializer(initializer, current, convertStudioDefinition = fromStudioMachine) {
|
|
18314
18468
|
if (initializer.type === "overlay") return applyPresentationMetadata(initializer.overlay, current);
|
|
18315
18469
|
if (!isGraph(current)) return current;
|
|
18316
|
-
|
|
18470
|
+
const presentationGraph = convertStudioDefinition(initializer.definition);
|
|
18471
|
+
if (!isGraph(presentationGraph)) return current;
|
|
18472
|
+
const overlay = createPresentationSnapshot(presentationGraph);
|
|
18473
|
+
const sourceIds = presentationIds(current);
|
|
18474
|
+
const studioIds = presentationIds(presentationGraph);
|
|
18475
|
+
const liveIds = /* @__PURE__ */ new Map();
|
|
18476
|
+
for (const kind of ["nodes", "edges"]) {
|
|
18477
|
+
const bySemanticId = new Map(current[kind].map((entity, index) => [sourceIds[kind][index], entity.id]));
|
|
18478
|
+
presentationGraph[kind].forEach((entity, index) => {
|
|
18479
|
+
const liveId = bySemanticId.get(studioIds[kind][index]);
|
|
18480
|
+
if (typeof liveId === "string") liveIds.set(entity.id, liveId);
|
|
18481
|
+
});
|
|
18482
|
+
}
|
|
18483
|
+
const sourceEntityIds = new Set([...current.nodes, ...current.edges].map((entity) => entity.id));
|
|
18484
|
+
overlay.annotations = (overlay.annotations ?? []).filter((annotation) => annotation.parentId == null || liveIds.has(annotation.parentId));
|
|
18485
|
+
for (const annotation of overlay.annotations) {
|
|
18486
|
+
annotation.parentId = liveIds.get(annotation.parentId) ?? annotation.parentId;
|
|
18487
|
+
if (Array.isArray(annotation.data?.referenceIds)) annotation.data.referenceIds = annotation.data.referenceIds.map((id) => liveIds.get(id) ?? id).filter((id) => sourceEntityIds.has(id));
|
|
18488
|
+
}
|
|
18489
|
+
return applyPresentationMetadata(overlay, current);
|
|
18317
18490
|
}
|
|
18318
18491
|
function applyPresentationMetadata(overlay, current) {
|
|
18319
18492
|
if (!isPresentationOverlay(overlay) || !isGraph(current)) return current;
|
|
@@ -18321,6 +18494,7 @@ function applyPresentationMetadata(overlay, current) {
|
|
|
18321
18494
|
const addedNodes = [];
|
|
18322
18495
|
const addedEdges = [];
|
|
18323
18496
|
const semanticIds = overlay.identity === "semantic-v1" ? presentationIds(result) : void 0;
|
|
18497
|
+
const legacyIds = semanticIds ? presentationIds(result, false) : void 0;
|
|
18324
18498
|
const renamedGuardPresentation = semanticIds ? matchUniqueGuardRenames(semanticIds.edges, overlay.edges ?? {}) : /* @__PURE__ */ new Map();
|
|
18325
18499
|
for (const [index, node] of result.nodes.entries()) {
|
|
18326
18500
|
normalizeCanonicalGeometry(node);
|
|
@@ -18331,7 +18505,7 @@ function applyPresentationMetadata(overlay, current) {
|
|
|
18331
18505
|
for (const [index, edge] of result.edges.entries()) {
|
|
18332
18506
|
normalizeCanonicalGeometry(edge);
|
|
18333
18507
|
const semanticId = semanticIds?.edges[index] ?? edge.id;
|
|
18334
|
-
const presentation = overlay.edges?.[semanticId] ?? renamedGuardPresentation.get(semanticId);
|
|
18508
|
+
const presentation = overlay.edges?.[semanticId] ?? overlay.edges?.[legacyIds?.edges[index] ?? edge.id] ?? renamedGuardPresentation.get(semanticId);
|
|
18335
18509
|
if (presentation) applyEntityPresentation(presentation, edge);
|
|
18336
18510
|
else addedEdges.push(edge);
|
|
18337
18511
|
}
|
|
@@ -18411,6 +18585,7 @@ function entityPresentationMap(entities, includeSourceSide, ids) {
|
|
|
18411
18585
|
const presentation = compactDefined({
|
|
18412
18586
|
...pick(canonicalGeometry(entity), GEOMETRY_FIELDS),
|
|
18413
18587
|
color: clone(entity.data?.color),
|
|
18588
|
+
layout: clone(entity.data?.layout),
|
|
18414
18589
|
assets: clone(entity.data?.assets),
|
|
18415
18590
|
sourceSide: includeSourceSide ? clone(entity.data?.sourceSide) : void 0
|
|
18416
18591
|
});
|
|
@@ -18418,7 +18593,8 @@ function entityPresentationMap(entities, includeSourceSide, ids) {
|
|
|
18418
18593
|
});
|
|
18419
18594
|
return entries.length > 0 ? Object.fromEntries(entries) : void 0;
|
|
18420
18595
|
}
|
|
18421
|
-
function presentationIds(graph) {
|
|
18596
|
+
function presentationIds(graph, canonicalEvents = true) {
|
|
18597
|
+
const matchingGraph = canonicalEvents ? presentationMatchingGraph(graph) : graph;
|
|
18422
18598
|
const normalized = normalizeGraphForSemanticDiff({
|
|
18423
18599
|
id: graph.id ?? "presentation",
|
|
18424
18600
|
nodes: graph.nodes.map((node) => ({
|
|
@@ -18426,7 +18602,7 @@ function presentationIds(graph) {
|
|
|
18426
18602
|
parentId: node.parentId,
|
|
18427
18603
|
data: { key: node.data?.key }
|
|
18428
18604
|
})),
|
|
18429
|
-
edges:
|
|
18605
|
+
edges: matchingGraph.edges.map((edge) => ({
|
|
18430
18606
|
id: edge.id,
|
|
18431
18607
|
sourceId: edge.sourceId,
|
|
18432
18608
|
targetId: edge.targetId,
|
|
@@ -18459,10 +18635,12 @@ function createAnnotationSnapshot(annotations) {
|
|
|
18459
18635
|
parentId: annotation.parentId,
|
|
18460
18636
|
content: clone(annotation.content),
|
|
18461
18637
|
...pick(geometry, GEOMETRY_FIELDS),
|
|
18638
|
+
...pick(annotation, ["width", "height"]),
|
|
18462
18639
|
data: compactDefined({
|
|
18463
18640
|
referenceIds: clone(annotation.data?.referenceIds),
|
|
18464
18641
|
color: clone(annotation.data?.color),
|
|
18465
|
-
textAlign: clone(annotation.data?.textAlign)
|
|
18642
|
+
textAlign: clone(annotation.data?.textAlign),
|
|
18643
|
+
placement: clone(annotation.data?.placement)
|
|
18466
18644
|
})
|
|
18467
18645
|
});
|
|
18468
18646
|
});
|
|
@@ -18481,7 +18659,8 @@ function applyEntityPresentation(presentation, entity) {
|
|
|
18481
18659
|
for (const field of [
|
|
18482
18660
|
"color",
|
|
18483
18661
|
"assets",
|
|
18484
|
-
"sourceSide"
|
|
18662
|
+
"sourceSide",
|
|
18663
|
+
"layout"
|
|
18485
18664
|
]) copyField(presentation, entity.data, field);
|
|
18486
18665
|
}
|
|
18487
18666
|
function placeAddedNodes(added, allNodes) {
|
|
@@ -19004,7 +19183,7 @@ const editorSyncApplyResponseSchema = z$1.object({ replacements: z$1.array(edito
|
|
|
19004
19183
|
const editorSyncAccessResponseSchema = z$1.object({ access: editorSyncAccessSchema });
|
|
19005
19184
|
|
|
19006
19185
|
//#endregion
|
|
19007
|
-
//#region ../editor-sync/dist/host-
|
|
19186
|
+
//#region ../editor-sync/dist/host-Dvy75KWk.mjs
|
|
19008
19187
|
let diagnosticSequence = 0;
|
|
19009
19188
|
function presentationsEqual(first, second) {
|
|
19010
19189
|
return JSON.stringify(createPresentationSnapshot(first)) === JSON.stringify(createPresentationSnapshot(second));
|
|
@@ -19031,6 +19210,12 @@ var EditorSyncError = class extends Error {
|
|
|
19031
19210
|
this.code = code;
|
|
19032
19211
|
}
|
|
19033
19212
|
};
|
|
19213
|
+
function isEditorSyncAuthenticationError(error) {
|
|
19214
|
+
return error instanceof Error && "status" in error && error.status === 401;
|
|
19215
|
+
}
|
|
19216
|
+
function authenticationRecoveryInstructions(recovery) {
|
|
19217
|
+
return recovery.host === "cli" ? "Run `npx statelyai login` in your terminal, then reload the editor." : "In the VS Code Command Palette, run “Stately: Sign In”, then reopen the visual editor.";
|
|
19218
|
+
}
|
|
19034
19219
|
async function fetchEditorSyncAccess(options) {
|
|
19035
19220
|
const fetchImpl = options.fetch ?? globalThis.fetch;
|
|
19036
19221
|
const url = new URL("/api/editor-sync/access", `${options.editorUrl.replace(/\/+$/, "")}/`);
|
|
@@ -19124,12 +19309,14 @@ var EditorHostSession = class {
|
|
|
19124
19309
|
await this.initialize();
|
|
19125
19310
|
} catch (error) {
|
|
19126
19311
|
const message = formatError(error, "Failed to initialize the visual editor.");
|
|
19312
|
+
const recovery = isEditorSyncAuthenticationError(error) ? this.options.authenticationRecovery : void 0;
|
|
19127
19313
|
this.options.send({
|
|
19128
19314
|
type: "@statelyai.error",
|
|
19129
19315
|
code: "initialization_failed",
|
|
19130
|
-
message
|
|
19316
|
+
message,
|
|
19317
|
+
...recovery ? { authenticationRecovery: recovery } : {}
|
|
19131
19318
|
});
|
|
19132
|
-
this.options.showError?.(message);
|
|
19319
|
+
this.options.showError?.(recovery ? `${message}\n${authenticationRecoveryInstructions(recovery)}` : message);
|
|
19133
19320
|
}
|
|
19134
19321
|
break;
|
|
19135
19322
|
case "@statelyai.loaded":
|
|
@@ -19330,7 +19517,7 @@ var EditorHostSession = class {
|
|
|
19330
19517
|
return;
|
|
19331
19518
|
}
|
|
19332
19519
|
const documents = await this.options.source.collectDocuments(sourceLocationUris(this.currentSourceLocations));
|
|
19333
|
-
const serialized = await this.getSerializedPayload();
|
|
19520
|
+
const serialized = await this.getSerializedPayload(message.serialized);
|
|
19334
19521
|
const response = await this.options.sync.apply({
|
|
19335
19522
|
rootUri: this.options.source.rootUri,
|
|
19336
19523
|
rootFileName: this.options.source.rootFileName,
|
|
@@ -19379,7 +19566,7 @@ var EditorHostSession = class {
|
|
|
19379
19566
|
});
|
|
19380
19567
|
}
|
|
19381
19568
|
async acknowledgeWithoutSourceChanges(message, serialized) {
|
|
19382
|
-
await this.persistPresentation(message.graph, serialized ?? await this.getSerializedPayload());
|
|
19569
|
+
await this.persistPresentation(message.graph, serialized ?? await this.getSerializedPayload(message.serialized));
|
|
19383
19570
|
this.currentGraph = message.graph;
|
|
19384
19571
|
this.lastPersistedGraph = message.graph;
|
|
19385
19572
|
this.options.send({
|
|
@@ -19477,11 +19664,12 @@ var EditorHostSession = class {
|
|
|
19477
19664
|
this.watchedSourceUris.clear();
|
|
19478
19665
|
for (const uri of sourceLocationUris(sourceLocations)) if (uri !== this.options.source.rootUri) this.watchedSourceUris.add(uri);
|
|
19479
19666
|
}
|
|
19480
|
-
async getSerializedPayload() {
|
|
19667
|
+
async getSerializedPayload(provided) {
|
|
19481
19668
|
const format = this.currentFormat;
|
|
19482
|
-
|
|
19669
|
+
const formats = [...new Set([...format && format !== "xstate" ? [format] : [], ...this.initialPresentation?.type === "studio" ? ["digraph"] : []])];
|
|
19670
|
+
if (formats.length === 0) return void 0;
|
|
19483
19671
|
try {
|
|
19484
|
-
return
|
|
19672
|
+
return Object.fromEntries(await Promise.all(formats.map(async (format) => [format, provided?.[format] ?? await this.requestSerialized(format)])));
|
|
19485
19673
|
} catch {
|
|
19486
19674
|
return;
|
|
19487
19675
|
}
|
|
@@ -19856,14 +20044,31 @@ async function assertSourceSaveMatchesGraph(input) {
|
|
|
19856
20044
|
const graph = convertMachineToGraph({
|
|
19857
20045
|
machine: parsed.machine,
|
|
19858
20046
|
format,
|
|
19859
|
-
|
|
20047
|
+
profile: input.profile ?? (format === "json" ? input.graph.data?.profile : void 0)
|
|
19860
20048
|
}).graph;
|
|
20049
|
+
if (format === "json" && graph.data.schemas && input.machineConfig?.schemas !== void 0) {
|
|
20050
|
+
const root = graph.nodes.find((node) => !node.parentId);
|
|
20051
|
+
if (root) root.data.schemas = graph.data.schemas;
|
|
20052
|
+
}
|
|
19861
20053
|
return graphToMachineConfig(graph);
|
|
19862
20054
|
};
|
|
19863
20055
|
const expectedConfig = comparableMachineConfig(stripStatelyMetadata(input.machineConfig));
|
|
19864
20056
|
const actualConfig = comparableMachineConfig(stripStatelyMetadata(projectConfig(documents)));
|
|
20057
|
+
const baselineConfig = comparableMachineConfig(stripStatelyMetadata(projectConfig(input.documents)));
|
|
20058
|
+
const schemaEvents = (config) => config?.schemas?.events;
|
|
20059
|
+
const expectedEvents = schemaEvents(expectedConfig);
|
|
20060
|
+
const eventOrigins = input.graph.data?.schemaMeta?.events;
|
|
20061
|
+
let removedAutoEvent = false;
|
|
20062
|
+
for (const [event, origin] of Object.entries(eventOrigins ?? {})) if (origin.origin === "auto" && expectedEvents && JSON.stringify(expectedEvents[event]) === JSON.stringify(comparableMachineConfig({
|
|
20063
|
+
type: "object",
|
|
20064
|
+
properties: {},
|
|
20065
|
+
required: []
|
|
20066
|
+
})) && !Object.hasOwn(schemaEvents(baselineConfig) ?? {}, event) && !Object.hasOwn(schemaEvents(actualConfig) ?? {}, event)) {
|
|
20067
|
+
delete expectedEvents[event];
|
|
20068
|
+
removedAutoEvent = true;
|
|
20069
|
+
}
|
|
20070
|
+
if (removedAutoEvent && expectedEvents && Object.keys(expectedEvents).length === 0) delete expectedConfig.schemas.events;
|
|
19865
20071
|
if (expectedConfig && typeof expectedConfig === "object" && !Array.isArray(expectedConfig) && actualConfig && typeof actualConfig === "object" && !Array.isArray(actualConfig) && !("id" in expectedConfig) && "id" in actualConfig) {
|
|
19866
|
-
const baselineConfig = comparableMachineConfig(stripStatelyMetadata(projectConfig(input.documents)));
|
|
19867
20072
|
if (baselineConfig && typeof baselineConfig === "object" && "id" in baselineConfig && actualConfig.id === baselineConfig.id) delete actualConfig.id;
|
|
19868
20073
|
}
|
|
19869
20074
|
if (JSON.stringify(expectedConfig) !== JSON.stringify(actualConfig)) throw new Error("The updated source does not match the requested machine.");
|
|
@@ -19945,7 +20150,7 @@ function sourceLocationUris(sourceLocations) {
|
|
|
19945
20150
|
|
|
19946
20151
|
//#endregion
|
|
19947
20152
|
//#region src/version.ts
|
|
19948
|
-
const CLI_VERSION = "0.12.
|
|
20153
|
+
const CLI_VERSION = "0.12.3";
|
|
19949
20154
|
|
|
19950
20155
|
//#endregion
|
|
19951
20156
|
//#region src/cliHost.ts
|
|
@@ -19986,11 +20191,21 @@ function rawDataToBuffer(data) {
|
|
|
19986
20191
|
var CliEditorSession = class {
|
|
19987
20192
|
session;
|
|
19988
20193
|
workspaceWatcher;
|
|
20194
|
+
readyMessage;
|
|
20195
|
+
loginPromise;
|
|
20196
|
+
loginController;
|
|
20197
|
+
disposed = false;
|
|
19989
20198
|
constructor(options, sendMessage) {
|
|
19990
20199
|
this.options = options;
|
|
20200
|
+
this.sendMessage = sendMessage;
|
|
20201
|
+
this.workspaceWatcher = createSharedWorkspaceWatcher(options.rootDir);
|
|
20202
|
+
this.session = this.createSession();
|
|
20203
|
+
}
|
|
20204
|
+
createSession() {
|
|
20205
|
+
const options = this.options;
|
|
19991
20206
|
const send = (message) => {
|
|
19992
20207
|
this.log("send", message.type, message);
|
|
19993
|
-
sendMessage(message);
|
|
20208
|
+
this.sendMessage(message);
|
|
19994
20209
|
};
|
|
19995
20210
|
const machines = options.machines ?? [{
|
|
19996
20211
|
id: `${options.rootUri}#0`,
|
|
@@ -20004,8 +20219,7 @@ var CliEditorSession = class {
|
|
|
20004
20219
|
baseUrl: options.studioUrl,
|
|
20005
20220
|
apiKey: options.apiKey
|
|
20006
20221
|
});
|
|
20007
|
-
|
|
20008
|
-
let access;
|
|
20222
|
+
let access = options.access ? Promise.resolve(options.access) : void 0;
|
|
20009
20223
|
const getAccess = () => {
|
|
20010
20224
|
if (!access) {
|
|
20011
20225
|
const request = fetchEditorSyncAccess({
|
|
@@ -20020,7 +20234,11 @@ var CliEditorSession = class {
|
|
|
20020
20234
|
}
|
|
20021
20235
|
return access;
|
|
20022
20236
|
};
|
|
20023
|
-
|
|
20237
|
+
return new EditorHostWorkspaceSession({
|
|
20238
|
+
authenticationRecovery: {
|
|
20239
|
+
host: "cli",
|
|
20240
|
+
canLogin: Boolean(options.onLogin)
|
|
20241
|
+
},
|
|
20024
20242
|
machines: machines.map((machine) => ({
|
|
20025
20243
|
id: machine.id,
|
|
20026
20244
|
name: machine.name,
|
|
@@ -20056,14 +20274,75 @@ var CliEditorSession = class {
|
|
|
20056
20274
|
showError: (message) => console.error(`Stately Editor: ${message}`)
|
|
20057
20275
|
});
|
|
20058
20276
|
}
|
|
20059
|
-
receiveMessage(message) {
|
|
20277
|
+
async receiveMessage(message) {
|
|
20060
20278
|
this.log("recv", message.type, message);
|
|
20279
|
+
if (this.disposed) return;
|
|
20280
|
+
if (message.type === "@statelyai.login") {
|
|
20281
|
+
if (!this.readyMessage || !this.options.onLogin) return;
|
|
20282
|
+
this.loginPromise ??= this.login().finally(() => {
|
|
20283
|
+
this.loginPromise = void 0;
|
|
20284
|
+
});
|
|
20285
|
+
return this.loginPromise;
|
|
20286
|
+
}
|
|
20287
|
+
if (this.loginPromise) {
|
|
20288
|
+
if (message.type !== "@statelyai.ready") return this.loginPromise;
|
|
20289
|
+
this.loginController?.abort();
|
|
20290
|
+
await this.loginPromise;
|
|
20291
|
+
if (this.disposed) return;
|
|
20292
|
+
}
|
|
20293
|
+
if (message.type === "@statelyai.ready") {
|
|
20294
|
+
this.readyMessage = message;
|
|
20295
|
+
try {
|
|
20296
|
+
const apiKey = this.options.getApiKey ? await this.options.getApiKey() : this.options.apiKey;
|
|
20297
|
+
if (this.disposed) return;
|
|
20298
|
+
if (apiKey !== this.options.apiKey) this.replaceCredential(apiKey);
|
|
20299
|
+
} catch (error) {
|
|
20300
|
+
this.reportLoginError(error);
|
|
20301
|
+
return;
|
|
20302
|
+
}
|
|
20303
|
+
}
|
|
20061
20304
|
return this.session.receive(message);
|
|
20062
20305
|
}
|
|
20063
20306
|
dispose() {
|
|
20307
|
+
this.disposed = true;
|
|
20308
|
+
this.loginController?.abort();
|
|
20064
20309
|
this.session.dispose();
|
|
20065
20310
|
this.workspaceWatcher.dispose();
|
|
20066
20311
|
}
|
|
20312
|
+
replaceCredential(apiKey) {
|
|
20313
|
+
this.session.dispose();
|
|
20314
|
+
this.options.apiKey = apiKey;
|
|
20315
|
+
this.options.access = void 0;
|
|
20316
|
+
this.session = this.createSession();
|
|
20317
|
+
}
|
|
20318
|
+
async login() {
|
|
20319
|
+
const controller = new AbortController();
|
|
20320
|
+
this.loginController = controller;
|
|
20321
|
+
try {
|
|
20322
|
+
const apiKey = await this.options.onLogin(controller.signal);
|
|
20323
|
+
if (this.disposed || controller.signal.aborted) return;
|
|
20324
|
+
this.replaceCredential(apiKey);
|
|
20325
|
+
await this.session.receive(this.readyMessage);
|
|
20326
|
+
} catch (error) {
|
|
20327
|
+
if (!this.disposed) this.reportLoginError(error);
|
|
20328
|
+
} finally {
|
|
20329
|
+
this.loginController = void 0;
|
|
20330
|
+
}
|
|
20331
|
+
}
|
|
20332
|
+
reportLoginError(error) {
|
|
20333
|
+
const message = error instanceof Error ? error.message : "Stately login failed. Try again.";
|
|
20334
|
+
const authenticationRecovery = {
|
|
20335
|
+
host: "cli",
|
|
20336
|
+
canLogin: Boolean(this.options.onLogin)
|
|
20337
|
+
};
|
|
20338
|
+
this.sendMessage({
|
|
20339
|
+
type: "@statelyai.error",
|
|
20340
|
+
code: "initialization_failed",
|
|
20341
|
+
message,
|
|
20342
|
+
authenticationRecovery
|
|
20343
|
+
});
|
|
20344
|
+
console.error(`Stately Editor: ${message}\n${authenticationRecoveryInstructions(authenticationRecovery)}`);
|
|
20345
|
+
}
|
|
20067
20346
|
log(direction, type, payload) {
|
|
20068
20347
|
if (this.options.debug) console.error(`[${direction}] ${type}`, redactDebugPayload(payload) ?? "");
|
|
20069
20348
|
}
|
|
@@ -20165,6 +20444,31 @@ function redactDebugPayload(payload) {
|
|
|
20165
20444
|
if (!payload || typeof payload !== "object") return payload;
|
|
20166
20445
|
return Object.fromEntries(Object.entries(payload).map(([key, value]) => [key, /^(?:apiKey|accessToken|refreshToken|token|authorization)$/i.test(key) ? "[REDACTED]" : redactDebugPayload(value)]));
|
|
20167
20446
|
}
|
|
20447
|
+
async function prepareEditorAuthentication(options) {
|
|
20448
|
+
const getAccess = (apiKey) => fetchEditorSyncAccess({
|
|
20449
|
+
editorUrl: options.editorUrl,
|
|
20450
|
+
apiKey,
|
|
20451
|
+
fetch: (input, init) => fetchEditorHost(input instanceof URL ? input : new URL(String(input)), init)
|
|
20452
|
+
});
|
|
20453
|
+
try {
|
|
20454
|
+
return {
|
|
20455
|
+
apiKey: options.apiKey,
|
|
20456
|
+
access: await getAccess(options.apiKey)
|
|
20457
|
+
};
|
|
20458
|
+
} catch (error) {
|
|
20459
|
+
if (!isEditorSyncAuthenticationError(error)) return { apiKey: options.apiKey };
|
|
20460
|
+
console.log("Log in to Stately to open this machine. Complete sign-in in your browser; the editor will open automatically.");
|
|
20461
|
+
const apiKey = await options.onLogin(new AbortController().signal);
|
|
20462
|
+
try {
|
|
20463
|
+
return {
|
|
20464
|
+
apiKey,
|
|
20465
|
+
access: await getAccess(apiKey)
|
|
20466
|
+
};
|
|
20467
|
+
} catch {
|
|
20468
|
+
return { apiKey };
|
|
20469
|
+
}
|
|
20470
|
+
}
|
|
20471
|
+
}
|
|
20168
20472
|
async function openEditor(options) {
|
|
20169
20473
|
const fileName = path$1.resolve(options.fileName);
|
|
20170
20474
|
const machines = (options.machines ?? [{
|
|
@@ -20177,6 +20481,11 @@ async function openEditor(options) {
|
|
|
20177
20481
|
}));
|
|
20178
20482
|
await Promise.all([...new Set(machines.map((machine) => machine.fileName))].map((target) => fsPromises.access(target)));
|
|
20179
20483
|
await assertEditorHostAvailable(options.editorUrl);
|
|
20484
|
+
if (options.shouldOpen && options.onLogin && process.stdin.isTTY && process.stdout.isTTY) Object.assign(options, await prepareEditorAuthentication({
|
|
20485
|
+
editorUrl: options.editorUrl,
|
|
20486
|
+
apiKey: options.apiKey,
|
|
20487
|
+
onLogin: options.onLogin
|
|
20488
|
+
}));
|
|
20180
20489
|
const rootUri = fileNameToUri(fileName);
|
|
20181
20490
|
const rootDir = path$1.resolve(options.rootDir ?? path$1.dirname(fileName));
|
|
20182
20491
|
let activeClient;
|
|
@@ -20196,6 +20505,10 @@ async function openEditor(options) {
|
|
|
20196
20505
|
socket.end("HTTP/1.1 404 Not Found\r\n\r\n");
|
|
20197
20506
|
return;
|
|
20198
20507
|
}
|
|
20508
|
+
if (request.headers.origin !== editorPageUrl || request.headers.host !== new URL(editorPageUrl).host) {
|
|
20509
|
+
socket.end("HTTP/1.1 403 Forbidden\r\n\r\n");
|
|
20510
|
+
return;
|
|
20511
|
+
}
|
|
20199
20512
|
webSocketServer.handleUpgrade(request, socket, head, (webSocket) => {
|
|
20200
20513
|
activeClient?.close();
|
|
20201
20514
|
session?.dispose();
|
|
@@ -20218,7 +20531,11 @@ async function openEditor(options) {
|
|
|
20218
20531
|
const editorPageUrl = `http://${options.host}:${port}`;
|
|
20219
20532
|
console.log(`Stately visual editor: ${editorPageUrl}`);
|
|
20220
20533
|
console.log(`Editing ${machines.length} machine${machines.length === 1 ? "" : "s"} in ${rootDir}`);
|
|
20221
|
-
if (options.shouldOpen)
|
|
20534
|
+
if (options.shouldOpen) try {
|
|
20535
|
+
await openBrowser(editorPageUrl);
|
|
20536
|
+
} catch {
|
|
20537
|
+
console.warn("Could not open a browser automatically. Open the editor URL above.");
|
|
20538
|
+
}
|
|
20222
20539
|
const shutdown = () => {
|
|
20223
20540
|
session?.dispose();
|
|
20224
20541
|
activeClient?.close();
|
|
@@ -20399,6 +20716,7 @@ function getCliWebviewContent(options) {
|
|
|
20399
20716
|
></iframe>
|
|
20400
20717
|
<script>
|
|
20401
20718
|
const iframe = document.getElementById('stately-editor');
|
|
20719
|
+
const editorOrigin = new URL(iframe.src).origin;
|
|
20402
20720
|
const socket = new WebSocket(
|
|
20403
20721
|
(location.protocol === 'https:' ? 'wss:' : 'ws:') + '//' + location.host + '/ws'
|
|
20404
20722
|
);
|
|
@@ -20419,10 +20737,13 @@ function getCliWebviewContent(options) {
|
|
|
20419
20737
|
});
|
|
20420
20738
|
|
|
20421
20739
|
socket.addEventListener('message', (event) => {
|
|
20422
|
-
iframe.contentWindow?.postMessage(JSON.parse(event.data),
|
|
20740
|
+
iframe.contentWindow?.postMessage(JSON.parse(event.data), editorOrigin);
|
|
20423
20741
|
});
|
|
20424
20742
|
|
|
20425
20743
|
window.addEventListener('message', (event) => {
|
|
20744
|
+
if (event.source !== iframe.contentWindow || event.origin !== editorOrigin) {
|
|
20745
|
+
return;
|
|
20746
|
+
}
|
|
20426
20747
|
if (!event.data?.type?.startsWith?.('@statelyai.')) {
|
|
20427
20748
|
return;
|
|
20428
20749
|
}
|
|
@@ -20455,8 +20776,8 @@ async function assertEditorHostAvailable(editorUrl) {
|
|
|
20455
20776
|
function formatEditorHostError(baseUrl, status, cause) {
|
|
20456
20777
|
return `Cannot reach a usable editor host at ${baseUrl}.${status ? ` HTTP ${status} from /embed.` : ""}${cause instanceof Error && cause.message ? ` ${cause.message}` : ""} The CLI loads editor URL defaults from your environment, including \`.env.local\`. Start the editor host, set \`STATELY_EDITOR_URL\`, or pass \`--editor-url <url>\`.`;
|
|
20457
20778
|
}
|
|
20458
|
-
function openBrowser(url) {
|
|
20459
|
-
spawn(process.platform === "darwin" ? "open" : process.platform === "win32" ? "cmd" : "xdg-open", process.platform === "win32" ? [
|
|
20779
|
+
async function openBrowser(url) {
|
|
20780
|
+
const child = spawn(process.platform === "darwin" ? "open" : process.platform === "win32" ? "cmd" : "xdg-open", process.platform === "win32" ? [
|
|
20460
20781
|
"/c",
|
|
20461
20782
|
"start",
|
|
20462
20783
|
"",
|
|
@@ -20464,7 +20785,12 @@ function openBrowser(url) {
|
|
|
20464
20785
|
] : [url], {
|
|
20465
20786
|
detached: true,
|
|
20466
20787
|
stdio: "ignore"
|
|
20467
|
-
})
|
|
20788
|
+
});
|
|
20789
|
+
child.unref();
|
|
20790
|
+
await new Promise((resolve, reject) => {
|
|
20791
|
+
child.once("spawn", resolve);
|
|
20792
|
+
child.once("error", reject);
|
|
20793
|
+
});
|
|
20468
20794
|
}
|
|
20469
20795
|
function fileNameToUri(fileName) {
|
|
20470
20796
|
return pathToFileURL(path$1.resolve(fileName)).toString();
|
|
@@ -20490,6 +20816,8 @@ async function createLocalOAuthCallbackServer(options) {
|
|
|
20490
20816
|
resolveCode = resolve;
|
|
20491
20817
|
rejectCode = reject;
|
|
20492
20818
|
});
|
|
20819
|
+
codePromise.catch(() => {});
|
|
20820
|
+
const cancel = () => rejectCode(/* @__PURE__ */ new Error("Stately sign-in was canceled."));
|
|
20493
20821
|
const server = http.createServer((req, res) => {
|
|
20494
20822
|
const requestUrl = new URL(req.url ?? "/", "http://127.0.0.1");
|
|
20495
20823
|
const code = requestUrl.searchParams.get("code");
|
|
@@ -20517,12 +20845,17 @@ async function createLocalOAuthCallbackServer(options) {
|
|
|
20517
20845
|
});
|
|
20518
20846
|
const address = server.address();
|
|
20519
20847
|
if (!address || typeof address === "string") throw new Error("Could not start OAuth callback server.");
|
|
20848
|
+
options.signal?.addEventListener("abort", cancel, { once: true });
|
|
20849
|
+
if (options.signal?.aborted) cancel();
|
|
20520
20850
|
return {
|
|
20521
20851
|
redirectUri: `http://127.0.0.1:${address.port}/callback`,
|
|
20522
20852
|
waitForCode: () => codePromise,
|
|
20523
|
-
close: () =>
|
|
20524
|
-
|
|
20525
|
-
|
|
20853
|
+
close: () => {
|
|
20854
|
+
options.signal?.removeEventListener("abort", cancel);
|
|
20855
|
+
return new Promise((resolve) => {
|
|
20856
|
+
server.close(() => resolve());
|
|
20857
|
+
});
|
|
20858
|
+
}
|
|
20526
20859
|
};
|
|
20527
20860
|
}
|
|
20528
20861
|
|
|
@@ -21781,9 +22114,10 @@ function getOAuthExpiresAt(credential) {
|
|
|
21781
22114
|
function isTerminalOAuthRefreshError(error) {
|
|
21782
22115
|
return error instanceof Error && /Token refresh failed with HTTP (?:400|401|403)\b/.test(error.message);
|
|
21783
22116
|
}
|
|
22117
|
+
var ExpiredStatelyCredentialError = class extends Error {};
|
|
21784
22118
|
async function invalidateExpiredOAuthCredential() {
|
|
21785
22119
|
await deleteStoredApiKey();
|
|
21786
|
-
throw new
|
|
22120
|
+
throw new ExpiredStatelyCredentialError("Your Stately session expired. Run `npx statelyai login` to continue.");
|
|
21787
22121
|
}
|
|
21788
22122
|
async function refreshStoredOAuthCredential(credential, options) {
|
|
21789
22123
|
if (!credential.refreshToken) return invalidateExpiredOAuthCredential();
|
|
@@ -21817,7 +22151,7 @@ async function refreshStoredOAuthCredential(credential, options) {
|
|
|
21817
22151
|
}
|
|
21818
22152
|
}
|
|
21819
22153
|
async function resolveApiKey(options = {}) {
|
|
21820
|
-
const envApiKey = getEnvApiKey();
|
|
22154
|
+
const envApiKey = options.ignoreEnvironment ? void 0 : getEnvApiKey();
|
|
21821
22155
|
if (envApiKey) return {
|
|
21822
22156
|
apiKey: envApiKey.apiKey,
|
|
21823
22157
|
source: "env",
|
|
@@ -22043,22 +22377,32 @@ function formatStoredCredentialSource(storedCredential) {
|
|
|
22043
22377
|
return `Credential source: stored unknown (${describeCredentialBackend(storedCredential.backend, storedCredential.location)}).`;
|
|
22044
22378
|
}
|
|
22045
22379
|
async function runOAuthBrowserLogin(options) {
|
|
22380
|
+
options.signal?.throwIfAborted();
|
|
22046
22381
|
const state = crypto.randomBytes(16).toString("base64url");
|
|
22047
|
-
const callbackServer = await createLocalOAuthCallbackServer({
|
|
22382
|
+
const callbackServer = await createLocalOAuthCallbackServer({
|
|
22383
|
+
state,
|
|
22384
|
+
signal: options.signal
|
|
22385
|
+
});
|
|
22386
|
+
const loginFetch = (input, init) => fetch(input, {
|
|
22387
|
+
...init,
|
|
22388
|
+
signal: options.signal
|
|
22389
|
+
});
|
|
22048
22390
|
try {
|
|
22049
22391
|
const { authorizeUrl, codeVerifier, discovery } = await buildOAuthLoginStart({
|
|
22392
|
+
fetch: loginFetch,
|
|
22050
22393
|
baseUrl: options.baseUrl,
|
|
22051
22394
|
redirectUri: callbackServer.redirectUri,
|
|
22052
22395
|
state
|
|
22053
22396
|
});
|
|
22397
|
+
options.signal?.throwIfAborted();
|
|
22054
22398
|
options.log(`Opening browser for ${discovery.resourceUrl}`);
|
|
22055
|
-
options.log(authorizeUrl);
|
|
22056
22399
|
let openedBrowser = false;
|
|
22057
22400
|
try {
|
|
22058
|
-
openBrowser(authorizeUrl);
|
|
22401
|
+
await openBrowser(authorizeUrl);
|
|
22059
22402
|
openedBrowser = true;
|
|
22060
22403
|
} catch {
|
|
22061
22404
|
options.log("Could not open a browser automatically.");
|
|
22405
|
+
options.log(authorizeUrl);
|
|
22062
22406
|
}
|
|
22063
22407
|
const codePromise = callbackServer.waitForCode();
|
|
22064
22408
|
const pastedCodePromise = !openedBrowser && process.stdin.isTTY && process.stdout.isTTY ? promptForOAuthCallback().then((value) => {
|
|
@@ -22067,13 +22411,16 @@ async function runOAuthBrowserLogin(options) {
|
|
|
22067
22411
|
return callback.code;
|
|
22068
22412
|
}) : void 0;
|
|
22069
22413
|
const code = await (pastedCodePromise ? Promise.race([codePromise, pastedCodePromise]) : codePromise);
|
|
22070
|
-
|
|
22414
|
+
const tokenResponse = await exchangeCodeForToken({
|
|
22415
|
+
fetch: loginFetch,
|
|
22071
22416
|
tokenEndpoint: discovery.tokenEndpoint,
|
|
22072
22417
|
code,
|
|
22073
22418
|
codeVerifier,
|
|
22074
22419
|
redirectUri: callbackServer.redirectUri,
|
|
22075
22420
|
clientId: discovery.clientId
|
|
22076
|
-
})
|
|
22421
|
+
});
|
|
22422
|
+
options.signal?.throwIfAborted();
|
|
22423
|
+
return setStoredCredential(createOAuthCredential(tokenResponse, {
|
|
22077
22424
|
clientId: discovery.clientId,
|
|
22078
22425
|
tokenEndpoint: discovery.tokenEndpoint
|
|
22079
22426
|
}));
|
|
@@ -22986,7 +23333,16 @@ var OpenCommand = class OpenCommand extends Command {
|
|
|
22986
23333
|
};
|
|
22987
23334
|
async run() {
|
|
22988
23335
|
const { args, flags } = await this.parse(OpenCommand);
|
|
22989
|
-
|
|
23336
|
+
let hasLoggedIn = false;
|
|
23337
|
+
const getApiKey = async () => {
|
|
23338
|
+
try {
|
|
23339
|
+
return (await resolveApiKey({ ignoreEnvironment: hasLoggedIn })).apiKey;
|
|
23340
|
+
} catch (error) {
|
|
23341
|
+
if (error instanceof ExpiredStatelyCredentialError) return void 0;
|
|
23342
|
+
throw error;
|
|
23343
|
+
}
|
|
23344
|
+
};
|
|
23345
|
+
const apiKey = await getApiKey();
|
|
22990
23346
|
const cwd = process.cwd();
|
|
22991
23347
|
const discovered = args.file ? await discoverMachinesInFile(path.resolve(args.file)) : await scanProjectMachines({ cwd });
|
|
22992
23348
|
if (discovered.length === 0) throw new Error(args.file ? `No machines found in ${path.resolve(args.file)}.` : `No machines found in ${cwd}.`);
|
|
@@ -23019,7 +23375,19 @@ var OpenCommand = class OpenCommand extends Command {
|
|
|
23019
23375
|
sourceUpdateStrategy: flags["source-update"] ?? configuredSourceUpdateStrategy ?? "preserve",
|
|
23020
23376
|
apiKey,
|
|
23021
23377
|
studioUrl: resolveApiBaseUrl(configuredStudioUrl),
|
|
23022
|
-
debug: flags.debug
|
|
23378
|
+
debug: flags.debug,
|
|
23379
|
+
getApiKey,
|
|
23380
|
+
onLogin: async (signal) => {
|
|
23381
|
+
const stored = await runOAuthBrowserLogin({
|
|
23382
|
+
baseUrl: flags["editor-url"] ?? getDefaultEditorUrl(),
|
|
23383
|
+
log: (message) => this.log(message),
|
|
23384
|
+
signal
|
|
23385
|
+
});
|
|
23386
|
+
if (stored.credential?.type !== "oauth") throw new Error("Stately login did not return an OAuth credential.");
|
|
23387
|
+
hasLoggedIn = true;
|
|
23388
|
+
this.log("Logged in to Stately. Loading your machine…");
|
|
23389
|
+
return stored.credential.accessToken;
|
|
23390
|
+
}
|
|
23023
23391
|
});
|
|
23024
23392
|
}
|
|
23025
23393
|
};
|