eventmodeler 0.4.4 → 0.4.5
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/index.d.ts +282 -0
- package/dist/api/index.js +320 -0
- package/dist/index.js +256 -809
- package/dist/lib/config.d.ts +2 -1
- package/dist/lib/project-config.d.ts +0 -3
- package/dist/lib/project-config.js +1 -8
- package/dist/lib/slice-utils.d.ts +0 -79
- package/dist/lib/slice-utils.js +87 -237
- package/dist/projection.js +0 -30
- package/dist/slices/add-scenario/index.d.ts +0 -2
- package/dist/slices/add-scenario/index.js +120 -318
- package/dist/slices/init/index.d.ts +1 -0
- package/dist/slices/init/index.js +40 -93
- package/dist/slices/whoami/index.d.ts +1 -1
- package/dist/slices/whoami/index.js +19 -10
- package/package.json +5 -2
package/dist/lib/config.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
|
|
1
|
+
type OutputFormat = 'xml' | 'json';
|
|
2
2
|
export interface AuthTokens {
|
|
3
3
|
accessToken: string;
|
|
4
4
|
refreshToken: string;
|
|
@@ -27,3 +27,4 @@ export declare function setBackendUrl(url: string): void;
|
|
|
27
27
|
export declare function getKeycloakUrl(): string;
|
|
28
28
|
export declare function setKeycloakUrl(url: string): void;
|
|
29
29
|
export declare function getDefaultFormat(): OutputFormat;
|
|
30
|
+
export {};
|
|
@@ -37,11 +37,6 @@ export function loadProjectConfig(startDir) {
|
|
|
37
37
|
if (config.type === 'cloud' && config.modelId && config.modelName) {
|
|
38
38
|
return { type: 'cloud', modelId: config.modelId, modelName: config.modelName };
|
|
39
39
|
}
|
|
40
|
-
if (config.type === 'local' && config.file) {
|
|
41
|
-
// Resolve file path relative to the config file location
|
|
42
|
-
const configDir = path.dirname(configPath);
|
|
43
|
-
return { type: 'local', file: path.resolve(configDir, config.file) };
|
|
44
|
-
}
|
|
45
40
|
return null;
|
|
46
41
|
}
|
|
47
42
|
catch {
|
|
@@ -53,9 +48,7 @@ export function loadProjectConfig(startDir) {
|
|
|
53
48
|
*/
|
|
54
49
|
export function saveProjectConfig(config, targetDir = process.cwd()) {
|
|
55
50
|
const configPath = path.join(targetDir, PROJECT_CONFIG_FILENAME);
|
|
56
|
-
const content =
|
|
57
|
-
? { type: 'cloud', modelId: config.modelId, modelName: config.modelName }
|
|
58
|
-
: { type: 'local', file: config.file };
|
|
51
|
+
const content = { type: 'cloud', modelId: config.modelId, modelName: config.modelName };
|
|
59
52
|
fs.writeFileSync(configPath, JSON.stringify(content, null, 2) + '\n');
|
|
60
53
|
return configPath;
|
|
61
54
|
}
|
|
@@ -1,81 +1,3 @@
|
|
|
1
|
-
import type { EventModel, Field, FieldMapping, Slice } from '../types.js';
|
|
2
|
-
export declare const STATE_CHANGE_SLICE: {
|
|
3
|
-
width: number;
|
|
4
|
-
height: number;
|
|
5
|
-
screen: {
|
|
6
|
-
width: number;
|
|
7
|
-
height: number;
|
|
8
|
-
offsetX: number;
|
|
9
|
-
offsetY: number;
|
|
10
|
-
};
|
|
11
|
-
command: {
|
|
12
|
-
width: number;
|
|
13
|
-
height: number;
|
|
14
|
-
offsetX: number;
|
|
15
|
-
offsetY: number;
|
|
16
|
-
};
|
|
17
|
-
event: {
|
|
18
|
-
width: number;
|
|
19
|
-
height: number;
|
|
20
|
-
offsetX: number;
|
|
21
|
-
offsetY: number;
|
|
22
|
-
};
|
|
23
|
-
};
|
|
24
|
-
export declare const AUTOMATION_SLICE: {
|
|
25
|
-
width: number;
|
|
26
|
-
height: number;
|
|
27
|
-
readModel: {
|
|
28
|
-
width: number;
|
|
29
|
-
height: number;
|
|
30
|
-
offsetX: number;
|
|
31
|
-
offsetY: number;
|
|
32
|
-
};
|
|
33
|
-
processor: {
|
|
34
|
-
width: number;
|
|
35
|
-
height: number;
|
|
36
|
-
offsetX: number;
|
|
37
|
-
offsetY: number;
|
|
38
|
-
};
|
|
39
|
-
command: {
|
|
40
|
-
width: number;
|
|
41
|
-
height: number;
|
|
42
|
-
offsetX: number;
|
|
43
|
-
offsetY: number;
|
|
44
|
-
};
|
|
45
|
-
event: {
|
|
46
|
-
width: number;
|
|
47
|
-
height: number;
|
|
48
|
-
offsetX: number;
|
|
49
|
-
offsetY: number;
|
|
50
|
-
};
|
|
51
|
-
};
|
|
52
|
-
export declare const STATE_VIEW_SLICE: {
|
|
53
|
-
width: number;
|
|
54
|
-
height: number;
|
|
55
|
-
readModel: {
|
|
56
|
-
width: number;
|
|
57
|
-
height: number;
|
|
58
|
-
offsetX: number;
|
|
59
|
-
offsetY: number;
|
|
60
|
-
};
|
|
61
|
-
};
|
|
62
|
-
export declare const SLICE_GAP = 20;
|
|
63
|
-
export interface PositionReference {
|
|
64
|
-
after?: string;
|
|
65
|
-
before?: string;
|
|
66
|
-
}
|
|
67
|
-
export declare function findSliceByName(model: EventModel, name: string): Slice | undefined;
|
|
68
|
-
export declare function validateSliceNameUnique(model: EventModel, name: string): void;
|
|
69
|
-
export declare function calculateSlicePosition(model: EventModel, sliceWidth: number, ref: PositionReference): {
|
|
70
|
-
x: number;
|
|
71
|
-
y: number;
|
|
72
|
-
};
|
|
73
|
-
export declare function getSlicesToShift(model: EventModel, insertX: number, shiftAmount: number): Array<{
|
|
74
|
-
sliceId: string;
|
|
75
|
-
newX: number;
|
|
76
|
-
currentY: number;
|
|
77
|
-
}>;
|
|
78
|
-
export declare function inferFieldMappings(sourceFields: Field[], targetFields: Field[]): FieldMapping[];
|
|
79
1
|
export interface FieldInput {
|
|
80
2
|
name: string;
|
|
81
3
|
type: string;
|
|
@@ -86,7 +8,6 @@ export interface FieldInput {
|
|
|
86
8
|
subfields?: FieldInput[];
|
|
87
9
|
}
|
|
88
10
|
export declare function parseFieldsFromXml(xml: string): FieldInput[];
|
|
89
|
-
export declare function fieldInputToField(input: FieldInput): Field;
|
|
90
11
|
export interface StateChangeSliceInput {
|
|
91
12
|
sliceName: string;
|
|
92
13
|
after?: string;
|
package/dist/lib/slice-utils.js
CHANGED
|
@@ -1,96 +1,4 @@
|
|
|
1
|
-
|
|
2
|
-
export const STATE_CHANGE_SLICE = {
|
|
3
|
-
width: 560,
|
|
4
|
-
height: 1000,
|
|
5
|
-
screen: { width: 180, height: 120, offsetX: 40, offsetY: 120 },
|
|
6
|
-
command: { width: 160, height: 100, offsetX: 180, offsetY: 460 },
|
|
7
|
-
event: { width: 160, height: 100, offsetX: 360, offsetY: 860 },
|
|
8
|
-
};
|
|
9
|
-
export const AUTOMATION_SLICE = {
|
|
10
|
-
width: 880,
|
|
11
|
-
height: 1000,
|
|
12
|
-
readModel: { width: 160, height: 100, offsetX: 40, offsetY: 460 },
|
|
13
|
-
processor: { width: 120, height: 120, offsetX: 280, offsetY: 120 },
|
|
14
|
-
command: { width: 160, height: 100, offsetX: 440, offsetY: 460 },
|
|
15
|
-
event: { width: 160, height: 100, offsetX: 680, offsetY: 860 },
|
|
16
|
-
};
|
|
17
|
-
export const STATE_VIEW_SLICE = {
|
|
18
|
-
width: 380,
|
|
19
|
-
height: 1000,
|
|
20
|
-
readModel: { width: 160, height: 100, offsetX: 110, offsetY: 460 },
|
|
21
|
-
};
|
|
22
|
-
export const SLICE_GAP = 20;
|
|
23
|
-
export function findSliceByName(model, name) {
|
|
24
|
-
const nameLower = name.toLowerCase();
|
|
25
|
-
return [...model.slices.values()].find(s => s.name.toLowerCase() === nameLower || s.name.toLowerCase().includes(nameLower));
|
|
26
|
-
}
|
|
27
|
-
export function validateSliceNameUnique(model, name) {
|
|
28
|
-
const existing = findSliceByName(model, name);
|
|
29
|
-
if (existing && existing.name.toLowerCase() === name.toLowerCase()) {
|
|
30
|
-
throw new Error(`Slice "${name}" already exists`);
|
|
31
|
-
}
|
|
32
|
-
}
|
|
33
|
-
export function calculateSlicePosition(model, sliceWidth, ref) {
|
|
34
|
-
const slices = [...model.slices.values()];
|
|
35
|
-
if (slices.length === 0) {
|
|
36
|
-
return { x: 0, y: 0 };
|
|
37
|
-
}
|
|
38
|
-
if (ref.after) {
|
|
39
|
-
const refSlice = findSliceByName(model, ref.after);
|
|
40
|
-
if (!refSlice) {
|
|
41
|
-
const available = slices.map(s => s.name).join(', ');
|
|
42
|
-
throw new Error(`Slice "${ref.after}" not found. Available: ${available}`);
|
|
43
|
-
}
|
|
44
|
-
return {
|
|
45
|
-
x: refSlice.position.x + refSlice.size.width + SLICE_GAP,
|
|
46
|
-
y: refSlice.position.y
|
|
47
|
-
};
|
|
48
|
-
}
|
|
49
|
-
if (ref.before) {
|
|
50
|
-
const refSlice = findSliceByName(model, ref.before);
|
|
51
|
-
if (!refSlice) {
|
|
52
|
-
const available = slices.map(s => s.name).join(', ');
|
|
53
|
-
throw new Error(`Slice "${ref.before}" not found. Available: ${available}`);
|
|
54
|
-
}
|
|
55
|
-
return {
|
|
56
|
-
x: refSlice.position.x,
|
|
57
|
-
y: refSlice.position.y
|
|
58
|
-
};
|
|
59
|
-
}
|
|
60
|
-
// Default: append to end (right of rightmost slice)
|
|
61
|
-
const rightmost = slices.reduce((max, s) => Math.max(max, s.position.x + s.size.width), 0);
|
|
62
|
-
const avgY = slices.reduce((sum, s) => sum + s.position.y, 0) / slices.length;
|
|
63
|
-
return {
|
|
64
|
-
x: rightmost + SLICE_GAP,
|
|
65
|
-
y: avgY
|
|
66
|
-
};
|
|
67
|
-
}
|
|
68
|
-
export function getSlicesToShift(model, insertX, shiftAmount) {
|
|
69
|
-
return [...model.slices.values()]
|
|
70
|
-
.filter(s => s.position.x >= insertX)
|
|
71
|
-
.map(s => ({
|
|
72
|
-
sliceId: s.id,
|
|
73
|
-
newX: s.position.x + shiftAmount,
|
|
74
|
-
currentY: s.position.y
|
|
75
|
-
}));
|
|
76
|
-
}
|
|
77
|
-
export function inferFieldMappings(sourceFields, targetFields) {
|
|
78
|
-
const mappings = [];
|
|
79
|
-
for (const targetField of targetFields) {
|
|
80
|
-
// Skip generated fields - they have no source
|
|
81
|
-
if (targetField.isGenerated)
|
|
82
|
-
continue;
|
|
83
|
-
// Find source field with matching name (case-insensitive)
|
|
84
|
-
const sourceField = sourceFields.find(sf => sf.name.toLowerCase() === targetField.name.toLowerCase());
|
|
85
|
-
if (sourceField) {
|
|
86
|
-
mappings.push({
|
|
87
|
-
sourceFieldId: sourceField.id,
|
|
88
|
-
targetFieldId: targetField.id
|
|
89
|
-
});
|
|
90
|
-
}
|
|
91
|
-
}
|
|
92
|
-
return mappings;
|
|
93
|
-
}
|
|
1
|
+
import { XMLParser } from 'fast-xml-parser';
|
|
94
2
|
const VALID_FIELD_TYPES = ['UUID', 'Boolean', 'Double', 'Decimal', 'Date', 'DateTime', 'Long', 'Int', 'String', 'Custom'];
|
|
95
3
|
function validateFieldType(type, fieldName) {
|
|
96
4
|
if (!VALID_FIELD_TYPES.includes(type)) {
|
|
@@ -102,189 +10,131 @@ function validateFieldType(type, fieldName) {
|
|
|
102
10
|
throw new Error(`Invalid field type "${type}" for field "${fieldName}". Valid types: ${VALID_FIELD_TYPES.join(', ')}${hint}`);
|
|
103
11
|
}
|
|
104
12
|
}
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
13
|
+
const xmlParser = new XMLParser({
|
|
14
|
+
ignoreAttributes: false,
|
|
15
|
+
attributeNamePrefix: '@_',
|
|
16
|
+
allowBooleanAttributes: false,
|
|
17
|
+
parseAttributeValue: false,
|
|
18
|
+
isArray: (name) => name === 'field',
|
|
19
|
+
});
|
|
20
|
+
function asArray(value) {
|
|
21
|
+
if (value === undefined || value === null)
|
|
22
|
+
return [];
|
|
23
|
+
return Array.isArray(value) ? value : [value];
|
|
108
24
|
}
|
|
109
|
-
|
|
25
|
+
function parseFieldNodes(nodes) {
|
|
110
26
|
const fields = [];
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
const
|
|
115
|
-
const content = match[2];
|
|
116
|
-
const name = getAttr(attrs, 'name');
|
|
117
|
-
const type = getAttr(attrs, 'type');
|
|
27
|
+
for (const node of nodes) {
|
|
28
|
+
const n = node;
|
|
29
|
+
const name = n['@_name'];
|
|
30
|
+
const type = n['@_type'];
|
|
118
31
|
if (!name || !type)
|
|
119
32
|
continue;
|
|
120
|
-
// Validate the field type
|
|
121
33
|
validateFieldType(type, name);
|
|
122
34
|
const field = {
|
|
123
35
|
name,
|
|
124
36
|
type,
|
|
125
|
-
isList:
|
|
126
|
-
isGenerated:
|
|
127
|
-
isOptional:
|
|
128
|
-
isUserInput:
|
|
37
|
+
isList: n['@_isList'] === 'true',
|
|
38
|
+
isGenerated: n['@_isGenerated'] === 'true',
|
|
39
|
+
isOptional: n['@_isOptional'] === 'true',
|
|
40
|
+
isUserInput: n['@_isUserInput'] === 'true',
|
|
129
41
|
};
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
42
|
+
if (type === 'Custom') {
|
|
43
|
+
const childFields = asArray(n['field']);
|
|
44
|
+
if (childFields.length > 0) {
|
|
45
|
+
field.subfields = parseFieldNodes(childFields);
|
|
46
|
+
}
|
|
133
47
|
}
|
|
134
48
|
fields.push(field);
|
|
135
49
|
}
|
|
136
50
|
return fields;
|
|
137
51
|
}
|
|
138
|
-
export function
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
isOptional: input.isOptional,
|
|
146
|
-
isUserInput: input.isUserInput,
|
|
147
|
-
subfields: input.subfields?.map(fieldInputToField),
|
|
148
|
-
};
|
|
52
|
+
export function parseFieldsFromXml(xml) {
|
|
53
|
+
const wrapper = `<root>${xml}</root>`;
|
|
54
|
+
const parsed = xmlParser.parse(wrapper);
|
|
55
|
+
const root = parsed['root'];
|
|
56
|
+
if (!root)
|
|
57
|
+
return [];
|
|
58
|
+
return parseFieldNodes(asArray(root['field']));
|
|
149
59
|
}
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
throw new Error('Invalid XML: missing <state-change-slice> tag');
|
|
60
|
+
function requireAttr(node, attr, tagName) {
|
|
61
|
+
const value = node[`@_${attr}`];
|
|
62
|
+
if (!value) {
|
|
63
|
+
throw new Error(`Invalid XML: ${tagName} must have a ${attr} attribute`);
|
|
155
64
|
}
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
}
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
throw new Error('Invalid XML: missing <screen> element');
|
|
166
|
-
}
|
|
167
|
-
const screenName = getAttr(screenMatch[1], 'name');
|
|
168
|
-
if (!screenName) {
|
|
169
|
-
throw new Error('Invalid XML: screen must have a name attribute');
|
|
170
|
-
}
|
|
171
|
-
const screenFields = parseFieldsFromXml(screenMatch[2]);
|
|
172
|
-
// Parse command
|
|
173
|
-
const commandMatch = xml.match(/<command([^>]*)>([\s\S]*?)<\/command>/);
|
|
174
|
-
if (!commandMatch) {
|
|
175
|
-
throw new Error('Invalid XML: missing <command> element');
|
|
176
|
-
}
|
|
177
|
-
const commandName = getAttr(commandMatch[1], 'name');
|
|
178
|
-
if (!commandName) {
|
|
179
|
-
throw new Error('Invalid XML: command must have a name attribute');
|
|
180
|
-
}
|
|
181
|
-
const commandFields = parseFieldsFromXml(commandMatch[2]);
|
|
182
|
-
// Parse event
|
|
183
|
-
const eventMatch = xml.match(/<event([^>]*)>([\s\S]*?)<\/event>/);
|
|
184
|
-
if (!eventMatch) {
|
|
185
|
-
throw new Error('Invalid XML: missing <event> element');
|
|
65
|
+
return value;
|
|
66
|
+
}
|
|
67
|
+
function optAttr(node, attr) {
|
|
68
|
+
return node[`@_${attr}`];
|
|
69
|
+
}
|
|
70
|
+
function getElement(parent, tag) {
|
|
71
|
+
const el = parent[tag];
|
|
72
|
+
if (!el) {
|
|
73
|
+
throw new Error(`Invalid XML: missing <${tag}> element`);
|
|
186
74
|
}
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
75
|
+
return el;
|
|
76
|
+
}
|
|
77
|
+
function extractFields(node) {
|
|
78
|
+
return parseFieldNodes(asArray(node['field']));
|
|
79
|
+
}
|
|
80
|
+
export function parseStateChangeSliceXml(xml) {
|
|
81
|
+
const parsed = xmlParser.parse(xml);
|
|
82
|
+
const slice = parsed['state-change-slice'];
|
|
83
|
+
if (!slice) {
|
|
84
|
+
throw new Error('Invalid XML: missing <state-change-slice> tag');
|
|
190
85
|
}
|
|
191
|
-
const
|
|
86
|
+
const sliceName = requireAttr(slice, 'name', 'state-change-slice');
|
|
87
|
+
const after = optAttr(slice, 'after');
|
|
88
|
+
const before = optAttr(slice, 'before');
|
|
89
|
+
const screen = getElement(slice, 'screen');
|
|
90
|
+
const command = getElement(slice, 'command');
|
|
91
|
+
const event = getElement(slice, 'event');
|
|
192
92
|
return {
|
|
193
93
|
sliceName,
|
|
194
94
|
after,
|
|
195
95
|
before,
|
|
196
|
-
screen: { name:
|
|
197
|
-
command: { name:
|
|
198
|
-
event: { name:
|
|
96
|
+
screen: { name: requireAttr(screen, 'name', 'screen'), fields: extractFields(screen) },
|
|
97
|
+
command: { name: requireAttr(command, 'name', 'command'), fields: extractFields(command) },
|
|
98
|
+
event: { name: requireAttr(event, 'name', 'event'), fields: extractFields(event) },
|
|
199
99
|
};
|
|
200
100
|
}
|
|
201
101
|
export function parseAutomationSliceXml(xml) {
|
|
202
|
-
|
|
203
|
-
const
|
|
204
|
-
if (!
|
|
102
|
+
const parsed = xmlParser.parse(xml);
|
|
103
|
+
const slice = parsed['automation-slice'];
|
|
104
|
+
if (!slice) {
|
|
205
105
|
throw new Error('Invalid XML: missing <automation-slice> tag');
|
|
206
106
|
}
|
|
207
|
-
const sliceName =
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
const
|
|
212
|
-
const
|
|
213
|
-
|
|
214
|
-
const readModelMatch = xml.match(/<read-model([^>]*)>([\s\S]*?)<\/read-model>/);
|
|
215
|
-
if (!readModelMatch) {
|
|
216
|
-
throw new Error('Invalid XML: missing <read-model> element');
|
|
217
|
-
}
|
|
218
|
-
const readModelName = getAttr(readModelMatch[1], 'name');
|
|
219
|
-
if (!readModelName) {
|
|
220
|
-
throw new Error('Invalid XML: read-model must have a name attribute');
|
|
221
|
-
}
|
|
222
|
-
const readModelFields = parseFieldsFromXml(readModelMatch[2]);
|
|
223
|
-
// Parse processor (fields are not supported for processor in this slice type)
|
|
224
|
-
const processorMatch = xml.match(/<processor([^>]*?)(?:\/>|>([\s\S]*?)<\/processor>)/);
|
|
225
|
-
if (!processorMatch) {
|
|
226
|
-
throw new Error('Invalid XML: missing <processor> element');
|
|
227
|
-
}
|
|
228
|
-
const processorName = getAttr(processorMatch[1], 'name');
|
|
229
|
-
if (!processorName) {
|
|
230
|
-
throw new Error('Invalid XML: processor must have a name attribute');
|
|
231
|
-
}
|
|
232
|
-
// Parse command
|
|
233
|
-
const commandMatch = xml.match(/<command([^>]*)>([\s\S]*?)<\/command>/);
|
|
234
|
-
if (!commandMatch) {
|
|
235
|
-
throw new Error('Invalid XML: missing <command> element');
|
|
236
|
-
}
|
|
237
|
-
const commandName = getAttr(commandMatch[1], 'name');
|
|
238
|
-
if (!commandName) {
|
|
239
|
-
throw new Error('Invalid XML: command must have a name attribute');
|
|
240
|
-
}
|
|
241
|
-
const commandFields = parseFieldsFromXml(commandMatch[2]);
|
|
242
|
-
// Parse event
|
|
243
|
-
const eventMatch = xml.match(/<event([^>]*)>([\s\S]*?)<\/event>/);
|
|
244
|
-
if (!eventMatch) {
|
|
245
|
-
throw new Error('Invalid XML: missing <event> element');
|
|
246
|
-
}
|
|
247
|
-
const eventName = getAttr(eventMatch[1], 'name');
|
|
248
|
-
if (!eventName) {
|
|
249
|
-
throw new Error('Invalid XML: event must have a name attribute');
|
|
250
|
-
}
|
|
251
|
-
const eventFields = parseFieldsFromXml(eventMatch[2]);
|
|
107
|
+
const sliceName = requireAttr(slice, 'name', 'automation-slice');
|
|
108
|
+
const after = optAttr(slice, 'after');
|
|
109
|
+
const before = optAttr(slice, 'before');
|
|
110
|
+
const readModel = getElement(slice, 'read-model');
|
|
111
|
+
const processor = getElement(slice, 'processor');
|
|
112
|
+
const command = getElement(slice, 'command');
|
|
113
|
+
const event = getElement(slice, 'event');
|
|
252
114
|
return {
|
|
253
115
|
sliceName,
|
|
254
116
|
after,
|
|
255
117
|
before,
|
|
256
|
-
readModel: { name:
|
|
257
|
-
processor: { name:
|
|
258
|
-
command: { name:
|
|
259
|
-
event: { name:
|
|
118
|
+
readModel: { name: requireAttr(readModel, 'name', 'read-model'), fields: extractFields(readModel) },
|
|
119
|
+
processor: { name: requireAttr(processor, 'name', 'processor') },
|
|
120
|
+
command: { name: requireAttr(command, 'name', 'command'), fields: extractFields(command) },
|
|
121
|
+
event: { name: requireAttr(event, 'name', 'event'), fields: extractFields(event) },
|
|
260
122
|
};
|
|
261
123
|
}
|
|
262
124
|
export function parseStateViewSliceXml(xml) {
|
|
263
|
-
|
|
264
|
-
const
|
|
265
|
-
if (!
|
|
125
|
+
const parsed = xmlParser.parse(xml);
|
|
126
|
+
const slice = parsed['state-view-slice'];
|
|
127
|
+
if (!slice) {
|
|
266
128
|
throw new Error('Invalid XML: missing <state-view-slice> tag');
|
|
267
129
|
}
|
|
268
|
-
const sliceName =
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
const after = getAttr(sliceMatch[1], 'after');
|
|
273
|
-
const before = getAttr(sliceMatch[1], 'before');
|
|
274
|
-
// Parse read-model
|
|
275
|
-
const readModelMatch = xml.match(/<read-model([^>]*)>([\s\S]*?)<\/read-model>/);
|
|
276
|
-
if (!readModelMatch) {
|
|
277
|
-
throw new Error('Invalid XML: missing <read-model> element');
|
|
278
|
-
}
|
|
279
|
-
const readModelName = getAttr(readModelMatch[1], 'name');
|
|
280
|
-
if (!readModelName) {
|
|
281
|
-
throw new Error('Invalid XML: read-model must have a name attribute');
|
|
282
|
-
}
|
|
283
|
-
const readModelFields = parseFieldsFromXml(readModelMatch[2]);
|
|
130
|
+
const sliceName = requireAttr(slice, 'name', 'state-view-slice');
|
|
131
|
+
const after = optAttr(slice, 'after');
|
|
132
|
+
const before = optAttr(slice, 'before');
|
|
133
|
+
const readModel = getElement(slice, 'read-model');
|
|
284
134
|
return {
|
|
285
135
|
sliceName,
|
|
286
136
|
after,
|
|
287
137
|
before,
|
|
288
|
-
readModel: { name:
|
|
138
|
+
readModel: { name: requireAttr(readModel, 'name', 'read-model'), fields: extractFields(readModel) },
|
|
289
139
|
};
|
|
290
140
|
}
|
package/dist/projection.js
CHANGED
|
@@ -450,16 +450,6 @@ function applyEvent(model, event) {
|
|
|
450
450
|
nodeIds: [],
|
|
451
451
|
});
|
|
452
452
|
break;
|
|
453
|
-
case 'NodesGroupedIntoSlice':
|
|
454
|
-
model.slices.set(d.sliceId, {
|
|
455
|
-
id: d.sliceId,
|
|
456
|
-
name: d.name,
|
|
457
|
-
status: 'created',
|
|
458
|
-
position: d.position,
|
|
459
|
-
size: d.size,
|
|
460
|
-
nodeIds: d.nodeIds,
|
|
461
|
-
});
|
|
462
|
-
break;
|
|
463
453
|
case 'SliceMoved': {
|
|
464
454
|
const slice = model.slices.get(d.sliceId);
|
|
465
455
|
if (slice)
|
|
@@ -540,17 +530,6 @@ function applyEvent(model, event) {
|
|
|
540
530
|
aggregateIdFieldType: d.aggregateIdFieldType,
|
|
541
531
|
});
|
|
542
532
|
break;
|
|
543
|
-
case 'EventsGroupedIntoAggregate':
|
|
544
|
-
model.aggregates.set(d.aggregateId, {
|
|
545
|
-
id: d.aggregateId,
|
|
546
|
-
name: d.name,
|
|
547
|
-
position: d.position,
|
|
548
|
-
size: d.size,
|
|
549
|
-
eventIds: d.eventIds,
|
|
550
|
-
aggregateIdFieldName: d.aggregateIdFieldName,
|
|
551
|
-
aggregateIdFieldType: d.aggregateIdFieldType,
|
|
552
|
-
});
|
|
553
|
-
break;
|
|
554
533
|
case 'AggregateMoved': {
|
|
555
534
|
const aggregate = model.aggregates.get(d.aggregateId);
|
|
556
535
|
if (aggregate)
|
|
@@ -592,15 +571,6 @@ function applyEvent(model, event) {
|
|
|
592
571
|
screenIds: [],
|
|
593
572
|
});
|
|
594
573
|
break;
|
|
595
|
-
case 'ScreensGroupedIntoActor':
|
|
596
|
-
model.actors.set(d.actorId, {
|
|
597
|
-
id: d.actorId,
|
|
598
|
-
name: d.name,
|
|
599
|
-
position: d.position,
|
|
600
|
-
size: d.size,
|
|
601
|
-
screenIds: d.screenIds,
|
|
602
|
-
});
|
|
603
|
-
break;
|
|
604
574
|
case 'ActorMoved': {
|
|
605
575
|
const actor = model.actors.get(d.actorId);
|
|
606
576
|
if (actor)
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import type { EventModel } from '../../types.js';
|
|
2
1
|
export interface ScenarioInput {
|
|
3
2
|
name: string;
|
|
4
3
|
description?: string;
|
|
@@ -25,5 +24,4 @@ interface EventInput {
|
|
|
25
24
|
fieldValues?: Record<string, unknown>;
|
|
26
25
|
}
|
|
27
26
|
export declare function parseScenarioInput(input: string): ScenarioInput;
|
|
28
|
-
export declare function addScenario(model: EventModel, filePath: string, sliceName: string, input: string): void;
|
|
29
27
|
export {};
|