@bpmnkit/core 0.0.27 → 0.1.1
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/bpmn/auto-layout.js +39 -126
- package/dist/bpmn/bpmn-builder.d.ts +30 -0
- package/dist/bpmn/bpmn-builder.js +350 -31
- package/dist/bpmn/bpmn-model.d.ts +35 -2
- package/dist/bpmn/bpmn-parser.js +39 -1
- package/dist/bpmn/bpmn-serializer.js +27 -0
- package/dist/bpmn/compact.js +11 -1
- package/dist/bpmn/di-check.d.ts +14 -0
- package/dist/bpmn/di-check.js +51 -0
- package/dist/bpmn/di-planes.d.ts +13 -0
- package/dist/bpmn/di-planes.js +20 -0
- package/dist/bpmn/optimize/tasks.js +1 -0
- package/dist/bpmn/svg.js +36 -4
- package/dist/bpmn/type-guards.d.ts +7 -1
- package/dist/bpmn/type-guards.js +13 -0
- package/dist/index.d.ts +5 -2
- package/dist/index.js +3 -1
- package/dist/layout/annotations.d.ts +27 -0
- package/dist/layout/annotations.js +251 -0
- package/dist/layout/grid/edge-labels.d.ts +8 -0
- package/dist/layout/grid/edge-labels.js +126 -0
- package/dist/layout/grid/flow-graph.d.ts +25 -0
- package/dist/layout/grid/flow-graph.js +99 -0
- package/dist/layout/grid/grid-engine.d.ts +4 -0
- package/dist/layout/grid/grid-engine.js +214 -0
- package/dist/layout/grid/grid-router.d.ts +36 -0
- package/dist/layout/grid/grid-router.js +190 -0
- package/dist/layout/grid/grid.d.ts +43 -0
- package/dist/layout/grid/grid.js +174 -0
- package/dist/layout/grid/walker.d.ts +11 -0
- package/dist/layout/grid/walker.js +126 -0
- package/dist/layout/index.d.ts +2 -5
- package/dist/layout/index.js +1 -4
- package/dist/layout/layout-engine.d.ts +5 -15
- package/dist/layout/layout-engine.js +8 -486
- package/dist/layout/types.js +4 -0
- package/dist/xml/xml-parser.js +5 -0
- package/package.json +1 -1
- package/dist/layout/astar.d.ts +0 -15
- package/dist/layout/astar.js +0 -191
- package/dist/layout/block-builder.d.ts +0 -37
- package/dist/layout/block-builder.js +0 -154
- package/dist/layout/block-layout.d.ts +0 -9
- package/dist/layout/block-layout.js +0 -163
- package/dist/layout/coordinates.d.ts +0 -85
- package/dist/layout/coordinates.js +0 -1392
- package/dist/layout/crossing.d.ts +0 -8
- package/dist/layout/crossing.js +0 -60
- package/dist/layout/graph.d.ts +0 -28
- package/dist/layout/graph.js +0 -126
- package/dist/layout/layers.d.ts +0 -13
- package/dist/layout/layers.js +0 -49
- package/dist/layout/routing.d.ts +0 -33
- package/dist/layout/routing.js +0 -622
- package/dist/layout/subprocess.d.ts +0 -14
- package/dist/layout/subprocess.js +0 -115
|
@@ -127,6 +127,7 @@ function makeFlowElement(id, type, options) {
|
|
|
127
127
|
sequenceFlows: [],
|
|
128
128
|
textAnnotations: [],
|
|
129
129
|
associations: [],
|
|
130
|
+
groups: [],
|
|
130
131
|
};
|
|
131
132
|
case "adHocSubProcess":
|
|
132
133
|
return {
|
|
@@ -136,6 +137,7 @@ function makeFlowElement(id, type, options) {
|
|
|
136
137
|
sequenceFlows: [],
|
|
137
138
|
textAnnotations: [],
|
|
138
139
|
associations: [],
|
|
140
|
+
groups: [],
|
|
139
141
|
};
|
|
140
142
|
case "eventSubProcess":
|
|
141
143
|
return {
|
|
@@ -145,6 +147,7 @@ function makeFlowElement(id, type, options) {
|
|
|
145
147
|
sequenceFlows: [],
|
|
146
148
|
textAnnotations: [],
|
|
147
149
|
associations: [],
|
|
150
|
+
groups: [],
|
|
148
151
|
};
|
|
149
152
|
case "transaction":
|
|
150
153
|
return {
|
|
@@ -154,7 +157,10 @@ function makeFlowElement(id, type, options) {
|
|
|
154
157
|
sequenceFlows: [],
|
|
155
158
|
textAnnotations: [],
|
|
156
159
|
associations: [],
|
|
160
|
+
groups: [],
|
|
157
161
|
};
|
|
162
|
+
default:
|
|
163
|
+
return { ...base, type };
|
|
158
164
|
}
|
|
159
165
|
}
|
|
160
166
|
function buildMultiInstance(options) {
|
|
@@ -333,6 +339,31 @@ function makeInclusiveGatewayEl(id, options) {
|
|
|
333
339
|
}
|
|
334
340
|
return el;
|
|
335
341
|
}
|
|
342
|
+
/**
|
|
343
|
+
* `subProcess`/`eventSubProcess`/`adHocSubProcess` all take a required content
|
|
344
|
+
* callback as their 2nd argument and an optional options object as their 3rd.
|
|
345
|
+
* That shape isn't demonstrated anywhere in this SDK's docs/examples, and
|
|
346
|
+
* callers that only see the parameter *names* (not enforced types — e.g.
|
|
347
|
+
* generated code run without type-checking) sometimes guess the common
|
|
348
|
+
* "options before callback" order instead. Detect that by runtime type and
|
|
349
|
+
* swap, so a reversed call still succeeds instead of throwing on `content`
|
|
350
|
+
* not being callable.
|
|
351
|
+
*/
|
|
352
|
+
function resolveSubProcessArgs(content, options) {
|
|
353
|
+
if (typeof content === "function") {
|
|
354
|
+
return {
|
|
355
|
+
content: content,
|
|
356
|
+
options: options,
|
|
357
|
+
};
|
|
358
|
+
}
|
|
359
|
+
if (typeof options === "function") {
|
|
360
|
+
return {
|
|
361
|
+
content: options,
|
|
362
|
+
options: content,
|
|
363
|
+
};
|
|
364
|
+
}
|
|
365
|
+
throw new TypeError("subProcess() requires a content callback function");
|
|
366
|
+
}
|
|
336
367
|
// ---------------------------------------------------------------------------
|
|
337
368
|
// Shared graph helpers — used by ProcessBuilder and SubProcessContentBuilder
|
|
338
369
|
// ---------------------------------------------------------------------------
|
|
@@ -712,6 +743,120 @@ export class BranchBuilder {
|
|
|
712
743
|
this.openBranchEnds = savedOpenEnds;
|
|
713
744
|
return this;
|
|
714
745
|
}
|
|
746
|
+
// ---- Sub-process ----
|
|
747
|
+
/** Add a sub-process (mirrors `ProcessBuilder.subProcess`). */
|
|
748
|
+
subProcess(id, content, options) {
|
|
749
|
+
const resolved = resolveSubProcessArgs(content, options);
|
|
750
|
+
const sub = new SubProcessContentBuilder(this.rootMessages);
|
|
751
|
+
resolved.content(sub);
|
|
752
|
+
insertJoinGateways(sub._elements, sub._flows);
|
|
753
|
+
recomputeIncomingOutgoing(sub._elements, sub._flows);
|
|
754
|
+
const element = makeFlowElement(id, "subProcess", resolved.options);
|
|
755
|
+
if (element.type === "subProcess") {
|
|
756
|
+
element.flowElements = sub._elements;
|
|
757
|
+
element.sequenceFlows = sub._flows;
|
|
758
|
+
element.textAnnotations = sub._textAnnotations;
|
|
759
|
+
element.associations = sub._associations;
|
|
760
|
+
if (resolved.options?.multiInstance) {
|
|
761
|
+
element.loopCharacteristics = buildMultiInstance(resolved.options.multiInstance);
|
|
762
|
+
}
|
|
763
|
+
}
|
|
764
|
+
return this.addElement(element);
|
|
765
|
+
}
|
|
766
|
+
/** Add an ad-hoc sub-process (mirrors `ProcessBuilder.adHocSubProcess`). */
|
|
767
|
+
adHocSubProcess(id, content, options) {
|
|
768
|
+
const resolved = resolveSubProcessArgs(content, options);
|
|
769
|
+
const sub = new SubProcessContentBuilder(this.rootMessages);
|
|
770
|
+
resolved.content(sub);
|
|
771
|
+
insertJoinGateways(sub._elements, sub._flows);
|
|
772
|
+
recomputeIncomingOutgoing(sub._elements, sub._flows);
|
|
773
|
+
const zeebeExt = {};
|
|
774
|
+
if (resolved.options?.taskDefinition) {
|
|
775
|
+
zeebeExt.taskDefinition = resolved.options.taskDefinition;
|
|
776
|
+
}
|
|
777
|
+
if (resolved.options?.ioMapping) {
|
|
778
|
+
zeebeExt.ioMapping = {
|
|
779
|
+
inputs: resolved.options.ioMapping.inputs ?? [],
|
|
780
|
+
outputs: resolved.options.ioMapping.outputs ?? [],
|
|
781
|
+
};
|
|
782
|
+
}
|
|
783
|
+
if (resolved.options?.taskHeaders) {
|
|
784
|
+
zeebeExt.taskHeaders = {
|
|
785
|
+
headers: Object.entries(resolved.options.taskHeaders).map(([key, value]) => ({
|
|
786
|
+
key,
|
|
787
|
+
value,
|
|
788
|
+
})),
|
|
789
|
+
};
|
|
790
|
+
}
|
|
791
|
+
const extensionElements = zeebeExtensionsToXmlElements(zeebeExt);
|
|
792
|
+
const adHocAttrs = {};
|
|
793
|
+
if (resolved.options?.activeElementsCollection) {
|
|
794
|
+
adHocAttrs.activeElementsCollection = resolved.options.activeElementsCollection;
|
|
795
|
+
}
|
|
796
|
+
if (resolved.options?.outputCollection) {
|
|
797
|
+
adHocAttrs.outputCollection = resolved.options.outputCollection;
|
|
798
|
+
}
|
|
799
|
+
if (resolved.options?.outputElement) {
|
|
800
|
+
adHocAttrs.outputElement = resolved.options.outputElement;
|
|
801
|
+
}
|
|
802
|
+
if (Object.keys(adHocAttrs).length > 0) {
|
|
803
|
+
extensionElements.push({
|
|
804
|
+
name: "zeebe:adHoc",
|
|
805
|
+
attributes: adHocAttrs,
|
|
806
|
+
children: [],
|
|
807
|
+
});
|
|
808
|
+
}
|
|
809
|
+
const element = makeFlowElement(id, "adHocSubProcess", {
|
|
810
|
+
name: resolved.options?.name,
|
|
811
|
+
extensionElements,
|
|
812
|
+
});
|
|
813
|
+
if (resolved.options?.modelerTemplate) {
|
|
814
|
+
element.unknownAttributes["zeebe:modelerTemplate"] = resolved.options.modelerTemplate;
|
|
815
|
+
}
|
|
816
|
+
if (resolved.options?.modelerTemplateVersion) {
|
|
817
|
+
element.unknownAttributes["zeebe:modelerTemplateVersion"] =
|
|
818
|
+
resolved.options.modelerTemplateVersion;
|
|
819
|
+
}
|
|
820
|
+
if (resolved.options?.modelerTemplateIcon) {
|
|
821
|
+
element.unknownAttributes["zeebe:modelerTemplateIcon"] = resolved.options.modelerTemplateIcon;
|
|
822
|
+
}
|
|
823
|
+
if (element.type === "adHocSubProcess") {
|
|
824
|
+
element.flowElements = sub._elements;
|
|
825
|
+
element.sequenceFlows = sub._flows;
|
|
826
|
+
element.textAnnotations = sub._textAnnotations;
|
|
827
|
+
element.associations = sub._associations;
|
|
828
|
+
if (resolved.options?.loopCharacteristics) {
|
|
829
|
+
element.loopCharacteristics = buildAdHocLoopCharacteristics(resolved.options.loopCharacteristics);
|
|
830
|
+
}
|
|
831
|
+
else if (resolved.options?.multiInstance) {
|
|
832
|
+
element.loopCharacteristics = buildMultiInstance(resolved.options.multiInstance);
|
|
833
|
+
}
|
|
834
|
+
}
|
|
835
|
+
return this.addElement(element);
|
|
836
|
+
}
|
|
837
|
+
/** Add an event sub-process. Triggered by its start event — no incoming or outgoing sequence flows. */
|
|
838
|
+
eventSubProcess(id, content, options) {
|
|
839
|
+
const resolved = resolveSubProcessArgs(content, options);
|
|
840
|
+
const sub = new SubProcessContentBuilder(this.rootMessages);
|
|
841
|
+
resolved.content(sub);
|
|
842
|
+
insertJoinGateways(sub._elements, sub._flows);
|
|
843
|
+
recomputeIncomingOutgoing(sub._elements, sub._flows);
|
|
844
|
+
const element = makeFlowElement(id, "subProcess", resolved.options);
|
|
845
|
+
if (element.type === "subProcess") {
|
|
846
|
+
element.triggeredByEvent = true;
|
|
847
|
+
element.flowElements = sub._elements;
|
|
848
|
+
element.sequenceFlows = sub._flows;
|
|
849
|
+
element.textAnnotations = sub._textAnnotations;
|
|
850
|
+
element.associations = sub._associations;
|
|
851
|
+
}
|
|
852
|
+
// Event sub-processes have no incoming/outgoing sequence flows and must not
|
|
853
|
+
// advance the branch cursor — mirrors ProcessBuilder.eventSubProcess.
|
|
854
|
+
if (this._elements.some((n) => n.id === element.id)) {
|
|
855
|
+
throw new Error(`Duplicate element ID "${element.id}"`);
|
|
856
|
+
}
|
|
857
|
+
this._elements.push(element);
|
|
858
|
+
return this;
|
|
859
|
+
}
|
|
715
860
|
/**
|
|
716
861
|
* Create a named branch from the last gateway added inside this branch.
|
|
717
862
|
*
|
|
@@ -976,6 +1121,172 @@ export class SubProcessContentBuilder {
|
|
|
976
1121
|
this.currentGatewayId = undefined;
|
|
977
1122
|
return this;
|
|
978
1123
|
}
|
|
1124
|
+
// ---- Boundary events ----
|
|
1125
|
+
/**
|
|
1126
|
+
* Add a boundary event attached to an existing activity in this sub-process.
|
|
1127
|
+
*
|
|
1128
|
+
* The boundary event is NOT connected by a sequence flow — it attaches via
|
|
1129
|
+
* `attachedToRef`. The builder cursor advances to the boundary event so
|
|
1130
|
+
* subsequent elements chain from it. Use `withBoundary()` if you want the
|
|
1131
|
+
* cursor to return to the task afterward.
|
|
1132
|
+
*/
|
|
1133
|
+
boundaryEvent(id, options) {
|
|
1134
|
+
const element = makeFlowElement(id, "boundaryEvent", options);
|
|
1135
|
+
if (element.type === "boundaryEvent") {
|
|
1136
|
+
element.attachedToRef = options.attachedTo;
|
|
1137
|
+
element.cancelActivity = options.cancelActivity;
|
|
1138
|
+
element.eventDefinitions = buildEventDefinitions(options);
|
|
1139
|
+
}
|
|
1140
|
+
// Push directly — no sequence flow, boundary events attach via attachedToRef
|
|
1141
|
+
this._elements.push(element);
|
|
1142
|
+
this.lastNodeId = element.id;
|
|
1143
|
+
return this;
|
|
1144
|
+
}
|
|
1145
|
+
/**
|
|
1146
|
+
* Attach a boundary event to the preceding task and build its outgoing path,
|
|
1147
|
+
* then restore the builder cursor to the preceding task so the main flow continues.
|
|
1148
|
+
*
|
|
1149
|
+
* @param id - ID for the boundary event element.
|
|
1150
|
+
* @param options - Boundary event options (without `attachedTo` — inferred from cursor).
|
|
1151
|
+
* @param handler - Callback that chains elements from the boundary event.
|
|
1152
|
+
*/
|
|
1153
|
+
withBoundary(id, options, handler) {
|
|
1154
|
+
const attachedTo = this.lastNodeId;
|
|
1155
|
+
if (!attachedTo) {
|
|
1156
|
+
throw new Error("withBoundary() must follow a task element inside the sub-process. Current builder position has no active task.");
|
|
1157
|
+
}
|
|
1158
|
+
const attachedEl = this._elements.find((n) => n.id === attachedTo);
|
|
1159
|
+
if (attachedEl?.type === "boundaryEvent") {
|
|
1160
|
+
throw new Error("withBoundary() cannot attach to a boundary event. It must follow a task or activity element.");
|
|
1161
|
+
}
|
|
1162
|
+
const savedLast = this.lastNodeId;
|
|
1163
|
+
const savedGateway = this.currentGatewayId;
|
|
1164
|
+
const savedOpenEnds = [...this.openBranchEnds];
|
|
1165
|
+
this.openBranchEnds = [];
|
|
1166
|
+
// Create and push the boundary event (no sequence flow)
|
|
1167
|
+
this.boundaryEvent(id, { ...options, attachedTo });
|
|
1168
|
+
// Build the boundary event's outgoing path
|
|
1169
|
+
handler(this);
|
|
1170
|
+
// Restore cursor to the task so the sub-process main flow continues
|
|
1171
|
+
this.lastNodeId = savedLast;
|
|
1172
|
+
this.currentGatewayId = savedGateway;
|
|
1173
|
+
this.openBranchEnds = savedOpenEnds;
|
|
1174
|
+
return this;
|
|
1175
|
+
}
|
|
1176
|
+
// ---- Sub-process ----
|
|
1177
|
+
/** Add a sub-process nested inside this sub-process's content. */
|
|
1178
|
+
subProcess(id, content, options) {
|
|
1179
|
+
const resolved = resolveSubProcessArgs(content, options);
|
|
1180
|
+
const sub = new SubProcessContentBuilder(this.rootMessages);
|
|
1181
|
+
resolved.content(sub);
|
|
1182
|
+
insertJoinGateways(sub._elements, sub._flows);
|
|
1183
|
+
recomputeIncomingOutgoing(sub._elements, sub._flows);
|
|
1184
|
+
const element = makeFlowElement(id, "subProcess", resolved.options);
|
|
1185
|
+
if (element.type === "subProcess") {
|
|
1186
|
+
element.flowElements = sub._elements;
|
|
1187
|
+
element.sequenceFlows = sub._flows;
|
|
1188
|
+
element.textAnnotations = sub._textAnnotations;
|
|
1189
|
+
element.associations = sub._associations;
|
|
1190
|
+
if (resolved.options?.multiInstance) {
|
|
1191
|
+
element.loopCharacteristics = buildMultiInstance(resolved.options.multiInstance);
|
|
1192
|
+
}
|
|
1193
|
+
}
|
|
1194
|
+
return this.addElement(element);
|
|
1195
|
+
}
|
|
1196
|
+
/** Add an ad-hoc sub-process nested inside this sub-process's content. */
|
|
1197
|
+
adHocSubProcess(id, content, options) {
|
|
1198
|
+
const resolved = resolveSubProcessArgs(content, options);
|
|
1199
|
+
const sub = new SubProcessContentBuilder(this.rootMessages);
|
|
1200
|
+
resolved.content(sub);
|
|
1201
|
+
insertJoinGateways(sub._elements, sub._flows);
|
|
1202
|
+
recomputeIncomingOutgoing(sub._elements, sub._flows);
|
|
1203
|
+
const zeebeExt = {};
|
|
1204
|
+
if (resolved.options?.taskDefinition) {
|
|
1205
|
+
zeebeExt.taskDefinition = resolved.options.taskDefinition;
|
|
1206
|
+
}
|
|
1207
|
+
if (resolved.options?.ioMapping) {
|
|
1208
|
+
zeebeExt.ioMapping = {
|
|
1209
|
+
inputs: resolved.options.ioMapping.inputs ?? [],
|
|
1210
|
+
outputs: resolved.options.ioMapping.outputs ?? [],
|
|
1211
|
+
};
|
|
1212
|
+
}
|
|
1213
|
+
if (resolved.options?.taskHeaders) {
|
|
1214
|
+
zeebeExt.taskHeaders = {
|
|
1215
|
+
headers: Object.entries(resolved.options.taskHeaders).map(([key, value]) => ({
|
|
1216
|
+
key,
|
|
1217
|
+
value,
|
|
1218
|
+
})),
|
|
1219
|
+
};
|
|
1220
|
+
}
|
|
1221
|
+
const extensionElements = zeebeExtensionsToXmlElements(zeebeExt);
|
|
1222
|
+
const adHocAttrs = {};
|
|
1223
|
+
if (resolved.options?.activeElementsCollection) {
|
|
1224
|
+
adHocAttrs.activeElementsCollection = resolved.options.activeElementsCollection;
|
|
1225
|
+
}
|
|
1226
|
+
if (resolved.options?.outputCollection) {
|
|
1227
|
+
adHocAttrs.outputCollection = resolved.options.outputCollection;
|
|
1228
|
+
}
|
|
1229
|
+
if (resolved.options?.outputElement) {
|
|
1230
|
+
adHocAttrs.outputElement = resolved.options.outputElement;
|
|
1231
|
+
}
|
|
1232
|
+
if (Object.keys(adHocAttrs).length > 0) {
|
|
1233
|
+
extensionElements.push({
|
|
1234
|
+
name: "zeebe:adHoc",
|
|
1235
|
+
attributes: adHocAttrs,
|
|
1236
|
+
children: [],
|
|
1237
|
+
});
|
|
1238
|
+
}
|
|
1239
|
+
const element = makeFlowElement(id, "adHocSubProcess", {
|
|
1240
|
+
name: resolved.options?.name,
|
|
1241
|
+
extensionElements,
|
|
1242
|
+
});
|
|
1243
|
+
if (resolved.options?.modelerTemplate) {
|
|
1244
|
+
element.unknownAttributes["zeebe:modelerTemplate"] = resolved.options.modelerTemplate;
|
|
1245
|
+
}
|
|
1246
|
+
if (resolved.options?.modelerTemplateVersion) {
|
|
1247
|
+
element.unknownAttributes["zeebe:modelerTemplateVersion"] =
|
|
1248
|
+
resolved.options.modelerTemplateVersion;
|
|
1249
|
+
}
|
|
1250
|
+
if (resolved.options?.modelerTemplateIcon) {
|
|
1251
|
+
element.unknownAttributes["zeebe:modelerTemplateIcon"] = resolved.options.modelerTemplateIcon;
|
|
1252
|
+
}
|
|
1253
|
+
if (element.type === "adHocSubProcess") {
|
|
1254
|
+
element.flowElements = sub._elements;
|
|
1255
|
+
element.sequenceFlows = sub._flows;
|
|
1256
|
+
element.textAnnotations = sub._textAnnotations;
|
|
1257
|
+
element.associations = sub._associations;
|
|
1258
|
+
if (resolved.options?.loopCharacteristics) {
|
|
1259
|
+
element.loopCharacteristics = buildAdHocLoopCharacteristics(resolved.options.loopCharacteristics);
|
|
1260
|
+
}
|
|
1261
|
+
else if (resolved.options?.multiInstance) {
|
|
1262
|
+
element.loopCharacteristics = buildMultiInstance(resolved.options.multiInstance);
|
|
1263
|
+
}
|
|
1264
|
+
}
|
|
1265
|
+
return this.addElement(element);
|
|
1266
|
+
}
|
|
1267
|
+
/** Add an event sub-process. Triggered by its start event — no incoming or outgoing sequence flows. */
|
|
1268
|
+
eventSubProcess(id, content, options) {
|
|
1269
|
+
const resolved = resolveSubProcessArgs(content, options);
|
|
1270
|
+
const sub = new SubProcessContentBuilder(this.rootMessages);
|
|
1271
|
+
resolved.content(sub);
|
|
1272
|
+
insertJoinGateways(sub._elements, sub._flows);
|
|
1273
|
+
recomputeIncomingOutgoing(sub._elements, sub._flows);
|
|
1274
|
+
const element = makeFlowElement(id, "subProcess", resolved.options);
|
|
1275
|
+
if (element.type === "subProcess") {
|
|
1276
|
+
element.triggeredByEvent = true;
|
|
1277
|
+
element.flowElements = sub._elements;
|
|
1278
|
+
element.sequenceFlows = sub._flows;
|
|
1279
|
+
element.textAnnotations = sub._textAnnotations;
|
|
1280
|
+
element.associations = sub._associations;
|
|
1281
|
+
}
|
|
1282
|
+
// Event sub-processes have no incoming/outgoing sequence flows and must not
|
|
1283
|
+
// advance the cursor — mirrors ProcessBuilder.eventSubProcess.
|
|
1284
|
+
if (this._elements.some((n) => n.id === element.id)) {
|
|
1285
|
+
throw new Error(`Duplicate element ID "${element.id}" in sub-process`);
|
|
1286
|
+
}
|
|
1287
|
+
this._elements.push(element);
|
|
1288
|
+
return this;
|
|
1289
|
+
}
|
|
979
1290
|
}
|
|
980
1291
|
// ---------------------------------------------------------------------------
|
|
981
1292
|
// Process builder (top-level entry point)
|
|
@@ -1374,36 +1685,40 @@ export class ProcessBuilder {
|
|
|
1374
1685
|
// ---- Sub-processes ----
|
|
1375
1686
|
/** Add an ad-hoc sub-process with optional AI agent or multi-instance configuration. */
|
|
1376
1687
|
adHocSubProcess(id, content, options) {
|
|
1688
|
+
const resolved = resolveSubProcessArgs(content, options);
|
|
1377
1689
|
const sub = new SubProcessContentBuilder(this.rootMessages);
|
|
1378
|
-
content(sub);
|
|
1690
|
+
resolved.content(sub);
|
|
1379
1691
|
insertJoinGateways(sub._elements, sub._flows);
|
|
1380
1692
|
recomputeIncomingOutgoing(sub._elements, sub._flows);
|
|
1381
1693
|
const zeebeExt = {};
|
|
1382
|
-
if (options?.taskDefinition) {
|
|
1383
|
-
zeebeExt.taskDefinition = options.taskDefinition;
|
|
1694
|
+
if (resolved.options?.taskDefinition) {
|
|
1695
|
+
zeebeExt.taskDefinition = resolved.options.taskDefinition;
|
|
1384
1696
|
}
|
|
1385
|
-
if (options?.ioMapping) {
|
|
1697
|
+
if (resolved.options?.ioMapping) {
|
|
1386
1698
|
zeebeExt.ioMapping = {
|
|
1387
|
-
inputs: options.ioMapping.inputs ?? [],
|
|
1388
|
-
outputs: options.ioMapping.outputs ?? [],
|
|
1699
|
+
inputs: resolved.options.ioMapping.inputs ?? [],
|
|
1700
|
+
outputs: resolved.options.ioMapping.outputs ?? [],
|
|
1389
1701
|
};
|
|
1390
1702
|
}
|
|
1391
|
-
if (options?.taskHeaders) {
|
|
1703
|
+
if (resolved.options?.taskHeaders) {
|
|
1392
1704
|
zeebeExt.taskHeaders = {
|
|
1393
|
-
headers: Object.entries(options.taskHeaders).map(([key, value]) => ({
|
|
1705
|
+
headers: Object.entries(resolved.options.taskHeaders).map(([key, value]) => ({
|
|
1706
|
+
key,
|
|
1707
|
+
value,
|
|
1708
|
+
})),
|
|
1394
1709
|
};
|
|
1395
1710
|
}
|
|
1396
1711
|
const extensionElements = zeebeExtensionsToXmlElements(zeebeExt);
|
|
1397
1712
|
// zeebe:adHoc element
|
|
1398
1713
|
const adHocAttrs = {};
|
|
1399
|
-
if (options?.activeElementsCollection) {
|
|
1400
|
-
adHocAttrs.activeElementsCollection = options.activeElementsCollection;
|
|
1714
|
+
if (resolved.options?.activeElementsCollection) {
|
|
1715
|
+
adHocAttrs.activeElementsCollection = resolved.options.activeElementsCollection;
|
|
1401
1716
|
}
|
|
1402
|
-
if (options?.outputCollection) {
|
|
1403
|
-
adHocAttrs.outputCollection = options.outputCollection;
|
|
1717
|
+
if (resolved.options?.outputCollection) {
|
|
1718
|
+
adHocAttrs.outputCollection = resolved.options.outputCollection;
|
|
1404
1719
|
}
|
|
1405
|
-
if (options?.outputElement) {
|
|
1406
|
-
adHocAttrs.outputElement = options.outputElement;
|
|
1720
|
+
if (resolved.options?.outputElement) {
|
|
1721
|
+
adHocAttrs.outputElement = resolved.options.outputElement;
|
|
1407
1722
|
}
|
|
1408
1723
|
if (Object.keys(adHocAttrs).length > 0) {
|
|
1409
1724
|
extensionElements.push({
|
|
@@ -1413,28 +1728,29 @@ export class ProcessBuilder {
|
|
|
1413
1728
|
});
|
|
1414
1729
|
}
|
|
1415
1730
|
const element = makeFlowElement(id, "adHocSubProcess", {
|
|
1416
|
-
name: options?.name,
|
|
1731
|
+
name: resolved.options?.name,
|
|
1417
1732
|
extensionElements,
|
|
1418
1733
|
});
|
|
1419
|
-
if (options?.modelerTemplate) {
|
|
1420
|
-
element.unknownAttributes["zeebe:modelerTemplate"] = options.modelerTemplate;
|
|
1734
|
+
if (resolved.options?.modelerTemplate) {
|
|
1735
|
+
element.unknownAttributes["zeebe:modelerTemplate"] = resolved.options.modelerTemplate;
|
|
1421
1736
|
}
|
|
1422
|
-
if (options?.modelerTemplateVersion) {
|
|
1423
|
-
element.unknownAttributes["zeebe:modelerTemplateVersion"] =
|
|
1737
|
+
if (resolved.options?.modelerTemplateVersion) {
|
|
1738
|
+
element.unknownAttributes["zeebe:modelerTemplateVersion"] =
|
|
1739
|
+
resolved.options.modelerTemplateVersion;
|
|
1424
1740
|
}
|
|
1425
|
-
if (options?.modelerTemplateIcon) {
|
|
1426
|
-
element.unknownAttributes["zeebe:modelerTemplateIcon"] = options.modelerTemplateIcon;
|
|
1741
|
+
if (resolved.options?.modelerTemplateIcon) {
|
|
1742
|
+
element.unknownAttributes["zeebe:modelerTemplateIcon"] = resolved.options.modelerTemplateIcon;
|
|
1427
1743
|
}
|
|
1428
1744
|
if (element.type === "adHocSubProcess") {
|
|
1429
1745
|
element.flowElements = sub._elements;
|
|
1430
1746
|
element.sequenceFlows = sub._flows;
|
|
1431
1747
|
element.textAnnotations = sub._textAnnotations;
|
|
1432
1748
|
element.associations = sub._associations;
|
|
1433
|
-
if (options?.loopCharacteristics) {
|
|
1434
|
-
element.loopCharacteristics = buildAdHocLoopCharacteristics(options.loopCharacteristics);
|
|
1749
|
+
if (resolved.options?.loopCharacteristics) {
|
|
1750
|
+
element.loopCharacteristics = buildAdHocLoopCharacteristics(resolved.options.loopCharacteristics);
|
|
1435
1751
|
}
|
|
1436
|
-
else if (options?.multiInstance) {
|
|
1437
|
-
element.loopCharacteristics = buildMultiInstance(options.multiInstance);
|
|
1752
|
+
else if (resolved.options?.multiInstance) {
|
|
1753
|
+
element.loopCharacteristics = buildMultiInstance(resolved.options.multiInstance);
|
|
1438
1754
|
}
|
|
1439
1755
|
}
|
|
1440
1756
|
this.addFlowElement(element);
|
|
@@ -1442,18 +1758,19 @@ export class ProcessBuilder {
|
|
|
1442
1758
|
}
|
|
1443
1759
|
/** Add a sub-process (aspirational). */
|
|
1444
1760
|
subProcess(id, content, options) {
|
|
1761
|
+
const resolved = resolveSubProcessArgs(content, options);
|
|
1445
1762
|
const sub = new SubProcessContentBuilder(this.rootMessages);
|
|
1446
|
-
content(sub);
|
|
1763
|
+
resolved.content(sub);
|
|
1447
1764
|
insertJoinGateways(sub._elements, sub._flows);
|
|
1448
1765
|
recomputeIncomingOutgoing(sub._elements, sub._flows);
|
|
1449
|
-
const element = makeFlowElement(id, "subProcess", options);
|
|
1766
|
+
const element = makeFlowElement(id, "subProcess", resolved.options);
|
|
1450
1767
|
if (element.type === "subProcess") {
|
|
1451
1768
|
element.flowElements = sub._elements;
|
|
1452
1769
|
element.sequenceFlows = sub._flows;
|
|
1453
1770
|
element.textAnnotations = sub._textAnnotations;
|
|
1454
1771
|
element.associations = sub._associations;
|
|
1455
|
-
if (options?.multiInstance) {
|
|
1456
|
-
element.loopCharacteristics = buildMultiInstance(options.multiInstance);
|
|
1772
|
+
if (resolved.options?.multiInstance) {
|
|
1773
|
+
element.loopCharacteristics = buildMultiInstance(resolved.options.multiInstance);
|
|
1457
1774
|
}
|
|
1458
1775
|
}
|
|
1459
1776
|
this.addFlowElement(element);
|
|
@@ -1461,11 +1778,12 @@ export class ProcessBuilder {
|
|
|
1461
1778
|
}
|
|
1462
1779
|
/** Add an event sub-process. Triggered by its start event — no incoming or outgoing sequence flows. */
|
|
1463
1780
|
eventSubProcess(id, content, options) {
|
|
1781
|
+
const resolved = resolveSubProcessArgs(content, options);
|
|
1464
1782
|
const sub = new SubProcessContentBuilder(this.rootMessages);
|
|
1465
|
-
content(sub);
|
|
1783
|
+
resolved.content(sub);
|
|
1466
1784
|
insertJoinGateways(sub._elements, sub._flows);
|
|
1467
1785
|
recomputeIncomingOutgoing(sub._elements, sub._flows);
|
|
1468
|
-
const element = makeFlowElement(id, "subProcess", options);
|
|
1786
|
+
const element = makeFlowElement(id, "subProcess", resolved.options);
|
|
1469
1787
|
if (element.type === "subProcess") {
|
|
1470
1788
|
element.triggeredByEvent = true;
|
|
1471
1789
|
element.flowElements = sub._elements;
|
|
@@ -1543,6 +1861,7 @@ export class ProcessBuilder {
|
|
|
1543
1861
|
sequenceFlows: this.sequenceFlows,
|
|
1544
1862
|
textAnnotations: this._textAnnotations,
|
|
1545
1863
|
associations: this._associations,
|
|
1864
|
+
groups: [],
|
|
1546
1865
|
unknownAttributes: {},
|
|
1547
1866
|
};
|
|
1548
1867
|
const defs = {
|
|
@@ -5,7 +5,7 @@ import type { XmlElement } from "../types/xml-element.js";
|
|
|
5
5
|
* exhaustive `switch` statements and type-narrowing with the type guard helpers
|
|
6
6
|
* exported from `@bpmnkit/core`.
|
|
7
7
|
*/
|
|
8
|
-
export type BpmnElementType = "startEvent" | "endEvent" | "intermediateThrowEvent" | "intermediateCatchEvent" | "boundaryEvent" | "task" | "serviceTask" | "scriptTask" | "userTask" | "sendTask" | "receiveTask" | "businessRuleTask" | "manualTask" | "callActivity" | "exclusiveGateway" | "parallelGateway" | "inclusiveGateway" | "eventBasedGateway" | "complexGateway" | "subProcess" | "adHocSubProcess" | "eventSubProcess" | "transaction";
|
|
8
|
+
export type BpmnElementType = "startEvent" | "endEvent" | "intermediateThrowEvent" | "intermediateCatchEvent" | "boundaryEvent" | "task" | "serviceTask" | "scriptTask" | "userTask" | "sendTask" | "receiveTask" | "businessRuleTask" | "manualTask" | "callActivity" | "exclusiveGateway" | "parallelGateway" | "inclusiveGateway" | "eventBasedGateway" | "complexGateway" | "subProcess" | "adHocSubProcess" | "eventSubProcess" | "transaction" | "dataObject" | "dataObjectReference" | "dataStoreReference";
|
|
9
9
|
/** Axis-aligned bounding box used by BPMN diagram interchange (BPMNDi). */
|
|
10
10
|
export interface BpmnBounds {
|
|
11
11
|
x: number;
|
|
@@ -150,6 +150,26 @@ export interface BpmnCallActivity extends BpmnFlowNodeBase {
|
|
|
150
150
|
type: "callActivity";
|
|
151
151
|
loopCharacteristics?: BpmnMultiInstanceLoopCharacteristics;
|
|
152
152
|
}
|
|
153
|
+
/** A data object — a piece of information flowing through the process. */
|
|
154
|
+
export interface BpmnDataObject extends BpmnFlowNodeBase {
|
|
155
|
+
type: "dataObject";
|
|
156
|
+
/** When true, represents a collection of items. */
|
|
157
|
+
isCollection?: boolean;
|
|
158
|
+
}
|
|
159
|
+
/** A visual reference to a {@link BpmnDataObject} (the shape drawn on the canvas). */
|
|
160
|
+
export interface BpmnDataObjectReference extends BpmnFlowNodeBase {
|
|
161
|
+
type: "dataObjectReference";
|
|
162
|
+
/** Id of the referenced `dataObject`. */
|
|
163
|
+
dataObjectRef?: string;
|
|
164
|
+
/** When true, drawn with the collection (parallel-bars) marker. */
|
|
165
|
+
isCollection?: boolean;
|
|
166
|
+
}
|
|
167
|
+
/** A visual reference to a data store (drawn as a cylinder). */
|
|
168
|
+
export interface BpmnDataStoreReference extends BpmnFlowNodeBase {
|
|
169
|
+
type: "dataStoreReference";
|
|
170
|
+
/** Id of the referenced `dataStore`. */
|
|
171
|
+
dataStoreRef?: string;
|
|
172
|
+
}
|
|
153
173
|
export interface BpmnSendTask extends BpmnFlowNodeBase {
|
|
154
174
|
type: "sendTask";
|
|
155
175
|
messageRef?: string;
|
|
@@ -167,6 +187,7 @@ export interface BpmnAdHocSubProcess extends BpmnFlowNodeBase {
|
|
|
167
187
|
sequenceFlows: BpmnSequenceFlow[];
|
|
168
188
|
textAnnotations: BpmnTextAnnotation[];
|
|
169
189
|
associations: BpmnAssociation[];
|
|
190
|
+
groups: BpmnGroup[];
|
|
170
191
|
}
|
|
171
192
|
export interface BpmnSubProcess extends BpmnFlowNodeBase {
|
|
172
193
|
type: "subProcess";
|
|
@@ -176,6 +197,7 @@ export interface BpmnSubProcess extends BpmnFlowNodeBase {
|
|
|
176
197
|
sequenceFlows: BpmnSequenceFlow[];
|
|
177
198
|
textAnnotations: BpmnTextAnnotation[];
|
|
178
199
|
associations: BpmnAssociation[];
|
|
200
|
+
groups: BpmnGroup[];
|
|
179
201
|
}
|
|
180
202
|
export interface BpmnEventSubProcess extends BpmnFlowNodeBase {
|
|
181
203
|
type: "eventSubProcess";
|
|
@@ -183,6 +205,7 @@ export interface BpmnEventSubProcess extends BpmnFlowNodeBase {
|
|
|
183
205
|
sequenceFlows: BpmnSequenceFlow[];
|
|
184
206
|
textAnnotations: BpmnTextAnnotation[];
|
|
185
207
|
associations: BpmnAssociation[];
|
|
208
|
+
groups: BpmnGroup[];
|
|
186
209
|
}
|
|
187
210
|
export interface BpmnExclusiveGateway extends BpmnFlowNodeBase {
|
|
188
211
|
type: "exclusiveGateway";
|
|
@@ -217,6 +240,7 @@ export interface BpmnTransaction extends BpmnFlowNodeBase {
|
|
|
217
240
|
sequenceFlows: BpmnSequenceFlow[];
|
|
218
241
|
textAnnotations: BpmnTextAnnotation[];
|
|
219
242
|
associations: BpmnAssociation[];
|
|
243
|
+
groups: BpmnGroup[];
|
|
220
244
|
}
|
|
221
245
|
/**
|
|
222
246
|
* Discriminated union of every BPMN flow node that can appear inside a
|
|
@@ -233,7 +257,7 @@ export interface BpmnTransaction extends BpmnFlowNodeBase {
|
|
|
233
257
|
* }
|
|
234
258
|
* ```
|
|
235
259
|
*/
|
|
236
|
-
export type BpmnFlowElement = BpmnStartEvent | BpmnEndEvent | BpmnIntermediateCatchEvent | BpmnIntermediateThrowEvent | BpmnBoundaryEvent | BpmnTask | BpmnServiceTask | BpmnScriptTask | BpmnUserTask | BpmnSendTask | BpmnReceiveTask | BpmnBusinessRuleTask | BpmnManualTask | BpmnCallActivity | BpmnSubProcess | BpmnAdHocSubProcess | BpmnEventSubProcess | BpmnTransaction | BpmnExclusiveGateway | BpmnParallelGateway | BpmnInclusiveGateway | BpmnEventBasedGateway | BpmnComplexGateway;
|
|
260
|
+
export type BpmnFlowElement = BpmnStartEvent | BpmnEndEvent | BpmnIntermediateCatchEvent | BpmnIntermediateThrowEvent | BpmnBoundaryEvent | BpmnTask | BpmnServiceTask | BpmnScriptTask | BpmnUserTask | BpmnSendTask | BpmnReceiveTask | BpmnBusinessRuleTask | BpmnManualTask | BpmnCallActivity | BpmnSubProcess | BpmnAdHocSubProcess | BpmnEventSubProcess | BpmnTransaction | BpmnExclusiveGateway | BpmnParallelGateway | BpmnInclusiveGateway | BpmnEventBasedGateway | BpmnComplexGateway | BpmnDataObject | BpmnDataObjectReference | BpmnDataStoreReference;
|
|
237
261
|
/** Backward-compat alias used by the layout module. */
|
|
238
262
|
export type BpmnFlowNode = BpmnFlowElement;
|
|
239
263
|
/**
|
|
@@ -264,6 +288,13 @@ export interface BpmnAssociation {
|
|
|
264
288
|
associationDirection?: string;
|
|
265
289
|
unknownAttributes: Record<string, string>;
|
|
266
290
|
}
|
|
291
|
+
/** A group artifact — a dashed rounded rectangle visually grouping elements. */
|
|
292
|
+
export interface BpmnGroup {
|
|
293
|
+
id: string;
|
|
294
|
+
/** Id of the `categoryValue` supplying the group's label, if any. */
|
|
295
|
+
categoryValueRef?: string;
|
|
296
|
+
unknownAttributes: Record<string, string>;
|
|
297
|
+
}
|
|
267
298
|
/** A swim lane within a pool (organises flow nodes visually). */
|
|
268
299
|
export interface BpmnLane {
|
|
269
300
|
id: string;
|
|
@@ -294,6 +325,7 @@ export interface BpmnProcess {
|
|
|
294
325
|
sequenceFlows: BpmnSequenceFlow[];
|
|
295
326
|
textAnnotations: BpmnTextAnnotation[];
|
|
296
327
|
associations: BpmnAssociation[];
|
|
328
|
+
groups: BpmnGroup[];
|
|
297
329
|
laneSet?: BpmnLaneSet;
|
|
298
330
|
unknownAttributes: Record<string, string>;
|
|
299
331
|
}
|
|
@@ -319,6 +351,7 @@ export interface BpmnCollaboration {
|
|
|
319
351
|
messageFlows: BpmnMessageFlow[];
|
|
320
352
|
textAnnotations: BpmnTextAnnotation[];
|
|
321
353
|
associations: BpmnAssociation[];
|
|
354
|
+
groups: BpmnGroup[];
|
|
322
355
|
extensionElements: XmlElement[];
|
|
323
356
|
unknownAttributes: Record<string, string>;
|
|
324
357
|
}
|