statelyai 0.12.0 → 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-Dr85YlA5.mjs → cli-RFjHJYb3.mjs} +467 -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 {
|
|
@@ -18241,6 +18395,7 @@ function createStudioPresentationMetadataStore(client, machineId) {
|
|
|
18241
18395
|
return {
|
|
18242
18396
|
load,
|
|
18243
18397
|
async hydrate(graph) {
|
|
18398
|
+
if (!isGraph(graph)) return graph;
|
|
18244
18399
|
return {
|
|
18245
18400
|
presentationMachine: mergeLocalGraphIntoRemoteDefinition(graph, (await load()).definition).definition,
|
|
18246
18401
|
presentationFormat: "digraph"
|
|
@@ -18248,7 +18403,7 @@ function createStudioPresentationMetadataStore(client, machineId) {
|
|
|
18248
18403
|
},
|
|
18249
18404
|
async persist(_graph, context) {
|
|
18250
18405
|
const serialized = context?.serialized?.digraph;
|
|
18251
|
-
if (!serialized)
|
|
18406
|
+
if (!serialized) throw new Error("Studio presentation requires a serialized digraph. Presentation was not saved.");
|
|
18252
18407
|
const editedDefinition = JSON.parse(serialized);
|
|
18253
18408
|
const latest = await client.machines.get(machineId);
|
|
18254
18409
|
if (!latest.updatedAt) throw new Error(`Studio machine "${machineId}" did not provide an updatedAt guard. Presentation was not saved.`);
|
|
@@ -18309,10 +18464,29 @@ function createLocalPresentationMetadataRepository(file) {
|
|
|
18309
18464
|
};
|
|
18310
18465
|
} };
|
|
18311
18466
|
}
|
|
18312
|
-
function applyPresentationInitializer(initializer, current) {
|
|
18467
|
+
function applyPresentationInitializer(initializer, current, convertStudioDefinition = fromStudioMachine) {
|
|
18313
18468
|
if (initializer.type === "overlay") return applyPresentationMetadata(initializer.overlay, current);
|
|
18314
18469
|
if (!isGraph(current)) return current;
|
|
18315
|
-
|
|
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);
|
|
18316
18490
|
}
|
|
18317
18491
|
function applyPresentationMetadata(overlay, current) {
|
|
18318
18492
|
if (!isPresentationOverlay(overlay) || !isGraph(current)) return current;
|
|
@@ -18320,6 +18494,7 @@ function applyPresentationMetadata(overlay, current) {
|
|
|
18320
18494
|
const addedNodes = [];
|
|
18321
18495
|
const addedEdges = [];
|
|
18322
18496
|
const semanticIds = overlay.identity === "semantic-v1" ? presentationIds(result) : void 0;
|
|
18497
|
+
const legacyIds = semanticIds ? presentationIds(result, false) : void 0;
|
|
18323
18498
|
const renamedGuardPresentation = semanticIds ? matchUniqueGuardRenames(semanticIds.edges, overlay.edges ?? {}) : /* @__PURE__ */ new Map();
|
|
18324
18499
|
for (const [index, node] of result.nodes.entries()) {
|
|
18325
18500
|
normalizeCanonicalGeometry(node);
|
|
@@ -18330,7 +18505,7 @@ function applyPresentationMetadata(overlay, current) {
|
|
|
18330
18505
|
for (const [index, edge] of result.edges.entries()) {
|
|
18331
18506
|
normalizeCanonicalGeometry(edge);
|
|
18332
18507
|
const semanticId = semanticIds?.edges[index] ?? edge.id;
|
|
18333
|
-
const presentation = overlay.edges?.[semanticId] ?? renamedGuardPresentation.get(semanticId);
|
|
18508
|
+
const presentation = overlay.edges?.[semanticId] ?? overlay.edges?.[legacyIds?.edges[index] ?? edge.id] ?? renamedGuardPresentation.get(semanticId);
|
|
18334
18509
|
if (presentation) applyEntityPresentation(presentation, edge);
|
|
18335
18510
|
else addedEdges.push(edge);
|
|
18336
18511
|
}
|
|
@@ -18410,6 +18585,7 @@ function entityPresentationMap(entities, includeSourceSide, ids) {
|
|
|
18410
18585
|
const presentation = compactDefined({
|
|
18411
18586
|
...pick(canonicalGeometry(entity), GEOMETRY_FIELDS),
|
|
18412
18587
|
color: clone(entity.data?.color),
|
|
18588
|
+
layout: clone(entity.data?.layout),
|
|
18413
18589
|
assets: clone(entity.data?.assets),
|
|
18414
18590
|
sourceSide: includeSourceSide ? clone(entity.data?.sourceSide) : void 0
|
|
18415
18591
|
});
|
|
@@ -18417,7 +18593,8 @@ function entityPresentationMap(entities, includeSourceSide, ids) {
|
|
|
18417
18593
|
});
|
|
18418
18594
|
return entries.length > 0 ? Object.fromEntries(entries) : void 0;
|
|
18419
18595
|
}
|
|
18420
|
-
function presentationIds(graph) {
|
|
18596
|
+
function presentationIds(graph, canonicalEvents = true) {
|
|
18597
|
+
const matchingGraph = canonicalEvents ? presentationMatchingGraph(graph) : graph;
|
|
18421
18598
|
const normalized = normalizeGraphForSemanticDiff({
|
|
18422
18599
|
id: graph.id ?? "presentation",
|
|
18423
18600
|
nodes: graph.nodes.map((node) => ({
|
|
@@ -18425,7 +18602,7 @@ function presentationIds(graph) {
|
|
|
18425
18602
|
parentId: node.parentId,
|
|
18426
18603
|
data: { key: node.data?.key }
|
|
18427
18604
|
})),
|
|
18428
|
-
edges:
|
|
18605
|
+
edges: matchingGraph.edges.map((edge) => ({
|
|
18429
18606
|
id: edge.id,
|
|
18430
18607
|
sourceId: edge.sourceId,
|
|
18431
18608
|
targetId: edge.targetId,
|
|
@@ -18458,10 +18635,12 @@ function createAnnotationSnapshot(annotations) {
|
|
|
18458
18635
|
parentId: annotation.parentId,
|
|
18459
18636
|
content: clone(annotation.content),
|
|
18460
18637
|
...pick(geometry, GEOMETRY_FIELDS),
|
|
18638
|
+
...pick(annotation, ["width", "height"]),
|
|
18461
18639
|
data: compactDefined({
|
|
18462
18640
|
referenceIds: clone(annotation.data?.referenceIds),
|
|
18463
18641
|
color: clone(annotation.data?.color),
|
|
18464
|
-
textAlign: clone(annotation.data?.textAlign)
|
|
18642
|
+
textAlign: clone(annotation.data?.textAlign),
|
|
18643
|
+
placement: clone(annotation.data?.placement)
|
|
18465
18644
|
})
|
|
18466
18645
|
});
|
|
18467
18646
|
});
|
|
@@ -18480,7 +18659,8 @@ function applyEntityPresentation(presentation, entity) {
|
|
|
18480
18659
|
for (const field of [
|
|
18481
18660
|
"color",
|
|
18482
18661
|
"assets",
|
|
18483
|
-
"sourceSide"
|
|
18662
|
+
"sourceSide",
|
|
18663
|
+
"layout"
|
|
18484
18664
|
]) copyField(presentation, entity.data, field);
|
|
18485
18665
|
}
|
|
18486
18666
|
function placeAddedNodes(added, allNodes) {
|
|
@@ -19003,7 +19183,7 @@ const editorSyncApplyResponseSchema = z$1.object({ replacements: z$1.array(edito
|
|
|
19003
19183
|
const editorSyncAccessResponseSchema = z$1.object({ access: editorSyncAccessSchema });
|
|
19004
19184
|
|
|
19005
19185
|
//#endregion
|
|
19006
|
-
//#region ../editor-sync/dist/host-
|
|
19186
|
+
//#region ../editor-sync/dist/host-Dvy75KWk.mjs
|
|
19007
19187
|
let diagnosticSequence = 0;
|
|
19008
19188
|
function presentationsEqual(first, second) {
|
|
19009
19189
|
return JSON.stringify(createPresentationSnapshot(first)) === JSON.stringify(createPresentationSnapshot(second));
|
|
@@ -19030,6 +19210,12 @@ var EditorSyncError = class extends Error {
|
|
|
19030
19210
|
this.code = code;
|
|
19031
19211
|
}
|
|
19032
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
|
+
}
|
|
19033
19219
|
async function fetchEditorSyncAccess(options) {
|
|
19034
19220
|
const fetchImpl = options.fetch ?? globalThis.fetch;
|
|
19035
19221
|
const url = new URL("/api/editor-sync/access", `${options.editorUrl.replace(/\/+$/, "")}/`);
|
|
@@ -19123,12 +19309,14 @@ var EditorHostSession = class {
|
|
|
19123
19309
|
await this.initialize();
|
|
19124
19310
|
} catch (error) {
|
|
19125
19311
|
const message = formatError(error, "Failed to initialize the visual editor.");
|
|
19312
|
+
const recovery = isEditorSyncAuthenticationError(error) ? this.options.authenticationRecovery : void 0;
|
|
19126
19313
|
this.options.send({
|
|
19127
19314
|
type: "@statelyai.error",
|
|
19128
19315
|
code: "initialization_failed",
|
|
19129
|
-
message
|
|
19316
|
+
message,
|
|
19317
|
+
...recovery ? { authenticationRecovery: recovery } : {}
|
|
19130
19318
|
});
|
|
19131
|
-
this.options.showError?.(message);
|
|
19319
|
+
this.options.showError?.(recovery ? `${message}\n${authenticationRecoveryInstructions(recovery)}` : message);
|
|
19132
19320
|
}
|
|
19133
19321
|
break;
|
|
19134
19322
|
case "@statelyai.loaded":
|
|
@@ -19329,7 +19517,7 @@ var EditorHostSession = class {
|
|
|
19329
19517
|
return;
|
|
19330
19518
|
}
|
|
19331
19519
|
const documents = await this.options.source.collectDocuments(sourceLocationUris(this.currentSourceLocations));
|
|
19332
|
-
const serialized = await this.getSerializedPayload();
|
|
19520
|
+
const serialized = await this.getSerializedPayload(message.serialized);
|
|
19333
19521
|
const response = await this.options.sync.apply({
|
|
19334
19522
|
rootUri: this.options.source.rootUri,
|
|
19335
19523
|
rootFileName: this.options.source.rootFileName,
|
|
@@ -19378,7 +19566,7 @@ var EditorHostSession = class {
|
|
|
19378
19566
|
});
|
|
19379
19567
|
}
|
|
19380
19568
|
async acknowledgeWithoutSourceChanges(message, serialized) {
|
|
19381
|
-
await this.persistPresentation(message.graph, serialized ?? await this.getSerializedPayload());
|
|
19569
|
+
await this.persistPresentation(message.graph, serialized ?? await this.getSerializedPayload(message.serialized));
|
|
19382
19570
|
this.currentGraph = message.graph;
|
|
19383
19571
|
this.lastPersistedGraph = message.graph;
|
|
19384
19572
|
this.options.send({
|
|
@@ -19476,11 +19664,12 @@ var EditorHostSession = class {
|
|
|
19476
19664
|
this.watchedSourceUris.clear();
|
|
19477
19665
|
for (const uri of sourceLocationUris(sourceLocations)) if (uri !== this.options.source.rootUri) this.watchedSourceUris.add(uri);
|
|
19478
19666
|
}
|
|
19479
|
-
async getSerializedPayload() {
|
|
19667
|
+
async getSerializedPayload(provided) {
|
|
19480
19668
|
const format = this.currentFormat;
|
|
19481
|
-
|
|
19669
|
+
const formats = [...new Set([...format && format !== "xstate" ? [format] : [], ...this.initialPresentation?.type === "studio" ? ["digraph"] : []])];
|
|
19670
|
+
if (formats.length === 0) return void 0;
|
|
19482
19671
|
try {
|
|
19483
|
-
return
|
|
19672
|
+
return Object.fromEntries(await Promise.all(formats.map(async (format) => [format, provided?.[format] ?? await this.requestSerialized(format)])));
|
|
19484
19673
|
} catch {
|
|
19485
19674
|
return;
|
|
19486
19675
|
}
|
|
@@ -19855,14 +20044,31 @@ async function assertSourceSaveMatchesGraph(input) {
|
|
|
19855
20044
|
const graph = convertMachineToGraph({
|
|
19856
20045
|
machine: parsed.machine,
|
|
19857
20046
|
format,
|
|
19858
|
-
|
|
20047
|
+
profile: input.profile ?? (format === "json" ? input.graph.data?.profile : void 0)
|
|
19859
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
|
+
}
|
|
19860
20053
|
return graphToMachineConfig(graph);
|
|
19861
20054
|
};
|
|
19862
20055
|
const expectedConfig = comparableMachineConfig(stripStatelyMetadata(input.machineConfig));
|
|
19863
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;
|
|
19864
20071
|
if (expectedConfig && typeof expectedConfig === "object" && !Array.isArray(expectedConfig) && actualConfig && typeof actualConfig === "object" && !Array.isArray(actualConfig) && !("id" in expectedConfig) && "id" in actualConfig) {
|
|
19865
|
-
const baselineConfig = comparableMachineConfig(stripStatelyMetadata(projectConfig(input.documents)));
|
|
19866
20072
|
if (baselineConfig && typeof baselineConfig === "object" && "id" in baselineConfig && actualConfig.id === baselineConfig.id) delete actualConfig.id;
|
|
19867
20073
|
}
|
|
19868
20074
|
if (JSON.stringify(expectedConfig) !== JSON.stringify(actualConfig)) throw new Error("The updated source does not match the requested machine.");
|
|
@@ -19944,7 +20150,7 @@ function sourceLocationUris(sourceLocations) {
|
|
|
19944
20150
|
|
|
19945
20151
|
//#endregion
|
|
19946
20152
|
//#region src/version.ts
|
|
19947
|
-
const CLI_VERSION = "0.12.
|
|
20153
|
+
const CLI_VERSION = "0.12.3";
|
|
19948
20154
|
|
|
19949
20155
|
//#endregion
|
|
19950
20156
|
//#region src/cliHost.ts
|
|
@@ -19985,11 +20191,21 @@ function rawDataToBuffer(data) {
|
|
|
19985
20191
|
var CliEditorSession = class {
|
|
19986
20192
|
session;
|
|
19987
20193
|
workspaceWatcher;
|
|
20194
|
+
readyMessage;
|
|
20195
|
+
loginPromise;
|
|
20196
|
+
loginController;
|
|
20197
|
+
disposed = false;
|
|
19988
20198
|
constructor(options, sendMessage) {
|
|
19989
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;
|
|
19990
20206
|
const send = (message) => {
|
|
19991
20207
|
this.log("send", message.type, message);
|
|
19992
|
-
sendMessage(message);
|
|
20208
|
+
this.sendMessage(message);
|
|
19993
20209
|
};
|
|
19994
20210
|
const machines = options.machines ?? [{
|
|
19995
20211
|
id: `${options.rootUri}#0`,
|
|
@@ -20003,8 +20219,7 @@ var CliEditorSession = class {
|
|
|
20003
20219
|
baseUrl: options.studioUrl,
|
|
20004
20220
|
apiKey: options.apiKey
|
|
20005
20221
|
});
|
|
20006
|
-
|
|
20007
|
-
let access;
|
|
20222
|
+
let access = options.access ? Promise.resolve(options.access) : void 0;
|
|
20008
20223
|
const getAccess = () => {
|
|
20009
20224
|
if (!access) {
|
|
20010
20225
|
const request = fetchEditorSyncAccess({
|
|
@@ -20019,7 +20234,11 @@ var CliEditorSession = class {
|
|
|
20019
20234
|
}
|
|
20020
20235
|
return access;
|
|
20021
20236
|
};
|
|
20022
|
-
|
|
20237
|
+
return new EditorHostWorkspaceSession({
|
|
20238
|
+
authenticationRecovery: {
|
|
20239
|
+
host: "cli",
|
|
20240
|
+
canLogin: Boolean(options.onLogin)
|
|
20241
|
+
},
|
|
20023
20242
|
machines: machines.map((machine) => ({
|
|
20024
20243
|
id: machine.id,
|
|
20025
20244
|
name: machine.name,
|
|
@@ -20055,14 +20274,75 @@ var CliEditorSession = class {
|
|
|
20055
20274
|
showError: (message) => console.error(`Stately Editor: ${message}`)
|
|
20056
20275
|
});
|
|
20057
20276
|
}
|
|
20058
|
-
receiveMessage(message) {
|
|
20277
|
+
async receiveMessage(message) {
|
|
20059
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
|
+
}
|
|
20060
20304
|
return this.session.receive(message);
|
|
20061
20305
|
}
|
|
20062
20306
|
dispose() {
|
|
20307
|
+
this.disposed = true;
|
|
20308
|
+
this.loginController?.abort();
|
|
20063
20309
|
this.session.dispose();
|
|
20064
20310
|
this.workspaceWatcher.dispose();
|
|
20065
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
|
+
}
|
|
20066
20346
|
log(direction, type, payload) {
|
|
20067
20347
|
if (this.options.debug) console.error(`[${direction}] ${type}`, redactDebugPayload(payload) ?? "");
|
|
20068
20348
|
}
|
|
@@ -20164,6 +20444,31 @@ function redactDebugPayload(payload) {
|
|
|
20164
20444
|
if (!payload || typeof payload !== "object") return payload;
|
|
20165
20445
|
return Object.fromEntries(Object.entries(payload).map(([key, value]) => [key, /^(?:apiKey|accessToken|refreshToken|token|authorization)$/i.test(key) ? "[REDACTED]" : redactDebugPayload(value)]));
|
|
20166
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
|
+
}
|
|
20167
20472
|
async function openEditor(options) {
|
|
20168
20473
|
const fileName = path$1.resolve(options.fileName);
|
|
20169
20474
|
const machines = (options.machines ?? [{
|
|
@@ -20176,6 +20481,11 @@ async function openEditor(options) {
|
|
|
20176
20481
|
}));
|
|
20177
20482
|
await Promise.all([...new Set(machines.map((machine) => machine.fileName))].map((target) => fsPromises.access(target)));
|
|
20178
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
|
+
}));
|
|
20179
20489
|
const rootUri = fileNameToUri(fileName);
|
|
20180
20490
|
const rootDir = path$1.resolve(options.rootDir ?? path$1.dirname(fileName));
|
|
20181
20491
|
let activeClient;
|
|
@@ -20195,6 +20505,10 @@ async function openEditor(options) {
|
|
|
20195
20505
|
socket.end("HTTP/1.1 404 Not Found\r\n\r\n");
|
|
20196
20506
|
return;
|
|
20197
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
|
+
}
|
|
20198
20512
|
webSocketServer.handleUpgrade(request, socket, head, (webSocket) => {
|
|
20199
20513
|
activeClient?.close();
|
|
20200
20514
|
session?.dispose();
|
|
@@ -20217,7 +20531,11 @@ async function openEditor(options) {
|
|
|
20217
20531
|
const editorPageUrl = `http://${options.host}:${port}`;
|
|
20218
20532
|
console.log(`Stately visual editor: ${editorPageUrl}`);
|
|
20219
20533
|
console.log(`Editing ${machines.length} machine${machines.length === 1 ? "" : "s"} in ${rootDir}`);
|
|
20220
|
-
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
|
+
}
|
|
20221
20539
|
const shutdown = () => {
|
|
20222
20540
|
session?.dispose();
|
|
20223
20541
|
activeClient?.close();
|
|
@@ -20398,6 +20716,7 @@ function getCliWebviewContent(options) {
|
|
|
20398
20716
|
></iframe>
|
|
20399
20717
|
<script>
|
|
20400
20718
|
const iframe = document.getElementById('stately-editor');
|
|
20719
|
+
const editorOrigin = new URL(iframe.src).origin;
|
|
20401
20720
|
const socket = new WebSocket(
|
|
20402
20721
|
(location.protocol === 'https:' ? 'wss:' : 'ws:') + '//' + location.host + '/ws'
|
|
20403
20722
|
);
|
|
@@ -20418,10 +20737,13 @@ function getCliWebviewContent(options) {
|
|
|
20418
20737
|
});
|
|
20419
20738
|
|
|
20420
20739
|
socket.addEventListener('message', (event) => {
|
|
20421
|
-
iframe.contentWindow?.postMessage(JSON.parse(event.data),
|
|
20740
|
+
iframe.contentWindow?.postMessage(JSON.parse(event.data), editorOrigin);
|
|
20422
20741
|
});
|
|
20423
20742
|
|
|
20424
20743
|
window.addEventListener('message', (event) => {
|
|
20744
|
+
if (event.source !== iframe.contentWindow || event.origin !== editorOrigin) {
|
|
20745
|
+
return;
|
|
20746
|
+
}
|
|
20425
20747
|
if (!event.data?.type?.startsWith?.('@statelyai.')) {
|
|
20426
20748
|
return;
|
|
20427
20749
|
}
|
|
@@ -20454,8 +20776,8 @@ async function assertEditorHostAvailable(editorUrl) {
|
|
|
20454
20776
|
function formatEditorHostError(baseUrl, status, cause) {
|
|
20455
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>\`.`;
|
|
20456
20778
|
}
|
|
20457
|
-
function openBrowser(url) {
|
|
20458
|
-
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" ? [
|
|
20459
20781
|
"/c",
|
|
20460
20782
|
"start",
|
|
20461
20783
|
"",
|
|
@@ -20463,7 +20785,12 @@ function openBrowser(url) {
|
|
|
20463
20785
|
] : [url], {
|
|
20464
20786
|
detached: true,
|
|
20465
20787
|
stdio: "ignore"
|
|
20466
|
-
})
|
|
20788
|
+
});
|
|
20789
|
+
child.unref();
|
|
20790
|
+
await new Promise((resolve, reject) => {
|
|
20791
|
+
child.once("spawn", resolve);
|
|
20792
|
+
child.once("error", reject);
|
|
20793
|
+
});
|
|
20467
20794
|
}
|
|
20468
20795
|
function fileNameToUri(fileName) {
|
|
20469
20796
|
return pathToFileURL(path$1.resolve(fileName)).toString();
|
|
@@ -20489,6 +20816,8 @@ async function createLocalOAuthCallbackServer(options) {
|
|
|
20489
20816
|
resolveCode = resolve;
|
|
20490
20817
|
rejectCode = reject;
|
|
20491
20818
|
});
|
|
20819
|
+
codePromise.catch(() => {});
|
|
20820
|
+
const cancel = () => rejectCode(/* @__PURE__ */ new Error("Stately sign-in was canceled."));
|
|
20492
20821
|
const server = http.createServer((req, res) => {
|
|
20493
20822
|
const requestUrl = new URL(req.url ?? "/", "http://127.0.0.1");
|
|
20494
20823
|
const code = requestUrl.searchParams.get("code");
|
|
@@ -20516,12 +20845,17 @@ async function createLocalOAuthCallbackServer(options) {
|
|
|
20516
20845
|
});
|
|
20517
20846
|
const address = server.address();
|
|
20518
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();
|
|
20519
20850
|
return {
|
|
20520
20851
|
redirectUri: `http://127.0.0.1:${address.port}/callback`,
|
|
20521
20852
|
waitForCode: () => codePromise,
|
|
20522
|
-
close: () =>
|
|
20523
|
-
|
|
20524
|
-
|
|
20853
|
+
close: () => {
|
|
20854
|
+
options.signal?.removeEventListener("abort", cancel);
|
|
20855
|
+
return new Promise((resolve) => {
|
|
20856
|
+
server.close(() => resolve());
|
|
20857
|
+
});
|
|
20858
|
+
}
|
|
20525
20859
|
};
|
|
20526
20860
|
}
|
|
20527
20861
|
|
|
@@ -21780,9 +22114,10 @@ function getOAuthExpiresAt(credential) {
|
|
|
21780
22114
|
function isTerminalOAuthRefreshError(error) {
|
|
21781
22115
|
return error instanceof Error && /Token refresh failed with HTTP (?:400|401|403)\b/.test(error.message);
|
|
21782
22116
|
}
|
|
22117
|
+
var ExpiredStatelyCredentialError = class extends Error {};
|
|
21783
22118
|
async function invalidateExpiredOAuthCredential() {
|
|
21784
22119
|
await deleteStoredApiKey();
|
|
21785
|
-
throw new
|
|
22120
|
+
throw new ExpiredStatelyCredentialError("Your Stately session expired. Run `npx statelyai login` to continue.");
|
|
21786
22121
|
}
|
|
21787
22122
|
async function refreshStoredOAuthCredential(credential, options) {
|
|
21788
22123
|
if (!credential.refreshToken) return invalidateExpiredOAuthCredential();
|
|
@@ -21816,7 +22151,7 @@ async function refreshStoredOAuthCredential(credential, options) {
|
|
|
21816
22151
|
}
|
|
21817
22152
|
}
|
|
21818
22153
|
async function resolveApiKey(options = {}) {
|
|
21819
|
-
const envApiKey = getEnvApiKey();
|
|
22154
|
+
const envApiKey = options.ignoreEnvironment ? void 0 : getEnvApiKey();
|
|
21820
22155
|
if (envApiKey) return {
|
|
21821
22156
|
apiKey: envApiKey.apiKey,
|
|
21822
22157
|
source: "env",
|
|
@@ -22042,22 +22377,32 @@ function formatStoredCredentialSource(storedCredential) {
|
|
|
22042
22377
|
return `Credential source: stored unknown (${describeCredentialBackend(storedCredential.backend, storedCredential.location)}).`;
|
|
22043
22378
|
}
|
|
22044
22379
|
async function runOAuthBrowserLogin(options) {
|
|
22380
|
+
options.signal?.throwIfAborted();
|
|
22045
22381
|
const state = crypto.randomBytes(16).toString("base64url");
|
|
22046
|
-
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
|
+
});
|
|
22047
22390
|
try {
|
|
22048
22391
|
const { authorizeUrl, codeVerifier, discovery } = await buildOAuthLoginStart({
|
|
22392
|
+
fetch: loginFetch,
|
|
22049
22393
|
baseUrl: options.baseUrl,
|
|
22050
22394
|
redirectUri: callbackServer.redirectUri,
|
|
22051
22395
|
state
|
|
22052
22396
|
});
|
|
22397
|
+
options.signal?.throwIfAborted();
|
|
22053
22398
|
options.log(`Opening browser for ${discovery.resourceUrl}`);
|
|
22054
|
-
options.log(authorizeUrl);
|
|
22055
22399
|
let openedBrowser = false;
|
|
22056
22400
|
try {
|
|
22057
|
-
openBrowser(authorizeUrl);
|
|
22401
|
+
await openBrowser(authorizeUrl);
|
|
22058
22402
|
openedBrowser = true;
|
|
22059
22403
|
} catch {
|
|
22060
22404
|
options.log("Could not open a browser automatically.");
|
|
22405
|
+
options.log(authorizeUrl);
|
|
22061
22406
|
}
|
|
22062
22407
|
const codePromise = callbackServer.waitForCode();
|
|
22063
22408
|
const pastedCodePromise = !openedBrowser && process.stdin.isTTY && process.stdout.isTTY ? promptForOAuthCallback().then((value) => {
|
|
@@ -22066,13 +22411,16 @@ async function runOAuthBrowserLogin(options) {
|
|
|
22066
22411
|
return callback.code;
|
|
22067
22412
|
}) : void 0;
|
|
22068
22413
|
const code = await (pastedCodePromise ? Promise.race([codePromise, pastedCodePromise]) : codePromise);
|
|
22069
|
-
|
|
22414
|
+
const tokenResponse = await exchangeCodeForToken({
|
|
22415
|
+
fetch: loginFetch,
|
|
22070
22416
|
tokenEndpoint: discovery.tokenEndpoint,
|
|
22071
22417
|
code,
|
|
22072
22418
|
codeVerifier,
|
|
22073
22419
|
redirectUri: callbackServer.redirectUri,
|
|
22074
22420
|
clientId: discovery.clientId
|
|
22075
|
-
})
|
|
22421
|
+
});
|
|
22422
|
+
options.signal?.throwIfAborted();
|
|
22423
|
+
return setStoredCredential(createOAuthCredential(tokenResponse, {
|
|
22076
22424
|
clientId: discovery.clientId,
|
|
22077
22425
|
tokenEndpoint: discovery.tokenEndpoint
|
|
22078
22426
|
}));
|
|
@@ -22985,7 +23333,16 @@ var OpenCommand = class OpenCommand extends Command {
|
|
|
22985
23333
|
};
|
|
22986
23334
|
async run() {
|
|
22987
23335
|
const { args, flags } = await this.parse(OpenCommand);
|
|
22988
|
-
|
|
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();
|
|
22989
23346
|
const cwd = process.cwd();
|
|
22990
23347
|
const discovered = args.file ? await discoverMachinesInFile(path.resolve(args.file)) : await scanProjectMachines({ cwd });
|
|
22991
23348
|
if (discovered.length === 0) throw new Error(args.file ? `No machines found in ${path.resolve(args.file)}.` : `No machines found in ${cwd}.`);
|
|
@@ -23018,7 +23375,19 @@ var OpenCommand = class OpenCommand extends Command {
|
|
|
23018
23375
|
sourceUpdateStrategy: flags["source-update"] ?? configuredSourceUpdateStrategy ?? "preserve",
|
|
23019
23376
|
apiKey,
|
|
23020
23377
|
studioUrl: resolveApiBaseUrl(configuredStudioUrl),
|
|
23021
|
-
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
|
+
}
|
|
23022
23391
|
});
|
|
23023
23392
|
}
|
|
23024
23393
|
};
|