@mmmnt/cli 0.8.0 → 0.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/moment.mjs +126 -62
- package/dist/moment.mjs.map +2 -2
- package/package.json +9 -9
package/dist/moment.mjs
CHANGED
|
@@ -59218,6 +59218,10 @@ var MomentGrammar = () => loadedMomentGrammar ?? (loadedMomentGrammar = loadGram
|
|
|
59218
59218
|
{
|
|
59219
59219
|
"$type": "Keyword",
|
|
59220
59220
|
"value": "note"
|
|
59221
|
+
},
|
|
59222
|
+
{
|
|
59223
|
+
"$type": "Keyword",
|
|
59224
|
+
"value": "outcome"
|
|
59221
59225
|
}
|
|
59222
59226
|
]
|
|
59223
59227
|
},
|
|
@@ -59324,6 +59328,10 @@ var MomentGrammar = () => loadedMomentGrammar ?? (loadedMomentGrammar = loadGram
|
|
|
59324
59328
|
{
|
|
59325
59329
|
"$type": "Keyword",
|
|
59326
59330
|
"value": "terminal"
|
|
59331
|
+
},
|
|
59332
|
+
{
|
|
59333
|
+
"$type": "Keyword",
|
|
59334
|
+
"value": "outcome"
|
|
59327
59335
|
}
|
|
59328
59336
|
]
|
|
59329
59337
|
},
|
|
@@ -59765,6 +59773,10 @@ var MomentGrammar = () => loadedMomentGrammar ?? (loadedMomentGrammar = loadGram
|
|
|
59765
59773
|
{
|
|
59766
59774
|
"$type": "Keyword",
|
|
59767
59775
|
"value": "note"
|
|
59776
|
+
},
|
|
59777
|
+
{
|
|
59778
|
+
"$type": "Keyword",
|
|
59779
|
+
"value": "outcome"
|
|
59768
59780
|
}
|
|
59769
59781
|
]
|
|
59770
59782
|
},
|
|
@@ -60291,7 +60303,7 @@ var MomentValidator = class {
|
|
|
60291
60303
|
// those are alternative branch arms, not continuations.
|
|
60292
60304
|
// =========================================================================
|
|
60293
60305
|
checkTerminalIsLast(node, accept) {
|
|
60294
|
-
if (node
|
|
60306
|
+
if (!endsFlow(node))
|
|
60295
60307
|
return;
|
|
60296
60308
|
const container = node.$container;
|
|
60297
60309
|
const siblings = "nodes" in container ? container.nodes : [];
|
|
@@ -60762,6 +60774,10 @@ var MomentValidator = class {
|
|
|
60762
60774
|
return false;
|
|
60763
60775
|
}
|
|
60764
60776
|
};
|
|
60777
|
+
function endsFlow(node) {
|
|
60778
|
+
const type = node.modifier?.type;
|
|
60779
|
+
return type === "terminal" || type === "outcome";
|
|
60780
|
+
}
|
|
60765
60781
|
|
|
60766
60782
|
// ../core/dist/moment-module.js
|
|
60767
60783
|
var MomentModule = {
|
|
@@ -61778,13 +61794,18 @@ function transformNodeToEntry(node, laneContextMap, nodeKindMap) {
|
|
|
61778
61794
|
if (node.cause !== void 0) {
|
|
61779
61795
|
entry.cause = node.cause;
|
|
61780
61796
|
}
|
|
61781
|
-
|
|
61797
|
+
applyModifier(entry, node.modifier?.type);
|
|
61798
|
+
return entry;
|
|
61799
|
+
}
|
|
61800
|
+
function applyModifier(entry, modifierType) {
|
|
61782
61801
|
if (modifierType === "optional") {
|
|
61783
61802
|
entry.optional = true;
|
|
61784
61803
|
} else if (modifierType === "terminal") {
|
|
61785
61804
|
entry.terminal = true;
|
|
61805
|
+
} else if (modifierType === "outcome") {
|
|
61806
|
+
entry.terminal = true;
|
|
61807
|
+
entry.exit = "outcome";
|
|
61786
61808
|
}
|
|
61787
|
-
return entry;
|
|
61788
61809
|
}
|
|
61789
61810
|
function extractConnections(flow, laneContextMap) {
|
|
61790
61811
|
const connections = [];
|
|
@@ -64934,14 +64955,16 @@ function resolveScenarioLabel(flow, reachedBranches) {
|
|
|
64934
64955
|
if (deviations.length === 0)
|
|
64935
64956
|
return `Happy Path: ${flow.name}`;
|
|
64936
64957
|
const bracket = deviations.map((b) => b.condition).join(", ");
|
|
64937
|
-
|
|
64938
|
-
return hasTerminalArm ? `Failure Path: ${flow.name} [${bracket}]` : `Variant: ${flow.name} [${bracket}]`;
|
|
64958
|
+
return endsAtFailureExit(deviations) ? `Failure Path: ${flow.name} [${bracket}]` : `Variant: ${flow.name} [${bracket}]`;
|
|
64939
64959
|
}
|
|
64940
64960
|
function resolveScenarioKind(reachedBranches) {
|
|
64941
64961
|
const deviations = reachedBranches.filter((b) => !b.isFirstArm);
|
|
64942
64962
|
if (deviations.length === 0)
|
|
64943
64963
|
return "happy";
|
|
64944
|
-
return deviations
|
|
64964
|
+
return endsAtFailureExit(deviations) ? "failure" : "variant";
|
|
64965
|
+
}
|
|
64966
|
+
function endsAtFailureExit(deviations) {
|
|
64967
|
+
return deviations.some((b) => b.armHasFailureExit);
|
|
64945
64968
|
}
|
|
64946
64969
|
function buildContextMap(ir) {
|
|
64947
64970
|
return new Map(ir.contexts.map((c) => [c.id, c]));
|
|
@@ -65021,6 +65044,10 @@ function selectBranch(moment, branchSelections, state) {
|
|
|
65021
65044
|
const branch = (selected ? branches.find((b) => b.condition === selected) : void 0) ?? branches[0];
|
|
65022
65045
|
return { branch, forced };
|
|
65023
65046
|
}
|
|
65047
|
+
function armEndsAtFailureExit(branch) {
|
|
65048
|
+
const exit = branch.entries.find((e) => e.terminal);
|
|
65049
|
+
return exit !== void 0 && exit.exit !== "outcome";
|
|
65050
|
+
}
|
|
65024
65051
|
function recordBranchPoint(state, moment, branch, branchIdx, forced) {
|
|
65025
65052
|
state.activations.push({ momentName: moment.name, condition: branch.condition });
|
|
65026
65053
|
if (!forced && !state.reachedNames.has(moment.name)) {
|
|
@@ -65029,7 +65056,7 @@ function recordBranchPoint(state, moment, branch, branchIdx, forced) {
|
|
|
65029
65056
|
momentName: moment.name,
|
|
65030
65057
|
condition: branch.condition,
|
|
65031
65058
|
isFirstArm: branchIdx === 0,
|
|
65032
|
-
|
|
65059
|
+
armHasFailureExit: armEndsAtFailureExit(branch)
|
|
65033
65060
|
});
|
|
65034
65061
|
}
|
|
65035
65062
|
}
|
|
@@ -65278,23 +65305,40 @@ function findEventAfter(events, eventType, afterIndex) {
|
|
|
65278
65305
|
function deriveNegativeScenarios(ir, flow, options) {
|
|
65279
65306
|
const contextMap = buildContextMap(ir);
|
|
65280
65307
|
const opts = resolveOptions(flow, options);
|
|
65281
|
-
const walk = walkPath(flow, opts.branchSelections);
|
|
65282
|
-
const nodes = walk.nodes;
|
|
65283
65308
|
const scenarios = [];
|
|
65284
65309
|
const usedIds = /* @__PURE__ */ new Set();
|
|
65285
|
-
|
|
65286
|
-
|
|
65287
|
-
const
|
|
65288
|
-
|
|
65289
|
-
|
|
65290
|
-
|
|
65291
|
-
|
|
65292
|
-
|
|
65293
|
-
const
|
|
65294
|
-
|
|
65295
|
-
|
|
65296
|
-
|
|
65310
|
+
const covered = /* @__PURE__ */ new Set();
|
|
65311
|
+
const deriveOnPath = (walk, onlyUncovered) => {
|
|
65312
|
+
const nodes = walk.nodes;
|
|
65313
|
+
for (let i = 0; i < nodes.length; i++) {
|
|
65314
|
+
const node = nodes[i];
|
|
65315
|
+
const kind = resolveNodeKind(node.nodeName, node.contextId, contextMap, node.nodeKind);
|
|
65316
|
+
if (kind !== "command")
|
|
65317
|
+
continue;
|
|
65318
|
+
for (const pre of findPreconditions(node, contextMap)) {
|
|
65319
|
+
const key = [node.nodeName, pre.name, node.cause ?? ""].join("\0");
|
|
65320
|
+
if (onlyUncovered && covered.has(key))
|
|
65321
|
+
continue;
|
|
65322
|
+
covered.add(key);
|
|
65323
|
+
const baseId = `${opts.scenarioId}-neg-${node.nodeName}-${pre.name}`;
|
|
65324
|
+
const scenarioId = usedIds.has(baseId) ? `${baseId}-${i}` : baseId;
|
|
65325
|
+
usedIds.add(scenarioId);
|
|
65326
|
+
usedIds.add(baseId);
|
|
65327
|
+
scenarios.push(buildNegativeScenario(ir, flow, walk, i, pre, contextMap, opts, scenarioId));
|
|
65328
|
+
}
|
|
65297
65329
|
}
|
|
65330
|
+
};
|
|
65331
|
+
deriveOnPath(walkPath(flow, opts.branchSelections), false);
|
|
65332
|
+
if (options?.branchSelections !== void 0)
|
|
65333
|
+
return scenarios;
|
|
65334
|
+
const seenPaths = /* @__PURE__ */ new Set();
|
|
65335
|
+
for (const selections of enumerateBranchCombinations(flow)) {
|
|
65336
|
+
const walk = walkPath(flow, selections);
|
|
65337
|
+
const pathKey = walk.nodes.map((n) => n.nodeId).join("|");
|
|
65338
|
+
if (seenPaths.has(pathKey))
|
|
65339
|
+
continue;
|
|
65340
|
+
seenPaths.add(pathKey);
|
|
65341
|
+
deriveOnPath(walk, true);
|
|
65298
65342
|
}
|
|
65299
65343
|
return scenarios;
|
|
65300
65344
|
}
|
|
@@ -66253,46 +66297,51 @@ function findProcess(nodeName, ctx) {
|
|
|
66253
66297
|
return null;
|
|
66254
66298
|
}
|
|
66255
66299
|
function buildConnections(flow) {
|
|
66256
|
-
return flow.connections.map((conn) => {
|
|
66257
|
-
|
|
66258
|
-
|
|
66259
|
-
|
|
66260
|
-
|
|
66261
|
-
|
|
66262
|
-
|
|
66263
|
-
|
|
66264
|
-
|
|
66265
|
-
|
|
66266
|
-
|
|
66267
|
-
|
|
66268
|
-
|
|
66269
|
-
|
|
66270
|
-
|
|
66271
|
-
};
|
|
66272
|
-
}
|
|
66300
|
+
return flow.connections.map((conn) => ({
|
|
66301
|
+
...buildConnection(conn),
|
|
66302
|
+
// ADR-044: the IR already states which arm declared the connection.
|
|
66303
|
+
...conn.branchCondition !== void 0 ? { branchCondition: conn.branchCondition } : {}
|
|
66304
|
+
}));
|
|
66305
|
+
}
|
|
66306
|
+
function buildConnection(conn) {
|
|
66307
|
+
const eventType = conn.eventId.replace(/^evt-/, "");
|
|
66308
|
+
const endpoints = {
|
|
66309
|
+
eventType,
|
|
66310
|
+
sourceNodeName: conn.sourceNodeName,
|
|
66311
|
+
targetNodeName: conn.targetNodeName
|
|
66312
|
+
};
|
|
66313
|
+
if (conn.connectionType === "returns-to") {
|
|
66314
|
+
if (conn.targetMomentId) {
|
|
66273
66315
|
return {
|
|
66274
66316
|
from: conn.sourceMomentId,
|
|
66275
|
-
to: conn.
|
|
66276
|
-
label: `unresolved returns-to target: ${conn.targetMomentLabel ?? "(unknown)"}`,
|
|
66317
|
+
to: conn.targetMomentId,
|
|
66277
66318
|
style: "return",
|
|
66278
66319
|
targetMomentLabel: conn.targetMomentLabel,
|
|
66279
66320
|
...endpoints
|
|
66280
66321
|
};
|
|
66281
66322
|
}
|
|
66282
|
-
const isCrossing2 = conn.connectionType === "crosses-to";
|
|
66283
66323
|
return {
|
|
66284
66324
|
from: conn.sourceMomentId,
|
|
66285
|
-
// For 'triggers' the core now resolves targetContextId to the context
|
|
66286
|
-
// where the TARGET node is placed (not the source's own lane).
|
|
66287
66325
|
to: conn.targetContextId,
|
|
66288
|
-
label:
|
|
66289
|
-
style:
|
|
66290
|
-
|
|
66291
|
-
relationship: isCrossing2 ? conn.schemaContract.relationshipType : void 0,
|
|
66292
|
-
schemaContract: isCrossing2 ? mapSchemaContract(conn) : void 0,
|
|
66326
|
+
label: `unresolved returns-to target: ${conn.targetMomentLabel ?? "(unknown)"}`,
|
|
66327
|
+
style: "return",
|
|
66328
|
+
targetMomentLabel: conn.targetMomentLabel,
|
|
66293
66329
|
...endpoints
|
|
66294
66330
|
};
|
|
66295
|
-
}
|
|
66331
|
+
}
|
|
66332
|
+
const isCrossing2 = conn.connectionType === "crosses-to";
|
|
66333
|
+
return {
|
|
66334
|
+
from: conn.sourceMomentId,
|
|
66335
|
+
// For 'triggers' the core now resolves targetContextId to the context
|
|
66336
|
+
// where the TARGET node is placed (not the source's own lane).
|
|
66337
|
+
to: conn.targetContextId,
|
|
66338
|
+
label: isCrossing2 ? eventType : void 0,
|
|
66339
|
+
style: mapConnectionStyle(conn),
|
|
66340
|
+
crossBoundary: isCrossing2 || void 0,
|
|
66341
|
+
relationship: isCrossing2 ? conn.schemaContract.relationshipType : void 0,
|
|
66342
|
+
schemaContract: isCrossing2 ? mapSchemaContract(conn) : void 0,
|
|
66343
|
+
...endpoints
|
|
66344
|
+
};
|
|
66296
66345
|
}
|
|
66297
66346
|
function mapConnectionStyle(conn) {
|
|
66298
66347
|
if (conn.connectionType === "crosses-to")
|
|
@@ -66565,12 +66614,16 @@ function renderNoteOnlyMoment(lines, moment, flow) {
|
|
|
66565
66614
|
lines.push(...noteComments(moment, flow, " "));
|
|
66566
66615
|
lines.push("");
|
|
66567
66616
|
}
|
|
66617
|
+
function armEndsAtOutcome(branchEntries) {
|
|
66618
|
+
return branchEntries.find((e) => e.terminal)?.exit === "outcome";
|
|
66619
|
+
}
|
|
66568
66620
|
function renderTerminalBranchScenario(lines, moment, condition, branchEntries, flow, ctxMap, ir) {
|
|
66569
|
-
const
|
|
66621
|
+
const endsAtOutcome = armEndsAtOutcome(branchEntries);
|
|
66622
|
+
const tags = ["@terminal", endsAtOutcome ? "@alt-path" : "@failure-path"];
|
|
66570
66623
|
lines.push(` ${tags.join(" ")}`);
|
|
66571
66624
|
lines.push(` Scenario: ${moment.name} [${condition}]`);
|
|
66572
66625
|
lines.push(...noteComments(moment, flow, " "));
|
|
66573
|
-
const failedPrecondition = findFailedPrecondition(moment, ctxMap);
|
|
66626
|
+
const failedPrecondition = endsAtOutcome ? void 0 : findFailedPrecondition(moment, ctxMap);
|
|
66574
66627
|
lines.push(` Given the ${moment.name.toLowerCase()} is evaluated`);
|
|
66575
66628
|
if (failedPrecondition) {
|
|
66576
66629
|
lines.push(` When ${failedPrecondition.name} is not satisfied`);
|
|
@@ -66585,7 +66638,8 @@ function renderTerminalBranchScenario(lines, moment, condition, branchEntries, f
|
|
|
66585
66638
|
lines.push(` Then the flow terminates because ${failedPrecondition.description}`);
|
|
66586
66639
|
} else {
|
|
66587
66640
|
const terminalNode = branchEntries.find((e) => e.terminal)?.nodeName;
|
|
66588
|
-
|
|
66641
|
+
const verb = endsAtOutcome ? "ends" : "terminates";
|
|
66642
|
+
lines.push(` Then the flow ${verb}${terminalNode ? ` at ${terminalNode}` : ""}`);
|
|
66589
66643
|
}
|
|
66590
66644
|
const compensation = findCompensationForMoment(moment, ir);
|
|
66591
66645
|
if (compensation) {
|
|
@@ -66714,7 +66768,7 @@ function readOrEmit(entry) {
|
|
|
66714
66768
|
return "emits";
|
|
66715
66769
|
}
|
|
66716
66770
|
function renderInternalEventStep(lines, entry, evt, ctxName) {
|
|
66717
|
-
const modifier = entry.optional ? " (optional)" : entry.terminal ? " (terminal)" : "";
|
|
66771
|
+
const modifier = entry.optional ? " (optional)" : entry.terminal ? entry.exit === "outcome" ? " (outcome)" : " (terminal)" : "";
|
|
66718
66772
|
lines.push(` Then ${ctxName} ${readOrEmit(entry)} ${entry.nodeName}${modifier}`);
|
|
66719
66773
|
if (evt && evt.fields.length > 0) {
|
|
66720
66774
|
lines.push(` carrying ${evt.fields.map((f) => f.name).join(", ")}`);
|
|
@@ -67221,8 +67275,10 @@ var SpecificationDocumentGenerator = class {
|
|
|
67221
67275
|
}
|
|
67222
67276
|
renderTerminalBranch(lines, moment, branch, flow, ir) {
|
|
67223
67277
|
const usedConnections = /* @__PURE__ */ new Set();
|
|
67224
|
-
const
|
|
67225
|
-
|
|
67278
|
+
const exit = branch.entries.find((e) => e.terminal);
|
|
67279
|
+
const terminalNode = exit?.nodeName;
|
|
67280
|
+
const [mark, verb] = exit?.exit === "outcome" ? ["\u2705", "ends"] : ["\u274C", "terminates"];
|
|
67281
|
+
lines.push(` - ${mark} **If ${branch.condition}:** flow ${verb}${terminalNode ? ` at **${terminalNode}**` : ""}`);
|
|
67226
67282
|
for (const entry of branch.entries) {
|
|
67227
67283
|
if (entry.terminal)
|
|
67228
67284
|
continue;
|
|
@@ -67548,8 +67604,11 @@ var SpecificationDocumentGenerator = class {
|
|
|
67548
67604
|
}
|
|
67549
67605
|
renderBranchAltBlock(lines, moment, ctxName, flow, ir) {
|
|
67550
67606
|
const nonTerminal = moment.branches.filter((b) => !b.entries.some((e) => e.terminal));
|
|
67551
|
-
const
|
|
67552
|
-
|
|
67607
|
+
const ending = moment.branches.filter((b) => b.entries.some((e) => e.terminal));
|
|
67608
|
+
const isOutcome = (b) => b.entries.find((e) => e.terminal)?.exit === "outcome";
|
|
67609
|
+
const terminal = ending.filter((b) => !isOutcome(b));
|
|
67610
|
+
const outcome = ending.filter(isOutcome);
|
|
67611
|
+
if (nonTerminal.length === 0 && ending.length === 0)
|
|
67553
67612
|
return;
|
|
67554
67613
|
for (let i = 0; i < nonTerminal.length; i++) {
|
|
67555
67614
|
const branch = nonTerminal[i];
|
|
@@ -67557,11 +67616,16 @@ var SpecificationDocumentGenerator = class {
|
|
|
67557
67616
|
lines.push(` ${keyword} ${branch.condition}`);
|
|
67558
67617
|
this.renderSequenceEntries(lines, branch.entries, moment, branch.condition, flow, ir);
|
|
67559
67618
|
}
|
|
67560
|
-
|
|
67561
|
-
|
|
67562
|
-
|
|
67563
|
-
|
|
67564
|
-
|
|
67619
|
+
let opened = nonTerminal.length > 0;
|
|
67620
|
+
for (const [arms, note] of [
|
|
67621
|
+
[terminal, "Flow terminates"],
|
|
67622
|
+
[outcome, "Flow ends at an outcome"]
|
|
67623
|
+
]) {
|
|
67624
|
+
if (arms.length === 0)
|
|
67625
|
+
continue;
|
|
67626
|
+
lines.push(` ${opened ? "else" : "alt"} ${arms.map((b) => b.condition).join(" / ")}`);
|
|
67627
|
+
lines.push(` Note over ${ctxName}: ${note}`);
|
|
67628
|
+
opened = true;
|
|
67565
67629
|
}
|
|
67566
67630
|
lines.push(" end");
|
|
67567
67631
|
}
|