@formicoidea/labre-framework-bpmn 0.32.0 → 0.33.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 (47) hide show
  1. package/dist/actions.d.ts +202 -6
  2. package/dist/actions.js +421 -43
  3. package/dist/background.d.ts +2 -0
  4. package/dist/background.js +158 -0
  5. package/dist/commands.js +496 -5
  6. package/dist/consts.d.ts +157 -3
  7. package/dist/consts.js +192 -3
  8. package/dist/element-renderer.d.ts +10 -4
  9. package/dist/element-renderer.js +14 -55
  10. package/dist/element-view.d.ts +100 -8
  11. package/dist/element-view.js +249 -30
  12. package/dist/export.d.ts +277 -0
  13. package/dist/export.js +1802 -0
  14. package/dist/facts.d.ts +48 -0
  15. package/dist/facts.js +127 -0
  16. package/dist/import.d.ts +44 -0
  17. package/dist/import.js +1440 -0
  18. package/dist/index.d.ts +12 -0
  19. package/dist/index.js +44 -0
  20. package/dist/interchange.d.ts +109 -0
  21. package/dist/interchange.js +191 -0
  22. package/dist/morph.d.ts +61 -0
  23. package/dist/morph.js +118 -0
  24. package/dist/node/node-renderer.d.ts +0 -9
  25. package/dist/node/node-renderer.js +294 -17
  26. package/dist/pool-hit.d.ts +98 -0
  27. package/dist/pool-hit.js +130 -0
  28. package/dist/presets.d.ts +114 -0
  29. package/dist/presets.js +232 -0
  30. package/dist/profiles.d.ts +2 -0
  31. package/dist/profiles.js +189 -0
  32. package/dist/roles.d.ts +96 -0
  33. package/dist/roles.js +410 -0
  34. package/dist/rules.d.ts +199 -0
  35. package/dist/rules.js +1539 -0
  36. package/dist/templates/index.js +116 -9
  37. package/dist/toolbar/bpmn-senior-button.js +8 -2
  38. package/dist/toolbar/config.d.ts +27 -2
  39. package/dist/toolbar/config.js +86 -2
  40. package/dist/toolbar/icons.d.ts +67 -0
  41. package/dist/toolbar/icons.js +141 -0
  42. package/dist/toolbar/senior-tool.js +1 -0
  43. package/dist/translations.d.ts +3 -1
  44. package/dist/translations.js +8 -3
  45. package/dist/view.d.ts +6 -2
  46. package/dist/view.js +68 -5
  47. package/package.json +2 -2
