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.
- 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 +38 -38
- package/dist/slices/guide/guides/create-slices.js +110 -140
- package/dist/slices/guide/guides/explore.js +37 -50
- package/dist/slices/guide/guides/information-flow.js +70 -84
- 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,448 +0,0 @@
|
|
|
1
|
-
import { outputJson } from '../../lib/format.js';
|
|
2
|
-
import { findElementOrExit } from '../../lib/element-lookup.js';
|
|
3
|
-
import { findChapterForSlice, getChapterHierarchy } from '../../lib/chapter-utils.js';
|
|
4
|
-
// Get components inside a slice by checking if center point is within bounds
|
|
5
|
-
function getSliceComponents(model, slice) {
|
|
6
|
-
const bounds = {
|
|
7
|
-
left: slice.position.x,
|
|
8
|
-
right: slice.position.x + slice.size.width,
|
|
9
|
-
top: slice.position.y,
|
|
10
|
-
bottom: slice.position.y + slice.size.height,
|
|
11
|
-
};
|
|
12
|
-
function isInSlice(pos, width, height) {
|
|
13
|
-
const centerX = pos.x + width / 2;
|
|
14
|
-
const centerY = pos.y + height / 2;
|
|
15
|
-
return centerX >= bounds.left && centerX <= bounds.right && centerY >= bounds.top && centerY <= bounds.bottom;
|
|
16
|
-
}
|
|
17
|
-
// Only include canonical elements - linked copies are UI-only conveniences
|
|
18
|
-
// and should not appear as slice contents in codegen output
|
|
19
|
-
return {
|
|
20
|
-
commands: [...model.commands.values()].filter(c => isInSlice(c.position, c.width, c.height)),
|
|
21
|
-
events: [...model.events.values()].filter(e => !e.originalNodeId && isInSlice(e.position, e.width, e.height)),
|
|
22
|
-
readModels: [...model.readModels.values()].filter(rm => !rm.originalNodeId && isInSlice(rm.position, rm.width, rm.height)),
|
|
23
|
-
screens: [...model.screens.values()].filter(s => !s.originalNodeId && isInSlice(s.position, s.width, s.height)),
|
|
24
|
-
processors: [...model.processors.values()].filter(p => isInSlice(p.position, p.width, p.height)),
|
|
25
|
-
};
|
|
26
|
-
}
|
|
27
|
-
// Find which slice contains a node
|
|
28
|
-
function findSliceForNode(model, nodeId) {
|
|
29
|
-
const event = model.events.get(nodeId);
|
|
30
|
-
const readModel = model.readModels.get(nodeId);
|
|
31
|
-
const screen = model.screens.get(nodeId);
|
|
32
|
-
const command = model.commands.get(nodeId);
|
|
33
|
-
const processor = model.processors.get(nodeId);
|
|
34
|
-
const node = event ?? readModel ?? screen ?? command ?? processor;
|
|
35
|
-
if (!node)
|
|
36
|
-
return null;
|
|
37
|
-
for (const slice of model.slices.values()) {
|
|
38
|
-
const centerX = node.position.x + node.width / 2;
|
|
39
|
-
const centerY = node.position.y + node.height / 2;
|
|
40
|
-
if (centerX >= slice.position.x &&
|
|
41
|
-
centerX <= slice.position.x + slice.size.width &&
|
|
42
|
-
centerY >= slice.position.y &&
|
|
43
|
-
centerY <= slice.position.y + slice.size.height) {
|
|
44
|
-
return slice;
|
|
45
|
-
}
|
|
46
|
-
}
|
|
47
|
-
return null;
|
|
48
|
-
}
|
|
49
|
-
// Find which aggregate an event belongs to
|
|
50
|
-
function findAggregateForEvent(model, event) {
|
|
51
|
-
const centerX = event.position.x + event.width / 2;
|
|
52
|
-
const centerY = event.position.y + event.height / 2;
|
|
53
|
-
for (const aggregate of model.aggregates.values()) {
|
|
54
|
-
if (centerX >= aggregate.position.x &&
|
|
55
|
-
centerX <= aggregate.position.x + aggregate.size.width &&
|
|
56
|
-
centerY >= aggregate.position.y &&
|
|
57
|
-
centerY <= aggregate.position.y + aggregate.size.height) {
|
|
58
|
-
return aggregate.name;
|
|
59
|
-
}
|
|
60
|
-
}
|
|
61
|
-
return undefined;
|
|
62
|
-
}
|
|
63
|
-
// Find which actor a screen belongs to
|
|
64
|
-
function findActorForScreen(model, screen) {
|
|
65
|
-
const centerX = screen.position.x + screen.width / 2;
|
|
66
|
-
const centerY = screen.position.y + screen.height / 2;
|
|
67
|
-
for (const actor of model.actors.values()) {
|
|
68
|
-
if (centerX >= actor.position.x &&
|
|
69
|
-
centerX <= actor.position.x + actor.size.width &&
|
|
70
|
-
centerY >= actor.position.y &&
|
|
71
|
-
centerY <= actor.position.y + actor.size.height) {
|
|
72
|
-
return actor.name;
|
|
73
|
-
}
|
|
74
|
-
}
|
|
75
|
-
return undefined;
|
|
76
|
-
}
|
|
77
|
-
// Convert Field to JSON-friendly format
|
|
78
|
-
function fieldToJson(field) {
|
|
79
|
-
const result = {
|
|
80
|
-
name: field.name,
|
|
81
|
-
type: field.fieldType,
|
|
82
|
-
};
|
|
83
|
-
if (field.isList)
|
|
84
|
-
result.list = true;
|
|
85
|
-
if (field.isGenerated)
|
|
86
|
-
result.generated = true;
|
|
87
|
-
if (field.isOptional)
|
|
88
|
-
result.optional = true;
|
|
89
|
-
if (field.isUserInput)
|
|
90
|
-
result.userInput = true;
|
|
91
|
-
if (field.subfields && field.subfields.length > 0) {
|
|
92
|
-
result.subfields = field.subfields.map(fieldToJson);
|
|
93
|
-
}
|
|
94
|
-
return result;
|
|
95
|
-
}
|
|
96
|
-
// Determine slice type based on components, returns null for invalid configurations
|
|
97
|
-
function determineSliceType(hasProcessors, hasCommands, hasEvents, hasReadModels, hasScreens) {
|
|
98
|
-
// AUTOMATION: Must have a Processor (and typically ReadModel, Command, Event)
|
|
99
|
-
if (hasProcessors)
|
|
100
|
-
return 'AUTOMATION';
|
|
101
|
-
// STATE_CHANGE: Must have both Command and Event (typically with Screen)
|
|
102
|
-
if (hasCommands && hasEvents)
|
|
103
|
-
return 'STATE_CHANGE';
|
|
104
|
-
// STATE_VIEW: Must have at least one ReadModel
|
|
105
|
-
if (hasReadModels && !hasCommands && !hasEvents)
|
|
106
|
-
return 'STATE_VIEW';
|
|
107
|
-
// Invalid configurations:
|
|
108
|
-
// - Empty slice
|
|
109
|
-
// - Only Command (no Event)
|
|
110
|
-
// - Only Event (no Command)
|
|
111
|
-
// - Only Screen (no Command)
|
|
112
|
-
return null;
|
|
113
|
-
}
|
|
114
|
-
// Get element type for an ID
|
|
115
|
-
function getElementType(model, id) {
|
|
116
|
-
if (model.commands.has(id))
|
|
117
|
-
return 'COMMAND';
|
|
118
|
-
if (model.events.has(id))
|
|
119
|
-
return 'EVENT';
|
|
120
|
-
if (model.readModels.has(id))
|
|
121
|
-
return 'READMODEL';
|
|
122
|
-
if (model.screens.has(id))
|
|
123
|
-
return 'SCREEN';
|
|
124
|
-
if (model.processors.has(id))
|
|
125
|
-
return 'PROCESSOR';
|
|
126
|
-
return null;
|
|
127
|
-
}
|
|
128
|
-
// Get element name for an ID
|
|
129
|
-
function getElementName(model, id) {
|
|
130
|
-
return (model.commands.get(id)?.name ??
|
|
131
|
-
model.events.get(id)?.name ??
|
|
132
|
-
model.readModels.get(id)?.name ??
|
|
133
|
-
model.screens.get(id)?.name ??
|
|
134
|
-
model.processors.get(id)?.name ??
|
|
135
|
-
'Unknown');
|
|
136
|
-
}
|
|
137
|
-
// Get element fields for an ID
|
|
138
|
-
function getElementFields(model, id) {
|
|
139
|
-
return (model.commands.get(id)?.fields ??
|
|
140
|
-
model.events.get(id)?.fields ??
|
|
141
|
-
model.readModels.get(id)?.fields ??
|
|
142
|
-
model.screens.get(id)?.fields ??
|
|
143
|
-
model.processors.get(id)?.fields ??
|
|
144
|
-
[]);
|
|
145
|
-
}
|
|
146
|
-
// Find a field by ID within an element's fields
|
|
147
|
-
function findFieldById(fields, fieldId) {
|
|
148
|
-
for (const field of fields) {
|
|
149
|
-
if (field.id === fieldId)
|
|
150
|
-
return field;
|
|
151
|
-
if (field.subfields) {
|
|
152
|
-
const found = findFieldById(field.subfields, fieldId);
|
|
153
|
-
if (found)
|
|
154
|
-
return found;
|
|
155
|
-
}
|
|
156
|
-
}
|
|
157
|
-
return undefined;
|
|
158
|
-
}
|
|
159
|
-
// Get element reference (type, id, name)
|
|
160
|
-
function getElementRef(model, id) {
|
|
161
|
-
return {
|
|
162
|
-
type: getElementType(model, id) ?? 'EVENT',
|
|
163
|
-
id,
|
|
164
|
-
name: getElementName(model, id),
|
|
165
|
-
};
|
|
166
|
-
}
|
|
167
|
-
// Get element with full schema
|
|
168
|
-
function getElementWithSchema(model, id) {
|
|
169
|
-
const type = getElementType(model, id) ?? 'EVENT';
|
|
170
|
-
const name = getElementName(model, id);
|
|
171
|
-
const fields = getElementFields(model, id).map(fieldToJson);
|
|
172
|
-
const result = { type, id, name, fields };
|
|
173
|
-
// Add aggregate info for events
|
|
174
|
-
const event = model.events.get(id);
|
|
175
|
-
if (event) {
|
|
176
|
-
const aggregate = findAggregateForEvent(model, event);
|
|
177
|
-
if (aggregate)
|
|
178
|
-
result.aggregate = aggregate;
|
|
179
|
-
const originSlice = findSliceForNode(model, id);
|
|
180
|
-
if (originSlice)
|
|
181
|
-
result.originSlice = originSlice.name;
|
|
182
|
-
}
|
|
183
|
-
// Add actor info for screens
|
|
184
|
-
const screen = model.screens.get(id);
|
|
185
|
-
if (screen) {
|
|
186
|
-
const actor = findActorForScreen(model, screen);
|
|
187
|
-
if (actor)
|
|
188
|
-
result.actor = actor;
|
|
189
|
-
}
|
|
190
|
-
return result;
|
|
191
|
-
}
|
|
192
|
-
// Enrich field mappings with field names
|
|
193
|
-
function enrichFieldMappings(model, flow) {
|
|
194
|
-
const sourceFields = getElementFields(model, flow.sourceId);
|
|
195
|
-
const targetFields = getElementFields(model, flow.targetId);
|
|
196
|
-
return flow.fieldMappings.map(mapping => {
|
|
197
|
-
const sourceField = findFieldById(sourceFields, mapping.sourceFieldId);
|
|
198
|
-
const targetField = findFieldById(targetFields, mapping.targetFieldId);
|
|
199
|
-
return {
|
|
200
|
-
sourceFieldId: mapping.sourceFieldId,
|
|
201
|
-
sourceFieldName: sourceField?.name ?? 'unknown',
|
|
202
|
-
targetFieldId: mapping.targetFieldId,
|
|
203
|
-
targetFieldName: targetField?.name ?? 'unknown',
|
|
204
|
-
};
|
|
205
|
-
});
|
|
206
|
-
}
|
|
207
|
-
// Get inbound dependencies (flows where target is in slice but source is not)
|
|
208
|
-
function getInboundDependencies(model, componentIds) {
|
|
209
|
-
return [...model.flows.values()]
|
|
210
|
-
.filter(f => componentIds.has(f.targetId) && !componentIds.has(f.sourceId))
|
|
211
|
-
.map(flow => ({
|
|
212
|
-
flowId: flow.id,
|
|
213
|
-
flowType: flow.flowType,
|
|
214
|
-
source: getElementWithSchema(model, flow.sourceId),
|
|
215
|
-
target: getElementRef(model, flow.targetId),
|
|
216
|
-
fieldMappings: enrichFieldMappings(model, flow),
|
|
217
|
-
}));
|
|
218
|
-
}
|
|
219
|
-
// Get internal flows (both source and target are in slice)
|
|
220
|
-
function getInternalFlows(model, componentIds) {
|
|
221
|
-
return [...model.flows.values()]
|
|
222
|
-
.filter(f => componentIds.has(f.sourceId) && componentIds.has(f.targetId))
|
|
223
|
-
.map(flow => ({
|
|
224
|
-
flowId: flow.id,
|
|
225
|
-
flowType: flow.flowType,
|
|
226
|
-
source: getElementRef(model, flow.sourceId),
|
|
227
|
-
target: getElementRef(model, flow.targetId),
|
|
228
|
-
fieldMappings: enrichFieldMappings(model, flow),
|
|
229
|
-
}));
|
|
230
|
-
}
|
|
231
|
-
// Format scenario then clause
|
|
232
|
-
function formatScenarioThen(model, then) {
|
|
233
|
-
if (then.type === 'error') {
|
|
234
|
-
return {
|
|
235
|
-
type: 'error',
|
|
236
|
-
errorType: then.errorType,
|
|
237
|
-
errorMessage: then.errorMessage,
|
|
238
|
-
};
|
|
239
|
-
}
|
|
240
|
-
if (then.type === 'events' && then.expectedEvents) {
|
|
241
|
-
return {
|
|
242
|
-
type: 'events',
|
|
243
|
-
expectedEvents: then.expectedEvents.map(expected => {
|
|
244
|
-
const event = model.events.get(expected.eventStickyId);
|
|
245
|
-
return {
|
|
246
|
-
eventId: expected.eventStickyId,
|
|
247
|
-
eventName: event?.name ?? 'UnknownEvent',
|
|
248
|
-
eventSchema: { fields: event?.fields.map(fieldToJson) ?? [] },
|
|
249
|
-
fieldValues: expected.fieldValues ?? {},
|
|
250
|
-
};
|
|
251
|
-
}),
|
|
252
|
-
};
|
|
253
|
-
}
|
|
254
|
-
if (then.type === 'command' && then.expectedCommand) {
|
|
255
|
-
const command = model.commands.get(then.expectedCommand.commandStickyId);
|
|
256
|
-
return {
|
|
257
|
-
type: 'command',
|
|
258
|
-
expectedCommand: {
|
|
259
|
-
commandId: then.expectedCommand.commandStickyId,
|
|
260
|
-
commandName: command?.name ?? 'UnknownCommand',
|
|
261
|
-
commandSchema: { fields: command?.fields.map(fieldToJson) ?? [] },
|
|
262
|
-
fieldValues: then.expectedCommand.fieldValues ?? {},
|
|
263
|
-
},
|
|
264
|
-
};
|
|
265
|
-
}
|
|
266
|
-
if (then.type === 'noCommand') {
|
|
267
|
-
return {
|
|
268
|
-
type: 'noCommand',
|
|
269
|
-
};
|
|
270
|
-
}
|
|
271
|
-
if (then.type === 'readModelAssertion' && then.readModelAssertion) {
|
|
272
|
-
const rm = model.readModels.get(then.readModelAssertion.readModelStickyId);
|
|
273
|
-
return {
|
|
274
|
-
type: 'readModelAssertion',
|
|
275
|
-
readModelName: rm?.name ?? 'UnknownReadModel',
|
|
276
|
-
expectedFieldValues: then.readModelAssertion.expectedFieldValues,
|
|
277
|
-
};
|
|
278
|
-
}
|
|
279
|
-
// Default fallback
|
|
280
|
-
return { type: 'events', expectedEvents: [] };
|
|
281
|
-
}
|
|
282
|
-
// Format scenarios with resolved schemas
|
|
283
|
-
function formatScenarios(model, scenarios) {
|
|
284
|
-
return scenarios.map(scenario => ({
|
|
285
|
-
id: scenario.id,
|
|
286
|
-
name: scenario.name,
|
|
287
|
-
description: scenario.description,
|
|
288
|
-
given: scenario.givenEvents.map(ref => {
|
|
289
|
-
const event = model.events.get(ref.eventStickyId);
|
|
290
|
-
const originSlice = findSliceForNode(model, ref.eventStickyId);
|
|
291
|
-
return {
|
|
292
|
-
eventId: ref.eventStickyId,
|
|
293
|
-
eventName: event?.name ?? 'UnknownEvent',
|
|
294
|
-
originSlice: originSlice?.name ?? null,
|
|
295
|
-
eventSchema: { fields: event?.fields.map(fieldToJson) ?? [] },
|
|
296
|
-
fieldValues: ref.fieldValues ?? {},
|
|
297
|
-
};
|
|
298
|
-
}),
|
|
299
|
-
whenCommand: scenario.whenCommand
|
|
300
|
-
? {
|
|
301
|
-
commandId: scenario.whenCommand.commandStickyId,
|
|
302
|
-
commandName: model.commands.get(scenario.whenCommand.commandStickyId)?.name ?? 'UnknownCommand',
|
|
303
|
-
fieldValues: scenario.whenCommand.fieldValues ?? {},
|
|
304
|
-
}
|
|
305
|
-
: null,
|
|
306
|
-
whenEvents: scenario.whenEvents.map(ref => {
|
|
307
|
-
const event = model.events.get(ref.eventStickyId);
|
|
308
|
-
const originSlice = findSliceForNode(model, ref.eventStickyId);
|
|
309
|
-
return {
|
|
310
|
-
eventId: ref.eventStickyId,
|
|
311
|
-
eventName: event?.name ?? 'UnknownEvent',
|
|
312
|
-
originSlice: originSlice?.name ?? null,
|
|
313
|
-
eventSchema: { fields: event?.fields.map(fieldToJson) ?? [] },
|
|
314
|
-
fieldValues: ref.fieldValues ?? {},
|
|
315
|
-
};
|
|
316
|
-
}),
|
|
317
|
-
then: formatScenarioThen(model, scenario.then),
|
|
318
|
-
}));
|
|
319
|
-
}
|
|
320
|
-
export function codegenSlice(model, sliceName) {
|
|
321
|
-
// 1. Find the slice
|
|
322
|
-
const slice = findElementOrExit(model.slices, sliceName, 'slice');
|
|
323
|
-
// 2. Get components inside slice
|
|
324
|
-
const components = getSliceComponents(model, slice);
|
|
325
|
-
// 3. Build component ID set (including canonical group members for linked copies)
|
|
326
|
-
const componentIds = new Set();
|
|
327
|
-
components.commands.forEach(c => componentIds.add(c.id));
|
|
328
|
-
components.events.forEach(e => {
|
|
329
|
-
componentIds.add(e.id);
|
|
330
|
-
// If this is a linked copy, also add all elements in the same canonical group
|
|
331
|
-
if (e.canonicalId) {
|
|
332
|
-
for (const evt of model.events.values()) {
|
|
333
|
-
if (evt.canonicalId === e.canonicalId) {
|
|
334
|
-
componentIds.add(evt.id);
|
|
335
|
-
}
|
|
336
|
-
}
|
|
337
|
-
}
|
|
338
|
-
});
|
|
339
|
-
components.readModels.forEach(rm => {
|
|
340
|
-
componentIds.add(rm.id);
|
|
341
|
-
// If this is a linked copy, also add all elements in the same canonical group
|
|
342
|
-
if (rm.canonicalId) {
|
|
343
|
-
for (const r of model.readModels.values()) {
|
|
344
|
-
if (r.canonicalId === rm.canonicalId) {
|
|
345
|
-
componentIds.add(r.id);
|
|
346
|
-
}
|
|
347
|
-
}
|
|
348
|
-
}
|
|
349
|
-
});
|
|
350
|
-
components.screens.forEach(s => {
|
|
351
|
-
componentIds.add(s.id);
|
|
352
|
-
// If this is a linked copy, also add all elements in the same canonical group
|
|
353
|
-
if (s.canonicalId) {
|
|
354
|
-
for (const scr of model.screens.values()) {
|
|
355
|
-
if (scr.canonicalId === s.canonicalId) {
|
|
356
|
-
componentIds.add(scr.id);
|
|
357
|
-
}
|
|
358
|
-
}
|
|
359
|
-
}
|
|
360
|
-
});
|
|
361
|
-
components.processors.forEach(p => componentIds.add(p.id));
|
|
362
|
-
// 4. Determine slice type
|
|
363
|
-
const sliceType = determineSliceType(components.processors.length > 0, components.commands.length > 0, components.events.length > 0, components.readModels.length > 0, components.screens.length > 0);
|
|
364
|
-
// Validate slice type - exit with error for invalid configurations
|
|
365
|
-
if (sliceType === null) {
|
|
366
|
-
const hasAny = componentIds.size > 0;
|
|
367
|
-
if (!hasAny) {
|
|
368
|
-
console.error(`Error: Slice "${slice.name}" is empty - no elements found inside slice bounds`);
|
|
369
|
-
}
|
|
370
|
-
else {
|
|
371
|
-
const parts = [];
|
|
372
|
-
if (components.commands.length > 0)
|
|
373
|
-
parts.push(`${components.commands.length} command(s)`);
|
|
374
|
-
if (components.events.length > 0)
|
|
375
|
-
parts.push(`${components.events.length} event(s)`);
|
|
376
|
-
if (components.screens.length > 0)
|
|
377
|
-
parts.push(`${components.screens.length} screen(s)`);
|
|
378
|
-
if (components.readModels.length > 0)
|
|
379
|
-
parts.push(`${components.readModels.length} read model(s)`);
|
|
380
|
-
console.error(`Error: Slice "${slice.name}" has invalid configuration for codegen: ${parts.join(', ')}`);
|
|
381
|
-
console.error('Valid configurations:');
|
|
382
|
-
console.error(' AUTOMATION: Processor + ReadModel + Command + Event');
|
|
383
|
-
console.error(' STATE_CHANGE: Screen + Command + Event');
|
|
384
|
-
console.error(' STATE_VIEW: ReadModel only');
|
|
385
|
-
}
|
|
386
|
-
process.exit(1);
|
|
387
|
-
}
|
|
388
|
-
// 5. Get inbound dependencies with full schemas
|
|
389
|
-
const inboundDependencies = getInboundDependencies(model, componentIds);
|
|
390
|
-
// 6. Get internal flows with field mappings
|
|
391
|
-
const internalFlows = getInternalFlows(model, componentIds);
|
|
392
|
-
// 7. Get scenarios for this slice
|
|
393
|
-
const scenarios = [...model.scenarios.values()].filter(s => s.sliceId === slice.id);
|
|
394
|
-
// 8. Find which chapter this slice belongs to
|
|
395
|
-
const chapter = findChapterForSlice(model, slice);
|
|
396
|
-
// 9. Build output
|
|
397
|
-
const output = {
|
|
398
|
-
sliceType,
|
|
399
|
-
slice: {
|
|
400
|
-
id: slice.id,
|
|
401
|
-
name: slice.name,
|
|
402
|
-
},
|
|
403
|
-
...(chapter && { chapter: getChapterHierarchy(model, chapter) }),
|
|
404
|
-
elements: {
|
|
405
|
-
readModels: components.readModels.map(rm => ({
|
|
406
|
-
id: rm.id,
|
|
407
|
-
name: rm.name,
|
|
408
|
-
fields: rm.fields.map(fieldToJson),
|
|
409
|
-
})),
|
|
410
|
-
processors: components.processors.map(p => ({
|
|
411
|
-
id: p.id,
|
|
412
|
-
name: p.name,
|
|
413
|
-
})),
|
|
414
|
-
commands: components.commands.map(cmd => ({
|
|
415
|
-
id: cmd.id,
|
|
416
|
-
name: cmd.name,
|
|
417
|
-
fields: cmd.fields.map(fieldToJson),
|
|
418
|
-
})),
|
|
419
|
-
events: components.events.map(evt => {
|
|
420
|
-
const result = {
|
|
421
|
-
id: evt.id,
|
|
422
|
-
name: evt.name,
|
|
423
|
-
fields: evt.fields.map(fieldToJson),
|
|
424
|
-
};
|
|
425
|
-
const aggregate = findAggregateForEvent(model, evt);
|
|
426
|
-
if (aggregate)
|
|
427
|
-
result.aggregate = aggregate;
|
|
428
|
-
return result;
|
|
429
|
-
}),
|
|
430
|
-
screens: components.screens.map(scr => {
|
|
431
|
-
const result = {
|
|
432
|
-
id: scr.id,
|
|
433
|
-
name: scr.name,
|
|
434
|
-
fields: scr.fields.map(fieldToJson),
|
|
435
|
-
};
|
|
436
|
-
const actor = findActorForScreen(model, scr);
|
|
437
|
-
if (actor)
|
|
438
|
-
result.actor = actor;
|
|
439
|
-
return result;
|
|
440
|
-
}),
|
|
441
|
-
},
|
|
442
|
-
inboundDependencies,
|
|
443
|
-
internalFlows,
|
|
444
|
-
scenarios: formatScenarios(model, scenarios),
|
|
445
|
-
};
|
|
446
|
-
// 10. Output JSON
|
|
447
|
-
outputJson(output);
|
|
448
|
-
}
|