eventmodeler 0.5.0 → 0.6.1

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 (150) hide show
  1. package/dist/index.js +6776 -2132
  2. package/package.json +11 -5
  3. package/dist/api/index.d.ts +0 -285
  4. package/dist/api/index.js +0 -323
  5. package/dist/cloud/slices/index.d.ts +0 -276
  6. package/dist/cloud/slices/index.js +0 -406
  7. package/dist/eventmodeler.js +0 -5646
  8. package/dist/formatters.d.ts +0 -17
  9. package/dist/formatters.js +0 -482
  10. package/dist/index.d.ts +0 -2
  11. package/dist/lib/auth.d.ts +0 -24
  12. package/dist/lib/auth.js +0 -331
  13. package/dist/lib/backend.d.ts +0 -43
  14. package/dist/lib/backend.js +0 -73
  15. package/dist/lib/chapter-utils.d.ts +0 -13
  16. package/dist/lib/chapter-utils.js +0 -71
  17. package/dist/lib/cloud-client.d.ts +0 -69
  18. package/dist/lib/cloud-client.js +0 -364
  19. package/dist/lib/config.d.ts +0 -30
  20. package/dist/lib/config.js +0 -95
  21. package/dist/lib/diff/merge-rules.d.ts +0 -45
  22. package/dist/lib/diff/merge-rules.js +0 -210
  23. package/dist/lib/diff/model-differ.d.ts +0 -8
  24. package/dist/lib/diff/model-differ.js +0 -568
  25. package/dist/lib/diff/three-way-merge.d.ts +0 -7
  26. package/dist/lib/diff/three-way-merge.js +0 -390
  27. package/dist/lib/diff/types.d.ts +0 -75
  28. package/dist/lib/diff/types.js +0 -1
  29. package/dist/lib/element-lookup.d.ts +0 -58
  30. package/dist/lib/element-lookup.js +0 -126
  31. package/dist/lib/file-loader.d.ts +0 -8
  32. package/dist/lib/file-loader.js +0 -108
  33. package/dist/lib/flow-utils.d.ts +0 -53
  34. package/dist/lib/flow-utils.js +0 -348
  35. package/dist/lib/format.d.ts +0 -10
  36. package/dist/lib/format.js +0 -23
  37. package/dist/lib/project-config.d.ts +0 -27
  38. package/dist/lib/project-config.js +0 -83
  39. package/dist/lib/slice-utils.d.ts +0 -59
  40. package/dist/lib/slice-utils.js +0 -140
  41. package/dist/local/slices/index.d.ts +0 -11
  42. package/dist/local/slices/index.js +0 -13
  43. package/dist/projection.d.ts +0 -3
  44. package/dist/projection.js +0 -828
  45. package/dist/slices/add-field/index.d.ts +0 -8
  46. package/dist/slices/add-field/index.js +0 -211
  47. package/dist/slices/add-scenario/index.d.ts +0 -27
  48. package/dist/slices/add-scenario/index.js +0 -307
  49. package/dist/slices/codegen-chapter-events/index.d.ts +0 -2
  50. package/dist/slices/codegen-chapter-events/index.js +0 -145
  51. package/dist/slices/codegen-slice/index.d.ts +0 -2
  52. package/dist/slices/codegen-slice/index.js +0 -448
  53. package/dist/slices/create-automation-slice/index.d.ts +0 -2
  54. package/dist/slices/create-automation-slice/index.js +0 -304
  55. package/dist/slices/create-flow/index.d.ts +0 -2
  56. package/dist/slices/create-flow/index.js +0 -183
  57. package/dist/slices/create-state-change-slice/index.d.ts +0 -2
  58. package/dist/slices/create-state-change-slice/index.js +0 -263
  59. package/dist/slices/create-state-view-slice/index.d.ts +0 -2
  60. package/dist/slices/create-state-view-slice/index.js +0 -128
  61. package/dist/slices/diff/index.d.ts +0 -11
  62. package/dist/slices/diff/index.js +0 -293
  63. package/dist/slices/export-eventmodel-to-json/index.d.ts +0 -2
  64. package/dist/slices/export-eventmodel-to-json/index.js +0 -355
  65. package/dist/slices/git/index.d.ts +0 -2
  66. package/dist/slices/git/index.js +0 -125
  67. package/dist/slices/guide/guides/codegen.d.ts +0 -5
  68. package/dist/slices/guide/guides/codegen.js +0 -339
  69. package/dist/slices/guide/guides/connect-slices.d.ts +0 -5
  70. package/dist/slices/guide/guides/connect-slices.js +0 -202
  71. package/dist/slices/guide/guides/create-slices.d.ts +0 -5
  72. package/dist/slices/guide/guides/create-slices.js +0 -303
  73. package/dist/slices/guide/guides/explore.d.ts +0 -5
  74. package/dist/slices/guide/guides/explore.js +0 -251
  75. package/dist/slices/guide/guides/information-flow.d.ts +0 -5
  76. package/dist/slices/guide/guides/information-flow.js +0 -318
  77. package/dist/slices/guide/guides/scenarios.d.ts +0 -5
  78. package/dist/slices/guide/guides/scenarios.js +0 -269
  79. package/dist/slices/guide/index.d.ts +0 -1
  80. package/dist/slices/guide/index.js +0 -40
  81. package/dist/slices/import/index.d.ts +0 -8
  82. package/dist/slices/import/index.js +0 -63
  83. package/dist/slices/init/index.d.ts +0 -5
  84. package/dist/slices/init/index.js +0 -80
  85. package/dist/slices/list-chapters/index.d.ts +0 -3
  86. package/dist/slices/list-chapters/index.js +0 -21
  87. package/dist/slices/list-commands/index.d.ts +0 -3
  88. package/dist/slices/list-commands/index.js +0 -20
  89. package/dist/slices/list-events/index.d.ts +0 -3
  90. package/dist/slices/list-events/index.js +0 -98
  91. package/dist/slices/list-processors/index.d.ts +0 -3
  92. package/dist/slices/list-processors/index.js +0 -20
  93. package/dist/slices/list-readmodels/index.d.ts +0 -3
  94. package/dist/slices/list-readmodels/index.js +0 -21
  95. package/dist/slices/list-scenarios/index.d.ts +0 -3
  96. package/dist/slices/list-scenarios/index.js +0 -35
  97. package/dist/slices/list-screens/index.d.ts +0 -3
  98. package/dist/slices/list-screens/index.js +0 -47
  99. package/dist/slices/list-slices/index.d.ts +0 -3
  100. package/dist/slices/list-slices/index.js +0 -35
  101. package/dist/slices/login/index.d.ts +0 -1
  102. package/dist/slices/login/index.js +0 -20
  103. package/dist/slices/logout/index.d.ts +0 -1
  104. package/dist/slices/logout/index.js +0 -14
  105. package/dist/slices/map-fields/index.d.ts +0 -2
  106. package/dist/slices/map-fields/index.js +0 -269
  107. package/dist/slices/mark-slice-status/index.d.ts +0 -2
  108. package/dist/slices/mark-slice-status/index.js +0 -31
  109. package/dist/slices/merge/index.d.ts +0 -19
  110. package/dist/slices/merge/index.js +0 -147
  111. package/dist/slices/open-app/index.d.ts +0 -1
  112. package/dist/slices/open-app/index.js +0 -36
  113. package/dist/slices/remove-field/index.d.ts +0 -8
  114. package/dist/slices/remove-field/index.js +0 -167
  115. package/dist/slices/remove-scenario/index.d.ts +0 -2
  116. package/dist/slices/remove-scenario/index.js +0 -77
  117. package/dist/slices/search/index.d.ts +0 -3
  118. package/dist/slices/search/index.js +0 -302
  119. package/dist/slices/show-actor/index.d.ts +0 -4
  120. package/dist/slices/show-actor/index.js +0 -115
  121. package/dist/slices/show-aggregate/index.d.ts +0 -3
  122. package/dist/slices/show-aggregate/index.js +0 -108
  123. package/dist/slices/show-aggregate-completeness/index.d.ts +0 -4
  124. package/dist/slices/show-aggregate-completeness/index.js +0 -181
  125. package/dist/slices/show-chapter/index.d.ts +0 -3
  126. package/dist/slices/show-chapter/index.js +0 -195
  127. package/dist/slices/show-command/index.d.ts +0 -3
  128. package/dist/slices/show-command/index.js +0 -133
  129. package/dist/slices/show-completeness/index.d.ts +0 -4
  130. package/dist/slices/show-completeness/index.js +0 -731
  131. package/dist/slices/show-event/index.d.ts +0 -3
  132. package/dist/slices/show-event/index.js +0 -118
  133. package/dist/slices/show-model-summary/index.d.ts +0 -3
  134. package/dist/slices/show-model-summary/index.js +0 -31
  135. package/dist/slices/show-processor/index.d.ts +0 -3
  136. package/dist/slices/show-processor/index.js +0 -111
  137. package/dist/slices/show-readmodel/index.d.ts +0 -3
  138. package/dist/slices/show-readmodel/index.js +0 -158
  139. package/dist/slices/show-scenario/index.d.ts +0 -3
  140. package/dist/slices/show-scenario/index.js +0 -196
  141. package/dist/slices/show-screen/index.d.ts +0 -3
  142. package/dist/slices/show-screen/index.js +0 -139
  143. package/dist/slices/show-slice/index.d.ts +0 -3
  144. package/dist/slices/show-slice/index.js +0 -696
  145. package/dist/slices/update-field/index.d.ts +0 -15
  146. package/dist/slices/update-field/index.js +0 -208
  147. package/dist/slices/whoami/index.d.ts +0 -2
  148. package/dist/slices/whoami/index.js +0 -44
  149. package/dist/types.d.ts +0 -195
  150. package/dist/types.js +0 -1
