@aranzatech/diagrams-bpmn 0.1.3 → 0.2.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/CHANGELOG.md +20 -0
- package/README.md +121 -0
- package/dist/{chunk-4AX573IV.js → chunk-5GRCJ5X6.js} +2 -2
- package/dist/{chunk-4AX573IV.js.map → chunk-5GRCJ5X6.js.map} +1 -1
- package/dist/chunk-G5S4ASP3.js +277 -0
- package/dist/chunk-G5S4ASP3.js.map +1 -0
- package/dist/{chunk-W3ROOC6E.js → chunk-MF2WE3OM.js} +145 -36
- package/dist/chunk-MF2WE3OM.js.map +1 -0
- package/dist/chunk-OZKTOILD.js +3 -0
- package/dist/chunk-OZKTOILD.js.map +1 -0
- package/dist/{chunk-NXMUX67A.js → chunk-S3GGEEA5.js} +31 -8
- package/dist/chunk-S3GGEEA5.js.map +1 -0
- package/dist/elements/index.d.cts +2 -2
- package/dist/elements/index.d.ts +2 -2
- package/dist/elements/index.js +2 -1
- package/dist/index.cjs +454 -66
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +7 -62
- package/dist/index.d.ts +7 -62
- package/dist/index.js +6 -40
- package/dist/index.js.map +1 -1
- package/dist/modeling/index.cjs +894 -0
- package/dist/modeling/index.cjs.map +1 -0
- package/dist/modeling/index.d.cts +88 -0
- package/dist/modeling/index.d.ts +88 -0
- package/dist/modeling/index.js +5 -0
- package/dist/modeling/index.js.map +1 -0
- package/dist/nodes/index.cjs +29 -6
- package/dist/nodes/index.cjs.map +1 -1
- package/dist/nodes/index.js +1 -1
- package/dist/{types-C78d_Kdh.d.cts → types-BKA0GZz5.d.cts} +6 -18
- package/dist/{types-C78d_Kdh.d.ts → types-BKA0GZz5.d.ts} +6 -18
- package/dist/types-CCkHqtC_.d.cts +20 -0
- package/dist/types-hj621ZRJ.d.ts +20 -0
- package/dist/xml/index.cjs +143 -34
- package/dist/xml/index.cjs.map +1 -1
- package/dist/xml/index.d.cts +4 -19
- package/dist/xml/index.d.ts +4 -19
- package/dist/xml/index.js +1 -1
- package/package.json +10 -3
- package/dist/chunk-NXMUX67A.js.map +0 -1
- package/dist/chunk-W3ROOC6E.js.map +0 -1
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
## Unreleased
|
|
4
|
+
|
|
5
|
+
- Expanded BPMN modeling helpers on top of the new `diagrams-core` primitives.
|
|
6
|
+
- Added BPMN node factory, edge-type inference and BPMN document serialization helpers.
|
|
7
|
+
- Added replace, resize, reparent, select, copy/paste and batch-command helpers.
|
|
8
|
+
- Improved BPMN connection rules to allow subprocesses as flow nodes while blocking pools/lanes/artifacts without handles.
|
|
9
|
+
- Added sequence-flow cardinality checks based on the BPMN element catalog.
|
|
10
|
+
- Boundary attachment now updates both `parentId` and BPMN `attachedToRef` data.
|
|
11
|
+
|
|
12
|
+
## 0.2.0
|
|
13
|
+
|
|
14
|
+
- Added BPMN modeling helpers built on `@aranzatech/diagrams-core` commands and rules.
|
|
15
|
+
- Added public `@aranzatech/diagrams-bpmn/modeling` subpath.
|
|
16
|
+
- Improved XML roundtrip for default sequence flows, boundary event attachment,
|
|
17
|
+
non-interrupting boundary events, documentation and parent-relative coordinates.
|
|
18
|
+
- Removed Flowable adapter exports from the root public API; Flowable integration
|
|
19
|
+
is planned as a separate wrapper concern.
|
|
20
|
+
- Added README coverage matrix and stable-scope notes.
|
package/README.md
ADDED
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
# @aranzatech/diagrams-bpmn
|
|
2
|
+
|
|
3
|
+
BPMN 2.0 building blocks for the Aranza diagram ecosystem. This package owns
|
|
4
|
+
BPMN-specific visual components, element metadata, BPMN modeling helpers, XML
|
|
5
|
+
import/export and preview token simulation.
|
|
6
|
+
|
|
7
|
+
It is intentionally not responsible for execution-engine communication. Flowable
|
|
8
|
+
integration belongs in a future wrapper package or in the consuming app backend.
|
|
9
|
+
|
|
10
|
+
## Public Subpaths
|
|
11
|
+
|
|
12
|
+
```ts
|
|
13
|
+
import { BPMN_NODE_TYPES } from "@aranzatech/diagrams-bpmn/nodes";
|
|
14
|
+
import { BPMN_EDGE_TYPES } from "@aranzatech/diagrams-bpmn/edges";
|
|
15
|
+
import { BPMN_ELEMENT_CATALOG } from "@aranzatech/diagrams-bpmn/elements";
|
|
16
|
+
import { parseBpmnXml, serializeBpmnXml } from "@aranzatech/diagrams-bpmn/xml";
|
|
17
|
+
import {
|
|
18
|
+
createBpmnNodeCommand,
|
|
19
|
+
replaceBpmnNodeCommand,
|
|
20
|
+
serializeBpmnDiagram,
|
|
21
|
+
} from "@aranzatech/diagrams-bpmn/modeling";
|
|
22
|
+
import { createSimulation } from "@aranzatech/diagrams-bpmn/simulation";
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
## Scope
|
|
26
|
+
|
|
27
|
+
- BPMN visual node and edge renderers for ReactFlow.
|
|
28
|
+
- BPMN element catalog and guards.
|
|
29
|
+
- BPMN XML import/export through `bpmn-moddle`.
|
|
30
|
+
- BPMN modeling commands and interaction rules on top of `diagrams-core`.
|
|
31
|
+
- Client-side preview token simulation.
|
|
32
|
+
|
|
33
|
+
## Out Of Scope
|
|
34
|
+
|
|
35
|
+
- Flowable REST/backend communication.
|
|
36
|
+
- BPMN business validation rules. Those belong in `@aranzatech/flowslint`.
|
|
37
|
+
- Full execution semantics.
|
|
38
|
+
|
|
39
|
+
## Coverage Matrix
|
|
40
|
+
|
|
41
|
+
| Area | Status | Notes |
|
|
42
|
+
|---|---:|---|
|
|
43
|
+
| Events | Partial | Start, end, intermediate catch/throw, boundary; common triggers rendered/imported. |
|
|
44
|
+
| Tasks | Partial | Task variants and call activity rendered; advanced task semantics still need richer XML mapping. |
|
|
45
|
+
| Gateways | Good | Exclusive, inclusive, parallel, event-based and complex rendered. |
|
|
46
|
+
| Containers | Partial | Pool, lane, subprocess, transaction, event subprocess and ad-hoc subprocess rendered; lane resizing/modeling still needs depth. |
|
|
47
|
+
| Artifacts | Partial | Text annotation and group rendered; association semantics are basic. |
|
|
48
|
+
| Data | Partial | Data object/input/output/store and refs rendered; full item definitions/data states pending. |
|
|
49
|
+
| Conversation | Partial | Conversation nodes and links rendered; full conversation model pending. |
|
|
50
|
+
| Choreography | Partial | Choreography nodes rendered; participant semantics are lightweight. |
|
|
51
|
+
| XML import/export | Partial | Basic BPMN + DI, default flows, boundary attachment, docs and relative child coordinates; full lossless roundtrip pending. |
|
|
52
|
+
| Modeling | Growing | Commands and rules for create/connect/attach/delete/replace/resize/reparent/copy/paste; palette/context-pad/auto-place can build on this. |
|
|
53
|
+
| Simulation | Preview | Useful design-time token simulation, not an execution engine. |
|
|
54
|
+
|
|
55
|
+
## Modeling Example
|
|
56
|
+
|
|
57
|
+
```ts
|
|
58
|
+
import { createCommandStackState } from "@aranzatech/diagrams-core/commands";
|
|
59
|
+
import {
|
|
60
|
+
createBpmnNodeCommand,
|
|
61
|
+
connectBpmnCommand,
|
|
62
|
+
replaceBpmnNodeCommand,
|
|
63
|
+
runBpmnCommands,
|
|
64
|
+
runBpmnCommand,
|
|
65
|
+
} from "@aranzatech/diagrams-bpmn/modeling";
|
|
66
|
+
|
|
67
|
+
let stack = createCommandStackState({ nodes: [], edges: [] });
|
|
68
|
+
|
|
69
|
+
stack = runBpmnCommand(
|
|
70
|
+
stack,
|
|
71
|
+
createBpmnNodeCommand({
|
|
72
|
+
id: "task_1",
|
|
73
|
+
elementType: "Task",
|
|
74
|
+
position: { x: 100, y: 100 },
|
|
75
|
+
label: "Review request",
|
|
76
|
+
}),
|
|
77
|
+
);
|
|
78
|
+
|
|
79
|
+
stack = runBpmnCommand(
|
|
80
|
+
stack,
|
|
81
|
+
connectBpmnCommand({
|
|
82
|
+
source: "start_1",
|
|
83
|
+
target: "task_1",
|
|
84
|
+
}),
|
|
85
|
+
);
|
|
86
|
+
|
|
87
|
+
stack = runBpmnCommands(
|
|
88
|
+
stack,
|
|
89
|
+
[
|
|
90
|
+
replaceBpmnNodeCommand({
|
|
91
|
+
id: "task_1",
|
|
92
|
+
elementType: "UserTask",
|
|
93
|
+
label: "Human review",
|
|
94
|
+
}),
|
|
95
|
+
],
|
|
96
|
+
{ id: "review-as-user-task" },
|
|
97
|
+
);
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
## BPMN Diagram Document Example
|
|
101
|
+
|
|
102
|
+
```ts
|
|
103
|
+
import {
|
|
104
|
+
deserializeBpmnDiagram,
|
|
105
|
+
serializeBpmnDiagram,
|
|
106
|
+
} from "@aranzatech/diagrams-bpmn/modeling";
|
|
107
|
+
|
|
108
|
+
const json = serializeBpmnDiagram(stack.current, {
|
|
109
|
+
metadata: { source: "designer" },
|
|
110
|
+
});
|
|
111
|
+
|
|
112
|
+
const restored = deserializeBpmnDiagram(json);
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
## Road To Stable
|
|
116
|
+
|
|
117
|
+
- Expand XML to preserve more BPMN semantics losslessly.
|
|
118
|
+
- Add real-world XML fixtures from bpmn.io/Camunda/Flowable modelers.
|
|
119
|
+
- Add palette/context-pad and auto-place commands on top of the current modeling API.
|
|
120
|
+
- Add robust lane/pool resize and reparent behavior.
|
|
121
|
+
- Move engine-specific extensions to a dedicated package.
|
|
@@ -82,5 +82,5 @@ function supportsMarkers(type) {
|
|
|
82
82
|
}
|
|
83
83
|
|
|
84
84
|
export { acceptsBoundaryEvents, getHandlePolicy, getOrientation, isChoreographyType, isContainerType, isConversationType, isDataType, isEventType, isGatewayType, isTaskType, supportsCollapse, supportsMarkers };
|
|
85
|
-
//# sourceMappingURL=chunk-
|
|
86
|
-
//# sourceMappingURL=chunk-
|
|
85
|
+
//# sourceMappingURL=chunk-5GRCJ5X6.js.map
|
|
86
|
+
//# sourceMappingURL=chunk-5GRCJ5X6.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/elements/guards.ts"],"names":[],"mappings":";;;AAGA,IAAM,UAAA,uBAAiB,GAAA,CAAqB;AAAA,EAC1C,MAAA;AAAA,EAAQ,UAAA;AAAA,EAAY,aAAA;AAAA,EAAe,YAAA;AAAA,EACnC,YAAA;AAAA,EAAc,kBAAA;AAAA,EAAoB,aAAA;AAAA,EAAe,UAAA;AAAA,EAAY;AAC/D,CAAC,CAAA;AAED,IAAM,aAAA,uBAAoB,GAAA,CAAqB;AAAA,EAC7C,kBAAA;AAAA,EAAoB,kBAAA;AAAA,EAAoB,iBAAA;AAAA,EACxC,mBAAA;AAAA,EAAqB;AACvB,CAAC,CAAA;AAED,IAAM,WAAA,uBAAkB,GAAA,CAAqB;AAAA,EAC3C,YAAA;AAAA,EAAc,UAAA;AAAA,EAAY,wBAAA;AAAA,EAC1B,wBAAA;AAAA,EAA0B;AAC5B,CAAC,CAAA;AAED,IAAM,UAAA,uBAAiB,GAAA,CAAqB;AAAA,EAC1C,YAAA;AAAA,EAAc,qBAAA;AAAA,EAAuB,WAAA;AAAA,EAAa,YAAA;AAAA,EAClD,WAAA;AAAA,EAAa;AACf,CAAC,CAAA;AAED,IAAM,kBAAA,uBAAyB,GAAA,CAAqB;AAAA,EAClD,cAAA;AAAA,EAAgB,iBAAA;AAAA,EAAmB;AACrC,CAAC,CAAA;AAED,IAAM,kBAAA,uBAAyB,GAAA,CAAqB;AAAA,EAClD,kBAAA;AAAA,EAAoB,iBAAA;AAAA,EAAmB;AACzC,CAAC,CAAA;AAEM,SAAS,WAAW,IAAA,EAAgC;AACzD,EAAA,OAAO,UAAA,CAAW,IAAI,IAAI,CAAA;AAC5B;AAEO,SAAS,cAAc,IAAA,EAAgC;AAC5D,EAAA,OAAO,aAAA,CAAc,IAAI,IAAI,CAAA;AAC/B;AAEO,SAAS,YAAY,IAAA,EAAgC;AAC1D,EAAA,OAAO,WAAA,CAAY,IAAI,IAAI,CAAA;AAC7B;AAEO,SAAS,WAAW,IAAA,EAAgC;AACzD,EAAA,OAAO,UAAA,CAAW,IAAI,IAAI,CAAA;AAC5B;AAEO,SAAS,mBAAmB,IAAA,EAAgC;AACjE,EAAA,OAAO,kBAAA,CAAmB,IAAI,IAAI,CAAA;AACpC;AAEO,SAAS,mBAAmB,IAAA,EAAgC;AACjE,EAAA,OAAO,kBAAA,CAAmB,IAAI,IAAI,CAAA;AACpC;AAEO,SAAS,gBAAgB,IAAA,EAAgC;AAC9D,EAAA,OAAO,oBAAA,CAAqB,IAAI,CAAA,CAAE,WAAA;AACpC;AAEO,SAAS,sBAAsB,IAAA,EAAgC;AACpE,EAAA,OAAO,oBAAA,CAAqB,IAAI,CAAA,CAAE,qBAAA;AACpC;AAEO,SAAS,gBAAgB,IAAA,EAAuB;AACrD,EAAA,OAAO,oBAAA,CAAqB,IAAI,CAAA,CAAE,YAAA;AACpC;AAEO,SAAS,eAAe,IAAA,EAAuB;AACpD,EAAA,OAAO,oBAAA,CAAqB,IAAI,CAAA,CAAE,WAAA;AACpC;AAEO,SAAS,iBAAiB,IAAA,EAAgC;AAC/D,EAAA,OAAO,oBAAA,CAAqB,IAAI,CAAA,CAAE,gBAAA,IAAoB,KAAA;AACxD;AAEO,SAAS,gBAAgB,IAAA,EAAgC;AAC9D,EAAA,OAAO,oBAAA,CAAqB,IAAI,CAAA,CAAE,eAAA,IAAmB,KAAA;AACvD","file":"chunk-
|
|
1
|
+
{"version":3,"sources":["../src/elements/guards.ts"],"names":[],"mappings":";;;AAGA,IAAM,UAAA,uBAAiB,GAAA,CAAqB;AAAA,EAC1C,MAAA;AAAA,EAAQ,UAAA;AAAA,EAAY,aAAA;AAAA,EAAe,YAAA;AAAA,EACnC,YAAA;AAAA,EAAc,kBAAA;AAAA,EAAoB,aAAA;AAAA,EAAe,UAAA;AAAA,EAAY;AAC/D,CAAC,CAAA;AAED,IAAM,aAAA,uBAAoB,GAAA,CAAqB;AAAA,EAC7C,kBAAA;AAAA,EAAoB,kBAAA;AAAA,EAAoB,iBAAA;AAAA,EACxC,mBAAA;AAAA,EAAqB;AACvB,CAAC,CAAA;AAED,IAAM,WAAA,uBAAkB,GAAA,CAAqB;AAAA,EAC3C,YAAA;AAAA,EAAc,UAAA;AAAA,EAAY,wBAAA;AAAA,EAC1B,wBAAA;AAAA,EAA0B;AAC5B,CAAC,CAAA;AAED,IAAM,UAAA,uBAAiB,GAAA,CAAqB;AAAA,EAC1C,YAAA;AAAA,EAAc,qBAAA;AAAA,EAAuB,WAAA;AAAA,EAAa,YAAA;AAAA,EAClD,WAAA;AAAA,EAAa;AACf,CAAC,CAAA;AAED,IAAM,kBAAA,uBAAyB,GAAA,CAAqB;AAAA,EAClD,cAAA;AAAA,EAAgB,iBAAA;AAAA,EAAmB;AACrC,CAAC,CAAA;AAED,IAAM,kBAAA,uBAAyB,GAAA,CAAqB;AAAA,EAClD,kBAAA;AAAA,EAAoB,iBAAA;AAAA,EAAmB;AACzC,CAAC,CAAA;AAEM,SAAS,WAAW,IAAA,EAAgC;AACzD,EAAA,OAAO,UAAA,CAAW,IAAI,IAAI,CAAA;AAC5B;AAEO,SAAS,cAAc,IAAA,EAAgC;AAC5D,EAAA,OAAO,aAAA,CAAc,IAAI,IAAI,CAAA;AAC/B;AAEO,SAAS,YAAY,IAAA,EAAgC;AAC1D,EAAA,OAAO,WAAA,CAAY,IAAI,IAAI,CAAA;AAC7B;AAEO,SAAS,WAAW,IAAA,EAAgC;AACzD,EAAA,OAAO,UAAA,CAAW,IAAI,IAAI,CAAA;AAC5B;AAEO,SAAS,mBAAmB,IAAA,EAAgC;AACjE,EAAA,OAAO,kBAAA,CAAmB,IAAI,IAAI,CAAA;AACpC;AAEO,SAAS,mBAAmB,IAAA,EAAgC;AACjE,EAAA,OAAO,kBAAA,CAAmB,IAAI,IAAI,CAAA;AACpC;AAEO,SAAS,gBAAgB,IAAA,EAAgC;AAC9D,EAAA,OAAO,oBAAA,CAAqB,IAAI,CAAA,CAAE,WAAA;AACpC;AAEO,SAAS,sBAAsB,IAAA,EAAgC;AACpE,EAAA,OAAO,oBAAA,CAAqB,IAAI,CAAA,CAAE,qBAAA;AACpC;AAEO,SAAS,gBAAgB,IAAA,EAAuB;AACrD,EAAA,OAAO,oBAAA,CAAqB,IAAI,CAAA,CAAE,YAAA;AACpC;AAEO,SAAS,eAAe,IAAA,EAAuB;AACpD,EAAA,OAAO,oBAAA,CAAqB,IAAI,CAAA,CAAE,WAAA;AACpC;AAEO,SAAS,iBAAiB,IAAA,EAAgC;AAC/D,EAAA,OAAO,oBAAA,CAAqB,IAAI,CAAA,CAAE,gBAAA,IAAoB,KAAA;AACxD;AAEO,SAAS,gBAAgB,IAAA,EAAgC;AAC9D,EAAA,OAAO,oBAAA,CAAqB,IAAI,CAAA,CAAE,eAAA,IAAmB,KAAA;AACvD","file":"chunk-5GRCJ5X6.js","sourcesContent":["import { BPMN_ELEMENT_CATALOG } from \"./catalog\";\nimport type { BpmnElementType } from \"./types\";\n\nconst TASK_TYPES = new Set<BpmnElementType>([\n \"Task\", \"UserTask\", \"ServiceTask\", \"ScriptTask\",\n \"ManualTask\", \"BusinessRuleTask\", \"ReceiveTask\", \"SendTask\", \"CallActivity\",\n]);\n\nconst GATEWAY_TYPES = new Set<BpmnElementType>([\n \"ExclusiveGateway\", \"InclusiveGateway\", \"ParallelGateway\",\n \"EventBasedGateway\", \"ComplexGateway\",\n]);\n\nconst EVENT_TYPES = new Set<BpmnElementType>([\n \"StartEvent\", \"EndEvent\", \"IntermediateCatchEvent\",\n \"IntermediateThrowEvent\", \"BoundaryEvent\",\n]);\n\nconst DATA_TYPES = new Set<BpmnElementType>([\n \"DataObject\", \"DataObjectReference\", \"DataInput\", \"DataOutput\",\n \"DataStore\", \"DataStoreReference\",\n]);\n\nconst CONVERSATION_TYPES = new Set<BpmnElementType>([\n \"Conversation\", \"SubConversation\", \"CallConversation\",\n]);\n\nconst CHOREOGRAPHY_TYPES = new Set<BpmnElementType>([\n \"ChoreographyTask\", \"SubChoreography\", \"CallChoreography\",\n]);\n\nexport function isTaskType(type: BpmnElementType): boolean {\n return TASK_TYPES.has(type);\n}\n\nexport function isGatewayType(type: BpmnElementType): boolean {\n return GATEWAY_TYPES.has(type);\n}\n\nexport function isEventType(type: BpmnElementType): boolean {\n return EVENT_TYPES.has(type);\n}\n\nexport function isDataType(type: BpmnElementType): boolean {\n return DATA_TYPES.has(type);\n}\n\nexport function isConversationType(type: BpmnElementType): boolean {\n return CONVERSATION_TYPES.has(type);\n}\n\nexport function isChoreographyType(type: BpmnElementType): boolean {\n return CHOREOGRAPHY_TYPES.has(type);\n}\n\nexport function isContainerType(type: BpmnElementType): boolean {\n return BPMN_ELEMENT_CATALOG[type].isContainer;\n}\n\nexport function acceptsBoundaryEvents(type: BpmnElementType): boolean {\n return BPMN_ELEMENT_CATALOG[type].acceptsBoundaryEvents;\n}\n\nexport function getHandlePolicy(type: BpmnElementType) {\n return BPMN_ELEMENT_CATALOG[type].handlePolicy;\n}\n\nexport function getOrientation(type: BpmnElementType) {\n return BPMN_ELEMENT_CATALOG[type].orientation;\n}\n\nexport function supportsCollapse(type: BpmnElementType): boolean {\n return BPMN_ELEMENT_CATALOG[type].supportsCollapse ?? false;\n}\n\nexport function supportsMarkers(type: BpmnElementType): boolean {\n return BPMN_ELEMENT_CATALOG[type].supportsMarkers ?? false;\n}\n"]}
|
|
@@ -0,0 +1,277 @@
|
|
|
1
|
+
import { acceptsBoundaryEvents, isEventType, getHandlePolicy, isDataType } from './chunk-5GRCJ5X6.js';
|
|
2
|
+
import { BPMN_ELEMENT_CATALOG } from './chunk-DNR5WBQH.js';
|
|
3
|
+
import { createModelingRules, getNode, getOutgoingEdges, getIncomingEdges, addNode, connectNodes, reparentNode, patchNode, replaceNode, resizeNode, removeElements, copyElements, pasteElements, setSelection, createSelectionState, normalizeDiagramState, executeCommand, executeCommands } from '@aranzatech/diagrams-core';
|
|
4
|
+
import { createDiagramDocument, serializeDiagram, parseDiagramDocument, deserializeDiagram } from '@aranzatech/diagrams-core/serialization';
|
|
5
|
+
|
|
6
|
+
function createBpmnNode(options) {
|
|
7
|
+
const meta = BPMN_ELEMENT_CATALOG[options.elementType];
|
|
8
|
+
return {
|
|
9
|
+
id: options.id,
|
|
10
|
+
type: options.elementType,
|
|
11
|
+
position: options.position,
|
|
12
|
+
data: {
|
|
13
|
+
elementType: options.elementType,
|
|
14
|
+
...options.label ? { label: options.label } : {},
|
|
15
|
+
...options.data ?? {}
|
|
16
|
+
},
|
|
17
|
+
width: options.width ?? meta.defaultWidth,
|
|
18
|
+
height: options.height ?? meta.defaultHeight,
|
|
19
|
+
...options.parentId ? { parentId: options.parentId } : {}
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
function inferBpmnEdgeType(state, sourceId, targetId) {
|
|
23
|
+
const source = getNode(state, sourceId);
|
|
24
|
+
const target = getNode(state, targetId);
|
|
25
|
+
if (!source || !target) return "sequenceFlow";
|
|
26
|
+
if (isDataType(source.data.elementType) || isDataType(target.data.elementType)) {
|
|
27
|
+
return "dataAssociation";
|
|
28
|
+
}
|
|
29
|
+
if (source.data.elementType === "Annotation" || target.data.elementType === "Annotation" || source.data.elementType === "Group" || target.data.elementType === "Group") {
|
|
30
|
+
return "association";
|
|
31
|
+
}
|
|
32
|
+
if (source.data.elementType === "Conversation" || source.data.elementType === "SubConversation" || source.data.elementType === "CallConversation" || target.data.elementType === "Conversation" || target.data.elementType === "SubConversation" || target.data.elementType === "CallConversation") {
|
|
33
|
+
return "conversationLink";
|
|
34
|
+
}
|
|
35
|
+
if (source.parentId && target.parentId && source.parentId !== target.parentId) {
|
|
36
|
+
return "messageFlow";
|
|
37
|
+
}
|
|
38
|
+
return "sequenceFlow";
|
|
39
|
+
}
|
|
40
|
+
function canUseSequenceFlow(type) {
|
|
41
|
+
const meta = BPMN_ELEMENT_CATALOG[type];
|
|
42
|
+
return meta.handlePolicy !== "none" && !isDataType(type) && type !== "Annotation" && type !== "Group" && meta.category !== "conversation";
|
|
43
|
+
}
|
|
44
|
+
function validateEdgeCardinality(state, edgeType, source, target) {
|
|
45
|
+
if (edgeType !== "sequenceFlow") return true;
|
|
46
|
+
const sourceMax = BPMN_ELEMENT_CATALOG[source.data.elementType].maxOutgoing;
|
|
47
|
+
const targetMax = BPMN_ELEMENT_CATALOG[target.data.elementType].maxIncoming;
|
|
48
|
+
const outgoing = getOutgoingEdges(state, source.id).filter(
|
|
49
|
+
(edge) => edge.data?.edgeType === "sequenceFlow"
|
|
50
|
+
);
|
|
51
|
+
const incoming = getIncomingEdges(state, target.id).filter(
|
|
52
|
+
(edge) => edge.data?.edgeType === "sequenceFlow"
|
|
53
|
+
);
|
|
54
|
+
if (sourceMax !== void 0 && outgoing.length >= sourceMax) {
|
|
55
|
+
return `${source.data.elementType} cannot have more than ${sourceMax} outgoing sequence flow(s).`;
|
|
56
|
+
}
|
|
57
|
+
if (targetMax !== void 0 && incoming.length >= targetMax) {
|
|
58
|
+
return `${target.data.elementType} cannot have more than ${targetMax} incoming sequence flow(s).`;
|
|
59
|
+
}
|
|
60
|
+
return true;
|
|
61
|
+
}
|
|
62
|
+
var bpmnConnectionValidators = [
|
|
63
|
+
({ state, source, target }) => {
|
|
64
|
+
if (source.id === target.id) return "BPMN self-connections are not allowed.";
|
|
65
|
+
const edgeType = inferBpmnEdgeType(state, source.id, target.id);
|
|
66
|
+
if (getHandlePolicy(source.data.elementType) === "none" || getHandlePolicy(target.data.elementType) === "none") {
|
|
67
|
+
return "Elements without BPMN connection handles cannot be directly connected.";
|
|
68
|
+
}
|
|
69
|
+
if (edgeType === "sequenceFlow") {
|
|
70
|
+
if (!canUseSequenceFlow(source.data.elementType) || !canUseSequenceFlow(target.data.elementType)) {
|
|
71
|
+
return "Sequence flows can only connect BPMN flow nodes.";
|
|
72
|
+
}
|
|
73
|
+
if (source.data.elementType === "EndEvent") return "End events cannot have outgoing sequence flows.";
|
|
74
|
+
if (target.data.elementType === "StartEvent") return "Start events cannot have incoming sequence flows.";
|
|
75
|
+
return validateEdgeCardinality(state, edgeType, source, target);
|
|
76
|
+
}
|
|
77
|
+
return true;
|
|
78
|
+
}
|
|
79
|
+
];
|
|
80
|
+
var BPMN_MODELING_RULES = createModelingRules({
|
|
81
|
+
connect: [
|
|
82
|
+
({ state, source, target }) => {
|
|
83
|
+
if (!source || !target) return false;
|
|
84
|
+
for (const validator of bpmnConnectionValidators) {
|
|
85
|
+
const result = validator({
|
|
86
|
+
state,
|
|
87
|
+
source,
|
|
88
|
+
target,
|
|
89
|
+
existingEdges: state.edges
|
|
90
|
+
});
|
|
91
|
+
if (result !== true) return result;
|
|
92
|
+
}
|
|
93
|
+
return true;
|
|
94
|
+
}
|
|
95
|
+
],
|
|
96
|
+
drop: [
|
|
97
|
+
({ node, parent }) => {
|
|
98
|
+
if (!node || !parent) return true;
|
|
99
|
+
if (node.data.elementType === "BoundaryEvent") {
|
|
100
|
+
return acceptsBoundaryEvents(parent.data.elementType) ? true : "Boundary events can only be attached to tasks or subprocesses.";
|
|
101
|
+
}
|
|
102
|
+
if (parent.data.elementType === "Pool" || parent.data.elementType === "Lane") {
|
|
103
|
+
return isEventType(node.data.elementType) || node.data.elementType.includes("Task") || node.data.elementType.includes("Gateway") || node.data.elementType.includes("SubProcess") ? true : "Only flow nodes can be dropped into pools or lanes.";
|
|
104
|
+
}
|
|
105
|
+
return true;
|
|
106
|
+
}
|
|
107
|
+
],
|
|
108
|
+
reparent: [
|
|
109
|
+
({ node, parent }) => {
|
|
110
|
+
if (!node || !parent) return true;
|
|
111
|
+
if (node.data.elementType === "BoundaryEvent") {
|
|
112
|
+
return acceptsBoundaryEvents(parent.data.elementType) ? true : "Boundary events can only be reparented to tasks or subprocesses.";
|
|
113
|
+
}
|
|
114
|
+
return true;
|
|
115
|
+
}
|
|
116
|
+
],
|
|
117
|
+
delete: [() => true],
|
|
118
|
+
resize: [() => true]
|
|
119
|
+
});
|
|
120
|
+
function createBpmnNodeCommand(options) {
|
|
121
|
+
return {
|
|
122
|
+
id: `bpmn.createNode.${options.id}`,
|
|
123
|
+
label: `Create ${options.elementType}`,
|
|
124
|
+
execute: (state) => addNode(state, createBpmnNode(options))
|
|
125
|
+
};
|
|
126
|
+
}
|
|
127
|
+
function connectBpmnCommand(options) {
|
|
128
|
+
return {
|
|
129
|
+
id: `bpmn.connect.${options.id ?? `${options.source}-${options.target}`}`,
|
|
130
|
+
label: "Connect BPMN elements",
|
|
131
|
+
execute: (state) => {
|
|
132
|
+
const edgeType = options.edgeType ?? inferBpmnEdgeType(state, options.source, options.target);
|
|
133
|
+
return connectNodes(
|
|
134
|
+
state,
|
|
135
|
+
{
|
|
136
|
+
source: options.source,
|
|
137
|
+
target: options.target,
|
|
138
|
+
type: edgeType,
|
|
139
|
+
...options.sourceHandle !== void 0 ? { sourceHandle: options.sourceHandle } : {},
|
|
140
|
+
...options.targetHandle !== void 0 ? { targetHandle: options.targetHandle } : {},
|
|
141
|
+
...options.id ? { id: options.id } : {},
|
|
142
|
+
data: {
|
|
143
|
+
edgeType,
|
|
144
|
+
...options.label ? { label: options.label } : {},
|
|
145
|
+
...options.data ?? {}
|
|
146
|
+
}
|
|
147
|
+
},
|
|
148
|
+
bpmnConnectionValidators
|
|
149
|
+
);
|
|
150
|
+
}
|
|
151
|
+
};
|
|
152
|
+
}
|
|
153
|
+
function attachBoundaryEventCommand(boundaryId, hostId) {
|
|
154
|
+
return {
|
|
155
|
+
id: `bpmn.attachBoundary.${boundaryId}.${hostId}`,
|
|
156
|
+
label: "Attach boundary event",
|
|
157
|
+
execute: (state) => {
|
|
158
|
+
const host = getNode(state, hostId);
|
|
159
|
+
if (!host || !acceptsBoundaryEvents(host.data.elementType)) {
|
|
160
|
+
throw new Error(`Element "${hostId}" cannot host boundary events.`);
|
|
161
|
+
}
|
|
162
|
+
const boundary = getNode(state, boundaryId);
|
|
163
|
+
if (!boundary || boundary.data.elementType !== "BoundaryEvent") {
|
|
164
|
+
throw new Error(`Element "${boundaryId}" is not a boundary event.`);
|
|
165
|
+
}
|
|
166
|
+
const reparented = reparentNode(state, boundaryId, { parentId: hostId });
|
|
167
|
+
return patchNode(reparented, boundaryId, {
|
|
168
|
+
data: { attachedToRef: hostId }
|
|
169
|
+
});
|
|
170
|
+
}
|
|
171
|
+
};
|
|
172
|
+
}
|
|
173
|
+
function replaceBpmnNodeCommand(options) {
|
|
174
|
+
return {
|
|
175
|
+
id: `bpmn.replaceNode.${options.id}.${options.elementType}`,
|
|
176
|
+
label: `Replace with ${options.elementType}`,
|
|
177
|
+
execute: (state) => {
|
|
178
|
+
const current = getNode(state, options.id);
|
|
179
|
+
if (!current) throw new Error(`Element "${options.id}" does not exist.`);
|
|
180
|
+
const meta = BPMN_ELEMENT_CATALOG[options.elementType];
|
|
181
|
+
return replaceNode(state, options.id, {
|
|
182
|
+
...current,
|
|
183
|
+
type: options.elementType,
|
|
184
|
+
width: options.width ?? current.width ?? meta.defaultWidth,
|
|
185
|
+
height: options.height ?? current.height ?? meta.defaultHeight,
|
|
186
|
+
data: {
|
|
187
|
+
...current.data,
|
|
188
|
+
elementType: options.elementType,
|
|
189
|
+
...options.label ? { label: options.label } : {},
|
|
190
|
+
...options.data ?? {}
|
|
191
|
+
}
|
|
192
|
+
});
|
|
193
|
+
}
|
|
194
|
+
};
|
|
195
|
+
}
|
|
196
|
+
function reparentBpmnNodeCommand(options) {
|
|
197
|
+
return {
|
|
198
|
+
id: `bpmn.reparent.${options.id}.${options.parentId ?? "root"}`,
|
|
199
|
+
label: "Reparent BPMN element",
|
|
200
|
+
execute: (state) => {
|
|
201
|
+
const node = getNode(state, options.id);
|
|
202
|
+
const parent = options.parentId ? getNode(state, options.parentId) : void 0;
|
|
203
|
+
if (!node) throw new Error(`Element "${options.id}" does not exist.`);
|
|
204
|
+
if (parent && node.data.elementType === "BoundaryEvent" && !acceptsBoundaryEvents(parent.data.elementType)) {
|
|
205
|
+
throw new Error("Boundary events can only be reparented to tasks or subprocesses.");
|
|
206
|
+
}
|
|
207
|
+
return reparentNode(state, options.id, {
|
|
208
|
+
...options.parentId !== void 0 ? { parentId: options.parentId } : {},
|
|
209
|
+
...options.position ? { position: options.position } : {}
|
|
210
|
+
});
|
|
211
|
+
}
|
|
212
|
+
};
|
|
213
|
+
}
|
|
214
|
+
function resizeBpmnNodeCommand(options) {
|
|
215
|
+
return {
|
|
216
|
+
id: `bpmn.resize.${options.id}`,
|
|
217
|
+
label: "Resize BPMN element",
|
|
218
|
+
execute: (state) => resizeNode(state, options.id, options)
|
|
219
|
+
};
|
|
220
|
+
}
|
|
221
|
+
function deleteBpmnElementsCommand(ids) {
|
|
222
|
+
return {
|
|
223
|
+
id: `bpmn.delete.${ids.join(".")}`,
|
|
224
|
+
label: "Delete BPMN elements",
|
|
225
|
+
execute: (state) => removeElements(state, ids)
|
|
226
|
+
};
|
|
227
|
+
}
|
|
228
|
+
function copyBpmnElements(state, selection) {
|
|
229
|
+
return copyElements(state, selection);
|
|
230
|
+
}
|
|
231
|
+
function pasteBpmnElementsCommand(clipboard, options = {}) {
|
|
232
|
+
return {
|
|
233
|
+
id: "bpmn.paste",
|
|
234
|
+
label: "Paste BPMN elements",
|
|
235
|
+
execute: (state) => pasteElements(state, clipboard, options)
|
|
236
|
+
};
|
|
237
|
+
}
|
|
238
|
+
function selectBpmnElementsCommand(selection) {
|
|
239
|
+
return {
|
|
240
|
+
id: "bpmn.select",
|
|
241
|
+
label: "Select BPMN elements",
|
|
242
|
+
execute: (state) => setSelection(state, createSelectionState(selection.nodeIds, selection.edgeIds))
|
|
243
|
+
};
|
|
244
|
+
}
|
|
245
|
+
function createBpmnDiagramDocument(state, options = {}) {
|
|
246
|
+
return createDiagramDocument(normalizeDiagramState(state), {
|
|
247
|
+
...options,
|
|
248
|
+
diagramType: "bpmn"
|
|
249
|
+
});
|
|
250
|
+
}
|
|
251
|
+
function serializeBpmnDiagram(state, options = {}) {
|
|
252
|
+
return serializeDiagram(normalizeDiagramState(state), {
|
|
253
|
+
...options,
|
|
254
|
+
diagramType: "bpmn"
|
|
255
|
+
});
|
|
256
|
+
}
|
|
257
|
+
function parseBpmnDiagramDocument(json) {
|
|
258
|
+
const document = parseDiagramDocument(json);
|
|
259
|
+
if (document.diagramType && document.diagramType !== "bpmn") {
|
|
260
|
+
throw new Error(`Expected a BPMN diagram document, received "${document.diagramType}".`);
|
|
261
|
+
}
|
|
262
|
+
return document;
|
|
263
|
+
}
|
|
264
|
+
function deserializeBpmnDiagram(json) {
|
|
265
|
+
const document = parseBpmnDiagramDocument(json);
|
|
266
|
+
return deserializeDiagram(JSON.stringify(document));
|
|
267
|
+
}
|
|
268
|
+
function runBpmnCommand(stack, command) {
|
|
269
|
+
return executeCommand(stack, command);
|
|
270
|
+
}
|
|
271
|
+
function runBpmnCommands(stack, commands, options = {}) {
|
|
272
|
+
return executeCommands(stack, commands, options);
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
export { BPMN_MODELING_RULES, attachBoundaryEventCommand, bpmnConnectionValidators, connectBpmnCommand, copyBpmnElements, createBpmnDiagramDocument, createBpmnNode, createBpmnNodeCommand, deleteBpmnElementsCommand, deserializeBpmnDiagram, inferBpmnEdgeType, parseBpmnDiagramDocument, pasteBpmnElementsCommand, reparentBpmnNodeCommand, replaceBpmnNodeCommand, resizeBpmnNodeCommand, runBpmnCommand, runBpmnCommands, selectBpmnElementsCommand, serializeBpmnDiagram };
|
|
276
|
+
//# sourceMappingURL=chunk-G5S4ASP3.js.map
|
|
277
|
+
//# sourceMappingURL=chunk-G5S4ASP3.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/modeling/index.ts"],"names":[],"mappings":"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","file":"chunk-G5S4ASP3.js","sourcesContent":["import {\n addNode,\n connectNodes,\n copyElements,\n createModelingRules,\n createSelectionState,\n executeCommand,\n executeCommands,\n getNode,\n getOutgoingEdges,\n getIncomingEdges,\n normalizeDiagramState,\n pasteElements,\n patchNode,\n removeElements,\n replaceNode,\n reparentNode,\n resizeNode,\n setSelection,\n type CommandStackState,\n type ClipboardState,\n type ConnectionValidator,\n type DiagramCommand,\n type DiagramState,\n type ModelingRules,\n type SelectionState,\n} from \"@aranzatech/diagrams-core\";\nimport {\n createDiagramDocument,\n deserializeDiagram,\n parseDiagramDocument,\n serializeDiagram,\n type CreateDiagramDocumentOptions,\n type DiagramDocument,\n} from \"@aranzatech/diagrams-core/serialization\";\nimport { BPMN_ELEMENT_CATALOG } from \"../elements/catalog\";\nimport {\n acceptsBoundaryEvents,\n getHandlePolicy,\n isDataType,\n isEventType,\n} from \"../elements/guards\";\nimport type { BpmnElementType, BpmnEdgeData, BpmnEdgeType, BpmnNodeData } from \"../elements/types\";\nimport type { BpmnRFEdge, BpmnRFNode } from \"../xml/types\";\n\nexport type BpmnDiagramState = DiagramState<BpmnRFNode, BpmnRFEdge>;\nexport type BpmnClipboardState = ClipboardState<BpmnRFNode, BpmnRFEdge>;\nexport type BpmnDiagramDocument = DiagramDocument<BpmnRFNode, BpmnRFEdge>;\n\nexport interface CreateBpmnNodeOptions {\n id: string;\n elementType: BpmnElementType;\n position: { x: number; y: number };\n label?: string;\n parentId?: string;\n width?: number;\n height?: number;\n data?: Partial<BpmnNodeData>;\n}\n\nexport interface ConnectBpmnOptions {\n id?: string;\n source: string;\n target: string;\n edgeType?: BpmnEdgeType;\n label?: string;\n sourceHandle?: string | null;\n targetHandle?: string | null;\n data?: Partial<BpmnEdgeData>;\n}\n\nexport interface ReplaceBpmnNodeOptions {\n id: string;\n elementType: BpmnElementType;\n label?: string;\n data?: Partial<BpmnNodeData>;\n width?: number;\n height?: number;\n}\n\nexport interface ReparentBpmnNodeOptions {\n id: string;\n parentId?: string;\n position?: { x: number; y: number };\n}\n\nexport interface ResizeBpmnNodeOptions {\n id: string;\n width?: number;\n height?: number;\n}\n\nexport interface PasteBpmnOptions {\n offset?: { x: number; y: number };\n position?: { x: number; y: number };\n}\n\nexport function createBpmnNode(options: CreateBpmnNodeOptions): BpmnRFNode {\n const meta = BPMN_ELEMENT_CATALOG[options.elementType];\n return {\n id: options.id,\n type: options.elementType,\n position: options.position,\n data: {\n elementType: options.elementType,\n ...(options.label ? { label: options.label } : {}),\n ...(options.data ?? {}),\n },\n width: options.width ?? meta.defaultWidth,\n height: options.height ?? meta.defaultHeight,\n ...(options.parentId ? { parentId: options.parentId } : {}),\n };\n}\n\nexport function inferBpmnEdgeType(\n state: BpmnDiagramState,\n sourceId: string,\n targetId: string,\n): BpmnEdgeType {\n const source = getNode(state, sourceId);\n const target = getNode(state, targetId);\n if (!source || !target) return \"sequenceFlow\";\n\n if (isDataType(source.data.elementType) || isDataType(target.data.elementType)) {\n return \"dataAssociation\";\n }\n if (\n source.data.elementType === \"Annotation\" ||\n target.data.elementType === \"Annotation\" ||\n source.data.elementType === \"Group\" ||\n target.data.elementType === \"Group\"\n ) {\n return \"association\";\n }\n if (\n source.data.elementType === \"Conversation\" ||\n source.data.elementType === \"SubConversation\" ||\n source.data.elementType === \"CallConversation\" ||\n target.data.elementType === \"Conversation\" ||\n target.data.elementType === \"SubConversation\" ||\n target.data.elementType === \"CallConversation\"\n ) {\n return \"conversationLink\";\n }\n if (source.parentId && target.parentId && source.parentId !== target.parentId) {\n return \"messageFlow\";\n }\n return \"sequenceFlow\";\n}\n\nfunction canUseSequenceFlow(type: BpmnElementType): boolean {\n const meta = BPMN_ELEMENT_CATALOG[type];\n return (\n meta.handlePolicy !== \"none\" &&\n !isDataType(type) &&\n type !== \"Annotation\" &&\n type !== \"Group\" &&\n meta.category !== \"conversation\"\n );\n}\n\nfunction validateEdgeCardinality(\n state: BpmnDiagramState,\n edgeType: BpmnEdgeType,\n source: BpmnRFNode,\n target: BpmnRFNode,\n): true | string {\n if (edgeType !== \"sequenceFlow\") return true;\n\n const sourceMax = BPMN_ELEMENT_CATALOG[source.data.elementType].maxOutgoing;\n const targetMax = BPMN_ELEMENT_CATALOG[target.data.elementType].maxIncoming;\n const outgoing = getOutgoingEdges(state, source.id).filter(\n (edge) => edge.data?.edgeType === \"sequenceFlow\",\n );\n const incoming = getIncomingEdges(state, target.id).filter(\n (edge) => edge.data?.edgeType === \"sequenceFlow\",\n );\n\n if (sourceMax !== undefined && outgoing.length >= sourceMax) {\n return `${source.data.elementType} cannot have more than ${sourceMax} outgoing sequence flow(s).`;\n }\n if (targetMax !== undefined && incoming.length >= targetMax) {\n return `${target.data.elementType} cannot have more than ${targetMax} incoming sequence flow(s).`;\n }\n return true;\n}\n\nexport const bpmnConnectionValidators: Array<\n ConnectionValidator<BpmnRFNode, BpmnRFEdge>\n> = [\n ({ state, source, target }) => {\n if (source.id === target.id) return \"BPMN self-connections are not allowed.\";\n const edgeType = inferBpmnEdgeType(state, source.id, target.id);\n\n if (getHandlePolicy(source.data.elementType) === \"none\" || getHandlePolicy(target.data.elementType) === \"none\") {\n return \"Elements without BPMN connection handles cannot be directly connected.\";\n }\n\n if (edgeType === \"sequenceFlow\") {\n if (!canUseSequenceFlow(source.data.elementType) || !canUseSequenceFlow(target.data.elementType)) {\n return \"Sequence flows can only connect BPMN flow nodes.\";\n }\n if (source.data.elementType === \"EndEvent\") return \"End events cannot have outgoing sequence flows.\";\n if (target.data.elementType === \"StartEvent\") return \"Start events cannot have incoming sequence flows.\";\n return validateEdgeCardinality(state, edgeType, source, target);\n }\n\n return true;\n },\n];\n\nexport const BPMN_MODELING_RULES: ModelingRules<BpmnRFNode, BpmnRFEdge> =\n createModelingRules({\n connect: [\n ({ state, source, target }) => {\n if (!source || !target) return false;\n for (const validator of bpmnConnectionValidators) {\n const result = validator({\n state,\n source,\n target,\n existingEdges: state.edges,\n });\n if (result !== true) return result;\n }\n return true;\n },\n ],\n drop: [\n ({ node, parent }) => {\n if (!node || !parent) return true;\n if (node.data.elementType === \"BoundaryEvent\") {\n return acceptsBoundaryEvents(parent.data.elementType)\n ? true\n : \"Boundary events can only be attached to tasks or subprocesses.\";\n }\n if (parent.data.elementType === \"Pool\" || parent.data.elementType === \"Lane\") {\n return isEventType(node.data.elementType) ||\n node.data.elementType.includes(\"Task\") ||\n node.data.elementType.includes(\"Gateway\") ||\n node.data.elementType.includes(\"SubProcess\")\n ? true\n : \"Only flow nodes can be dropped into pools or lanes.\";\n }\n return true;\n },\n ],\n reparent: [\n ({ node, parent }) => {\n if (!node || !parent) return true;\n if (node.data.elementType === \"BoundaryEvent\") {\n return acceptsBoundaryEvents(parent.data.elementType)\n ? true\n : \"Boundary events can only be reparented to tasks or subprocesses.\";\n }\n return true;\n },\n ],\n delete: [() => true],\n resize: [() => true],\n });\n\nexport function createBpmnNodeCommand(\n options: CreateBpmnNodeOptions,\n): DiagramCommand<BpmnRFNode, BpmnRFEdge> {\n return {\n id: `bpmn.createNode.${options.id}`,\n label: `Create ${options.elementType}`,\n execute: (state) => addNode(state, createBpmnNode(options)),\n };\n}\n\nexport function connectBpmnCommand(\n options: ConnectBpmnOptions,\n): DiagramCommand<BpmnRFNode, BpmnRFEdge> {\n return {\n id: `bpmn.connect.${options.id ?? `${options.source}-${options.target}`}`,\n label: \"Connect BPMN elements\",\n execute: (state) => {\n const edgeType = options.edgeType ?? inferBpmnEdgeType(state, options.source, options.target);\n return connectNodes(\n state,\n {\n source: options.source,\n target: options.target,\n type: edgeType,\n ...(options.sourceHandle !== undefined\n ? { sourceHandle: options.sourceHandle }\n : {}),\n ...(options.targetHandle !== undefined\n ? { targetHandle: options.targetHandle }\n : {}),\n ...(options.id ? { id: options.id } : {}),\n data: {\n edgeType,\n ...(options.label ? { label: options.label } : {}),\n ...(options.data ?? {}),\n },\n },\n bpmnConnectionValidators,\n );\n },\n };\n}\n\nexport function attachBoundaryEventCommand(\n boundaryId: string,\n hostId: string,\n): DiagramCommand<BpmnRFNode, BpmnRFEdge> {\n return {\n id: `bpmn.attachBoundary.${boundaryId}.${hostId}`,\n label: \"Attach boundary event\",\n execute: (state) => {\n const host = getNode(state, hostId);\n if (!host || !acceptsBoundaryEvents(host.data.elementType)) {\n throw new Error(`Element \"${hostId}\" cannot host boundary events.`);\n }\n const boundary = getNode(state, boundaryId);\n if (!boundary || boundary.data.elementType !== \"BoundaryEvent\") {\n throw new Error(`Element \"${boundaryId}\" is not a boundary event.`);\n }\n const reparented = reparentNode(state, boundaryId, { parentId: hostId });\n return patchNode(reparented, boundaryId, {\n data: { attachedToRef: hostId },\n });\n },\n };\n}\n\nexport function replaceBpmnNodeCommand(\n options: ReplaceBpmnNodeOptions,\n): DiagramCommand<BpmnRFNode, BpmnRFEdge> {\n return {\n id: `bpmn.replaceNode.${options.id}.${options.elementType}`,\n label: `Replace with ${options.elementType}`,\n execute: (state) => {\n const current = getNode(state, options.id);\n if (!current) throw new Error(`Element \"${options.id}\" does not exist.`);\n const meta = BPMN_ELEMENT_CATALOG[options.elementType];\n return replaceNode(state, options.id, {\n ...current,\n type: options.elementType,\n width: options.width ?? current.width ?? meta.defaultWidth,\n height: options.height ?? current.height ?? meta.defaultHeight,\n data: {\n ...current.data,\n elementType: options.elementType,\n ...(options.label ? { label: options.label } : {}),\n ...(options.data ?? {}),\n },\n });\n },\n };\n}\n\nexport function reparentBpmnNodeCommand(\n options: ReparentBpmnNodeOptions,\n): DiagramCommand<BpmnRFNode, BpmnRFEdge> {\n return {\n id: `bpmn.reparent.${options.id}.${options.parentId ?? \"root\"}`,\n label: \"Reparent BPMN element\",\n execute: (state) => {\n const node = getNode(state, options.id);\n const parent = options.parentId ? getNode(state, options.parentId) : undefined;\n if (!node) throw new Error(`Element \"${options.id}\" does not exist.`);\n if (parent && node.data.elementType === \"BoundaryEvent\" && !acceptsBoundaryEvents(parent.data.elementType)) {\n throw new Error(\"Boundary events can only be reparented to tasks or subprocesses.\");\n }\n return reparentNode(state, options.id, {\n ...(options.parentId !== undefined ? { parentId: options.parentId } : {}),\n ...(options.position ? { position: options.position } : {}),\n });\n },\n };\n}\n\nexport function resizeBpmnNodeCommand(\n options: ResizeBpmnNodeOptions,\n): DiagramCommand<BpmnRFNode, BpmnRFEdge> {\n return {\n id: `bpmn.resize.${options.id}`,\n label: \"Resize BPMN element\",\n execute: (state) => resizeNode(state, options.id, options),\n };\n}\n\nexport function deleteBpmnElementsCommand(\n ids: string[],\n): DiagramCommand<BpmnRFNode, BpmnRFEdge> {\n return {\n id: `bpmn.delete.${ids.join(\".\")}`,\n label: \"Delete BPMN elements\",\n execute: (state) => removeElements(state, ids),\n };\n}\n\nexport function copyBpmnElements(\n state: BpmnDiagramState,\n selection?: SelectionState,\n): BpmnClipboardState {\n return copyElements(state, selection);\n}\n\nexport function pasteBpmnElementsCommand(\n clipboard: BpmnClipboardState,\n options: PasteBpmnOptions = {},\n): DiagramCommand<BpmnRFNode, BpmnRFEdge> {\n return {\n id: \"bpmn.paste\",\n label: \"Paste BPMN elements\",\n execute: (state) => pasteElements(state, clipboard, options),\n };\n}\n\nexport function selectBpmnElementsCommand(\n selection: SelectionState,\n): DiagramCommand<BpmnRFNode, BpmnRFEdge> {\n return {\n id: \"bpmn.select\",\n label: \"Select BPMN elements\",\n execute: (state) => setSelection(state, createSelectionState(selection.nodeIds, selection.edgeIds)),\n };\n}\n\nexport function createBpmnDiagramDocument(\n state: BpmnDiagramState,\n options: Omit<CreateDiagramDocumentOptions, \"diagramType\"> = {},\n): BpmnDiagramDocument {\n return createDiagramDocument(normalizeDiagramState(state), {\n ...options,\n diagramType: \"bpmn\",\n });\n}\n\nexport function serializeBpmnDiagram(\n state: BpmnDiagramState,\n options: Omit<CreateDiagramDocumentOptions, \"diagramType\"> = {},\n): string {\n return serializeDiagram(normalizeDiagramState(state), {\n ...options,\n diagramType: \"bpmn\",\n });\n}\n\nexport function parseBpmnDiagramDocument(json: string): BpmnDiagramDocument {\n const document = parseDiagramDocument<BpmnRFNode, BpmnRFEdge>(json);\n if (document.diagramType && document.diagramType !== \"bpmn\") {\n throw new Error(`Expected a BPMN diagram document, received \"${document.diagramType}\".`);\n }\n return document;\n}\n\nexport function deserializeBpmnDiagram(json: string): BpmnDiagramState {\n const document = parseBpmnDiagramDocument(json);\n return deserializeDiagram<BpmnRFNode, BpmnRFEdge>(JSON.stringify(document));\n}\n\nexport function runBpmnCommand(\n stack: CommandStackState<BpmnRFNode, BpmnRFEdge>,\n command: DiagramCommand<BpmnRFNode, BpmnRFEdge>,\n): CommandStackState<BpmnRFNode, BpmnRFEdge> {\n return executeCommand(stack, command);\n}\n\nexport function runBpmnCommands(\n stack: CommandStackState<BpmnRFNode, BpmnRFEdge>,\n commands: Array<DiagramCommand<BpmnRFNode, BpmnRFEdge>>,\n options: { id?: string; label?: string } = {},\n): CommandStackState<BpmnRFNode, BpmnRFEdge> {\n return executeCommands(stack, commands, options);\n}\n"]}
|