@bpmnkit/core 0.0.26 → 0.1.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/dist/bpmn/auto-layout.js +71 -139
- package/dist/bpmn/bpmn-builder.d.ts +30 -0
- package/dist/bpmn/bpmn-builder.js +343 -31
- package/dist/bpmn/di-check.d.ts +14 -0
- package/dist/bpmn/di-check.js +51 -0
- package/dist/bpmn/svg.js +14 -1
- package/dist/index.d.ts +2 -0
- package/dist/index.js +1 -0
- 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 -478
- package/dist/layout/types.d.ts +2 -2
- package/dist/layout/types.js +6 -2
- 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 -77
|
@@ -333,6 +333,31 @@ function makeInclusiveGatewayEl(id, options) {
|
|
|
333
333
|
}
|
|
334
334
|
return el;
|
|
335
335
|
}
|
|
336
|
+
/**
|
|
337
|
+
* `subProcess`/`eventSubProcess`/`adHocSubProcess` all take a required content
|
|
338
|
+
* callback as their 2nd argument and an optional options object as their 3rd.
|
|
339
|
+
* That shape isn't demonstrated anywhere in this SDK's docs/examples, and
|
|
340
|
+
* callers that only see the parameter *names* (not enforced types — e.g.
|
|
341
|
+
* generated code run without type-checking) sometimes guess the common
|
|
342
|
+
* "options before callback" order instead. Detect that by runtime type and
|
|
343
|
+
* swap, so a reversed call still succeeds instead of throwing on `content`
|
|
344
|
+
* not being callable.
|
|
345
|
+
*/
|
|
346
|
+
function resolveSubProcessArgs(content, options) {
|
|
347
|
+
if (typeof content === "function") {
|
|
348
|
+
return {
|
|
349
|
+
content: content,
|
|
350
|
+
options: options,
|
|
351
|
+
};
|
|
352
|
+
}
|
|
353
|
+
if (typeof options === "function") {
|
|
354
|
+
return {
|
|
355
|
+
content: options,
|
|
356
|
+
options: content,
|
|
357
|
+
};
|
|
358
|
+
}
|
|
359
|
+
throw new TypeError("subProcess() requires a content callback function");
|
|
360
|
+
}
|
|
336
361
|
// ---------------------------------------------------------------------------
|
|
337
362
|
// Shared graph helpers — used by ProcessBuilder and SubProcessContentBuilder
|
|
338
363
|
// ---------------------------------------------------------------------------
|
|
@@ -712,6 +737,120 @@ export class BranchBuilder {
|
|
|
712
737
|
this.openBranchEnds = savedOpenEnds;
|
|
713
738
|
return this;
|
|
714
739
|
}
|
|
740
|
+
// ---- Sub-process ----
|
|
741
|
+
/** Add a sub-process (mirrors `ProcessBuilder.subProcess`). */
|
|
742
|
+
subProcess(id, content, options) {
|
|
743
|
+
const resolved = resolveSubProcessArgs(content, options);
|
|
744
|
+
const sub = new SubProcessContentBuilder(this.rootMessages);
|
|
745
|
+
resolved.content(sub);
|
|
746
|
+
insertJoinGateways(sub._elements, sub._flows);
|
|
747
|
+
recomputeIncomingOutgoing(sub._elements, sub._flows);
|
|
748
|
+
const element = makeFlowElement(id, "subProcess", resolved.options);
|
|
749
|
+
if (element.type === "subProcess") {
|
|
750
|
+
element.flowElements = sub._elements;
|
|
751
|
+
element.sequenceFlows = sub._flows;
|
|
752
|
+
element.textAnnotations = sub._textAnnotations;
|
|
753
|
+
element.associations = sub._associations;
|
|
754
|
+
if (resolved.options?.multiInstance) {
|
|
755
|
+
element.loopCharacteristics = buildMultiInstance(resolved.options.multiInstance);
|
|
756
|
+
}
|
|
757
|
+
}
|
|
758
|
+
return this.addElement(element);
|
|
759
|
+
}
|
|
760
|
+
/** Add an ad-hoc sub-process (mirrors `ProcessBuilder.adHocSubProcess`). */
|
|
761
|
+
adHocSubProcess(id, content, options) {
|
|
762
|
+
const resolved = resolveSubProcessArgs(content, options);
|
|
763
|
+
const sub = new SubProcessContentBuilder(this.rootMessages);
|
|
764
|
+
resolved.content(sub);
|
|
765
|
+
insertJoinGateways(sub._elements, sub._flows);
|
|
766
|
+
recomputeIncomingOutgoing(sub._elements, sub._flows);
|
|
767
|
+
const zeebeExt = {};
|
|
768
|
+
if (resolved.options?.taskDefinition) {
|
|
769
|
+
zeebeExt.taskDefinition = resolved.options.taskDefinition;
|
|
770
|
+
}
|
|
771
|
+
if (resolved.options?.ioMapping) {
|
|
772
|
+
zeebeExt.ioMapping = {
|
|
773
|
+
inputs: resolved.options.ioMapping.inputs ?? [],
|
|
774
|
+
outputs: resolved.options.ioMapping.outputs ?? [],
|
|
775
|
+
};
|
|
776
|
+
}
|
|
777
|
+
if (resolved.options?.taskHeaders) {
|
|
778
|
+
zeebeExt.taskHeaders = {
|
|
779
|
+
headers: Object.entries(resolved.options.taskHeaders).map(([key, value]) => ({
|
|
780
|
+
key,
|
|
781
|
+
value,
|
|
782
|
+
})),
|
|
783
|
+
};
|
|
784
|
+
}
|
|
785
|
+
const extensionElements = zeebeExtensionsToXmlElements(zeebeExt);
|
|
786
|
+
const adHocAttrs = {};
|
|
787
|
+
if (resolved.options?.activeElementsCollection) {
|
|
788
|
+
adHocAttrs.activeElementsCollection = resolved.options.activeElementsCollection;
|
|
789
|
+
}
|
|
790
|
+
if (resolved.options?.outputCollection) {
|
|
791
|
+
adHocAttrs.outputCollection = resolved.options.outputCollection;
|
|
792
|
+
}
|
|
793
|
+
if (resolved.options?.outputElement) {
|
|
794
|
+
adHocAttrs.outputElement = resolved.options.outputElement;
|
|
795
|
+
}
|
|
796
|
+
if (Object.keys(adHocAttrs).length > 0) {
|
|
797
|
+
extensionElements.push({
|
|
798
|
+
name: "zeebe:adHoc",
|
|
799
|
+
attributes: adHocAttrs,
|
|
800
|
+
children: [],
|
|
801
|
+
});
|
|
802
|
+
}
|
|
803
|
+
const element = makeFlowElement(id, "adHocSubProcess", {
|
|
804
|
+
name: resolved.options?.name,
|
|
805
|
+
extensionElements,
|
|
806
|
+
});
|
|
807
|
+
if (resolved.options?.modelerTemplate) {
|
|
808
|
+
element.unknownAttributes["zeebe:modelerTemplate"] = resolved.options.modelerTemplate;
|
|
809
|
+
}
|
|
810
|
+
if (resolved.options?.modelerTemplateVersion) {
|
|
811
|
+
element.unknownAttributes["zeebe:modelerTemplateVersion"] =
|
|
812
|
+
resolved.options.modelerTemplateVersion;
|
|
813
|
+
}
|
|
814
|
+
if (resolved.options?.modelerTemplateIcon) {
|
|
815
|
+
element.unknownAttributes["zeebe:modelerTemplateIcon"] = resolved.options.modelerTemplateIcon;
|
|
816
|
+
}
|
|
817
|
+
if (element.type === "adHocSubProcess") {
|
|
818
|
+
element.flowElements = sub._elements;
|
|
819
|
+
element.sequenceFlows = sub._flows;
|
|
820
|
+
element.textAnnotations = sub._textAnnotations;
|
|
821
|
+
element.associations = sub._associations;
|
|
822
|
+
if (resolved.options?.loopCharacteristics) {
|
|
823
|
+
element.loopCharacteristics = buildAdHocLoopCharacteristics(resolved.options.loopCharacteristics);
|
|
824
|
+
}
|
|
825
|
+
else if (resolved.options?.multiInstance) {
|
|
826
|
+
element.loopCharacteristics = buildMultiInstance(resolved.options.multiInstance);
|
|
827
|
+
}
|
|
828
|
+
}
|
|
829
|
+
return this.addElement(element);
|
|
830
|
+
}
|
|
831
|
+
/** Add an event sub-process. Triggered by its start event — no incoming or outgoing sequence flows. */
|
|
832
|
+
eventSubProcess(id, content, options) {
|
|
833
|
+
const resolved = resolveSubProcessArgs(content, options);
|
|
834
|
+
const sub = new SubProcessContentBuilder(this.rootMessages);
|
|
835
|
+
resolved.content(sub);
|
|
836
|
+
insertJoinGateways(sub._elements, sub._flows);
|
|
837
|
+
recomputeIncomingOutgoing(sub._elements, sub._flows);
|
|
838
|
+
const element = makeFlowElement(id, "subProcess", resolved.options);
|
|
839
|
+
if (element.type === "subProcess") {
|
|
840
|
+
element.triggeredByEvent = true;
|
|
841
|
+
element.flowElements = sub._elements;
|
|
842
|
+
element.sequenceFlows = sub._flows;
|
|
843
|
+
element.textAnnotations = sub._textAnnotations;
|
|
844
|
+
element.associations = sub._associations;
|
|
845
|
+
}
|
|
846
|
+
// Event sub-processes have no incoming/outgoing sequence flows and must not
|
|
847
|
+
// advance the branch cursor — mirrors ProcessBuilder.eventSubProcess.
|
|
848
|
+
if (this._elements.some((n) => n.id === element.id)) {
|
|
849
|
+
throw new Error(`Duplicate element ID "${element.id}"`);
|
|
850
|
+
}
|
|
851
|
+
this._elements.push(element);
|
|
852
|
+
return this;
|
|
853
|
+
}
|
|
715
854
|
/**
|
|
716
855
|
* Create a named branch from the last gateway added inside this branch.
|
|
717
856
|
*
|
|
@@ -976,6 +1115,172 @@ export class SubProcessContentBuilder {
|
|
|
976
1115
|
this.currentGatewayId = undefined;
|
|
977
1116
|
return this;
|
|
978
1117
|
}
|
|
1118
|
+
// ---- Boundary events ----
|
|
1119
|
+
/**
|
|
1120
|
+
* Add a boundary event attached to an existing activity in this sub-process.
|
|
1121
|
+
*
|
|
1122
|
+
* The boundary event is NOT connected by a sequence flow — it attaches via
|
|
1123
|
+
* `attachedToRef`. The builder cursor advances to the boundary event so
|
|
1124
|
+
* subsequent elements chain from it. Use `withBoundary()` if you want the
|
|
1125
|
+
* cursor to return to the task afterward.
|
|
1126
|
+
*/
|
|
1127
|
+
boundaryEvent(id, options) {
|
|
1128
|
+
const element = makeFlowElement(id, "boundaryEvent", options);
|
|
1129
|
+
if (element.type === "boundaryEvent") {
|
|
1130
|
+
element.attachedToRef = options.attachedTo;
|
|
1131
|
+
element.cancelActivity = options.cancelActivity;
|
|
1132
|
+
element.eventDefinitions = buildEventDefinitions(options);
|
|
1133
|
+
}
|
|
1134
|
+
// Push directly — no sequence flow, boundary events attach via attachedToRef
|
|
1135
|
+
this._elements.push(element);
|
|
1136
|
+
this.lastNodeId = element.id;
|
|
1137
|
+
return this;
|
|
1138
|
+
}
|
|
1139
|
+
/**
|
|
1140
|
+
* Attach a boundary event to the preceding task and build its outgoing path,
|
|
1141
|
+
* then restore the builder cursor to the preceding task so the main flow continues.
|
|
1142
|
+
*
|
|
1143
|
+
* @param id - ID for the boundary event element.
|
|
1144
|
+
* @param options - Boundary event options (without `attachedTo` — inferred from cursor).
|
|
1145
|
+
* @param handler - Callback that chains elements from the boundary event.
|
|
1146
|
+
*/
|
|
1147
|
+
withBoundary(id, options, handler) {
|
|
1148
|
+
const attachedTo = this.lastNodeId;
|
|
1149
|
+
if (!attachedTo) {
|
|
1150
|
+
throw new Error("withBoundary() must follow a task element inside the sub-process. Current builder position has no active task.");
|
|
1151
|
+
}
|
|
1152
|
+
const attachedEl = this._elements.find((n) => n.id === attachedTo);
|
|
1153
|
+
if (attachedEl?.type === "boundaryEvent") {
|
|
1154
|
+
throw new Error("withBoundary() cannot attach to a boundary event. It must follow a task or activity element.");
|
|
1155
|
+
}
|
|
1156
|
+
const savedLast = this.lastNodeId;
|
|
1157
|
+
const savedGateway = this.currentGatewayId;
|
|
1158
|
+
const savedOpenEnds = [...this.openBranchEnds];
|
|
1159
|
+
this.openBranchEnds = [];
|
|
1160
|
+
// Create and push the boundary event (no sequence flow)
|
|
1161
|
+
this.boundaryEvent(id, { ...options, attachedTo });
|
|
1162
|
+
// Build the boundary event's outgoing path
|
|
1163
|
+
handler(this);
|
|
1164
|
+
// Restore cursor to the task so the sub-process main flow continues
|
|
1165
|
+
this.lastNodeId = savedLast;
|
|
1166
|
+
this.currentGatewayId = savedGateway;
|
|
1167
|
+
this.openBranchEnds = savedOpenEnds;
|
|
1168
|
+
return this;
|
|
1169
|
+
}
|
|
1170
|
+
// ---- Sub-process ----
|
|
1171
|
+
/** Add a sub-process nested inside this sub-process's content. */
|
|
1172
|
+
subProcess(id, content, options) {
|
|
1173
|
+
const resolved = resolveSubProcessArgs(content, options);
|
|
1174
|
+
const sub = new SubProcessContentBuilder(this.rootMessages);
|
|
1175
|
+
resolved.content(sub);
|
|
1176
|
+
insertJoinGateways(sub._elements, sub._flows);
|
|
1177
|
+
recomputeIncomingOutgoing(sub._elements, sub._flows);
|
|
1178
|
+
const element = makeFlowElement(id, "subProcess", resolved.options);
|
|
1179
|
+
if (element.type === "subProcess") {
|
|
1180
|
+
element.flowElements = sub._elements;
|
|
1181
|
+
element.sequenceFlows = sub._flows;
|
|
1182
|
+
element.textAnnotations = sub._textAnnotations;
|
|
1183
|
+
element.associations = sub._associations;
|
|
1184
|
+
if (resolved.options?.multiInstance) {
|
|
1185
|
+
element.loopCharacteristics = buildMultiInstance(resolved.options.multiInstance);
|
|
1186
|
+
}
|
|
1187
|
+
}
|
|
1188
|
+
return this.addElement(element);
|
|
1189
|
+
}
|
|
1190
|
+
/** Add an ad-hoc sub-process nested inside this sub-process's content. */
|
|
1191
|
+
adHocSubProcess(id, content, options) {
|
|
1192
|
+
const resolved = resolveSubProcessArgs(content, options);
|
|
1193
|
+
const sub = new SubProcessContentBuilder(this.rootMessages);
|
|
1194
|
+
resolved.content(sub);
|
|
1195
|
+
insertJoinGateways(sub._elements, sub._flows);
|
|
1196
|
+
recomputeIncomingOutgoing(sub._elements, sub._flows);
|
|
1197
|
+
const zeebeExt = {};
|
|
1198
|
+
if (resolved.options?.taskDefinition) {
|
|
1199
|
+
zeebeExt.taskDefinition = resolved.options.taskDefinition;
|
|
1200
|
+
}
|
|
1201
|
+
if (resolved.options?.ioMapping) {
|
|
1202
|
+
zeebeExt.ioMapping = {
|
|
1203
|
+
inputs: resolved.options.ioMapping.inputs ?? [],
|
|
1204
|
+
outputs: resolved.options.ioMapping.outputs ?? [],
|
|
1205
|
+
};
|
|
1206
|
+
}
|
|
1207
|
+
if (resolved.options?.taskHeaders) {
|
|
1208
|
+
zeebeExt.taskHeaders = {
|
|
1209
|
+
headers: Object.entries(resolved.options.taskHeaders).map(([key, value]) => ({
|
|
1210
|
+
key,
|
|
1211
|
+
value,
|
|
1212
|
+
})),
|
|
1213
|
+
};
|
|
1214
|
+
}
|
|
1215
|
+
const extensionElements = zeebeExtensionsToXmlElements(zeebeExt);
|
|
1216
|
+
const adHocAttrs = {};
|
|
1217
|
+
if (resolved.options?.activeElementsCollection) {
|
|
1218
|
+
adHocAttrs.activeElementsCollection = resolved.options.activeElementsCollection;
|
|
1219
|
+
}
|
|
1220
|
+
if (resolved.options?.outputCollection) {
|
|
1221
|
+
adHocAttrs.outputCollection = resolved.options.outputCollection;
|
|
1222
|
+
}
|
|
1223
|
+
if (resolved.options?.outputElement) {
|
|
1224
|
+
adHocAttrs.outputElement = resolved.options.outputElement;
|
|
1225
|
+
}
|
|
1226
|
+
if (Object.keys(adHocAttrs).length > 0) {
|
|
1227
|
+
extensionElements.push({
|
|
1228
|
+
name: "zeebe:adHoc",
|
|
1229
|
+
attributes: adHocAttrs,
|
|
1230
|
+
children: [],
|
|
1231
|
+
});
|
|
1232
|
+
}
|
|
1233
|
+
const element = makeFlowElement(id, "adHocSubProcess", {
|
|
1234
|
+
name: resolved.options?.name,
|
|
1235
|
+
extensionElements,
|
|
1236
|
+
});
|
|
1237
|
+
if (resolved.options?.modelerTemplate) {
|
|
1238
|
+
element.unknownAttributes["zeebe:modelerTemplate"] = resolved.options.modelerTemplate;
|
|
1239
|
+
}
|
|
1240
|
+
if (resolved.options?.modelerTemplateVersion) {
|
|
1241
|
+
element.unknownAttributes["zeebe:modelerTemplateVersion"] =
|
|
1242
|
+
resolved.options.modelerTemplateVersion;
|
|
1243
|
+
}
|
|
1244
|
+
if (resolved.options?.modelerTemplateIcon) {
|
|
1245
|
+
element.unknownAttributes["zeebe:modelerTemplateIcon"] = resolved.options.modelerTemplateIcon;
|
|
1246
|
+
}
|
|
1247
|
+
if (element.type === "adHocSubProcess") {
|
|
1248
|
+
element.flowElements = sub._elements;
|
|
1249
|
+
element.sequenceFlows = sub._flows;
|
|
1250
|
+
element.textAnnotations = sub._textAnnotations;
|
|
1251
|
+
element.associations = sub._associations;
|
|
1252
|
+
if (resolved.options?.loopCharacteristics) {
|
|
1253
|
+
element.loopCharacteristics = buildAdHocLoopCharacteristics(resolved.options.loopCharacteristics);
|
|
1254
|
+
}
|
|
1255
|
+
else if (resolved.options?.multiInstance) {
|
|
1256
|
+
element.loopCharacteristics = buildMultiInstance(resolved.options.multiInstance);
|
|
1257
|
+
}
|
|
1258
|
+
}
|
|
1259
|
+
return this.addElement(element);
|
|
1260
|
+
}
|
|
1261
|
+
/** Add an event sub-process. Triggered by its start event — no incoming or outgoing sequence flows. */
|
|
1262
|
+
eventSubProcess(id, content, options) {
|
|
1263
|
+
const resolved = resolveSubProcessArgs(content, options);
|
|
1264
|
+
const sub = new SubProcessContentBuilder(this.rootMessages);
|
|
1265
|
+
resolved.content(sub);
|
|
1266
|
+
insertJoinGateways(sub._elements, sub._flows);
|
|
1267
|
+
recomputeIncomingOutgoing(sub._elements, sub._flows);
|
|
1268
|
+
const element = makeFlowElement(id, "subProcess", resolved.options);
|
|
1269
|
+
if (element.type === "subProcess") {
|
|
1270
|
+
element.triggeredByEvent = true;
|
|
1271
|
+
element.flowElements = sub._elements;
|
|
1272
|
+
element.sequenceFlows = sub._flows;
|
|
1273
|
+
element.textAnnotations = sub._textAnnotations;
|
|
1274
|
+
element.associations = sub._associations;
|
|
1275
|
+
}
|
|
1276
|
+
// Event sub-processes have no incoming/outgoing sequence flows and must not
|
|
1277
|
+
// advance the cursor — mirrors ProcessBuilder.eventSubProcess.
|
|
1278
|
+
if (this._elements.some((n) => n.id === element.id)) {
|
|
1279
|
+
throw new Error(`Duplicate element ID "${element.id}" in sub-process`);
|
|
1280
|
+
}
|
|
1281
|
+
this._elements.push(element);
|
|
1282
|
+
return this;
|
|
1283
|
+
}
|
|
979
1284
|
}
|
|
980
1285
|
// ---------------------------------------------------------------------------
|
|
981
1286
|
// Process builder (top-level entry point)
|
|
@@ -1374,36 +1679,40 @@ export class ProcessBuilder {
|
|
|
1374
1679
|
// ---- Sub-processes ----
|
|
1375
1680
|
/** Add an ad-hoc sub-process with optional AI agent or multi-instance configuration. */
|
|
1376
1681
|
adHocSubProcess(id, content, options) {
|
|
1682
|
+
const resolved = resolveSubProcessArgs(content, options);
|
|
1377
1683
|
const sub = new SubProcessContentBuilder(this.rootMessages);
|
|
1378
|
-
content(sub);
|
|
1684
|
+
resolved.content(sub);
|
|
1379
1685
|
insertJoinGateways(sub._elements, sub._flows);
|
|
1380
1686
|
recomputeIncomingOutgoing(sub._elements, sub._flows);
|
|
1381
1687
|
const zeebeExt = {};
|
|
1382
|
-
if (options?.taskDefinition) {
|
|
1383
|
-
zeebeExt.taskDefinition = options.taskDefinition;
|
|
1688
|
+
if (resolved.options?.taskDefinition) {
|
|
1689
|
+
zeebeExt.taskDefinition = resolved.options.taskDefinition;
|
|
1384
1690
|
}
|
|
1385
|
-
if (options?.ioMapping) {
|
|
1691
|
+
if (resolved.options?.ioMapping) {
|
|
1386
1692
|
zeebeExt.ioMapping = {
|
|
1387
|
-
inputs: options.ioMapping.inputs ?? [],
|
|
1388
|
-
outputs: options.ioMapping.outputs ?? [],
|
|
1693
|
+
inputs: resolved.options.ioMapping.inputs ?? [],
|
|
1694
|
+
outputs: resolved.options.ioMapping.outputs ?? [],
|
|
1389
1695
|
};
|
|
1390
1696
|
}
|
|
1391
|
-
if (options?.taskHeaders) {
|
|
1697
|
+
if (resolved.options?.taskHeaders) {
|
|
1392
1698
|
zeebeExt.taskHeaders = {
|
|
1393
|
-
headers: Object.entries(options.taskHeaders).map(([key, value]) => ({
|
|
1699
|
+
headers: Object.entries(resolved.options.taskHeaders).map(([key, value]) => ({
|
|
1700
|
+
key,
|
|
1701
|
+
value,
|
|
1702
|
+
})),
|
|
1394
1703
|
};
|
|
1395
1704
|
}
|
|
1396
1705
|
const extensionElements = zeebeExtensionsToXmlElements(zeebeExt);
|
|
1397
1706
|
// zeebe:adHoc element
|
|
1398
1707
|
const adHocAttrs = {};
|
|
1399
|
-
if (options?.activeElementsCollection) {
|
|
1400
|
-
adHocAttrs.activeElementsCollection = options.activeElementsCollection;
|
|
1708
|
+
if (resolved.options?.activeElementsCollection) {
|
|
1709
|
+
adHocAttrs.activeElementsCollection = resolved.options.activeElementsCollection;
|
|
1401
1710
|
}
|
|
1402
|
-
if (options?.outputCollection) {
|
|
1403
|
-
adHocAttrs.outputCollection = options.outputCollection;
|
|
1711
|
+
if (resolved.options?.outputCollection) {
|
|
1712
|
+
adHocAttrs.outputCollection = resolved.options.outputCollection;
|
|
1404
1713
|
}
|
|
1405
|
-
if (options?.outputElement) {
|
|
1406
|
-
adHocAttrs.outputElement = options.outputElement;
|
|
1714
|
+
if (resolved.options?.outputElement) {
|
|
1715
|
+
adHocAttrs.outputElement = resolved.options.outputElement;
|
|
1407
1716
|
}
|
|
1408
1717
|
if (Object.keys(adHocAttrs).length > 0) {
|
|
1409
1718
|
extensionElements.push({
|
|
@@ -1413,28 +1722,29 @@ export class ProcessBuilder {
|
|
|
1413
1722
|
});
|
|
1414
1723
|
}
|
|
1415
1724
|
const element = makeFlowElement(id, "adHocSubProcess", {
|
|
1416
|
-
name: options?.name,
|
|
1725
|
+
name: resolved.options?.name,
|
|
1417
1726
|
extensionElements,
|
|
1418
1727
|
});
|
|
1419
|
-
if (options?.modelerTemplate) {
|
|
1420
|
-
element.unknownAttributes["zeebe:modelerTemplate"] = options.modelerTemplate;
|
|
1728
|
+
if (resolved.options?.modelerTemplate) {
|
|
1729
|
+
element.unknownAttributes["zeebe:modelerTemplate"] = resolved.options.modelerTemplate;
|
|
1421
1730
|
}
|
|
1422
|
-
if (options?.modelerTemplateVersion) {
|
|
1423
|
-
element.unknownAttributes["zeebe:modelerTemplateVersion"] =
|
|
1731
|
+
if (resolved.options?.modelerTemplateVersion) {
|
|
1732
|
+
element.unknownAttributes["zeebe:modelerTemplateVersion"] =
|
|
1733
|
+
resolved.options.modelerTemplateVersion;
|
|
1424
1734
|
}
|
|
1425
|
-
if (options?.modelerTemplateIcon) {
|
|
1426
|
-
element.unknownAttributes["zeebe:modelerTemplateIcon"] = options.modelerTemplateIcon;
|
|
1735
|
+
if (resolved.options?.modelerTemplateIcon) {
|
|
1736
|
+
element.unknownAttributes["zeebe:modelerTemplateIcon"] = resolved.options.modelerTemplateIcon;
|
|
1427
1737
|
}
|
|
1428
1738
|
if (element.type === "adHocSubProcess") {
|
|
1429
1739
|
element.flowElements = sub._elements;
|
|
1430
1740
|
element.sequenceFlows = sub._flows;
|
|
1431
1741
|
element.textAnnotations = sub._textAnnotations;
|
|
1432
1742
|
element.associations = sub._associations;
|
|
1433
|
-
if (options?.loopCharacteristics) {
|
|
1434
|
-
element.loopCharacteristics = buildAdHocLoopCharacteristics(options.loopCharacteristics);
|
|
1743
|
+
if (resolved.options?.loopCharacteristics) {
|
|
1744
|
+
element.loopCharacteristics = buildAdHocLoopCharacteristics(resolved.options.loopCharacteristics);
|
|
1435
1745
|
}
|
|
1436
|
-
else if (options?.multiInstance) {
|
|
1437
|
-
element.loopCharacteristics = buildMultiInstance(options.multiInstance);
|
|
1746
|
+
else if (resolved.options?.multiInstance) {
|
|
1747
|
+
element.loopCharacteristics = buildMultiInstance(resolved.options.multiInstance);
|
|
1438
1748
|
}
|
|
1439
1749
|
}
|
|
1440
1750
|
this.addFlowElement(element);
|
|
@@ -1442,18 +1752,19 @@ export class ProcessBuilder {
|
|
|
1442
1752
|
}
|
|
1443
1753
|
/** Add a sub-process (aspirational). */
|
|
1444
1754
|
subProcess(id, content, options) {
|
|
1755
|
+
const resolved = resolveSubProcessArgs(content, options);
|
|
1445
1756
|
const sub = new SubProcessContentBuilder(this.rootMessages);
|
|
1446
|
-
content(sub);
|
|
1757
|
+
resolved.content(sub);
|
|
1447
1758
|
insertJoinGateways(sub._elements, sub._flows);
|
|
1448
1759
|
recomputeIncomingOutgoing(sub._elements, sub._flows);
|
|
1449
|
-
const element = makeFlowElement(id, "subProcess", options);
|
|
1760
|
+
const element = makeFlowElement(id, "subProcess", resolved.options);
|
|
1450
1761
|
if (element.type === "subProcess") {
|
|
1451
1762
|
element.flowElements = sub._elements;
|
|
1452
1763
|
element.sequenceFlows = sub._flows;
|
|
1453
1764
|
element.textAnnotations = sub._textAnnotations;
|
|
1454
1765
|
element.associations = sub._associations;
|
|
1455
|
-
if (options?.multiInstance) {
|
|
1456
|
-
element.loopCharacteristics = buildMultiInstance(options.multiInstance);
|
|
1766
|
+
if (resolved.options?.multiInstance) {
|
|
1767
|
+
element.loopCharacteristics = buildMultiInstance(resolved.options.multiInstance);
|
|
1457
1768
|
}
|
|
1458
1769
|
}
|
|
1459
1770
|
this.addFlowElement(element);
|
|
@@ -1461,11 +1772,12 @@ export class ProcessBuilder {
|
|
|
1461
1772
|
}
|
|
1462
1773
|
/** Add an event sub-process. Triggered by its start event — no incoming or outgoing sequence flows. */
|
|
1463
1774
|
eventSubProcess(id, content, options) {
|
|
1775
|
+
const resolved = resolveSubProcessArgs(content, options);
|
|
1464
1776
|
const sub = new SubProcessContentBuilder(this.rootMessages);
|
|
1465
|
-
content(sub);
|
|
1777
|
+
resolved.content(sub);
|
|
1466
1778
|
insertJoinGateways(sub._elements, sub._flows);
|
|
1467
1779
|
recomputeIncomingOutgoing(sub._elements, sub._flows);
|
|
1468
|
-
const element = makeFlowElement(id, "subProcess", options);
|
|
1780
|
+
const element = makeFlowElement(id, "subProcess", resolved.options);
|
|
1469
1781
|
if (element.type === "subProcess") {
|
|
1470
1782
|
element.triggeredByEvent = true;
|
|
1471
1783
|
element.flowElements = sub._elements;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { BpmnDefinitions } from "./bpmn-model.js";
|
|
2
|
+
export interface DiCompleteness {
|
|
3
|
+
missingShapes: string[];
|
|
4
|
+
missingEdges: string[];
|
|
5
|
+
}
|
|
6
|
+
/**
|
|
7
|
+
* Assert the diagram DI is complete: every flow node (recursively, incl.
|
|
8
|
+
* subprocess children and boundary events) and text annotation has a
|
|
9
|
+
* BPMNShape; every sequence flow, association and message flow has a
|
|
10
|
+
* BPMNEdge. Lanes are ignored (no reliable lane DI — matches the
|
|
11
|
+
* tmp/02-di-check.cjs rule this ports).
|
|
12
|
+
*/
|
|
13
|
+
export declare function checkDiCompleteness(defs: BpmnDefinitions): DiCompleteness;
|
|
14
|
+
//# sourceMappingURL=di-check.d.ts.map
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Assert the diagram DI is complete: every flow node (recursively, incl.
|
|
3
|
+
* subprocess children and boundary events) and text annotation has a
|
|
4
|
+
* BPMNShape; every sequence flow, association and message flow has a
|
|
5
|
+
* BPMNEdge. Lanes are ignored (no reliable lane DI — matches the
|
|
6
|
+
* tmp/02-di-check.cjs rule this ports).
|
|
7
|
+
*/
|
|
8
|
+
export function checkDiCompleteness(defs) {
|
|
9
|
+
const shapes = new Set();
|
|
10
|
+
const edges = new Set();
|
|
11
|
+
for (const d of defs.diagrams) {
|
|
12
|
+
for (const s of d.plane.shapes)
|
|
13
|
+
shapes.add(s.bpmnElement);
|
|
14
|
+
for (const e of d.plane.edges)
|
|
15
|
+
edges.add(e.bpmnElement);
|
|
16
|
+
}
|
|
17
|
+
const missingShapes = [];
|
|
18
|
+
const missingEdges = [];
|
|
19
|
+
function walkElements(els, flows) {
|
|
20
|
+
for (const el of els) {
|
|
21
|
+
if (!shapes.has(el.id))
|
|
22
|
+
missingShapes.push(el.id);
|
|
23
|
+
const sub = el;
|
|
24
|
+
if (sub.flowElements?.length)
|
|
25
|
+
walkElements(sub.flowElements, sub.sequenceFlows ?? []);
|
|
26
|
+
}
|
|
27
|
+
for (const f of flows) {
|
|
28
|
+
if (!edges.has(f.id))
|
|
29
|
+
missingEdges.push(f.id);
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
for (const p of defs.processes) {
|
|
33
|
+
walkElements(p.flowElements, p.sequenceFlows);
|
|
34
|
+
for (const ta of p.textAnnotations)
|
|
35
|
+
if (!shapes.has(ta.id))
|
|
36
|
+
missingShapes.push(ta.id);
|
|
37
|
+
for (const a of p.associations)
|
|
38
|
+
if (!edges.has(a.id))
|
|
39
|
+
missingEdges.push(a.id);
|
|
40
|
+
}
|
|
41
|
+
for (const c of defs.collaborations) {
|
|
42
|
+
for (const part of c.participants)
|
|
43
|
+
if (!shapes.has(part.id))
|
|
44
|
+
missingShapes.push(part.id);
|
|
45
|
+
for (const mf of c.messageFlows)
|
|
46
|
+
if (!edges.has(mf.id))
|
|
47
|
+
missingEdges.push(mf.id);
|
|
48
|
+
}
|
|
49
|
+
return { missingShapes, missingEdges };
|
|
50
|
+
}
|
|
51
|
+
//# sourceMappingURL=di-check.js.map
|
package/dist/bpmn/svg.js
CHANGED
|
@@ -119,6 +119,9 @@ export function exportSvg(defs, options) {
|
|
|
119
119
|
}
|
|
120
120
|
}
|
|
121
121
|
// ── Shapes ────────────────────────────────────────────────────────────────
|
|
122
|
+
// Pool/lane backgrounds are opaque and must render first, or they paint over
|
|
123
|
+
// the flow-node shapes and edges nested inside them.
|
|
124
|
+
const containerParts = [];
|
|
122
125
|
const shapeParts = [];
|
|
123
126
|
const labelParts = [];
|
|
124
127
|
for (const shape of plane.shapes) {
|
|
@@ -126,6 +129,7 @@ export function exportSvg(defs, options) {
|
|
|
126
129
|
const el = idx.elements.get(shape.bpmnElement);
|
|
127
130
|
const type = el?.type ?? "";
|
|
128
131
|
let inner;
|
|
132
|
+
let isContainer = false;
|
|
129
133
|
if (isEvent(type)) {
|
|
130
134
|
inner = renderEvent(el, width, height, t);
|
|
131
135
|
}
|
|
@@ -140,9 +144,11 @@ export function exportSvg(defs, options) {
|
|
|
140
144
|
}
|
|
141
145
|
else if (idx.participants.has(shape.bpmnElement)) {
|
|
142
146
|
inner = renderPool(idx.participants.get(shape.bpmnElement), width, height, t);
|
|
147
|
+
isContainer = true;
|
|
143
148
|
}
|
|
144
149
|
else if (idx.lanes.has(shape.bpmnElement)) {
|
|
145
150
|
inner = renderLane(idx.lanes.get(shape.bpmnElement), width, height, t);
|
|
151
|
+
isContainer = true;
|
|
146
152
|
}
|
|
147
153
|
else {
|
|
148
154
|
inner = "";
|
|
@@ -152,7 +158,13 @@ export function exportSvg(defs, options) {
|
|
|
152
158
|
inner = renderTask(el, width, height, t);
|
|
153
159
|
}
|
|
154
160
|
if (inner) {
|
|
155
|
-
|
|
161
|
+
const g = `<g transform="translate(${x} ${y})">${inner}</g>`;
|
|
162
|
+
if (isContainer) {
|
|
163
|
+
containerParts.push(g);
|
|
164
|
+
}
|
|
165
|
+
else {
|
|
166
|
+
shapeParts.push(g);
|
|
167
|
+
}
|
|
156
168
|
}
|
|
157
169
|
// External labels for events and gateways
|
|
158
170
|
const isExtLabel = isEvent(type) || isGateway(type);
|
|
@@ -177,6 +189,7 @@ export function exportSvg(defs, options) {
|
|
|
177
189
|
` <path d="M0,0 L8,3 L0,6 Z" fill="${arrowFill}"/>`,
|
|
178
190
|
" </marker>",
|
|
179
191
|
"</defs>",
|
|
192
|
+
...containerParts,
|
|
180
193
|
...edgeParts,
|
|
181
194
|
...shapeParts,
|
|
182
195
|
...labelParts,
|
package/dist/index.d.ts
CHANGED
|
@@ -4,6 +4,8 @@ export { isBpmnActivity, isBpmnAdHocSubProcess, isBpmnBoundaryEvent, isBpmnBusin
|
|
|
4
4
|
export { findElement, findElementInProcess, findProcess, findSequenceFlow, getAllElements, getElementType, getZeebeExtensions, } from "./bpmn/utils.js";
|
|
5
5
|
export { Bpmn, SAMPLE_BPMN_XML } from "./bpmn/index.js";
|
|
6
6
|
export { applyAutoLayout } from "./bpmn/auto-layout.js";
|
|
7
|
+
export { checkDiCompleteness } from "./bpmn/di-check.js";
|
|
8
|
+
export type { DiCompleteness } from "./bpmn/di-check.js";
|
|
7
9
|
export { DiagramBuilder } from "./bpmn/bpmn-builder.js";
|
|
8
10
|
export type { ProcessBuilder, BranchBuilder, SubProcessContentBuilder, ServiceTaskOptions, ScriptTaskOptions, UserTaskOptions, CallActivityOptions, BusinessRuleTaskOptions, ElementOptions, GatewayOptions, MultiInstanceOptions, SubProcessOptions, StartEventOptions, IntermediateCatchEventOptions, IntermediateThrowEventOptions, EndEventOptions, BoundaryEventOptions, AdHocSubProcessOptions, } from "./bpmn/bpmn-builder.js";
|
|
9
11
|
export type { BpmnDefinitions, BpmnProcess, BpmnFlowNode, BpmnFlowElement, BpmnSequenceFlow, BpmnBoundaryEvent, BpmnElementType, BpmnStartEvent, BpmnEndEvent, BpmnIntermediateCatchEvent, BpmnIntermediateThrowEvent, BpmnTask, BpmnServiceTask, BpmnScriptTask, BpmnUserTask, BpmnSendTask, BpmnReceiveTask, BpmnBusinessRuleTask, BpmnManualTask, BpmnCallActivity, BpmnSubProcess, BpmnAdHocSubProcess, BpmnEventSubProcess, BpmnTransaction, BpmnExclusiveGateway, BpmnParallelGateway, BpmnInclusiveGateway, BpmnEventBasedGateway, BpmnComplexGateway, BpmnCollaboration, BpmnParticipant, BpmnMessageFlow, BpmnLane, BpmnLaneSet, BpmnError, BpmnEscalation, BpmnMessage, BpmnSignal, BpmnTextAnnotation, BpmnAssociation, BpmnConditionExpression, BpmnEventDefinition, BpmnTimerEventDefinition, BpmnErrorEventDefinition, BpmnEscalationEventDefinition, BpmnMessageEventDefinition, BpmnSignalEventDefinition, BpmnConditionalEventDefinition, BpmnLinkEventDefinition, BpmnCancelEventDefinition, BpmnTerminateEventDefinition, BpmnCompensateEventDefinition, BpmnMultiInstanceLoopCharacteristics, BpmnDiagram, BpmnDiPlane, BpmnDiShape, BpmnDiEdge, BpmnDiLabel, BpmnBounds, BpmnWaypoint, } from "./bpmn/bpmn-model.js";
|
package/dist/index.js
CHANGED
|
@@ -3,6 +3,7 @@ export { isBpmnActivity, isBpmnAdHocSubProcess, isBpmnBoundaryEvent, isBpmnBusin
|
|
|
3
3
|
export { findElement, findElementInProcess, findProcess, findSequenceFlow, getAllElements, getElementType, getZeebeExtensions, } from "./bpmn/utils.js";
|
|
4
4
|
export { Bpmn, SAMPLE_BPMN_XML } from "./bpmn/index.js";
|
|
5
5
|
export { applyAutoLayout } from "./bpmn/auto-layout.js";
|
|
6
|
+
export { checkDiCompleteness } from "./bpmn/di-check.js";
|
|
6
7
|
export { DiagramBuilder } from "./bpmn/bpmn-builder.js";
|
|
7
8
|
export { zeebeExtensionsToXmlElements } from "./bpmn/zeebe-extensions.js";
|
|
8
9
|
export { Dmn, layoutDmn, benchmarkDmnLayout, compactifyDmn, expandDmn } from "./dmn/index.js";
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Text-annotation packer. Port of the layout phase of
|
|
3
|
+
* tmp/01-annotation-layouting.cjs (lines 96-389), adapted to operate on
|
|
4
|
+
* already-parsed LayoutNode[] / Bounds instead of regex-parsed BPMN DI
|
|
5
|
+
* shapes. Constants, formulas and control flow match the reference exactly.
|
|
6
|
+
*/
|
|
7
|
+
import type { BpmnProcess } from "../bpmn/bpmn-model.js";
|
|
8
|
+
import type { Bounds, LayoutNode, Waypoint } from "./types.js";
|
|
9
|
+
/**
|
|
10
|
+
* Sizes and packs text annotations around their linked elements without
|
|
11
|
+
* overlapping each other or any other layout node (incl. node labels).
|
|
12
|
+
* Returns final Bounds per annotation id; annotations with no resolvable
|
|
13
|
+
* association target (no association at all, or the linked element isn't
|
|
14
|
+
* in `layoutNodes`) still get an entry — they're placed at a fixed fallback
|
|
15
|
+
* origin and pushed clear of everything else already placed, mirroring the
|
|
16
|
+
* pre-port fallback in auto-layout.ts's computeAnnotationLocalBounds.
|
|
17
|
+
*/
|
|
18
|
+
export declare function packAnnotations(process: BpmnProcess, layoutNodes: LayoutNode[]): Map<string, Bounds>;
|
|
19
|
+
/**
|
|
20
|
+
* Edge-to-edge, clamped association waypoints between a linked element and
|
|
21
|
+
* its annotation. Port of `chooseWaypoints` (tmp/01-annotation-layouting.cjs:365-389).
|
|
22
|
+
*/
|
|
23
|
+
export declare function associationWaypoints(elementBounds: Bounds, annotationBounds: Bounds): {
|
|
24
|
+
pElem: Waypoint;
|
|
25
|
+
pAnn: Waypoint;
|
|
26
|
+
};
|
|
27
|
+
//# sourceMappingURL=annotations.d.ts.map
|