@bpmnkit/core 0.1.1 → 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.
Files changed (83) hide show
  1. package/README.md +32 -1
  2. package/dist/bpmn/agentic.d.ts +121 -0
  3. package/dist/bpmn/agentic.js +97 -0
  4. package/dist/bpmn/auto-layout.d.ts +5 -5
  5. package/dist/bpmn/auto-layout.js +592 -36
  6. package/dist/bpmn/bpmn-builder.d.ts +265 -3
  7. package/dist/bpmn/bpmn-builder.js +603 -197
  8. package/dist/bpmn/bpmn-model.d.ts +114 -0
  9. package/dist/bpmn/bpmn-parser.js +1414 -521
  10. package/dist/bpmn/bpmn-serializer.js +107 -19
  11. package/dist/bpmn/compact.d.ts +17 -2
  12. package/dist/bpmn/compact.js +3 -3
  13. package/dist/bpmn/full-operations.d.ts +89 -0
  14. package/dist/bpmn/full-operations.js +478 -0
  15. package/dist/bpmn/index.d.ts +19 -0
  16. package/dist/bpmn/index.js +21 -0
  17. package/dist/bpmn/optimize/agentic.d.ts +10 -0
  18. package/dist/bpmn/optimize/agentic.js +88 -0
  19. package/dist/bpmn/optimize/deploy.d.ts +16 -0
  20. package/dist/bpmn/optimize/deploy.js +143 -0
  21. package/dist/bpmn/optimize/feel-syntax.d.ts +12 -0
  22. package/dist/bpmn/optimize/feel-syntax.js +87 -0
  23. package/dist/bpmn/optimize/feel.js +7 -4
  24. package/dist/bpmn/optimize/flow.js +22 -2
  25. package/dist/bpmn/optimize/index.js +20 -9
  26. package/dist/bpmn/optimize/patterns.js +23 -16
  27. package/dist/bpmn/optimize/tasks.js +30 -7
  28. package/dist/bpmn/optimize/types.d.ts +10 -1
  29. package/dist/bpmn/optimize/utils.js +2 -4
  30. package/dist/bpmn/optimize/variable-flow.js +58 -67
  31. package/dist/bpmn/semantic-hash.d.ts +93 -0
  32. package/dist/bpmn/semantic-hash.js +155 -0
  33. package/dist/bpmn/sha256.d.ts +17 -0
  34. package/dist/bpmn/sha256.js +95 -0
  35. package/dist/bpmn/zeebe-extensions.d.ts +83 -0
  36. package/dist/bpmn/zeebe-extensions.js +117 -0
  37. package/dist/bpmn/zeebe-placement.d.ts +12 -0
  38. package/dist/bpmn/zeebe-placement.js +140 -0
  39. package/dist/errors.d.ts +40 -1
  40. package/dist/errors.js +41 -0
  41. package/dist/index.d.ts +16 -5
  42. package/dist/index.js +9 -3
  43. package/dist/layout/annotations.js +36 -1
  44. package/dist/layout/collaboration/alignment.d.ts +26 -0
  45. package/dist/layout/collaboration/alignment.js +66 -0
  46. package/dist/layout/collaboration/ordering.d.ts +21 -0
  47. package/dist/layout/collaboration/ordering.js +102 -0
  48. package/dist/layout/index.d.ts +1 -0
  49. package/dist/layout/layout-engine.d.ts +13 -3
  50. package/dist/layout/layout-engine.js +9 -4
  51. package/dist/layout/semantic/bands.d.ts +19 -0
  52. package/dist/layout/semantic/bands.js +324 -0
  53. package/dist/layout/semantic/graph.d.ts +37 -0
  54. package/dist/layout/semantic/graph.js +242 -0
  55. package/dist/layout/semantic/index.d.ts +13 -0
  56. package/dist/layout/semantic/index.js +181 -0
  57. package/dist/layout/semantic/place.d.ts +40 -0
  58. package/dist/layout/semantic/place.js +271 -0
  59. package/dist/layout/semantic/route.d.ts +14 -0
  60. package/dist/layout/semantic/route.js +514 -0
  61. package/dist/layout/types.d.ts +17 -0
  62. package/dist/node/index.d.ts +10 -0
  63. package/dist/node/index.js +9 -0
  64. package/dist/node/write.d.ts +81 -0
  65. package/dist/node/write.js +167 -0
  66. package/dist/plan/compile.d.ts +39 -0
  67. package/dist/plan/compile.js +380 -0
  68. package/dist/plan/extract.d.ts +31 -0
  69. package/dist/plan/extract.js +248 -0
  70. package/dist/plan/index.d.ts +6 -0
  71. package/dist/plan/index.js +5 -0
  72. package/dist/plan/merge.d.ts +13 -0
  73. package/dist/plan/merge.js +80 -0
  74. package/dist/plan/slug.d.ts +5 -0
  75. package/dist/plan/slug.js +22 -0
  76. package/dist/plan/types.d.ts +225 -0
  77. package/dist/plan/types.js +13 -0
  78. package/dist/types/id-generator.js +11 -3
  79. package/dist/xml/index.d.ts +3 -1
  80. package/dist/xml/index.js +2 -1
  81. package/dist/xml/xml-parser.d.ts +32 -0
  82. package/dist/xml/xml-parser.js +394 -143
  83. package/package.json +9 -2
@@ -1,3 +1,4 @@
1
+ import { ZEEBE_PLACEMENT } from "./zeebe-placement.js";
1
2
  /** Convert Zeebe extensions to XmlElement array for the BPMN model. */
