eventmodeler 0.4.0 → 0.4.2
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/cloud/slices/index.d.ts +269 -0
- package/dist/cloud/slices/index.js +348 -0
- package/dist/index.js +1017 -45
- package/dist/lib/auth.d.ts +24 -0
- package/dist/lib/auth.js +331 -0
- package/dist/lib/backend.d.ts +43 -0
- package/dist/lib/backend.js +73 -0
- package/dist/lib/cloud-client.d.ts +69 -0
- package/dist/lib/cloud-client.js +297 -0
- package/dist/lib/config.d.ts +27 -0
- package/dist/lib/config.js +80 -11
- package/dist/lib/diff/three-way-merge.js +4 -4
- package/dist/lib/file-loader.js +43 -12
- package/dist/lib/project-config.d.ts +30 -0
- package/dist/lib/project-config.js +90 -0
- package/dist/lib/slice-utils.d.ts +49 -0
- package/dist/lib/slice-utils.js +141 -0
- package/dist/local/slices/index.d.ts +11 -0
- package/dist/local/slices/index.js +13 -0
- package/dist/projection.js +372 -371
- package/dist/slices/add-field/index.js +25 -15
- package/dist/slices/add-scenario/index.d.ts +27 -0
- package/dist/slices/add-scenario/index.js +317 -155
- package/dist/slices/codegen-chapter-events/index.d.ts +2 -0
- package/dist/slices/codegen-chapter-events/index.js +145 -0
- package/dist/slices/create-automation-slice/index.js +93 -65
- package/dist/slices/create-flow/index.js +24 -18
- package/dist/slices/create-state-change-slice/index.js +77 -53
- package/dist/slices/create-state-view-slice/index.js +25 -17
- package/dist/slices/import/index.d.ts +8 -0
- package/dist/slices/import/index.js +63 -0
- package/dist/slices/init/index.d.ts +4 -0
- package/dist/slices/init/index.js +133 -0
- package/dist/slices/list-processors/index.d.ts +3 -0
- package/dist/slices/list-processors/index.js +20 -0
- package/dist/slices/list-readmodels/index.d.ts +3 -0
- package/dist/slices/list-readmodels/index.js +21 -0
- package/dist/slices/list-scenarios/index.d.ts +3 -0
- package/dist/slices/list-scenarios/index.js +35 -0
- package/dist/slices/list-screens/index.d.ts +3 -0
- package/dist/slices/list-screens/index.js +47 -0
- package/dist/slices/login/index.d.ts +1 -0
- package/dist/slices/login/index.js +20 -0
- package/dist/slices/logout/index.d.ts +1 -0
- package/dist/slices/logout/index.js +14 -0
- package/dist/slices/map-fields/index.js +5 -3
- package/dist/slices/mark-slice-status/index.js +4 -2
- package/dist/slices/remove-field/index.js +25 -15
- package/dist/slices/remove-scenario/index.js +8 -4
- package/dist/slices/show-aggregate/index.d.ts +3 -0
- package/dist/slices/show-aggregate/index.js +108 -0
- package/dist/slices/show-processor/index.d.ts +3 -0
- package/dist/slices/show-processor/index.js +111 -0
- package/dist/slices/show-readmodel/index.d.ts +3 -0
- package/dist/slices/show-readmodel/index.js +158 -0
- package/dist/slices/show-scenario/index.d.ts +3 -0
- package/dist/slices/show-scenario/index.js +196 -0
- package/dist/slices/show-screen/index.d.ts +3 -0
- package/dist/slices/show-screen/index.js +139 -0
- package/dist/slices/update-field/index.js +30 -20
- package/dist/slices/whoami/index.d.ts +2 -0
- package/dist/slices/whoami/index.js +35 -0
- package/dist/types.d.ts +1 -2
- package/package.json +1 -1
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
import { escapeXml, outputJson } from '../../lib/format.js';
|
|
2
|
+
import { findElementOrExit } from '../../lib/element-lookup.js';
|
|
3
|
+
function formatFieldXml(field, indent) {
|
|
4
|
+
const attrs = [
|
|
5
|
+
`name="${escapeXml(field.name)}"`,
|
|
6
|
+
`type="${field.fieldType}"`,
|
|
7
|
+
];
|
|
8
|
+
if (field.isList)
|
|
9
|
+
attrs.push('list="true"');
|
|
10
|
+
if (field.isGenerated)
|
|
11
|
+
attrs.push('generated="true"');
|
|
12
|
+
if (field.isOptional)
|
|
13
|
+
attrs.push('optional="true"');
|
|
14
|
+
if (field.isUserInput)
|
|
15
|
+
attrs.push('user-input="true"');
|
|
16
|
+
if (field.subfields && field.subfields.length > 0) {
|
|
17
|
+
let xml = `${indent}<field ${attrs.join(' ')}>\n`;
|
|
18
|
+
for (const subfield of field.subfields) {
|
|
19
|
+
xml += formatFieldXml(subfield, indent + ' ');
|
|
20
|
+
}
|
|
21
|
+
xml += `${indent}</field>\n`;
|
|
22
|
+
return xml;
|
|
23
|
+
}
|
|
24
|
+
return `${indent}<field ${attrs.join(' ')}/>\n`;
|
|
25
|
+
}
|
|
26
|
+
function fieldToJson(field) {
|
|
27
|
+
const result = {
|
|
28
|
+
name: field.name,
|
|
29
|
+
type: field.fieldType
|
|
30
|
+
};
|
|
31
|
+
if (field.isList)
|
|
32
|
+
result.list = true;
|
|
33
|
+
if (field.isGenerated)
|
|
34
|
+
result.generated = true;
|
|
35
|
+
if (field.isOptional)
|
|
36
|
+
result.optional = true;
|
|
37
|
+
if (field.isUserInput)
|
|
38
|
+
result.userInput = true;
|
|
39
|
+
if (field.subfields && field.subfields.length > 0) {
|
|
40
|
+
result.subfields = field.subfields.map(fieldToJson);
|
|
41
|
+
}
|
|
42
|
+
return result;
|
|
43
|
+
}
|
|
44
|
+
// Find which slice contains a screen
|
|
45
|
+
function findSliceForScreen(model, screen) {
|
|
46
|
+
for (const slice of model.slices.values()) {
|
|
47
|
+
const centerX = screen.position.x + screen.width / 2;
|
|
48
|
+
const centerY = screen.position.y + screen.height / 2;
|
|
49
|
+
if (centerX >= slice.position.x &&
|
|
50
|
+
centerX <= slice.position.x + slice.size.width &&
|
|
51
|
+
centerY >= slice.position.y &&
|
|
52
|
+
centerY <= slice.position.y + slice.size.height) {
|
|
53
|
+
return slice.name;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
return null;
|
|
57
|
+
}
|
|
58
|
+
// Find which actor contains a screen
|
|
59
|
+
function findActorForScreen(model, screen) {
|
|
60
|
+
const centerX = screen.position.x + screen.width / 2;
|
|
61
|
+
const centerY = screen.position.y + screen.height / 2;
|
|
62
|
+
for (const actor of model.actors.values()) {
|
|
63
|
+
const bounds = {
|
|
64
|
+
left: actor.position.x,
|
|
65
|
+
right: actor.position.x + actor.size.width,
|
|
66
|
+
top: actor.position.y,
|
|
67
|
+
bottom: actor.position.y + actor.size.height,
|
|
68
|
+
};
|
|
69
|
+
if (centerX >= bounds.left && centerX <= bounds.right &&
|
|
70
|
+
centerY >= bounds.top && centerY <= bounds.bottom) {
|
|
71
|
+
return actor;
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
return null;
|
|
75
|
+
}
|
|
76
|
+
export function showScreen(model, name, format) {
|
|
77
|
+
// Filter out linked copies
|
|
78
|
+
const originalScreens = new Map([...model.screens.entries()].filter(([_, s]) => !s.originalNodeId));
|
|
79
|
+
const screen = findElementOrExit(originalScreens, name, 'screen');
|
|
80
|
+
const slice = findSliceForScreen(model, screen);
|
|
81
|
+
const actor = findActorForScreen(model, screen);
|
|
82
|
+
// Find incoming flows (ReadModel → Screen)
|
|
83
|
+
const incomingFlows = [...model.flows.values()].filter(f => f.flowType === 'ReadModelToScreen' && f.targetId === screen.id);
|
|
84
|
+
// Find outgoing flows (Screen → Command)
|
|
85
|
+
const outgoingFlows = [...model.flows.values()].filter(f => f.flowType === 'ScreenToCommand' && f.sourceId === screen.id);
|
|
86
|
+
if (format === 'json') {
|
|
87
|
+
const result = {
|
|
88
|
+
id: screen.id,
|
|
89
|
+
name: screen.name,
|
|
90
|
+
fields: screen.fields.map(fieldToJson)
|
|
91
|
+
};
|
|
92
|
+
if (slice)
|
|
93
|
+
result.slice = slice;
|
|
94
|
+
if (actor)
|
|
95
|
+
result.actor = actor.name;
|
|
96
|
+
if (incomingFlows.length > 0) {
|
|
97
|
+
result.displaysFrom = incomingFlows.map(flow => {
|
|
98
|
+
const rm = model.readModels.get(flow.sourceId);
|
|
99
|
+
return rm?.name ?? flow.sourceId;
|
|
100
|
+
});
|
|
101
|
+
}
|
|
102
|
+
if (outgoingFlows.length > 0) {
|
|
103
|
+
result.triggersCommands = outgoingFlows.map(flow => {
|
|
104
|
+
const cmd = model.commands.get(flow.targetId);
|
|
105
|
+
return cmd?.name ?? flow.targetId;
|
|
106
|
+
});
|
|
107
|
+
}
|
|
108
|
+
outputJson(result);
|
|
109
|
+
return;
|
|
110
|
+
}
|
|
111
|
+
// XML output
|
|
112
|
+
const sliceAttr = slice ? ` slice="${escapeXml(slice)}"` : '';
|
|
113
|
+
const actorAttr = actor ? ` actor="${escapeXml(actor.name)}"` : '';
|
|
114
|
+
console.log(`<screen id="${screen.id}" name="${escapeXml(screen.name)}"${sliceAttr}${actorAttr}>`);
|
|
115
|
+
if (screen.fields.length > 0) {
|
|
116
|
+
console.log(' <fields>');
|
|
117
|
+
for (const field of screen.fields) {
|
|
118
|
+
process.stdout.write(formatFieldXml(field, ' '));
|
|
119
|
+
}
|
|
120
|
+
console.log(' </fields>');
|
|
121
|
+
}
|
|
122
|
+
if (incomingFlows.length > 0) {
|
|
123
|
+
console.log(' <displays-from>');
|
|
124
|
+
for (const flow of incomingFlows) {
|
|
125
|
+
const rm = model.readModels.get(flow.sourceId);
|
|
126
|
+
console.log(` <read-model name="${escapeXml(rm?.name ?? flow.sourceId)}"/>`);
|
|
127
|
+
}
|
|
128
|
+
console.log(' </displays-from>');
|
|
129
|
+
}
|
|
130
|
+
if (outgoingFlows.length > 0) {
|
|
131
|
+
console.log(' <triggers-commands>');
|
|
132
|
+
for (const flow of outgoingFlows) {
|
|
133
|
+
const cmd = model.commands.get(flow.targetId);
|
|
134
|
+
console.log(` <command name="${escapeXml(cmd?.name ?? flow.targetId)}"/>`);
|
|
135
|
+
}
|
|
136
|
+
console.log(' </triggers-commands>');
|
|
137
|
+
}
|
|
138
|
+
console.log('</screen>');
|
|
139
|
+
}
|
|
@@ -75,10 +75,12 @@ function updateCommandField(model, filePath, commandName, fieldName, updates) {
|
|
|
75
75
|
const updatedField = createUpdatedField(field, updates);
|
|
76
76
|
appendEvent(filePath, {
|
|
77
77
|
type: 'CommandFieldAdjusted',
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
78
|
+
data: {
|
|
79
|
+
commandStickyId: command.id,
|
|
80
|
+
fieldId: field.id,
|
|
81
|
+
field: updatedField,
|
|
82
|
+
timestamp: Date.now(),
|
|
83
|
+
},
|
|
82
84
|
});
|
|
83
85
|
console.log(`Updated field "${field.name}" on command "${command.name}"`);
|
|
84
86
|
logUpdates(updates);
|
|
@@ -100,10 +102,12 @@ function updateEventField(model, filePath, eventName, fieldName, updates) {
|
|
|
100
102
|
const updatedField = createUpdatedField(field, updates);
|
|
101
103
|
appendEvent(filePath, {
|
|
102
104
|
type: 'EventFieldAdjusted',
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
105
|
+
data: {
|
|
106
|
+
eventStickyId: event.id,
|
|
107
|
+
fieldId: field.id,
|
|
108
|
+
field: updatedField,
|
|
109
|
+
timestamp: Date.now(),
|
|
110
|
+
},
|
|
107
111
|
});
|
|
108
112
|
console.log(`Updated field "${field.name}" on event "${event.name}"`);
|
|
109
113
|
logUpdates(updates);
|
|
@@ -125,10 +129,12 @@ function updateReadModelField(model, filePath, readModelName, fieldName, updates
|
|
|
125
129
|
const updatedField = createUpdatedField(field, updates);
|
|
126
130
|
appendEvent(filePath, {
|
|
127
131
|
type: 'ReadModelFieldAdjusted',
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
+
data: {
|
|
133
|
+
readModelStickyId: readModel.id,
|
|
134
|
+
fieldId: field.id,
|
|
135
|
+
field: updatedField,
|
|
136
|
+
timestamp: Date.now(),
|
|
137
|
+
},
|
|
132
138
|
});
|
|
133
139
|
console.log(`Updated field "${field.name}" on read model "${readModel.name}"`);
|
|
134
140
|
logUpdates(updates);
|
|
@@ -150,10 +156,12 @@ function updateScreenField(model, filePath, screenName, fieldName, updates) {
|
|
|
150
156
|
const updatedField = createUpdatedField(field, updates);
|
|
151
157
|
appendEvent(filePath, {
|
|
152
158
|
type: 'ScreenFieldAdjusted',
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
159
|
+
data: {
|
|
160
|
+
screenId: screen.id,
|
|
161
|
+
fieldId: field.id,
|
|
162
|
+
field: updatedField,
|
|
163
|
+
timestamp: Date.now(),
|
|
164
|
+
},
|
|
157
165
|
});
|
|
158
166
|
console.log(`Updated field "${field.name}" on screen "${screen.name}"`);
|
|
159
167
|
logUpdates(updates);
|
|
@@ -174,10 +182,12 @@ function updateProcessorField(model, filePath, processorName, fieldName, updates
|
|
|
174
182
|
const updatedField = createUpdatedField(field, updates);
|
|
175
183
|
appendEvent(filePath, {
|
|
176
184
|
type: 'ProcessorFieldAdjusted',
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
185
|
+
data: {
|
|
186
|
+
processorId: processor.id,
|
|
187
|
+
fieldId: field.id,
|
|
188
|
+
field: updatedField,
|
|
189
|
+
timestamp: Date.now(),
|
|
190
|
+
},
|
|
181
191
|
});
|
|
182
192
|
console.log(`Updated field "${field.name}" on processor "${processor.name}"`);
|
|
183
193
|
logUpdates(updates);
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { isAuthenticated, getAuthTokens, getBackendUrl, getKeycloakUrl } from '../../lib/config.js';
|
|
2
|
+
import { outputJson, escapeXml } from '../../lib/format.js';
|
|
3
|
+
export function whoami(format) {
|
|
4
|
+
const tokens = getAuthTokens();
|
|
5
|
+
const backendUrl = getBackendUrl();
|
|
6
|
+
const keycloakUrl = getKeycloakUrl();
|
|
7
|
+
if (!tokens) {
|
|
8
|
+
if (format === 'json') {
|
|
9
|
+
outputJson({ authenticated: false, backendUrl, keycloakUrl });
|
|
10
|
+
}
|
|
11
|
+
else {
|
|
12
|
+
console.log(`<auth authenticated="false" backendUrl="${escapeXml(backendUrl)}" keycloakUrl="${escapeXml(keycloakUrl)}"/>`);
|
|
13
|
+
}
|
|
14
|
+
return;
|
|
15
|
+
}
|
|
16
|
+
const isValid = isAuthenticated();
|
|
17
|
+
if (format === 'json') {
|
|
18
|
+
outputJson({
|
|
19
|
+
authenticated: isValid,
|
|
20
|
+
email: tokens.email,
|
|
21
|
+
userId: tokens.userId,
|
|
22
|
+
backendUrl,
|
|
23
|
+
keycloakUrl,
|
|
24
|
+
expiresAt: new Date(tokens.expiresAt).toISOString(),
|
|
25
|
+
});
|
|
26
|
+
}
|
|
27
|
+
else {
|
|
28
|
+
if (isValid) {
|
|
29
|
+
console.log(`<auth authenticated="true" email="${escapeXml(tokens.email)}" backendUrl="${escapeXml(backendUrl)}"/>`);
|
|
30
|
+
}
|
|
31
|
+
else {
|
|
32
|
+
console.log(`<auth authenticated="false" email="${escapeXml(tokens.email)}" backendUrl="${escapeXml(backendUrl)}" reason="token_expired"/>`);
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
}
|
package/dist/types.d.ts
CHANGED