eventmodeler 0.5.0 → 0.6.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 (204) hide show
  1. package/dist/api/client-config.js +10 -0
  2. package/dist/api/generated/client/client.gen.js +235 -0
  3. package/dist/api/generated/client/index.js +6 -0
  4. package/dist/api/generated/client/types.gen.js +2 -0
  5. package/dist/api/generated/client/utils.gen.js +228 -0
  6. package/dist/api/generated/client.gen.js +4 -0
  7. package/dist/api/generated/core/auth.gen.js +14 -0
  8. package/dist/api/generated/core/bodySerializer.gen.js +57 -0
  9. package/dist/api/generated/core/params.gen.js +100 -0
  10. package/dist/api/generated/core/pathSerializer.gen.js +106 -0
  11. package/dist/api/generated/core/queryKeySerializer.gen.js +92 -0
  12. package/dist/api/generated/core/serverSentEvents.gen.js +133 -0
  13. package/dist/api/generated/core/types.gen.js +2 -0
  14. package/dist/api/generated/core/utils.gen.js +87 -0
  15. package/dist/api/generated/index.js +2 -0
  16. package/dist/api/generated/sdk.gen.js +4222 -0
  17. package/dist/api/generated/types.gen.js +2 -0
  18. package/dist/api/generated/zod.gen.js +7217 -0
  19. package/dist/commands/add.js +315 -0
  20. package/dist/commands/auth.js +14 -0
  21. package/dist/commands/create.js +192 -0
  22. package/dist/commands/design.js +108 -0
  23. package/dist/commands/guide.js +15 -0
  24. package/dist/commands/init.js +21 -0
  25. package/dist/commands/list-schemas.js +177 -0
  26. package/dist/commands/list.js +39 -0
  27. package/dist/commands/loop.js +101 -0
  28. package/dist/commands/map.js +40 -0
  29. package/dist/commands/mark.js +27 -0
  30. package/dist/commands/move.js +35 -0
  31. package/dist/commands/remove.js +170 -0
  32. package/dist/commands/rename.js +53 -0
  33. package/dist/commands/resize.js +30 -0
  34. package/dist/commands/search.js +14 -0
  35. package/dist/commands/set.js +199 -0
  36. package/dist/commands/show-schemas.js +259 -0
  37. package/dist/commands/show.js +56 -0
  38. package/dist/commands/summary.js +13 -0
  39. package/dist/commands/update.js +240 -0
  40. package/dist/index.js +46 -2379
  41. package/dist/lib/auth.js +1 -1
  42. package/dist/lib/config.js +0 -15
  43. package/dist/lib/excalidraw-schema.js +66 -0
  44. package/dist/lib/globals.js +8 -0
  45. package/dist/lib/model.js +11 -0
  46. package/dist/lib/project-config.js +20 -0
  47. package/dist/lib/resolve.js +59 -0
  48. package/dist/lib/scenario.js +15 -0
  49. package/dist/slices/add-scenario/index.js +2 -206
  50. package/dist/slices/guide/guides/codegen.js +1 -1
  51. package/dist/slices/guide/guides/connect-slices.js +38 -38
  52. package/dist/slices/guide/guides/create-slices.js +110 -140
  53. package/dist/slices/guide/guides/explore.js +37 -50
  54. package/dist/slices/guide/guides/information-flow.js +70 -84
  55. package/dist/slices/guide/guides/scenarios.js +82 -137
  56. package/dist/slices/guide/index.js +6 -6
  57. package/dist/slices/help/index.js +96 -0
  58. package/dist/slices/help/topics/build-codegen.js +109 -0
  59. package/dist/slices/help/topics/build-slice.js +147 -0
  60. package/dist/slices/help/topics/check-completeness.js +57 -0
  61. package/dist/slices/help/topics/connect-slices.js +99 -0
  62. package/dist/slices/help/topics/explore-model.js +112 -0
  63. package/dist/slices/help/topics/json-reference.js +188 -0
  64. package/dist/slices/help/topics/linked-copies.js +89 -0
  65. package/dist/slices/help/topics/manipulate-canvas.js +150 -0
  66. package/dist/slices/help/topics/write-scenarios.js +162 -0
  67. package/dist/slices/init/index.js +10 -4
  68. package/dist/slices/init/loop.js +60 -0
  69. package/dist/slices/login/index.js +2 -2
  70. package/dist/slices/logout/index.js +2 -2
  71. package/dist/slices/whoami/index.js +11 -36
  72. package/package.json +8 -3
  73. package/dist/api/index.d.ts +0 -285
  74. package/dist/api/index.js +0 -323
  75. package/dist/cloud/slices/index.d.ts +0 -276
  76. package/dist/cloud/slices/index.js +0 -406
  77. package/dist/eventmodeler.js +0 -5646
  78. package/dist/formatters.d.ts +0 -17
  79. package/dist/formatters.js +0 -482
  80. package/dist/index.d.ts +0 -2
  81. package/dist/lib/auth.d.ts +0 -24
  82. package/dist/lib/backend.d.ts +0 -43
  83. package/dist/lib/backend.js +0 -73
  84. package/dist/lib/chapter-utils.d.ts +0 -13
  85. package/dist/lib/chapter-utils.js +0 -71
  86. package/dist/lib/cloud-client.d.ts +0 -69
  87. package/dist/lib/cloud-client.js +0 -364
  88. package/dist/lib/config.d.ts +0 -30
  89. package/dist/lib/diff/merge-rules.d.ts +0 -45
  90. package/dist/lib/diff/merge-rules.js +0 -210
  91. package/dist/lib/diff/model-differ.d.ts +0 -8
  92. package/dist/lib/diff/model-differ.js +0 -568
  93. package/dist/lib/diff/three-way-merge.d.ts +0 -7
  94. package/dist/lib/diff/three-way-merge.js +0 -390
  95. package/dist/lib/diff/types.d.ts +0 -75
  96. package/dist/lib/diff/types.js +0 -1
  97. package/dist/lib/element-lookup.d.ts +0 -58
  98. package/dist/lib/element-lookup.js +0 -126
  99. package/dist/lib/file-loader.d.ts +0 -8
  100. package/dist/lib/file-loader.js +0 -108
  101. package/dist/lib/flow-utils.d.ts +0 -53
  102. package/dist/lib/flow-utils.js +0 -348
  103. package/dist/lib/format.d.ts +0 -10
  104. package/dist/lib/format.js +0 -23
  105. package/dist/lib/project-config.d.ts +0 -27
  106. package/dist/lib/slice-utils.d.ts +0 -59
  107. package/dist/lib/slice-utils.js +0 -140
  108. package/dist/local/slices/index.d.ts +0 -11
  109. package/dist/local/slices/index.js +0 -13
  110. package/dist/projection.d.ts +0 -3
  111. package/dist/projection.js +0 -828
  112. package/dist/slices/add-field/index.d.ts +0 -8
  113. package/dist/slices/add-field/index.js +0 -211
  114. package/dist/slices/add-scenario/index.d.ts +0 -27
  115. package/dist/slices/codegen-chapter-events/index.d.ts +0 -2
  116. package/dist/slices/codegen-chapter-events/index.js +0 -145
  117. package/dist/slices/codegen-slice/index.d.ts +0 -2
  118. package/dist/slices/codegen-slice/index.js +0 -448
  119. package/dist/slices/create-automation-slice/index.d.ts +0 -2
  120. package/dist/slices/create-automation-slice/index.js +0 -304
  121. package/dist/slices/create-flow/index.d.ts +0 -2
  122. package/dist/slices/create-flow/index.js +0 -183
  123. package/dist/slices/create-state-change-slice/index.d.ts +0 -2
  124. package/dist/slices/create-state-change-slice/index.js +0 -263
  125. package/dist/slices/create-state-view-slice/index.d.ts +0 -2
  126. package/dist/slices/create-state-view-slice/index.js +0 -128
  127. package/dist/slices/diff/index.d.ts +0 -11
  128. package/dist/slices/diff/index.js +0 -293
  129. package/dist/slices/export-eventmodel-to-json/index.d.ts +0 -2
  130. package/dist/slices/export-eventmodel-to-json/index.js +0 -355
  131. package/dist/slices/git/index.d.ts +0 -2
  132. package/dist/slices/git/index.js +0 -125
  133. package/dist/slices/guide/guides/codegen.d.ts +0 -5
  134. package/dist/slices/guide/guides/connect-slices.d.ts +0 -5
  135. package/dist/slices/guide/guides/create-slices.d.ts +0 -5
  136. package/dist/slices/guide/guides/explore.d.ts +0 -5
  137. package/dist/slices/guide/guides/information-flow.d.ts +0 -5
  138. package/dist/slices/guide/guides/scenarios.d.ts +0 -5
  139. package/dist/slices/guide/index.d.ts +0 -1
  140. package/dist/slices/import/index.d.ts +0 -8
  141. package/dist/slices/import/index.js +0 -63
  142. package/dist/slices/init/index.d.ts +0 -5
  143. package/dist/slices/list-chapters/index.d.ts +0 -3
  144. package/dist/slices/list-chapters/index.js +0 -21
  145. package/dist/slices/list-commands/index.d.ts +0 -3
  146. package/dist/slices/list-commands/index.js +0 -20
  147. package/dist/slices/list-events/index.d.ts +0 -3
  148. package/dist/slices/list-events/index.js +0 -98
  149. package/dist/slices/list-processors/index.d.ts +0 -3
  150. package/dist/slices/list-processors/index.js +0 -20
  151. package/dist/slices/list-readmodels/index.d.ts +0 -3
  152. package/dist/slices/list-readmodels/index.js +0 -21
  153. package/dist/slices/list-scenarios/index.d.ts +0 -3
  154. package/dist/slices/list-scenarios/index.js +0 -35
  155. package/dist/slices/list-screens/index.d.ts +0 -3
  156. package/dist/slices/list-screens/index.js +0 -47
  157. package/dist/slices/list-slices/index.d.ts +0 -3
  158. package/dist/slices/list-slices/index.js +0 -35
  159. package/dist/slices/login/index.d.ts +0 -1
  160. package/dist/slices/logout/index.d.ts +0 -1
  161. package/dist/slices/map-fields/index.d.ts +0 -2
  162. package/dist/slices/map-fields/index.js +0 -269
  163. package/dist/slices/mark-slice-status/index.d.ts +0 -2
  164. package/dist/slices/mark-slice-status/index.js +0 -31
  165. package/dist/slices/merge/index.d.ts +0 -19
  166. package/dist/slices/merge/index.js +0 -147
  167. package/dist/slices/open-app/index.d.ts +0 -1
  168. package/dist/slices/remove-field/index.d.ts +0 -8
  169. package/dist/slices/remove-field/index.js +0 -167
  170. package/dist/slices/remove-scenario/index.d.ts +0 -2
  171. package/dist/slices/remove-scenario/index.js +0 -77
  172. package/dist/slices/search/index.d.ts +0 -3
  173. package/dist/slices/search/index.js +0 -302
  174. package/dist/slices/show-actor/index.d.ts +0 -4
  175. package/dist/slices/show-actor/index.js +0 -115
  176. package/dist/slices/show-aggregate/index.d.ts +0 -3
  177. package/dist/slices/show-aggregate/index.js +0 -108
  178. package/dist/slices/show-aggregate-completeness/index.d.ts +0 -4
  179. package/dist/slices/show-aggregate-completeness/index.js +0 -181
  180. package/dist/slices/show-chapter/index.d.ts +0 -3
  181. package/dist/slices/show-chapter/index.js +0 -195
  182. package/dist/slices/show-command/index.d.ts +0 -3
  183. package/dist/slices/show-command/index.js +0 -133
  184. package/dist/slices/show-completeness/index.d.ts +0 -4
  185. package/dist/slices/show-completeness/index.js +0 -731
  186. package/dist/slices/show-event/index.d.ts +0 -3
  187. package/dist/slices/show-event/index.js +0 -118
  188. package/dist/slices/show-model-summary/index.d.ts +0 -3
  189. package/dist/slices/show-model-summary/index.js +0 -31
  190. package/dist/slices/show-processor/index.d.ts +0 -3
  191. package/dist/slices/show-processor/index.js +0 -111
  192. package/dist/slices/show-readmodel/index.d.ts +0 -3
  193. package/dist/slices/show-readmodel/index.js +0 -158
  194. package/dist/slices/show-scenario/index.d.ts +0 -3
  195. package/dist/slices/show-scenario/index.js +0 -196
  196. package/dist/slices/show-screen/index.d.ts +0 -3
  197. package/dist/slices/show-screen/index.js +0 -139
  198. package/dist/slices/show-slice/index.d.ts +0 -3
  199. package/dist/slices/show-slice/index.js +0 -696
  200. package/dist/slices/update-field/index.d.ts +0 -15
  201. package/dist/slices/update-field/index.js +0 -208
  202. package/dist/slices/whoami/index.d.ts +0 -2
  203. package/dist/types.d.ts +0 -195
  204. package/dist/types.js +0 -1