2
3
  export function zeebeExtensionsToXmlElements(extensions) {
3
4
  const elements = [];
@@ -91,9 +92,125 @@ export function zeebeExtensionsToXmlElements(extensions) {
91
92
  children: [],
92
93
  });
93
94
  }
95
+ if (extensions.assignmentDefinition) {
96
+ const attrs = {};
97
+ const { assignee, candidateGroups, candidateUsers } = extensions.assignmentDefinition;
98
+ if (assignee)
99
+ attrs.assignee = assignee;
100
+ if (candidateGroups)
101
+ attrs.candidateGroups = candidateGroups;
102
+ if (candidateUsers)
103
+ attrs.candidateUsers = candidateUsers;
104
+ if (Object.keys(attrs).length > 0) {
105
+ elements.push({ name: "zeebe:assignmentDefinition", attributes: attrs, children: [] });
106
+ }
107
+ }
108
+ if (extensions.taskSchedule) {
109
+ const attrs = {};
110
+ if (extensions.taskSchedule.dueDate)
111
+ attrs.dueDate = extensions.taskSchedule.dueDate;
112
+ if (extensions.taskSchedule.followUpDate) {
113
+ attrs.followUpDate = extensions.taskSchedule.followUpDate;
114
+ }
115
+ if (Object.keys(attrs).length > 0) {
116
+ elements.push({ name: "zeebe:taskSchedule", attributes: attrs, children: [] });
117
+ }
118
+ }
119
+ if (extensions.priorityDefinition) {
120
+ elements.push({
121
+ name: "zeebe:priorityDefinition",
122
+ attributes: { priority: extensions.priorityDefinition.priority },
123
+ children: [],
124
+ });
125
+ }
126
+ if (extensions.subscription) {
127
+ elements.push({
128
+ name: "zeebe:subscription",
129
+ attributes: { correlationKey: extensions.subscription.correlationKey },
130
+ children: [],
131
+ });
132
+ }
94
133
  if (extensions.unknownElements) {
95
134
  elements.push(...extensions.unknownElements);
96
135
  }
97
136
  return elements;
98
137
  }
138
+ // ---------------------------------------------------------------------------
139
+ // Placement
140
+ // ---------------------------------------------------------------------------
141
+ /**
142
+ * Reports where a Zeebe extension may go, from the descriptor rather than from
143
+ * our own idea of the rules.
144
+ *
145
+ * `zeebe.json` records a `meta.allowedIn` list per extension type;
146
+ * `scripts/generate-zeebe-placement.ts` resolves those entries — many of which
147
+ * name abstract BPMN types or Zeebe aliases — into the concrete element names in
148
+ * `ZEEBE_PLACEMENT`. Writing `zeebe:calledDecision` onto a service task produces
149
+ * a file Camunda rejects at deploy time; catching it at the write is the point.
150
+ *
151
+ * **An extension the table does not mention is allowed.** The descriptor
152
+ * declares no owner for `zeebe:subscription` or `zeebe:properties`, so we do not
153
+ * know where they may go and must not invent a rule — this check rejects only
154
+ * what the descriptor positively forbids. Vendor extensions outside the `zeebe:`
155
+ * namespace are not this function's business and are likewise allowed.
156
+ *
157
+ * @param ownerElement - The owner's BPMN element name, e.g. `bpmn:serviceTask`.
158
+ * @param extension - The extension element name, e.g. `zeebe:taskDefinition`.
159
+ */
160
+ export function isZeebePlacementAllowed(ownerElement, extension) {
161
+ const owners = ZEEBE_PLACEMENT[extension];
162
+ return owners === undefined || owners.includes(ownerElement);
163
+ }
164
+ /** Thrown when a Zeebe extension is written somewhere the descriptor forbids. */
165
+ export class ZeebePlacementError extends Error {
166
+ ownerElement;
167
+ extension;
168
+ allowedOn;
169
+ constructor(ownerElement, extension, allowedOn) {
170
+ super(`<${extension}> is not allowed on <${ownerElement}>. The Zeebe schema allows it on: ${allowedOn.join(", ")}.`);
171
+ this.ownerElement = ownerElement;
172
+ this.extension = extension;
173
+ this.allowedOn = allowedOn;
174
+ this.name = "ZeebePlacementError";
175
+ }
176
+ }
177
+ /**
178
+ * Throws {@link ZeebePlacementError} if the placement is one the descriptor
179
+ * forbids. See {@link isZeebePlacementAllowed} for what "forbids" covers.
180
+ */
181
+ export function assertZeebePlacement(ownerElement, extension) {
182
+ if (isZeebePlacementAllowed(ownerElement, extension))
183
+ return;
184
+ throw new ZeebePlacementError(ownerElement, extension, ZEEBE_PLACEMENT[extension] ?? []);
185
+ }
186
+ /**
187
+ * The BPMN element name a flow element is written as.
188
+ *
189
+ * The model's `type` is the element's local name in every case but one:
190
+ * `eventSubProcess` is our name for a `bpmn:subProcess` carrying
191
+ * `triggeredByEvent`, and BPMN has no element of that name.
192
+ */
193
+ export function bpmnElementName(flowElement) {
194
+ const local = flowElement.type === "eventSubProcess" ? "subProcess" : flowElement.type;
195
+ return `bpmn:${local}`;
196
+ }
197
+ /**
198
+ * Finds a Zeebe extension element on a flow element, creating it if absent, and
199
+ * refuses a placement the descriptor forbids.
200
+ *
201
+ * Use this rather than pushing onto `extensionElements` directly: the push
202
+ * cannot fail, so an extension on the wrong element becomes a deploy-time error
203
+ * in someone else's terminal instead of a throw here.
204
+ *
205
+ * @throws ZeebePlacementError
206
+ */
207
+ export function ensureZeebeExtension(owner, extension) {
208
+ assertZeebePlacement(bpmnElementName(owner), extension);
209
+ const existing = owner.extensionElements.find((candidate) => candidate.name === extension);
210
+ if (existing)
211
+ return existing;
212
+ const created = { name: extension, attributes: {}, children: [] };
213
+ owner.extensionElements.push(created);
214
+ return created;
215
+ }
99
216
  //# sourceMappingURL=zeebe-extensions.js.map
