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,293 +0,0 @@
1
- import { execSync } from 'node:child_process';
2
- import * as fs from 'node:fs';
3
- import { loadModel, loadModelFromContent } from '../../lib/file-loader.js';
4
- import { diffModels } from '../../lib/diff/model-differ.js';
5
- import { escapeXml, outputJson } from '../../lib/format.js';
6
- function formatFieldChangeXml(change, indent) {
7
- const typeAttr = change.changeType;
8
- const pathAttr = escapeXml(change.fieldPath);
9
- if (change.changeType === 'added') {
10
- const fieldType = change.newValue?.fieldType ?? 'unknown';
11
- return `${indent}<field-${typeAttr} path="${pathAttr}" type="${fieldType}"/>`;
12
- }
13
- else if (change.changeType === 'removed') {
14
- const fieldType = change.oldValue?.fieldType ?? 'unknown';
15
- return `${indent}<field-${typeAttr} path="${pathAttr}" type="${fieldType}"/>`;
16
- }
17
- else {
18
- const oldType = change.oldValue?.fieldType ?? 'unknown';
19
- const newType = change.newValue?.fieldType ?? 'unknown';
20
- return `${indent}<field-${typeAttr} path="${pathAttr}" old-type="${oldType}" new-type="${newType}"/>`;
21
- }
22
- }
23
- function formatEntityChangeXml(change) {
24
- const lines = [];
25
- const typeAttr = escapeXml(change.entityType);
26
- const nameAttr = escapeXml(change.entityName);
27
- const idAttr = escapeXml(change.entityId);
28
- if (change.changeType === 'added') {
29
- lines.push(` <added type="${typeAttr}" name="${nameAttr}" id="${idAttr}"/>`);
30
- }
31
- else if (change.changeType === 'removed') {
32
- lines.push(` <removed type="${typeAttr}" name="${nameAttr}" id="${idAttr}"/>`);
33
- }
34
- else {
35
- const hasChanges = (change.propertyChanges && change.propertyChanges.length > 0) ||
36
- (change.fieldChanges && change.fieldChanges.length > 0);
37
- if (hasChanges) {
38
- lines.push(` <modified type="${typeAttr}" name="${nameAttr}" id="${idAttr}">`);
39
- if (change.propertyChanges) {
40
- for (const prop of change.propertyChanges) {
41
- const propName = escapeXml(prop.property);
42
- const oldVal = escapeXml(String(prop.oldValue ?? ''));
43
- const newVal = escapeXml(String(prop.newValue ?? ''));
44
- lines.push(` <property-changed name="${propName}" old="${oldVal}" new="${newVal}"/>`);
45
- }
46
- }
47
- if (change.fieldChanges) {
48
- lines.push(' <field-changes>');
49
- for (const fieldChange of change.fieldChanges) {
50
- lines.push(formatFieldChangeXml(fieldChange, ' '));
51
- }
52
- lines.push(' </field-changes>');
53
- }
54
- lines.push(' </modified>');
55
- }
56
- else {
57
- lines.push(` <modified type="${typeAttr}" name="${nameAttr}" id="${idAttr}"/>`);
58
- }
59
- }
60
- return lines.join('\n');
61
- }
62
- function formatFlowChangeXml(change) {
63
- const typeAttr = escapeXml(change.flowType);
64
- const sourceAttr = escapeXml(change.sourceName ?? '');
65
- const targetAttr = escapeXml(change.targetName ?? '');
66
- if (change.changeType === 'added') {
67
- return ` <flow-added type="${typeAttr}" source="${sourceAttr}" target="${targetAttr}"/>`;
68
- }
69
- else if (change.changeType === 'removed') {
70
- return ` <flow-removed type="${typeAttr}" source="${sourceAttr}" target="${targetAttr}"/>`;
71
- }
72
- else {
73
- const mappingCount = change.mappingChanges?.length ?? 0;
74
- return ` <flow-modified type="${typeAttr}" source="${sourceAttr}" target="${targetAttr}" mapping-changes="${mappingCount}"/>`;
75
- }
76
- }
77
- function formatDiffXml(result) {
78
- const lines = [];
79
- lines.push('<diff>');
80
- lines.push(` <summary added="${result.summary.added}" removed="${result.summary.removed}" modified="${result.summary.modified}"/>`);
81
- if (result.entityChanges.length > 0) {
82
- lines.push(' <entity-changes>');
83
- for (const change of result.entityChanges) {
84
- lines.push(formatEntityChangeXml(change));
85
- }
86
- lines.push(' </entity-changes>');
87
- }
88
- if (result.flowChanges.length > 0) {
89
- lines.push(' <flow-changes>');
90
- for (const change of result.flowChanges) {
91
- lines.push(formatFlowChangeXml(change));
92
- }
93
- lines.push(' </flow-changes>');
94
- }
95
- lines.push('</diff>');
96
- return lines.join('\n');
97
- }
98
- function formatDiffJson(result) {
99
- return {
100
- summary: result.summary,
101
- entityChanges: result.entityChanges.map((c) => ({
102
- type: c.entityType,
103
- id: c.entityId,
104
- name: c.entityName,
105
- change: c.changeType,
106
- propertyChanges: c.propertyChanges,
107
- fieldChanges: c.fieldChanges?.map((f) => ({
108
- path: f.fieldPath,
109
- change: f.changeType,
110
- oldType: f.oldValue?.fieldType,
111
- newType: f.newValue?.fieldType,
112
- })),
113
- })),
114
- flowChanges: result.flowChanges.map((c) => ({
115
- id: c.flowId,
116
- type: c.flowType,
117
- change: c.changeType,
118
- source: c.sourceName,
119
- target: c.targetName,
120
- mappingChanges: c.mappingChanges?.length,
121
- })),
122
- };
123
- }
124
- function formatEntityType(type) {
125
- const typeNames = {
126
- command: 'Command',
127
- event: 'Event',
128
- readModel: 'Read Model',
129
- screen: 'Screen',
130
- processor: 'Processor',
131
- slice: 'Slice',
132
- chapter: 'Chapter',
133
- aggregate: 'Aggregate',
134
- actor: 'Actor',
135
- scenario: 'Scenario',
136
- flow: 'Flow',
137
- };
138
- return typeNames[type] ?? type;
139
- }
140
- function formatDiffText(result) {
141
- const lines = [];
142
- const { added, removed, modified } = result.summary;
143
- const total = added + removed + modified;
144
- if (total === 0) {
145
- return 'No changes detected.';
146
- }
147
- lines.push(`${total} change${total === 1 ? '' : 's'}: ${added} added, ${removed} removed, ${modified} modified\n`);
148
- // Group changes by type
149
- const addedChanges = result.entityChanges.filter((c) => c.changeType === 'added');
150
- const removedChanges = result.entityChanges.filter((c) => c.changeType === 'removed');
151
- const modifiedChanges = result.entityChanges.filter((c) => c.changeType === 'modified');
152
- if (addedChanges.length > 0) {
153
- lines.push('Added:');
154
- for (const change of addedChanges) {
155
- lines.push(` + ${formatEntityType(change.entityType)} "${change.entityName}"`);
156
- }
157
- lines.push('');
158
- }
159
- if (removedChanges.length > 0) {
160
- lines.push('Removed:');
161
- for (const change of removedChanges) {
162
- lines.push(` - ${formatEntityType(change.entityType)} "${change.entityName}"`);
163
- }
164
- lines.push('');
165
- }
166
- if (modifiedChanges.length > 0) {
167
- lines.push('Modified:');
168
- for (const change of modifiedChanges) {
169
- lines.push(` ~ ${formatEntityType(change.entityType)} "${change.entityName}"`);
170
- if (change.propertyChanges) {
171
- for (const prop of change.propertyChanges) {
172
- if (prop.property === 'name') {
173
- lines.push(` renamed from "${prop.oldValue}" to "${prop.newValue}"`);
174
- }
175
- else if (prop.property === 'status') {
176
- lines.push(` status: ${prop.oldValue} -> ${prop.newValue}`);
177
- }
178
- else {
179
- lines.push(` ${prop.property} changed`);
180
- }
181
- }
182
- }
183
- if (change.fieldChanges) {
184
- for (const field of change.fieldChanges) {
185
- if (field.changeType === 'added') {
186
- lines.push(` + field "${field.fieldPath}" (${field.newValue?.fieldType})`);
187
- }
188
- else if (field.changeType === 'removed') {
189
- lines.push(` - field "${field.fieldPath}"`);
190
- }
191
- else {
192
- lines.push(` ~ field "${field.fieldPath}": ${field.oldValue?.fieldType} -> ${field.newValue?.fieldType}`);
193
- }
194
- }
195
- }
196
- }
197
- lines.push('');
198
- }
199
- // Flow changes
200
- const addedFlows = result.flowChanges.filter((c) => c.changeType === 'added');
201
- const removedFlows = result.flowChanges.filter((c) => c.changeType === 'removed');
202
- const modifiedFlows = result.flowChanges.filter((c) => c.changeType === 'modified');
203
- if (addedFlows.length > 0) {
204
- lines.push('Flows Added:');
205
- for (const flow of addedFlows) {
206
- lines.push(` + ${flow.sourceName} -> ${flow.targetName}`);
207
- }
208
- lines.push('');
209
- }
210
- if (removedFlows.length > 0) {
211
- lines.push('Flows Removed:');
212
- for (const flow of removedFlows) {
213
- lines.push(` - ${flow.sourceName} -> ${flow.targetName}`);
214
- }
215
- lines.push('');
216
- }
217
- if (modifiedFlows.length > 0) {
218
- lines.push('Flows Modified:');
219
- for (const flow of modifiedFlows) {
220
- const mappingCount = flow.mappingChanges?.length ?? 0;
221
- lines.push(` ~ ${flow.sourceName} -> ${flow.targetName} (${mappingCount} mapping changes)`);
222
- }
223
- lines.push('');
224
- }
225
- return lines.join('\n').trim();
226
- }
227
- /**
228
- * Get file content from a git ref (e.g., HEAD, HEAD~1, branch name)
229
- */
230
- function getGitFileContent(filePath, ref) {
231
- try {
232
- // Get the relative path from the repo root
233
- const repoRoot = execSync('git rev-parse --show-toplevel', { encoding: 'utf-8' }).trim();
234
- const absolutePath = fs.realpathSync(filePath);
235
- const relativePath = absolutePath.replace(repoRoot + '/', '');
236
- const content = execSync(`git show ${ref}:${relativePath}`, {
237
- encoding: 'utf-8',
238
- stdio: ['pipe', 'pipe', 'pipe'],
239
- });
240
- return content;
241
- }
242
- catch {
243
- return null;
244
- }
245
- }
246
- function outputDiff(result, format) {
247
- if (format === 'json') {
248
- outputJson(formatDiffJson(result));
249
- }
250
- else if (format === 'text') {
251
- console.log(formatDiffText(result));
252
- }
253
- else {
254
- console.log(formatDiffXml(result));
255
- }
256
- }
257
- /**
258
- * Diff two eventmodel files or compare a file against a git ref.
259
- *
260
- * Usage:
261
- * diff(file1, file2, format) - Compare two files
262
- * diff(file1, undefined, format, ref) - Compare file against git ref (default: HEAD)
263
- */
264
- export function diff(basePath, comparePath, format, gitRef) {
265
- // Single file mode: compare against git ref
266
- if (!comparePath) {
267
- const ref = gitRef ?? 'HEAD';
268
- const gitContent = getGitFileContent(basePath, ref);
269
- if (gitContent === null) {
270
- console.error(`Error: Could not get ${basePath} from git ref '${ref}'`);
271
- console.error('Make sure the file is tracked by git and the ref exists.');
272
- process.exit(2);
273
- }
274
- const baseModel = loadModelFromContent(gitContent);
275
- const compareModel = loadModel(basePath);
276
- const result = diffModels(baseModel, compareModel);
277
- outputDiff(result, format);
278
- return;
279
- }
280
- // Two file mode: compare two files
281
- if (!fs.existsSync(basePath)) {
282
- console.error(`Error: File not found: ${basePath}`);
283
- process.exit(2);
284
- }
285
- if (!fs.existsSync(comparePath)) {
286
- console.error(`Error: File not found: ${comparePath}`);
287
- process.exit(2);
288
- }
289
- const baseModel = loadModel(basePath);
290
- const compareModel = loadModel(comparePath);
291
- const result = diffModels(baseModel, compareModel);
292
- outputDiff(result, format);
293
- }
@@ -1,2 +0,0 @@
1
- import type { EventModel } from '../../types.js';
2
- export declare function exportEventmodelToJson(model: EventModel): void;
@@ -1,355 +0,0 @@
1
- function mapFieldType(fieldType) {
2
- // Map our field types to spec field types
3
- const typeMap = {
4
- 'UUID': 'UUID',
5
- 'Boolean': 'Boolean',
6
- 'Double': 'Double',
7
- 'Decimal': 'Decimal',
8
- 'Date': 'Date',
9
- 'DateTime': 'DateTime',
10
- 'Long': 'Long',
11
- 'Int': 'Int',
12
- 'String': 'String',
13
- 'Custom': 'Custom',
14
- };
15
- return typeMap[fieldType] || 'String';
16
- }
17
- function mapStatus(status) {
18
- const statusMap = {
19
- 'created': 'Created',
20
- 'done': 'Done',
21
- 'in-progress': 'InProgress',
22
- 'blocked': 'InProgress', // No blocked in spec, map to InProgress
23
- };
24
- return statusMap[status];
25
- }
26
- function convertField(field) {
27
- const specField = {
28
- name: field.name,
29
- type: mapFieldType(field.fieldType),
30
- };
31
- if (field.isOptional)
32
- specField.optional = true;
33
- if (field.isGenerated)
34
- specField.generated = true;
35
- if (field.subfields && field.subfields.length > 0) {
36
- specField.subfields = field.subfields.map(convertField);
37
- }
38
- return specField;
39
- }
40
- function isInSlice(slice, pos, width, height) {
41
- const centerX = pos.x + width / 2;
42
- const centerY = pos.y + height / 2;
43
- return (centerX >= slice.position.x &&
44
- centerX <= slice.position.x + slice.size.width &&
45
- centerY >= slice.position.y &&
46
- centerY <= slice.position.y + slice.size.height);
47
- }
48
- function getInboundDependencies(model, entityId, entityType) {
49
- const deps = [];
50
- for (const flow of model.flows.values()) {
51
- if (flow.targetId === entityId) {
52
- let sourceTitle = '';
53
- let sourceType = 'COMMAND';
54
- const cmd = model.commands.get(flow.sourceId);
55
- const evt = model.events.get(flow.sourceId);
56
- const rm = model.readModels.get(flow.sourceId);
57
- const scr = model.screens.get(flow.sourceId);
58
- const proc = model.processors.get(flow.sourceId);
59
- if (cmd) {
60
- sourceTitle = cmd.name;
61
- sourceType = 'COMMAND';
62
- }
63
- else if (evt) {
64
- sourceTitle = evt.name;
65
- sourceType = 'EVENT';
66
- }
67
- else if (rm) {
68
- sourceTitle = rm.name;
69
- sourceType = 'READMODEL';
70
- }
71
- else if (scr) {
72
- sourceTitle = scr.name;
73
- sourceType = 'SCREEN';
74
- }
75
- else if (proc) {
76
- sourceTitle = proc.name;
77
- sourceType = 'AUTOMATION';
78
- }
79
- if (sourceTitle) {
80
- deps.push({
81
- id: flow.id,
82
- title: sourceTitle,
83
- type: 'INBOUND',
84
- elementType: sourceType,
85
- });
86
- }
87
- }
88
- }
89
- return deps;
90
- }
91
- function getOutboundDependencies(model, entityId, entityType) {
92
- const deps = [];
93
- for (const flow of model.flows.values()) {
94
- if (flow.sourceId === entityId) {
95
- let targetTitle = '';
96
- let targetType = 'EVENT';
97
- const cmd = model.commands.get(flow.targetId);
98
- const evt = model.events.get(flow.targetId);
99
- const rm = model.readModels.get(flow.targetId);
100
- const scr = model.screens.get(flow.targetId);
101
- const proc = model.processors.get(flow.targetId);
102
- if (cmd) {
103
- targetTitle = cmd.name;
104
- targetType = 'COMMAND';
105
- }
106
- else if (evt) {
107
- targetTitle = evt.name;
108
- targetType = 'EVENT';
109
- }
110
- else if (rm) {
111
- targetTitle = rm.name;
112
- targetType = 'READMODEL';
113
- }
114
- else if (scr) {
115
- targetTitle = scr.name;
116
- targetType = 'SCREEN';
117
- }
118
- else if (proc) {
119
- targetTitle = proc.name;
120
- targetType = 'AUTOMATION';
121
- }
122
- if (targetTitle) {
123
- deps.push({
124
- id: flow.id,
125
- title: targetTitle,
126
- type: 'OUTBOUND',
127
- elementType: targetType,
128
- });
129
- }
130
- }
131
- }
132
- return deps;
133
- }
134
- function determineSliceType(commands, events, processors) {
135
- // If there are processors, it's an automation slice
136
- if (processors.length > 0)
137
- return 'AUTOMATION';
138
- // If there are commands and events, it's a state change
139
- if (commands.length > 0 && events.length > 0)
140
- return 'STATE_CHANGE';
141
- // Otherwise it's a state view (read-only)
142
- return 'STATE_VIEW';
143
- }
144
- // Check if two rectangles overlap
145
- function rectanglesOverlap(r1, r2) {
146
- return (r1.x < r2.x + r2.width &&
147
- r1.x + r1.width > r2.x &&
148
- r1.y < r2.y + r2.height &&
149
- r1.y + r1.height > r2.y);
150
- }
151
- // Find aggregates that overlap with the slice
152
- function getAggregatesForSlice(model, slice) {
153
- const sliceRect = {
154
- x: slice.position.x,
155
- y: slice.position.y,
156
- width: slice.size.width,
157
- height: slice.size.height,
158
- };
159
- const aggregateNames = [];
160
- for (const aggregate of model.aggregates.values()) {
161
- const aggRect = {
162
- x: aggregate.position.x,
163
- y: aggregate.position.y,
164
- width: aggregate.size.width,
165
- height: aggregate.size.height,
166
- };
167
- if (rectanglesOverlap(sliceRect, aggRect)) {
168
- aggregateNames.push(aggregate.name);
169
- }
170
- }
171
- return aggregateNames;
172
- }
173
- // Find actors that overlap with the slice
174
- function getActorsForSlice(model, slice) {
175
- const sliceRect = {
176
- x: slice.position.x,
177
- y: slice.position.y,
178
- width: slice.size.width,
179
- height: slice.size.height,
180
- };
181
- const actors = [];
182
- for (const actor of model.actors.values()) {
183
- const actorRect = {
184
- x: actor.position.x,
185
- y: actor.position.y,
186
- width: actor.size.width,
187
- height: actor.size.height,
188
- };
189
- if (rectanglesOverlap(sliceRect, actorRect)) {
190
- actors.push({
191
- name: actor.name,
192
- authRequired: false, // Default - we don't track this property yet
193
- });
194
- }
195
- }
196
- return actors;
197
- }
198
- export function exportEventmodelToJson(model) {
199
- const specSlices = [];
200
- // Sort slices by position
201
- const sortedSlices = [...model.slices.values()].sort((a, b) => a.position.x - b.position.x);
202
- for (const slice of sortedSlices) {
203
- // Find components in this slice
204
- const commands = [];
205
- const events = [];
206
- const readModels = [];
207
- const screens = [];
208
- const processors = [];
209
- for (const cmd of model.commands.values()) {
210
- if (isInSlice(slice, cmd.position, cmd.width, cmd.height)) {
211
- commands.push(cmd);
212
- }
213
- }
214
- // Filter out linked copies - only export originals
215
- for (const evt of model.events.values()) {
216
- if (!evt.originalNodeId && isInSlice(slice, evt.position, evt.width, evt.height)) {
217
- events.push(evt);
218
- }
219
- }
220
- // Filter out linked copies - only export originals
221
- for (const rm of model.readModels.values()) {
222
- if (!rm.originalNodeId && isInSlice(slice, rm.position, rm.width, rm.height)) {
223
- readModels.push(rm);
224
- }
225
- }
226
- // Filter out linked copies - only export originals
227
- for (const scr of model.screens.values()) {
228
- if (!scr.originalNodeId && isInSlice(slice, scr.position, scr.width, scr.height)) {
229
- screens.push(scr);
230
- }
231
- }
232
- for (const proc of model.processors.values()) {
233
- if (isInSlice(slice, proc.position, proc.width, proc.height)) {
234
- processors.push(proc);
235
- }
236
- }
237
- // Find scenarios for this slice
238
- const scenarios = [...model.scenarios.values()].filter(s => s.sliceId === slice.id);
239
- // Convert to spec format
240
- const specSlice = {
241
- id: slice.id,
242
- title: slice.name,
243
- sliceType: determineSliceType(commands, events, processors),
244
- status: mapStatus(slice.status),
245
- commands: commands.map(cmd => ({
246
- id: cmd.id,
247
- title: cmd.name,
248
- type: 'COMMAND',
249
- fields: cmd.fields.map(convertField),
250
- dependencies: [
251
- ...getInboundDependencies(model, cmd.id, 'COMMAND'),
252
- ...getOutboundDependencies(model, cmd.id, 'COMMAND'),
253
- ],
254
- })),
255
- events: events.map(evt => ({
256
- id: evt.id,
257
- title: evt.name,
258
- type: 'EVENT',
259
- fields: evt.fields.map(convertField),
260
- dependencies: [
261
- ...getInboundDependencies(model, evt.id, 'EVENT'),
262
- ...getOutboundDependencies(model, evt.id, 'EVENT'),
263
- ],
264
- })),
265
- readmodels: readModels.map(rm => ({
266
- id: rm.id,
267
- title: rm.name,
268
- type: 'READMODEL',
269
- fields: rm.fields.map(convertField),
270
- dependencies: [
271
- ...getInboundDependencies(model, rm.id, 'READMODEL'),
272
- ...getOutboundDependencies(model, rm.id, 'READMODEL'),
273
- ],
274
- })),
275
- screens: screens.map(scr => ({
276
- id: scr.id,
277
- title: scr.name,
278
- type: 'SCREEN',
279
- fields: scr.fields.map(convertField),
280
- dependencies: [
281
- ...getInboundDependencies(model, scr.id, 'SCREEN'),
282
- ...getOutboundDependencies(model, scr.id, 'SCREEN'),
283
- ],
284
- })),
285
- processors: processors.map(proc => ({
286
- id: proc.id,
287
- title: proc.name,
288
- type: 'AUTOMATION',
289
- fields: proc.fields.map(convertField),
290
- dependencies: [
291
- ...getInboundDependencies(model, proc.id, 'AUTOMATION'),
292
- ...getOutboundDependencies(model, proc.id, 'AUTOMATION'),
293
- ],
294
- })),
295
- tables: [],
296
- actors: getActorsForSlice(model, slice),
297
- aggregates: getAggregatesForSlice(model, slice),
298
- specifications: scenarios.map(scenario => {
299
- const givenSteps = scenario.givenEvents.map(given => {
300
- const evt = model.events.get(given.eventStickyId);
301
- return {
302
- id: given.eventStickyId,
303
- title: evt?.name ?? 'Unknown',
304
- elementType: 'EVENT',
305
- fields: given.fieldValues,
306
- };
307
- });
308
- const whenSteps = [];
309
- if (scenario.whenCommand) {
310
- const cmd = model.commands.get(scenario.whenCommand.commandStickyId);
311
- whenSteps.push({
312
- id: scenario.whenCommand.commandStickyId,
313
- title: cmd?.name ?? 'Unknown',
314
- elementType: 'COMMAND',
315
- fields: scenario.whenCommand.fieldValues,
316
- });
317
- }
318
- const thenSteps = [];
319
- if (scenario.then.type === 'events' && scenario.then.expectedEvents) {
320
- for (const expected of scenario.then.expectedEvents) {
321
- const evt = model.events.get(expected.eventStickyId);
322
- thenSteps.push({
323
- id: expected.eventStickyId,
324
- title: evt?.name ?? 'Unknown',
325
- elementType: 'EVENT',
326
- fields: expected.fieldValues,
327
- });
328
- }
329
- }
330
- else if (scenario.then.type === 'readModelAssertion' && scenario.then.readModelAssertion) {
331
- const rm = model.readModels.get(scenario.then.readModelAssertion.readModelStickyId);
332
- thenSteps.push({
333
- id: scenario.then.readModelAssertion.readModelStickyId,
334
- title: rm?.name ?? 'Unknown',
335
- elementType: 'READMODEL',
336
- fields: scenario.then.readModelAssertion.expectedFieldValues,
337
- });
338
- }
339
- return {
340
- id: scenario.id,
341
- title: scenario.name,
342
- linkedId: slice.id,
343
- given: givenSteps,
344
- when: whenSteps,
345
- then: thenSteps,
346
- };
347
- }),
348
- };
349
- specSlices.push(specSlice);
350
- }
351
- const exportData = {
352
- slices: specSlices,
353
- };
354
- console.log(JSON.stringify(exportData, null, 2));
355
- }
@@ -1,2 +0,0 @@
1
- export declare function gitSetup(global: boolean): void;
2
- export declare function gitStatus(): void;