@aranzatech/diagrams-bpmn 0.2.11 → 0.2.13

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.
Files changed (41) hide show
  1. package/dist/{catalog-Ch3YT0-0.d.cts → catalog-BiLXVn-2.d.cts} +1 -1
  2. package/dist/{catalog-BOwJOaXV.d.ts → catalog-Di2nzGs9.d.ts} +1 -1
  3. package/dist/chunk-FBTGIYZS.js +218 -0
  4. package/dist/chunk-FBTGIYZS.js.map +1 -0
  5. package/dist/{chunk-HLCUGTEK.js → chunk-YUE5EM3W.js} +223 -35
  6. package/dist/chunk-YUE5EM3W.js.map +1 -0
  7. package/dist/elements/index.cjs +217 -0
  8. package/dist/elements/index.cjs.map +1 -1
  9. package/dist/elements/index.d.cts +15 -16
  10. package/dist/elements/index.d.ts +15 -16
  11. package/dist/elements/index.js +1 -1
  12. package/dist/guards-DPHXfpY8.d.cts +16 -0
  13. package/dist/guards-qgSeZEU4.d.ts +16 -0
  14. package/dist/index.cjs +221 -33
  15. package/dist/index.cjs.map +1 -1
  16. package/dist/index.d.cts +4 -4
  17. package/dist/index.d.ts +4 -4
  18. package/dist/index.js +2 -2
  19. package/dist/layout/index.cjs +87 -0
  20. package/dist/layout/index.cjs.map +1 -1
  21. package/dist/layout/index.d.cts +22 -4
  22. package/dist/layout/index.d.ts +22 -4
  23. package/dist/layout/index.js +90 -2
  24. package/dist/layout/index.js.map +1 -1
  25. package/dist/modeling/index.d.cts +3 -3
  26. package/dist/modeling/index.d.ts +3 -3
  27. package/dist/{types-BTuiBv7p.d.cts → types-Dfrt0wVs.d.cts} +45 -1
  28. package/dist/{types-BTuiBv7p.d.ts → types-Dfrt0wVs.d.ts} +45 -1
  29. package/dist/{types-DSDMCAre.d.ts → types-rEfHsPr5.d.ts} +1 -1
  30. package/dist/{types-C7tONwP5.d.cts → types-s2_VvPGf.d.cts} +1 -1
  31. package/dist/validation/index.d.cts +2 -2
  32. package/dist/validation/index.d.ts +2 -2
  33. package/dist/xml/index.cjs +221 -33
  34. package/dist/xml/index.cjs.map +1 -1
  35. package/dist/xml/index.d.cts +3 -3
  36. package/dist/xml/index.d.ts +3 -3
  37. package/dist/xml/index.js +1 -1
  38. package/package.json +2 -2
  39. package/dist/chunk-HLCUGTEK.js.map +0 -1
  40. package/dist/chunk-OZKTOILD.js +0 -3
  41. package/dist/chunk-OZKTOILD.js.map +0 -1
@@ -26,7 +26,29 @@ var ARANZA_DESCRIPTOR = {
26
26
  { name: "formKey", isAttr: true, type: "String" },
27
27
  // UserTask: Flowable task assignment — comma-separated ids
28
28
  { name: "candidateUsers", isAttr: true, type: "String" },
29
- { name: "candidateGroups", isAttr: true, type: "String" }
29
+ { name: "candidateGroups", isAttr: true, type: "String" },
30
+ // UserTask: scheduling + skip expression
31
+ { name: "dueDate", isAttr: true, type: "String" },
32
+ { name: "skipExpression", isAttr: true, type: "String" },
33
+ { name: "businessCalendarName", isAttr: true, type: "String" }
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" }
30
52
  ]
31
53
  }
32
54
  ],
@@ -907,7 +929,20 @@ function extractAranzaExtensions(el) {
907
929
  }
908
930
  const ext = el.extensionElements;
