@aranzatech/diagrams-bpmn 0.2.12 → 0.2.14
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/{catalog-BKdtbOQT.d.ts → catalog-CK3_4cOb.d.ts} +1 -1
- package/dist/{catalog-DUfPajtM.d.cts → catalog-xOMF2ifW.d.cts} +1 -1
- package/dist/chunk-FBTGIYZS.js +218 -0
- package/dist/chunk-FBTGIYZS.js.map +1 -0
- package/dist/{chunk-O3NWJ5H7.js → chunk-QSMP34CT.js} +38 -5
- package/dist/chunk-QSMP34CT.js.map +1 -0
- package/dist/{chunk-MZVDC6FU.js → chunk-YUE5EM3W.js} +76 -10
- package/dist/chunk-YUE5EM3W.js.map +1 -0
- package/dist/edges/index.cjs +35 -2
- package/dist/edges/index.cjs.map +1 -1
- package/dist/edges/index.js +1 -1
- package/dist/elements/index.cjs +217 -0
- package/dist/elements/index.cjs.map +1 -1
- package/dist/elements/index.d.cts +15 -16
- package/dist/elements/index.d.ts +15 -16
- package/dist/elements/index.js +1 -1
- package/dist/guards-C70uIY_O.d.cts +16 -0
- package/dist/guards-foB6XIfZ.d.ts +16 -0
- package/dist/index.cjs +109 -10
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +4 -4
- package/dist/index.d.ts +4 -4
- package/dist/index.js +3 -3
- package/dist/layout/index.cjs +55 -19
- package/dist/layout/index.cjs.map +1 -1
- package/dist/layout/index.d.cts +17 -11
- package/dist/layout/index.d.ts +17 -11
- package/dist/layout/index.js +55 -19
- package/dist/layout/index.js.map +1 -1
- package/dist/modeling/index.d.cts +3 -3
- package/dist/modeling/index.d.ts +3 -3
- package/dist/{types-kI1SiQB4.d.ts → types-DG5yPKld.d.ts} +1 -1
- package/dist/{types-44yNtMtO.d.cts → types-jIDz306Y.d.cts} +1 -1
- package/dist/{types-hgmLfRA9.d.cts → types-y-ZbX-ff.d.cts} +32 -1
- package/dist/{types-hgmLfRA9.d.ts → types-y-ZbX-ff.d.ts} +32 -1
- package/dist/validation/index.d.cts +2 -2
- package/dist/validation/index.d.ts +2 -2
- package/dist/xml/index.cjs +74 -8
- package/dist/xml/index.cjs.map +1 -1
- package/dist/xml/index.d.cts +3 -3
- package/dist/xml/index.d.ts +3 -3
- package/dist/xml/index.js +1 -1
- package/package.json +2 -2
- package/dist/chunk-MZVDC6FU.js.map +0 -1
- package/dist/chunk-O3NWJ5H7.js.map +0 -1
- package/dist/chunk-OZKTOILD.js +0 -3
- package/dist/chunk-OZKTOILD.js.map +0 -1
package/dist/layout/index.d.ts
CHANGED
|
@@ -1,25 +1,31 @@
|
|
|
1
1
|
import { LayoutResult, LayoutOptions } from '@aranzatech/diagrams-core/types';
|
|
2
2
|
export { applyLayoutResultToDiagram } from '@aranzatech/diagrams-core/layout';
|
|
3
|
-
import { d as BpmnRFNode, c as BpmnRFEdge } from '../types-
|
|
3
|
+
import { d as BpmnRFNode, c as BpmnRFEdge } from '../types-DG5yPKld.js';
|
|
4
4
|
import { BpmnDiagramState } from '../modeling/index.js';
|
|
5
5
|
import '@xyflow/react';
|
|
6
|
-
import '../types-
|
|
6
|
+
import '../types-y-ZbX-ff.js';
|
|
7
7
|
import '@aranzatech/diagrams-core';
|
|
8
8
|
import '@aranzatech/diagrams-core/serialization';
|
|
9
|
-
import '../catalog-
|
|
9
|
+
import '../catalog-CK3_4cOb.js';
|
|
10
10
|
|
|
11
11
|
/**
|
|
12
12
|
* ELK-based auto-layout for BPMN diagrams.
|
|
13
13
|
*
|
|
14
|
-
*
|
|
14
|
+
* Spacing philosophy: fixed, generous values that scale consistently
|
|
15
|
+
* regardless of diagram size. "Air" between elements is not waste —
|
|
16
|
+
* it is what makes the flow readable to the human eye.
|
|
17
|
+
*
|
|
18
|
+
* Direction policy:
|
|
15
19
|
* - Root: RIGHT — free nodes and pools flow LR on the canvas.
|
|
16
|
-
* - Pool
|
|
17
|
-
*
|
|
18
|
-
* -
|
|
19
|
-
*
|
|
20
|
-
* -
|
|
21
|
-
*
|
|
22
|
-
* -
|
|
20
|
+
* - Pool with Lanes: DOWN internally so lanes stack top-to-bottom;
|
|
21
|
+
* the pool itself is placed LR on the canvas.
|
|
22
|
+
* - Lane / SubProcess / Pool-without-lanes: RIGHT — content flows LR.
|
|
23
|
+
* - Each container runs its own INCLUDE_CHILDREN pass (per-container
|
|
24
|
+
* hierarchyHandling) so cross-lane edges are routed correctly without
|
|
25
|
+
* the global RIGHT direction forcing Lane containers sideways.
|
|
26
|
+
* - Root uses INHERIT so each pool is laid out independently.
|
|
27
|
+
* - Post-processing equalises Lane widths within each Pool so all Lanes
|
|
28
|
+
* span the full Pool width.
|
|
23
29
|
*/
|
|
24
30
|
declare function bpmnElkLayout(nodes: BpmnRFNode[], edges: BpmnRFEdge[]): Promise<{
|
|
25
31
|
nodes: BpmnRFNode[];
|
package/dist/layout/index.js
CHANGED
|
@@ -13,20 +13,20 @@ var BPMN_CONTAINER_TYPES = /* @__PURE__ */ new Set([
|
|
|
13
13
|
"AdHocSubProcess"
|
|
14
14
|
]);
|
|
15
15
|
var CONTAINER_MIN_SIZE = {
|
|
16
|
-
Pool: { w:
|
|
17
|
-
Lane: { w:
|
|
18
|
-
SubProcess: { w:
|
|
19
|
-
Transaction: { w:
|
|
20
|
-
EventSubProcess: { w:
|
|
21
|
-
AdHocSubProcess: { w:
|
|
16
|
+
Pool: { w: 720, h: 200 },
|
|
17
|
+
Lane: { w: 600, h: 160 },
|
|
18
|
+
SubProcess: { w: 240, h: 140 },
|
|
19
|
+
Transaction: { w: 240, h: 140 },
|
|
20
|
+
EventSubProcess: { w: 240, h: 140 },
|
|
21
|
+
AdHocSubProcess: { w: 240, h: 140 }
|
|
22
22
|
};
|
|
23
23
|
var CONTAINER_PADDING = {
|
|
24
|
-
Pool: "[top=
|
|
25
|
-
Lane: "[top=
|
|
26
|
-
SubProcess: "[top=
|
|
27
|
-
Transaction: "[top=
|
|
28
|
-
EventSubProcess: "[top=
|
|
29
|
-
AdHocSubProcess: "[top=
|
|
24
|
+
Pool: "[top=30,left=60,bottom=30,right=50]",
|
|
25
|
+
Lane: "[top=40,left=70,bottom=40,right=50]",
|
|
26
|
+
SubProcess: "[top=30,left=40,bottom=30,right=40]",
|
|
27
|
+
Transaction: "[top=30,left=40,bottom=30,right=40]",
|
|
28
|
+
EventSubProcess: "[top=30,left=40,bottom=30,right=40]",
|
|
29
|
+
AdHocSubProcess: "[top=30,left=40,bottom=30,right=40]"
|
|
30
30
|
};
|
|
31
31
|
async function bpmnElkLayout(nodes, edges) {
|
|
32
32
|
const poolsWithLanes = /* @__PURE__ */ new Set();
|
|
@@ -47,13 +47,26 @@ async function bpmnElkLayout(nodes, edges) {
|
|
|
47
47
|
},
|
|
48
48
|
isContainerNode: (node) => BPMN_CONTAINER_TYPES.has(node.data.elementType),
|
|
49
49
|
getNodeLayoutOptions: (node) => {
|
|
50
|
-
const
|
|
50
|
+
const bNode = node;
|
|
51
|
+
const type = bNode.data.elementType;
|
|
51
52
|
if (!BPMN_CONTAINER_TYPES.has(type)) return void 0;
|
|
52
53
|
const min = CONTAINER_MIN_SIZE[type];
|
|
53
|
-
const
|
|
54
|
+
const isPoolWithLanes = type === "Pool" && poolsWithLanes.has(node.id);
|
|
55
|
+
const dir = isPoolWithLanes ? "DOWN" : "RIGHT";
|
|
54
56
|
return {
|
|
55
57
|
"elk.direction": dir,
|
|
56
58
|
"elk.nodeSize.constraints": "MINIMUM_SIZE",
|
|
59
|
+
// Each container handles its own layout pass so cross-lane edges
|
|
60
|
+
// participate in the internal layout without the global direction
|
|
61
|
+
// forcing Lane containers to align sideways.
|
|
62
|
+
"elk.hierarchyHandling": "INCLUDE_CHILDREN",
|
|
63
|
+
// Lanes within a Pool share a border — zero gap between them.
|
|
64
|
+
// Other containers keep the tighter inner spacing.
|
|
65
|
+
...isPoolWithLanes ? { "elk.spacing.nodeNode": "0", "elk.spacing.componentComponent": "0" } : {
|
|
66
|
+
"elk.layered.spacing.nodeNodeBetweenLayers": "100",
|
|
67
|
+
"elk.layered.spacing.edgeNodeBetweenLayers": "45",
|
|
68
|
+
"elk.spacing.nodeNode": "50"
|
|
69
|
+
},
|
|
57
70
|
...min ? { "elk.nodeSize.minimum": `[w=${min.w},h=${min.h}]` } : {},
|
|
58
71
|
...CONTAINER_PADDING[type] ? { "elk.padding": CONTAINER_PADDING[type] } : {}
|
|
59
72
|
};
|
|
@@ -61,12 +74,15 @@ async function bpmnElkLayout(nodes, edges) {
|
|
|
61
74
|
elk: {
|
|
62
75
|
"elk.algorithm": "layered",
|
|
63
76
|
"elk.direction": "RIGHT",
|
|
64
|
-
|
|
77
|
+
// INHERIT: each container handles its own INCLUDE_CHILDREN pass so
|
|
78
|
+
// the global RIGHT direction does not force Lane containers sideways.
|
|
79
|
+
"elk.hierarchyHandling": "INHERIT",
|
|
65
80
|
"elk.edgeRouting": "ORTHOGONAL",
|
|
66
|
-
|
|
67
|
-
"elk.layered.spacing.
|
|
68
|
-
"elk.spacing.
|
|
69
|
-
"elk.spacing.
|
|
81
|
+
// Global spacing — generous values for visual breathing room.
|
|
82
|
+
"elk.layered.spacing.nodeNodeBetweenLayers": "120",
|
|
83
|
+
"elk.layered.spacing.edgeNodeBetweenLayers": "50",
|
|
84
|
+
"elk.spacing.nodeNode": "70",
|
|
85
|
+
"elk.spacing.componentComponent": "100"
|
|
70
86
|
}
|
|
71
87
|
}
|
|
72
88
|
);
|
|
@@ -77,6 +93,26 @@ async function bpmnElkLayout(nodes, edges) {
|
|
|
77
93
|
if (!laid) return node;
|
|
78
94
|
return { ...node, position: laid.position, width: laid.width, height: laid.height };
|
|
79
95
|
});
|
|
96
|
+
const lanesByPool = /* @__PURE__ */ new Map();
|
|
97
|
+
for (const node of updatedNodes) {
|
|
98
|
+
if (node.data.elementType === "Lane" && node.parentId) {
|
|
99
|
+
const arr = lanesByPool.get(node.parentId) ?? [];
|
|
100
|
+
arr.push(node.id);
|
|
101
|
+
lanesByPool.set(node.parentId, arr);
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
const nodeIndex = new Map(updatedNodes.map((n, i) => [n.id, i]));
|
|
105
|
+
for (const laneIds of lanesByPool.values()) {
|
|
106
|
+
const widths = laneIds.map((id) => updatedNodes[nodeIndex.get(id)]?.width ?? 0);
|
|
107
|
+
const maxWidth = Math.max(...widths);
|
|
108
|
+
if (maxWidth <= 0) continue;
|
|
109
|
+
for (const id of laneIds) {
|
|
110
|
+
const idx = nodeIndex.get(id);
|
|
111
|
+
if (idx !== void 0) {
|
|
112
|
+
updatedNodes[idx] = { ...updatedNodes[idx], width: maxWidth };
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
}
|
|
80
116
|
const updatedEdges = edges.map((edge) => {
|
|
81
117
|
const laid = edgeMap.get(edge.id);
|
|
82
118
|
if (!laid) return edge;
|
package/dist/layout/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/layout/elk.ts","../../src/layout/index.ts"],"names":[],"mappings":"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","file":"index.js","sourcesContent":["import { elkLayout } from \"@aranzatech/diagrams-core/layout\";\nimport type { DiagramNode, DiagramEdge } from \"@aranzatech/diagrams-core/types\";\nimport type { BpmnRFNode, BpmnRFEdge } from \"../xml/types\";\nimport type { BpmnElementType } from \"../elements/types\";\nimport { getBpmnNodeSize } from \"../modeling\";\n\n// Container types that ELK auto-sizes based on their children.\nconst BPMN_CONTAINER_TYPES = new Set<BpmnElementType>([\n \"Pool\",\n \"Lane\",\n \"SubProcess\",\n \"Transaction\",\n \"EventSubProcess\",\n \"AdHocSubProcess\",\n]);\n\nconst CONTAINER_MIN_SIZE: Partial<Record<BpmnElementType, { w: number; h: number }>> = {\n Pool: { w: 560, h: 160 },\n Lane: { w: 480, h: 100 },\n SubProcess: { w: 200, h: 120 },\n Transaction: { w: 200, h: 120 },\n EventSubProcess: { w: 200, h: 120 },\n AdHocSubProcess: { w: 200, h: 120 },\n};\n\n// Left padding includes the pool label strip (≈30 px).\nconst CONTAINER_PADDING: Partial<Record<BpmnElementType, string>> = {\n Pool: \"[top=20,left=30,bottom=20,right=20]\",\n Lane: \"[top=20,left=50,bottom=20,right=50]\",\n SubProcess: \"[top=20,left=30,bottom=20,right=30]\",\n Transaction: \"[top=20,left=30,bottom=20,right=30]\",\n EventSubProcess: \"[top=20,left=30,bottom=20,right=30]\",\n AdHocSubProcess: \"[top=20,left=30,bottom=20,right=30]\",\n};\n\n/**\n * ELK-based auto-layout for BPMN diagrams.\n *\n * Direction policy — always LEFT-TO-RIGHT to match screen anatomy:\n * - Root: RIGHT — free nodes and pools flow LR on the canvas.\n * - Pool that contains Lanes: DOWN internally so lanes stack top-to-bottom\n * (standard horizontal-pool anatomy); the pool itself is still placed LR.\n * - Pool without lanes, Lane, SubProcess, Transaction, AdHoc: RIGHT — content\n * flows left-to-right inside the container.\n * - All edges get ORTHOGONAL routing in a single INCLUDE_CHILDREN pass so\n * cross-pool and cross-lane edges are routed correctly.\n * - Containers auto-resize to fit their children.\n */\nexport async function bpmnElkLayout(\n nodes: BpmnRFNode[],\n edges: BpmnRFEdge[],\n): Promise<{ nodes: BpmnRFNode[]; edges: BpmnRFEdge[] }> {\n // Pools that contain at least one Lane child need DOWN internal direction so\n // the lanes stack vertically (standard horizontal BPMN pool).\n const poolsWithLanes = new Set<string>();\n for (const node of nodes) {\n if (node.data.elementType === \"Lane\" && node.parentId) {\n poolsWithLanes.add(node.parentId);\n }\n }\n\n const result = await elkLayout(\n nodes as unknown as DiagramNode[],\n edges as unknown as DiagramEdge[],\n {\n direction: \"LR\",\n getNodeSize: (node) => {\n const bNode = node as unknown as BpmnRFNode;\n if (BPMN_CONTAINER_TYPES.has(bNode.data.elementType)) return undefined;\n return getBpmnNodeSize(bNode);\n },\n isContainerNode: (node) =>\n BPMN_CONTAINER_TYPES.has((node as unknown as BpmnRFNode).data.elementType),\n getNodeLayoutOptions: (node) => {\n const type = (node as unknown as BpmnRFNode).data.elementType;\n if (!BPMN_CONTAINER_TYPES.has(type)) return undefined;\n const min = CONTAINER_MIN_SIZE[type];\n // Pool with Lanes: DOWN so lanes stack top-to-bottom inside the pool.\n // Everything else (Lane content, SubProcess, free tasks): RIGHT (LR).\n const dir = type === \"Pool\" && poolsWithLanes.has(node.id) ? \"DOWN\" : \"RIGHT\";\n return {\n \"elk.direction\": dir,\n \"elk.nodeSize.constraints\": \"MINIMUM_SIZE\",\n ...(min ? { \"elk.nodeSize.minimum\": `[w=${min.w},h=${min.h}]` } : {}),\n ...(CONTAINER_PADDING[type] ? { \"elk.padding\": CONTAINER_PADDING[type] } : {}),\n };\n },\n elk: {\n \"elk.algorithm\": \"layered\",\n \"elk.direction\": \"RIGHT\",\n \"elk.hierarchyHandling\": \"INCLUDE_CHILDREN\",\n \"elk.edgeRouting\": \"ORTHOGONAL\",\n \"elk.layered.spacing.nodeNodeBetweenLayers\": \"80\",\n \"elk.layered.spacing.edgeNodeBetweenLayers\": \"20\",\n \"elk.spacing.nodeNode\": \"40\",\n \"elk.spacing.componentComponent\": \"60\",\n },\n },\n );\n\n const nodeMap = new Map(result.nodes.map((n) => [n.id, n]));\n const edgeMap = new Map(result.edges.map((e) => [e.id, e]));\n\n const updatedNodes = nodes.map((node) => {\n const laid = nodeMap.get(node.id);\n if (!laid) return node;\n return { ...node, position: laid.position, width: laid.width, height: laid.height };\n });\n\n const updatedEdges = edges.map((edge) => {\n const laid = edgeMap.get(edge.id);\n if (!laid) return edge;\n const nextData = { ...edge.data };\n if (laid.points && laid.points.length > 0) {\n nextData.routingPoints = laid.points;\n } else {\n delete nextData.routingPoints;\n }\n return { ...edge, data: nextData };\n });\n\n return { nodes: updatedNodes, edges: updatedEdges as BpmnRFEdge[] };\n}\n","import type { DiagramEdge, LayoutOptions, LayoutResult } from \"@aranzatech/diagrams-core/types\";\nimport { dagreLayout, applyLayoutResultToDiagram } from \"@aranzatech/diagrams-core/layout\";\nimport type { DiagramNode } from \"@aranzatech/diagrams-core/types\";\nimport type { BpmnRFNode, BpmnRFEdge } from \"../xml/types\";\nimport { getBpmnNodeSize } from \"../modeling\";\nimport type { BpmnDiagramState } from \"../modeling\";\n\nexport { applyLayoutResultToDiagram };\nexport { bpmnElkLayout } from \"./elk\";\n\n/**\n * Dagre layout pre-configured for BPMN diagrams.\n * Uses BPMN-specific node sizes (events 52×52, gateways 64×64, tasks 192×64, etc.)\n * instead of the generic fallback, which prevents overlaps and poor spacing.\n */\nexport async function bpmnDagreLayout(\n nodes: BpmnRFNode[],\n edges: BpmnRFEdge[],\n options: LayoutOptions = {},\n): Promise<LayoutResult> {\n return dagreLayout(nodes as DiagramNode[], edges as DiagramEdge[], {\n ...options,\n getNodeSize: (node) => getBpmnNodeSize(node as BpmnRFNode),\n });\n}\n\n/**\n * Applies a bpmn dagre layout result back to the diagram state.\n * Convenience wrapper so callers only need one import.\n */\nexport function applyBpmnLayoutResult(\n state: BpmnDiagramState,\n result: LayoutResult,\n): BpmnDiagramState {\n return applyLayoutResultToDiagram(state, result) as BpmnDiagramState;\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../../src/layout/elk.ts","../../src/layout/index.ts"],"names":[],"mappings":"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","file":"index.js","sourcesContent":["import { elkLayout } from \"@aranzatech/diagrams-core/layout\";\nimport type { DiagramNode, DiagramEdge } from \"@aranzatech/diagrams-core/types\";\nimport type { BpmnRFNode, BpmnRFEdge } from \"../xml/types\";\nimport type { BpmnElementType } from \"../elements/types\";\nimport { getBpmnNodeSize } from \"../modeling\";\n\n// Container types that ELK auto-sizes based on their children.\nconst BPMN_CONTAINER_TYPES = new Set<BpmnElementType>([\n \"Pool\",\n \"Lane\",\n \"SubProcess\",\n \"Transaction\",\n \"EventSubProcess\",\n \"AdHocSubProcess\",\n]);\n\nconst CONTAINER_MIN_SIZE: Partial<Record<BpmnElementType, { w: number; h: number }>> = {\n Pool: { w: 720, h: 200 },\n Lane: { w: 600, h: 160 },\n SubProcess: { w: 240, h: 140 },\n Transaction: { w: 240, h: 140 },\n EventSubProcess: { w: 240, h: 140 },\n AdHocSubProcess: { w: 240, h: 140 },\n};\n\n// Padding inside each container type.\n// Left padding for Pool/Lane accounts for the vertical label strip (~30px) + breathing room.\nconst CONTAINER_PADDING: Partial<Record<BpmnElementType, string>> = {\n Pool: \"[top=30,left=60,bottom=30,right=50]\",\n Lane: \"[top=40,left=70,bottom=40,right=50]\",\n SubProcess: \"[top=30,left=40,bottom=30,right=40]\",\n Transaction: \"[top=30,left=40,bottom=30,right=40]\",\n EventSubProcess: \"[top=30,left=40,bottom=30,right=40]\",\n AdHocSubProcess: \"[top=30,left=40,bottom=30,right=40]\",\n};\n\n/**\n * ELK-based auto-layout for BPMN diagrams.\n *\n * Spacing philosophy: fixed, generous values that scale consistently\n * regardless of diagram size. \"Air\" between elements is not waste —\n * it is what makes the flow readable to the human eye.\n *\n * Direction policy:\n * - Root: RIGHT — free nodes and pools flow LR on the canvas.\n * - Pool with Lanes: DOWN internally so lanes stack top-to-bottom;\n * the pool itself is placed LR on the canvas.\n * - Lane / SubProcess / Pool-without-lanes: RIGHT — content flows LR.\n * - Each container runs its own INCLUDE_CHILDREN pass (per-container\n * hierarchyHandling) so cross-lane edges are routed correctly without\n * the global RIGHT direction forcing Lane containers sideways.\n * - Root uses INHERIT so each pool is laid out independently.\n * - Post-processing equalises Lane widths within each Pool so all Lanes\n * span the full Pool width.\n */\nexport async function bpmnElkLayout(\n nodes: BpmnRFNode[],\n edges: BpmnRFEdge[],\n): Promise<{ nodes: BpmnRFNode[]; edges: BpmnRFEdge[] }> {\n // Pools that directly contain at least one Lane.\n const poolsWithLanes = new Set<string>();\n for (const node of nodes) {\n if (node.data.elementType === \"Lane\" && node.parentId) {\n poolsWithLanes.add(node.parentId);\n }\n }\n\n const result = await elkLayout(\n nodes as unknown as DiagramNode[],\n edges as unknown as DiagramEdge[],\n {\n direction: \"LR\",\n getNodeSize: (node) => {\n const bNode = node as unknown as BpmnRFNode;\n if (BPMN_CONTAINER_TYPES.has(bNode.data.elementType)) return undefined;\n return getBpmnNodeSize(bNode);\n },\n isContainerNode: (node) =>\n BPMN_CONTAINER_TYPES.has((node as unknown as BpmnRFNode).data.elementType),\n getNodeLayoutOptions: (node) => {\n const bNode = node as unknown as BpmnRFNode;\n const type = bNode.data.elementType;\n if (!BPMN_CONTAINER_TYPES.has(type)) return undefined;\n\n const min = CONTAINER_MIN_SIZE[type];\n const isPoolWithLanes = type === \"Pool\" && poolsWithLanes.has(node.id);\n\n // Pool with Lanes stacks Lanes top-to-bottom (standard horizontal BPMN).\n // Everything else flows left-to-right.\n const dir = isPoolWithLanes ? \"DOWN\" : \"RIGHT\";\n\n return {\n \"elk.direction\": dir,\n \"elk.nodeSize.constraints\": \"MINIMUM_SIZE\",\n // Each container handles its own layout pass so cross-lane edges\n // participate in the internal layout without the global direction\n // forcing Lane containers to align sideways.\n \"elk.hierarchyHandling\": \"INCLUDE_CHILDREN\",\n // Lanes within a Pool share a border — zero gap between them.\n // Other containers keep the tighter inner spacing.\n ...(isPoolWithLanes\n ? { \"elk.spacing.nodeNode\": \"0\", \"elk.spacing.componentComponent\": \"0\" }\n : {\n \"elk.layered.spacing.nodeNodeBetweenLayers\": \"100\",\n \"elk.layered.spacing.edgeNodeBetweenLayers\": \"45\",\n \"elk.spacing.nodeNode\": \"50\",\n }),\n ...(min ? { \"elk.nodeSize.minimum\": `[w=${min.w},h=${min.h}]` } : {}),\n ...(CONTAINER_PADDING[type] ? { \"elk.padding\": CONTAINER_PADDING[type] } : {}),\n };\n },\n elk: {\n \"elk.algorithm\": \"layered\",\n \"elk.direction\": \"RIGHT\",\n // INHERIT: each container handles its own INCLUDE_CHILDREN pass so\n // the global RIGHT direction does not force Lane containers sideways.\n \"elk.hierarchyHandling\": \"INHERIT\",\n \"elk.edgeRouting\": \"ORTHOGONAL\",\n // Global spacing — generous values for visual breathing room.\n \"elk.layered.spacing.nodeNodeBetweenLayers\": \"120\",\n \"elk.layered.spacing.edgeNodeBetweenLayers\": \"50\",\n \"elk.spacing.nodeNode\": \"70\",\n \"elk.spacing.componentComponent\": \"100\",\n },\n },\n );\n\n const nodeMap = new Map(result.nodes.map((n) => [n.id, n]));\n const edgeMap = new Map(result.edges.map((e) => [e.id, e]));\n\n const updatedNodes = nodes.map((node) => {\n const laid = nodeMap.get(node.id);\n if (!laid) return node;\n return { ...node, position: laid.position, width: laid.width, height: laid.height };\n });\n\n // Post-processing: equalise Lane widths within each Pool so all Lanes\n // span the full Pool width regardless of their individual content width.\n const lanesByPool = new Map<string, string[]>();\n for (const node of updatedNodes) {\n if (node.data.elementType === \"Lane\" && node.parentId) {\n const arr = lanesByPool.get(node.parentId) ?? [];\n arr.push(node.id);\n lanesByPool.set(node.parentId, arr);\n }\n }\n const nodeIndex = new Map(updatedNodes.map((n, i) => [n.id, i]));\n for (const laneIds of lanesByPool.values()) {\n const widths = laneIds.map((id) => updatedNodes[nodeIndex.get(id)!]?.width ?? 0);\n const maxWidth = Math.max(...widths);\n if (maxWidth <= 0) continue;\n for (const id of laneIds) {\n const idx = nodeIndex.get(id);\n if (idx !== undefined) {\n updatedNodes[idx] = { ...updatedNodes[idx], width: maxWidth };\n }\n }\n }\n\n const updatedEdges = edges.map((edge) => {\n const laid = edgeMap.get(edge.id);\n if (!laid) return edge;\n const nextData = { ...edge.data };\n if (laid.points && laid.points.length > 0) {\n nextData.routingPoints = laid.points;\n } else {\n delete nextData.routingPoints;\n }\n return { ...edge, data: nextData };\n });\n\n return { nodes: updatedNodes, edges: updatedEdges as BpmnRFEdge[] };\n}\n","import type { DiagramEdge, LayoutOptions, LayoutResult } from \"@aranzatech/diagrams-core/types\";\nimport { dagreLayout, applyLayoutResultToDiagram } from \"@aranzatech/diagrams-core/layout\";\nimport type { DiagramNode } from \"@aranzatech/diagrams-core/types\";\nimport type { BpmnRFNode, BpmnRFEdge } from \"../xml/types\";\nimport { getBpmnNodeSize } from \"../modeling\";\nimport type { BpmnDiagramState } from \"../modeling\";\n\nexport { applyLayoutResultToDiagram };\nexport { bpmnElkLayout } from \"./elk\";\n\n/**\n * Dagre layout pre-configured for BPMN diagrams.\n * Uses BPMN-specific node sizes (events 52×52, gateways 64×64, tasks 192×64, etc.)\n * instead of the generic fallback, which prevents overlaps and poor spacing.\n */\nexport async function bpmnDagreLayout(\n nodes: BpmnRFNode[],\n edges: BpmnRFEdge[],\n options: LayoutOptions = {},\n): Promise<LayoutResult> {\n return dagreLayout(nodes as DiagramNode[], edges as DiagramEdge[], {\n ...options,\n getNodeSize: (node) => getBpmnNodeSize(node as BpmnRFNode),\n });\n}\n\n/**\n * Applies a bpmn dagre layout result back to the diagram state.\n * Convenience wrapper so callers only need one import.\n */\nexport function applyBpmnLayoutResult(\n state: BpmnDiagramState,\n result: LayoutResult,\n): BpmnDiagramState {\n return applyLayoutResultToDiagram(state, result) as BpmnDiagramState;\n}\n"]}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { ModelingRules, ClipboardState, DiagramSnapshot, DiagramState, DiagramEventBus, ResizeHandlePosition, DiagramCommand, ConnectionValidator, SmartGuideResult, SelectionState, LayoutCacheOptions, LayoutCache, EdgeLabelOffsetOptions, EdgeLabelLayout, CommandStackState, Viewport, LayoutFn } from '@aranzatech/diagrams-core';
|
|
2
2
|
import { DiagramDocument, CreateDiagramDocumentOptions } from '@aranzatech/diagrams-core/serialization';
|
|
3
|
-
import { c as BpmnEdgeType, b as BpmnEdgeData, f as BpmnElementType, m as BpmnNodeData } from '../types-
|
|
4
|
-
import { d as BpmnRFNode, c as BpmnRFEdge } from '../types-
|
|
5
|
-
export { g as getBpmnElementSize, i as isBpmnElementResizable } from '../catalog-
|
|
3
|
+
import { c as BpmnEdgeType, b as BpmnEdgeData, f as BpmnElementType, m as BpmnNodeData } from '../types-y-ZbX-ff.cjs';
|
|
4
|
+
import { d as BpmnRFNode, c as BpmnRFEdge } from '../types-jIDz306Y.cjs';
|
|
5
|
+
export { g as getBpmnElementSize, i as isBpmnElementResizable } from '../catalog-xOMF2ifW.cjs';
|
|
6
6
|
import '@xyflow/react';
|
|
7
7
|
|
|
8
8
|
type BpmnDiagramState = DiagramState<BpmnRFNode, BpmnRFEdge>;
|
package/dist/modeling/index.d.ts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { ModelingRules, ClipboardState, DiagramSnapshot, DiagramState, DiagramEventBus, ResizeHandlePosition, DiagramCommand, ConnectionValidator, SmartGuideResult, SelectionState, LayoutCacheOptions, LayoutCache, EdgeLabelOffsetOptions, EdgeLabelLayout, CommandStackState, Viewport, LayoutFn } from '@aranzatech/diagrams-core';
|
|
2
2
|
import { DiagramDocument, CreateDiagramDocumentOptions } from '@aranzatech/diagrams-core/serialization';
|
|
3
|
-
import { c as BpmnEdgeType, b as BpmnEdgeData, f as BpmnElementType, m as BpmnNodeData } from '../types-
|
|
4
|
-
import { d as BpmnRFNode, c as BpmnRFEdge } from '../types-
|
|
5
|
-
export { g as getBpmnElementSize, i as isBpmnElementResizable } from '../catalog-
|
|
3
|
+
import { c as BpmnEdgeType, b as BpmnEdgeData, f as BpmnElementType, m as BpmnNodeData } from '../types-y-ZbX-ff.js';
|
|
4
|
+
import { d as BpmnRFNode, c as BpmnRFEdge } from '../types-DG5yPKld.js';
|
|
5
|
+
export { g as getBpmnElementSize, i as isBpmnElementResizable } from '../catalog-CK3_4cOb.js';
|
|
6
6
|
import '@xyflow/react';
|
|
7
7
|
|
|
8
8
|
type BpmnDiagramState = DiagramState<BpmnRFNode, BpmnRFEdge>;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Node, Edge } from '@xyflow/react';
|
|
2
|
-
import { m as BpmnNodeData, b as BpmnEdgeData, a as BpmnDefinitionsSet } from './types-
|
|
2
|
+
import { m as BpmnNodeData, b as BpmnEdgeData, a as BpmnDefinitionsSet } from './types-y-ZbX-ff.js';
|
|
3
3
|
|
|
4
4
|
type BpmnRFNode = Node<BpmnNodeData>;
|
|
5
5
|
type BpmnRFEdge = Edge<BpmnEdgeData>;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Node, Edge } from '@xyflow/react';
|
|
2
|
-
import { m as BpmnNodeData, b as BpmnEdgeData, a as BpmnDefinitionsSet } from './types-
|
|
2
|
+
import { m as BpmnNodeData, b as BpmnEdgeData, a as BpmnDefinitionsSet } from './types-y-ZbX-ff.cjs';
|
|
3
3
|
|
|
4
4
|
type BpmnRFNode = Node<BpmnNodeData>;
|
|
5
5
|
type BpmnRFEdge = Edge<BpmnEdgeData>;
|
|
@@ -166,6 +166,8 @@ interface BpmnNodeData extends Record<string, unknown> {
|
|
|
166
166
|
script?: string;
|
|
167
167
|
/** BusinessRuleTask: id of the referenced DMN decision table. */
|
|
168
168
|
decisionRef?: string;
|
|
169
|
+
/** BusinessRuleTask: simplified inline decision table (alternative to external decisionRef). */
|
|
170
|
+
inlineDecisionTable?: InlineDecisionTable;
|
|
169
171
|
/** UserTask: form key resolved to a FormDefinition by name at runtime. */
|
|
170
172
|
formKey?: string;
|
|
171
173
|
/** UserTask: comma-separated Flowable user ids that can claim this task. */
|
|
@@ -191,6 +193,28 @@ interface BpmnNodeData extends Record<string, unknown> {
|
|
|
191
193
|
/** MultiInstanceLoopCharacteristics: FEEL condition to stop before all instances finish. */
|
|
192
194
|
loopCompletionCondition?: string;
|
|
193
195
|
}
|
|
196
|
+
interface InlineDecisionInput {
|
|
197
|
+
id: string;
|
|
198
|
+
expression: string;
|
|
199
|
+
label: string;
|
|
200
|
+
}
|
|
201
|
+
interface InlineDecisionOutput {
|
|
202
|
+
id: string;
|
|
203
|
+
name: string;
|
|
204
|
+
label: string;
|
|
205
|
+
}
|
|
206
|
+
interface InlineDecisionRule {
|
|
207
|
+
id: string;
|
|
208
|
+
inputs: Record<string, string>;
|
|
209
|
+
outputs: Record<string, string>;
|
|
210
|
+
annotation?: string;
|
|
211
|
+
}
|
|
212
|
+
interface InlineDecisionTable {
|
|
213
|
+
hitPolicy: "FIRST" | "UNIQUE" | "COLLECT";
|
|
214
|
+
inputs: InlineDecisionInput[];
|
|
215
|
+
outputs: InlineDecisionOutput[];
|
|
216
|
+
rules: InlineDecisionRule[];
|
|
217
|
+
}
|
|
194
218
|
interface BpmnEdgeData extends Record<string, unknown> {
|
|
195
219
|
label?: string;
|
|
196
220
|
edgeType: BpmnEdgeType;
|
|
@@ -206,6 +230,13 @@ interface BpmnEdgeData extends Record<string, unknown> {
|
|
|
206
230
|
x: number;
|
|
207
231
|
y: number;
|
|
208
232
|
}>;
|
|
233
|
+
/** Manual label offset from the auto-computed midpoint (px). Set by dragging the label. */
|
|
234
|
+
labelOffsetX?: number;
|
|
235
|
+
labelOffsetY?: number;
|
|
236
|
+
/** MessageFlow: free-text description or JSON schema of the message payload. */
|
|
237
|
+
payloadSchema?: string;
|
|
238
|
+
/** MessageFlow: FEEL/JSONPath correlation key expression, e.g. $.orderId. */
|
|
239
|
+
correlationKey?: string;
|
|
209
240
|
}
|
|
210
241
|
|
|
211
|
-
export type { BpmnCategory as B, EventTrigger as E, SubProcessVariant as S, TaskMarker as T, BpmnDefinitionsSet as a, BpmnEdgeData as b, BpmnEdgeType as c, BpmnElementMeta as d, BpmnElementSize as e, BpmnElementType as f, BpmnErrorDefinition as g, BpmnEscalationDefinition as h, BpmnEventDefinition as i, BpmnEventSemantics as j, BpmnHandlePolicy as k, BpmnMessageDefinition as l, BpmnNodeData as m, BpmnOrientation as n, BpmnProcessVariable as o, BpmnSignalDefinition as p, BpmnTimerDefinition as q, BpmnTimerKind as r };
|
|
242
|
+
export type { BpmnCategory as B, EventTrigger as E, InlineDecisionInput as I, SubProcessVariant as S, TaskMarker as T, BpmnDefinitionsSet as a, BpmnEdgeData as b, BpmnEdgeType as c, BpmnElementMeta as d, BpmnElementSize as e, BpmnElementType as f, BpmnErrorDefinition as g, BpmnEscalationDefinition as h, BpmnEventDefinition as i, BpmnEventSemantics as j, BpmnHandlePolicy as k, BpmnMessageDefinition as l, BpmnNodeData as m, BpmnOrientation as n, BpmnProcessVariable as o, BpmnSignalDefinition as p, BpmnTimerDefinition as q, BpmnTimerKind as r, InlineDecisionOutput as s, InlineDecisionRule as t, InlineDecisionTable as u };
|
|
@@ -166,6 +166,8 @@ interface BpmnNodeData extends Record<string, unknown> {
|
|
|
166
166
|
script?: string;
|
|
167
167
|
/** BusinessRuleTask: id of the referenced DMN decision table. */
|
|
168
168
|
decisionRef?: string;
|
|
169
|
+
/** BusinessRuleTask: simplified inline decision table (alternative to external decisionRef). */
|
|
170
|
+
inlineDecisionTable?: InlineDecisionTable;
|
|
169
171
|
/** UserTask: form key resolved to a FormDefinition by name at runtime. */
|
|
170
172
|
formKey?: string;
|
|
171
173
|
/** UserTask: comma-separated Flowable user ids that can claim this task. */
|
|
@@ -191,6 +193,28 @@ interface BpmnNodeData extends Record<string, unknown> {
|
|
|
191
193
|
/** MultiInstanceLoopCharacteristics: FEEL condition to stop before all instances finish. */
|
|
192
194
|
loopCompletionCondition?: string;
|
|
193
195
|
}
|
|
196
|
+
interface InlineDecisionInput {
|
|
197
|
+
id: string;
|
|
198
|
+
expression: string;
|
|
199
|
+
label: string;
|
|
200
|
+
}
|
|
201
|
+
interface InlineDecisionOutput {
|
|
202
|
+
id: string;
|
|
203
|
+
name: string;
|
|
204
|
+
label: string;
|
|
205
|
+
}
|
|
206
|
+
interface InlineDecisionRule {
|
|
207
|
+
id: string;
|
|
208
|
+
inputs: Record<string, string>;
|
|
209
|
+
outputs: Record<string, string>;
|
|
210
|
+
annotation?: string;
|
|
211
|
+
}
|
|
212
|
+
interface InlineDecisionTable {
|
|
213
|
+
hitPolicy: "FIRST" | "UNIQUE" | "COLLECT";
|
|
214
|
+
inputs: InlineDecisionInput[];
|
|
215
|
+
outputs: InlineDecisionOutput[];
|
|
216
|
+
rules: InlineDecisionRule[];
|
|
217
|
+
}
|
|
194
218
|
interface BpmnEdgeData extends Record<string, unknown> {
|
|
195
219
|
label?: string;
|
|
196
220
|
edgeType: BpmnEdgeType;
|
|
@@ -206,6 +230,13 @@ interface BpmnEdgeData extends Record<string, unknown> {
|
|
|
206
230
|
x: number;
|
|
207
231
|
y: number;
|
|
208
232
|
}>;
|
|
233
|
+
/** Manual label offset from the auto-computed midpoint (px). Set by dragging the label. */
|
|
234
|
+
labelOffsetX?: number;
|
|
235
|
+
labelOffsetY?: number;
|
|
236
|
+
/** MessageFlow: free-text description or JSON schema of the message payload. */
|
|
237
|
+
payloadSchema?: string;
|
|
238
|
+
/** MessageFlow: FEEL/JSONPath correlation key expression, e.g. $.orderId. */
|
|
239
|
+
correlationKey?: string;
|
|
209
240
|
}
|
|
210
241
|
|
|
211
|
-
export type { BpmnCategory as B, EventTrigger as E, SubProcessVariant as S, TaskMarker as T, BpmnDefinitionsSet as a, BpmnEdgeData as b, BpmnEdgeType as c, BpmnElementMeta as d, BpmnElementSize as e, BpmnElementType as f, BpmnErrorDefinition as g, BpmnEscalationDefinition as h, BpmnEventDefinition as i, BpmnEventSemantics as j, BpmnHandlePolicy as k, BpmnMessageDefinition as l, BpmnNodeData as m, BpmnOrientation as n, BpmnProcessVariable as o, BpmnSignalDefinition as p, BpmnTimerDefinition as q, BpmnTimerKind as r };
|
|
242
|
+
export type { BpmnCategory as B, EventTrigger as E, InlineDecisionInput as I, SubProcessVariant as S, TaskMarker as T, BpmnDefinitionsSet as a, BpmnEdgeData as b, BpmnEdgeType as c, BpmnElementMeta as d, BpmnElementSize as e, BpmnElementType as f, BpmnErrorDefinition as g, BpmnEscalationDefinition as h, BpmnEventDefinition as i, BpmnEventSemantics as j, BpmnHandlePolicy as k, BpmnMessageDefinition as l, BpmnNodeData as m, BpmnOrientation as n, BpmnProcessVariable as o, BpmnSignalDefinition as p, BpmnTimerDefinition as q, BpmnTimerKind as r, InlineDecisionOutput as s, InlineDecisionRule as t, InlineDecisionTable as u };
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { d as BpmnRFNode, c as BpmnRFEdge } from '../types-
|
|
1
|
+
import { d as BpmnRFNode, c as BpmnRFEdge } from '../types-jIDz306Y.cjs';
|
|
2
2
|
import '@xyflow/react';
|
|
3
|
-
import '../types-
|
|
3
|
+
import '../types-y-ZbX-ff.cjs';
|
|
4
4
|
|
|
5
5
|
type BpmnValidationSeverity = "error" | "warning" | "info";
|
|
6
6
|
interface BpmnValidationIssue {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { d as BpmnRFNode, c as BpmnRFEdge } from '../types-
|
|
1
|
+
import { d as BpmnRFNode, c as BpmnRFEdge } from '../types-DG5yPKld.js';
|
|
2
2
|
import '@xyflow/react';
|
|
3
|
-
import '../types-
|
|
3
|
+
import '../types-y-ZbX-ff.js';
|
|
4
4
|
|
|
5
5
|
type BpmnValidationSeverity = "error" | "warning" | "info";
|
|
6
6
|
interface BpmnValidationIssue {
|
package/dist/xml/index.cjs
CHANGED
|
@@ -32,6 +32,24 @@ var ARANZA_DESCRIPTOR = {
|
|
|
32
32
|
{ name: "skipExpression", isAttr: true, type: "String" },
|
|
33
33
|
{ name: "businessCalendarName", isAttr: true, type: "String" }
|
|
34
34
|
]
|
|
35
|
+
},
|
|
36
|
+
{
|
|
37
|
+
// BusinessRuleTask: simplified inline decision table (JSON-serialized)
|
|
38
|
+
name: "InlineDecision",
|
|
39
|
+
superClass: ["Element"],
|
|
40
|
+
properties: [
|
|
41
|
+
{ name: "hitPolicy", isAttr: true, type: "String" },
|
|
42
|
+
{ name: "tableJson", isAttr: true, type: "String" }
|
|
43
|
+
]
|
|
44
|
+
},
|
|
45
|
+
{
|
|
46
|
+
// MessageFlow: payload schema + correlation key for executable BPMN
|
|
47
|
+
name: "MessageFlowConfig",
|
|
48
|
+
superClass: ["Element"],
|
|
49
|
+
properties: [
|
|
50
|
+
{ name: "payloadSchema", isAttr: true, type: "String" },
|
|
51
|
+
{ name: "correlationKey", isAttr: true, type: "String" }
|
|
52
|
+
]
|
|
35
53
|
}
|
|
36
54
|
],
|
|
37
55
|
enumerations: [],
|
|
@@ -911,7 +929,20 @@ function extractAranzaExtensions(el) {
|
|
|
911
929
|
}
|
|
912
930
|
const ext = el.extensionElements;
|
|
913
931
|
if (!ext) return result;
|
|
914
|
-
const
|
|
932
|
+
const extValues = asElements(ext.values);
|
|
933
|
+
const inlineDecision = extValues.find((v) => v.$type === "aranza:InlineDecision");
|
|
934
|
+
if (inlineDecision) {
|
|
935
|
+
const hitPolicy = asString(inlineDecision.hitPolicy) ?? "UNIQUE";
|
|
936
|
+
const tableJson = asString(inlineDecision.tableJson);
|
|
937
|
+
if (tableJson) {
|
|
938
|
+
try {
|
|
939
|
+
const parsed = JSON.parse(tableJson);
|
|
940
|
+
result.inlineDecisionTable = { hitPolicy, ...parsed };
|
|
941
|
+
} catch {
|
|
942
|
+
}
|
|
943
|
+
}
|
|
944
|
+
}
|
|
945
|
+
const taskConfig = extValues.find((v) => v.$type === "aranza:TaskConfig");
|
|
915
946
|
if (!taskConfig) return result;
|
|
916
947
|
const priority = asString(taskConfig.priority);
|
|
917
948
|
if (priority === "critical" || priority === "high" || priority === "medium" || priority === "low") {
|
|
@@ -1069,12 +1100,26 @@ function buildEdge(el, edgeType, ctx, edges) {
|
|
|
1069
1100
|
const condExpr = el.conditionExpression;
|
|
1070
1101
|
const rawDir = asString(el.associationDirection);
|
|
1071
1102
|
const associationDirection = edgeType === "association" && rawDir ? rawDir.toLowerCase() : void 0;
|
|
1103
|
+
let payloadSchema;
|
|
1104
|
+
let correlationKey;
|
|
1105
|
+
if (edgeType === "messageFlow") {
|
|
1106
|
+
const mfExt = el.extensionElements;
|
|
1107
|
+
if (mfExt) {
|
|
1108
|
+
const mfConfig = asElements(mfExt.values).find((v) => v.$type === "aranza:MessageFlowConfig");
|
|
1109
|
+
if (mfConfig) {
|
|
1110
|
+
payloadSchema = asString(mfConfig.payloadSchema) || void 0;
|
|
1111
|
+
correlationKey = asString(mfConfig.correlationKey) || void 0;
|
|
1112
|
+
}
|
|
1113
|
+
}
|
|
1114
|
+
}
|
|
1072
1115
|
const data = {
|
|
1073
1116
|
edgeType,
|
|
1074
1117
|
...label ? { label } : {},
|
|
1075
1118
|
...documentation ? { documentation } : {},
|
|
1076
1119
|
...condExpr?.body ? { conditionExpression: condExpr.body } : {},
|
|
1077
|
-
...associationDirection ? { associationDirection } : {}
|
|
1120
|
+
...associationDirection ? { associationDirection } : {},
|
|
1121
|
+
...payloadSchema ? { payloadSchema } : {},
|
|
1122
|
+
...correlationKey ? { correlationKey } : {}
|
|
1078
1123
|
};
|
|
1079
1124
|
const waypoints = ctx.waypoints.get(id);
|
|
1080
1125
|
if (waypoints?.length) data.routingPoints = waypoints;
|
|
@@ -1361,8 +1406,19 @@ function buildAranzaExtensionElements(moddle, node) {
|
|
|
1361
1406
|
if (dueDate) configAttrs.dueDate = dueDate;
|
|
1362
1407
|
if (skipExpression) configAttrs.skipExpression = skipExpression;
|
|
1363
1408
|
if (businessCalendarName) configAttrs.businessCalendarName = businessCalendarName;
|
|
1364
|
-
const
|
|
1365
|
-
|
|
1409
|
+
const values = [moddle.create("aranza:TaskConfig", configAttrs)];
|
|
1410
|
+
const inlineDecisionTable = node.data.inlineDecisionTable;
|
|
1411
|
+
if (inlineDecisionTable && typeof inlineDecisionTable === "object") {
|
|
1412
|
+
const tbl = inlineDecisionTable;
|
|
1413
|
+
const { hitPolicy, ...rest } = tbl;
|
|
1414
|
+
values.push(
|
|
1415
|
+
moddle.create("aranza:InlineDecision", {
|
|
1416
|
+
hitPolicy: hitPolicy ?? "UNIQUE",
|
|
1417
|
+
tableJson: JSON.stringify(rest)
|
|
1418
|
+
})
|
|
1419
|
+
);
|
|
1420
|
+
}
|
|
1421
|
+
return moddle.create("bpmn:ExtensionElements", { values });
|
|
1366
1422
|
}
|
|
1367
1423
|
var ARTIFACT_ELEMENT_TYPES = /* @__PURE__ */ new Set(["Annotation", "Group"]);
|
|
1368
1424
|
function buildSemanticModel(moddle, nodes, edges, opts) {
|
|
@@ -1399,14 +1455,24 @@ function buildSemanticModel(moddle, nodes, edges, opts) {
|
|
|
1399
1455
|
}
|
|
1400
1456
|
const messageFlowEdges = edges.filter((e) => e.data?.edgeType === "messageFlow");
|
|
1401
1457
|
const conversationLinkEdges = edges.filter((e) => e.data?.edgeType === "conversationLink");
|
|
1402
|
-
const messageFlows = messageFlowEdges.map(
|
|
1403
|
-
|
|
1458
|
+
const messageFlows = messageFlowEdges.map((e) => {
|
|
1459
|
+
const ps = typeof e.data?.payloadSchema === "string" ? e.data.payloadSchema : void 0;
|
|
1460
|
+
const ck = typeof e.data?.correlationKey === "string" ? e.data.correlationKey : void 0;
|
|
1461
|
+
const mfAttrs = {
|
|
1404
1462
|
id: e.id,
|
|
1405
1463
|
name: e.data?.label ?? "",
|
|
1406
1464
|
sourceRef: { id: e.source },
|
|
1407
1465
|
targetRef: { id: e.target }
|
|
1408
|
-
}
|
|
1409
|
-
|
|
1466
|
+
};
|
|
1467
|
+
if (ps || ck) {
|
|
1468
|
+
const cfg = moddle.create("aranza:MessageFlowConfig", {
|
|
1469
|
+
...ps ? { payloadSchema: ps } : {},
|
|
1470
|
+
...ck ? { correlationKey: ck } : {}
|
|
1471
|
+
});
|
|
1472
|
+
mfAttrs.extensionElements = moddle.create("bpmn:ExtensionElements", { values: [cfg] });
|
|
1473
|
+
}
|
|
1474
|
+
return moddle.create("bpmn:MessageFlow", mfAttrs);
|
|
1475
|
+
});
|
|
1410
1476
|
const conversationLinks = conversationLinkEdges.map(
|
|
1411
1477
|
(e) => moddle.create("bpmn:ConversationLink", {
|
|
1412
1478
|
id: e.id,
|