@@ -0,0 +1,12 @@
1
+ /**
2
+ * Where each Zeebe extension element may be placed, keyed by element name.
3
+ *
4
+ * The value is the set of element names that may own it. Owners are BPMN
5
+ * elements for extensions that sit in an `extensionElements` bag, and Zeebe
6
+ * elements for the few that nest inside another extension.
7
+ *
8
+ * An extension absent from this table is one the descriptor says nothing about;
9
+ * see `isZeebePlacementAllowed` for what that means.
10
+ */
11
+ export declare const ZEEBE_PLACEMENT: Readonly<Record<string, readonly string[]>>;
12
+ //# sourceMappingURL=zeebe-placement.d.ts.map
@@ -0,0 +1,140 @@
1
+ // Generated by scripts/generate-zeebe-placement.ts — do not edit.
2
+ // Source: descriptors/zeebe.json (zeebe-bpmn-moddle, MIT) resolved against
3
+ // descriptors/bpmn.json (bpmn-moddle, MIT). Regenerate with:
4
+ // pnpm --filter @bpmnkit/core generate:placement
5
+ /**
6
+ * Where each Zeebe extension element may be placed, keyed by element name.
7
+ *
8
+ * The value is the set of element names that may own it. Owners are BPMN
9
+ * elements for extensions that sit in an `extensionElements` bag, and Zeebe
10
+ * elements for the few that nest inside another extension.
11
+ *
12
+ * An extension absent from this table is one the descriptor says nothing about;
13
+ * see `isZeebePlacementAllowed` for what that means.
14
+ */
15
+ export const ZEEBE_PLACEMENT = {
16
+ "zeebe:adHoc": ["bpmn:adHocSubProcess"],
17
+ "zeebe:agentDefinition": ["bpmn:adHocSubProcess", "bpmn:serviceTask"],
18
+ "zeebe:assignmentDefinition": ["bpmn:userTask"],
19
+ "zeebe:calledDecision": ["bpmn:businessRuleTask"],
20
+ "zeebe:calledElement": ["bpmn:callActivity"],
21
+ "zeebe:conditionalFilter": ["bpmn:conditionalEventDefinition"],
22
+ "zeebe:executionListener": ["zeebe:executionListeners"],
23
+ "zeebe:executionListeners": [
24
+ "bpmn:adHocSubProcess",
25
+ "bpmn:boundaryEvent",
26
+ "bpmn:businessRuleTask",
27
+ "bpmn:callActivity",
28
+ "bpmn:endEvent",
29
+ "bpmn:eventBasedGateway",
30
+ "bpmn:exclusiveGateway",
31
+ "bpmn:implicitThrowEvent",
32
+ "bpmn:inclusiveGateway",
33
+ "bpmn:intermediateCatchEvent",
34
+ "bpmn:intermediateThrowEvent",
35
+ "bpmn:manualTask",
36
+ "bpmn:parallelGateway",
37
+ "bpmn:process",
38
+ "bpmn:receiveTask",
39
+ "bpmn:scriptTask",
40
+ "bpmn:sendTask",
41
+ "bpmn:serviceTask",
42
+ "bpmn:startEvent",
43
+ "bpmn:subProcess",
44
+ "bpmn:task",
45
+ "bpmn:transaction",
46
+ "bpmn:userTask",
47
+ ],
48
+ "zeebe:formDefinition": ["bpmn:startEvent", "bpmn:userTask"],
49
+ "zeebe:input": [
50
+ "bpmn:adHocSubProcess",
51
+ "bpmn:businessRuleTask",
52
+ "bpmn:callActivity",
53
+ "bpmn:endEvent",
54
+ "bpmn:intermediateThrowEvent",
55
+ "bpmn:scriptTask",
56
+ "bpmn:sendTask",
57
+ "bpmn:serviceTask",
58
+ "bpmn:subProcess",
59
+ "bpmn:transaction",
60
+ "bpmn:userTask",
61
+ ],
62
+ "zeebe:ioMapping": [
63
+ "bpmn:adHocSubProcess",
64
+ "bpmn:boundaryEvent",
65
+ "bpmn:businessRuleTask",
66
+ "bpmn:callActivity",
67
+ "bpmn:endEvent",
68
+ "bpmn:implicitThrowEvent",
69
+ "bpmn:intermediateCatchEvent",
70
+ "bpmn:intermediateThrowEvent",
71
+ "bpmn:receiveTask",
72
+ "bpmn:scriptTask",
73
+ "bpmn:sendTask",
74
+ "bpmn:serviceTask",
75
+ "bpmn:startEvent",
76
+ "bpmn:subProcess",
77
+ "bpmn:transaction",
78
+ "bpmn:userTask",
79
+ ],
80
+ "zeebe:jobPriorityDefinition": [
81
+ "bpmn:adHocSubProcess",
82
+ "bpmn:businessRuleTask",
83
+ "bpmn:endEvent",
84
+ "bpmn:intermediateThrowEvent",
85
+ "bpmn:process",
86
+ "bpmn:scriptTask",
87
+ "bpmn:sendTask",
88
+ "bpmn:serviceTask",
89
+ ],
90
+ "zeebe:linkedResource": ["bpmn:serviceTask"],
91
+ "zeebe:linkedResources": ["bpmn:serviceTask"],
92
+ "zeebe:loopCharacteristics": ["bpmn:multiInstanceLoopCharacteristics"],
93
+ "zeebe:output": [
94
+ "bpmn:adHocSubProcess",
95
+ "bpmn:boundaryEvent",
96
+ "bpmn:businessRuleTask",
97
+ "bpmn:callActivity",
98
+ "bpmn:endEvent",
99
+ "bpmn:implicitThrowEvent",
100
+ "bpmn:intermediateCatchEvent",
101
+ "bpmn:intermediateThrowEvent",
102
+ "bpmn:receiveTask",
103
+ "bpmn:scriptTask",
104
+ "bpmn:sendTask",
105
+ "bpmn:serviceTask",
106
+ "bpmn:startEvent",
107
+ "bpmn:subProcess",
108
+ "bpmn:transaction",
109
+ "bpmn:userTask",
110
+ ],
111
+ "zeebe:priorityDefinition": ["bpmn:userTask"],
112
+ "zeebe:script": ["bpmn:scriptTask"],
113
+ "zeebe:taskDefinition": [
114
+ "bpmn:adHocSubProcess",
115
+ "bpmn:businessRuleTask",
116
+ "bpmn:endEvent",
117
+ "bpmn:intermediateThrowEvent",
118
+ "bpmn:scriptTask",
119
+ "bpmn:sendTask",
120
+ "bpmn:serviceTask",
121
+ ],
122
+ "zeebe:taskHeaders": [
123
+ "bpmn:adHocSubProcess",
124
+ "bpmn:businessRuleTask",
125
+ "bpmn:endEvent",
126
+ "bpmn:intermediateThrowEvent",
127
+ "bpmn:scriptTask",
128
+ "bpmn:sendTask",
129
+ "bpmn:serviceTask",
130
+ "bpmn:userTask",
131
+ "zeebe:executionListener",
132
+ ],
133
+ "zeebe:taskListener": ["zeebe:taskListeners"],
134
+ "zeebe:taskListeners": ["bpmn:userTask"],
135
+ "zeebe:taskSchedule": ["bpmn:userTask"],
136
+ "zeebe:userTask": ["bpmn:userTask"],
137
+ "zeebe:userTaskForm": ["bpmn:process"],
138
+ "zeebe:versionTag": ["bpmn:process"],
139
+ };
140
+ //# sourceMappingURL=zeebe-placement.js.map
package/dist/errors.d.ts CHANGED
@@ -1,3 +1,4 @@
1
+ import type { SemanticDiff } from "./bpmn/semantic-hash.js";
1
2
  /**
2
3
  * Typed error codes for all errors thrown by `@bpmnkit/core`.
3
4
  *
@@ -18,7 +19,11 @@ export type ErrorCode =
18
19
  /** XML could not be parsed or a required attribute was missing. */
