@pipelex/mthds-ui 0.29.0 → 0.30.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/README.md +14 -8
- package/dist/{chunk-ZTXSDTVF.js → chunk-3BXB6HSF.js} +1304 -31
- package/dist/chunk-3BXB6HSF.js.map +1 -0
- package/dist/{chunk-Y46574OW.js → chunk-GAOBB3UT.js} +5 -2
- package/dist/chunk-GAOBB3UT.js.map +1 -0
- package/dist/chunk-KB2DIEVF.js +1 -0
- package/dist/{chunk-3I3ZPYMW.js → chunk-PJTYQURQ.js} +33 -1
- package/dist/chunk-PJTYQURQ.js.map +1 -0
- package/dist/form/react/index.d.ts +1 -1
- package/dist/form/react/index.js +2 -2
- package/dist/graph/index.d.ts +336 -9
- package/dist/graph/index.js +98 -4
- package/dist/graph/react/index.d.ts +26 -2
- package/dist/graph/react/index.js +975 -371
- package/dist/graph/react/index.js.map +1 -1
- package/dist/graph/react/styles/simple/SimpleStyle.css +434 -0
- package/dist/graph/react/viewer/GraphToolbar.css +114 -0
- package/dist/index.d.ts +2 -2
- package/dist/index.js +98 -4
- package/dist/standalone/graph-standalone.html +714 -165
- package/dist/standalone/graph-viewer.css +549 -0
- package/dist/standalone/graph-viewer.js +164 -164
- package/dist/static-graph/index.d.ts +1 -1
- package/dist/static-graph/index.js +1 -1
- package/dist/{types-BaFWy56P.d.ts → types-BNqjYF_x.d.ts} +152 -1
- package/package.json +2 -1
- package/dist/chunk-3I3ZPYMW.js.map +0 -1
- package/dist/chunk-F6TZIJ7A.js +0 -1
- package/dist/chunk-Y46574OW.js.map +0 -1
- package/dist/chunk-ZTXSDTVF.js.map +0 -1
- package/dist/graph/react/index.css +0 -749
- package/dist/graph/react/index.css.map +0 -1
- /package/dist/{chunk-F6TZIJ7A.js.map → chunk-KB2DIEVF.js.map} +0 -0
|
@@ -1,25 +1,37 @@
|
|
|
1
1
|
import {
|
|
2
|
-
makePipeRef
|
|
2
|
+
makePipeRef,
|
|
3
|
+
parsePipeRef
|
|
3
4
|
} from "./chunk-2N65P32H.js";
|
|
5
|
+
import {
|
|
6
|
+
DEFAULT_GRAPH_CONFIG
|
|
7
|
+
} from "./chunk-GAOBB3UT.js";
|
|
4
8
|
import {
|
|
5
9
|
ARROW_CLOSED_MARKER,
|
|
6
10
|
BINDING_STEP_TYPE,
|
|
7
11
|
CONTROLLER_PADDING_BOTTOM,
|
|
8
12
|
CONTROLLER_PADDING_TOP,
|
|
9
13
|
CONTROLLER_PADDING_X,
|
|
14
|
+
EDGE_TYPE_ROUTED,
|
|
15
|
+
GRAPH_STYLE,
|
|
10
16
|
KNOWN_PIPE_TYPES,
|
|
11
17
|
NODE_TYPE_CONTROLLER,
|
|
12
18
|
NODE_TYPE_PIPE_CARD,
|
|
19
|
+
NODE_TYPE_SIMPLE_DECISION,
|
|
20
|
+
NODE_TYPE_SIMPLE_FRAME,
|
|
21
|
+
NODE_TYPE_SIMPLE_STEP,
|
|
22
|
+
NODE_TYPE_SIMPLE_TERMINAL,
|
|
13
23
|
NODE_TYPE_STUFF,
|
|
24
|
+
STEP_CATEGORY,
|
|
14
25
|
graphSpecMode,
|
|
15
26
|
isBindingNode,
|
|
27
|
+
isPluralMultiplicity,
|
|
16
28
|
isStuffNodeId,
|
|
17
29
|
multiplicitySuffix,
|
|
18
30
|
nodeHeight,
|
|
19
31
|
nodeWidth,
|
|
20
32
|
stuffDigestFromId,
|
|
21
33
|
stuffNodeId
|
|
22
|
-
} from "./chunk-
|
|
34
|
+
} from "./chunk-PJTYQURQ.js";
|
|
23
35
|
import {
|
|
24
36
|
__objRest,
|
|
25
37
|
__spreadProps,
|
|
@@ -934,13 +946,12 @@ function issueTargetIds(issue, graphspec) {
|
|
|
934
946
|
}
|
|
935
947
|
return [];
|
|
936
948
|
}
|
|
937
|
-
function buildValidationDecorations(issues, graphspec, childToCtrl, foldedSet) {
|
|
938
|
-
var _a;
|
|
949
|
+
function buildValidationDecorations(issues, graphspec, childToCtrl, foldedSet, standIns) {
|
|
939
950
|
const decorations = /* @__PURE__ */ new Map();
|
|
940
951
|
if (!issues || issues.length === 0 || !graphspec) return decorations;
|
|
941
952
|
for (const issue of issues) {
|
|
942
953
|
for (const targetId of issueTargetIds(issue, graphspec)) {
|
|
943
|
-
const visibleId = (
|
|
954
|
+
const visibleId = visibleNodeId(targetId, childToCtrl, foldedSet, standIns);
|
|
944
955
|
const existing = decorations.get(visibleId);
|
|
945
956
|
const lines = [issue.message, ...issue.suggestedFix ? [`Fix: ${issue.suggestedFix}`] : []];
|
|
946
957
|
if (existing) {
|
|
@@ -954,11 +965,15 @@ function buildValidationDecorations(issues, graphspec, childToCtrl, foldedSet) {
|
|
|
954
965
|
}
|
|
955
966
|
return decorations;
|
|
956
967
|
}
|
|
957
|
-
function
|
|
958
|
-
var _a;
|
|
968
|
+
function visibleNodeId(targetId, childToCtrl, foldedSet, standIns) {
|
|
969
|
+
var _a, _b;
|
|
970
|
+
const unfolded = (_a = outermostFoldedAncestor(targetId, childToCtrl, foldedSet)) != null ? _a : targetId;
|
|
971
|
+
return (_b = standIns == null ? void 0 : standIns.get(unfolded)) != null ? _b : unfolded;
|
|
972
|
+
}
|
|
973
|
+
function resolveIssueTargetNodeId(issue, graphspec, childToCtrl, foldedSet, renderedNodeIds, standIns) {
|
|
959
974
|
if (!graphspec) return null;
|
|
960
975
|
for (const targetId of issueTargetIds(issue, graphspec)) {
|
|
961
|
-
const visibleId = (
|
|
976
|
+
const visibleId = visibleNodeId(targetId, childToCtrl, foldedSet, standIns);
|
|
962
977
|
if (renderedNodeIds.has(visibleId)) return visibleId;
|
|
963
978
|
}
|
|
964
979
|
return null;
|
|
@@ -1133,6 +1148,7 @@ function countTbPillRows(pills, cardWidth) {
|
|
|
1133
1148
|
function estimateNodeDimensions(node, isHorizontal) {
|
|
1134
1149
|
var _a, _b, _c;
|
|
1135
1150
|
const nodeData = node.data || {};
|
|
1151
|
+
if (nodeData.layoutSize) return __spreadValues({}, nodeData.layoutSize);
|
|
1136
1152
|
const isStuff = nodeData.isStuff;
|
|
1137
1153
|
const labelText = nodeData.labelText || "";
|
|
1138
1154
|
const isPipeCard = node.type === NODE_TYPE_PIPE_CARD;
|
|
@@ -1217,11 +1233,35 @@ function makeLeafNode(nodeId, dims, direction) {
|
|
|
1217
1233
|
}
|
|
1218
1234
|
};
|
|
1219
1235
|
}
|
|
1236
|
+
function makeElkEdge(edge, routeEdges) {
|
|
1237
|
+
const elkEdge = {
|
|
1238
|
+
id: edge.id,
|
|
1239
|
+
sources: [outputPortId(edge.source)],
|
|
1240
|
+
targets: [inputPortId(edge.target)]
|
|
1241
|
+
};
|
|
1242
|
+
if (routeEdges && edge.label && edge.labelSize) {
|
|
1243
|
+
elkEdge.labels = [
|
|
1244
|
+
{
|
|
1245
|
+
id: `${edge.id}_label`,
|
|
1246
|
+
text: edge.label,
|
|
1247
|
+
width: edge.labelSize.width,
|
|
1248
|
+
height: edge.labelSize.height
|
|
1249
|
+
}
|
|
1250
|
+
];
|
|
1251
|
+
}
|
|
1252
|
+
return elkEdge;
|
|
1253
|
+
}
|
|
1220
1254
|
function buildElkGraph(nodes, edges, graphspec, analysis, direction, layoutConfig) {
|
|
1221
|
-
var _a, _b, _c;
|
|
1255
|
+
var _a, _b, _c, _d, _e;
|
|
1222
1256
|
const isHorizontal = direction === "LR" || direction === "RL";
|
|
1223
1257
|
const nodesep = (_a = layoutConfig == null ? void 0 : layoutConfig.nodesep) != null ? _a : 80;
|
|
1224
1258
|
const ranksep = (_b = layoutConfig == null ? void 0 : layoutConfig.ranksep) != null ? _b : 70;
|
|
1259
|
+
const routeEdges = (_c = layoutConfig == null ? void 0 : layoutConfig.routeEdges) != null ? _c : false;
|
|
1260
|
+
const groupPadding = (_d = layoutConfig == null ? void 0 : layoutConfig.groupPadding) != null ? _d : {
|
|
1261
|
+
x: CONTROLLER_PADDING_X,
|
|
1262
|
+
top: CONTROLLER_PADDING_TOP,
|
|
1263
|
+
bottom: CONTROLLER_PADDING_BOTTOM
|
|
1264
|
+
};
|
|
1225
1265
|
const elkDir = elkDirection(direction);
|
|
1226
1266
|
const edgeNodeSpacing = "30";
|
|
1227
1267
|
const rootLayoutOptions = {
|
|
@@ -1236,6 +1276,9 @@ function buildElkGraph(nodes, edges, graphspec, analysis, direction, layoutConfi
|
|
|
1236
1276
|
"elk.layered.spacing.edgeEdgeBetweenLayers": "15",
|
|
1237
1277
|
"elk.layered.nodePlacement.favorStraightEdges": "true"
|
|
1238
1278
|
};
|
|
1279
|
+
if (routeEdges) {
|
|
1280
|
+
rootLayoutOptions["elk.json.edgeCoords"] = "ROOT";
|
|
1281
|
+
}
|
|
1239
1282
|
if (!graphspec || !analysis || analysis.controllerNodeIds.size === 0) {
|
|
1240
1283
|
const dimensionMap2 = {};
|
|
1241
1284
|
const elkChildren = nodes.map((node) => {
|
|
@@ -1243,11 +1286,7 @@ function buildElkGraph(nodes, edges, graphspec, analysis, direction, layoutConfi
|
|
|
1243
1286
|
dimensionMap2[node.id] = dims;
|
|
1244
1287
|
return makeLeafNode(node.id, dims, direction);
|
|
1245
1288
|
});
|
|
1246
|
-
const elkEdges2 = edges.map((edge) => (
|
|
1247
|
-
id: edge.id,
|
|
1248
|
-
sources: [outputPortId(edge.source)],
|
|
1249
|
-
targets: [inputPortId(edge.target)]
|
|
1250
|
-
}));
|
|
1289
|
+
const elkEdges2 = edges.map((edge) => makeElkEdge(edge, routeEdges));
|
|
1251
1290
|
return {
|
|
1252
1291
|
elkGraph: {
|
|
1253
1292
|
id: "root",
|
|
@@ -1270,11 +1309,11 @@ function buildElkGraph(nodes, edges, graphspec, analysis, direction, layoutConfi
|
|
|
1270
1309
|
return ((_a2 = depths[a]) != null ? _a2 : 0) - ((_b2 = depths[b]) != null ? _b2 : 0);
|
|
1271
1310
|
});
|
|
1272
1311
|
for (const ctrlId of controllerIds) {
|
|
1273
|
-
const depth = (
|
|
1312
|
+
const depth = (_e = depths[ctrlId]) != null ? _e : 0;
|
|
1274
1313
|
const depthScale = 1 + depth * 0.15;
|
|
1275
|
-
const padX = Math.round(
|
|
1276
|
-
const padTop = Math.round(
|
|
1277
|
-
const padBottom = Math.round(
|
|
1314
|
+
const padX = Math.round(groupPadding.x * depthScale);
|
|
1315
|
+
const padTop = Math.round(groupPadding.top * depthScale);
|
|
1316
|
+
const padBottom = Math.round(groupPadding.bottom * depthScale);
|
|
1278
1317
|
const ctrlLayoutOptions = {
|
|
1279
1318
|
"elk.padding": `[top=${padTop},left=${padX},bottom=${padBottom},right=${padX}]`,
|
|
1280
1319
|
"elk.spacing.nodeNode": String(nodesep),
|
|
@@ -1327,11 +1366,7 @@ function buildElkGraph(nodes, edges, graphspec, analysis, direction, layoutConfi
|
|
|
1327
1366
|
}
|
|
1328
1367
|
}
|
|
1329
1368
|
const nodeIdSet = new Set(nodes.map((n) => n.id));
|
|
1330
|
-
const elkEdges = edges.filter((e) => nodeIdSet.has(e.source) && nodeIdSet.has(e.target)).map((edge) => (
|
|
1331
|
-
id: edge.id,
|
|
1332
|
-
sources: [outputPortId(edge.source)],
|
|
1333
|
-
targets: [inputPortId(edge.target)]
|
|
1334
|
-
}));
|
|
1369
|
+
const elkEdges = edges.filter((e) => nodeIdSet.has(e.source) && nodeIdSet.has(e.target)).map((edge) => makeElkEdge(edge, routeEdges));
|
|
1335
1370
|
return {
|
|
1336
1371
|
elkGraph: {
|
|
1337
1372
|
id: "root",
|
|
@@ -1363,6 +1398,38 @@ function extractAbsolutePositions(elkResult) {
|
|
|
1363
1398
|
walk(elkResult, 0, 0);
|
|
1364
1399
|
return positions;
|
|
1365
1400
|
}
|
|
1401
|
+
function extractEdgeRoutes(elkResult) {
|
|
1402
|
+
const routes = {};
|
|
1403
|
+
function walk(node) {
|
|
1404
|
+
var _a, _b, _c, _d, _e, _f, _g;
|
|
1405
|
+
for (const edge of (_a = node.edges) != null ? _a : []) {
|
|
1406
|
+
const points = [];
|
|
1407
|
+
for (const section of (_b = edge.sections) != null ? _b : []) {
|
|
1408
|
+
for (const point of [section.startPoint, ...(_c = section.bendPoints) != null ? _c : [], section.endPoint]) {
|
|
1409
|
+
const last = points[points.length - 1];
|
|
1410
|
+
if (!last || last.x !== point.x || last.y !== point.y) {
|
|
1411
|
+
points.push({ x: point.x, y: point.y });
|
|
1412
|
+
}
|
|
1413
|
+
}
|
|
1414
|
+
}
|
|
1415
|
+
if (points.length < 2) continue;
|
|
1416
|
+
const route = { points };
|
|
1417
|
+
const label = (_d = edge.labels) == null ? void 0 : _d[0];
|
|
1418
|
+
if (label && label.x !== void 0 && label.y !== void 0) {
|
|
1419
|
+
route.label = {
|
|
1420
|
+
x: label.x,
|
|
1421
|
+
y: label.y,
|
|
1422
|
+
width: (_e = label.width) != null ? _e : 0,
|
|
1423
|
+
height: (_f = label.height) != null ? _f : 0
|
|
1424
|
+
};
|
|
1425
|
+
}
|
|
1426
|
+
routes[edge.id] = route;
|
|
1427
|
+
}
|
|
1428
|
+
for (const child of (_g = node.children) != null ? _g : []) walk(child);
|
|
1429
|
+
}
|
|
1430
|
+
walk(elkResult);
|
|
1431
|
+
return routes;
|
|
1432
|
+
}
|
|
1366
1433
|
|
|
1367
1434
|
// src/graph/graphLayout.ts
|
|
1368
1435
|
import ELK from "elkjs/lib/elk.bundled.js";
|
|
@@ -1422,7 +1489,98 @@ async function getLayoutedElements(nodes, edges, direction, layoutConfig, graphs
|
|
|
1422
1489
|
targetPosition: isHorizontal ? direction === "LR" ? "left" : "right" : direction === "TB" ? "top" : "bottom"
|
|
1423
1490
|
});
|
|
1424
1491
|
});
|
|
1425
|
-
return { nodes: result, edges, controllerPositions };
|
|
1492
|
+
if (!(layoutConfig == null ? void 0 : layoutConfig.routeEdges)) return { nodes: result, edges, controllerPositions };
|
|
1493
|
+
const routes = extractEdgeRoutes(layoutResult);
|
|
1494
|
+
const routedEdges = edges.map((edge) => {
|
|
1495
|
+
const route = routes[edge.id];
|
|
1496
|
+
return route ? __spreadProps(__spreadValues({}, edge), { route }) : edge;
|
|
1497
|
+
});
|
|
1498
|
+
return { nodes: result, edges: routedEdges, controllerPositions };
|
|
1499
|
+
}
|
|
1500
|
+
|
|
1501
|
+
// src/graph/edgeRoutes.ts
|
|
1502
|
+
var ROUTE_ENDPOINT_TOLERANCE_PX = 8;
|
|
1503
|
+
var ROUTE_CORNER_RADIUS_PX = 8;
|
|
1504
|
+
var SAME_AXIS_EPSILON = 0.5;
|
|
1505
|
+
function near(a, b, tolerance) {
|
|
1506
|
+
return Math.abs(a.x - b.x) <= tolerance && Math.abs(a.y - b.y) <= tolerance;
|
|
1507
|
+
}
|
|
1508
|
+
function fitRoute(points, source, target, tolerance = ROUTE_ENDPOINT_TOLERANCE_PX) {
|
|
1509
|
+
if (points.length < 2) return null;
|
|
1510
|
+
const first = points[0];
|
|
1511
|
+
const last = points[points.length - 1];
|
|
1512
|
+
if (!near(first, source, tolerance) || !near(last, target, tolerance)) return null;
|
|
1513
|
+
const fitted = points.map((p) => ({ x: p.x, y: p.y }));
|
|
1514
|
+
const end = fitted.length - 1;
|
|
1515
|
+
if (fitted.length > 2) {
|
|
1516
|
+
alignNeighbour(fitted, 0, 1, source);
|
|
1517
|
+
alignNeighbour(fitted, end, end - 1, target);
|
|
1518
|
+
}
|
|
1519
|
+
fitted[0] = { x: source.x, y: source.y };
|
|
1520
|
+
fitted[end] = { x: target.x, y: target.y };
|
|
1521
|
+
return fitted;
|
|
1522
|
+
}
|
|
1523
|
+
function alignNeighbour(points, endIndex, neighbourIndex, to) {
|
|
1524
|
+
const end = points[endIndex];
|
|
1525
|
+
const neighbour = points[neighbourIndex];
|
|
1526
|
+
if (Math.abs(end.y - neighbour.y) <= SAME_AXIS_EPSILON) neighbour.y = to.y;
|
|
1527
|
+
else if (Math.abs(end.x - neighbour.x) <= SAME_AXIS_EPSILON) neighbour.x = to.x;
|
|
1528
|
+
}
|
|
1529
|
+
function roundedPolylinePath(points, radius = ROUTE_CORNER_RADIUS_PX) {
|
|
1530
|
+
if (points.length === 0) return "";
|
|
1531
|
+
const parts = [`M ${points[0].x},${points[0].y}`];
|
|
1532
|
+
for (let i = 1; i < points.length - 1; i++) {
|
|
1533
|
+
const previous = points[i - 1];
|
|
1534
|
+
const bend = points[i];
|
|
1535
|
+
const next = points[i + 1];
|
|
1536
|
+
const inLength = Math.hypot(bend.x - previous.x, bend.y - previous.y);
|
|
1537
|
+
const outLength = Math.hypot(next.x - bend.x, next.y - bend.y);
|
|
1538
|
+
const r = Math.min(radius, inLength / 2, outLength / 2);
|
|
1539
|
+
if (r <= 0) {
|
|
1540
|
+
parts.push(`L ${bend.x},${bend.y}`);
|
|
1541
|
+
continue;
|
|
1542
|
+
}
|
|
1543
|
+
const before = {
|
|
1544
|
+
x: bend.x + (previous.x - bend.x) / inLength * r,
|
|
1545
|
+
y: bend.y + (previous.y - bend.y) / inLength * r
|
|
1546
|
+
};
|
|
1547
|
+
const after = {
|
|
1548
|
+
x: bend.x + (next.x - bend.x) / outLength * r,
|
|
1549
|
+
y: bend.y + (next.y - bend.y) / outLength * r
|
|
1550
|
+
};
|
|
1551
|
+
parts.push(`L ${before.x},${before.y}`, `Q ${bend.x},${bend.y} ${after.x},${after.y}`);
|
|
1552
|
+
}
|
|
1553
|
+
const last = points[points.length - 1];
|
|
1554
|
+
parts.push(`L ${last.x},${last.y}`);
|
|
1555
|
+
return parts.join(" ");
|
|
1556
|
+
}
|
|
1557
|
+
function polylineMidpoint(points) {
|
|
1558
|
+
if (points.length === 0) return { x: 0, y: 0 };
|
|
1559
|
+
let total = 0;
|
|
1560
|
+
for (let i = 1; i < points.length; i++) {
|
|
1561
|
+
total += Math.hypot(points[i].x - points[i - 1].x, points[i].y - points[i - 1].y);
|
|
1562
|
+
}
|
|
1563
|
+
let remaining = total / 2;
|
|
1564
|
+
for (let i = 1; i < points.length; i++) {
|
|
1565
|
+
const a = points[i - 1];
|
|
1566
|
+
const b = points[i];
|
|
1567
|
+
const length = Math.hypot(b.x - a.x, b.y - a.y);
|
|
1568
|
+
if (length >= remaining && length > 0) {
|
|
1569
|
+
const t = remaining / length;
|
|
1570
|
+
return { x: a.x + (b.x - a.x) * t, y: a.y + (b.y - a.y) * t };
|
|
1571
|
+
}
|
|
1572
|
+
remaining -= length;
|
|
1573
|
+
}
|
|
1574
|
+
return points[points.length - 1];
|
|
1575
|
+
}
|
|
1576
|
+
function routeLabelCenter(route, fitted) {
|
|
1577
|
+
if (route.label) {
|
|
1578
|
+
return {
|
|
1579
|
+
x: route.label.x + route.label.width / 2,
|
|
1580
|
+
y: route.label.y + route.label.height / 2
|
|
1581
|
+
};
|
|
1582
|
+
}
|
|
1583
|
+
return polylineMidpoint(fitted);
|
|
1426
1584
|
}
|
|
1427
1585
|
|
|
1428
1586
|
// src/graph/graphControllers.ts
|
|
@@ -1655,9 +1813,11 @@ function applyControllers(layoutedNodes, layoutedEdges, graphspec, analysis, sho
|
|
|
1655
1813
|
cn.data.onToggleFold = (options) => onToggleFold(id, options);
|
|
1656
1814
|
}
|
|
1657
1815
|
}
|
|
1658
|
-
|
|
1816
|
+
return { nodes: sortParentsFirst([...controllerNodes, ...filteredNodes]), edges: filteredEdges };
|
|
1817
|
+
}
|
|
1818
|
+
function sortParentsFirst(nodes) {
|
|
1659
1819
|
const nodeMap = {};
|
|
1660
|
-
for (const n of
|
|
1820
|
+
for (const n of nodes) nodeMap[n.id] = n;
|
|
1661
1821
|
const depthOf = {};
|
|
1662
1822
|
const depthVisiting = /* @__PURE__ */ new Set();
|
|
1663
1823
|
function getContainmentDepth(id) {
|
|
@@ -1673,11 +1833,1084 @@ function applyControllers(layoutedNodes, layoutedEdges, graphspec, analysis, sho
|
|
|
1673
1833
|
depthVisiting.delete(id);
|
|
1674
1834
|
return depthOf[id];
|
|
1675
1835
|
}
|
|
1676
|
-
for (const n of
|
|
1677
|
-
|
|
1678
|
-
|
|
1836
|
+
for (const n of nodes) getContainmentDepth(n.id);
|
|
1837
|
+
return [...nodes].sort((a, b) => depthOf[a.id] - depthOf[b.id]);
|
|
1838
|
+
}
|
|
1839
|
+
|
|
1840
|
+
// src/graph/styles/graphStyles.ts
|
|
1841
|
+
var GRAPH_STYLES = {
|
|
1842
|
+
[GRAPH_STYLE.DETAILED]: {
|
|
1843
|
+
id: GRAPH_STYLE.DETAILED,
|
|
1844
|
+
name: "Detailed",
|
|
1845
|
+
description: "Every pipe with its inputs, outputs and settings",
|
|
1846
|
+
capabilities: { controllerFrameToggle: true, foldAll: true }
|
|
1847
|
+
},
|
|
1848
|
+
[GRAPH_STYLE.SIMPLE]: {
|
|
1849
|
+
id: GRAPH_STYLE.SIMPLE,
|
|
1850
|
+
name: "Simple",
|
|
1851
|
+
description: "The method's steps in plain words",
|
|
1852
|
+
capabilities: { controllerFrameToggle: false, foldAll: true },
|
|
1853
|
+
layout: {
|
|
1854
|
+
nodesep: 28,
|
|
1855
|
+
ranksep: 44,
|
|
1856
|
+
routeEdges: true,
|
|
1857
|
+
groupPadding: { x: 20, top: 40, bottom: 16 }
|
|
1858
|
+
}
|
|
1859
|
+
}
|
|
1860
|
+
};
|
|
1861
|
+
var GRAPH_STYLE_IDS = [GRAPH_STYLE.DETAILED, GRAPH_STYLE.SIMPLE];
|
|
1862
|
+
function isGraphStyleId(value) {
|
|
1863
|
+
return typeof value === "string" && Object.hasOwn(GRAPH_STYLES, value);
|
|
1864
|
+
}
|
|
1865
|
+
function resolveGraphStyle(styleProp, configStyle) {
|
|
1866
|
+
if (isGraphStyleId(styleProp)) return styleProp;
|
|
1867
|
+
if (isGraphStyleId(configStyle)) return configStyle;
|
|
1868
|
+
return DEFAULT_GRAPH_CONFIG.graphStyle;
|
|
1869
|
+
}
|
|
1870
|
+
function resolveStyleMenu(styleMenu) {
|
|
1871
|
+
if (styleMenu === void 0 || styleMenu === false) return [];
|
|
1872
|
+
const requested = styleMenu === true ? GRAPH_STYLE_IDS : styleMenu;
|
|
1873
|
+
const offered = [];
|
|
1874
|
+
for (const id of requested) {
|
|
1875
|
+
if (isGraphStyleId(id) && !offered.includes(id)) offered.push(id);
|
|
1876
|
+
}
|
|
1877
|
+
return offered.length >= 2 ? offered : [];
|
|
1878
|
+
}
|
|
1879
|
+
|
|
1880
|
+
// src/graph/styles/humanize.ts
|
|
1881
|
+
var VOWELED_ACRONYMS = /* @__PURE__ */ new Set([
|
|
1882
|
+
"ai",
|
|
1883
|
+
"api",
|
|
1884
|
+
"faq",
|
|
1885
|
+
"iban",
|
|
1886
|
+
"id",
|
|
1887
|
+
"io",
|
|
1888
|
+
"ip",
|
|
1889
|
+
"json",
|
|
1890
|
+
"kpi",
|
|
1891
|
+
"ocr",
|
|
1892
|
+
"roi",
|
|
1893
|
+
"seo",
|
|
1894
|
+
"ui",
|
|
1895
|
+
"uri",
|
|
1896
|
+
"url",
|
|
1897
|
+
"uuid",
|
|
1898
|
+
"ux"
|
|
1899
|
+
]);
|
|
1900
|
+
var VOWELS = /[aeiouy]/;
|
|
1901
|
+
var VOWELLESS_WORDS = /* @__PURE__ */ new Set([
|
|
1902
|
+
"cfg",
|
|
1903
|
+
"cm",
|
|
1904
|
+
"cnt",
|
|
1905
|
+
"ctx",
|
|
1906
|
+
"dr",
|
|
1907
|
+
"dst",
|
|
1908
|
+
"fn",
|
|
1909
|
+
"ft",
|
|
1910
|
+
"hmm",
|
|
1911
|
+
"hr",
|
|
1912
|
+
"kg",
|
|
1913
|
+
"km",
|
|
1914
|
+
"lb",
|
|
1915
|
+
"mg",
|
|
1916
|
+
"ml",
|
|
1917
|
+
"mm",
|
|
1918
|
+
"mr",
|
|
1919
|
+
"mrs",
|
|
1920
|
+
"ms",
|
|
1921
|
+
"msg",
|
|
1922
|
+
"nd",
|
|
1923
|
+
"nth",
|
|
1924
|
+
"pkg",
|
|
1925
|
+
"pt",
|
|
1926
|
+
"rd",
|
|
1927
|
+
"src",
|
|
1928
|
+
"st",
|
|
1929
|
+
"th",
|
|
1930
|
+
"tmp",
|
|
1931
|
+
"vs"
|
|
1932
|
+
]);
|
|
1933
|
+
var SINGULAR_S_ACRONYMS = /* @__PURE__ */ new Set([
|
|
1934
|
+
"cms",
|
|
1935
|
+
"css",
|
|
1936
|
+
"dns",
|
|
1937
|
+
"gps",
|
|
1938
|
+
"rss",
|
|
1939
|
+
"sms"
|
|
1940
|
+
]);
|
|
1941
|
+
var NATIVE_PLAIN_NAMES = {
|
|
1942
|
+
Html: "HTML",
|
|
1943
|
+
JSON: "JSON",
|
|
1944
|
+
TextAndImages: "Text and images",
|
|
1945
|
+
YesNo: "Yes or no",
|
|
1946
|
+
SearchResult: "Search result",
|
|
1947
|
+
Composite: "Combined results",
|
|
1948
|
+
Dynamic: "Data"
|
|
1949
|
+
};
|
|
1950
|
+
var GENERIC_NATIVES = /* @__PURE__ */ new Set(["Anything", "Dynamic", "Composite"]);
|
|
1951
|
+
function isAcronymWord(lower) {
|
|
1952
|
+
if (lower.length < 2 || !/^[a-z]+$/.test(lower)) return false;
|
|
1953
|
+
if (VOWELLESS_WORDS.has(lower)) return false;
|
|
1954
|
+
if (lower.endsWith("s") && VOWELLESS_WORDS.has(lower.slice(0, -1))) return false;
|
|
1955
|
+
return !VOWELS.test(lower) || VOWELED_ACRONYMS.has(lower);
|
|
1956
|
+
}
|
|
1957
|
+
function spellWord(lower, wasAllCaps) {
|
|
1958
|
+
if (/^\d+$/.test(lower)) return lower;
|
|
1959
|
+
if (wasAllCaps && lower.length >= 2) return lower.toUpperCase();
|
|
1960
|
+
if (lower.endsWith("s") && !SINGULAR_S_ACRONYMS.has(lower) && isAcronymWord(lower.slice(0, -1))) {
|
|
1961
|
+
return lower.slice(0, -1).toUpperCase() + "s";
|
|
1962
|
+
}
|
|
1963
|
+
if (isAcronymWord(lower)) return lower.toUpperCase();
|
|
1964
|
+
return lower;
|
|
1965
|
+
}
|
|
1966
|
+
function splitIdentifier(identifier) {
|
|
1967
|
+
const parts = identifier.replace(/([a-z\d])([A-Z])/g, "$1 $2").replace(/([A-Z]+)([A-Z][a-z])/g, "$1 $2").replace(/([A-Za-z])(\d)/g, "$1 $2").split(/[\s_\-.]+/).filter((p) => p.length > 0);
|
|
1968
|
+
return parts.map((p) => ({
|
|
1969
|
+
word: p.toLowerCase(),
|
|
1970
|
+
wasAllCaps: p.length >= 2 && p === p.toUpperCase() && /[A-Z]/.test(p)
|
|
1971
|
+
}));
|
|
1972
|
+
}
|
|
1973
|
+
function capitalizeFirst(text) {
|
|
1974
|
+
return text.length === 0 ? text : text.charAt(0).toUpperCase() + text.slice(1);
|
|
1975
|
+
}
|
|
1976
|
+
function stripDomain(ref) {
|
|
1977
|
+
const dot = ref.lastIndexOf(".");
|
|
1978
|
+
return dot === -1 ? ref : ref.slice(dot + 1);
|
|
1979
|
+
}
|
|
1980
|
+
function humanizeIdentifier(identifier) {
|
|
1981
|
+
const words = splitIdentifier(stripDomain(identifier.trim()));
|
|
1982
|
+
if (words.length === 0) return "";
|
|
1983
|
+
return capitalizeFirst(words.map((w) => spellWord(w.word, w.wasAllCaps)).join(" "));
|
|
1984
|
+
}
|
|
1985
|
+
function conceptPlainName(conceptRef) {
|
|
1986
|
+
var _a;
|
|
1987
|
+
const code = stripDomain(conceptRef.trim());
|
|
1988
|
+
return (_a = NATIVE_PLAIN_NAMES[code]) != null ? _a : humanizeIdentifier(code);
|
|
1989
|
+
}
|
|
1990
|
+
function isGenericConcept(conceptRef) {
|
|
1991
|
+
return GENERIC_NATIVES.has(stripDomain(conceptRef.trim()));
|
|
1992
|
+
}
|
|
1993
|
+
function sentenceCase(text) {
|
|
1994
|
+
const collapsed = text.replace(/\s+/g, " ").trim();
|
|
1995
|
+
const trimmed = collapsed.endsWith(".") && !collapsed.endsWith("..") ? collapsed.slice(0, -1) : collapsed;
|
|
1996
|
+
return capitalizeFirst(trimmed);
|
|
1997
|
+
}
|
|
1998
|
+
var OUTCOME_WORDS = {
|
|
1999
|
+
true: "Yes",
|
|
2000
|
+
false: "No",
|
|
2001
|
+
default: "Otherwise"
|
|
2002
|
+
};
|
|
2003
|
+
function outcomeLabel(outcome) {
|
|
2004
|
+
const outcomes = outcome.split("|").map((o) => o.trim()).filter((o) => o.length > 0);
|
|
2005
|
+
const labels = outcomes.map((o, index) => {
|
|
2006
|
+
var _a;
|
|
2007
|
+
const label = (_a = OUTCOME_WORDS[o.toLowerCase()]) != null ? _a : humanizeIdentifier(o);
|
|
2008
|
+
return index === 0 ? label : label.charAt(0).toLowerCase() + label.slice(1);
|
|
2009
|
+
});
|
|
2010
|
+
return labels.join(" or ");
|
|
2011
|
+
}
|
|
2012
|
+
|
|
2013
|
+
// src/graph/styles/textMetrics.ts
|
|
2014
|
+
var GLYPH_EM_GROUPS = [
|
|
2015
|
+
[0.28, "il .,'"],
|
|
2016
|
+
[0.33, "fjt:;!()"],
|
|
2017
|
+
[0.35, "/"],
|
|
2018
|
+
[0.39, "I"],
|
|
2019
|
+
[0.44, "r-"],
|
|
2020
|
+
[0.51, "1z"],
|
|
2021
|
+
[0.56, '7aceksvxyJ"'],
|
|
2022
|
+
[0.59, "25"],
|
|
2023
|
+
[0.6, "8"],
|
|
2024
|
+
[0.61, "369bdghnopquF?"],
|
|
2025
|
+
[0.64, "04"],
|
|
2026
|
+
[0.67, "ELPSTZ"],
|
|
2027
|
+
[0.72, "ABCDNRUVXY"],
|
|
2028
|
+
[0.78, "GHKOQ"],
|
|
2029
|
+
[0.8, "w"],
|
|
2030
|
+
[0.83, "&"],
|
|
2031
|
+
[0.89, "m"],
|
|
2032
|
+
[0.94, "M"],
|
|
2033
|
+
[1, "W%"]
|
|
2034
|
+
];
|
|
2035
|
+
var GLYPH_EM = new Map(
|
|
2036
|
+
GLYPH_EM_GROUPS.flatMap(([em, glyphs]) => [...glyphs].map((glyph) => [glyph, em]))
|
|
2037
|
+
);
|
|
2038
|
+
var UNLISTED_LOWER_EM = 0.62;
|
|
2039
|
+
var UNLISTED_UPPER_EM = 0.78;
|
|
2040
|
+
function glyphEm(glyph) {
|
|
2041
|
+
const listed = GLYPH_EM.get(glyph);
|
|
2042
|
+
if (listed !== void 0) return listed;
|
|
2043
|
+
return glyph !== glyph.toLowerCase() ? UNLISTED_UPPER_EM : UNLISTED_LOWER_EM;
|
|
2044
|
+
}
|
|
2045
|
+
function textWidthPx(text, fontPx) {
|
|
2046
|
+
let em = 0;
|
|
2047
|
+
for (const glyph of text) em += glyphEm(glyph);
|
|
2048
|
+
return em * fontPx;
|
|
2049
|
+
}
|
|
2050
|
+
function estimateWrap(text, lineWidthPx, fontPx, maxLines) {
|
|
2051
|
+
const words = text.split(/\s+/).filter((w) => w.length > 0);
|
|
2052
|
+
const spacePx = textWidthPx(" ", fontPx);
|
|
2053
|
+
let lines = words.length === 0 ? 0 : 1;
|
|
2054
|
+
let used = 0;
|
|
2055
|
+
for (const word of words) {
|
|
2056
|
+
const wordPx = textWidthPx(word, fontPx);
|
|
2057
|
+
if (wordPx > lineWidthPx) {
|
|
2058
|
+
if (used > 0) lines += 1;
|
|
2059
|
+
used = 0;
|
|
2060
|
+
for (const glyph of word) {
|
|
2061
|
+
const glyphPx = textWidthPx(glyph, fontPx);
|
|
2062
|
+
if (used > 0 && used + glyphPx > lineWidthPx) {
|
|
2063
|
+
lines += 1;
|
|
2064
|
+
used = 0;
|
|
2065
|
+
}
|
|
2066
|
+
used += glyphPx;
|
|
2067
|
+
}
|
|
2068
|
+
continue;
|
|
2069
|
+
}
|
|
2070
|
+
const needed = used === 0 ? wordPx : used + spacePx + wordPx;
|
|
2071
|
+
if (needed <= lineWidthPx) {
|
|
2072
|
+
used = needed;
|
|
2073
|
+
} else {
|
|
2074
|
+
lines += 1;
|
|
2075
|
+
used = wordPx;
|
|
2076
|
+
}
|
|
2077
|
+
}
|
|
2078
|
+
const drawnLines = Math.min(lines, maxLines);
|
|
2079
|
+
return { lines, drawnLines, clamped: lines > maxLines };
|
|
2080
|
+
}
|
|
2081
|
+
|
|
2082
|
+
// src/graph/styles/simpleStyle.ts
|
|
2083
|
+
var NATIVE_DOMAIN = "native";
|
|
2084
|
+
var SIMPLE_STEP_WIDTH = 160;
|
|
2085
|
+
var SIMPLE_STEP_WIDE_WIDTH = 200;
|
|
2086
|
+
var STEP_PADDING_X = 12;
|
|
2087
|
+
var STEP_PADDING_Y = 10;
|
|
2088
|
+
var STEP_BORDER = 1.5;
|
|
2089
|
+
var STEP_HEADER_HEIGHT = 16;
|
|
2090
|
+
var STEP_GAP = 6;
|
|
2091
|
+
var SIMPLE_STEP_TITLE_FONT_PX = 15;
|
|
2092
|
+
var STEP_TITLE_LINE_HEIGHT = 20;
|
|
2093
|
+
var SIMPLE_TITLE_MAX_LINES = 3;
|
|
2094
|
+
var STEP_MARKER_HEIGHT = 18;
|
|
2095
|
+
var STEP_INNER_HEIGHT = 22;
|
|
2096
|
+
var EDGE_LABEL_FONT_PX = 11;
|
|
2097
|
+
var EDGE_LABEL_LINE_HEIGHT = 13;
|
|
2098
|
+
var EDGE_LABEL_PADDING = [5, 3];
|
|
2099
|
+
var SIMPLE_TERMINAL_WIDTH = 124;
|
|
2100
|
+
var TERMINAL_PADDING_X = 12;
|
|
2101
|
+
var TERMINAL_PADDING_TOP = 10;
|
|
2102
|
+
var TERMINAL_PADDING_BOTTOM = 16;
|
|
2103
|
+
var TERMINAL_TITLE_FONT_PX = 13;
|
|
2104
|
+
var TERMINAL_TITLE_LINE_HEIGHT = 17;
|
|
2105
|
+
var TERMINAL_TITLE_MAX_LINES = 2;
|
|
2106
|
+
var TERMINAL_SUBTITLE_HEIGHT = 17;
|
|
2107
|
+
var TERMINAL_MIN_HEIGHT = 52;
|
|
2108
|
+
var SIMPLE_DECISION_WIDTHS = [188, 220, 252, 284];
|
|
2109
|
+
var DECISION_TITLE_FONT_PX = 13;
|
|
2110
|
+
var DECISION_TITLE_LINE_HEIGHT = 16;
|
|
2111
|
+
var DECISION_TEXT_WIDTH_SHARE = 0.56;
|
|
2112
|
+
var DECISION_TEXT_HEIGHT_SHARE = 0.4;
|
|
2113
|
+
var DECISION_MIN_HEIGHT = 84;
|
|
2114
|
+
var WRAP_SLACK_PX = 2;
|
|
2115
|
+
function stepTitleWidth(boxWidth) {
|
|
2116
|
+
return boxWidth - 2 * (STEP_PADDING_X + STEP_BORDER) - WRAP_SLACK_PX;
|
|
2117
|
+
}
|
|
2118
|
+
var TERMINAL_TITLE_WIDTH = SIMPLE_TERMINAL_WIDTH - 2 * TERMINAL_PADDING_X - WRAP_SLACK_PX;
|
|
2119
|
+
function decisionTextWidth(diamondWidth) {
|
|
2120
|
+
return Math.floor(diamondWidth * DECISION_TEXT_WIDTH_SHARE) - WRAP_SLACK_PX;
|
|
2121
|
+
}
|
|
2122
|
+
var SIMPLE_FOLD_DEPTH = 3;
|
|
2123
|
+
var STEP_CATEGORY_BY_PIPE_TYPE = {
|
|
2124
|
+
PipeLLM: STEP_CATEGORY.AI,
|
|
2125
|
+
PipeStructure: STEP_CATEGORY.AI,
|
|
2126
|
+
PipeJudge: STEP_CATEGORY.JUDGE,
|
|
2127
|
+
PipeExtract: STEP_CATEGORY.EXTRACT,
|
|
2128
|
+
PipeImgGen: STEP_CATEGORY.IMAGE,
|
|
2129
|
+
PipeSearch: STEP_CATEGORY.SEARCH,
|
|
2130
|
+
PipeFunc: STEP_CATEGORY.CODE,
|
|
2131
|
+
PipeCompose: STEP_CATEGORY.TEMPLATE,
|
|
2132
|
+
PipeDocGen: STEP_CATEGORY.DOCUMENT,
|
|
2133
|
+
PipeSignature: STEP_CATEGORY.PLANNED,
|
|
2134
|
+
PipeSequence: STEP_CATEGORY.STEPS,
|
|
2135
|
+
PipeParallel: STEP_CATEGORY.PARALLEL,
|
|
2136
|
+
PipeCondition: STEP_CATEGORY.DECISION,
|
|
2137
|
+
PipeBatch: STEP_CATEGORY.REPEAT,
|
|
2138
|
+
BindingStep: STEP_CATEGORY.PICK
|
|
2139
|
+
};
|
|
2140
|
+
var STEP_CATEGORY_WORDS = {
|
|
2141
|
+
ai: "AI",
|
|
2142
|
+
extract: "Extract",
|
|
2143
|
+
image: "Image",
|
|
2144
|
+
search: "Search",
|
|
2145
|
+
code: "Code",
|
|
2146
|
+
template: "Template",
|
|
2147
|
+
document: "Document",
|
|
2148
|
+
judge: "Judge",
|
|
2149
|
+
planned: "To build",
|
|
2150
|
+
steps: "Steps",
|
|
2151
|
+
parallel: "Side by side",
|
|
2152
|
+
decision: "Decision",
|
|
2153
|
+
repeat: "For each",
|
|
2154
|
+
pick: "Pick"
|
|
2155
|
+
};
|
|
2156
|
+
function simpleStepSize(title, options = {}) {
|
|
2157
|
+
let width = SIMPLE_STEP_WIDTH;
|
|
2158
|
+
let wrap = simpleTitleWrap(title);
|
|
2159
|
+
if (wrap.clamped) {
|
|
2160
|
+
const wide = simpleTitleWrap(title, SIMPLE_STEP_WIDE_WIDTH);
|
|
2161
|
+
if (!wide.clamped) {
|
|
2162
|
+
width = SIMPLE_STEP_WIDE_WIDTH;
|
|
2163
|
+
wrap = wide;
|
|
2164
|
+
}
|
|
2165
|
+
}
|
|
2166
|
+
let height = 2 * STEP_PADDING_Y + STEP_HEADER_HEIGHT + STEP_GAP + Math.max(1, wrap.drawnLines) * STEP_TITLE_LINE_HEIGHT;
|
|
2167
|
+
if (options.forEach) height += STEP_GAP + STEP_MARKER_HEIGHT;
|
|
2168
|
+
if (options.innerSteps) height += STEP_GAP + STEP_INNER_HEIGHT;
|
|
2169
|
+
return { width, height: Math.ceil(height + 2 * STEP_BORDER) };
|
|
2170
|
+
}
|
|
2171
|
+
function simpleTerminalSize(title, hasSubtitle) {
|
|
2172
|
+
const wrap = estimateWrap(
|
|
2173
|
+
title,
|
|
2174
|
+
TERMINAL_TITLE_WIDTH,
|
|
2175
|
+
TERMINAL_TITLE_FONT_PX,
|
|
2176
|
+
TERMINAL_TITLE_MAX_LINES
|
|
2177
|
+
);
|
|
2178
|
+
const height = TERMINAL_PADDING_TOP + Math.max(1, wrap.drawnLines) * TERMINAL_TITLE_LINE_HEIGHT + (hasSubtitle ? TERMINAL_SUBTITLE_HEIGHT : 0) + TERMINAL_PADDING_BOTTOM;
|
|
2179
|
+
return { width: SIMPLE_TERMINAL_WIDTH, height: Math.max(TERMINAL_MIN_HEIGHT, height) };
|
|
2180
|
+
}
|
|
2181
|
+
function simpleDecisionSize(title) {
|
|
2182
|
+
let width = SIMPLE_DECISION_WIDTHS[0];
|
|
2183
|
+
let wrap = estimateWrap(
|
|
2184
|
+
title,
|
|
2185
|
+
decisionTextWidth(width),
|
|
2186
|
+
DECISION_TITLE_FONT_PX,
|
|
2187
|
+
SIMPLE_TITLE_MAX_LINES
|
|
2188
|
+
);
|
|
2189
|
+
for (const candidate of SIMPLE_DECISION_WIDTHS.slice(1)) {
|
|
2190
|
+
if (!wrap.clamped) break;
|
|
2191
|
+
width = candidate;
|
|
2192
|
+
wrap = estimateWrap(
|
|
2193
|
+
title,
|
|
2194
|
+
decisionTextWidth(width),
|
|
2195
|
+
DECISION_TITLE_FONT_PX,
|
|
2196
|
+
SIMPLE_TITLE_MAX_LINES
|
|
2197
|
+
);
|
|
2198
|
+
}
|
|
2199
|
+
const textHeight = Math.max(1, wrap.drawnLines) * DECISION_TITLE_LINE_HEIGHT;
|
|
2200
|
+
const height = Math.max(DECISION_MIN_HEIGHT, Math.ceil(textHeight / DECISION_TEXT_HEIGHT_SHARE));
|
|
2201
|
+
return { width, height };
|
|
2202
|
+
}
|
|
2203
|
+
function simpleTitleWrap(title, boxWidth = SIMPLE_STEP_WIDTH) {
|
|
2204
|
+
return estimateWrap(
|
|
2205
|
+
title,
|
|
2206
|
+
stepTitleWidth(boxWidth),
|
|
2207
|
+
SIMPLE_STEP_TITLE_FONT_PX,
|
|
2208
|
+
SIMPLE_TITLE_MAX_LINES
|
|
2209
|
+
);
|
|
2210
|
+
}
|
|
2211
|
+
var STATUS_PRECEDENCE = [
|
|
2212
|
+
"failed",
|
|
2213
|
+
"running",
|
|
2214
|
+
"scheduled",
|
|
2215
|
+
"canceled",
|
|
2216
|
+
"skipped",
|
|
2217
|
+
"succeeded"
|
|
2218
|
+
];
|
|
2219
|
+
function aggregateStatus(statuses) {
|
|
2220
|
+
for (const status of STATUS_PRECEDENCE) {
|
|
2221
|
+
if (statuses.includes(status)) return status;
|
|
2222
|
+
}
|
|
2223
|
+
return void 0;
|
|
2224
|
+
}
|
|
2225
|
+
function parentMap(containmentTree) {
|
|
2226
|
+
const parentOf = {};
|
|
2227
|
+
for (const [ctrlId, children] of Object.entries(containmentTree)) {
|
|
2228
|
+
for (const child of children) parentOf[child] = ctrlId;
|
|
2229
|
+
}
|
|
2230
|
+
return parentOf;
|
|
2231
|
+
}
|
|
2232
|
+
function unique(items) {
|
|
2233
|
+
return [...new Set(items)];
|
|
2234
|
+
}
|
|
2235
|
+
function batchRepresentatives(graphspec, analysis, drawability) {
|
|
2236
|
+
var _a;
|
|
2237
|
+
const specById = new Map(graphspec.nodes.map((n) => [n.id, n]));
|
|
2238
|
+
const runsWithPath = /* @__PURE__ */ new Map();
|
|
2239
|
+
const representativeOf = /* @__PURE__ */ new Map();
|
|
2240
|
+
const order = [];
|
|
2241
|
+
function visit(ids, parentPath, inBatch) {
|
|
2242
|
+
var _a2, _b;
|
|
2243
|
+
const seen = /* @__PURE__ */ new Map();
|
|
2244
|
+
for (const id of ids) {
|
|
2245
|
+
const spec = specById.get(id);
|
|
2246
|
+
const pipe = spec ? stepIdentity(spec) : id;
|
|
2247
|
+
const occurrence = (_a2 = seen.get(pipe)) != null ? _a2 : 0;
|
|
2248
|
+
seen.set(pipe, occurrence + 1);
|
|
2249
|
+
const path = `${parentPath}/${pipe}#${inBatch ? "*" : occurrence}`;
|
|
2250
|
+
const runs = runsWithPath.get(path);
|
|
2251
|
+
if (runs) runs.push(id);
|
|
2252
|
+
else runsWithPath.set(path, [id]);
|
|
2253
|
+
order.push(id);
|
|
2254
|
+
visit((_b = analysis.containmentTree[id]) != null ? _b : [], path, (spec == null ? void 0 : spec.pipe_type) === "PipeBatch");
|
|
2255
|
+
}
|
|
2256
|
+
}
|
|
2257
|
+
visit(
|
|
2258
|
+
graphspec.nodes.filter((n) => !analysis.childNodeIds.has(n.id)).map((n) => n.id),
|
|
2259
|
+
"",
|
|
2260
|
+
false
|
|
2261
|
+
);
|
|
2262
|
+
for (const runs of runsWithPath.values()) {
|
|
2263
|
+
if (runs.length < 2) continue;
|
|
2264
|
+
const best = Math.max(...runs.map(drawability));
|
|
2265
|
+
const representative = (_a = runs.find((id) => drawability(id) === best)) != null ? _a : runs[0];
|
|
2266
|
+
for (const id of runs) if (id !== representative) representativeOf.set(id, representative);
|
|
2267
|
+
}
|
|
2268
|
+
return { representativeOf, order };
|
|
2269
|
+
}
|
|
2270
|
+
function stepIdentity(spec) {
|
|
2271
|
+
var _a;
|
|
2272
|
+
const ref = spec.domain_code && spec.pipe_code ? makePipeRef(spec.domain_code, spec.pipe_code) : (_a = spec.pipe_code) != null ? _a : spec.pipe_type;
|
|
2273
|
+
return `${spec.kind}:${ref}`;
|
|
2274
|
+
}
|
|
2275
|
+
function forEachLabel(itemName) {
|
|
2276
|
+
var _a;
|
|
2277
|
+
const words = humanizeIdentifier(itemName);
|
|
2278
|
+
const first = (_a = words.split(" ")[0]) != null ? _a : "";
|
|
2279
|
+
const inSentence = first.length >= 2 && first === first.toUpperCase() ? words : words.charAt(0).toLowerCase() + words.slice(1);
|
|
2280
|
+
return `For each ${inSentence}`;
|
|
2281
|
+
}
|
|
2282
|
+
function projectSimpleGraph(input) {
|
|
2283
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j;
|
|
2284
|
+
const { graphspec, nodes, analysis, rawAnalysis } = input;
|
|
2285
|
+
const graphMode = graphSpecMode(graphspec);
|
|
2286
|
+
const specById = new Map(graphspec.nodes.map((n) => [n.id, n]));
|
|
2287
|
+
const cards = /* @__PURE__ */ new Map();
|
|
2288
|
+
for (const node of nodes) {
|
|
2289
|
+
if (node.type === NODE_TYPE_PIPE_CARD) cards.set(node.id, node);
|
|
2290
|
+
}
|
|
2291
|
+
const liveControllers = analysis.controllerNodeIds;
|
|
2292
|
+
const pipeTypeOf = (id) => {
|
|
2293
|
+
var _a2;
|
|
2294
|
+
return (_a2 = specById.get(id)) == null ? void 0 : _a2.pipe_type;
|
|
2295
|
+
};
|
|
2296
|
+
const { representativeOf, order } = batchRepresentatives(graphspec, rawAnalysis, (id) => {
|
|
2297
|
+
var _a2;
|
|
2298
|
+
if (liveControllers.has(id)) return 2;
|
|
2299
|
+
const card = cards.get(id);
|
|
2300
|
+
if (!card) return 0;
|
|
2301
|
+
return card.data.isController !== true && ((_a2 = specById.get(id)) == null ? void 0 : _a2.kind) === "controller" ? 1 : 2;
|
|
2302
|
+
});
|
|
2303
|
+
const repOf = (id) => {
|
|
2304
|
+
var _a2;
|
|
2305
|
+
return (_a2 = representativeOf.get(id)) != null ? _a2 : id;
|
|
2306
|
+
};
|
|
2307
|
+
const parentOf = {};
|
|
2308
|
+
for (const [id, parent] of Object.entries(parentMap(rawAnalysis.containmentTree))) {
|
|
2309
|
+
parentOf[id] = repOf(parent);
|
|
2310
|
+
}
|
|
2311
|
+
const foldedAbove = /* @__PURE__ */ new Map();
|
|
2312
|
+
for (const id of order) {
|
|
2313
|
+
for (let current = parentOf[id]; current; current = parentOf[current]) {
|
|
2314
|
+
if (((_a = cards.get(current)) == null ? void 0 : _a.data.isController) === true) {
|
|
2315
|
+
foldedAbove.set(id, current);
|
|
2316
|
+
break;
|
|
2317
|
+
}
|
|
2318
|
+
}
|
|
2319
|
+
}
|
|
2320
|
+
const drawnAs = (id) => {
|
|
2321
|
+
var _a2;
|
|
2322
|
+
return (_a2 = foldedAbove.get(id)) != null ? _a2 : repOf(id);
|
|
2323
|
+
};
|
|
2324
|
+
const hidden = /* @__PURE__ */ new Set([...representativeOf.keys(), ...foldedAbove.keys()]);
|
|
2325
|
+
const childrenOf = {};
|
|
2326
|
+
for (const id of order) {
|
|
2327
|
+
const parent = parentOf[id];
|
|
2328
|
+
if (parent && !hidden.has(id)) ((_b = childrenOf[parent]) != null ? _b : childrenOf[parent] = []).push(id);
|
|
2329
|
+
}
|
|
2330
|
+
function isInside(id, ancestorId) {
|
|
2331
|
+
let current = parentOf[id];
|
|
2332
|
+
while (current) {
|
|
2333
|
+
if (current === ancestorId) return true;
|
|
2334
|
+
current = parentOf[current];
|
|
2335
|
+
}
|
|
2336
|
+
return false;
|
|
2337
|
+
}
|
|
2338
|
+
const batchBranch = {};
|
|
2339
|
+
for (const ctrlId of liveControllers) {
|
|
2340
|
+
if (hidden.has(ctrlId) || pipeTypeOf(ctrlId) !== "PipeBatch") continue;
|
|
2341
|
+
const first = (_c = analysis.containmentTree[ctrlId]) == null ? void 0 : _c[0];
|
|
2342
|
+
if (first) batchBranch[ctrlId] = repOf(first);
|
|
2343
|
+
}
|
|
2344
|
+
const decisions = [...liveControllers].filter(
|
|
2345
|
+
(id) => !hidden.has(id) && pipeTypeOf(id) === "PipeCondition"
|
|
2346
|
+
);
|
|
2347
|
+
const decisionSet = new Set(decisions);
|
|
2348
|
+
const frameSet = new Set(
|
|
2349
|
+
Object.entries(batchBranch).filter(([batchId, branchId]) => !hidden.has(batchId) && liveControllers.has(branchId)).map(([batchId]) => batchId)
|
|
2350
|
+
);
|
|
2351
|
+
const markedSteps = {};
|
|
2352
|
+
for (const [batchId, branchId] of Object.entries(batchBranch)) {
|
|
2353
|
+
if (!hidden.has(batchId) && cards.has(branchId)) markedSteps[branchId] = batchId;
|
|
2354
|
+
}
|
|
2355
|
+
const runStatuses = /* @__PURE__ */ new Map();
|
|
2356
|
+
for (const spec of graphspec.nodes) {
|
|
2357
|
+
const rep = repOf(spec.id);
|
|
2358
|
+
const statuses = runStatuses.get(rep);
|
|
2359
|
+
if (statuses) statuses.push(spec.status);
|
|
2360
|
+
else runStatuses.set(rep, [spec.status]);
|
|
2361
|
+
}
|
|
2362
|
+
function stepStatus(spec) {
|
|
2363
|
+
var _a2, _b2;
|
|
2364
|
+
return (_b2 = aggregateStatus((_a2 = runStatuses.get(spec.id)) != null ? _a2 : [])) != null ? _b2 : spec.status;
|
|
2365
|
+
}
|
|
2366
|
+
const drawnSteps = [...cards.values()].filter(
|
|
2367
|
+
(card) => {
|
|
2368
|
+
var _a2;
|
|
2369
|
+
return !hidden.has(card.id) && (card.data.pipeType !== BINDING_STEP_TYPE || aggregateStatus((_a2 = runStatuses.get(card.id)) != null ? _a2 : []) === "failed");
|
|
2370
|
+
}
|
|
2371
|
+
);
|
|
2372
|
+
const drawnStepIds = new Set(drawnSteps.map((card) => card.id));
|
|
2373
|
+
const roots = graphspec.nodes.filter(
|
|
2374
|
+
(n) => !rawAnalysis.childNodeIds.has(n.id) && (n.kind === "controller" || n.kind === "operator")
|
|
2375
|
+
);
|
|
2376
|
+
const rootReads = new Set(roots.flatMap((r) => r.io.inputs.map((item) => item.digest)));
|
|
2377
|
+
const rootWrites = new Set(roots.flatMap((r) => r.io.outputs.map((item) => item.digest)));
|
|
2378
|
+
const inputItems = /* @__PURE__ */ new Map();
|
|
2379
|
+
const outputItems = /* @__PURE__ */ new Map();
|
|
2380
|
+
for (const root of roots) {
|
|
2381
|
+
for (const item of root.io.inputs) {
|
|
2382
|
+
if (!item.digest || inputItems.has(item.digest) || rootWrites.has(item.digest)) continue;
|
|
2383
|
+
inputItems.set(item.digest, item);
|
|
2384
|
+
}
|
|
2385
|
+
}
|
|
2386
|
+
for (const root of roots) {
|
|
2387
|
+
for (const item of root.io.outputs) {
|
|
2388
|
+
if (!item.digest || inputItems.has(item.digest) || outputItems.has(item.digest)) continue;
|
|
2389
|
+
if (rootReads.has(item.digest)) continue;
|
|
2390
|
+
outputItems.set(item.digest, item);
|
|
2391
|
+
}
|
|
2392
|
+
}
|
|
2393
|
+
const combinedFrom = /* @__PURE__ */ new Map();
|
|
2394
|
+
for (const edge of graphspec.edges) {
|
|
2395
|
+
const from = edge.source_stuff_digest;
|
|
2396
|
+
const into = edge.target_stuff_digest;
|
|
2397
|
+
if (!from || !into || from === into) continue;
|
|
2398
|
+
if (edge.kind !== "parallel_combine" && edge.kind !== "batch_aggregate" && edge.kind !== "batch_item") {
|
|
2399
|
+
continue;
|
|
2400
|
+
}
|
|
2401
|
+
const list = combinedFrom.get(into);
|
|
2402
|
+
if (list) list.push(from);
|
|
2403
|
+
else combinedFrom.set(into, [from]);
|
|
2404
|
+
}
|
|
2405
|
+
const sourceMemo = /* @__PURE__ */ new Map();
|
|
2406
|
+
function sourcesOf(digest, visiting = /* @__PURE__ */ new Set()) {
|
|
2407
|
+
var _a2, _b2, _c2, _d2;
|
|
2408
|
+
const memo = sourceMemo.get(digest);
|
|
2409
|
+
if (memo) return memo;
|
|
2410
|
+
if (inputItems.has(digest)) return [stuffNodeId(digest)];
|
|
2411
|
+
if (visiting.has(digest)) return [];
|
|
2412
|
+
visiting.add(digest);
|
|
2413
|
+
const found = [];
|
|
2414
|
+
const producers = (_a2 = analysis.stuffProducers[digest]) != null ? _a2 : [];
|
|
2415
|
+
for (const producerId of producers) {
|
|
2416
|
+
const card = cards.get(drawnAs(producerId));
|
|
2417
|
+
if (!card) continue;
|
|
2418
|
+
if (card.data.pipeType === BINDING_STEP_TYPE && !drawnStepIds.has(card.id)) {
|
|
2419
|
+
for (const item of (_c2 = (_b2 = specById.get(producerId)) == null ? void 0 : _b2.io.inputs) != null ? _c2 : []) {
|
|
2420
|
+
if (item.digest) found.push(...sourcesOf(item.digest, visiting));
|
|
2421
|
+
}
|
|
2422
|
+
} else {
|
|
2423
|
+
found.push(card.id);
|
|
2424
|
+
}
|
|
2425
|
+
}
|
|
2426
|
+
if (producers.length === 0) {
|
|
2427
|
+
for (const from of (_d2 = combinedFrom.get(digest)) != null ? _d2 : []) found.push(...sourcesOf(from, visiting));
|
|
2428
|
+
}
|
|
2429
|
+
visiting.delete(digest);
|
|
2430
|
+
const result = unique(found);
|
|
2431
|
+
sourceMemo.set(digest, result);
|
|
2432
|
+
return result;
|
|
2433
|
+
}
|
|
2434
|
+
function branchOf(decisionId, nodeId) {
|
|
2435
|
+
let current = nodeId;
|
|
2436
|
+
while (parentOf[current] && parentOf[current] !== decisionId) current = parentOf[current];
|
|
2437
|
+
return current;
|
|
2438
|
+
}
|
|
2439
|
+
function outcomeFor(decisionId, branchId) {
|
|
2440
|
+
var _a2;
|
|
2441
|
+
const branch = specById.get(branchId);
|
|
2442
|
+
const tagged = (_a2 = branch == null ? void 0 : branch.tags) == null ? void 0 : _a2.outcome;
|
|
2443
|
+
if (tagged) return outcomeLabel(tagged);
|
|
2444
|
+
const contains = graphspec.edges.find(
|
|
2445
|
+
(e) => e.kind === "contains" && repOf(e.source) === decisionId && e.target === branchId && e.label
|
|
2446
|
+
);
|
|
2447
|
+
if (contains == null ? void 0 : contains.label) return outcomeLabel(contains.label);
|
|
2448
|
+
const decision = specById.get(decisionId);
|
|
2449
|
+
if (!(decision == null ? void 0 : decision.domain_code) || !decision.pipe_code || !(branch == null ? void 0 : branch.pipe_code)) return void 0;
|
|
2450
|
+
const blueprint = getPipeBlueprint(
|
|
2451
|
+
graphspec,
|
|
2452
|
+
makePipeRef(decision.domain_code, decision.pipe_code)
|
|
2453
|
+
);
|
|
2454
|
+
if ((blueprint == null ? void 0 : blueprint.type) !== "PipeCondition") return void 0;
|
|
2455
|
+
const conditionDomain = decision.domain_code;
|
|
2456
|
+
const branchCode = branch.pipe_code;
|
|
2457
|
+
function namesBranch(pipeRef) {
|
|
2458
|
+
var _a3;
|
|
2459
|
+
const parsed = parsePipeRef(pipeRef);
|
|
2460
|
+
if (!parsed) return stripDomain(pipeRef) === branchCode;
|
|
2461
|
+
if (parsed.pipeCode !== branchCode) return false;
|
|
2462
|
+
const domain = (_a3 = parsed.domainPath) != null ? _a3 : conditionDomain;
|
|
2463
|
+
return (branch == null ? void 0 : branch.domain_code) === void 0 || branch.domain_code === domain;
|
|
2464
|
+
}
|
|
2465
|
+
const outcomes = Object.entries(blueprint.outcome_map).filter(([, pipeRef]) => namesBranch(pipeRef)).map(([outcome]) => outcome);
|
|
2466
|
+
if (blueprint.default_outcome && namesBranch(blueprint.default_outcome)) {
|
|
2467
|
+
outcomes.push("default");
|
|
2468
|
+
}
|
|
2469
|
+
return outcomes.length > 0 ? outcomeLabel(outcomes.join("|")) : void 0;
|
|
2470
|
+
}
|
|
2471
|
+
function decisionsAbove(nodeId) {
|
|
2472
|
+
const chain = [];
|
|
2473
|
+
let current = parentOf[nodeId];
|
|
2474
|
+
while (current) {
|
|
2475
|
+
if (decisionSet.has(current)) chain.unshift(current);
|
|
2476
|
+
current = parentOf[current];
|
|
2477
|
+
}
|
|
2478
|
+
return chain;
|
|
2479
|
+
}
|
|
2480
|
+
const edges = /* @__PURE__ */ new Map();
|
|
2481
|
+
let edgeCount = 0;
|
|
2482
|
+
function addEdge(source, target) {
|
|
2483
|
+
if (source === target) return;
|
|
2484
|
+
const key = `${source}->${target}`;
|
|
2485
|
+
if (edges.has(key)) return;
|
|
2486
|
+
const label = decisionSet.has(source) ? outcomeFor(source, branchOf(source, target)) : void 0;
|
|
2487
|
+
edges.set(key, simpleEdge(`simple_edge_${edgeCount++}`, source, target, label));
|
|
2488
|
+
}
|
|
2489
|
+
function route(sources, target) {
|
|
2490
|
+
let froms = [...sources];
|
|
2491
|
+
for (const decisionId of decisionsAbove(target)) {
|
|
2492
|
+
const outside = froms.filter((s) => !isInside(s, decisionId));
|
|
2493
|
+
if (outside.length === 0) continue;
|
|
2494
|
+
for (const source of outside) addEdge(source, decisionId);
|
|
2495
|
+
froms = [decisionId, ...froms.filter((s) => isInside(s, decisionId))];
|
|
2496
|
+
}
|
|
2497
|
+
for (const source of froms) addEdge(source, target);
|
|
2498
|
+
}
|
|
2499
|
+
const danglingInputs = /* @__PURE__ */ new Map();
|
|
2500
|
+
function sourcesOrDangling(digest) {
|
|
2501
|
+
const sources = sourcesOf(digest);
|
|
2502
|
+
if (sources.length > 0) return sources;
|
|
2503
|
+
const entry = analysis.stuffRegistry[digest];
|
|
2504
|
+
if (!entry) return [];
|
|
2505
|
+
danglingInputs.set(digest, __spreadValues(__spreadValues({
|
|
2506
|
+
name: entry.name,
|
|
2507
|
+
digest
|
|
2508
|
+
}, entry.concept !== void 0 ? { concept: entry.concept } : {}), entry.multiplicity !== void 0 ? { multiplicity: entry.multiplicity } : {}));
|
|
2509
|
+
return [stuffNodeId(digest)];
|
|
2510
|
+
}
|
|
2511
|
+
function routeRead(digest, readerId) {
|
|
2512
|
+
const target = drawnAs(readerId);
|
|
2513
|
+
if (target === readerId) route(sourcesOrDangling(digest), target);
|
|
2514
|
+
else route(sourcesOf(digest), target);
|
|
2515
|
+
}
|
|
2516
|
+
for (const [digest, consumers] of Object.entries(analysis.stuffConsumers)) {
|
|
2517
|
+
for (const consumerId of consumers) {
|
|
2518
|
+
if (drawnStepIds.has(drawnAs(consumerId))) routeRead(digest, consumerId);
|
|
2519
|
+
}
|
|
2520
|
+
}
|
|
2521
|
+
for (const conditionId of liveControllers) {
|
|
2522
|
+
if (!decisionSet.has(drawnAs(conditionId))) continue;
|
|
2523
|
+
for (const item of (_e = (_d = specById.get(conditionId)) == null ? void 0 : _d.io.inputs) != null ? _e : []) {
|
|
2524
|
+
if (item.digest) routeRead(item.digest, conditionId);
|
|
2525
|
+
}
|
|
2526
|
+
}
|
|
2527
|
+
for (const digest of outputItems.keys()) {
|
|
2528
|
+
for (const source of sourcesOf(digest)) addEdge(source, stuffNodeId(digest));
|
|
2529
|
+
}
|
|
2530
|
+
for (const [key, edge] of [...edges]) {
|
|
2531
|
+
if (!decisionSet.has(edge.source)) continue;
|
|
2532
|
+
const branchId = branchOf(edge.source, edge.target);
|
|
2533
|
+
const followsInBranch = [...edges.values()].some(
|
|
2534
|
+
(other) => other.target === edge.target && other.source !== edge.source && isInside(other.source, branchId)
|
|
2535
|
+
);
|
|
2536
|
+
if (followsInBranch) edges.delete(key);
|
|
2537
|
+
}
|
|
2538
|
+
function firstDrawnIn(id) {
|
|
2539
|
+
var _a2;
|
|
2540
|
+
if (drawnStepIds.has(id) || decisionSet.has(id)) return id;
|
|
2541
|
+
for (const child of (_a2 = childrenOf[id]) != null ? _a2 : []) {
|
|
2542
|
+
const found = firstDrawnIn(child);
|
|
2543
|
+
if (found) return found;
|
|
2544
|
+
}
|
|
2545
|
+
return void 0;
|
|
2546
|
+
}
|
|
2547
|
+
for (const decisionId of decisions) {
|
|
2548
|
+
for (const branchId of (_f = childrenOf[decisionId]) != null ? _f : []) {
|
|
2549
|
+
const reached = [...edges.values()].some(
|
|
2550
|
+
(e) => e.source === decisionId && (e.target === branchId || isInside(e.target, branchId))
|
|
2551
|
+
);
|
|
2552
|
+
const entry = reached ? void 0 : firstDrawnIn(branchId);
|
|
2553
|
+
if (entry) addEdge(decisionId, entry);
|
|
2554
|
+
}
|
|
2555
|
+
}
|
|
2556
|
+
const simpleNodes = [];
|
|
2557
|
+
function isBuiltInConcept(conceptRef) {
|
|
2558
|
+
const info = resolveConceptRef(graphspec, conceptRef);
|
|
2559
|
+
if (info) return info.domain_code === NATIVE_DOMAIN;
|
|
2560
|
+
return conceptRef.startsWith(`${NATIVE_DOMAIN}.`) || isGenericConcept(conceptRef);
|
|
2561
|
+
}
|
|
2562
|
+
function terminalNode(item, kind) {
|
|
2563
|
+
const digest = item.digest;
|
|
2564
|
+
const concept = item.concept;
|
|
2565
|
+
const isList = isPluralMultiplicity(item.multiplicity);
|
|
2566
|
+
let title;
|
|
2567
|
+
let subtitle;
|
|
2568
|
+
if (kind === "output" && concept && !isBuiltInConcept(concept)) {
|
|
2569
|
+
title = conceptPlainName(concept);
|
|
2570
|
+
} else {
|
|
2571
|
+
title = humanizeIdentifier(item.name);
|
|
2572
|
+
const plain = concept ? conceptPlainName(concept) : void 0;
|
|
2573
|
+
subtitle = plain && plain.toLowerCase() !== title.toLowerCase() ? plain : void 0;
|
|
2574
|
+
}
|
|
2575
|
+
const simple = __spreadValues({ kind, title, isList }, subtitle ? { subtitle } : {});
|
|
2576
|
+
return {
|
|
2577
|
+
id: stuffNodeId(digest),
|
|
2578
|
+
type: NODE_TYPE_SIMPLE_TERMINAL,
|
|
2579
|
+
data: {
|
|
2580
|
+
isPipe: false,
|
|
2581
|
+
isStuff: true,
|
|
2582
|
+
labelText: title,
|
|
2583
|
+
stuffRole: kind,
|
|
2584
|
+
stuffDigest: digest,
|
|
2585
|
+
graphMode,
|
|
2586
|
+
simple,
|
|
2587
|
+
layoutSize: simpleTerminalSize(title, subtitle !== void 0)
|
|
2588
|
+
},
|
|
2589
|
+
position: { x: 0, y: 0 }
|
|
2590
|
+
};
|
|
2591
|
+
}
|
|
2592
|
+
for (const item of [...inputItems.values(), ...danglingInputs.values()]) {
|
|
2593
|
+
simpleNodes.push(terminalNode(item, "input"));
|
|
2594
|
+
}
|
|
2595
|
+
function itemName(batchId) {
|
|
2596
|
+
var _a2, _b2, _c2, _d2;
|
|
2597
|
+
const batch = specById.get(batchId);
|
|
2598
|
+
if ((batch == null ? void 0 : batch.domain_code) && batch.pipe_code) {
|
|
2599
|
+
const blueprint = getPipeBlueprint(
|
|
2600
|
+
graphspec,
|
|
2601
|
+
makePipeRef(batch.domain_code, batch.pipe_code)
|
|
2602
|
+
);
|
|
2603
|
+
if ((blueprint == null ? void 0 : blueprint.type) === "PipeBatch" && blueprint.batch_params.input_item_stuff_name) {
|
|
2604
|
+
return blueprint.batch_params.input_item_stuff_name;
|
|
2605
|
+
}
|
|
2606
|
+
}
|
|
2607
|
+
const runsOfBatch = /* @__PURE__ */ new Set([batchId]);
|
|
2608
|
+
for (const [id, representative] of representativeOf) {
|
|
2609
|
+
if (representative === batchId) runsOfBatch.add(id);
|
|
2610
|
+
}
|
|
2611
|
+
const itemEdges = graphspec.edges.filter(
|
|
2612
|
+
(e) => e.kind === "batch_item" && runsOfBatch.has(e.source) && e.target_stuff_digest
|
|
2613
|
+
);
|
|
2614
|
+
const itemDigests = new Set(itemEdges.map((e) => e.target_stuff_digest));
|
|
2615
|
+
const branchId = (_b2 = batchBranch[batchId]) != null ? _b2 : (_a2 = rawAnalysis.containmentTree[batchId]) == null ? void 0 : _a2[0];
|
|
2616
|
+
const branch = branchId ? specById.get(branchId) : void 0;
|
|
2617
|
+
const read = branch == null ? void 0 : branch.io.inputs.find((i) => itemDigests.has(i.digest));
|
|
2618
|
+
if (read == null ? void 0 : read.name) return read.name;
|
|
2619
|
+
const firstItem = (_c2 = itemEdges.find((e) => e.source === batchId)) != null ? _c2 : itemEdges[0];
|
|
2620
|
+
return (firstItem == null ? void 0 : firstItem.target_stuff_digest) ? ((_d2 = analysis.stuffRegistry[firstItem.target_stuff_digest]) == null ? void 0 : _d2.name) || void 0 : void 0;
|
|
2621
|
+
}
|
|
2622
|
+
function stepsInside(id) {
|
|
2623
|
+
var _a2;
|
|
2624
|
+
const spec = specById.get(id);
|
|
2625
|
+
const children = (_a2 = rawAnalysis.containmentTree[id]) != null ? _a2 : [];
|
|
2626
|
+
if (children.length === 0) return spec && spec.kind === "operator" ? 1 : 0;
|
|
2627
|
+
const counted = (spec == null ? void 0 : spec.pipe_type) === "PipeBatch" ? children.slice(0, 1) : children;
|
|
2628
|
+
return counted.reduce((sum, child) => sum + stepsInside(child), 0);
|
|
2629
|
+
}
|
|
2630
|
+
function stepTitle(spec, folded) {
|
|
2631
|
+
var _a2, _b2, _c2, _d2, _e2, _f2;
|
|
2632
|
+
if (spec.pipe_type === BINDING_STEP_TYPE) {
|
|
2633
|
+
return humanizeIdentifier((_b2 = (_a2 = spec.pipe_code) == null ? void 0 : _a2.split(".").pop()) != null ? _b2 : "");
|
|
2634
|
+
}
|
|
2635
|
+
let source = spec;
|
|
2636
|
+
if (folded && spec.pipe_type === "PipeBatch") {
|
|
2637
|
+
const branch = specById.get((_d2 = (_c2 = rawAnalysis.containmentTree[spec.id]) == null ? void 0 : _c2[0]) != null ? _d2 : "");
|
|
2638
|
+
if (branch) source = branch;
|
|
2639
|
+
}
|
|
2640
|
+
const described = sentenceCase((_e2 = source.description) != null ? _e2 : "");
|
|
2641
|
+
return described || humanizeIdentifier((_f2 = source.pipe_code) != null ? _f2 : "");
|
|
2642
|
+
}
|
|
2643
|
+
const stepById = new Map(drawnSteps.map((card) => [card.id, card]));
|
|
2644
|
+
for (const spec of graphspec.nodes) {
|
|
2645
|
+
const card = stepById.get(spec.id);
|
|
2646
|
+
if (card) {
|
|
2647
|
+
const folded = card.data.isController === true;
|
|
2648
|
+
const pipeType = spec.pipe_type;
|
|
2649
|
+
const title = stepTitle(spec, folded);
|
|
2650
|
+
const markerBatch = (_g = markedSteps[spec.id]) != null ? _g : folded && pipeType === "PipeBatch" ? spec.id : void 0;
|
|
2651
|
+
const markerItem = markerBatch ? itemName(markerBatch) : void 0;
|
|
2652
|
+
const forEach = markerBatch ? forEachLabel(markerItem || "item") : void 0;
|
|
2653
|
+
const innerStepCount = folded ? stepsInside(spec.id) : void 0;
|
|
2654
|
+
const onExpand = (_h = card.data.pipeCardData) == null ? void 0 : _h.onExpand;
|
|
2655
|
+
const simple = __spreadValues(__spreadValues(__spreadValues(__spreadValues({
|
|
2656
|
+
kind: "step",
|
|
2657
|
+
title,
|
|
2658
|
+
category: STEP_CATEGORY_BY_PIPE_TYPE[pipeType],
|
|
2659
|
+
status: stepStatus(spec)
|
|
2660
|
+
}, graphMode !== void 0 ? { graphMode } : {}), forEach ? { forEach } : {}), innerStepCount !== void 0 ? { innerStepCount } : {}), onExpand ? { onExpand } : {});
|
|
2661
|
+
simpleNodes.push({
|
|
2662
|
+
id: spec.id,
|
|
2663
|
+
type: NODE_TYPE_SIMPLE_STEP,
|
|
2664
|
+
data: {
|
|
2665
|
+
nodeData: spec,
|
|
2666
|
+
isPipe: !folded,
|
|
2667
|
+
isStuff: false,
|
|
2668
|
+
isController: folded,
|
|
2669
|
+
labelText: title,
|
|
2670
|
+
pipeCode: spec.pipe_code,
|
|
2671
|
+
pipeType: spec.pipe_type,
|
|
2672
|
+
graphMode,
|
|
2673
|
+
simple,
|
|
2674
|
+
layoutSize: simpleStepSize(title, {
|
|
2675
|
+
forEach: forEach !== void 0,
|
|
2676
|
+
innerSteps: innerStepCount !== void 0
|
|
2677
|
+
})
|
|
2678
|
+
},
|
|
2679
|
+
position: { x: 0, y: 0 }
|
|
2680
|
+
});
|
|
2681
|
+
continue;
|
|
2682
|
+
}
|
|
2683
|
+
if (decisionSet.has(spec.id)) {
|
|
2684
|
+
const title = sentenceCase((_i = spec.description) != null ? _i : "") || humanizeIdentifier((_j = spec.pipe_code) != null ? _j : "");
|
|
2685
|
+
simpleNodes.push({
|
|
2686
|
+
id: spec.id,
|
|
2687
|
+
type: NODE_TYPE_SIMPLE_DECISION,
|
|
2688
|
+
data: {
|
|
2689
|
+
nodeData: spec,
|
|
2690
|
+
isPipe: false,
|
|
2691
|
+
isStuff: false,
|
|
2692
|
+
isController: true,
|
|
2693
|
+
labelText: title,
|
|
2694
|
+
pipeCode: spec.pipe_code,
|
|
2695
|
+
pipeType: spec.pipe_type,
|
|
2696
|
+
graphMode,
|
|
2697
|
+
simple: __spreadValues({
|
|
2698
|
+
kind: "decision",
|
|
2699
|
+
title,
|
|
2700
|
+
status: stepStatus(spec)
|
|
2701
|
+
}, graphMode !== void 0 ? { graphMode } : {}),
|
|
2702
|
+
layoutSize: simpleDecisionSize(title)
|
|
2703
|
+
},
|
|
2704
|
+
position: { x: 0, y: 0 }
|
|
2705
|
+
});
|
|
2706
|
+
}
|
|
2707
|
+
}
|
|
2708
|
+
for (const item of outputItems.values()) {
|
|
2709
|
+
simpleNodes.push(terminalNode(item, "output"));
|
|
2710
|
+
}
|
|
2711
|
+
const nearestFrame = (id) => {
|
|
2712
|
+
let current = parentOf[id];
|
|
2713
|
+
while (current) {
|
|
2714
|
+
if (frameSet.has(current)) return current;
|
|
2715
|
+
current = parentOf[current];
|
|
2716
|
+
}
|
|
2717
|
+
return void 0;
|
|
2718
|
+
};
|
|
2719
|
+
const containmentTree = {};
|
|
2720
|
+
for (const frameId of frameSet) containmentTree[frameId] = [];
|
|
2721
|
+
for (const node of simpleNodes) {
|
|
2722
|
+
const frameId = node.data.isStuff ? void 0 : nearestFrame(node.id);
|
|
2723
|
+
if (frameId) containmentTree[frameId].push(node.id);
|
|
2724
|
+
}
|
|
2725
|
+
for (const frameId of frameSet) {
|
|
2726
|
+
const outer = nearestFrame(frameId);
|
|
2727
|
+
if (outer) containmentTree[outer].push(frameId);
|
|
2728
|
+
}
|
|
2729
|
+
const childNodeIds = new Set(Object.values(containmentTree).flat());
|
|
2730
|
+
for (const frameId of frameSet) {
|
|
2731
|
+
const spec = specById.get(frameId);
|
|
2732
|
+
if (!spec) continue;
|
|
2733
|
+
const title = forEachLabel(itemName(frameId) || "item");
|
|
2734
|
+
simpleNodes.push({
|
|
2735
|
+
id: frameId,
|
|
2736
|
+
type: NODE_TYPE_SIMPLE_FRAME,
|
|
2737
|
+
data: {
|
|
2738
|
+
nodeData: spec,
|
|
2739
|
+
isPipe: false,
|
|
2740
|
+
isStuff: false,
|
|
2741
|
+
isController: true,
|
|
2742
|
+
labelText: title,
|
|
2743
|
+
pipeCode: spec.pipe_code,
|
|
2744
|
+
pipeType: spec.pipe_type,
|
|
2745
|
+
graphMode,
|
|
2746
|
+
simple: __spreadValues({
|
|
2747
|
+
kind: "frame",
|
|
2748
|
+
title,
|
|
2749
|
+
status: stepStatus(spec)
|
|
2750
|
+
}, graphMode !== void 0 ? { graphMode } : {})
|
|
2751
|
+
},
|
|
2752
|
+
position: { x: 0, y: 0 }
|
|
2753
|
+
});
|
|
2754
|
+
}
|
|
2755
|
+
const drawnIds = new Set(simpleNodes.map((n) => n.id));
|
|
2756
|
+
const standIns = /* @__PURE__ */ new Map();
|
|
2757
|
+
const resolving = /* @__PURE__ */ new Set();
|
|
2758
|
+
function standIn(id) {
|
|
2759
|
+
var _a2, _b2, _c2, _d2, _e2;
|
|
2760
|
+
if (drawnIds.has(id)) return id;
|
|
2761
|
+
if (standIns.has(id)) return standIns.get(id);
|
|
2762
|
+
if (resolving.has(id)) return void 0;
|
|
2763
|
+
resolving.add(id);
|
|
2764
|
+
let found;
|
|
2765
|
+
const representative = (_a2 = foldedAbove.get(id)) != null ? _a2 : representativeOf.get(id);
|
|
2766
|
+
const branch = batchBranch[id];
|
|
2767
|
+
if (representative) {
|
|
2768
|
+
found = standIn(representative);
|
|
2769
|
+
} else if (branch && markedSteps[branch] === id) {
|
|
2770
|
+
found = standIn(branch);
|
|
2771
|
+
} else if (pipeTypeOf(id) === BINDING_STEP_TYPE) {
|
|
2772
|
+
for (const item of (_c2 = (_b2 = specById.get(id)) == null ? void 0 : _b2.io.outputs) != null ? _c2 : []) {
|
|
2773
|
+
if (!item.digest) continue;
|
|
2774
|
+
for (const reader of (_d2 = rawAnalysis.stuffConsumers[item.digest]) != null ? _d2 : []) {
|
|
2775
|
+
found != null ? found : found = standIn(reader);
|
|
2776
|
+
}
|
|
2777
|
+
if (!found && drawnIds.has(stuffNodeId(item.digest))) found = stuffNodeId(item.digest);
|
|
2778
|
+
if (found) break;
|
|
2779
|
+
}
|
|
2780
|
+
const parent = parentOf[id];
|
|
2781
|
+
if (!found && parent) found = standIn(parent);
|
|
2782
|
+
} else {
|
|
2783
|
+
for (const child of (_e2 = childrenOf[id]) != null ? _e2 : []) {
|
|
2784
|
+
found = standIn(child);
|
|
2785
|
+
if (found) break;
|
|
2786
|
+
}
|
|
2787
|
+
}
|
|
2788
|
+
resolving.delete(id);
|
|
2789
|
+
if (found) standIns.set(id, found);
|
|
2790
|
+
return found;
|
|
2791
|
+
}
|
|
2792
|
+
for (const spec of graphspec.nodes) standIn(spec.id);
|
|
2793
|
+
return {
|
|
2794
|
+
nodes: simpleNodes,
|
|
2795
|
+
edges: [...edges.values()],
|
|
2796
|
+
standIns,
|
|
2797
|
+
analysis: {
|
|
2798
|
+
stuffRegistry: analysis.stuffRegistry,
|
|
2799
|
+
stuffProducers: {},
|
|
2800
|
+
stuffConsumers: {},
|
|
2801
|
+
controllerNodeIds: frameSet,
|
|
2802
|
+
childNodeIds,
|
|
2803
|
+
containmentTree
|
|
2804
|
+
}
|
|
2805
|
+
};
|
|
2806
|
+
}
|
|
2807
|
+
function simpleEdgeLabelSize(label) {
|
|
2808
|
+
const [padX, padY] = EDGE_LABEL_PADDING;
|
|
2809
|
+
return {
|
|
2810
|
+
width: Math.ceil(textWidthPx(label, EDGE_LABEL_FONT_PX)) + 2 * padX,
|
|
2811
|
+
height: EDGE_LABEL_LINE_HEIGHT + 2 * padY
|
|
2812
|
+
};
|
|
2813
|
+
}
|
|
2814
|
+
function simpleEdge(id, source, target, label) {
|
|
2815
|
+
const edge = {
|
|
2816
|
+
id,
|
|
2817
|
+
source,
|
|
2818
|
+
target,
|
|
2819
|
+
type: EDGE_TYPE_ROUTED,
|
|
2820
|
+
animated: false,
|
|
2821
|
+
style: { stroke: "var(--color-edge)", strokeWidth: 1.5 },
|
|
2822
|
+
markerEnd: { type: ARROW_CLOSED_MARKER, color: "var(--color-edge)" }
|
|
2823
|
+
};
|
|
2824
|
+
if (label) {
|
|
2825
|
+
edge.label = label;
|
|
2826
|
+
edge.labelStyle = {
|
|
2827
|
+
fontSize: `${EDGE_LABEL_FONT_PX}px`,
|
|
2828
|
+
fontFamily: "var(--font-sans)",
|
|
2829
|
+
fontWeight: 600,
|
|
2830
|
+
fill: "var(--ctrl-condition-text)"
|
|
2831
|
+
};
|
|
2832
|
+
edge.labelBgStyle = { fill: "var(--color-bg)", fillOpacity: 0.92 };
|
|
2833
|
+
edge.labelBgPadding = [...EDGE_LABEL_PADDING];
|
|
2834
|
+
edge.labelBgBorderRadius = 4;
|
|
2835
|
+
edge.labelSize = simpleEdgeLabelSize(label);
|
|
2836
|
+
}
|
|
2837
|
+
return edge;
|
|
2838
|
+
}
|
|
2839
|
+
function simpleDefaultFolds(graphspec, rawAnalysis) {
|
|
2840
|
+
const parentOf = parentMap(rawAnalysis.containmentTree);
|
|
2841
|
+
const sequenceIds = new Set(
|
|
2842
|
+
graphspec.nodes.filter((n) => n.pipe_type === "PipeSequence").map((n) => n.id)
|
|
2843
|
+
);
|
|
2844
|
+
const folded = /* @__PURE__ */ new Set();
|
|
2845
|
+
for (const ctrlId of rawAnalysis.controllerNodeIds) {
|
|
2846
|
+
let depth = 0;
|
|
2847
|
+
let current = parentOf[ctrlId];
|
|
2848
|
+
while (current) {
|
|
2849
|
+
depth += 1;
|
|
2850
|
+
current = parentOf[current];
|
|
2851
|
+
}
|
|
2852
|
+
if (depth >= SIMPLE_FOLD_DEPTH && sequenceIds.has(ctrlId)) folded.add(ctrlId);
|
|
2853
|
+
}
|
|
2854
|
+
return folded;
|
|
2855
|
+
}
|
|
2856
|
+
function applySimpleFrames(args) {
|
|
2857
|
+
const { nodes, edges, graphspec, analysis, controllerPositions, onToggleFold } = args;
|
|
2858
|
+
const placeholders = /* @__PURE__ */ new Map();
|
|
2859
|
+
const content = [];
|
|
2860
|
+
for (const node of nodes) {
|
|
2861
|
+
if (node.type === NODE_TYPE_SIMPLE_FRAME) placeholders.set(node.id, node);
|
|
2862
|
+
else content.push(node);
|
|
2863
|
+
}
|
|
2864
|
+
if (analysis.controllerNodeIds.size === 0) return { nodes: content, edges };
|
|
2865
|
+
const groups = buildControllerNodes(graphspec, analysis, content, controllerPositions);
|
|
2866
|
+
const frames = groups.map((group) => {
|
|
2867
|
+
var _a;
|
|
2868
|
+
const placeholder = placeholders.get(group.id);
|
|
2869
|
+
const id = group.id;
|
|
2870
|
+
const simple = placeholder == null ? void 0 : placeholder.data.simple;
|
|
2871
|
+
const withFold = (simple == null ? void 0 : simple.kind) === "frame" && onToggleFold ? __spreadProps(__spreadValues({}, simple), { onFold: (options) => onToggleFold(id, options) }) : simple;
|
|
2872
|
+
return __spreadProps(__spreadValues({}, group), {
|
|
2873
|
+
type: NODE_TYPE_SIMPLE_FRAME,
|
|
2874
|
+
data: __spreadProps(__spreadValues({}, (_a = placeholder == null ? void 0 : placeholder.data) != null ? _a : group.data), { simple: withFold })
|
|
2875
|
+
});
|
|
2876
|
+
});
|
|
2877
|
+
return { nodes: sortParentsFirst([...frames, ...content]), edges };
|
|
1679
2878
|
}
|
|
1680
2879
|
|
|
2880
|
+
// src/graph/styles/stylePipelines.ts
|
|
2881
|
+
var GRAPH_STYLE_PIPELINES = {
|
|
2882
|
+
// Today's drawing: the dataflow graph as built, framed by controller groups
|
|
2883
|
+
// when the viewer shows them.
|
|
2884
|
+
[GRAPH_STYLE.DETAILED]: {
|
|
2885
|
+
defaultFolds: () => /* @__PURE__ */ new Set(),
|
|
2886
|
+
project: ({ nodes, edges, analysis }) => ({ nodes, edges, analysis }),
|
|
2887
|
+
frame: (args) => applyControllers(
|
|
2888
|
+
args.nodes,
|
|
2889
|
+
args.edges,
|
|
2890
|
+
args.graphspec,
|
|
2891
|
+
args.analysis,
|
|
2892
|
+
args.showControllers,
|
|
2893
|
+
args.expandedControllers,
|
|
2894
|
+
args.onToggleCollapse,
|
|
2895
|
+
args.controllerPositions,
|
|
2896
|
+
args.onToggleFold
|
|
2897
|
+
)
|
|
2898
|
+
},
|
|
2899
|
+
[GRAPH_STYLE.SIMPLE]: {
|
|
2900
|
+
defaultFolds: simpleDefaultFolds,
|
|
2901
|
+
project: ({ graphspec, nodes, analysis, rawAnalysis }) => analysis && rawAnalysis ? projectSimpleGraph({ graphspec, nodes, analysis, rawAnalysis }) : { nodes: [], edges: [], analysis: null },
|
|
2902
|
+
// Its frames are its own decision, whatever the controllers toggle says.
|
|
2903
|
+
frame: (args) => args.graphspec && args.analysis ? applySimpleFrames({
|
|
2904
|
+
nodes: args.nodes,
|
|
2905
|
+
edges: args.edges,
|
|
2906
|
+
graphspec: args.graphspec,
|
|
2907
|
+
analysis: args.analysis,
|
|
2908
|
+
controllerPositions: args.controllerPositions,
|
|
2909
|
+
onToggleFold: args.onToggleFold
|
|
2910
|
+
}) : { nodes: args.nodes, edges: args.edges }
|
|
2911
|
+
}
|
|
2912
|
+
};
|
|
2913
|
+
|
|
1681
2914
|
export {
|
|
1682
2915
|
GraphSpecValidationError,
|
|
1683
2916
|
validateGraphSpec,
|
|
@@ -1705,9 +2938,49 @@ export {
|
|
|
1705
2938
|
estimateNodeDimensions,
|
|
1706
2939
|
buildElkGraph,
|
|
1707
2940
|
extractAbsolutePositions,
|
|
2941
|
+
extractEdgeRoutes,
|
|
1708
2942
|
getLayoutedElements,
|
|
2943
|
+
ROUTE_ENDPOINT_TOLERANCE_PX,
|
|
2944
|
+
ROUTE_CORNER_RADIUS_PX,
|
|
2945
|
+
fitRoute,
|
|
2946
|
+
roundedPolylinePath,
|
|
2947
|
+
polylineMidpoint,
|
|
2948
|
+
routeLabelCenter,
|
|
1709
2949
|
MAX_VISIBLE_CONTROLLER_CHILDREN,
|
|
1710
2950
|
buildControllerNodes,
|
|
1711
|
-
applyControllers
|
|
2951
|
+
applyControllers,
|
|
2952
|
+
sortParentsFirst,
|
|
2953
|
+
GRAPH_STYLES,
|
|
2954
|
+
GRAPH_STYLE_IDS,
|
|
2955
|
+
isGraphStyleId,
|
|
2956
|
+
resolveGraphStyle,
|
|
2957
|
+
resolveStyleMenu,
|
|
2958
|
+
stripDomain,
|
|
2959
|
+
humanizeIdentifier,
|
|
2960
|
+
conceptPlainName,
|
|
2961
|
+
isGenericConcept,
|
|
2962
|
+
sentenceCase,
|
|
2963
|
+
outcomeLabel,
|
|
2964
|
+
textWidthPx,
|
|
2965
|
+
estimateWrap,
|
|
2966
|
+
SIMPLE_STEP_WIDTH,
|
|
2967
|
+
SIMPLE_STEP_WIDE_WIDTH,
|
|
2968
|
+
SIMPLE_STEP_TITLE_FONT_PX,
|
|
2969
|
+
SIMPLE_TITLE_MAX_LINES,
|
|
2970
|
+
SIMPLE_TERMINAL_WIDTH,
|
|
2971
|
+
SIMPLE_DECISION_WIDTHS,
|
|
2972
|
+
SIMPLE_FOLD_DEPTH,
|
|
2973
|
+
STEP_CATEGORY_BY_PIPE_TYPE,
|
|
2974
|
+
STEP_CATEGORY_WORDS,
|
|
2975
|
+
simpleStepSize,
|
|
2976
|
+
simpleTerminalSize,
|
|
2977
|
+
simpleDecisionSize,
|
|
2978
|
+
simpleTitleWrap,
|
|
2979
|
+
aggregateStatus,
|
|
2980
|
+
projectSimpleGraph,
|
|
2981
|
+
simpleEdgeLabelSize,
|
|
2982
|
+
simpleDefaultFolds,
|
|
2983
|
+
applySimpleFrames,
|
|
2984
|
+
GRAPH_STYLE_PIPELINES
|
|
1712
2985
|
};
|
|
1713
|
-
//# sourceMappingURL=chunk-
|
|
2986
|
+
//# sourceMappingURL=chunk-3BXB6HSF.js.map
|