@@ -1,115 +0,0 @@
1
- import { escapeXml, outputJson } from '../../lib/format.js';
2
- import { findElementOrExit } from '../../lib/element-lookup.js';
3
- // Get screens whose center point is inside the actor bounds
4
- function getScreensInActor(model, actor) {
5
- const bounds = {
6
- left: actor.position.x,
7
- right: actor.position.x + actor.size.width,
8
- top: actor.position.y,
9
- bottom: actor.position.y + actor.size.height,
10
- };
11
- function isInActor(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
- return [...model.screens.values()].filter(s => isInActor(s.position, s.width, s.height));
17
- }
18
- // Find which slice contains a screen
19
- function findSliceForScreen(model, screen) {
20
- for (const slice of model.slices.values()) {
21
- const centerX = screen.position.x + screen.width / 2;
22
- const centerY = screen.position.y + screen.height / 2;
23
- if (centerX >= slice.position.x &&
24
- centerX <= slice.position.x + slice.size.width &&
25
- centerY >= slice.position.y &&
26
- centerY <= slice.position.y + slice.size.height) {
27
- return slice.name;
28
- }
29
- }
30
- return null;
31
- }
32
- export function showActor(model, actorName, format) {
33
- // Find the actor
34
- const actor = findElementOrExit(model.actors, actorName, 'actor');
35
- // Get screens dynamically based on position (center point inside actor bounds)
36
- const screensInActor = getScreensInActor(model, actor);
37
- if (format === 'json') {
38
- outputJson({
39
- id: actor.id,
40
- name: actor.name,
41
- screensCount: screensInActor.length,
42
- screens: screensInActor.map(screen => {
43
- const result = {
44
- id: screen.id,
45
- name: screen.name,
46
- fields: screen.fields.length
47
- };
48
- if (screen.originalNodeId) {
49
- result.linkedCopy = true;
50
- const original = model.screens.get(screen.originalNodeId);
51
- const originSlice = original ? findSliceForScreen(model, original) : null;
52
- if (originSlice)
53
- result.originSlice = originSlice;
54
- }
55
- return result;
56
- })
57
- });
58
- return;
59
- }
60
- console.log(`<actor id="${actor.id}" name="${escapeXml(actor.name)}">`);
61
- console.log(` <screens-count>${screensInActor.length}</screens-count>`);
62
- if (screensInActor.length > 0) {
63
- console.log(' <screens>');
64
- for (const screen of screensInActor) {
65
- const fieldCount = screen.fields.length;
66
- if (screen.originalNodeId) {
67
- // This is a linked copy - show origin info
68
- const original = model.screens.get(screen.originalNodeId);
69
- const originSlice = original ? findSliceForScreen(model, original) : null;
70
- const originAttr = originSlice ? ` origin-slice="${escapeXml(originSlice)}"` : '';
71
- console.log(` <screen id="${screen.id}" name="${escapeXml(screen.name)}" fields="${fieldCount}" linked-copy="true"${originAttr}/>`);
72
- }
73
- else {
74
- console.log(` <screen id="${screen.id}" name="${escapeXml(screen.name)}" fields="${fieldCount}"/>`);
75
- }
76
- }
77
- console.log(' </screens>');
78
- }
79
- console.log('</actor>');
80
- }
81
- export function listActors(model, format) {
82
- const actors = [...model.actors.values()];
83
- if (format === 'json') {
84
- outputJson({
85
- actors: actors.map(actor => {
86
- const screensInActor = getScreensInActor(model, actor);
87
- const originalCount = screensInActor.filter(s => !s.originalNodeId).length;
88
- const copyCount = screensInActor.filter(s => s.originalNodeId).length;
89
- const result = {
90
- id: actor.id,
91
- name: actor.name,
92
- screens: originalCount
93
- };
94
- if (copyCount > 0)
95
- result.copies = copyCount;
96
- return result;
97
- })
98
- });
99
- return;
100
- }
101
- if (actors.length === 0) {
102
- console.log('<actors/>');
103
- return;
104
- }
105
- console.log('<actors>');
106
- for (const actor of actors) {
107
- // Calculate screens dynamically based on position
108
- const screensInActor = getScreensInActor(model, actor);
109
- const originalCount = screensInActor.filter(s => !s.originalNodeId).length;
110
- const copyCount = screensInActor.filter(s => s.originalNodeId).length;
111
- const copiesAttr = copyCount > 0 ? ` copies="${copyCount}"` : '';
112
- console.log(` <actor id="${actor.id}" name="${escapeXml(actor.name)}" screens="${originalCount}"${copiesAttr}/>`);
113
- }
114
- console.log('</actors>');
115
- }
@@ -1,3 +0,0 @@
1
- import type { EventModel } from '../../types.js';
2
- import { type OutputFormat } from '../../lib/format.js';
3
- export declare function showAggregate(model: EventModel, name: string, format: OutputFormat): void;
@@ -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;