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,304 +0,0 @@
|
|
|
1
|
-
import { appendEvent } from '../../lib/file-loader.js';
|
|
2
|
-
import { AUTOMATION_SLICE, SLICE_GAP, calculateSlicePosition, validateSliceNameUnique, inferFieldMappings, parseFieldsFromXml, getSlicesToShift, fieldInputToField, } from '../../lib/slice-utils.js';
|
|
3
|
-
function getAttr(attrs, name) {
|
|
4
|
-
const match = attrs.match(new RegExp(`${name}="([^"]*)"`));
|
|
5
|
-
return match ? match[1] : undefined;
|
|
6
|
-
}
|
|
7
|
-
function parseXmlInput(xml) {
|
|
8
|
-
// Parse <automation-slice name="..." after="..." before="...">
|
|
9
|
-
const sliceMatch = xml.match(/<automation-slice([^>]*)>/);
|
|
10
|
-
if (!sliceMatch) {
|
|
11
|
-
throw new Error('Invalid XML: missing <automation-slice> tag');
|
|
12
|
-
}
|
|
13
|
-
const sliceName = getAttr(sliceMatch[1], 'name');
|
|
14
|
-
if (!sliceName) {
|
|
15
|
-
throw new Error('Invalid XML: automation-slice must have a name attribute');
|
|
16
|
-
}
|
|
17
|
-
const after = getAttr(sliceMatch[1], 'after');
|
|
18
|
-
const before = getAttr(sliceMatch[1], 'before');
|
|
19
|
-
// Parse read-model
|
|
20
|
-
const readModelMatch = xml.match(/<read-model([^>]*)>([\s\S]*?)<\/read-model>/);
|
|
21
|
-
if (!readModelMatch) {
|
|
22
|
-
throw new Error('Invalid XML: missing <read-model> element');
|
|
23
|
-
}
|
|
24
|
-
const readModelName = getAttr(readModelMatch[1], 'name');
|
|
25
|
-
if (!readModelName) {
|
|
26
|
-
throw new Error('Invalid XML: read-model must have a name attribute');
|
|
27
|
-
}
|
|
28
|
-
const readModelFields = parseFieldsFromXml(readModelMatch[2]);
|
|
29
|
-
// Parse processor (no fields)
|
|
30
|
-
const processorMatch = xml.match(/<processor([^>]*?)(?:\/>|>([\s\S]*?)<\/processor>)/);
|
|
31
|
-
if (!processorMatch) {
|
|
32
|
-
throw new Error('Invalid XML: missing <processor> element');
|
|
33
|
-
}
|
|
34
|
-
const processorName = getAttr(processorMatch[1], 'name');
|
|
35
|
-
if (!processorName) {
|
|
36
|
-
throw new Error('Invalid XML: processor must have a name attribute');
|
|
37
|
-
}
|
|
38
|
-
// Parse command
|
|
39
|
-
const commandMatch = xml.match(/<command([^>]*)>([\s\S]*?)<\/command>/);
|
|
40
|
-
if (!commandMatch) {
|
|
41
|
-
throw new Error('Invalid XML: missing <command> element');
|
|
42
|
-
}
|
|
43
|
-
const commandName = getAttr(commandMatch[1], 'name');
|
|
44
|
-
if (!commandName) {
|
|
45
|
-
throw new Error('Invalid XML: command must have a name attribute');
|
|
46
|
-
}
|
|
47
|
-
const commandFields = parseFieldsFromXml(commandMatch[2]);
|
|
48
|
-
// Parse event
|
|
49
|
-
const eventMatch = xml.match(/<event([^>]*)>([\s\S]*?)<\/event>/);
|
|
50
|
-
if (!eventMatch) {
|
|
51
|
-
throw new Error('Invalid XML: missing <event> element');
|
|
52
|
-
}
|
|
53
|
-
const eventName = getAttr(eventMatch[1], 'name');
|
|
54
|
-
if (!eventName) {
|
|
55
|
-
throw new Error('Invalid XML: event must have a name attribute');
|
|
56
|
-
}
|
|
57
|
-
const eventFields = parseFieldsFromXml(eventMatch[2]);
|
|
58
|
-
return {
|
|
59
|
-
sliceName,
|
|
60
|
-
after,
|
|
61
|
-
before,
|
|
62
|
-
readModel: { name: readModelName, fields: readModelFields },
|
|
63
|
-
processor: { name: processorName },
|
|
64
|
-
command: { name: commandName, fields: commandFields },
|
|
65
|
-
event: { name: eventName, fields: eventFields },
|
|
66
|
-
};
|
|
67
|
-
}
|
|
68
|
-
export function createAutomationSlice(model, filePath, xmlInput) {
|
|
69
|
-
// Parse input
|
|
70
|
-
let input;
|
|
71
|
-
try {
|
|
72
|
-
input = parseXmlInput(xmlInput);
|
|
73
|
-
}
|
|
74
|
-
catch (err) {
|
|
75
|
-
console.error(`Error: ${err.message}`);
|
|
76
|
-
process.exit(1);
|
|
77
|
-
}
|
|
78
|
-
// Validate slice name is unique
|
|
79
|
-
try {
|
|
80
|
-
validateSliceNameUnique(model, input.sliceName);
|
|
81
|
-
}
|
|
82
|
-
catch (err) {
|
|
83
|
-
console.error(`Error: ${err.message}`);
|
|
84
|
-
process.exit(1);
|
|
85
|
-
}
|
|
86
|
-
// Calculate position
|
|
87
|
-
let slicePosition;
|
|
88
|
-
try {
|
|
89
|
-
slicePosition = calculateSlicePosition(model, AUTOMATION_SLICE.width, {
|
|
90
|
-
after: input.after,
|
|
91
|
-
before: input.before,
|
|
92
|
-
});
|
|
93
|
-
}
|
|
94
|
-
catch (err) {
|
|
95
|
-
console.error(`Error: ${err.message}`);
|
|
96
|
-
process.exit(1);
|
|
97
|
-
}
|
|
98
|
-
// Handle "before" positioning - shift existing slices
|
|
99
|
-
if (input.before) {
|
|
100
|
-
const shiftAmount = AUTOMATION_SLICE.width + SLICE_GAP;
|
|
101
|
-
const toShift = getSlicesToShift(model, slicePosition.x, shiftAmount);
|
|
102
|
-
for (const { sliceId, newX, currentY } of toShift) {
|
|
103
|
-
appendEvent(filePath, {
|
|
104
|
-
type: 'SliceMoved',
|
|
105
|
-
data: {
|
|
106
|
-
sliceId,
|
|
107
|
-
position: { x: newX, y: currentY },
|
|
108
|
-
timestamp: Date.now(),
|
|
109
|
-
},
|
|
110
|
-
});
|
|
111
|
-
}
|
|
112
|
-
}
|
|
113
|
-
// Generate IDs
|
|
114
|
-
const sliceId = crypto.randomUUID();
|
|
115
|
-
const readModelId = crypto.randomUUID();
|
|
116
|
-
const processorId = crypto.randomUUID();
|
|
117
|
-
const commandId = crypto.randomUUID();
|
|
118
|
-
const eventId = crypto.randomUUID();
|
|
119
|
-
const readModelToProcessorFlowId = crypto.randomUUID();
|
|
120
|
-
const processorToCommandFlowId = crypto.randomUUID();
|
|
121
|
-
const commandToEventFlowId = crypto.randomUUID();
|
|
122
|
-
// Convert field inputs to fields with IDs
|
|
123
|
-
const readModelFields = input.readModel.fields.map(fieldInputToField);
|
|
124
|
-
const commandFields = input.command.fields.map(fieldInputToField);
|
|
125
|
-
const eventFields = input.event.fields.map(fieldInputToField);
|
|
126
|
-
// Infer field mappings
|
|
127
|
-
const readModelToCommandMappings = inferFieldMappings(readModelFields, commandFields);
|
|
128
|
-
const commandToEventMappings = inferFieldMappings(commandFields, eventFields);
|
|
129
|
-
// Calculate absolute positions for components within the slice
|
|
130
|
-
const readModelPosition = {
|
|
131
|
-
x: slicePosition.x + AUTOMATION_SLICE.readModel.offsetX,
|
|
132
|
-
y: slicePosition.y + AUTOMATION_SLICE.readModel.offsetY,
|
|
133
|
-
};
|
|
134
|
-
const processorPosition = {
|
|
135
|
-
x: slicePosition.x + AUTOMATION_SLICE.processor.offsetX,
|
|
136
|
-
y: slicePosition.y + AUTOMATION_SLICE.processor.offsetY,
|
|
137
|
-
};
|
|
138
|
-
const commandPosition = {
|
|
139
|
-
x: slicePosition.x + AUTOMATION_SLICE.command.offsetX,
|
|
140
|
-
y: slicePosition.y + AUTOMATION_SLICE.command.offsetY,
|
|
141
|
-
};
|
|
142
|
-
const eventPosition = {
|
|
143
|
-
x: slicePosition.x + AUTOMATION_SLICE.event.offsetX,
|
|
144
|
-
y: slicePosition.y + AUTOMATION_SLICE.event.offsetY,
|
|
145
|
-
};
|
|
146
|
-
// Emit atomic events in sequence
|
|
147
|
-
// 1. Create the slice
|
|
148
|
-
appendEvent(filePath, {
|
|
149
|
-
type: 'SlicePlaced',
|
|
150
|
-
data: {
|
|
151
|
-
sliceId,
|
|
152
|
-
name: input.sliceName,
|
|
153
|
-
position: slicePosition,
|
|
154
|
-
size: { width: AUTOMATION_SLICE.width, height: AUTOMATION_SLICE.height },
|
|
155
|
-
timestamp: Date.now(),
|
|
156
|
-
},
|
|
157
|
-
});
|
|
158
|
-
// 2. Create the read model
|
|
159
|
-
appendEvent(filePath, {
|
|
160
|
-
type: 'ReadModelStickyPlaced',
|
|
161
|
-
data: {
|
|
162
|
-
readModelStickyId: readModelId,
|
|
163
|
-
name: input.readModel.name,
|
|
164
|
-
position: readModelPosition,
|
|
165
|
-
width: AUTOMATION_SLICE.readModel.width,
|
|
166
|
-
height: AUTOMATION_SLICE.readModel.height,
|
|
167
|
-
timestamp: Date.now(),
|
|
168
|
-
},
|
|
169
|
-
});
|
|
170
|
-
// 3. Add read model fields
|
|
171
|
-
for (const field of readModelFields) {
|
|
172
|
-
appendEvent(filePath, {
|
|
173
|
-
type: 'ReadModelFieldAdded',
|
|
174
|
-
data: {
|
|
175
|
-
readModelStickyId: readModelId,
|
|
176
|
-
field,
|
|
177
|
-
timestamp: Date.now(),
|
|
178
|
-
},
|
|
179
|
-
});
|
|
180
|
-
}
|
|
181
|
-
// 4. Create the processor
|
|
182
|
-
appendEvent(filePath, {
|
|
183
|
-
type: 'ProcessorPlaced',
|
|
184
|
-
data: {
|
|
185
|
-
processorId,
|
|
186
|
-
name: input.processor.name,
|
|
187
|
-
position: processorPosition,
|
|
188
|
-
width: AUTOMATION_SLICE.processor.width,
|
|
189
|
-
height: AUTOMATION_SLICE.processor.height,
|
|
190
|
-
timestamp: Date.now(),
|
|
191
|
-
},
|
|
192
|
-
});
|
|
193
|
-
// 5. Create the command
|
|
194
|
-
appendEvent(filePath, {
|
|
195
|
-
type: 'CommandStickyPlaced',
|
|
196
|
-
data: {
|
|
197
|
-
commandStickyId: commandId,
|
|
198
|
-
name: input.command.name,
|
|
199
|
-
position: commandPosition,
|
|
200
|
-
width: AUTOMATION_SLICE.command.width,
|
|
201
|
-
height: AUTOMATION_SLICE.command.height,
|
|
202
|
-
timestamp: Date.now(),
|
|
203
|
-
},
|
|
204
|
-
});
|
|
205
|
-
// 6. Add command fields
|
|
206
|
-
for (const field of commandFields) {
|
|
207
|
-
appendEvent(filePath, {
|
|
208
|
-
type: 'CommandFieldAdded',
|
|
209
|
-
data: {
|
|
210
|
-
commandStickyId: commandId,
|
|
211
|
-
field,
|
|
212
|
-
timestamp: Date.now(),
|
|
213
|
-
},
|
|
214
|
-
});
|
|
215
|
-
}
|
|
216
|
-
// 7. Create the event
|
|
217
|
-
appendEvent(filePath, {
|
|
218
|
-
type: 'EventStickyPlaced',
|
|
219
|
-
data: {
|
|
220
|
-
eventStickyId: eventId,
|
|
221
|
-
name: input.event.name,
|
|
222
|
-
position: eventPosition,
|
|
223
|
-
width: AUTOMATION_SLICE.event.width,
|
|
224
|
-
height: AUTOMATION_SLICE.event.height,
|
|
225
|
-
timestamp: Date.now(),
|
|
226
|
-
},
|
|
227
|
-
});
|
|
228
|
-
// 8. Add event fields
|
|
229
|
-
for (const field of eventFields) {
|
|
230
|
-
appendEvent(filePath, {
|
|
231
|
-
type: 'EventFieldAdded',
|
|
232
|
-
data: {
|
|
233
|
-
eventStickyId: eventId,
|
|
234
|
-
field,
|
|
235
|
-
timestamp: Date.now(),
|
|
236
|
-
},
|
|
237
|
-
});
|
|
238
|
-
}
|
|
239
|
-
// 9. Create read model -> processor flow
|
|
240
|
-
appendEvent(filePath, {
|
|
241
|
-
type: 'ReadModelToProcessorFlowSpecified',
|
|
242
|
-
data: {
|
|
243
|
-
flowId: readModelToProcessorFlowId,
|
|
244
|
-
readModelStickyId: readModelId,
|
|
245
|
-
processorId,
|
|
246
|
-
sourceHandle: 'top-source',
|
|
247
|
-
targetHandle: 'bottom-target',
|
|
248
|
-
timestamp: Date.now(),
|
|
249
|
-
},
|
|
250
|
-
});
|
|
251
|
-
// 10. Add read model -> command field mappings
|
|
252
|
-
if (readModelToCommandMappings.length > 0) {
|
|
253
|
-
appendEvent(filePath, {
|
|
254
|
-
type: 'FieldMappingSpecified',
|
|
255
|
-
data: {
|
|
256
|
-
flowId: readModelToProcessorFlowId,
|
|
257
|
-
mappings: readModelToCommandMappings,
|
|
258
|
-
timestamp: Date.now(),
|
|
259
|
-
},
|
|
260
|
-
});
|
|
261
|
-
}
|
|
262
|
-
// 11. Create processor -> command flow
|
|
263
|
-
appendEvent(filePath, {
|
|
264
|
-
type: 'ProcessorToCommandFlowSpecified',
|
|
265
|
-
data: {
|
|
266
|
-
flowId: processorToCommandFlowId,
|
|
267
|
-
processorId,
|
|
268
|
-
commandStickyId: commandId,
|
|
269
|
-
sourceHandle: 'bottom-source',
|
|
270
|
-
targetHandle: 'top-target',
|
|
271
|
-
timestamp: Date.now(),
|
|
272
|
-
},
|
|
273
|
-
});
|
|
274
|
-
// 12. Create command -> event flow
|
|
275
|
-
appendEvent(filePath, {
|
|
276
|
-
type: 'CommandToEventFlowSpecified',
|
|
277
|
-
data: {
|
|
278
|
-
flowId: commandToEventFlowId,
|
|
279
|
-
commandStickyId: commandId,
|
|
280
|
-
eventStickyId: eventId,
|
|
281
|
-
sourceHandle: 'bottom-source',
|
|
282
|
-
targetHandle: 'top-target',
|
|
283
|
-
timestamp: Date.now(),
|
|
284
|
-
},
|
|
285
|
-
});
|
|
286
|
-
// 13. Add command -> event field mappings
|
|
287
|
-
if (commandToEventMappings.length > 0) {
|
|
288
|
-
appendEvent(filePath, {
|
|
289
|
-
type: 'FieldMappingSpecified',
|
|
290
|
-
data: {
|
|
291
|
-
flowId: commandToEventFlowId,
|
|
292
|
-
mappings: commandToEventMappings,
|
|
293
|
-
timestamp: Date.now(),
|
|
294
|
-
},
|
|
295
|
-
});
|
|
296
|
-
}
|
|
297
|
-
console.log(`Created automation slice "${input.sliceName}"`);
|
|
298
|
-
console.log(` ReadModel: ${input.readModel.name} (${readModelFields.length} fields)`);
|
|
299
|
-
console.log(` Processor: ${input.processor.name}`);
|
|
300
|
-
console.log(` Command: ${input.command.name} (${commandFields.length} fields)`);
|
|
301
|
-
console.log(` Event: ${input.event.name} (${eventFields.length} fields)`);
|
|
302
|
-
console.log(` ReadModel -> Command mappings: ${readModelToCommandMappings.length}`);
|
|
303
|
-
console.log(` Command -> Event mappings: ${commandToEventMappings.length}`);
|
|
304
|
-
}
|
|
@@ -1,183 +0,0 @@
|
|
|
1
|
-
import { appendEvent } from '../../lib/file-loader.js';
|
|
2
|
-
import { findElement, excludeLinkedCopies } from '../../lib/element-lookup.js';
|
|
3
|
-
function findSource(model, name) {
|
|
4
|
-
// Try events first (exclude linked copies - they share identity with canonical original)
|
|
5
|
-
const eventResult = findElement(excludeLinkedCopies(model.events), name);
|
|
6
|
-
if (eventResult.success) {
|
|
7
|
-
return { type: 'event', element: eventResult.element };
|
|
8
|
-
}
|
|
9
|
-
// Try read models (exclude linked copies)
|
|
10
|
-
const readModelResult = findElement(excludeLinkedCopies(model.readModels), name);
|
|
11
|
-
if (readModelResult.success) {
|
|
12
|
-
return { type: 'readModel', element: readModelResult.element };
|
|
13
|
-
}
|
|
14
|
-
return null;
|
|
15
|
-
}
|
|
16
|
-
function findTarget(model, name) {
|
|
17
|
-
// Try read models first (exclude linked copies)
|
|
18
|
-
const readModelResult = findElement(excludeLinkedCopies(model.readModels), name);
|
|
19
|
-
if (readModelResult.success) {
|
|
20
|
-
return { type: 'readModel', element: readModelResult.element };
|
|
21
|
-
}
|
|
22
|
-
// Try screens (exclude linked copies)
|
|
23
|
-
const screenResult = findElement(excludeLinkedCopies(model.screens), name);
|
|
24
|
-
if (screenResult.success) {
|
|
25
|
-
return { type: 'screen', element: screenResult.element };
|
|
26
|
-
}
|
|
27
|
-
// Try processors
|
|
28
|
-
const processorResult = findElement(model.processors, name);
|
|
29
|
-
if (processorResult.success) {
|
|
30
|
-
return { type: 'processor', element: processorResult.element };
|
|
31
|
-
}
|
|
32
|
-
return null;
|
|
33
|
-
}
|
|
34
|
-
function listAvailableSources(model) {
|
|
35
|
-
const sources = [];
|
|
36
|
-
for (const event of model.events.values()) {
|
|
37
|
-
sources.push(` - Event: "${event.name}"`);
|
|
38
|
-
}
|
|
39
|
-
for (const rm of model.readModels.values()) {
|
|
40
|
-
sources.push(` - ReadModel: "${rm.name}"`);
|
|
41
|
-
}
|
|
42
|
-
return sources;
|
|
43
|
-
}
|
|
44
|
-
function listAvailableTargets(model) {
|
|
45
|
-
const targets = [];
|
|
46
|
-
for (const rm of model.readModels.values()) {
|
|
47
|
-
targets.push(` - ReadModel: "${rm.name}"`);
|
|
48
|
-
}
|
|
49
|
-
for (const screen of model.screens.values()) {
|
|
50
|
-
targets.push(` - Screen: "${screen.name}"`);
|
|
51
|
-
}
|
|
52
|
-
for (const proc of model.processors.values()) {
|
|
53
|
-
targets.push(` - Processor: "${proc.name}"`);
|
|
54
|
-
}
|
|
55
|
-
return targets;
|
|
56
|
-
}
|
|
57
|
-
function flowExists(model, sourceId, targetId) {
|
|
58
|
-
for (const flow of model.flows.values()) {
|
|
59
|
-
if (flow.sourceId === sourceId && flow.targetId === targetId) {
|
|
60
|
-
return true;
|
|
61
|
-
}
|
|
62
|
-
}
|
|
63
|
-
return false;
|
|
64
|
-
}
|
|
65
|
-
export function createFlow(model, filePath, fromName, toName) {
|
|
66
|
-
// Find source element
|
|
67
|
-
const source = findSource(model, fromName);
|
|
68
|
-
if (!source) {
|
|
69
|
-
console.error(`Error: Source not found: "${fromName}"`);
|
|
70
|
-
console.error('Valid sources are events or read models.');
|
|
71
|
-
const available = listAvailableSources(model);
|
|
72
|
-
if (available.length > 0) {
|
|
73
|
-
console.error('Available sources:');
|
|
74
|
-
available.forEach(s => console.error(s));
|
|
75
|
-
}
|
|
76
|
-
process.exit(1);
|
|
77
|
-
}
|
|
78
|
-
// Find target element
|
|
79
|
-
const target = findTarget(model, toName);
|
|
80
|
-
if (!target) {
|
|
81
|
-
console.error(`Error: Target not found: "${toName}"`);
|
|
82
|
-
console.error('Valid targets are read models, screens, or processors.');
|
|
83
|
-
const available = listAvailableTargets(model);
|
|
84
|
-
if (available.length > 0) {
|
|
85
|
-
console.error('Available targets:');
|
|
86
|
-
available.forEach(t => console.error(t));
|
|
87
|
-
}
|
|
88
|
-
process.exit(1);
|
|
89
|
-
}
|
|
90
|
-
// Validate the flow combination
|
|
91
|
-
const flowId = crypto.randomUUID();
|
|
92
|
-
let event;
|
|
93
|
-
if (source.type === 'event' && target.type === 'readModel') {
|
|
94
|
-
// Event → ReadModel (event top → read model bottom)
|
|
95
|
-
if (flowExists(model, source.element.id, target.element.id)) {
|
|
96
|
-
console.error(`Error: Flow already exists from "${source.element.name}" to "${target.element.name}"`);
|
|
97
|
-
process.exit(1);
|
|
98
|
-
}
|
|
99
|
-
event = {
|
|
100
|
-
type: 'EventToReadModelFlowSpecified',
|
|
101
|
-
data: {
|
|
102
|
-
flowId,
|
|
103
|
-
eventStickyId: source.element.id,
|
|
104
|
-
readModelStickyId: target.element.id,
|
|
105
|
-
sourceHandle: 'top-source',
|
|
106
|
-
targetHandle: 'bottom-target',
|
|
107
|
-
timestamp: Date.now(),
|
|
108
|
-
},
|
|
109
|
-
};
|
|
110
|
-
appendEvent(filePath, event);
|
|
111
|
-
console.log(`Created flow: Event "${source.element.name}" → ReadModel "${target.element.name}"`);
|
|
112
|
-
}
|
|
113
|
-
else if (source.type === 'readModel' && target.type === 'screen') {
|
|
114
|
-
// ReadModel → Screen (read model top → screen bottom)
|
|
115
|
-
if (flowExists(model, source.element.id, target.element.id)) {
|
|
116
|
-
console.error(`Error: Flow already exists from "${source.element.name}" to "${target.element.name}"`);
|
|
117
|
-
process.exit(1);
|
|
118
|
-
}
|
|
119
|
-
event = {
|
|
120
|
-
type: 'ReadModelToScreenFlowSpecified',
|
|
121
|
-
data: {
|
|
122
|
-
flowId,
|
|
123
|
-
readModelStickyId: source.element.id,
|
|
124
|
-
screenId: target.element.id,
|
|
125
|
-
sourceHandle: 'top-source',
|
|
126
|
-
targetHandle: 'bottom-target',
|
|
127
|
-
timestamp: Date.now(),
|
|
128
|
-
},
|
|
129
|
-
};
|
|
130
|
-
appendEvent(filePath, event);
|
|
131
|
-
console.log(`Created flow: ReadModel "${source.element.name}" → Screen "${target.element.name}"`);
|
|
132
|
-
}
|
|
133
|
-
else if (source.type === 'readModel' && target.type === 'processor') {
|
|
134
|
-
// ReadModel → Processor (read model top → processor bottom)
|
|
135
|
-
if (flowExists(model, source.element.id, target.element.id)) {
|
|
136
|
-
console.error(`Error: Flow already exists from "${source.element.name}" to "${target.element.name}"`);
|
|
137
|
-
process.exit(1);
|
|
138
|
-
}
|
|
139
|
-
event = {
|
|
140
|
-
type: 'ReadModelToProcessorFlowSpecified',
|
|
141
|
-
data: {
|
|
142
|
-
flowId,
|
|
143
|
-
readModelStickyId: source.element.id,
|
|
144
|
-
processorId: target.element.id,
|
|
145
|
-
sourceHandle: 'top-source',
|
|
146
|
-
targetHandle: 'bottom-target',
|
|
147
|
-
timestamp: Date.now(),
|
|
148
|
-
},
|
|
149
|
-
};
|
|
150
|
-
appendEvent(filePath, event);
|
|
151
|
-
console.log(`Created flow: ReadModel "${source.element.name}" → Processor "${target.element.name}"`);
|
|
152
|
-
}
|
|
153
|
-
else if (source.type === 'event' && target.type === 'screen') {
|
|
154
|
-
console.error('Error: Cannot create flow directly from Event to Screen.');
|
|
155
|
-
console.error('Events flow to ReadModels, which then flow to Screens.');
|
|
156
|
-
console.error('Create a ReadModel first, then:');
|
|
157
|
-
console.error(` 1. eventmodeler create flow --from "${source.element.name}" --to "<ReadModelName>"`);
|
|
158
|
-
console.error(` 2. eventmodeler create flow --from "<ReadModelName>" --to "${target.element.name}"`);
|
|
159
|
-
process.exit(1);
|
|
160
|
-
}
|
|
161
|
-
else if (source.type === 'event' && target.type === 'processor') {
|
|
162
|
-
console.error('Error: Cannot create flow directly from Event to Processor.');
|
|
163
|
-
console.error('Events flow to ReadModels, which then flow to Processors.');
|
|
164
|
-
console.error('Create a ReadModel first, then:');
|
|
165
|
-
console.error(` 1. eventmodeler create flow --from "${source.element.name}" --to "<ReadModelName>"`);
|
|
166
|
-
console.error(` 2. eventmodeler create flow --from "<ReadModelName>" --to "${target.element.name}"`);
|
|
167
|
-
process.exit(1);
|
|
168
|
-
}
|
|
169
|
-
else if (source.type === 'readModel' && target.type === 'readModel') {
|
|
170
|
-
console.error('Error: Cannot create flow from ReadModel to ReadModel.');
|
|
171
|
-
console.error('ReadModels receive data from Events and provide data to Screens or Processors.');
|
|
172
|
-
process.exit(1);
|
|
173
|
-
}
|
|
174
|
-
else {
|
|
175
|
-
console.error(`Error: Invalid flow combination: ${source.type} → ${target.type}`);
|
|
176
|
-
console.error('Valid combinations:');
|
|
177
|
-
console.error(' - Event → ReadModel');
|
|
178
|
-
console.error(' - ReadModel → Screen');
|
|
179
|
-
console.error(' - ReadModel → Processor');
|
|
180
|
-
process.exit(1);
|
|
181
|
-
}
|
|
182
|
-
console.log(`Use 'eventmodeler map fields --flow "${fromName}→${toName}"' to set field mappings.`);
|
|
183
|
-
}
|