19
20
  "parse-error"
20
21
  /** A builder received an invalid combination of options. */
21
- | "validation-error";
22
+ | "validation-error"
23
+ /** Serialising a model and reading it back did not reproduce the model. */
24
+ | "write-verification-error"
25
+ /** The output file could not be written. */
26
+ | "write-error";
22
27
  /**
23
28
  * Base class for all errors thrown by `@bpmnkit/core`.
24
29
  *
@@ -74,4 +79,38 @@ export declare class ParseError extends BpmnSdkError {
74
79
  export declare class ValidationError extends BpmnSdkError {
75
80
  constructor(message: string);
76
81
  }
82
+ /**
83
+ * Thrown when serialising a model and parsing the result back does not
84
+ * reproduce the model.
85
+ *
86
+ * This means the write would have put something on disk that no longer says
87
+ * what the model said, so nothing is written. {@link changes} names the
88
+ * elements that diverged.
89
+ *
90
+ * @example
91
+ * ```typescript
92
+ * import { writeBpmn } from "@bpmnkit/core/node"
93
+ * import { WriteVerificationError } from "@bpmnkit/core"
94
+ *
95
+ * try {
96
+ * await writeBpmn(definitions, { output: "flow.bpmn" })
97
+ * } catch (err) {
98
+ * if (err instanceof WriteVerificationError) {
99
+ * console.error("would have lost:", err.changes.removed)
100
+ * }
101
+ * }
102
+ * ```
103
+ */
104
+ export declare class WriteVerificationError extends BpmnSdkError {
105
+ /** What differed between the model and the model read back from the output. */
106
+ readonly changes: SemanticDiff;
107
+ constructor(message: string, changes: SemanticDiff);
108
+ }
109
+ /**
110
+ * Thrown when the output file cannot be written — it already exists and
111
+ * `force` was not given, or the filesystem refused the write.
112
+ */
113
+ export declare class WriteError extends BpmnSdkError {
114
+ constructor(message: string);
115
+ }
77
116
  //# sourceMappingURL=errors.d.ts.map
package/dist/errors.js CHANGED
@@ -63,4 +63,45 @@ export class ValidationError extends BpmnSdkError {
63
63
  this.name = "ValidationError";
64
64
  }
65
65
  }