@@ -1,448 +0,0 @@
1
- import { outputJson } from '../../lib/format.js';
2
- import { findElementOrExit } from '../../lib/element-lookup.js';
3
- import { findChapterForSlice, getChapterHierarchy } from '../../lib/chapter-utils.js';
4
- // Get components inside a slice by checking if center point is within bounds
5
- function getSliceComponents(model, slice) {
6
- const bounds = {
7
- left: slice.position.x,
8
- right: slice.position.x + slice.size.width,
9
- top: slice.position.y,
10
- bottom: slice.position.y + slice.size.height,
11
- };
12
- function isInSlice(pos, width, height) {
13
- const centerX = pos.x + width / 2;
14
- const centerY = pos.y + height / 2;
15
- return centerX >= bounds.left && centerX <= bounds.right && centerY >= bounds.top && centerY <= bounds.bottom;
16
- }
17
- // Only include canonical elements - linked copies are UI-only conveniences
18
- // and should not appear as slice contents in codegen output
19
- return {
20
- commands: [...model.commands.values()].filter(c => isInSlice(c.position, c.width, c.height)),
21
- events: [...model.events.values()].filter(e => !e.originalNodeId && isInSlice(e.position, e.width, e.height)),
22
- readModels: [...model.readModels.values()].filter(rm => !rm.originalNodeId && isInSlice(rm.position, rm.width, rm.height)),
23
- screens: [...model.screens.values()].filter(s => !s.originalNodeId && isInSlice(s.position, s.width, s.height)),
24
- processors: [...model.processors.values()].filter(p => isInSlice(p.position, p.width, p.height)),
25
- };
26
- }
27
- // Find which slice contains a node
28
- function findSliceForNode(model, nodeId) {
29
- const event = model.events.get(nodeId);
30
- const readModel = model.readModels.get(nodeId);
31
- const screen = model.screens.get(nodeId);
32
- const command = model.commands.get(nodeId);
33
- const processor = model.processors.get(nodeId);
34
- const node = event ?? readModel ?? screen ?? command ?? processor;
35
- if (!node)
36
- return null;
37
- for (const slice of model.slices.values()) {
38
- const centerX = node.position.x + node.width / 2;
39
- const centerY = node.position.y + node.height / 2;
40
- if (centerX >= slice.position.x &&
41
- centerX <= slice.position.x + slice.size.width &&
42
- centerY >= slice.position.y &&
43
- centerY <= slice.position.y + slice.size.height) {
44
- return slice;
45
- }
46
- }
47
- return null;
48
- }
49
- // Find which aggregate an event belongs to
50
- function findAggregateForEvent(model, event) {
51
- const centerX = event.position.x + event.width / 2;
52
- const centerY = event.position.y + event.height / 2;
53
- for (const aggregate of model.aggregates.values()) {
54
- if (centerX >= aggregate.position.x &&
55
- centerX <= aggregate.position.x + aggregate.size.width &&
56
- centerY >= aggregate.position.y &&
57
- centerY <= aggregate.position.y + aggregate.size.height) {
58
- return aggregate.name;
59
- }
60
- }
61
- return undefined;
62
- }
63
- // Find which actor a screen belongs to
64
- function findActorForScreen(model, screen) {
65
- const centerX = screen.position.x + screen.width / 2;
66
- const centerY = screen.position.y + screen.height / 2;
67
- for (const actor of model.actors.values()) {
68
- if (centerX >= actor.position.x &&
69
- centerX <= actor.position.x + actor.size.width &&
70
- centerY >= actor.position.y &&
71
- centerY <= actor.position.y + actor.size.height) {
72
- return actor.name;
73
- }
74
- }
75
- return undefined;
76
- }
77
- // Convert Field to JSON-friendly format
78
- function fieldToJson(field) {
79
- const result = {
80
- name: field.name,
81
- type: field.fieldType,
82
- };
83
- if (field.isList)
84
- result.list = true;
85
- if (field.isGenerated)
86
- result.generated = true;
87
- if (field.isOptional)
88
- result.optional = true;
89
- if (field.isUserInput)
90
- result.userInput = true;
91
- if (field.subfields && field.subfields.length > 0) {
92
- result.subfields = field.subfields.map(fieldToJson);
93
- }
94
- return result;
95
- }
96
- // Determine slice type based on components, returns null for invalid configurations
97
- function determineSliceType(hasProcessors, hasCommands, hasEvents, hasReadModels, hasScreens) {
98
- // AUTOMATION: Must have a Processor (and typically ReadModel, Command, Event)
99
- if (hasProcessors)
100
- return 'AUTOMATION';
101
- // STATE_CHANGE: Must have both Command and Event (typically with Screen)
102
- if (hasCommands && hasEvents)
103
- return 'STATE_CHANGE';
104
- // STATE_VIEW: Must have at least one ReadModel
105
- if (hasReadModels && !hasCommands && !hasEvents)
106
- return 'STATE_VIEW';
107
- // Invalid configurations:
108
- // - Empty slice
109
- // - Only Command (no Event)
110
- // - Only Event (no Command)
111
- // - Only Screen (no Command)
112
- return null;
113
- }
114
- // Get element type for an ID
115
- function getElementType(model, id) {
116
- if (model.commands.has(id))
117
- return 'COMMAND';
118
- if (model.events.has(id))
119
- return 'EVENT';
120
- if (model.readModels.has(id))
121
- return 'READMODEL';
122
- if (model.screens.has(id))
123
- return 'SCREEN';
124
- if (model.processors.has(id))
125
- return 'PROCESSOR';
126
- return null;
127
- }
128
- // Get element name for an ID
129
- function getElementName(model, id) {
130
- return (model.commands.get(id)?.name ??
131
- model.events.get(id)?.name ??
132
- model.readModels.get(id)?.name ??
133
- model.screens.get(id)?.name ??
134
- model.processors.get(id)?.name ??
135
- 'Unknown');
136
- }
137
- // Get element fields for an ID
138
- function getElementFields(model, id) {
139
- return (model.commands.get(id)?.fields ??
140
- model.events.get(id)?.fields ??
141
- model.readModels.get(id)?.fields ??
142
- model.screens.get(id)?.fields ??
143
- model.processors.get(id)?.fields ??
144
- []);
145
- }
146
- // Find a field by ID within an element's fields
147
- function findFieldById(fields, fieldId) {
148
- for (const field of fields) {
149
- if (field.id === fieldId)
150
- return field;
151
- if (field.subfields) {
152
- const found = findFieldById(field.subfields, fieldId);
153
- if (found)
154
- return found;
155
- }
156
- }
157
- return undefined;
158
- }
159
- // Get element reference (type, id, name)
160
- function getElementRef(model, id) {
161
- return {
162
- type: getElementType(model, id) ?? 'EVENT',
163
- id,
164
- name: getElementName(model, id),
165
- };
166
- }
167
- // Get element with full schema
168
- function getElementWithSchema(model, id) {
169
- const type = getElementType(model, id) ?? 'EVENT';
170
- const name = getElementName(model, id);
171
- const fields = getElementFields(model, id).map(fieldToJson);
172
- const result = { type, id, name, fields };
173
- // Add aggregate info for events
174
- const event = model.events.get(id);
175
- if (event) {
176
- const aggregate = findAggregateForEvent(model, event);
177
- if (aggregate)
178
- result.aggregate = aggregate;
179
- const originSlice = findSliceForNode(model, id);
180
- if (originSlice)
181
- result.originSlice = originSlice.name;
182
- }
183
- // Add actor info for screens
184
- const screen = model.screens.get(id);
185
- if (screen) {
186
- const actor = findActorForScreen(model, screen);
187
- if (actor)
188
- result.actor = actor;
189
- }
190
- return result;
191
- }
192
- // Enrich field mappings with field names
193
- function enrichFieldMappings(model, flow) {
194
- const sourceFields = getElementFields(model, flow.sourceId);
195
- const targetFields = getElementFields(model, flow.targetId);
196
- return flow.fieldMappings.map(mapping => {
197
- const sourceField = findFieldById(sourceFields, mapping.sourceFieldId);
198
- const targetField = findFieldById(targetFields, mapping.targetFieldId);
199
- return {
200
- sourceFieldId: mapping.sourceFieldId,
201
- sourceFieldName: sourceField?.name ?? 'unknown',
202
- targetFieldId: mapping.targetFieldId,
203
- targetFieldName: targetField?.name ?? 'unknown',
204
- };
205
- });
206
- }
207
- // Get inbound dependencies (flows where target is in slice but source is not)
208
- function getInboundDependencies(model, componentIds) {
209
- return [...model.flows.values()]
210
- .filter(f => componentIds.has(f.targetId) && !componentIds.has(f.sourceId))
211
- .map(flow => ({
212
- flowId: flow.id,
213
- flowType: flow.flowType,
214
- source: getElementWithSchema(model, flow.sourceId),
215
- target: getElementRef(model, flow.targetId),
216
- fieldMappings: enrichFieldMappings(model, flow),
217
- }));
218
- }
219
- // Get internal flows (both source and target are in slice)
220
- function getInternalFlows(model, componentIds) {
221
- return [...model.flows.values()]
222
- .filter(f => componentIds.has(f.sourceId) && componentIds.has(f.targetId))
223
- .map(flow => ({
224
- flowId: flow.id,
225
- flowType: flow.flowType,
226
- source: getElementRef(model, flow.sourceId),
227
- target: getElementRef(model, flow.targetId),
228
- fieldMappings: enrichFieldMappings(model, flow),
229
- }));
230
- }
231
- // Format scenario then clause
232
- function formatScenarioThen(model, then) {
233
- if (then.type === 'error') {
234
- return {
235
- type: 'error',
236
- errorType: then.errorType,
237
- errorMessage: then.errorMessage,
238
- };
239
- }
240
- if (then.type === 'events' && then.expectedEvents) {
241
- return {
242
- type: 'events',
243
- expectedEvents: then.expectedEvents.map(expected => {
244
- const event = model.events.get(expected.eventStickyId);
245
- return {
246
- eventId: expected.eventStickyId,
247
- eventName: event?.name ?? 'UnknownEvent',
248
- eventSchema: { fields: event?.fields.map(fieldToJson) ?? [] },
249
- fieldValues: expected.fieldValues ?? {},
250
- };
251
- }),
252
- };
253
- }
254
- if (then.type === 'command' && then.expectedCommand) {
255
- const command = model.commands.get(then.expectedCommand.commandStickyId);
256
- return {
257
- type: 'command',
258
- expectedCommand: {
259
- commandId: then.expectedCommand.commandStickyId,
260
- commandName: command?.name ?? 'UnknownCommand',
261
- commandSchema: { fields: command?.fields.map(fieldToJson) ?? [] },
262
- fieldValues: then.expectedCommand.fieldValues ?? {},
263
- },
264
- };
265
- }
266
- if (then.type === 'noCommand') {
267
- return {
268
- type: 'noCommand',
269
- };
270
- }
271
- if (then.type === 'readModelAssertion' && then.readModelAssertion) {
272
- const rm = model.readModels.get(then.readModelAssertion.readModelStickyId);
273
- return {
274
- type: 'readModelAssertion',
275
- readModelName: rm?.name ?? 'UnknownReadModel',
276
- expectedFieldValues: then.readModelAssertion.expectedFieldValues,
277
- };
278
- }
279
- // Default fallback
280
- return { type: 'events', expectedEvents: [] };
281
- }
282
- // Format scenarios with resolved schemas
283
- function formatScenarios(model, scenarios) {
284
- return scenarios.map(scenario => ({
285
- id: scenario.id,
286
- name: scenario.name,
287
- description: scenario.description,
288
- given: scenario.givenEvents.map(ref => {
289
- const event = model.events.get(ref.eventStickyId);
290
- const originSlice = findSliceForNode(model, ref.eventStickyId);
291
- return {
292
- eventId: ref.eventStickyId,
293
- eventName: event?.name ?? 'UnknownEvent',
294
- originSlice: originSlice?.name ?? null,
295
- eventSchema: { fields: event?.fields.map(fieldToJson) ?? [] },
296
- fieldValues: ref.fieldValues ?? {},
297
- };
298
- }),
299
- whenCommand: scenario.whenCommand
300
- ? {
301
- commandId: scenario.whenCommand.commandStickyId,
302
- commandName: model.commands.get(scenario.whenCommand.commandStickyId)?.name ?? 'UnknownCommand',
303
- fieldValues: scenario.whenCommand.fieldValues ?? {},
304
- }
305
- : null,
306
- whenEvents: scenario.whenEvents.map(ref => {
307
- const event = model.events.get(ref.eventStickyId);
308
- const originSlice = findSliceForNode(model, ref.eventStickyId);
309
- return {
310
- eventId: ref.eventStickyId,
311
- eventName: event?.name ?? 'UnknownEvent',
312
- originSlice: originSlice?.name ?? null,
313
- eventSchema: { fields: event?.fields.map(fieldToJson) ?? [] },
314
- fieldValues: ref.fieldValues ?? {},
315
- };
316
- }),
317
- then: formatScenarioThen(model, scenario.then),
318
- }));
319
- }
320
- export function codegenSlice(model, sliceName) {
321
- // 1. Find the slice
322
- const slice = findElementOrExit(model.slices, sliceName, 'slice');
323
- // 2. Get components inside slice
324
- const components = getSliceComponents(model, slice);
325
- // 3. Build component ID set (including canonical group members for linked copies)
326
- const componentIds = new Set();
327
- components.commands.forEach(c => componentIds.add(c.id));
328
- components.events.forEach(e => {
329
- componentIds.add(e.id);
330
- // If this is a linked copy, also add all elements in the same canonical group
331
- if (e.canonicalId) {
332
- for (const evt of model.events.values()) {
333
- if (evt.canonicalId === e.canonicalId) {
334
- componentIds.add(evt.id);
335
- }
336
- }
337
- }
338
- });
339
- components.readModels.forEach(rm => {
340
- componentIds.add(rm.id);
341
- // If this is a linked copy, also add all elements in the same canonical group
342
- if (rm.canonicalId) {
343
- for (const r of model.readModels.values()) {
344
- if (r.canonicalId === rm.canonicalId) {
345
- componentIds.add(r.id);
346
- }
347
- }
348
- }
349
- });
350
- components.screens.forEach(s => {
351
- componentIds.add(s.id);
352
- // If this is a linked copy, also add all elements in the same canonical group
353
- if (s.canonicalId) {
354
- for (const scr of model.screens.values()) {
355
- if (scr.canonicalId === s.canonicalId) {
356
- componentIds.add(scr.id);
357
- }
358
- }
359
- }
360
- });
361
- components.processors.forEach(p => componentIds.add(p.id));
362
- // 4. Determine slice type
363
- const sliceType = determineSliceType(components.processors.length > 0, components.commands.length > 0, components.events.length > 0, components.readModels.length > 0, components.screens.length > 0);
364
- // Validate slice type - exit with error for invalid configurations
365
- if (sliceType === null) {
366
- const hasAny = componentIds.size > 0;
367
- if (!hasAny) {
368
- console.error(`Error: Slice "${slice.name}" is empty - no elements found inside slice bounds`);
369
- }
370
- else {
371
- const parts = [];
372
- if (components.commands.length > 0)
373
- parts.push(`${components.commands.length} command(s)`);
374
- if (components.events.length > 0)
375
- parts.push(`${components.events.length} event(s)`);
376
- if (components.screens.length > 0)
377
- parts.push(`${components.screens.length} screen(s)`);
378
- if (components.readModels.length > 0)
379
- parts.push(`${components.readModels.length} read model(s)`);
380
- console.error(`Error: Slice "${slice.name}" has invalid configuration for codegen: ${parts.join(', ')}`);
381
- console.error('Valid configurations:');
382
- console.error(' AUTOMATION: Processor + ReadModel + Command + Event');
383
- console.error(' STATE_CHANGE: Screen + Command + Event');
384
- console.error(' STATE_VIEW: ReadModel only');
385
- }
386
- process.exit(1);
387
- }
388
- // 5. Get inbound dependencies with full schemas
389
- const inboundDependencies = getInboundDependencies(model, componentIds);
390
- // 6. Get internal flows with field mappings
391
- const internalFlows = getInternalFlows(model, componentIds);
392
- // 7. Get scenarios for this slice
393
- const scenarios = [...model.scenarios.values()].filter(s => s.sliceId === slice.id);
394
- // 8. Find which chapter this slice belongs to
395
- const chapter = findChapterForSlice(model, slice);
396
- // 9. Build output
397
- const output = {
398
- sliceType,
399
- slice: {
400
- id: slice.id,
401
- name: slice.name,
402
- },
403
- ...(chapter && { chapter: getChapterHierarchy(model, chapter) }),
404
- elements: {
405
- readModels: components.readModels.map(rm => ({
406
- id: rm.id,
407
- name: rm.name,
408
- fields: rm.fields.map(fieldToJson),
409
- })),
410
- processors: components.processors.map(p => ({
411
- id: p.id,
412
- name: p.name,
413
- })),
414
- commands: components.commands.map(cmd => ({
415
- id: cmd.id,
416
- name: cmd.name,
417
- fields: cmd.fields.map(fieldToJson),
418
- })),
419
- events: components.events.map(evt => {
420
- const result = {
421
- id: evt.id,
422
- name: evt.name,
423
- fields: evt.fields.map(fieldToJson),
424
- };
425
- const aggregate = findAggregateForEvent(model, evt);
426
- if (aggregate)
427
- result.aggregate = aggregate;
428
- return result;
429
- }),
430
- screens: components.screens.map(scr => {
431
- const result = {
432
- id: scr.id,
433
- name: scr.name,
434
- fields: scr.fields.map(fieldToJson),
435
- };
436
- const actor = findActorForScreen(model, scr);
437
- if (actor)
438
- result.actor = actor;
439
- return result;
440
- }),
441
- },
442
- inboundDependencies,
443
- internalFlows,
444
- scenarios: formatScenarios(model, scenarios),
445
- };
446
- // 10. Output JSON
447
- outputJson(output);
448
- }
@@ -1,2 +0,0 @@
1
- import type { EventModel } from '../../types.js';
2
- export declare function createAutomationSlice(model: EventModel, filePath: string, xmlInput: string): void;