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,108 +0,0 @@
1
- import { escapeXml, outputJson } from '../../lib/format.js';
2
- import { findElementOrExit } from '../../lib/element-lookup.js';
3
- // Get events whose center point is inside the aggregate bounds
4
- function getEventsInAggregate(model, aggregate) {
5
- const bounds = {
6
- left: aggregate.position.x,
7
- right: aggregate.position.x + aggregate.size.width,
8
- top: aggregate.position.y,
9
- bottom: aggregate.position.y + aggregate.size.height,
10
- };
11
- function isInAggregate(pos, width, height) {
12
- const centerX = pos.x + width / 2;
13
- const centerY = pos.y + height / 2;
14
- return centerX >= bounds.left && centerX <= bounds.right && centerY >= bounds.top && centerY <= bounds.bottom;
15
- }
16
- // Filter out linked copies
17
- return [...model.events.values()].filter(e => !e.originalNodeId && isInAggregate(e.position, e.width, e.height));
18
- }
19
- // Check if an event has the aggregate's ID field
20
- function hasIdField(event, aggregate) {
21
- if (!aggregate.aggregateIdFieldName) {
22
- return { has: false };
23
- }
24
- const field = event.fields.find(f => f.name === aggregate.aggregateIdFieldName);
25
- if (!field) {
26
- return { has: false };
27
- }
28
- // Check if field type matches (if aggregate has a configured type)
29
- if (aggregate.aggregateIdFieldType && field.fieldType !== aggregate.aggregateIdFieldType) {
30
- return { has: true, fieldType: field.fieldType };
31
- }
32
- return { has: true, fieldType: field.fieldType };
33
- }
34
- export function showAggregate(model, name, format) {
35
- const aggregate = findElementOrExit(model.aggregates, name, 'aggregate');
36
- const events = getEventsInAggregate(model, aggregate);
37
- // Check ID field status for each event
38
- const eventsWithStatus = events.map(event => {
39
- const idStatus = hasIdField(event, aggregate);
40
- return {
41
- event,
42
- hasIdField: idStatus.has,
43
- fieldType: idStatus.fieldType
44
- };
45
- });
46
- // Calculate overall ID field completeness
47
- const hasIdFieldConfig = !!aggregate.aggregateIdFieldName;
48
- const eventsWithId = eventsWithStatus.filter(e => e.hasIdField).length;
49
- const completeness = hasIdFieldConfig && events.length > 0
50
- ? `${eventsWithId}/${events.length}`
51
- : undefined;
52
- if (format === 'json') {
53
- const result = {
54
- id: aggregate.id,
55
- name: aggregate.name,
56
- eventsCount: events.length
57
- };
58
- if (aggregate.aggregateIdFieldName) {
59
- result.idField = {
60
- name: aggregate.aggregateIdFieldName,
61
- type: aggregate.aggregateIdFieldType ?? 'any'
62
- };
63
- result.idFieldCompleteness = completeness;
64
- }
65
- result.events = eventsWithStatus.map(({ event, hasIdField, fieldType }) => {
66
- const eventResult = {
67
- id: event.id,
68
- name: event.name,
69
- fieldsCount: event.fields.length
70
- };
71
- if (hasIdFieldConfig) {
72
- eventResult.hasIdField = hasIdField;
73
- if (hasIdField && fieldType && fieldType !== aggregate.aggregateIdFieldType) {
74
- eventResult.idFieldType = fieldType;
75
- eventResult.typeMatch = false;
76
- }
77
- }
78
- return eventResult;
79
- });
80
- outputJson(result);
81
- return;
82
- }
83
- // XML output
84
- console.log(`<aggregate id="${aggregate.id}" name="${escapeXml(aggregate.name)}">`);
85
- console.log(` <events-count>${events.length}</events-count>`);
86
- if (aggregate.aggregateIdFieldName) {
87
- const typeAttr = aggregate.aggregateIdFieldType ? ` type="${aggregate.aggregateIdFieldType}"` : '';
88
- console.log(` <id-field name="${escapeXml(aggregate.aggregateIdFieldName)}"${typeAttr}/>`);
89
- if (completeness) {
90
- console.log(` <id-field-completeness>${completeness}</id-field-completeness>`);
91
- }
92
- }
93
- if (events.length > 0) {
94
- console.log(' <events>');
95
- for (const { event, hasIdField, fieldType } of eventsWithStatus) {
96
- let attrs = `id="${event.id}" name="${escapeXml(event.name)}" fields="${event.fields.length}"`;
97
- if (hasIdFieldConfig) {
98
- attrs += ` has-id-field="${hasIdField}"`;
99
- if (hasIdField && fieldType && fieldType !== aggregate.aggregateIdFieldType) {
100
- attrs += ` id-field-type="${fieldType}" type-match="false"`;
101
- }
102
- }
103
- console.log(` <event ${attrs}/>`);
104
- }
105
- console.log(' </events>');
106
- }
107
- console.log('</aggregate>');
108
- }
@@ -1,4 +0,0 @@
1
- import type { EventModel } from '../../types.js';
2
- import { type OutputFormat } from '../../lib/format.js';
3
- export declare function showAggregateCompleteness(model: EventModel, aggregateName: string, format: OutputFormat): void;
4
- export declare function listAggregates(model: EventModel, format: OutputFormat): void;
@@ -1,181 +0,0 @@
1
- import { escapeXml, outputJson } from '../../lib/format.js';
2
- import { findElementOrExit } from '../../lib/element-lookup.js';
3
- function findMatchingField(fields, targetName, targetType) {
4
- for (const field of fields) {
5
- // Check if name and type match
6
- if (field.name.toLowerCase() === targetName.toLowerCase() && field.fieldType === targetType) {
7
- return field;
8
- }
9
- // Check nested subfields
10
- if (field.fieldType === 'Custom' && field.subfields) {
11
- const nested = findMatchingField(field.subfields, targetName, targetType);
12
- if (nested)
13
- return nested;
14
- }
15
- }
16
- return undefined;
17
- }
18
- // Get events whose center point is inside the aggregate bounds
19
- // Only returns original events, not linked copies (linked copies have originalNodeId set)
20
- function getEventsInAggregate(model, aggregate) {
21
- const bounds = {
22
- left: aggregate.position.x,
23
- right: aggregate.position.x + aggregate.size.width,
24
- top: aggregate.position.y,
25
- bottom: aggregate.position.y + aggregate.size.height,
26
- };
27
- function isInAggregate(pos, width, height) {
28
- const centerX = pos.x + width / 2;
29
- const centerY = pos.y + height / 2;
30
- return centerX >= bounds.left && centerX <= bounds.right && centerY >= bounds.top && centerY <= bounds.bottom;
31
- }
32
- // Filter out linked copies - only return original events
33
- // Linked copies have originalNodeId set, originals do not
34
- return [...model.events.values()].filter(e => !e.originalNodeId && isInAggregate(e.position, e.width, e.height));
35
- }
36
- export function showAggregateCompleteness(model, aggregateName, format) {
37
- // Find the aggregate
38
- const aggregate = findElementOrExit(model.aggregates, aggregateName, 'aggregate');
39
- // Get events dynamically based on position (center point inside aggregate bounds)
40
- const eventsInAggregate = getEventsInAggregate(model, aggregate);
41
- // Check if aggregate has ID field configured
42
- if (!aggregate.aggregateIdFieldName || !aggregate.aggregateIdFieldType) {
43
- if (format === 'json') {
44
- outputJson({
45
- aggregate: aggregate.name,
46
- status: 'unconfigured',
47
- eventsCount: eventsInAggregate.length,
48
- events: eventsInAggregate.map(e => ({ id: e.id, name: e.name })),
49
- message: 'Aggregate ID field not configured. Set aggregateIdFieldName and aggregateIdFieldType.'
50
- });
51
- return;
52
- }
53
- console.log(`<aggregate-completeness aggregate="${escapeXml(aggregate.name)}" status="unconfigured">`);
54
- console.log(` <events-count>${eventsInAggregate.length}</events-count>`);
55
- console.log(' <events>');
56
- for (const event of eventsInAggregate) {
57
- console.log(` <event id="${event.id}" name="${escapeXml(event.name)}"/>`);
58
- }
59
- console.log(' </events>');
60
- console.log(' <message>Aggregate ID field not configured. Set aggregateIdFieldName and aggregateIdFieldType.</message>');
61
- console.log('</aggregate-completeness>');
62
- return;
63
- }
64
- const idFieldName = aggregate.aggregateIdFieldName;
65
- const idFieldType = aggregate.aggregateIdFieldType;
66
- if (eventsInAggregate.length === 0) {
67
- if (format === 'json') {
68
- outputJson({
69
- aggregate: aggregate.name,
70
- status: 'empty',
71
- idField: { name: idFieldName, type: idFieldType },
72
- message: 'No events in this aggregate.'
73
- });
74
- return;
75
- }
76
- console.log(`<aggregate-completeness aggregate="${escapeXml(aggregate.name)}" status="empty">`);
77
- console.log(` <id-field name="${escapeXml(idFieldName)}" type="${idFieldType}"/>`);
78
- console.log(' <message>No events in this aggregate.</message>');
79
- console.log('</aggregate-completeness>');
80
- return;
81
- }
82
- // Check each event for the ID field
83
- const eventResults = [];
84
- for (const event of eventsInAggregate) {
85
- const matchingField = findMatchingField(event.fields, idFieldName, idFieldType);
86
- eventResults.push({
87
- eventId: event.id,
88
- eventName: event.name,
89
- hasIdField: !!matchingField,
90
- matchingField: matchingField ? {
91
- fieldId: matchingField.id,
92
- fieldName: matchingField.name,
93
- fieldType: matchingField.fieldType,
94
- } : undefined,
95
- });
96
- }
97
- const completeEvents = eventResults.filter(e => e.hasIdField);
98
- const incompleteEvents = eventResults.filter(e => !e.hasIdField);
99
- const isComplete = incompleteEvents.length === 0;
100
- const overallStatus = isComplete ? 'complete' : 'incomplete';
101
- const completionPercent = eventResults.length > 0
102
- ? Math.round((completeEvents.length / eventResults.length) * 100)
103
- : 100;
104
- if (format === 'json') {
105
- outputJson({
106
- aggregate: aggregate.name,
107
- status: overallStatus,
108
- completion: `${completionPercent}%`,
109
- idField: { name: idFieldName, type: idFieldType },
110
- summary: {
111
- total: eventResults.length,
112
- complete: completeEvents.length,
113
- incomplete: incompleteEvents.length
114
- },
115
- incompleteEvents: incompleteEvents.map(e => ({ id: e.eventId, name: e.eventName })),
116
- completeEvents: completeEvents.map(e => ({
117
- id: e.eventId,
118
- name: e.eventName,
119
- fieldId: e.matchingField?.fieldId
120
- }))
121
- });
122
- return;
123
- }
124
- console.log(`<aggregate-completeness aggregate="${escapeXml(aggregate.name)}" status="${overallStatus}" completion="${completionPercent}%">`);
125
- console.log(` <id-field name="${escapeXml(idFieldName)}" type="${idFieldType}"/>`);
126
- console.log(` <summary total="${eventResults.length}" complete="${completeEvents.length}" incomplete="${incompleteEvents.length}"/>`);
127
- if (incompleteEvents.length > 0) {
128
- console.log(' <incomplete-events>');
129
- for (const event of incompleteEvents) {
130
- console.log(` <event id="${event.eventId}" name="${escapeXml(event.eventName)}"/>`);
131
- }
132
- console.log(' </incomplete-events>');
133
- }
134
- if (completeEvents.length > 0) {
135
- console.log(' <complete-events>');
136
- for (const event of completeEvents) {
137
- const fieldAttr = event.matchingField
138
- ? ` field-id="${event.matchingField.fieldId}"`
139
- : '';
140
- console.log(` <event id="${event.eventId}" name="${escapeXml(event.eventName)}"${fieldAttr}/>`);
141
- }
142
- console.log(' </complete-events>');
143
- }
144
- console.log('</aggregate-completeness>');
145
- }
146
- export function listAggregates(model, format) {
147
- const aggregates = [...model.aggregates.values()];
148
- if (format === 'json') {
149
- outputJson({
150
- aggregates: aggregates.map(aggregate => {
151
- const eventsInAggregate = getEventsInAggregate(model, aggregate);
152
- const result = {
153
- id: aggregate.id,
154
- name: aggregate.name,
155
- events: eventsInAggregate.length
156
- };
157
- if (aggregate.aggregateIdFieldName) {
158
- result.idField = aggregate.aggregateIdFieldName;
159
- result.idType = aggregate.aggregateIdFieldType ?? 'Unknown';
160
- }
161
- return result;
162
- })
163
- });
164
- return;
165
- }
166
- if (aggregates.length === 0) {
167
- console.log('<aggregates/>');
168
- return;
169
- }
170
- console.log('<aggregates>');
171
- for (const aggregate of aggregates) {
172
- // Calculate events dynamically based on position
173
- const eventsInAggregate = getEventsInAggregate(model, aggregate);
174
- const eventCount = eventsInAggregate.length;
175
- const idFieldAttr = aggregate.aggregateIdFieldName
176
- ? ` idField="${escapeXml(aggregate.aggregateIdFieldName)}" idType="${aggregate.aggregateIdFieldType ?? 'Unknown'}"`
177
- : '';
178
- console.log(` <aggregate id="${aggregate.id}" name="${escapeXml(aggregate.name)}" events="${eventCount}"${idFieldAttr}/>`);
179
- }
180
- console.log('</aggregates>');
181
- }
@@ -1,3 +0,0 @@
1
- import type { EventModel } from '../../types.js';
2
- import { type OutputFormat } from '../../lib/format.js';
3
- export declare function showChapter(model: EventModel, name: string, format: OutputFormat): void;
@@ -1,195 +0,0 @@
1
- import { escapeXml, outputJson } from '../../lib/format.js';
2
- import { findElementOrExit } from '../../lib/element-lookup.js';
3
- import { getChapterHierarchy, findChapterForSlice } from '../../lib/chapter-utils.js';
4
- import { findSliceToSliceFlows, findChapterInboundFlows, findChapterOutboundFlows, } from '../../lib/flow-utils.js';
5
- function getSlicesUnderChapter(model, chapter) {
6
- // A slice is "under" a chapter if its horizontal center falls within the chapter's x range
7
- const chapterLeft = chapter.position.x;
8
- const chapterRight = chapter.position.x + chapter.size.width;
9
- return [...model.slices.values()].filter(slice => {
10
- const sliceCenterX = slice.position.x + slice.size.width / 2;
11
- return sliceCenterX >= chapterLeft && sliceCenterX <= chapterRight;
12
- }).sort((a, b) => a.position.x - b.position.x);
13
- }
14
- function formatSliceFlowXml(sliceFlow) {
15
- let xml = ` <slice-flow from="${escapeXml(sliceFlow.fromSlice.name)}" to="${escapeXml(sliceFlow.toSlice.name)}">\n`;
16
- for (const flow of sliceFlow.flows) {
17
- xml += ` <via type="${flow.flowType}">\n`;
18
- xml += ` <source element="${escapeXml(flow.source.name)}" type="${flow.source.type}"/>\n`;
19
- xml += ` <target element="${escapeXml(flow.target.name)}" type="${flow.target.type}"/>\n`;
20
- if (flow.fieldMappings.length > 0) {
21
- xml += ' <mappings>\n';
22
- for (const mapping of flow.fieldMappings) {
23
- xml += ` <map from="${escapeXml(mapping.from)}" to="${escapeXml(mapping.to)}"/>\n`;
24
- }
25
- xml += ' </mappings>\n';
26
- }
27
- xml += ' </via>\n';
28
- }
29
- xml += ' </slice-flow>\n';
30
- return xml;
31
- }
32
- function formatExternalFlowXml(flow, direction, model) {
33
- let xml = ` <flow ${direction === 'inbound' ? `to-slice="${escapeXml(flow.targetSlice?.name ?? 'unknown')}"` : `from-slice="${escapeXml(flow.sourceSlice?.name ?? 'unknown')}"`} type="${flow.flowType}">\n`;
34
- // For inbound: source is external, for outbound: target is external
35
- if (direction === 'inbound') {
36
- // Find the chapter of the external source
37
- const sourceSlice = flow.sourceSlice;
38
- let chapterInfo = '';
39
- if (sourceSlice) {
40
- const sourceSliceObj = model.slices.get(sourceSlice.id);
41
- if (sourceSliceObj) {
42
- const sourceChapter = findChapterForSlice(model, sourceSliceObj);
43
- if (sourceChapter) {
44
- chapterInfo = ` chapter="${escapeXml(sourceChapter.name)}"`;
45
- }
46
- }
47
- }
48
- xml += ` <from external="true"${chapterInfo}>${escapeXml(flow.source.name)} (${flow.source.type})</from>\n`;
49
- xml += ` <to>${escapeXml(flow.target.name)} (${flow.target.type})</to>\n`;
50
- }
51
- else {
52
- xml += ` <from>${escapeXml(flow.source.name)} (${flow.source.type})</from>\n`;
53
- // Find the chapter of the external target
54
- const targetSlice = flow.targetSlice;
55
- let chapterInfo = '';
56
- if (targetSlice) {
57
- const targetSliceObj = model.slices.get(targetSlice.id);
58
- if (targetSliceObj) {
59
- const targetChapter = findChapterForSlice(model, targetSliceObj);
60
- if (targetChapter) {
61
- chapterInfo = ` chapter="${escapeXml(targetChapter.name)}"`;
62
- }
63
- }
64
- }
65
- xml += ` <to external="true"${chapterInfo}>${escapeXml(flow.target.name)} (${flow.target.type})</to>\n`;
66
- }
67
- if (flow.fieldMappings.length > 0) {
68
- xml += ' <mappings>\n';
69
- for (const mapping of flow.fieldMappings) {
70
- xml += ` <map from="${escapeXml(mapping.from)}" to="${escapeXml(mapping.to)}"/>\n`;
71
- }
72
- xml += ' </mappings>\n';
73
- }
74
- xml += ' </flow>\n';
75
- return xml;
76
- }
77
- export function showChapter(model, name, format) {
78
- const chapter = findElementOrExit(model.chapters, name, 'chapter');
79
- const slices = getSlicesUnderChapter(model, chapter);
80
- // Get flow information
81
- const sliceToSliceFlows = findSliceToSliceFlows(model, slices);
82
- const chapterInboundFlows = findChapterInboundFlows(model, slices);
83
- const chapterOutboundFlows = findChapterOutboundFlows(model, slices);
84
- if (format === 'json') {
85
- const result = {
86
- id: chapter.id,
87
- name: chapter.name,
88
- parent: chapter ? getChapterHierarchy(model, chapter).parent : undefined,
89
- slices: slices.map(s => ({ id: s.id, name: s.name, status: s.status }))
90
- };
91
- // Add flow graph if there are slice-to-slice flows
92
- if (sliceToSliceFlows.length > 0) {
93
- result.flowGraph = sliceToSliceFlows.map(sf => ({
94
- from: sf.fromSlice.name,
95
- to: sf.toSlice.name,
96
- flows: sf.flows.map(f => ({
97
- type: f.flowType,
98
- source: { element: f.source.name, type: f.source.type },
99
- target: { element: f.target.name, type: f.target.type },
100
- ...(f.fieldMappings.length > 0 && {
101
- mappings: f.fieldMappings.map(m => ({ from: m.from, to: m.to }))
102
- })
103
- }))
104
- }));
105
- }
106
- // Add external dependencies
107
- if (chapterInboundFlows.length > 0 || chapterOutboundFlows.length > 0) {
108
- result.externalDependencies = {
109
- ...(chapterInboundFlows.length > 0 && {
110
- inbound: chapterInboundFlows.map(f => {
111
- const sourceSliceObj = f.sourceSlice ? model.slices.get(f.sourceSlice.id) : null;
112
- const sourceChapter = sourceSliceObj ? findChapterForSlice(model, sourceSliceObj) : null;
113
- return {
114
- toSlice: f.targetSlice?.name,
115
- type: f.flowType,
116
- from: {
117
- element: f.source.name,
118
- type: f.source.type,
119
- slice: f.sourceSlice?.name,
120
- chapter: sourceChapter?.name
121
- },
122
- to: { element: f.target.name, type: f.target.type },
123
- ...(f.fieldMappings.length > 0 && {
124
- mappings: f.fieldMappings.map(m => ({ from: m.from, to: m.to }))
125
- })
126
- };
127
- })
128
- }),
129
- ...(chapterOutboundFlows.length > 0 && {
130
- outbound: chapterOutboundFlows.map(f => {
131
- const targetSliceObj = f.targetSlice ? model.slices.get(f.targetSlice.id) : null;
132
- const targetChapter = targetSliceObj ? findChapterForSlice(model, targetSliceObj) : null;
133
- return {
134
- fromSlice: f.sourceSlice?.name,
135
- type: f.flowType,
136
- from: { element: f.source.name, type: f.source.type },
137
- to: {
138
- element: f.target.name,
139
- type: f.target.type,
140
- slice: f.targetSlice?.name,
141
- chapter: targetChapter?.name
142
- },
143
- ...(f.fieldMappings.length > 0 && {
144
- mappings: f.fieldMappings.map(m => ({ from: m.from, to: m.to }))
145
- })
146
- };
147
- })
148
- })
149
- };
150
- }
151
- outputJson(result);
152
- return;
153
- }
154
- // XML format
155
- console.log(`<chapter id="${chapter.id}" name="${escapeXml(chapter.name)}">`);
156
- // Slices section
157
- if (slices.length === 0) {
158
- console.log(' <slices/>');
159
- }
160
- else {
161
- console.log(' <slices>');
162
- for (const slice of slices) {
163
- console.log(` <slice id="${slice.id}" name="${escapeXml(slice.name)}" status="${slice.status}"/>`);
164
- }
165
- console.log(' </slices>');
166
- }
167
- // Flow graph section
168
- if (sliceToSliceFlows.length > 0) {
169
- console.log(' <flow-graph>');
170
- for (const sliceFlow of sliceToSliceFlows) {
171
- process.stdout.write(formatSliceFlowXml(sliceFlow));
172
- }
173
- console.log(' </flow-graph>');
174
- }
175
- // External dependencies section
176
- if (chapterInboundFlows.length > 0 || chapterOutboundFlows.length > 0) {
177
- console.log(' <external-dependencies>');
178
- if (chapterInboundFlows.length > 0) {
179
- console.log(' <inbound>');
180
- for (const flow of chapterInboundFlows) {
181
- process.stdout.write(formatExternalFlowXml(flow, 'inbound', model));
182
- }
183
- console.log(' </inbound>');
184
- }
185
- if (chapterOutboundFlows.length > 0) {
186
- console.log(' <outbound>');
187
- for (const flow of chapterOutboundFlows) {
188
- process.stdout.write(formatExternalFlowXml(flow, 'outbound', model));
189
- }
190
- console.log(' </outbound>');
191
- }
192
- console.log(' </external-dependencies>');
193
- }
194
- console.log('</chapter>');
195
- }
@@ -1,3 +0,0 @@
1
- import type { EventModel } from '../../types.js';
2
- import { type OutputFormat } from '../../lib/format.js';
3
- export declare function showCommand(model: EventModel, name: string, format: OutputFormat): void;
@@ -1,133 +0,0 @@
1
- import { escapeXml, outputJson } from '../../lib/format.js';
2
- import { findElementOrExit } from '../../lib/element-lookup.js';
3
- function formatFieldXml(field, indent) {
4
- const attrs = [
5
- `name="${escapeXml(field.name)}"`,
6
- `type="${field.fieldType}"`,
7
- ];
8
- if (field.isList)
9
- attrs.push('list="true"');
10
- if (field.isGenerated)
11
- attrs.push('generated="true"');
12
- if (field.isOptional)
13
- attrs.push('optional="true"');
14
- if (field.subfields && field.subfields.length > 0) {
15
- let xml = `${indent}<field ${attrs.join(' ')}>\n`;
16
- for (const subfield of field.subfields) {
17
- xml += formatFieldXml(subfield, indent + ' ');
18
- }
19
- xml += `${indent}</field>\n`;
20
- return xml;
21
- }
22
- return `${indent}<field ${attrs.join(' ')}/>\n`;
23
- }
24
- function fieldToJson(field) {
25
- const result = {
26
- name: field.name,
27
- type: field.fieldType
28
- };
29
- if (field.isList)
30
- result.list = true;
31
- if (field.isGenerated)
32
- result.generated = true;
33
- if (field.isOptional)
34
- result.optional = true;
35
- if (field.subfields && field.subfields.length > 0) {
36
- result.subfields = field.subfields.map(fieldToJson);
37
- }
38
- return result;
39
- }
40
- // Find which aggregate an event belongs to (center point inside aggregate bounds)
41
- function findAggregateForEvent(model, event) {
42
- const centerX = event.position.x + event.width / 2;
43
- const centerY = event.position.y + event.height / 2;
44
- for (const aggregate of model.aggregates.values()) {
45
- const bounds = {
46
- left: aggregate.position.x,
47
- right: aggregate.position.x + aggregate.size.width,
48
- top: aggregate.position.y,
49
- bottom: aggregate.position.y + aggregate.size.height,
50
- };
51
- if (centerX >= bounds.left && centerX <= bounds.right && centerY >= bounds.top && centerY <= bounds.bottom) {
52
- return aggregate;
53
- }
54
- }
55
- return null;
56
- }
57
- function formatCommandXml(model, command) {
58
- let xml = `<command id="${command.id}" name="${escapeXml(command.name)}">\n`;
59
- if (command.fields.length > 0) {
60
- xml += ' <fields>\n';
61
- for (const field of command.fields) {
62
- xml += formatFieldXml(field, ' ');
63
- }
64
- xml += ' </fields>\n';
65
- }
66
- const incomingFlows = [...model.flows.values()].filter(f => f.targetId === command.id);
67
- const outgoingFlows = [...model.flows.values()].filter(f => f.sourceId === command.id);
68
- if (incomingFlows.length > 0) {
69
- xml += ' <triggered-by>\n';
70
- for (const flow of incomingFlows) {
71
- const screen = model.screens.get(flow.sourceId);
72
- const processor = model.processors.get(flow.sourceId);
73
- if (screen)
74
- xml += ` <screen name="${escapeXml(screen.name)}"/>\n`;
75
- if (processor)
76
- xml += ` <processor name="${escapeXml(processor.name)}"/>\n`;
77
- }
78
- xml += ' </triggered-by>\n';
79
- }
80
- if (outgoingFlows.length > 0) {
81
- xml += ' <produces>\n';
82
- for (const flow of outgoingFlows) {
83
- const target = model.events.get(flow.targetId);
84
- if (target) {
85
- const aggregate = findAggregateForEvent(model, target);
86
- const aggregateAttr = aggregate ? ` aggregate="${escapeXml(aggregate.name)}"` : '';
87
- xml += ` <event name="${escapeXml(target.name)}"${aggregateAttr}/>\n`;
88
- }
89
- }
90
- xml += ' </produces>\n';
91
- }
92
- xml += '</command>';
93
- return xml;
94
- }
95
- export function showCommand(model, name, format) {
96
- const command = findElementOrExit(model.commands, name, 'command');
97
- if (format === 'json') {
98
- const incomingFlows = [...model.flows.values()].filter(f => f.targetId === command.id);
99
- const outgoingFlows = [...model.flows.values()].filter(f => f.sourceId === command.id);
100
- const result = {
101
- id: command.id,
102
- name: command.name,
103
- fields: command.fields.map(fieldToJson)
104
- };
105
- const triggeredBy = [];
106
- for (const flow of incomingFlows) {
107
- const screen = model.screens.get(flow.sourceId);
108
- const processor = model.processors.get(flow.sourceId);
109
- if (screen)
110
- triggeredBy.push(screen.name);
111
- if (processor)
112
- triggeredBy.push(processor.name);
113
- }
114
- if (triggeredBy.length > 0)
115
- result.triggeredBy = triggeredBy;
116
- const produces = [];
117
- for (const flow of outgoingFlows) {
118
- const target = model.events.get(flow.targetId);
119
- if (target) {
120
- const aggregate = findAggregateForEvent(model, target);
121
- produces.push({
122
- name: target.name,
123
- ...(aggregate ? { aggregate: aggregate.name } : {})
124
- });
125
- }
126
- }
127
- if (produces.length > 0)
128
- result.produces = produces;
129
- outputJson(result);
130
- return;
131
- }
132
- console.log(formatCommandXml(model, command));
133
- }
@@ -1,4 +0,0 @@
1
- import type { EventModel } from '../../types.js';
2
- import { type OutputFormat } from '../../lib/format.js';
3
- export declare function showCompleteness(model: EventModel, elementName: string, format: OutputFormat): void;
4
- export declare function showModelCompleteness(model: EventModel, format: OutputFormat): void;