66
+ /**
67
+ * Thrown when serialising a model and parsing the result back does not
68
+ * reproduce the model.
69
+ *
70
+ * This means the write would have put something on disk that no longer says
71
+ * what the model said, so nothing is written. {@link changes} names the
72
+ * elements that diverged.
73
+ *
74
+ * @example
75
+ * ```typescript
76
+ * import { writeBpmn } from "@bpmnkit/core/node"
77
+ * import { WriteVerificationError } from "@bpmnkit/core"
78
+ *
79
+ * try {
80
+ * await writeBpmn(definitions, { output: "flow.bpmn" })
81
+ * } catch (err) {
82
+ * if (err instanceof WriteVerificationError) {
83
+ * console.error("would have lost:", err.changes.removed)
84
+ * }
85
+ * }
86
+ * ```
87
+ */
88
+ export class WriteVerificationError extends BpmnSdkError {
89
+ /** What differed between the model and the model read back from the output. */
90
+ changes;
91
+ constructor(message, changes) {
92
+ super(message, "write-verification-error");
93
+ this.name = "WriteVerificationError";
94
+ this.changes = changes;
95
+ }
96
+ }
97
+ /**
98
+ * Thrown when the output file cannot be written — it already exists and
99
+ * `force` was not given, or the filesystem refused the write.
100
+ */
101
+ export class WriteError extends BpmnSdkError {
102
+ constructor(message) {
103
+ super(message, "write-error");
104
+ this.name = "WriteError";
105
+ }
106
+ }
66
107
  //# sourceMappingURL=errors.js.map
package/dist/index.d.ts CHANGED
@@ -1,18 +1,24 @@
1
- export { BpmnSdkError, ParseError, ValidationError } from "./errors.js";
1
+ export { BpmnSdkError, ParseError, ValidationError, WriteError, WriteVerificationError, } from "./errors.js";
2
2
  export type { ErrorCode } from "./errors.js";
3
3
  export { isBpmnActivity, isBpmnAdHocSubProcess, isBpmnBoundaryEvent, isBpmnBusinessRuleTask, isBpmnCallActivity, isBpmnComplexGateway, isBpmnDataObject, isBpmnDataObjectReference, isBpmnDataStoreReference, isBpmnEndEvent, isBpmnEvent, isBpmnEventBasedGateway, isBpmnEventSubProcess, isBpmnExclusiveGateway, isBpmnGateway, isBpmnInclusiveGateway, isBpmnIntermediateCatchEvent, isBpmnIntermediateThrowEvent, isBpmnManualTask, isBpmnParallelGateway, isBpmnReceiveTask, isBpmnScriptTask, isBpmnSendTask, isBpmnServiceTask, isBpmnStartEvent, isBpmnSubProcess, isBpmnTask, isBpmnTransaction, isBpmnUserTask, } from "./bpmn/type-guards.js";
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 { diffSemantics, projectSemantics, semanticHash } from "./bpmn/semantic-hash.js";
8
+ export type { JsonValue, SemanticDiff, SemanticProjection } from "./bpmn/semantic-hash.js";
9
+ export { sha256Hex } from "./bpmn/sha256.js";
7
10
  export { checkDiCompleteness } from "./bpmn/di-check.js";
8
11
  export type { DiCompleteness } from "./bpmn/di-check.js";
9
12
  export { planeForElement, listPlaneElementIds } from "./bpmn/di-planes.js";
10
- export { DiagramBuilder } from "./bpmn/bpmn-builder.js";
11
- 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";
13
+ export { DiagramBuilder, ProcessBuilder } from "./bpmn/bpmn-builder.js";
14
+ export type { BranchBuilder, BuildOptions, MessageFlowOptions, ParticipantOptions, DiagramMessageOptions, SubProcessContentBuilder, ServiceTaskOptions, ScriptTaskOptions, UserTaskOptions, CallActivityOptions, BusinessRuleTaskOptions, ElementOptions, GatewayOptions, MultiInstanceOptions, SubProcessOptions, StartEventOptions, IntermediateCatchEventOptions, IntermediateThrowEventOptions, EndEventOptions, BoundaryEventOptions, AdHocSubProcessOptions, } from "./bpmn/bpmn-builder.js";
12
15
  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, BpmnGroup, BpmnDataObject, BpmnDataObjectReference, BpmnDataStoreReference, 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";
13
16
  export type { RestConnectorConfig, RestAuthentication, HttpMethod, } from "./bpmn/rest-connector.js";
14
- export type { ZeebeExtensions, ZeebeTaskDefinition, ZeebeIoMapping, ZeebeIoMappingEntry, ZeebeTaskHeaders, ZeebeTaskHeaderEntry, ZeebeProperties, ZeebePropertyEntry, ZeebeFormDefinition, ZeebeCalledDecision, } from "./bpmn/zeebe-extensions.js";
15
- export { zeebeExtensionsToXmlElements } from "./bpmn/zeebe-extensions.js";
17
+ export type { ZeebeExtensions, ZeebeTaskDefinition, ZeebeIoMapping, ZeebeIoMappingEntry, ZeebeTaskHeaders, ZeebeTaskHeaderEntry, ZeebeProperties, ZeebePropertyEntry, ZeebeFormDefinition, ZeebeCalledDecision, ZeebeAssignmentDefinition, ZeebeTaskSchedule, ZeebePriorityDefinition, ZeebeSubscription, } from "./bpmn/zeebe-extensions.js";
18
+ export { assertZeebePlacement, bpmnElementName, ensureZeebeExtension, isZeebePlacementAllowed, ZeebePlacementError, zeebeExtensionsToXmlElements, } from "./bpmn/zeebe-extensions.js";
19
+ export { ZEEBE_PLACEMENT } from "./bpmn/zeebe-placement.js";
20
+ export { buildAiAgentSubProcess, AI_AGENT_JOB_WORKER_TASK_TYPE, AI_AGENT_DEFAULT_OUTPUT_ELEMENT, } from "./bpmn/agentic.js";
21
+ export type { AiAgentOptions, AiAgentModelConfig, AiAgentToolSpec, AiAgentToolParam, AiAgentToolParamType, AiAgentBuild, } from "./bpmn/agentic.js";
16
22
  export { Dmn, layoutDmn, benchmarkDmnLayout, compactifyDmn, expandDmn } from "./dmn/index.js";
