eventmodeler 0.5.0 → 0.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (204) hide show
  1. package/dist/api/client-config.js +10 -0
  2. package/dist/api/generated/client/client.gen.js +235 -0
  3. package/dist/api/generated/client/index.js +6 -0
  4. package/dist/api/generated/client/types.gen.js +2 -0
  5. package/dist/api/generated/client/utils.gen.js +228 -0
  6. package/dist/api/generated/client.gen.js +4 -0
  7. package/dist/api/generated/core/auth.gen.js +14 -0
  8. package/dist/api/generated/core/bodySerializer.gen.js +57 -0
  9. package/dist/api/generated/core/params.gen.js +100 -0
  10. package/dist/api/generated/core/pathSerializer.gen.js +106 -0
  11. package/dist/api/generated/core/queryKeySerializer.gen.js +92 -0
  12. package/dist/api/generated/core/serverSentEvents.gen.js +133 -0
  13. package/dist/api/generated/core/types.gen.js +2 -0
  14. package/dist/api/generated/core/utils.gen.js +87 -0
  15. package/dist/api/generated/index.js +2 -0
  16. package/dist/api/generated/sdk.gen.js +4222 -0
  17. package/dist/api/generated/types.gen.js +2 -0
  18. package/dist/api/generated/zod.gen.js +7217 -0
  19. package/dist/commands/add.js +315 -0
  20. package/dist/commands/auth.js +14 -0
  21. package/dist/commands/create.js +192 -0
  22. package/dist/commands/design.js +108 -0
  23. package/dist/commands/guide.js +15 -0
  24. package/dist/commands/init.js +21 -0
  25. package/dist/commands/list-schemas.js +177 -0
  26. package/dist/commands/list.js +39 -0
  27. package/dist/commands/loop.js +101 -0
  28. package/dist/commands/map.js +40 -0
  29. package/dist/commands/mark.js +27 -0
  30. package/dist/commands/move.js +35 -0
  31. package/dist/commands/remove.js +170 -0
  32. package/dist/commands/rename.js +53 -0
  33. package/dist/commands/resize.js +30 -0
  34. package/dist/commands/search.js +14 -0
  35. package/dist/commands/set.js +199 -0
  36. package/dist/commands/show-schemas.js +259 -0
  37. package/dist/commands/show.js +56 -0
  38. package/dist/commands/summary.js +13 -0
  39. package/dist/commands/update.js +240 -0
  40. package/dist/index.js +46 -2379
  41. package/dist/lib/auth.js +1 -1
  42. package/dist/lib/config.js +0 -15
  43. package/dist/lib/excalidraw-schema.js +66 -0
  44. package/dist/lib/globals.js +8 -0
  45. package/dist/lib/model.js +11 -0
  46. package/dist/lib/project-config.js +20 -0
  47. package/dist/lib/resolve.js +59 -0
  48. package/dist/lib/scenario.js +15 -0
  49. package/dist/slices/add-scenario/index.js +2 -206
  50. package/dist/slices/guide/guides/codegen.js +1 -1
  51. package/dist/slices/guide/guides/connect-slices.js +38 -38
  52. package/dist/slices/guide/guides/create-slices.js +110 -140
  53. package/dist/slices/guide/guides/explore.js +37 -50
  54. package/dist/slices/guide/guides/information-flow.js +70 -84
  55. package/dist/slices/guide/guides/scenarios.js +82 -137
  56. package/dist/slices/guide/index.js +6 -6
  57. package/dist/slices/help/index.js +96 -0
  58. package/dist/slices/help/topics/build-codegen.js +109 -0
  59. package/dist/slices/help/topics/build-slice.js +147 -0
  60. package/dist/slices/help/topics/check-completeness.js +57 -0
  61. package/dist/slices/help/topics/connect-slices.js +99 -0
  62. package/dist/slices/help/topics/explore-model.js +112 -0
  63. package/dist/slices/help/topics/json-reference.js +188 -0
  64. package/dist/slices/help/topics/linked-copies.js +89 -0
  65. package/dist/slices/help/topics/manipulate-canvas.js +150 -0
  66. package/dist/slices/help/topics/write-scenarios.js +162 -0
  67. package/dist/slices/init/index.js +10 -4
  68. package/dist/slices/init/loop.js +60 -0
  69. package/dist/slices/login/index.js +2 -2
  70. package/dist/slices/logout/index.js +2 -2
  71. package/dist/slices/whoami/index.js +11 -36
  72. package/package.json +8 -3
  73. package/dist/api/index.d.ts +0 -285
  74. package/dist/api/index.js +0 -323
  75. package/dist/cloud/slices/index.d.ts +0 -276
  76. package/dist/cloud/slices/index.js +0 -406
  77. package/dist/eventmodeler.js +0 -5646
  78. package/dist/formatters.d.ts +0 -17
  79. package/dist/formatters.js +0 -482
  80. package/dist/index.d.ts +0 -2
  81. package/dist/lib/auth.d.ts +0 -24
  82. package/dist/lib/backend.d.ts +0 -43
  83. package/dist/lib/backend.js +0 -73
  84. package/dist/lib/chapter-utils.d.ts +0 -13
  85. package/dist/lib/chapter-utils.js +0 -71
  86. package/dist/lib/cloud-client.d.ts +0 -69
  87. package/dist/lib/cloud-client.js +0 -364
  88. package/dist/lib/config.d.ts +0 -30
  89. package/dist/lib/diff/merge-rules.d.ts +0 -45
  90. package/dist/lib/diff/merge-rules.js +0 -210
  91. package/dist/lib/diff/model-differ.d.ts +0 -8
  92. package/dist/lib/diff/model-differ.js +0 -568
  93. package/dist/lib/diff/three-way-merge.d.ts +0 -7
  94. package/dist/lib/diff/three-way-merge.js +0 -390
  95. package/dist/lib/diff/types.d.ts +0 -75
  96. package/dist/lib/diff/types.js +0 -1
  97. package/dist/lib/element-lookup.d.ts +0 -58
  98. package/dist/lib/element-lookup.js +0 -126
  99. package/dist/lib/file-loader.d.ts +0 -8
  100. package/dist/lib/file-loader.js +0 -108
  101. package/dist/lib/flow-utils.d.ts +0 -53
  102. package/dist/lib/flow-utils.js +0 -348
  103. package/dist/lib/format.d.ts +0 -10
  104. package/dist/lib/format.js +0 -23
  105. package/dist/lib/project-config.d.ts +0 -27
  106. package/dist/lib/slice-utils.d.ts +0 -59
  107. package/dist/lib/slice-utils.js +0 -140
  108. package/dist/local/slices/index.d.ts +0 -11
  109. package/dist/local/slices/index.js +0 -13
  110. package/dist/projection.d.ts +0 -3
  111. package/dist/projection.js +0 -828
  112. package/dist/slices/add-field/index.d.ts +0 -8
  113. package/dist/slices/add-field/index.js +0 -211
  114. package/dist/slices/add-scenario/index.d.ts +0 -27
  115. package/dist/slices/codegen-chapter-events/index.d.ts +0 -2
  116. package/dist/slices/codegen-chapter-events/index.js +0 -145
  117. package/dist/slices/codegen-slice/index.d.ts +0 -2
  118. package/dist/slices/codegen-slice/index.js +0 -448
  119. package/dist/slices/create-automation-slice/index.d.ts +0 -2
  120. package/dist/slices/create-automation-slice/index.js +0 -304
  121. package/dist/slices/create-flow/index.d.ts +0 -2
  122. package/dist/slices/create-flow/index.js +0 -183
  123. package/dist/slices/create-state-change-slice/index.d.ts +0 -2
  124. package/dist/slices/create-state-change-slice/index.js +0 -263
  125. package/dist/slices/create-state-view-slice/index.d.ts +0 -2
  126. package/dist/slices/create-state-view-slice/index.js +0 -128
  127. package/dist/slices/diff/index.d.ts +0 -11
  128. package/dist/slices/diff/index.js +0 -293
  129. package/dist/slices/export-eventmodel-to-json/index.d.ts +0 -2
  130. package/dist/slices/export-eventmodel-to-json/index.js +0 -355
  131. package/dist/slices/git/index.d.ts +0 -2
  132. package/dist/slices/git/index.js +0 -125
  133. package/dist/slices/guide/guides/codegen.d.ts +0 -5
  134. package/dist/slices/guide/guides/connect-slices.d.ts +0 -5
  135. package/dist/slices/guide/guides/create-slices.d.ts +0 -5
  136. package/dist/slices/guide/guides/explore.d.ts +0 -5
  137. package/dist/slices/guide/guides/information-flow.d.ts +0 -5
  138. package/dist/slices/guide/guides/scenarios.d.ts +0 -5
  139. package/dist/slices/guide/index.d.ts +0 -1
  140. package/dist/slices/import/index.d.ts +0 -8
  141. package/dist/slices/import/index.js +0 -63
  142. package/dist/slices/init/index.d.ts +0 -5
  143. package/dist/slices/list-chapters/index.d.ts +0 -3
  144. package/dist/slices/list-chapters/index.js +0 -21
  145. package/dist/slices/list-commands/index.d.ts +0 -3
  146. package/dist/slices/list-commands/index.js +0 -20
  147. package/dist/slices/list-events/index.d.ts +0 -3
  148. package/dist/slices/list-events/index.js +0 -98
  149. package/dist/slices/list-processors/index.d.ts +0 -3
  150. package/dist/slices/list-processors/index.js +0 -20
  151. package/dist/slices/list-readmodels/index.d.ts +0 -3
  152. package/dist/slices/list-readmodels/index.js +0 -21
  153. package/dist/slices/list-scenarios/index.d.ts +0 -3
  154. package/dist/slices/list-scenarios/index.js +0 -35
  155. package/dist/slices/list-screens/index.d.ts +0 -3
  156. package/dist/slices/list-screens/index.js +0 -47
  157. package/dist/slices/list-slices/index.d.ts +0 -3
  158. package/dist/slices/list-slices/index.js +0 -35
  159. package/dist/slices/login/index.d.ts +0 -1
  160. package/dist/slices/logout/index.d.ts +0 -1
  161. package/dist/slices/map-fields/index.d.ts +0 -2
  162. package/dist/slices/map-fields/index.js +0 -269
  163. package/dist/slices/mark-slice-status/index.d.ts +0 -2
  164. package/dist/slices/mark-slice-status/index.js +0 -31
  165. package/dist/slices/merge/index.d.ts +0 -19
  166. package/dist/slices/merge/index.js +0 -147
  167. package/dist/slices/open-app/index.d.ts +0 -1
  168. package/dist/slices/remove-field/index.d.ts +0 -8
  169. package/dist/slices/remove-field/index.js +0 -167
  170. package/dist/slices/remove-scenario/index.d.ts +0 -2
  171. package/dist/slices/remove-scenario/index.js +0 -77
  172. package/dist/slices/search/index.d.ts +0 -3
  173. package/dist/slices/search/index.js +0 -302
  174. package/dist/slices/show-actor/index.d.ts +0 -4
  175. package/dist/slices/show-actor/index.js +0 -115
  176. package/dist/slices/show-aggregate/index.d.ts +0 -3
  177. package/dist/slices/show-aggregate/index.js +0 -108
  178. package/dist/slices/show-aggregate-completeness/index.d.ts +0 -4
  179. package/dist/slices/show-aggregate-completeness/index.js +0 -181
  180. package/dist/slices/show-chapter/index.d.ts +0 -3
  181. package/dist/slices/show-chapter/index.js +0 -195
  182. package/dist/slices/show-command/index.d.ts +0 -3
  183. package/dist/slices/show-command/index.js +0 -133
  184. package/dist/slices/show-completeness/index.d.ts +0 -4
  185. package/dist/slices/show-completeness/index.js +0 -731
  186. package/dist/slices/show-event/index.d.ts +0 -3
  187. package/dist/slices/show-event/index.js +0 -118
  188. package/dist/slices/show-model-summary/index.d.ts +0 -3
  189. package/dist/slices/show-model-summary/index.js +0 -31
  190. package/dist/slices/show-processor/index.d.ts +0 -3
  191. package/dist/slices/show-processor/index.js +0 -111
  192. package/dist/slices/show-readmodel/index.d.ts +0 -3
  193. package/dist/slices/show-readmodel/index.js +0 -158
  194. package/dist/slices/show-scenario/index.d.ts +0 -3
  195. package/dist/slices/show-scenario/index.js +0 -196
  196. package/dist/slices/show-screen/index.d.ts +0 -3
  197. package/dist/slices/show-screen/index.js +0 -139
  198. package/dist/slices/show-slice/index.d.ts +0 -3
  199. package/dist/slices/show-slice/index.js +0 -696
  200. package/dist/slices/update-field/index.d.ts +0 -15
  201. package/dist/slices/update-field/index.js +0 -208
  202. package/dist/slices/whoami/index.d.ts +0 -2
  203. package/dist/types.d.ts +0 -195
  204. package/dist/types.js +0 -1
@@ -1,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;