eventmodeler 0.4.7 → 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.
- package/dist/api/client-config.js +10 -0
- package/dist/api/generated/client/client.gen.js +235 -0
- package/dist/api/generated/client/index.js +6 -0
- package/dist/api/generated/client/types.gen.js +2 -0
- package/dist/api/generated/client/utils.gen.js +228 -0
- package/dist/api/generated/client.gen.js +4 -0
- package/dist/api/generated/core/auth.gen.js +14 -0
- package/dist/api/generated/core/bodySerializer.gen.js +57 -0
- package/dist/api/generated/core/params.gen.js +100 -0
- package/dist/api/generated/core/pathSerializer.gen.js +106 -0
- package/dist/api/generated/core/queryKeySerializer.gen.js +92 -0
- package/dist/api/generated/core/serverSentEvents.gen.js +133 -0
- package/dist/api/generated/core/types.gen.js +2 -0
- package/dist/api/generated/core/utils.gen.js +87 -0
- package/dist/api/generated/index.js +2 -0
- package/dist/api/generated/sdk.gen.js +4222 -0
- package/dist/api/generated/types.gen.js +2 -0
- package/dist/api/generated/zod.gen.js +7217 -0
- package/dist/commands/add.js +315 -0
- package/dist/commands/auth.js +14 -0
- package/dist/commands/create.js +192 -0
- package/dist/commands/design.js +108 -0
- package/dist/commands/guide.js +15 -0
- package/dist/commands/init.js +21 -0
- package/dist/commands/list-schemas.js +177 -0
- package/dist/commands/list.js +39 -0
- package/dist/commands/loop.js +101 -0
- package/dist/commands/map.js +40 -0
- package/dist/commands/mark.js +27 -0
- package/dist/commands/move.js +35 -0
- package/dist/commands/remove.js +170 -0
- package/dist/commands/rename.js +53 -0
- package/dist/commands/resize.js +30 -0
- package/dist/commands/search.js +14 -0
- package/dist/commands/set.js +199 -0
- package/dist/commands/show-schemas.js +259 -0
- package/dist/commands/show.js +56 -0
- package/dist/commands/summary.js +13 -0
- package/dist/commands/update.js +240 -0
- package/dist/index.js +46 -2379
- package/dist/lib/auth.js +1 -1
- package/dist/lib/config.js +0 -15
- package/dist/lib/excalidraw-schema.js +66 -0
- package/dist/lib/globals.js +8 -0
- package/dist/lib/model.js +11 -0
- package/dist/lib/project-config.js +20 -0
- package/dist/lib/resolve.js +59 -0
- package/dist/lib/scenario.js +15 -0
- package/dist/slices/add-scenario/index.js +2 -206
- package/dist/slices/guide/guides/codegen.js +1 -1
- package/dist/slices/guide/guides/connect-slices.js +12 -37
- package/dist/slices/guide/guides/create-slices.js +110 -140
- package/dist/slices/guide/guides/explore.js +37 -26
- package/dist/slices/guide/guides/information-flow.js +70 -82
- package/dist/slices/guide/guides/scenarios.js +82 -137
- package/dist/slices/guide/index.js +6 -6
- package/dist/slices/help/index.js +96 -0
- package/dist/slices/help/topics/build-codegen.js +109 -0
- package/dist/slices/help/topics/build-slice.js +147 -0
- package/dist/slices/help/topics/check-completeness.js +57 -0
- package/dist/slices/help/topics/connect-slices.js +99 -0
- package/dist/slices/help/topics/explore-model.js +112 -0
- package/dist/slices/help/topics/json-reference.js +188 -0
- package/dist/slices/help/topics/linked-copies.js +89 -0
- package/dist/slices/help/topics/manipulate-canvas.js +150 -0
- package/dist/slices/help/topics/write-scenarios.js +162 -0
- package/dist/slices/init/index.js +10 -4
- package/dist/slices/init/loop.js +60 -0
- package/dist/slices/login/index.js +2 -2
- package/dist/slices/logout/index.js +2 -2
- package/dist/slices/whoami/index.js +11 -36
- package/package.json +8 -3
- package/dist/api/index.d.ts +0 -285
- package/dist/api/index.js +0 -323
- package/dist/cloud/slices/index.d.ts +0 -276
- package/dist/cloud/slices/index.js +0 -406
- package/dist/eventmodeler.js +0 -5646
- package/dist/formatters.d.ts +0 -17
- package/dist/formatters.js +0 -482
- package/dist/index.d.ts +0 -2
- package/dist/lib/auth.d.ts +0 -24
- package/dist/lib/backend.d.ts +0 -43
- package/dist/lib/backend.js +0 -73
- package/dist/lib/chapter-utils.d.ts +0 -13
- package/dist/lib/chapter-utils.js +0 -71
- package/dist/lib/cloud-client.d.ts +0 -69
- package/dist/lib/cloud-client.js +0 -364
- package/dist/lib/config.d.ts +0 -30
- package/dist/lib/diff/merge-rules.d.ts +0 -45
- package/dist/lib/diff/merge-rules.js +0 -210
- package/dist/lib/diff/model-differ.d.ts +0 -8
- package/dist/lib/diff/model-differ.js +0 -568
- package/dist/lib/diff/three-way-merge.d.ts +0 -7
- package/dist/lib/diff/three-way-merge.js +0 -390
- package/dist/lib/diff/types.d.ts +0 -75
- package/dist/lib/diff/types.js +0 -1
- package/dist/lib/element-lookup.d.ts +0 -58
- package/dist/lib/element-lookup.js +0 -126
- package/dist/lib/file-loader.d.ts +0 -8
- package/dist/lib/file-loader.js +0 -108
- package/dist/lib/flow-utils.d.ts +0 -53
- package/dist/lib/flow-utils.js +0 -348
- package/dist/lib/format.d.ts +0 -10
- package/dist/lib/format.js +0 -23
- package/dist/lib/project-config.d.ts +0 -27
- package/dist/lib/slice-utils.d.ts +0 -59
- package/dist/lib/slice-utils.js +0 -140
- package/dist/local/slices/index.d.ts +0 -11
- package/dist/local/slices/index.js +0 -13
- package/dist/projection.d.ts +0 -3
- package/dist/projection.js +0 -828
- package/dist/slices/add-field/index.d.ts +0 -8
- package/dist/slices/add-field/index.js +0 -211
- package/dist/slices/add-scenario/index.d.ts +0 -27
- package/dist/slices/codegen-chapter-events/index.d.ts +0 -2
- package/dist/slices/codegen-chapter-events/index.js +0 -145
- package/dist/slices/codegen-slice/index.d.ts +0 -2
- package/dist/slices/codegen-slice/index.js +0 -448
- package/dist/slices/create-automation-slice/index.d.ts +0 -2
- package/dist/slices/create-automation-slice/index.js +0 -304
- package/dist/slices/create-flow/index.d.ts +0 -2
- package/dist/slices/create-flow/index.js +0 -183
- package/dist/slices/create-state-change-slice/index.d.ts +0 -2
- package/dist/slices/create-state-change-slice/index.js +0 -263
- package/dist/slices/create-state-view-slice/index.d.ts +0 -2
- package/dist/slices/create-state-view-slice/index.js +0 -128
- package/dist/slices/diff/index.d.ts +0 -11
- package/dist/slices/diff/index.js +0 -293
- package/dist/slices/export-eventmodel-to-json/index.d.ts +0 -2
- package/dist/slices/export-eventmodel-to-json/index.js +0 -355
- package/dist/slices/git/index.d.ts +0 -2
- package/dist/slices/git/index.js +0 -125
- package/dist/slices/guide/guides/codegen.d.ts +0 -5
- package/dist/slices/guide/guides/connect-slices.d.ts +0 -5
- package/dist/slices/guide/guides/create-slices.d.ts +0 -5
- package/dist/slices/guide/guides/explore.d.ts +0 -5
- package/dist/slices/guide/guides/information-flow.d.ts +0 -5
- package/dist/slices/guide/guides/scenarios.d.ts +0 -5
- package/dist/slices/guide/index.d.ts +0 -1
- package/dist/slices/import/index.d.ts +0 -8
- package/dist/slices/import/index.js +0 -63
- package/dist/slices/init/index.d.ts +0 -5
- package/dist/slices/list-chapters/index.d.ts +0 -3
- package/dist/slices/list-chapters/index.js +0 -21
- package/dist/slices/list-commands/index.d.ts +0 -3
- package/dist/slices/list-commands/index.js +0 -20
- package/dist/slices/list-events/index.d.ts +0 -3
- package/dist/slices/list-events/index.js +0 -98
- package/dist/slices/list-processors/index.d.ts +0 -3
- package/dist/slices/list-processors/index.js +0 -20
- package/dist/slices/list-readmodels/index.d.ts +0 -3
- package/dist/slices/list-readmodels/index.js +0 -21
- package/dist/slices/list-scenarios/index.d.ts +0 -3
- package/dist/slices/list-scenarios/index.js +0 -35
- package/dist/slices/list-screens/index.d.ts +0 -3
- package/dist/slices/list-screens/index.js +0 -47
- package/dist/slices/list-slices/index.d.ts +0 -3
- package/dist/slices/list-slices/index.js +0 -35
- package/dist/slices/login/index.d.ts +0 -1
- package/dist/slices/logout/index.d.ts +0 -1
- package/dist/slices/map-fields/index.d.ts +0 -2
- package/dist/slices/map-fields/index.js +0 -269
- package/dist/slices/mark-slice-status/index.d.ts +0 -2
- package/dist/slices/mark-slice-status/index.js +0 -31
- package/dist/slices/merge/index.d.ts +0 -19
- package/dist/slices/merge/index.js +0 -147
- package/dist/slices/open-app/index.d.ts +0 -1
- package/dist/slices/remove-field/index.d.ts +0 -8
- package/dist/slices/remove-field/index.js +0 -167
- package/dist/slices/remove-scenario/index.d.ts +0 -2
- package/dist/slices/remove-scenario/index.js +0 -77
- package/dist/slices/search/index.d.ts +0 -3
- package/dist/slices/search/index.js +0 -302
- package/dist/slices/show-actor/index.d.ts +0 -4
- package/dist/slices/show-actor/index.js +0 -115
- package/dist/slices/show-aggregate/index.d.ts +0 -3
- package/dist/slices/show-aggregate/index.js +0 -108
- package/dist/slices/show-aggregate-completeness/index.d.ts +0 -4
- package/dist/slices/show-aggregate-completeness/index.js +0 -181
- package/dist/slices/show-chapter/index.d.ts +0 -3
- package/dist/slices/show-chapter/index.js +0 -195
- package/dist/slices/show-command/index.d.ts +0 -3
- package/dist/slices/show-command/index.js +0 -133
- package/dist/slices/show-completeness/index.d.ts +0 -4
- package/dist/slices/show-completeness/index.js +0 -731
- package/dist/slices/show-event/index.d.ts +0 -3
- package/dist/slices/show-event/index.js +0 -118
- package/dist/slices/show-model-summary/index.d.ts +0 -3
- package/dist/slices/show-model-summary/index.js +0 -31
- package/dist/slices/show-processor/index.d.ts +0 -3
- package/dist/slices/show-processor/index.js +0 -111
- package/dist/slices/show-readmodel/index.d.ts +0 -3
- package/dist/slices/show-readmodel/index.js +0 -158
- package/dist/slices/show-scenario/index.d.ts +0 -3
- package/dist/slices/show-scenario/index.js +0 -196
- package/dist/slices/show-screen/index.d.ts +0 -3
- package/dist/slices/show-screen/index.js +0 -139
- package/dist/slices/show-slice/index.d.ts +0 -3
- package/dist/slices/show-slice/index.js +0 -696
- package/dist/slices/update-field/index.d.ts +0 -15
- package/dist/slices/update-field/index.js +0 -208
- package/dist/slices/whoami/index.d.ts +0 -2
- package/dist/types.d.ts +0 -195
- 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,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
|
-
}
|