17
23
  export type { DmnBenchmarkResult, DmnElementPosition, CompactDmn, CompactDmnDecision, CompactDmnInput, CompactDmnOutput, CompactDmnRule, } from "./dmn/index.js";
18
24
  export { Form, compactifyForm, expandForm } from "./form/index.js";
@@ -33,6 +39,7 @@ export type { StoryRenderOptions } from "./bpmn/story.js";
33
39
  export { analyzeVariableFlow, extractFeelIdentifiers } from "./bpmn/optimize/variable-flow.js";
34
40
  export type { OptimizationReport, OptimizationFinding, OptimizationSeverity, OptimizationCategory, ApplyFixResult, OptimizeOptions, } from "./bpmn/optimize/types.js";
35
41
  export { layoutProcess, layoutFlowNodes } from "./layout/index.js";
42
+ export type { LayoutEngine } from "./layout/index.js";
36
43
  export { benchmarkLayout, compareLayouts, formatBenchmarkResult, generateAutoLayout, parseReferenceLayout, } from "./layout/index.js";
37
44
  export type { BenchmarkResult, BoundingBox, ElementComparison, ElementPosition, FlowOrderViolation, } from "./layout/index.js";
38
45
  export type { Bounds, LayoutEdge, LayoutNode, LayoutResult, Waypoint } from "./layout/index.js";
@@ -40,9 +47,13 @@ export { ELEMENT_SIZES, GRID_CELL_HEIGHT, GRID_CELL_WIDTH } from "./layout/index
40
47
  export { compactify, expand } from "./bpmn/compact.js";
41
48
  export { applyOperations } from "./bpmn/operations.js";
42
49
  export type { BpmnOperation } from "./bpmn/operations.js";
50
+ export { applyBpmnOperations, reconcileCompact, OperationError } from "./bpmn/full-operations.js";
51
+ export type { ApplyBpmnOperationsOptions, ApplyBpmnOperationsResult, OperationProblem, } from "./bpmn/full-operations.js";
43
52
  export { buildValidationDmn, findValidationStructure, getValidationInputNames, insertValidationStructure, removeValidationStructure, validationDecisionId, } from "./bpmn/input-validation.js";
44
53
  export type { InputVariableDef, ValidationStructure, ValidationVariableType, } from "./bpmn/input-validation.js";
45
54
  export { exportSvg } from "./bpmn/svg.js";
46
55
  export type { SvgExportOptions } from "./bpmn/svg.js";
47
56
  export type { CompactDiagram, CompactElement, CompactFlow, CompactProcess, } from "./bpmn/compact.js";
57
+ export { compilePlan, extractPlan, mergePlan, slugify, uniqueId, } from "./plan/index.js";
58
+ export type { CompilePlanOptions, ConnectorApplyResult, ConnectorResolver, ExtractResult, PlanAgentTool, PlanAiAgentStep, PlanBranch, PlanBusinessRuleTaskStep, PlanCallActivityStep, PlanConnectorRef, PlanConnectorStep, PlanEndStep, PlanErrorBoundary, PlanGatewayStep, PlanInputVariable, PlanProblem, PlanRawStep, PlanReceiveTaskStep, PlanScenario, PlanScriptTaskStep, PlanSendTaskStep, PlanServiceTaskStep, PlanStartStep, PlanStep, PlanSubProcessStep, PlanTimerBoundary, PlanUserTaskStep, PlanWaitStep, ProcessPlan, SynthResult, UnsupportedElement, } from "./plan/index.js";
48
59
  //# sourceMappingURL=index.d.ts.map
package/dist/index.js CHANGED
@@ -1,12 +1,16 @@
1
- export { BpmnSdkError, ParseError, ValidationError } from "./errors.js";
1
+ export { BpmnSdkError, ParseError, ValidationError, WriteError, WriteVerificationError, } from "./errors.js";
2
2
  export { isBpmnActivity, isBpmnAdHocSubProcess, isBpmnBoundaryEvent, isBpmnBusinessRuleTask, isBpmnCallActivity, isBpmnComplexGateway, isBpmnDataObject, isBpmnDataObjectReference, isBpmnDataStoreReference, isBpmnEndEvent, isBpmnEvent, isBpmnEventBasedGateway, isBpmnEventSubProcess, isBpmnExclusiveGateway, isBpmnGateway, isBpmnInclusiveGateway, isBpmnIntermediateCatchEvent, isBpmnIntermediateThrowEvent, isBpmnManualTask, isBpmnParallelGateway, isBpmnReceiveTask, isBpmnScriptTask, isBpmnSendTask, isBpmnServiceTask, isBpmnStartEvent, isBpmnSubProcess, isBpmnTask, isBpmnTransaction, isBpmnUserTask, } from "./bpmn/type-guards.js";
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 { diffSemantics, projectSemantics, semanticHash } from "./bpmn/semantic-hash.js";
7
+ export { sha256Hex } from "./bpmn/sha256.js";
6
8
  export { checkDiCompleteness } from "./bpmn/di-check.js";