909
931
  if (!ext) return result;
910
- const taskConfig = asElements(ext.values).find((v) => v.$type === "aranza:TaskConfig");
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");
911
946
  if (!taskConfig) return result;
912
947
  const priority = asString(taskConfig.priority);
913
948
  if (priority === "critical" || priority === "high" || priority === "medium" || priority === "low") {
@@ -933,6 +968,12 @@ function extractAranzaExtensions(el) {
933
968
  if (candidateUsers) result.candidateUsers = candidateUsers;
934
969
  const candidateGroups = asString(taskConfig.candidateGroups);
935
970
  if (candidateGroups) result.candidateGroups = candidateGroups;
971
+ const dueDate = asString(taskConfig.dueDate);
972
+ if (dueDate) result.dueDate = dueDate;
973
+ const skipExpression = asString(taskConfig.skipExpression);
974
+ if (skipExpression) result.skipExpression = skipExpression;
975
+ const businessCalendarName = asString(taskConfig.businessCalendarName);
976
+ if (businessCalendarName) result.businessCalendarName = businessCalendarName;
936
977
  return result;
937
978
  }
938
979
  function extractCompletionCondition(el) {
@@ -941,6 +982,25 @@ function extractCompletionCondition(el) {
941
982
  if (typeof cc === "string") return cc.trim() || void 0;
942
983
  return asString(cc.body);
943
984
  }
985
+ function extractLoopCharacteristics(el) {
986
+ const lc = el.loopCharacteristics;
987
+ if (!lc) return {};
988
+ if (lc.$type === "bpmn:StandardLoopCharacteristics") {
989
+ const loopCondition = asString(lc.loopCondition?.body);
990
+ return { loopType: "loop", ...loopCondition ? { loopCondition } : {} };
991
+ }
992
+ if (lc.$type === "bpmn:MultiInstanceLoopCharacteristics") {
993
+ const loopType = lc.isSequential === true ? "sequentialMultiple" : "parallelMultiple";
994
+ const loopCardinality = asString(lc.loopCardinality?.body);
995
+ const loopCompletionCondition = asString(lc.completionCondition?.body);
996
+ return {
997
+ loopType,
998
+ ...loopCardinality ? { loopCardinality } : {},
999
+ ...loopCompletionCondition ? { loopCompletionCondition } : {}
1000
+ };
1001
+ }
1002
+ return {};
1003
+ }
944
1004
  function walkFlowElements(elements, parentId, ctx, nodes, edges) {
945
1005
  for (const el of elements) {
946
1006
  const { $type, id } = el;
@@ -958,7 +1018,7 @@ function walkFlowElements(elements, parentId, ctx, nodes, edges) {
958
1018
  }
959
1019
  buildNode(el, elementType, parentId, ctx, nodes);
960
1020
  if ($type === "bpmn:SubProcess" || $type === "bpmn:Transaction" || $type === "bpmn:AdHocSubProcess") {
961
- const children = asElements(el.flowElements);
1021
+ const children = [...asElements(el.flowElements), ...asElements(el.artifacts)];
962
1022
  const laneMembership = extractLaneMembership(el);
963
1023
  walkFlowElements(children, id, { ...ctx, laneMembership }, nodes, edges);
964
1024
  }
@@ -971,7 +1031,7 @@ function buildNode(el, elementType, parentId, ctx, nodes) {
971
1031
  const x = shape?.x ?? ctx.autoX.value;
972
1032
  const y = shape?.y ?? 100;
973
1033
  if (!shape) ctx.autoX.value += (meta?.defaultWidth ?? 120) + 20;
974
- const label = asString(el.name);
1034
+ const label = elementType === "Annotation" ? asString(el.text) ?? asString(el.name) : asString(el.name);
975
1035
  const documentation = extractDocumentation(el);
976
1036
  const trigger = extractTrigger(el);
977
1037
  const eventDefinition = extractEventDefinition(el);
@@ -982,6 +1042,8 @@ function buildNode(el, elementType, parentId, ctx, nodes) {
982
1042
  const scriptFormat = elementType === "ScriptTask" ? asString(el.scriptFormat) : void 0;
983
1043
  const script = elementType === "ScriptTask" ? asString(el.script) : void 0;
984
1044
  const completionCondition = elementType === "AdHocSubProcess" ? extractCompletionCondition(el) : void 0;
1045
+ const loopChars = extractLoopCharacteristics(el);
1046
+ const dataObjectRef = elementType === "DataObjectReference" ? asString(el.dataObjectRef?.id) : void 0;
985
1047
  const data = {
986
1048
  elementType,
987
1049
  ...label ? { label } : {},
@@ -1002,6 +1064,8 @@ function buildNode(el, elementType, parentId, ctx, nodes) {
1002
1064
  ...scriptFormat ? { scriptFormat } : {},
1003
1065
  ...script ? { script } : {},
1004
1066
  ...completionCondition ? { completionCondition } : {},
1067
+ ...dataObjectRef ? { dataObjectRef } : {},
1068
+ ...loopChars,
1005
1069
  ...aranzaExt
1006
1070
  };
1007
1071
  if (elementType === "SubProcess" || elementType === "Transaction" || elementType === "EventSubProcess" || elementType === "AdHocSubProcess") {
@@ -1034,11 +1098,28 @@ function buildEdge(el, edgeType, ctx, edges) {
1034
1098
  const label = asString(el.name);
1035
1099
  const documentation = extractDocumentation(el);
1036
1100
  const condExpr = el.conditionExpression;
1101
+ const rawDir = asString(el.associationDirection);
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
+ }
1037
1115
  const data = {
1038
1116
  edgeType,
1039
1117
  ...label ? { label } : {},
1040
1118
  ...documentation ? { documentation } : {},
1041
- ...condExpr?.body ? { conditionExpression: condExpr.body } : {}
1119
+ ...condExpr?.body ? { conditionExpression: condExpr.body } : {},
1120
+ ...associationDirection ? { associationDirection } : {},
1121
+ ...payloadSchema ? { payloadSchema } : {},
1122
+ ...correlationKey ? { correlationKey } : {}
1042
1123
  };
1043
1124
  const waypoints = ctx.waypoints.get(id);
1044
1125
  if (waypoints?.length) data.routingPoints = waypoints;
@@ -1063,7 +1144,7 @@ function handleCollaboration(collaboration, ctx, nodes, edges) {
1063
1144
  if (processRef) {
1064
1145
  const laneMembership = extractLaneMembership(processRef);
1065
1146
  walkFlowElements(
1066
- asElements(processRef.flowElements),
1147
+ [...asElements(processRef.flowElements), ...asElements(processRef.artifacts)],
1067
1148
  id,
1068
1149
  { ...ctx, laneMembership },
1069
1150
  nodes,
@@ -1095,7 +1176,7 @@ function addLaneNodes(laneSet, poolId, ctx, nodes) {
1095
1176
  data: { elementType: "Lane", ...label ? { label } : {} },
1096
1177
  width: shape?.width ?? 570,
1097
1178
  height: shape?.height ?? 120,
1098
- parentId: poolId
1179
+ ...poolId ? { parentId: poolId } : {}
1099
1180
  });
1100
1181
  const child = lane.childLaneSet;
1101
1182
  if (child) addLaneNodes(child, poolId, ctx, nodes);
@@ -1129,9 +1210,9 @@ async function parseBpmnXml(xml) {
1129
1210
  } else if (rootEl.$type === "bpmn:Process") {
1130
1211
  const laneMembership = extractLaneMembership(rootEl);
1131
1212
  const laneSet = rootEl.laneSet;
1132
- if (laneSet) addLaneNodes(laneSet, "", ctx, nodes);
1213
+ if (laneSet) addLaneNodes(laneSet, void 0, ctx, nodes);
1133
1214
  walkFlowElements(
1134
- asElements(rootEl.flowElements),
1215
+ [...asElements(rootEl.flowElements), ...asElements(rootEl.artifacts)],
1135
1216
  void 0,
1136
1217
  { ...ctx, laneMembership },
1137
1218
  nodes,
@@ -1304,7 +1385,10 @@ function buildAranzaExtensionElements(moddle, node) {
1304
1385
  const formKey = typeof node.data.formKey === "string" ? node.data.formKey : void 0;
1305
1386
  const candidateUsers = typeof node.data.candidateUsers === "string" ? node.data.candidateUsers : void 0;
1306
1387
  const candidateGroups = typeof node.data.candidateGroups === "string" ? node.data.candidateGroups : void 0;
1307
- if (!priority && !owner && !sla && !connector && !action && !flowableType && !flowableDelegateExpression && !decisionRef && !formKey && !candidateUsers && !candidateGroups) {
1388
+ const dueDate = typeof node.data.dueDate === "string" ? node.data.dueDate : void 0;
1389
+ const skipExpression = typeof node.data.skipExpression === "string" ? node.data.skipExpression : void 0;
1390
+ const businessCalendarName = typeof node.data.businessCalendarName === "string" ? node.data.businessCalendarName : void 0;
1391
+ if (!priority && !owner && !sla && !connector && !action && !flowableType && !flowableDelegateExpression && !decisionRef && !formKey && !candidateUsers && !candidateGroups && !dueDate && !skipExpression && !businessCalendarName) {
1308
1392
  return null;
1309
1393
  }
1310
1394
  const configAttrs = {};
@@ -1319,9 +1403,24 @@ function buildAranzaExtensionElements(moddle, node) {
1319
1403
  if (formKey) configAttrs.formKey = formKey;
1320
1404
  if (candidateUsers) configAttrs.candidateUsers = candidateUsers;
1321
1405
  if (candidateGroups) configAttrs.candidateGroups = candidateGroups;
1322
- const taskConfig = moddle.create("aranza:TaskConfig", configAttrs);
1323
- return moddle.create("bpmn:ExtensionElements", { values: [taskConfig] });
1406
+ if (dueDate) configAttrs.dueDate = dueDate;
1407
+ if (skipExpression) configAttrs.skipExpression = skipExpression;
1408
+ if (businessCalendarName) configAttrs.businessCalendarName = businessCalendarName;
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 });
1324
1422
  }
1423
+ var ARTIFACT_ELEMENT_TYPES = /* @__PURE__ */ new Set(["Annotation", "Group"]);
1325
1424
  function buildSemanticModel(moddle, nodes, edges, opts) {
1326
1425
  const defId = opts.id ?? "Definitions_1";
1327
1426
  const defName = opts.name;
@@ -1356,14 +1455,24 @@ function buildSemanticModel(moddle, nodes, edges, opts) {
1356
1455
  }
1357
1456
  const messageFlowEdges = edges.filter((e) => e.data?.edgeType === "messageFlow");
1358
1457
  const conversationLinkEdges = edges.filter((e) => e.data?.edgeType === "conversationLink");
1359
- const messageFlows = messageFlowEdges.map(
1360
- (e) => moddle.create("bpmn:MessageFlow", {
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 = {
1361
1462
  id: e.id,
1362
1463
  name: e.data?.label ?? "",
1363
1464
  sourceRef: { id: e.source },
1364
1465
  targetRef: { id: e.target }
1365
- })
1366
- );
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
+ });
1367
1476
  const conversationLinks = conversationLinkEdges.map(
1368
1477
  (e) => moddle.create("bpmn:ConversationLink", {
1369
1478
  id: e.id,
@@ -1417,10 +1526,31 @@ function buildProcess(moddle, allNodes, allEdges, poolId, laneNodes, processId,
1417
1526
  };
1418
1527
  const myNodes = (poolId ? allNodes.filter((n) => belongsToPool(n)) : allNodes.filter((n) => n.data.elementType !== "Pool" && n.data.elementType !== "Lane")).filter((n) => !isInsideSubProcess(n));
1419
1528
  const myLanes = laneNodes.filter((l) => poolId ? l.parentId === poolId : true);
1529
+ const presentDataObjectIds = new Set(
1530
+ myNodes.filter((n) => n.data.elementType === "DataObject").map((n) => n.id)
1531
+ );
1420
1532
  const flowElements = [];
1533
+ const artifacts = [];
1534
+ for (const node of myNodes) {
1535
+ if (node.data.elementType === "DataObjectReference") {
1536
+ const explicitRef = typeof node.data.dataObjectRef === "string" ? node.data.dataObjectRef : null;
1537
+ if (!explicitRef || !presentDataObjectIds.has(explicitRef)) {
1538
+ const syntheticId = `DataObject_${node.id}`;
1539
+ if (!presentDataObjectIds.has(syntheticId)) {
1540
+ flowElements.push(moddle.create("bpmn:DataObject", { id: syntheticId }));
1541
+ presentDataObjectIds.add(syntheticId);
1542
+ }
1543
+ }
1544
+ }
1545
+ }
1421
1546
  for (const node of myNodes) {
1422
1547
  const el = buildFlowElement(moddle, node, allNodes, allEdges);
1423
- if (el) flowElements.push(el);
1548
+ if (!el) continue;
1549
+ if (ARTIFACT_ELEMENT_TYPES.has(node.data.elementType)) {
1550
+ artifacts.push(el);
1551
+ } else {
1552
+ flowElements.push(el);
1553
+ }
1424
1554
  }
1425
1555
  const myNodeIds = new Set(myNodes.map((n) => n.id));
1426
1556
  const myEdges = allEdges.filter(
@@ -1428,7 +1558,12 @@ function buildProcess(moddle, allNodes, allEdges, poolId, laneNodes, processId,
1428
1558
  );
1429
1559
  for (const edge of myEdges) {
1430
1560
  const edgeMeta = buildEdgeElement(moddle, edge);
1431
- if (edgeMeta) flowElements.push(edgeMeta);
1561
+ if (!edgeMeta) continue;
1562
+ if (edge.data?.edgeType === "association") {
1563
+ artifacts.push(edgeMeta);
1564
+ } else {
1565
+ flowElements.push(edgeMeta);
1566
+ }
1432
1567
  }
1433
1568
  const elementById = new Map(
1434
1569
  flowElements.filter((element) => typeof element.id === "string").map((element) => [element.id, element])
@@ -1444,7 +1579,8 @@ function buildProcess(moddle, allNodes, allEdges, poolId, laneNodes, processId,
1444
1579
  const process = moddle.create("bpmn:Process", {
1445
1580
  id: processId,
1446
1581
  isExecutable: opts.process?.executable ?? true,
1447
- flowElements
1582
+ flowElements,
1583
+ ...artifacts.length > 0 ? { artifacts } : {}
1448
1584
  });
1449
1585
  if (opts.process?.documentation) {
1450
1586
  process.documentation = [
@@ -1476,6 +1612,10 @@ function buildFlowElement(moddle, node, allNodes, allEdges) {
1476
1612
  id: node.id,
1477
1613
  name: label ?? ""
1478
1614
  };
1615
+ if (elementType === "Annotation") {
1616
+ delete attrs.name;
1617
+ attrs.text = label ?? "";
1618
+ }
1479
1619
  if (node.data.documentation) {
1480
1620
  attrs.documentation = [
1481
1621
  moddle.create("bpmn:Documentation", { text: node.data.documentation })
@@ -1494,22 +1634,16 @@ function buildFlowElement(moddle, node, allNodes, allEdges) {
1494
1634
  if (elementType === "CallActivity" && node.data.calledElement) {
1495
1635
  attrs.calledElement = node.data.calledElement;
1496
1636
  }
1637
+ if (elementType === "DataObjectReference") {
1638
+ const refId = typeof node.data.dataObjectRef === "string" ? node.data.dataObjectRef : `DataObject_${node.id}`;
1639
+ attrs.dataObjectRef = { id: refId };
1640
+ }
1497
1641
  if (elementType === "ScriptTask") {
1498
1642
  const scriptFormat = typeof node.data.scriptFormat === "string" ? node.data.scriptFormat : void 0;
1499
1643
  const script = typeof node.data.script === "string" ? node.data.script : void 0;
1500
1644
  if (scriptFormat) attrs.scriptFormat = scriptFormat;
1501
1645
  if (script) attrs.script = script;
1502
1646
  }
1503
- if (elementType === "UserTask") {
1504
- const flowableAttrs = {};
1505
- const fk = typeof node.data.formKey === "string" ? node.data.formKey : void 0;
1506
- const cu = typeof node.data.candidateUsers === "string" ? node.data.candidateUsers : void 0;
1507
- const cg = typeof node.data.candidateGroups === "string" ? node.data.candidateGroups : void 0;
1508
- if (fk) flowableAttrs["flowable:formKey"] = fk;
1509
- if (cu) flowableAttrs["flowable:candidateUsers"] = cu;
1510
- if (cg) flowableAttrs["flowable:candidateGroups"] = cg;
1511
- if (Object.keys(flowableAttrs).length > 0) attrs.$attrs = flowableAttrs;
1512
- }
1513
1647
  if (elementType === "ServiceTask") {
1514
1648
  const flowableAttrs = {};
1515
1649
  const flowableType = typeof node.data.flowableType === "string" ? node.data.flowableType : void 0;
@@ -1526,7 +1660,9 @@ function buildFlowElement(moddle, node, allNodes, allEdges) {
1526
1660
  if (aranzaConfig) attrs.extensionElements = aranzaConfig;
1527
1661
  const isSubProcess = elementType === "SubProcess" || elementType === "Transaction" || elementType === "EventSubProcess" || elementType === "AdHocSubProcess";
1528
1662
  if (isSubProcess) {
1529
- attrs.flowElements = buildNestedFlowElements(moddle, node, allNodes, allEdges);
1663
+ const nested = buildNestedFlowElements(moddle, node, allNodes, allEdges);
1664
+ attrs.flowElements = nested.flowElements;
1665
+ if (nested.artifacts.length > 0) attrs.artifacts = nested.artifacts;
1530
1666
  if (elementType === "EventSubProcess" || node.data.subProcessVariant === "event") {
1531
1667
  attrs.triggeredByEvent = true;
1532
1668
  }
@@ -1536,6 +1672,29 @@ function buildFlowElement(moddle, node, allNodes, allEdges) {
1536
1672
  });
1537
1673
  }
1538
1674
  }
1675
+ const loopType = typeof node.data.loopType === "string" ? node.data.loopType : "none";
1676
+ if (loopType && loopType !== "none") {
1677
+ if (loopType === "loop") {
1678
+ const lcAttrs = { id: uid("LoopChar", node.id) };
1679
+ const loopCondition = typeof node.data.loopCondition === "string" ? node.data.loopCondition : void 0;
1680
+ if (loopCondition) {
1681
+ lcAttrs.loopCondition = moddle.create("bpmn:FormalExpression", { body: loopCondition });
1682
+ }
1683
+ attrs.loopCharacteristics = moddle.create("bpmn:StandardLoopCharacteristics", lcAttrs);
1684
+ } else {
1685
+ const isSequential = loopType === "sequentialMultiple";
1686
+ const lcAttrs = { id: uid("LoopChar", node.id), isSequential };
1687
+ const loopCardinality = typeof node.data.loopCardinality === "string" ? node.data.loopCardinality : void 0;
1688
+ const loopCompletionCondition = typeof node.data.loopCompletionCondition === "string" ? node.data.loopCompletionCondition : void 0;
1689
+ if (loopCardinality) {
1690
+ lcAttrs.loopCardinality = moddle.create("bpmn:FormalExpression", { body: loopCardinality });
1691
+ }
1692
+ if (loopCompletionCondition) {
1693
+ lcAttrs.completionCondition = moddle.create("bpmn:FormalExpression", { body: loopCompletionCondition });
1694
+ }
1695
+ attrs.loopCharacteristics = moddle.create("bpmn:MultiInstanceLoopCharacteristics", lcAttrs);
1696
+ }
1697
+ }
1539
1698
  const element = moddle.create(moddleType, attrs);
1540
1699
  return element;
1541
1700
  }
@@ -1543,16 +1702,42 @@ function buildNestedFlowElements(moddle, parent, allNodes, allEdges) {
1543
1702
  const childNodes = allNodes.filter((node) => node.parentId === parent.id);
1544
1703
  const childNodeIds = new Set(childNodes.map((node) => node.id));
1545
1704
  const flowElements = [];
1705
+ const artifacts = [];
1706
+ const presentDataObjectIds = new Set(
1707
+ childNodes.filter((n) => n.data.elementType === "DataObject").map((n) => n.id)
1708
+ );
1709
+ for (const node of childNodes) {
1710
+ if (node.data.elementType === "DataObjectReference") {
1711
+ const explicitRef = typeof node.data.dataObjectRef === "string" ? node.data.dataObjectRef : null;
1712
+ if (!explicitRef || !presentDataObjectIds.has(explicitRef)) {
1713
+ const syntheticId = `DataObject_${node.id}`;
1714
+ if (!presentDataObjectIds.has(syntheticId)) {
1715
+ flowElements.push(moddle.create("bpmn:DataObject", { id: syntheticId }));
1716
+ presentDataObjectIds.add(syntheticId);
1717
+ }
1718
+ }
1719
+ }
1720
+ }
1546
1721
  for (const child of childNodes) {
1547
1722
  const element = buildFlowElement(moddle, child, allNodes, allEdges);
1548
- if (element) flowElements.push(element);
1723
+ if (!element) continue;
1724
+ if (ARTIFACT_ELEMENT_TYPES.has(child.data.elementType)) {
1725
+ artifacts.push(element);
1726
+ } else {
1727
+ flowElements.push(element);
1728
+ }
1549
1729
  }
1550
1730
  for (const edge of allEdges) {
1551
1731
  if (!childNodeIds.has(edge.source) || !childNodeIds.has(edge.target)) continue;
1552
1732
  const element = buildEdgeElement(moddle, edge);
1553
- if (element) flowElements.push(element);
1733
+ if (!element) continue;
1734
+ if (edge.data?.edgeType === "association") {
1735
+ artifacts.push(element);
1736
+ } else {
1737
+ flowElements.push(element);
1738
+ }
1554
1739
  }
1555
- return flowElements;
1740
+ return { flowElements, artifacts };
1556
1741
  }
1557
1742
  function buildEdgeElement(moddle, edge) {
1558
1743
  if (!edge.data) return null;
@@ -1574,6 +1759,9 @@ function buildEdgeElement(moddle, edge) {
1574
1759
  body: edge.data.conditionExpression
1575
1760
  });
1576
1761
  }
1762
+ if (edge.data.edgeType === "association" && edge.data.associationDirection && edge.data.associationDirection !== "none") {
1763
+ attrs.associationDirection = edge.data.associationDirection === "both" ? "Both" : "One";
1764
+ }
1577
1765
  return moddle.create(moddleType, attrs);
1578
1766
  }
1579
1767
  function buildBpmnDI(moddle, definitions, nodes, edges) {