@@ -0,0 +1,232 @@
1
+ import { FontFamily, ShapeStyle, StrokeStyle, TextAlign, TextFitMode, TextVerticalAlign, } from '@formicoidea/labre-core/model';
2
+ import { CALL_ACTIVITY_WIDTH, END_WIDTH, EVENT_END, EVENT_START, GROUP_RADIUS, GROUP_STROKE, INNER_FONT_SIZE, NEUTRAL_STROKE, NODE_FILL, NODE_STROKE_WIDTH, START_WIDTH, TASK_RADIUS, } from './consts.js';
3
+ import { BPMN_ROLE_OF_KIND } from './roles.js';
4
+ /** Per-kind native shape + accent presets (style C). */
5
+ export const NODE_PRESETS = {
6
+ // Events: one ellipse, and the ring weight says start or end. The message and
7
+ // timer variants keep their family's ring exactly — a message START is a thin
8
+ // green ring with an envelope in it, and a message END the thick red one.
9
+ startEvent: { shapeType: 'ellipse', stroke: EVENT_START, width: START_WIDTH },
10
+ startEventMessage: {
11
+ shapeType: 'ellipse',
12
+ stroke: EVENT_START,
13
+ width: START_WIDTH,
14
+ },
15
+ startEventTimer: {
16
+ shapeType: 'ellipse',
17
+ stroke: EVENT_START,
18
+ width: START_WIDTH,
19
+ },
20
+ endEvent: { shapeType: 'ellipse', stroke: EVENT_END, width: END_WIDTH },
21
+ endEventMessage: {
22
+ shapeType: 'ellipse',
23
+ stroke: EVENT_END,
24
+ width: END_WIDTH,
25
+ },
26
+ endEventTerminate: {
27
+ shapeType: 'ellipse',
28
+ stroke: EVENT_END,
29
+ width: END_WIDTH,
30
+ },
31
+ // Activities: the same rounded rectangle, and a marker tells them apart —
32
+ // except the call activity, whose thick border IS the distinction (it carries
33
+ // the same `+` as the sub-process).
34
+ task: {
35
+ shapeType: 'rect',
36
+ stroke: NEUTRAL_STROKE,
37
+ width: NODE_STROKE_WIDTH,
38
+ radius: TASK_RADIUS,
39
+ },
40
+ taskUser: {
41
+ shapeType: 'rect',
42
+ stroke: NEUTRAL_STROKE,
43
+ width: NODE_STROKE_WIDTH,
44
+ radius: TASK_RADIUS,
45
+ },
46
+ taskService: {
47
+ shapeType: 'rect',
48
+ stroke: NEUTRAL_STROKE,
49
+ width: NODE_STROKE_WIDTH,
50
+ radius: TASK_RADIUS,
51
+ },
52
+ subProcess: {
53
+ shapeType: 'rect',
54
+ stroke: NEUTRAL_STROKE,
55
+ width: NODE_STROKE_WIDTH,
56
+ radius: TASK_RADIUS,
57
+ },
58
+ callActivity: {
59
+ shapeType: 'rect',
60
+ stroke: NEUTRAL_STROKE,
61
+ width: CALL_ACTIVITY_WIDTH,
62
+ radius: TASK_RADIUS,
63
+ },
64
+ // Gateways: one diamond, one marker each.
65
+ gatewayExclusive: {
66
+ shapeType: 'diamond',
67
+ stroke: NEUTRAL_STROKE,
68
+ width: NODE_STROKE_WIDTH,
69
+ },
70
+ gatewayParallel: {
71
+ shapeType: 'diamond',
72
+ stroke: NEUTRAL_STROKE,
73
+ width: NODE_STROKE_WIDTH,
74
+ },
75
+ // Data and artifacts: body drawn by the glyph (see {@link BpmnNodePreset}).
76
+ dataObject: {
77
+ shapeType: 'rect',
78
+ stroke: NEUTRAL_STROKE,
79
+ width: NODE_STROKE_WIDTH,
80
+ glyphBody: true,
81
+ },
82
+ dataStore: {
83
+ shapeType: 'rect',
84
+ stroke: NEUTRAL_STROKE,
85
+ width: NODE_STROKE_WIDTH,
86
+ glyphBody: true,
87
+ },
88
+ textAnnotation: {
89
+ shapeType: 'rect',
90
+ stroke: NEUTRAL_STROKE,
91
+ width: NODE_STROKE_WIDTH,
92
+ glyphBody: true,
93
+ },
94
+ // The group: a dashed grey outline round part of the picture. Entirely a
95
+ // native shape — no glyph, nothing for the renderer to do — because the
96
+ // notation asks for exactly what `strokeStyle: dash` already draws.
97
+ group: {
98
+ shapeType: 'rect',
99
+ stroke: GROUP_STROKE,
100
+ width: NODE_STROKE_WIDTH,
101
+ radius: GROUP_RADIUS,
102
+ strokeStyle: StrokeStyle.Dash,
103
+ hollow: true,
104
+ textAlign: TextAlign.Left,
105
+ textVerticalAlign: TextVerticalAlign.Top,
106
+ },
107
+ };
108
+ /**
109
+ * One BPMN node, as the props `surface.addElement` takes.
110
+ *
111
+ * The single description of what a `bpmnNode` IS in a document: the palette
112
+ * hands it a box centred on the viewport, the importer hands it the box the
113
+ * file's `dc:Bounds` gave, and the element that lands is the same either way.
114
+ *
115
+ * `text` is passed through unchanged, `undefined` included — an artefact whose
116
+ * label the source left empty gets no `text` key at all rather than an empty
117
+ * one, which is what keeps an imported node byte-comparable with a drawn one
118
+ * that was never typed into.
119
+ */
120
+ export function bpmnNodeProps(kind, box) {
121
+ const preset = NODE_PRESETS[kind];
122
+ return {
123
+ type: 'bpmnNode',
124
+ kind,
125
+ // Semantic identity (B1): posted next to `kind`, which stays untouched and
126
+ // keeps driving the rendering. The role is the authority on what the node
127
+ // MEANS — see the table in `./roles.ts`.
128
+ role: BPMN_ROLE_OF_KIND[kind],
129
+ shapeType: preset.shapeType,
130
+ // A glyph-bodied artefact paints nothing natively: the folded page, the
131
+ // cylinder and the bracket are drawn by the renderer, which reads
132
+ // `fillColor` / `strokeColor` off this same model — so both stay editable
133
+ // from the shape toolbar exactly like every other node's. A `hollow` one
134
+ // paints natively and simply has no body: the group is an outline.
135
+ filled: !preset.glyphBody && !preset.hollow,
136
+ fillColor: NODE_FILL,
137
+ strokeColor: preset.stroke,
138
+ strokeWidth: preset.width,
139
+ strokeStyle: preset.glyphBody
140
+ ? StrokeStyle.None
141
+ : (preset.strokeStyle ?? StrokeStyle.Solid),
142
+ shapeStyle: ShapeStyle.General,
143
+ roughness: 0,
144
+ radius: preset.radius ?? 0,
145
+ text: box.text,
146
+ color: NEUTRAL_STROKE,
147
+ fontFamily: FontFamily.Inter,
148
+ fontSize: INNER_FONT_SIZE,
149
+ textAlign: preset.textAlign ?? TextAlign.Center,
150
+ // Spread, never a defaulted key: the model's own default is already
151
+ // `Center`, so writing it here would put a new key in the Y.Map of every
152
+ // artefact that does not ask for one — the same avoidable payload change
153
+ // review caught on `strokeStyle`.
154
+ ...(preset.textVerticalAlign
155
+ ? { textVerticalAlign: preset.textVerticalAlign }
156
+ : {}),
157
+ // BPMN symbols have normative sizes: a long label overflows rather
158
+ // than deforming the node
159
+ textFitMode: TextFitMode.Overflow,
160
+ xywh: box.xywh,
161
+ };
162
+ }
163
+ /**
164
+ * The box {@link bpmnMorphProps} hands {@link bpmnNodeProps} and then throws
165
+ * away. Never written to a document: a morph keeps the geometry the element
166
+ * already has, and this exists only because the one builder takes a box.
167
+ */
168
+ const DISCARDED_BOX = '[0,0,0,0]';
169
+ /** What a morph must never rewrite: identity, geometry, and the user's words. */
170
+ const NOT_A_MORPH = ['type', 'xywh', 'text'];
171
+ /**
172
+ * What a node's kind is worth to an element that ALREADY EXISTS — the same
173
+ * description as {@link bpmnNodeProps}, minus the three things a morph has no
174
+ * business touching.
175
+ *
176
+ * Derived from the creation builder rather than restated beside it, and that is
177
+ * the whole point of the function.
178
+ *
179
+ * ## Why a `{kind, role}` patch is not enough
180
+ *
181
+ * Because the appearance of a BPMN artefact lives in props the CREATING kind's
182
+ * preset wrote, and nothing else ever rewrites them. One shipped morph pair
183
+ * shows it today: `subProcess` and `callActivity` are the same rounded
184
+ * rectangle and differ only in `strokeWidth` — 2 against 4 — and that thick
185
+ * border IS how a reader tells "this box stands for a process defined
186
+ * elsewhere" from "this box stands for one defined inline". Morph between them
187
+ * with two keys and the call activity arrives wearing the sub-process's thin
188
+ * border, which is a drawing that says the wrong thing.
189
+ *
190
+ * Every other family declared in `./morph.ts` currently shares one preset
191
+ * across its members, so for those the full patch changes nothing — and that is
192
+ * the second reason to write it this way rather than to trim it. A family is
193
+ * DATA (`BPMN_MORPH_FAMILIES`) and grows by declaration, with no code change to
194
+ * prompt anyone to ask whether the presets still agree; deriving the patch from
195
+ * the creation builder means the answer is right in advance. It is also what
196
+ * guarantees that a morphed artefact and one drawn fresh from the palette are
197
+ * the same element — two builders would agree the day they were written and
198
+ * drift on the first restyle, which is the argument this file already makes for
199
+ * having one creation builder at all.
200
+ */
201
+ export function bpmnMorphProps(kind) {
202
+ // Widened to the plain record on the way in: `type` is required on what the
203
+ // creation builder returns, and `delete` may only take an optional key.
204
+ const props = {
205
+ ...bpmnNodeProps(kind, { xywh: DISCARDED_BOX }),
206
+ };
207
+ for (const key of NOT_A_MORPH)
208
+ delete props[key];
209
+ return props;
210
+ }
211
+ /**
212
+ * Every key ANY kind's props may carry — the union over the whole pack.
213
+ *
214
+ * Computed rather than listed, so a preset that starts spreading a second
215
+ * conditional key is covered on the day it is added rather than on the day
216
+ * somebody notices.
217
+ */
218
+ const EVERY_MORPH_KEY = new Set(Object.keys(NODE_PRESETS).flatMap(kind => Object.keys(bpmnMorphProps(kind))));
219
+ /**
220
+ * The fields to DELETE from an element after morphing it to `kind` — the keys
221
+ * some other kind writes and this one does not.
222
+ *
223
+ * A patch cannot express absence. `textVerticalAlign` is spread conditionally
224
+ * (see {@link bpmnNodeProps}), so morphing away from the group would leave
225
+ * `Top` sitting in the Y.Map and silently in force over a preset that means
226
+ * "centred". `clearField` removes the key, which is the same call `writeLanes`
227
+ * makes when a pool loses its last lane.
228
+ */
229
+ export function bpmnMorphClears(kind) {
230
+ const present = new Set(Object.keys(bpmnMorphProps(kind)));
231
+ return [...EVERY_MORPH_KEY].filter(key => !present.has(key));
232
+ }
@@ -0,0 +1,2 @@
1
+ import type { ValidationProfile } from '@formicoidea/labre-core/blocks/surface';
2
+ export declare const BPMN_PROFILES: readonly ValidationProfile[];
@@ -0,0 +1,189 @@
1
+ /**
2
+ * BPMN validation profiles (backlog item B6 — not the rule of that number; see
3
+ * the numbering note in `rules.ts`).
4
+ *
5
+ * DATA owned by the framework, like its rules and its roles. A profile is chosen
6
+ * per POOL — the framework's root instance — and the choice rides on the pool
7
+ * element itself, so two participants at two levels of requirement coexist on one
8
+ * canvas: the pool somebody is still sketching stays a sketch while the one
9
+ * that is being handed over is held to the norm.
10
+ *
11
+ * Registered from the flag-gated `BpmnViewExtension`, beside the rules:
12
+ * switching the `bpmn` flag off takes the choice away with the rest of the
13
+ * tooling, and a pool already set to `descriptive` simply stops being checked
14
+ * until it comes back — the id stays written, untouched.
15
+ *
16
+ * ## Two today, and the two that are future DATA
17
+ *
18
+ * BPMN 2.0 defines three conformance sub-classes, each a superset of the last:
19
+ * DESCRIPTIVE (the visual subset a business reader can follow — the one this
20
+ * pack draws), ANALYTIC (every event type, every gateway, the full flow
21
+ * semantics) and COMMON EXECUTABLE (what an engine can run: data mappings,
22
+ * expressions, message correlation). Only the first is meaningful against the
23
+ * twenty-two rules that exist, because the other two are levels of requirement
24
+ * about artefacts this pack does not yet draw.
25
+ *
26
+ * They arrive as PROFILES and not as engine work when they arrive: a level of
27
+ * requirement is a table of severities per rule id, so `bpmn.analytic` is an
28
+ * entry in the array at the bottom of this file plus whatever new rules the new
29
+ * artefacts bring. Nothing in the pipework has to learn a third word.
30
+ *
31
+ * ## Both tables spell out all TWENTY-TWO ids
32
+ *
33
+ * Every severity a user can get is either the one its rule declares or one of
34
+ * these lines — nothing is raised implicitly (PF9.4). Spelling them all out is
35
+ * also what let eight of these rules wait a review cycle for the engine fields
36
+ * they needed and then arrive already governed, rather than arriving and
37
+ * quietly keeping their own severity at a level nobody had chosen.
38
+ */
39
+ /**
40
+ * Sketch: every rule demoted to `audit`. Findings still reach `violations$` —
41
+ * a host panel and a conformance report see them — and the canvas says nothing.
42
+ *
43
+ * The DEFAULT, and deliberately so (PRD principle 3). A process is drawn in a
44
+ * workshop, at speed, with the steps going down before anybody decides where the
45
+ * pools are: for the first minutes of that, EVERY task is a dead end, no pool has
46
+ * a start event, and half the links are still plain connectors somebody
47
+ * quick-dragged. A tool arguing with that hand is a tool switched off within the
48
+ * hour, and it would be arguing about a diagram the author already knows is
49
+ * unfinished.
50
+ *
51
+ * The sketch PRIMES: the findings are computed, collected and available the
52
+ * moment the author asks — through the panel, through a check-up, through the
53
+ * profile switch — so nothing has to be re-derived when they decide the drawing
54
+ * is a deliverable. Being the default also means it WRITES NOTHING: a pool on
55
+ * `sketch` carries no profile key, so every process ever drawn is on it, with no
56
+ * migration and no backfill.
57
+ */
58
+ const sketch = {
59
+ id: 'bpmn.sketch',
60
+ framework: 'bpmn',
61
+ labelKey: 'com.labre.bpmn.profile.sketch',
62
+ fallback: 'Sketch',
63
+ isDefault: true,
64
+ rules: {
65
+ 'bpmn.sequence-flow-endpoints': 'audit',
66
+ 'bpmn.sequence-flow-self-loop': 'audit',
67
+ 'bpmn.message-flow-endpoints': 'audit',
68
+ 'bpmn.association-endpoints': 'audit',
69
+ 'bpmn.untyped-flow': 'audit',
70
+ 'bpmn.duplicate-sequence-flow': 'audit',
71
+ 'bpmn.start-event-no-inflow': 'audit',
72
+ 'bpmn.start-event-must-exit': 'audit',
73
+ 'bpmn.end-event-no-outflow': 'audit',
74
+ 'bpmn.end-event-must-be-reached': 'audit',
75
+ 'bpmn.activity-dead-end': 'audit',
76
+ 'bpmn.sequence-flow-stays-home': 'audit',
77
+ 'bpmn.message-flow-crosses-pools': 'audit',
78
+ 'bpmn.unreachable-step': 'audit',
79
+ 'bpmn.pool-end-without-start': 'audit',
80
+ 'bpmn.pool-start-without-end': 'audit',
81
+ 'bpmn.single-blank-start': 'audit',
82
+ 'bpmn.gateway-must-branch': 'audit',
83
+ 'bpmn.gateway-join-and-fork': 'audit',
84
+ 'bpmn.fake-join': 'audit',
85
+ 'bpmn.implicit-split': 'audit',
86
+ 'bpmn.unlabeled-step': 'audit',
87
+ },
88
+ };
89
+ /**
90
+ * Descriptive: the BPMN 2.0 DESCRIPTIVE conformance posture — a diagram a
91
+ * business reader can be handed and will read correctly.
92
+ *
93
+ * Every rule at the severity its own declaration carries, spelled out rather
94
+ * than left absent, so the answer is readable in one place. That is the point of
95
+ * a profile table: a reviewer asking "what does this level actually require"
96
+ * reads twenty-two lines instead of twenty-two files, and a rule added later
97
+ * cannot join
98
+ * a level silently — it arrives with its own severity until somebody writes it
99
+ * down here.
100
+ *
101
+ * ## Nothing is `blocking-overridable`, and one line each is what changes that
102
+ *
103
+ * Nothing in this library implements refusal — no gesture is declined anywhere —
104
+ * so declaring the level would be data claiming an effect that does not exist
105
+ * (the `wardley/rules.ts:30` promise, kept). FOUR rules would sit there the day
106
+ * a gesture refusal lands, and each moves in one line, here:
107
+ *
108
+ * - `bpmn.start-event-no-inflow` and `bpmn.end-event-no-outflow` (p.244 / p.248)
109
+ * — both say the process runs backwards, and neither has a reading in which
110
+ * the author is right;
111
+ * - `bpmn.pool-end-without-start` and `bpmn.pool-start-without-end` — verbatim
112
+ * normative MUSTs, guard included: "If there is an End Event, then there MUST
113
+ * be at least one Start Event" (p.238) and its mirror (p.246). The pack argued
114
+ * the pairing into existence before somebody read the pages; the specification
115
+ * simply states it.
116
+ *
117
+ * ## The five that do not move
118
+ *
119
+ * `bpmn.activity-dead-end`, `bpmn.fake-join`, `bpmn.implicit-split`,
120
+ * `bpmn.single-blank-start` and `bpmn.unlabeled-step` stay `audit` HERE TOO, and
121
+ * they are the reason a profile spells everything out.
122
+ *
123
+ * The first three report shapes the specification explicitly SANCTIONS: an
124
+ * activity with no outgoing sequence flow is a way to end a path (BPMN 2.0.2,
125
+ * p.151), and an activity with several incoming or several outgoing flows has
126
+ * defined token semantics on the same page. A warning would be the tool arguing
127
+ * with a house style the standard allows. They stay in the pack because on a
128
+ * diagram meant to be READ each of them is a question the drawing no longer asks
129
+ * out loud — which is a remark for the conformance panel, at every level of
130
+ * requirement. Every one of them is quieter than bpmnlint's own level for the
131
+ * same shape, deliberately.
132
+ *
133
+ * The last two report a diagram that is UNFINISHED rather than wrong — two
134
+ * indistinguishable blank starts, a step nobody has named — and "not done" is
135
+ * what a panel is for.
136
+ *
137
+ * The exact `context-map.acl-on-customer-supplier` shape, one layer over: a
138
+ * judgement the diagram cannot make on the author's behalf, so it is collected
139
+ * and never interrupts.
140
+ *
141
+ * ## Which line is which, now that a rule says so itself
142
+ *
143
+ * Every rule declares {@link ValidationRule.provenance}, so the question this
144
+ * table used to answer only in prose — is this a conformance defect or a
145
+ * suggestion — is readable off the rule. Twelve of them read a normative
146
+ * sentence of the standard, and those are not judgement calls: a message flow
147
+ * inside one pool is a sentence BPMN does not have. The other ten are a linter's
148
+ * rule, a reading nudge, or our own house style, and the bubble now says which
149
+ * before the user decides how much to care.
150
+ */
151
+ const descriptive = {
152
+ id: 'bpmn.descriptive',
153
+ framework: 'bpmn',
154
+ labelKey: 'com.labre.bpmn.profile.descriptive',
155
+ fallback: 'Descriptive',
156
+ rules: {
157
+ 'bpmn.sequence-flow-endpoints': 'warning',
158
+ // A LABRE convention (see B1a), and the one line of this table where that
159
+ // is worth knowing: an organisation that does not share the house style
160
+ // switches it off here without touching p.95, which is the whole point of
161
+ // having split it out of the endpoints rule.
162
+ 'bpmn.sequence-flow-self-loop': 'warning',
163
+ 'bpmn.message-flow-endpoints': 'warning',
164
+ 'bpmn.association-endpoints': 'warning',
165
+ 'bpmn.untyped-flow': 'warning',
166
+ 'bpmn.duplicate-sequence-flow': 'warning',
167
+ 'bpmn.start-event-no-inflow': 'warning',
168
+ 'bpmn.start-event-must-exit': 'warning',
169
+ 'bpmn.end-event-no-outflow': 'warning',
170
+ 'bpmn.end-event-must-be-reached': 'warning',
171
+ // The five that do not move — see the header.
172
+ 'bpmn.activity-dead-end': 'audit',
173
+ 'bpmn.sequence-flow-stays-home': 'warning',
174
+ 'bpmn.message-flow-crosses-pools': 'warning',
175
+ 'bpmn.unreachable-step': 'warning',
176
+ 'bpmn.pool-end-without-start': 'warning',
177
+ 'bpmn.pool-start-without-end': 'warning',
178
+ 'bpmn.single-blank-start': 'audit',
179
+ 'bpmn.gateway-must-branch': 'warning',
180
+ 'bpmn.gateway-join-and-fork': 'warning',
181
+ 'bpmn.fake-join': 'audit',
182
+ 'bpmn.implicit-split': 'audit',
183
+ 'bpmn.unlabeled-step': 'audit',
184
+ },
185
+ };
186
+ export const BPMN_PROFILES = [
187
+ sketch,
188
+ descriptive,
189
+ ];
@@ -0,0 +1,96 @@
1
+ import type { BpmnNodeKind } from '@formicoidea/labre-core/model';
2
+ import type { RoleDefs, RoleId } from '@formicoidea/labre-core/std/gfx';
3
+ /**
4
+ * BPMN role vocabulary (B1).
5
+ *
6
+ * A role is the semantic identity of a BPMN artefact — no rule will ever look at
7
+ * a shape type, and none ever could here: the whole notation is drawn with three
8
+ * native shapes, and an ellipse is a start event, an end event or somebody's
9
+ * doodle depending entirely on what the author meant. The `kind` discriminant
10
+ * the pack already carries answers a different question (which glyph to paint);
11
+ * the role answers what the glyph MEANS.
12
+ *
13
+ * Hierarchy is DATA (`parent`), never TS inheritance: `bpmn:start-event` and
14
+ * `bpmn:end-event` specialise `bpmn:event`, so a rule written on the parent
15
+ * applies to both for free (see `roleIsA`). The three families were declared
16
+ * while the lean pack still shipped one or two children each, precisely so that
17
+ * the descriptive profile could land underneath them without a reshuffle — and
18
+ * that is what happened: the message and timer starts, the message and terminate
19
+ * ends, the user and service tasks, the sub-process, the call activity and the
20
+ * parallel gateway all arrived as LEAVES, and everything already written about
21
+ * "an event" or "an activity" stayed written.
22
+ *
23
+ * The tree is FOUR levels deep on two branches — `bpmn:message-start-event` is a
24
+ * `bpmn:start-event` is a `bpmn:event` is a `bpmn:flow-object`, and
25
+ * `bpmn:user-task` is a `bpmn:task` is a `bpmn:activity` is a
26
+ * `bpmn:flow-object` — which `roleIsA` walks for free.
27
+ *
28
+ * `bpmn:flow-object` arrived with the rules, for the reason its own block gives:
29
+ * a sequence flow chains flow objects and a step must be reachable from the
30
+ * start, and both sentences are about events, activities and gateways at once.
31
+ * It is the one word BPMN itself uses, so the rules say it once instead of
32
+ * enumerating three families and forgetting the fourth.
33
+ *
34
+ * The **pool** is parent-less on purpose, the same call `wardley:map` makes: it
35
+ * is the FRAME the flow objects are drawn in, and a rule written on the artefacts
36
+ * must never fall on the lane they sit in — nor, therefore, under
37
+ * `bpmn:flow-object`. `bpmn:data` is a family of its own for
38
+ * the same reason inverted: a data object is not a flow object, it is never
39
+ * executed, and a rule about the WORK must not fall on the paperwork. And the
40
+ * two artifacts — `bpmn:text-annotation` and `bpmn:group` — are parent-less AND
41
+ * childless, because they are what the author drew ON the picture rather than
42
+ * IN it: a note and a lasso, neither of which says anything the process does.
43
+ * The group's isolation is the spec's own (BPMN 2.0.2 §10.4 exempts it from
44
+ * every connection and containment constraint there is), and the tree is where
45
+ * that exemption is written down.
46
+ *
47
+ * ## Compatibility
48
+ *
49
+ * Nothing is backfilled. A process drawn before today carries nodes, pools and
50
+ * connectors with no role, so it is never evaluated and never says a word — the
51
+ * same promise every role in this library has made (PRD principle 8).
52
+ */
53
+ /** Every role this framework declares. */
54
+ export type BpmnRole = 'flow-object' | 'event' | 'start-event' | 'message-start-event' | 'timer-start-event' | 'end-event' | 'message-end-event' | 'terminate-end-event' | 'activity' | 'task' | 'user-task' | 'service-task' | 'sub-process' | 'call-activity' | 'gateway' | 'gateway-exclusive' | 'parallel-gateway' | 'data' | 'data-object' | 'data-store' | 'text-annotation' | 'group' | 'pool' | 'sequence-flow' | 'message-flow' | 'association';
55
+ export type BpmnRoleId = `bpmn:${BpmnRole}`;
56
+ /** Role ids, keyed by the `kind` used at the creation sites. */
57
+ export declare const BPMN_ROLE: {
58
+ readonly flowObject: "bpmn:flow-object";
59
+ readonly event: "bpmn:event";
60
+ readonly startEvent: "bpmn:start-event";
61
+ readonly startEventMessage: "bpmn:message-start-event";
62
+ readonly startEventTimer: "bpmn:timer-start-event";
63
+ readonly endEvent: "bpmn:end-event";
64
+ readonly endEventMessage: "bpmn:message-end-event";
65
+ readonly endEventTerminate: "bpmn:terminate-end-event";
66
+ readonly activity: "bpmn:activity";
67
+ readonly task: "bpmn:task";
68
+ readonly taskUser: "bpmn:user-task";
69
+ readonly taskService: "bpmn:service-task";
70
+ readonly subProcess: "bpmn:sub-process";
71
+ readonly callActivity: "bpmn:call-activity";
72
+ readonly gateway: "bpmn:gateway";
73
+ readonly gatewayExclusive: "bpmn:gateway-exclusive";
74
+ readonly gatewayParallel: "bpmn:parallel-gateway";
75
+ readonly data: "bpmn:data";
76
+ readonly dataObject: "bpmn:data-object";
77
+ readonly dataStore: "bpmn:data-store";
78
+ readonly textAnnotation: "bpmn:text-annotation";
79
+ readonly group: "bpmn:group";
80
+ readonly pool: "bpmn:pool";
81
+ readonly sequenceFlow: "bpmn:sequence-flow";
82
+ readonly messageFlow: "bpmn:message-flow";
83
+ readonly association: "bpmn:association";
84
+ };
85
+ export declare const BPMN_ROLES: RoleDefs;
86
+ /**
87
+ * The legacy `kind` discriminant → the role it means.
88
+ *
89
+ * `kind` STAYS: it is persisted, it drives the renderer and it is what the
90
+ * palette writes. What it is not, from today, is the semantic authority — the
91
+ * ROLE is. The two are posted side by side at every creation site, the way
92
+ * Wardley already does it, and this table is the single place that says which
93
+ * kind means which role. Total over {@link BpmnNodeKind} by its type, so a new
94
+ * kind cannot land without being given a meaning.
95
+ */
96
+ export declare const BPMN_ROLE_OF_KIND: Record<BpmnNodeKind, RoleId>;