7
9
  export { planeForElement, listPlaneElementIds } from "./bpmn/di-planes.js";
8
- export { DiagramBuilder } from "./bpmn/bpmn-builder.js";
9
- export { zeebeExtensionsToXmlElements } from "./bpmn/zeebe-extensions.js";
10
+ export { DiagramBuilder, ProcessBuilder } from "./bpmn/bpmn-builder.js";
11
+ export { assertZeebePlacement, bpmnElementName, ensureZeebeExtension, isZeebePlacementAllowed, ZeebePlacementError, zeebeExtensionsToXmlElements, } from "./bpmn/zeebe-extensions.js";
12
+ export { ZEEBE_PLACEMENT } from "./bpmn/zeebe-placement.js";
13
+ export { buildAiAgentSubProcess, AI_AGENT_JOB_WORKER_TASK_TYPE, AI_AGENT_DEFAULT_OUTPUT_ELEMENT, } from "./bpmn/agentic.js";
10
14
  export { Dmn, layoutDmn, benchmarkDmnLayout, compactifyDmn, expandDmn } from "./dmn/index.js";
11
15
  export { Form, compactifyForm, expandForm } from "./form/index.js";
12
16
  export { FormBuilder, GroupBuilder } from "./form/form-builder.js";
@@ -21,6 +25,8 @@ export { benchmarkLayout, compareLayouts, formatBenchmarkResult, generateAutoLay
21
25
  export { ELEMENT_SIZES, GRID_CELL_HEIGHT, GRID_CELL_WIDTH } from "./layout/index.js";
22
26
  export { compactify, expand } from "./bpmn/compact.js";
23
27
  export { applyOperations } from "./bpmn/operations.js";
28
+ export { applyBpmnOperations, reconcileCompact, OperationError } from "./bpmn/full-operations.js";
24
29
  export { buildValidationDmn, findValidationStructure, getValidationInputNames, insertValidationStructure, removeValidationStructure, validationDecisionId, } from "./bpmn/input-validation.js";
25
30
  export { exportSvg } from "./bpmn/svg.js";
31
+ export { compilePlan, extractPlan, mergePlan, slugify, uniqueId, } from "./plan/index.js";
26
32
  //# sourceMappingURL=index.js.map
@@ -8,6 +8,8 @@ const ELEMENT_GAP = 30; // min gap between annotation and a non-annotation shape
8
8
  const PREFERRED_OFFSET = 50; // preferred gap to associated element
9
9
  const MIN_HEIGHT = 30;
10
10
  const HORIZONTAL_SHIFTS = [0, 60, -60, 120, -120, 180, -180, 240, -240];
11
+ /** Cost added to a candidate whose association line would cross a shape. */
12
+ const BLOCKED_LINE_COST = 10_000;
11
13
  function computeHeight(text, width) {
12
14
  if (!text || !text.trim())
13
15
  return MIN_HEIGHT;
@@ -189,7 +191,17 @@ export function packAnnotations(process, layoutNodes) {
189
191
  }
190
192
  }
191
193
  }
192
- const cost = Math.hypot(candidateX - naturalX, y - naturalY);
194
+ // A clear box is not enough: the association line drawn back to the
195
+ // element must not cut through anything either.
196
+ const candidate = {
197
+ x: candidateX,
198
+ y,
199
+ width: item.bounds.width,
200
+ height: item.bounds.height,
201
+ };
202
+ const { pElem, pAnn } = associationWaypoints(linked.bounds, candidate);
203
+ const crosses = obstacles.some((sh) => sh !== linked.bounds && segmentHitsBox(pElem, pAnn, sh));
204
+ const cost = Math.hypot(candidateX - naturalX, y - naturalY) + (crosses ? BLOCKED_LINE_COST : 0);
193
205
  if (cost < best.cost)
194
206
  best = { x: candidateX, y, cost };
195
207
  }
@@ -218,6 +230,29 @@ export function packAnnotations(process, layoutNodes) {
218
230
  }
219
231
  return result;
220
232
  }
