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,390 +0,0 @@
1
- import { diffModels } from './model-differ.js';
2
- import { resolvePropertyConflict, isLayoutOnlyChange, categorizeFieldChanges, } from './merge-rules.js';
3
- function groupChangesByEntity(diff) {
4
- const entityChanges = new Map();
5
- const flowChanges = new Map();
6
- for (const change of diff.entityChanges) {
7
- entityChanges.set(change.entityId, change);
8
- }
9
- for (const change of diff.flowChanges) {
10
- flowChanges.set(change.flowId, change);
11
- }
12
- return { entityChanges, flowChanges };
13
- }
14
- // Check if two entity changes are semantically identical
15
- function changesAreIdentical(a, b) {
16
- if (a.changeType !== b.changeType)
17
- return false;
18
- if (a.entityType !== b.entityType)
19
- return false;
20
- if (a.changeType === 'added' || a.changeType === 'removed') {
21
- return true;
22
- }
23
- const aProps = JSON.stringify(a.propertyChanges ?? []);
24
- const bProps = JSON.stringify(b.propertyChanges ?? []);
25
- const aFields = JSON.stringify(a.fieldChanges ?? []);
26
- const bFields = JSON.stringify(b.fieldChanges ?? []);
27
- return aProps === bProps && aFields === bFields;
28
- }
29
- /**
30
- * Analyze two modifications and determine conflicts.
31
- */
32
- function analyzeModificationConflicts(oursChange, theirsChange, strategy) {
33
- const conflicts = [];
34
- const autoResolved = [];
35
- let hasHardConflict = false;
36
- const entityType = oursChange.entityType;
37
- const entityId = oursChange.entityId;
38
- const entityName = oursChange.entityName;
39
- // Analyze property conflicts
40
- const oursProps = new Map((oursChange.propertyChanges ?? []).map(p => [p.property, p]));
41
- const theirsProps = new Map((theirsChange.propertyChanges ?? []).map(p => [p.property, p]));
42
- // Properties only in ours or theirs: auto-merge
43
- for (const [prop, change] of oursProps) {
44
- if (!theirsProps.has(prop)) {
45
- autoResolved.push({
46
- entityType,
47
- entityId,
48
- entityName,
49
- action: `property-${prop}-from-ours`,
50
- });
51
- }
52
- }
53
- for (const [prop, change] of theirsProps) {
54
- if (!oursProps.has(prop)) {
55
- autoResolved.push({
56
- entityType,
57
- entityId,
58
- entityName,
59
- action: `property-${prop}-from-theirs`,
60
- });
61
- }
62
- }
63
- // Properties in both: check for conflicts
64
- for (const [prop, oursProp] of oursProps) {
65
- const theirsProp = theirsProps.get(prop);
66
- if (!theirsProp)
67
- continue;
68
- const resolution = resolvePropertyConflict(prop, oursProp.newValue, theirsProp.newValue, entityType);
69
- if (resolution.type === 'auto') {
70
- autoResolved.push({
71
- entityType,
72
- entityId,
73
- entityName,
74
- action: resolution.action,
75
- });
76
- }
77
- else if (resolution.type === 'hard') {
78
- if (strategy) {
79
- autoResolved.push({
80
- entityType,
81
- entityId,
82
- entityName,
83
- action: `${prop}-resolved-${strategy}`,
84
- });
85
- }
86
- else {
87
- hasHardConflict = true;
88
- conflicts.push({
89
- entityType,
90
- entityId,
91
- entityName,
92
- reason: resolution.reason,
93
- property: prop,
94
- oursValue: oursProp.newValue,
95
- theirsValue: theirsProp.newValue,
96
- });
97
- }
98
- }
99
- }
100
- // Analyze field conflicts
101
- const oursFields = oursChange.fieldChanges ?? [];
102
- const theirsFields = theirsChange.fieldChanges ?? [];
103
- if (oursFields.length > 0 || theirsFields.length > 0) {
104
- const { oursOnly, theirsOnly, conflicts: fieldConflicts } = categorizeFieldChanges(oursFields, theirsFields);
105
- // Fields only in one branch: auto-merge
106
- for (const field of oursOnly) {
107
- autoResolved.push({
108
- entityType,
109
- entityId,
110
- entityName,
111
- action: `field-${field.fieldPath}-from-ours`,
112
- });
113
- }
114
- for (const field of theirsOnly) {
115
- autoResolved.push({
116
- entityType,
117
- entityId,
118
- entityName,
119
- action: `field-${field.fieldPath}-from-theirs`,
120
- });
121
- }
122
- // Field conflicts
123
- for (const { ours, theirs, resolution } of fieldConflicts) {
124
- if (resolution.type === 'auto') {
125
- autoResolved.push({
126
- entityType,
127
- entityId,
128
- entityName,
129
- action: `field-${ours.fieldPath}-${resolution.action}`,
130
- });
131
- }
132
- else if (resolution.type === 'hard') {
133
- if (strategy) {
134
- autoResolved.push({
135
- entityType,
136
- entityId,
137
- entityName,
138
- action: `field-${ours.fieldPath}-resolved-${strategy}`,
139
- });
140
- }
141
- else {
142
- hasHardConflict = true;
143
- conflicts.push({
144
- entityType,
145
- entityId,
146
- entityName,
147
- reason: resolution.reason,
148
- property: `field:${ours.fieldPath}`,
149
- oursValue: ours.newValue ?? ours.oldValue,
150
- theirsValue: theirs.newValue ?? theirs.oldValue,
151
- });
152
- }
153
- }
154
- }
155
- }
156
- return { conflicts, autoResolved, hasHardConflict };
157
- }
158
- /**
159
- * Perform a three-way merge of event models.
160
- */
161
- export function threeWayMerge(baseModel, oursModel, theirsModel, baseEvents, oursEvents, theirsEvents, strategy) {
162
- const conflicts = [];
163
- const autoResolved = [];
164
- // Compute diffs from base
165
- const oursDiff = diffModels(baseModel, oursModel);
166
- const theirsDiff = diffModels(baseModel, theirsModel);
167
- const oursChanges = groupChangesByEntity(oursDiff);
168
- const theirsChanges = groupChangesByEntity(theirsDiff);
169
- const baseTimestamp = baseEvents.length > 0
170
- ? Math.max(...baseEvents.map((e) => e.data.timestamp))
171
- : 0;
172
- const oursNewEvents = oursEvents.filter((e) => e.data.timestamp > baseTimestamp);
173
- const theirsNewEvents = theirsEvents.filter((e) => e.data.timestamp > baseTimestamp);
174
- const conflictingEntityIds = new Set();
175
- const conflictingFlowIds = new Set();
176
- // Analyze entity changes
177
- const allEntityIds = new Set([
178
- ...oursChanges.entityChanges.keys(),
179
- ...theirsChanges.entityChanges.keys(),
180
- ]);
181
- for (const entityId of allEntityIds) {
182
- const oursChange = oursChanges.entityChanges.get(entityId);
183
- const theirsChange = theirsChanges.entityChanges.get(entityId);
184
- // Only one side changed - no conflict
185
- if (!oursChange || !theirsChange) {
186
- continue;
187
- }
188
- // Both sides made the same change
189
- if (changesAreIdentical(oursChange, theirsChange)) {
190
- autoResolved.push({
191
- entityType: oursChange.entityType,
192
- entityId,
193
- entityName: oursChange.entityName,
194
- action: `both-${oursChange.changeType}-identically`,
195
- });
196
- continue;
197
- }
198
- // Layout-only changes: auto-resolve with theirs
199
- if (isLayoutOnlyChange(oursChange) && isLayoutOnlyChange(theirsChange)) {
200
- autoResolved.push({
201
- entityType: oursChange.entityType,
202
- entityId,
203
- entityName: oursChange.entityName,
204
- action: 'layout-only-use-theirs',
205
- });
206
- continue;
207
- }
208
- // One removed, other modified
209
- if ((oursChange.changeType === 'removed' && theirsChange.changeType === 'modified') ||
210
- (oursChange.changeType === 'modified' && theirsChange.changeType === 'removed')) {
211
- if (strategy) {
212
- autoResolved.push({
213
- entityType: oursChange.entityType,
214
- entityId,
215
- entityName: oursChange.entityName,
216
- action: `delete-vs-modify-resolved-${strategy}`,
217
- });
218
- }
219
- else {
220
- conflictingEntityIds.add(entityId);
221
- conflicts.push({
222
- entityType: oursChange.entityType,
223
- entityId,
224
- entityName: oursChange.entityName,
225
- reason: oursChange.changeType === 'removed'
226
- ? 'Ours deleted, theirs modified'
227
- : 'Ours modified, theirs deleted',
228
- oursValue: oursChange.changeType,
229
- theirsValue: theirsChange.changeType,
230
- });
231
- }
232
- continue;
233
- }
234
- // Both modified - detailed analysis
235
- if (oursChange.changeType === 'modified' && theirsChange.changeType === 'modified') {
236
- const analysis = analyzeModificationConflicts(oursChange, theirsChange, strategy);
237
- autoResolved.push(...analysis.autoResolved);
238
- conflicts.push(...analysis.conflicts);
239
- if (analysis.hasHardConflict) {
240
- conflictingEntityIds.add(entityId);
241
- }
242
- continue;
243
- }
244
- // Both added with same ID
245
- if (oursChange.changeType === 'added' && theirsChange.changeType === 'added') {
246
- if (strategy) {
247
- autoResolved.push({
248
- entityType: oursChange.entityType,
249
- entityId,
250
- entityName: oursChange.entityName,
251
- action: `both-added-resolved-${strategy}`,
252
- });
253
- }
254
- else {
255
- conflictingEntityIds.add(entityId);
256
- conflicts.push({
257
- entityType: oursChange.entityType,
258
- entityId,
259
- entityName: oursChange.entityName,
260
- reason: 'Both added entity with same ID',
261
- oursValue: oursChange.entityName,
262
- theirsValue: theirsChange.entityName,
263
- });
264
- }
265
- }
266
- }
267
- // Analyze flow changes
268
- const allFlowIds = new Set([
269
- ...oursChanges.flowChanges.keys(),
270
- ...theirsChanges.flowChanges.keys(),
271
- ]);
272
- for (const flowId of allFlowIds) {
273
- const oursChange = oursChanges.flowChanges.get(flowId);
274
- const theirsChange = theirsChanges.flowChanges.get(flowId);
275
- if (!oursChange || !theirsChange)
276
- continue;
277
- // Both added same flow
278
- if (oursChange.changeType === 'added' && theirsChange.changeType === 'added') {
279
- autoResolved.push({
280
- entityType: 'flow',
281
- entityId: flowId,
282
- entityName: `${oursChange.sourceName} → ${oursChange.targetName}`,
283
- action: 'both-added-flow-keep-one',
284
- });
285
- continue;
286
- }
287
- // Both removed
288
- if (oursChange.changeType === 'removed' && theirsChange.changeType === 'removed') {
289
- autoResolved.push({
290
- entityType: 'flow',
291
- entityId: flowId,
292
- entityName: `${oursChange.sourceName} → ${oursChange.targetName}`,
293
- action: 'both-removed-identically',
294
- });
295
- continue;
296
- }
297
- // One removed, other modified
298
- if ((oursChange.changeType === 'removed' && theirsChange.changeType === 'modified') ||
299
- (oursChange.changeType === 'modified' && theirsChange.changeType === 'removed')) {
300
- if (strategy) {
301
- autoResolved.push({
302
- entityType: 'flow',
303
- entityId: flowId,
304
- entityName: `${oursChange.sourceName} → ${oursChange.targetName}`,
305
- action: `flow-delete-vs-modify-resolved-${strategy}`,
306
- });
307
- }
308
- else {
309
- conflictingFlowIds.add(flowId);
310
- conflicts.push({
311
- entityType: 'flow',
312
- entityId: flowId,
313
- entityName: `${oursChange.sourceName} → ${oursChange.targetName}`,
314
- reason: oursChange.changeType === 'removed'
315
- ? 'Ours removed flow, theirs modified mappings'
316
- : 'Ours modified mappings, theirs removed flow',
317
- oursValue: oursChange.changeType,
318
- theirsValue: theirsChange.changeType,
319
- });
320
- }
321
- continue;
322
- }
323
- // Both modified mappings
324
- if (oursChange.changeType === 'modified' && theirsChange.changeType === 'modified') {
325
- if (strategy) {
326
- autoResolved.push({
327
- entityType: 'flow',
328
- entityId: flowId,
329
- entityName: `${oursChange.sourceName} → ${oursChange.targetName}`,
330
- action: `flow-mappings-resolved-${strategy}`,
331
- });
332
- }
333
- else {
334
- conflictingFlowIds.add(flowId);
335
- conflicts.push({
336
- entityType: 'flow',
337
- entityId: flowId,
338
- entityName: `${oursChange.sourceName} → ${oursChange.targetName}`,
339
- reason: 'Both modified flow field mappings',
340
- oursValue: oursChange.mappingChanges,
341
- theirsValue: theirsChange.mappingChanges,
342
- });
343
- }
344
- }
345
- }
346
- // Build merged events
347
- const mergedEvents = [...baseEvents];
348
- const affectsConflictingEntity = (event) => {
349
- const idFields = [
350
- 'commandStickyId', 'eventStickyId', 'readModelStickyId',
351
- 'screenId', 'processorId', 'sliceId', 'chapterId',
352
- 'aggregateId', 'actorId', 'scenarioId', 'flowId',
353
- ];
354
- for (const field of idFields) {
355
- const id = event.data[field];
356
- if (id && (conflictingEntityIds.has(id) || conflictingFlowIds.has(id))) {
357
- return true;
358
- }
359
- }
360
- return false;
361
- };
362
- // Add non-conflicting events from ours
363
- for (const event of oursNewEvents) {
364
- if (!affectsConflictingEntity(event)) {
365
- mergedEvents.push(event);
366
- }
367
- else if (strategy === 'ours') {
368
- mergedEvents.push(event);
369
- }
370
- }
371
- // Add non-conflicting events from theirs
372
- const oursEventKeys = new Set(oursNewEvents.map(e => `${e.type}:${JSON.stringify(e)}`));
373
- for (const event of theirsNewEvents) {
374
- const eventKey = `${event.type}:${JSON.stringify(event)}`;
375
- if (oursEventKeys.has(eventKey))
376
- continue;
377
- if (!affectsConflictingEntity(event)) {
378
- mergedEvents.push(event);
379
- }
380
- else if (strategy === 'theirs') {
381
- mergedEvents.push(event);
382
- }
383
- }
384
- return {
385
- success: conflicts.length === 0,
386
- conflicts,
387
- autoResolved,
388
- mergedEvents,
389
- };
390
- }
@@ -1,75 +0,0 @@
1
- import type { RawEvent, Field } from '../../types.js';
2
- export type EntityType = 'command' | 'event' | 'readModel' | 'screen' | 'processor' | 'slice' | 'chapter' | 'aggregate' | 'actor' | 'scenario' | 'flow';
3
- export type ChangeType = 'added' | 'removed' | 'modified';
4
- export interface FieldChange {
5
- fieldPath: string;
6
- changeType: ChangeType;
7
- oldValue?: Field;
8
- newValue?: Field;
9
- }
10
- export interface EntityChange {
11
- entityType: EntityType;
12
- entityId: string;
13
- entityName: string;
14
- canonicalId?: string;
15
- changeType: ChangeType;
16
- propertyChanges?: PropertyChange[];
17
- fieldChanges?: FieldChange[];
18
- }
19
- export interface PropertyChange {
20
- property: string;
21
- oldValue?: unknown;
22
- newValue?: unknown;
23
- }
24
- export interface FlowChange {
25
- flowId: string;
26
- flowType: string;
27
- changeType: ChangeType;
28
- sourceName?: string;
29
- targetName?: string;
30
- mappingChanges?: FieldMappingChange[];
31
- }
32
- export interface FieldMappingChange {
33
- changeType: ChangeType;
34
- sourceFieldName?: string;
35
- targetFieldName?: string;
36
- }
37
- export interface DiffResult {
38
- summary: {
39
- added: number;
40
- removed: number;
41
- modified: number;
42
- };
43
- entityChanges: EntityChange[];
44
- flowChanges: FlowChange[];
45
- }
46
- export interface MergeConflict {
47
- entityType: EntityType;
48
- entityId: string;
49
- entityName: string;
50
- reason: string;
51
- property?: string;
52
- baseValue?: unknown;
53
- oursValue?: unknown;
54
- theirsValue?: unknown;
55
- }
56
- export interface MergeResult {
57
- success: boolean;
58
- conflicts: MergeConflict[];
59
- autoResolved: AutoResolution[];
60
- mergedEvents: RawEvent[];
61
- }
62
- export interface AutoResolution {
63
- entityType: EntityType;
64
- entityId: string;
65
- entityName: string;
66
- action: string;
67
- }
68
- export interface MergeOptions {
69
- basePath: string;
70
- oursPath: string;
71
- theirsPath: string;
72
- outputPath: string;
73
- strategy?: 'ours' | 'theirs';
74
- dryRun?: boolean;
75
- }
@@ -1 +0,0 @@
1
- export {};
@@ -1,58 +0,0 @@
1
- /**
2
- * Element lookup utilities for CLI commands.
3
- * Provides fuzzy lookup with UUID disambiguation for ambiguous matches.
4
- */
5
- export type LookupResult<T> = {
6
- success: true;
7
- element: T;
8
- } | {
9
- success: false;
10
- error: 'not_found' | 'ambiguous';
11
- matches: T[];
12
- };
13
- /**
14
- * Filter out linked copies from a collection of elements.
15
- * Linked copies have `originalNodeId` set and should not be considered
16
- * as separate elements for lookup - they're UI conveniences only.
17
- */
18
- export declare function excludeLinkedCopies<T extends {
19
- id: string;
20
- originalNodeId?: string;
21
- }>(elements: Map<string, T> | T[]): T[];
22
- /**
23
- * Find an element by name (fuzzy) or UUID.
24
- * - If search starts with "id:", treats rest as UUID/UUID prefix
25
- * - Otherwise, performs fuzzy name matching:
26
- * 1. Exact match (case-insensitive, normalized spaces)
27
- * 2. Partial match (search is contained in name)
28
- * - Returns error if multiple elements match
29
- */
30
- export declare function findElement<T extends {
31
- id: string;
32
- name: string;
33
- }>(elements: Map<string, T> | T[], search: string): LookupResult<T>;
34
- /**
35
- * Format an element name with its ID for display
36
- */
37
- export declare function formatElementWithId<T extends {
38
- id: string;
39
- name: string;
40
- }>(element: T, truncateId?: boolean): string;
41
- /**
42
- * Print error message for lookup failures and exit
43
- */
44
- export declare function handleLookupError<T extends {
45
- id: string;
46
- name: string;
47
- }>(search: string, elementType: string, result: {
48
- success: false;
49
- error: 'not_found' | 'ambiguous';
50
- matches: T[];
51
- }, allElements: Map<string, T> | T[]): never;
52
- /**
53
- * Convenience function: find element or exit with error
54
- */
55
- export declare function findElementOrExit<T extends {
56
- id: string;
57
- name: string;
58
- }>(elements: Map<string, T> | T[], search: string, elementType: string): T;
@@ -1,126 +0,0 @@
1
- /**
2
- * Element lookup utilities for CLI commands.
3
- * Provides fuzzy lookup with UUID disambiguation for ambiguous matches.
4
- */
5
- /**
6
- * Filter out linked copies from a collection of elements.
7
- * Linked copies have `originalNodeId` set and should not be considered
8
- * as separate elements for lookup - they're UI conveniences only.
9
- */
10
- export function excludeLinkedCopies(elements) {
11
- const elementArray = Array.isArray(elements) ? elements : [...elements.values()];
12
- return elementArray.filter(e => !e.originalNodeId);
13
- }
14
- /**
15
- * Normalize a string for fuzzy matching:
16
- * - lowercase
17
- * - collapse multiple spaces to single space
18
- * - trim whitespace
19
- */
20
- function normalize(str) {
21
- return str.toLowerCase().replace(/\s+/g, ' ').trim();
22
- }
23
- /**
24
- * Find an element by name (fuzzy) or UUID.
25
- * - If search starts with "id:", treats rest as UUID/UUID prefix
26
- * - Otherwise, performs fuzzy name matching:
27
- * 1. Exact match (case-insensitive, normalized spaces)
28
- * 2. Partial match (search is contained in name)
29
- * - Returns error if multiple elements match
30
- */
31
- export function findElement(elements, search) {
32
- const elementArray = Array.isArray(elements) ? elements : [...elements.values()];
33
- // Check for UUID lookup (id:prefix or full UUID format)
34
- if (search.startsWith('id:')) {
35
- const idSearch = search.slice(3).toLowerCase();
36
- const match = elementArray.find(e => e.id.toLowerCase().startsWith(idSearch));
37
- if (match) {
38
- return { success: true, element: match };
39
- }
40
- return { success: false, error: 'not_found', matches: [] };
41
- }
42
- // Check if the search looks like a UUID (contains dashes in UUID pattern)
43
- const uuidPattern = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
44
- if (uuidPattern.test(search)) {
45
- const match = elementArray.find(e => e.id.toLowerCase() === search.toLowerCase());
46
- if (match) {
47
- return { success: true, element: match };
48
- }
49
- return { success: false, error: 'not_found', matches: [] };
50
- }
51
- const searchNorm = normalize(search);
52
- // 1. Try exact match first (case-insensitive, normalized)
53
- const exactMatches = elementArray.filter(e => normalize(e.name) === searchNorm);
54
- if (exactMatches.length === 1) {
55
- return { success: true, element: exactMatches[0] };
56
- }
57
- if (exactMatches.length > 1) {
58
- return { success: false, error: 'ambiguous', matches: exactMatches };
59
- }
60
- // 2. Try partial match (search contained in name)
61
- const partialMatches = elementArray.filter(e => normalize(e.name).includes(searchNorm));
62
- if (partialMatches.length === 1) {
63
- return { success: true, element: partialMatches[0] };
64
- }
65
- if (partialMatches.length > 1) {
66
- return { success: false, error: 'ambiguous', matches: partialMatches };
67
- }
68
- // 3. Try word-based match (all search words appear in name)
69
- const searchWords = searchNorm.split(' ').filter(w => w.length > 0);
70
- const wordMatches = elementArray.filter(e => {
71
- const nameNorm = normalize(e.name);
72
- return searchWords.every(word => nameNorm.includes(word));
73
- });
74
- if (wordMatches.length === 1) {
75
- return { success: true, element: wordMatches[0] };
76
- }
77
- if (wordMatches.length > 1) {
78
- return { success: false, error: 'ambiguous', matches: wordMatches };
79
- }
80
- return { success: false, error: 'not_found', matches: [] };
81
- }
82
- /**
83
- * Format an element name with its ID for display
84
- */
85
- export function formatElementWithId(element, truncateId = true) {
86
- const id = truncateId ? element.id.slice(0, 8) : element.id;
87
- return `"${element.name}" (id: ${id})`;
88
- }
89
- /**
90
- * Print error message for lookup failures and exit
91
- */
92
- export function handleLookupError(search, elementType, result, allElements) {
93
- const elementArray = Array.isArray(allElements) ? allElements : [...allElements.values()];
94
- if (result.error === 'ambiguous') {
95
- console.error(`Error: Multiple ${elementType}s found with name "${search}"`);
96
- console.error('Please specify using the element ID:');
97
- for (const el of result.matches) {
98
- console.error(` - ${formatElementWithId(el, false)}`);
99
- }
100
- console.error('');
101
- console.error(`Usage: eventmodeler <command> "id:${result.matches[0].id.slice(0, 8)}"`);
102
- }
103
- else {
104
- console.error(`Error: ${elementType.charAt(0).toUpperCase() + elementType.slice(1)} not found: "${search}"`);
105
- if (elementArray.length > 0) {
106
- console.error(`Available ${elementType}s:`);
107
- for (const el of elementArray) {
108
- console.error(` - ${formatElementWithId(el)}`);
109
- }
110
- }
111
- else {
112
- console.error(`No ${elementType}s exist in the model.`);
113
- }
114
- }
115
- process.exit(1);
116
- }
117
- /**
118
- * Convenience function: find element or exit with error
119
- */
120
- export function findElementOrExit(elements, search, elementType) {
121
- const result = findElement(elements, search);
122
- if (!result.success) {
123
- handleLookupError(search, elementType, result, elements);
124
- }
125
- return result.element;
126
- }
@@ -1,8 +0,0 @@
1
- import type { EventModel, RawEvent } from '../types.js';
2
- export declare function promptForFile(files: string[]): Promise<string>;
3
- export declare function findEventModelFile(): Promise<string | null>;
4
- export declare function loadModel(filePath: string): EventModel;
5
- export declare function appendEvent(filePath: string, event: RawEvent): void;
6
- export declare function loadRawEvents(filePath: string): RawEvent[];
7
- export declare function writeEvents(filePath: string, events: RawEvent[]): void;
8
- export declare function loadModelFromContent(content: string): EventModel;