233
+ /** Whether a straight segment passes through a box. */
234
+ function segmentHitsBox(a, b, box) {
235
+ const minX = Math.min(a.x, b.x);
236
+ const maxX = Math.max(a.x, b.x);
237
+ const minY = Math.min(a.y, b.y);
238
+ const maxY = Math.max(a.y, b.y);
239
+ if (maxX <= box.x || box.x + box.width <= minX)
240
+ return false;
241
+ if (maxY <= box.y || box.y + box.height <= minY)
242
+ return false;
243
+ if (a.x === b.x || a.y === b.y)
244
+ return true;
245
+ // Diagonal: the box is hit unless all four corners fall on one side of it.
246
+ const side = (p) => Math.sign((b.x - a.x) * (p.y - a.y) - (b.y - a.y) * (p.x - a.x));
247
+ const corners = [
248
+ { x: box.x, y: box.y },
249
+ { x: box.x + box.width, y: box.y },
250
+ { x: box.x + box.width, y: box.y + box.height },
251
+ { x: box.x, y: box.y + box.height },
252
+ ];
253
+ const first = side(corners[0] ?? { x: 0, y: 0 });
254
+ return corners.some((corner) => side(corner) !== first);
255
+ }
221
256
  /**
222
257
  * Edge-to-edge, clamped association waypoints between a linked element and
223
258
  * its annotation. Port of `chooseWaypoints` (tmp/01-annotation-layouting.cjs:365-389).
@@ -0,0 +1,26 @@
1
+ /**
2
+ * Horizontal alignment between the pools of a collaboration.
3
+ *
4
+ * Each process is laid out on its own, so two elements that exchange a message
5
+ * usually end up at unrelated x positions and the message has to travel sideways
6
+ * to reach its partner. Sliding a whole process sideways costs nothing — the
7
+ * pool grows with it — and a message that leaves straight down crosses far less
8
+ * than one that wanders across two pools first.
9
+ */
10
+ /** One message flow, as the two element centres it connects. */
11
+ export interface MessageLink {
12
+ fromPool: number;
13
+ toPool: number;
14
+ /** x centre of the source element within its pool's content. */
15
+ fromX: number;
16
+ /** x centre of the target element within its pool's content. */
17
+ toX: number;
18
+ }
19
+ /**
20
+ * Choose a horizontal offset per pool. The widest pool anchors the diagram and
21
+ * the rest slide to meet it, largest first, so the biggest process never moves
22
+ * to chase a small one. Offsets are normalised to keep every pool at or right of
23
+ * the origin.
24
+ */
25
+ export declare function alignPools(count: number, widths: readonly number[], links: readonly MessageLink[]): number[];
26
+ //# sourceMappingURL=alignment.d.ts.map
@@ -0,0 +1,66 @@
1
+ /**
2
+ * Horizontal alignment between the pools of a collaboration.
3
+ *
4
+ * Each process is laid out on its own, so two elements that exchange a message
5
+ * usually end up at unrelated x positions and the message has to travel sideways
6
+ * to reach its partner. Sliding a whole process sideways costs nothing — the
7
+ * pool grows with it — and a message that leaves straight down crosses far less
8
+ * than one that wanders across two pools first.
9
+ */
10
+ /**
11
+ * Choose a horizontal offset per pool. The widest pool anchors the diagram and
12
+ * the rest slide to meet it, largest first, so the biggest process never moves
13
+ * to chase a small one. Offsets are normalised to keep every pool at or right of
14
+ * the origin.
15
+ */
16
+ export function alignPools(count, widths, links) {
17
+ const offsets = new Array(count).fill(0);
18
+ if (count < 2 || links.length === 0)
19
+ return offsets;
20
+ const order = Array.from({ length: count }, (_, i) => i).sort((a, b) => (widths[b] ?? 0) - (widths[a] ?? 0) || a - b);
21
+ const placed = new Set();
22
+ const anchor = order[0];
23
+ if (anchor === undefined)
24
+ return offsets;
25
+ placed.add(anchor);
26
+ for (let i = 1; i < order.length; i++) {
27
+ const pool = order[i];
28
+ if (pool === undefined)
29
+ continue;
30
+ const connected = links.filter((link) => (link.fromPool === pool && placed.has(link.toPool)) ||
31
+ (link.toPool === pool && placed.has(link.fromPool)));
32
+ if (connected.length === 0) {
33
+ placed.add(pool);
34
+ continue;
35
+ }
36
+ // Every connected message suggests the shift that would make it vertical;
37
+ // staying put is always in the running.
38
+ const candidates = new Set([0]);
39
+ for (const link of connected) {
40
+ const mine = link.fromPool === pool ? link.fromX : link.toX;
41
+ const theirs = link.fromPool === pool ? link.toX : link.fromX;
42
+ const otherPool = link.fromPool === pool ? link.toPool : link.fromPool;
43
+ candidates.add(theirs + (offsets[otherPool] ?? 0) - mine);
44
+ }
45
+ let best = 0;
46
+ let bestCost = Number.POSITIVE_INFINITY;
47
+ for (const candidate of [...candidates].sort((a, b) => Math.abs(a) - Math.abs(b) || a - b)) {
48
+ let cost = 0;
49
+ for (const link of connected) {
50
+ const mine = link.fromPool === pool ? link.fromX : link.toX;
51
+ const theirs = link.fromPool === pool ? link.toX : link.fromX;
52
+ const otherPool = link.fromPool === pool ? link.toPool : link.fromPool;
53
+ cost += Math.abs(mine + candidate - (theirs + (offsets[otherPool] ?? 0)));
54
+ }
55
+ if (cost < bestCost) {
56
+ bestCost = cost;
57
+ best = candidate;
58
+ }
59
+ }
60
+ offsets[pool] = Math.round(best);
61
+ placed.add(pool);
62
+ }
63
+ const min = Math.min(...offsets);
64
+ return min === 0 ? offsets : offsets.map((offset) => offset - min);
65
+ }
66
+ //# sourceMappingURL=alignment.js.map
@@ -0,0 +1,21 @@
1
+ /**
2
+ * Vertical order of the pools in a collaboration.
3
+ *
4
+ * Message flows read best when the pools they connect sit next to each other,
5
+ * so the order is chosen to minimise how far messages travel vertically rather
6
+ * than left as declared. Small collaborations can afford an exhaustive search;
7
+ * larger ones use repeated remove-and-reinsert, which reaches the same answer on
8
+ * every realistic diagram and never depends on iteration order.
9
+ */
10
+ /** A message-flow relationship between two pools, by index into the input order. */
11
+ export interface PoolLink {
12
+ from: number;
13
+ to: number;
14
+ weight: number;
15
+ }
16
+ /**
17
+ * Order pools by their message-flow relationships. Returns indices into the
18
+ * input order; an input with no message flows comes back unchanged.
19
+ */
20
+ export declare function orderPools(count: number, links: readonly PoolLink[]): number[];
21
+ //# sourceMappingURL=ordering.d.ts.map