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
package/dist/index.js
CHANGED
|
@@ -2,2388 +2,55 @@
|
|
|
2
2
|
import * as fs from 'node:fs';
|
|
3
3
|
import * as path from 'node:path';
|
|
4
4
|
import { fileURLToPath } from 'node:url';
|
|
5
|
-
import {
|
|
5
|
+
import { Command } from 'commander';
|
|
6
6
|
const __filename = fileURLToPath(import.meta.url);
|
|
7
7
|
const __dirname = path.dirname(__filename);
|
|
8
8
|
const packageJson = JSON.parse(fs.readFileSync(path.join(__dirname, '..', 'package.json'), 'utf-8'));
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
import {
|
|
12
|
-
import {
|
|
13
|
-
import {
|
|
14
|
-
import {
|
|
15
|
-
import {
|
|
16
|
-
import {
|
|
17
|
-
import {
|
|
18
|
-
import
|
|
19
|
-
import {
|
|
20
|
-
import {
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
logout Sign out
|
|
55
|
-
whoami Show authentication status
|
|
56
|
-
|
|
57
|
-
PROJECT SETUP:
|
|
58
|
-
init Initialize project (link to a model)
|
|
59
|
-
|
|
60
|
-
COMMANDS:
|
|
61
|
-
list slices [--chapter <name>] List all slices (optionally filtered by chapter)
|
|
62
|
-
list events List all events
|
|
63
|
-
list commands List all commands
|
|
64
|
-
list chapters List all chapters
|
|
65
|
-
list aggregates List all aggregates
|
|
66
|
-
list actors List all actors
|
|
67
|
-
list readmodels List all read models
|
|
68
|
-
list screens List all screens
|
|
69
|
-
list processors List all processors
|
|
70
|
-
list scenarios List all scenarios
|
|
71
|
-
|
|
72
|
-
show slice <name> Show slice with components, flow annotations, and
|
|
73
|
-
inbound/outbound dependencies
|
|
74
|
-
show event <name> Show detailed XML view of an event
|
|
75
|
-
show command <name> Show detailed XML view of a command
|
|
76
|
-
show chapter <name> Show chapter with slices, flow graph, and
|
|
77
|
-
external dependencies
|
|
78
|
-
show information-completeness Show information completeness of all flows
|
|
79
|
-
show information-completeness <name>
|
|
80
|
-
Show field mapping completeness for an element
|
|
81
|
-
show aggregate-completeness <name>
|
|
82
|
-
Show if events in aggregate have the ID field
|
|
83
|
-
show actor <name> Show actor with its screens
|
|
84
|
-
show readmodel <name> Show read model with fields and flows
|
|
85
|
-
show screen <name> Show screen with fields and connections
|
|
86
|
-
show processor <name> Show processor with subscriptions and commands
|
|
87
|
-
show aggregate <name> Show aggregate with events and ID field status
|
|
88
|
-
show scenario <name> Show scenario with Given-When-Then details
|
|
89
|
-
|
|
90
|
-
search <term> Search for entities by name
|
|
91
|
-
|
|
92
|
-
mark <slice-name> <status> Mark a slice's status
|
|
93
|
-
Status: created | in-progress | blocked | done
|
|
94
|
-
|
|
95
|
-
add scenario --slice <name> --json|--xml <data>
|
|
96
|
-
Add a scenario to a slice
|
|
97
|
-
add field <element-name> --json|--xml <data>
|
|
98
|
-
Add a field to an entity
|
|
99
|
-
|
|
100
|
-
remove scenario <name> [--slice <name>]
|
|
101
|
-
Remove a scenario by name
|
|
102
|
-
remove field <element-name> --field <name>
|
|
103
|
-
Remove a field from an entity
|
|
104
|
-
|
|
105
|
-
map fields --flow <source→target> --json|--xml <mappings>
|
|
106
|
-
Set field mappings on a flow
|
|
107
|
-
|
|
108
|
-
update field <element-name> --field <name> [--optional true|false] [--generated true|false] [--user-input true|false]
|
|
109
|
-
Update field properties
|
|
110
|
-
|
|
111
|
-
create state-change-slice --xml <data>
|
|
112
|
-
Create a state-change slice (Screen → Command → Event)
|
|
113
|
-
create automation-slice --xml <data>
|
|
114
|
-
Create an automation slice (ReadModel → Processor → Command → Event)
|
|
115
|
-
create state-view-slice --xml <data>
|
|
116
|
-
Create a state-view slice (Read Model)
|
|
117
|
-
create flow --from <source> --to <target>
|
|
118
|
-
Create a flow between elements (Event→ReadModel, ReadModel→Screen/Processor)
|
|
119
|
-
|
|
120
|
-
codegen slice <name> Generate code-ready JSON for a slice (includes dependencies, mappings, scenarios)
|
|
121
|
-
codegen events [--chapter <name>]
|
|
122
|
-
Generate deduplicated events for a chapter or the whole model
|
|
123
|
-
|
|
124
|
-
summary Show model summary statistics
|
|
125
|
-
|
|
126
|
-
export json Export entire model as JSON
|
|
127
|
-
|
|
128
|
-
GUIDES:
|
|
129
|
-
guide List available guides for AI agents and users
|
|
130
|
-
guide <name> Read a conceptual guide (no auth required)
|
|
131
|
-
|
|
132
|
-
OPTIONS:
|
|
133
|
-
--format <xml|json> Output format (default: xml, or from config)
|
|
134
|
-
-h, --help Show this help message
|
|
135
|
-
-v, --version Show version number
|
|
136
|
-
|
|
137
|
-
CONFIGURATION:
|
|
138
|
-
Set default output format via:
|
|
139
|
-
- Environment variable: EVENTMODELER_FORMAT=json
|
|
140
|
-
- Config file: ~/.eventmodeler/config.json with {"format": "json"}
|
|
141
|
-
|
|
142
|
-
EXAMPLES:
|
|
143
|
-
eventmodeler list slices
|
|
144
|
-
eventmodeler show slice "Place Order"
|
|
145
|
-
eventmodeler mark "Place Order" done
|
|
146
|
-
eventmodeler add scenario --slice "Place Order" --json '{"name": "Happy path", "then": {"type": "events", "events": []}}'
|
|
147
|
-
eventmodeler add field "OrderPlaced" --json '{"name": "orderId", "type": "UUID"}'
|
|
148
|
-
eventmodeler remove field "OrderPlaced" --field "orderId"
|
|
149
|
-
eventmodeler show information-completeness
|
|
150
|
-
eventmodeler show information-completeness "OrderSummary"
|
|
151
|
-
eventmodeler map fields --flow "OrderPlaced→OrderSummary" --json '[{"from": "total", "to": "totalAmount"}]'
|
|
152
|
-
eventmodeler update field "OrderSummary" --field "notes" --optional true
|
|
153
|
-
`);
|
|
154
|
-
}
|
|
155
|
-
async function main() {
|
|
156
|
-
let formatArg = null;
|
|
157
|
-
let chapterArg = null;
|
|
158
|
-
const filteredArgs = [];
|
|
159
|
-
let helpRequested = false;
|
|
160
|
-
for (let i = 0; i < args.length; i++) {
|
|
161
|
-
if (args[i] === '--format') {
|
|
162
|
-
formatArg = args[++i];
|
|
163
|
-
}
|
|
164
|
-
else if (args[i] === '--chapter') {
|
|
165
|
-
chapterArg = args[++i];
|
|
166
|
-
}
|
|
167
|
-
else if (args[i] === '-v' || args[i] === '--version') {
|
|
168
|
-
console.log(`eventmodeler ${VERSION}`);
|
|
169
|
-
process.exit(0);
|
|
170
|
-
}
|
|
171
|
-
else if (args[i] === '-h' || args[i] === '--help') {
|
|
172
|
-
helpRequested = true;
|
|
173
|
-
}
|
|
174
|
-
else {
|
|
175
|
-
filteredArgs.push(args[i]);
|
|
176
|
-
}
|
|
177
|
-
}
|
|
178
|
-
// Handle --help: if no command specified, show general help
|
|
179
|
-
// Otherwise let command-specific help handle it
|
|
180
|
-
if (helpRequested && filteredArgs.length === 0) {
|
|
181
|
-
printHelp();
|
|
182
|
-
process.exit(0);
|
|
183
|
-
}
|
|
184
|
-
// Determine output format
|
|
185
|
-
const format = formatArg === 'json' ? 'json'
|
|
186
|
-
: formatArg === 'xml' ? 'xml'
|
|
187
|
-
: getDefaultFormat();
|
|
188
|
-
const command = filteredArgs[0];
|
|
189
|
-
const subcommand = filteredArgs[1];
|
|
190
|
-
// Join remaining args as target (allows "show chapter Register Products" without quotes)
|
|
191
|
-
// For commands with named args (--flag), those are already extracted by getNamedArg
|
|
192
|
-
const remainingArgs = filteredArgs.slice(2);
|
|
193
|
-
const target = remainingArgs.length > 0 ? remainingArgs.join(' ') : undefined;
|
|
194
|
-
if (!command) {
|
|
195
|
-
openApp();
|
|
196
|
-
return;
|
|
197
|
-
}
|
|
198
|
-
// Auth commands (no file needed)
|
|
199
|
-
if (command === 'login') {
|
|
200
|
-
if (helpRequested) {
|
|
201
|
-
console.log(`
|
|
202
|
-
eventmodeler login - Authenticate with eventmodeler.app
|
|
203
|
-
|
|
204
|
-
USAGE:
|
|
205
|
-
eventmodeler login
|
|
206
|
-
|
|
207
|
-
Opens your browser for authentication via Keycloak.
|
|
208
|
-
Credentials are stored securely in ~/.eventmodeler/config.json
|
|
209
|
-
|
|
210
|
-
After login, you can:
|
|
211
|
-
- Use "eventmodeler init" to connect a project to a model
|
|
212
|
-
|
|
213
|
-
EXAMPLES:
|
|
214
|
-
eventmodeler login
|
|
215
|
-
`);
|
|
216
|
-
process.exit(0);
|
|
217
|
-
}
|
|
218
|
-
await login();
|
|
219
|
-
return;
|
|
220
|
-
}
|
|
221
|
-
if (command === 'logout') {
|
|
222
|
-
if (helpRequested) {
|
|
223
|
-
console.log(`
|
|
224
|
-
eventmodeler logout - Sign out of eventmodeler.app
|
|
225
|
-
|
|
226
|
-
USAGE:
|
|
227
|
-
eventmodeler logout
|
|
228
|
-
|
|
229
|
-
Clears stored credentials from ~/.eventmodeler/config.json
|
|
230
|
-
|
|
231
|
-
EXAMPLES:
|
|
232
|
-
eventmodeler logout
|
|
233
|
-
`);
|
|
234
|
-
process.exit(0);
|
|
235
|
-
}
|
|
236
|
-
logout();
|
|
237
|
-
return;
|
|
238
|
-
}
|
|
239
|
-
if (command === 'whoami') {
|
|
240
|
-
if (helpRequested) {
|
|
241
|
-
console.log(`
|
|
242
|
-
eventmodeler whoami - Show current authentication status
|
|
243
|
-
|
|
244
|
-
USAGE:
|
|
245
|
-
eventmodeler whoami [--format xml|json]
|
|
246
|
-
|
|
247
|
-
OPTIONS:
|
|
248
|
-
--format <format> Output format: xml (default) or json
|
|
249
|
-
|
|
250
|
-
OUTPUT:
|
|
251
|
-
Shows whether you're logged in and your email address.
|
|
252
|
-
|
|
253
|
-
EXAMPLES:
|
|
254
|
-
eventmodeler whoami
|
|
255
|
-
eventmodeler whoami --format json
|
|
256
|
-
`);
|
|
257
|
-
process.exit(0);
|
|
258
|
-
}
|
|
259
|
-
whoami(format);
|
|
260
|
-
return;
|
|
261
|
-
}
|
|
262
|
-
if (command === 'init') {
|
|
263
|
-
if (helpRequested) {
|
|
264
|
-
console.log(`
|
|
265
|
-
eventmodeler init - Initialize a project
|
|
266
|
-
|
|
267
|
-
USAGE:
|
|
268
|
-
eventmodeler init
|
|
269
|
-
|
|
270
|
-
Interactive setup to connect this directory to an event model.
|
|
271
|
-
Creates a .eventmodeler.json config file in your project root.
|
|
272
|
-
|
|
273
|
-
PREREQUISITES:
|
|
274
|
-
- You must be logged in (run "eventmodeler login" first)
|
|
275
|
-
|
|
276
|
-
EXAMPLES:
|
|
277
|
-
cd my-project
|
|
278
|
-
eventmodeler init
|
|
279
|
-
`);
|
|
280
|
-
process.exit(0);
|
|
281
|
-
}
|
|
282
|
-
await init();
|
|
283
|
-
return;
|
|
284
|
-
}
|
|
285
|
-
if (command === 'guide') {
|
|
286
|
-
runGuide(subcommand);
|
|
287
|
-
return;
|
|
288
|
-
}
|
|
289
|
-
const projectConfig = loadProjectConfig();
|
|
290
|
-
if (!projectConfig || projectConfig.type !== 'cloud') {
|
|
291
|
-
console.error('Error: No project configured.');
|
|
292
|
-
console.error('Run "eventmodeler init" to connect this directory to a model.');
|
|
293
|
-
process.exit(1);
|
|
294
|
-
}
|
|
295
|
-
const modelId = projectConfig.modelId;
|
|
296
|
-
switch (command) {
|
|
297
|
-
case 'list':
|
|
298
|
-
if (helpRequested && !subcommand) {
|
|
299
|
-
console.log(`
|
|
300
|
-
eventmodeler list - List entities in the event model
|
|
301
|
-
|
|
302
|
-
USAGE:
|
|
303
|
-
eventmodeler list <type> [options]
|
|
304
|
-
|
|
305
|
-
TYPES:
|
|
306
|
-
slices List all slices (with optional --chapter filter)
|
|
307
|
-
events List all events
|
|
308
|
-
commands List all commands
|
|
309
|
-
chapters List all chapters
|
|
310
|
-
aggregates List all aggregates
|
|
311
|
-
actors List all actors
|
|
312
|
-
readmodels List all read models
|
|
313
|
-
screens List all screens
|
|
314
|
-
processors List all processors
|
|
315
|
-
|
|
316
|
-
OPTIONS:
|
|
317
|
-
--chapter <name> Filter slices by chapter (slices only)
|
|
318
|
-
--format xml|json Output format (default: xml)
|
|
319
|
-
|
|
320
|
-
EXAMPLES:
|
|
321
|
-
eventmodeler list slices
|
|
322
|
-
eventmodeler list slices --chapter "Order Management"
|
|
323
|
-
eventmodeler list events --format json
|
|
324
|
-
|
|
325
|
-
Run "eventmodeler list <type> --help" for type-specific help.
|
|
326
|
-
`);
|
|
327
|
-
process.exit(0);
|
|
328
|
-
}
|
|
329
|
-
switch (subcommand) {
|
|
330
|
-
case 'slices':
|
|
331
|
-
if (helpRequested) {
|
|
332
|
-
console.log(`
|
|
333
|
-
eventmodeler list slices - List all slices in the event model
|
|
334
|
-
|
|
335
|
-
USAGE:
|
|
336
|
-
eventmodeler list slices [--chapter <name>] [--format xml|json]
|
|
337
|
-
|
|
338
|
-
OPTIONS:
|
|
339
|
-
--chapter <name> Filter by chapter name
|
|
340
|
-
--format <format> Output format: xml (default) or json
|
|
341
|
-
|
|
342
|
-
OUTPUT FIELDS:
|
|
343
|
-
name Slice name
|
|
344
|
-
type state-change | automation | state-view
|
|
345
|
-
status created | in-progress | blocked | done
|
|
346
|
-
chapter Parent chapter name
|
|
347
|
-
|
|
348
|
-
EXAMPLES:
|
|
349
|
-
eventmodeler list slices
|
|
350
|
-
eventmodeler list slices --chapter "Order Management"
|
|
351
|
-
eventmodeler list slices --format json
|
|
352
|
-
`);
|
|
353
|
-
process.exit(0);
|
|
354
|
-
}
|
|
355
|
-
{
|
|
356
|
-
const output = await api.listSlices(modelId, format, chapterArg ?? undefined);
|
|
357
|
-
console.log(output);
|
|
358
|
-
}
|
|
359
|
-
break;
|
|
360
|
-
case 'events':
|
|
361
|
-
if (helpRequested) {
|
|
362
|
-
console.log(`
|
|
363
|
-
eventmodeler list events - List all events in the event model
|
|
364
|
-
|
|
365
|
-
USAGE:
|
|
366
|
-
eventmodeler list events [--format xml|json]
|
|
367
|
-
|
|
368
|
-
OPTIONS:
|
|
369
|
-
--format <format> Output format: xml (default) or json
|
|
370
|
-
|
|
371
|
-
OUTPUT FIELDS:
|
|
372
|
-
name Event name
|
|
373
|
-
aggregate Parent aggregate name
|
|
374
|
-
|
|
375
|
-
NOTE: Linked copies (events referencing a canonical original) are excluded.
|
|
376
|
-
|
|
377
|
-
EXAMPLES:
|
|
378
|
-
eventmodeler list events
|
|
379
|
-
eventmodeler list events --format json
|
|
380
|
-
`);
|
|
381
|
-
process.exit(0);
|
|
382
|
-
}
|
|
383
|
-
{
|
|
384
|
-
const output = await api.listEvents(modelId, format);
|
|
385
|
-
console.log(output);
|
|
386
|
-
}
|
|
387
|
-
break;
|
|
388
|
-
case 'commands':
|
|
389
|
-
if (helpRequested) {
|
|
390
|
-
console.log(`
|
|
391
|
-
eventmodeler list commands - List all commands in the event model
|
|
392
|
-
|
|
393
|
-
USAGE:
|
|
394
|
-
eventmodeler list commands [--format xml|json]
|
|
395
|
-
|
|
396
|
-
OPTIONS:
|
|
397
|
-
--format <format> Output format: xml (default) or json
|
|
398
|
-
|
|
399
|
-
OUTPUT FIELDS:
|
|
400
|
-
name Command name
|
|
401
|
-
aggregate Parent aggregate name
|
|
402
|
-
|
|
403
|
-
EXAMPLES:
|
|
404
|
-
eventmodeler list commands
|
|
405
|
-
eventmodeler list commands --format json
|
|
406
|
-
`);
|
|
407
|
-
process.exit(0);
|
|
408
|
-
}
|
|
409
|
-
{
|
|
410
|
-
const output = await api.listCommands(modelId, format);
|
|
411
|
-
console.log(output);
|
|
412
|
-
}
|
|
413
|
-
break;
|
|
414
|
-
case 'chapters':
|
|
415
|
-
if (helpRequested) {
|
|
416
|
-
console.log(`
|
|
417
|
-
eventmodeler list chapters - List all chapters in the event model
|
|
418
|
-
|
|
419
|
-
USAGE:
|
|
420
|
-
eventmodeler list chapters [--format xml|json]
|
|
421
|
-
|
|
422
|
-
OPTIONS:
|
|
423
|
-
--format <format> Output format: xml (default) or json
|
|
424
|
-
|
|
425
|
-
OUTPUT FIELDS:
|
|
426
|
-
name Chapter name
|
|
427
|
-
sliceCount Number of slices in chapter
|
|
428
|
-
|
|
429
|
-
EXAMPLES:
|
|
430
|
-
eventmodeler list chapters
|
|
431
|
-
eventmodeler list chapters --format json
|
|
432
|
-
`);
|
|
433
|
-
process.exit(0);
|
|
434
|
-
}
|
|
435
|
-
{
|
|
436
|
-
const output = await api.listChapters(modelId, format);
|
|
437
|
-
console.log(output);
|
|
438
|
-
}
|
|
439
|
-
break;
|
|
440
|
-
case 'aggregates':
|
|
441
|
-
if (helpRequested) {
|
|
442
|
-
console.log(`
|
|
443
|
-
eventmodeler list aggregates - List all aggregates in the event model
|
|
444
|
-
|
|
445
|
-
USAGE:
|
|
446
|
-
eventmodeler list aggregates [--format xml|json]
|
|
447
|
-
|
|
448
|
-
OPTIONS:
|
|
449
|
-
--format <format> Output format: xml (default) or json
|
|
450
|
-
|
|
451
|
-
OUTPUT FIELDS:
|
|
452
|
-
name Aggregate name
|
|
453
|
-
eventCount Number of events
|
|
454
|
-
commandCount Number of commands
|
|
455
|
-
|
|
456
|
-
EXAMPLES:
|
|
457
|
-
eventmodeler list aggregates
|
|
458
|
-
eventmodeler list aggregates --format json
|
|
459
|
-
`);
|
|
460
|
-
process.exit(0);
|
|
461
|
-
}
|
|
462
|
-
{
|
|
463
|
-
const result = await api.listAggregates(modelId, format);
|
|
464
|
-
console.log(result);
|
|
465
|
-
}
|
|
466
|
-
break;
|
|
467
|
-
case 'actors':
|
|
468
|
-
if (helpRequested) {
|
|
469
|
-
console.log(`
|
|
470
|
-
eventmodeler list actors - List all actors in the event model
|
|
471
|
-
|
|
472
|
-
USAGE:
|
|
473
|
-
eventmodeler list actors [--format xml|json]
|
|
474
|
-
|
|
475
|
-
OPTIONS:
|
|
476
|
-
--format <format> Output format: xml (default) or json
|
|
477
|
-
|
|
478
|
-
OUTPUT FIELDS:
|
|
479
|
-
name Actor name
|
|
480
|
-
screenCount Number of screens
|
|
481
|
-
|
|
482
|
-
EXAMPLES:
|
|
483
|
-
eventmodeler list actors
|
|
484
|
-
eventmodeler list actors --format json
|
|
485
|
-
`);
|
|
486
|
-
process.exit(0);
|
|
487
|
-
}
|
|
488
|
-
{
|
|
489
|
-
const output = await api.listActors(modelId, format);
|
|
490
|
-
console.log(output);
|
|
491
|
-
}
|
|
492
|
-
break;
|
|
493
|
-
case 'readmodels':
|
|
494
|
-
if (helpRequested) {
|
|
495
|
-
console.log(`
|
|
496
|
-
eventmodeler list readmodels - List all read models
|
|
497
|
-
|
|
498
|
-
USAGE:
|
|
499
|
-
eventmodeler list readmodels [--format xml|json]
|
|
500
|
-
|
|
501
|
-
OUTPUT:
|
|
502
|
-
Lists read models with id, name, and field count.
|
|
503
|
-
Excludes linked copies (shows only canonical read models).
|
|
504
|
-
|
|
505
|
-
EXAMPLES:
|
|
506
|
-
eventmodeler list readmodels
|
|
507
|
-
eventmodeler list readmodels --format json
|
|
508
|
-
`);
|
|
509
|
-
process.exit(0);
|
|
510
|
-
}
|
|
511
|
-
{
|
|
512
|
-
const output = await api.listReadModels(modelId, format);
|
|
513
|
-
console.log(output);
|
|
514
|
-
}
|
|
515
|
-
break;
|
|
516
|
-
case 'screens':
|
|
517
|
-
if (helpRequested) {
|
|
518
|
-
console.log(`
|
|
519
|
-
eventmodeler list screens - List all screens
|
|
520
|
-
|
|
521
|
-
USAGE:
|
|
522
|
-
eventmodeler list screens [--format xml|json]
|
|
523
|
-
|
|
524
|
-
OUTPUT:
|
|
525
|
-
Lists screens with id, name, field count, and actor (if in one).
|
|
526
|
-
Excludes linked copies (shows only canonical screens).
|
|
527
|
-
|
|
528
|
-
EXAMPLES:
|
|
529
|
-
eventmodeler list screens
|
|
530
|
-
eventmodeler list screens --format json
|
|
531
|
-
`);
|
|
532
|
-
process.exit(0);
|
|
533
|
-
}
|
|
534
|
-
{
|
|
535
|
-
const output = await api.listScreens(modelId, format);
|
|
536
|
-
console.log(output);
|
|
537
|
-
}
|
|
538
|
-
break;
|
|
539
|
-
case 'processors':
|
|
540
|
-
if (helpRequested) {
|
|
541
|
-
console.log(`
|
|
542
|
-
eventmodeler list processors - List all processors
|
|
543
|
-
|
|
544
|
-
USAGE:
|
|
545
|
-
eventmodeler list processors [--format xml|json]
|
|
546
|
-
|
|
547
|
-
OUTPUT:
|
|
548
|
-
Lists processors with id, name, and field count.
|
|
549
|
-
|
|
550
|
-
EXAMPLES:
|
|
551
|
-
eventmodeler list processors
|
|
552
|
-
eventmodeler list processors --format json
|
|
553
|
-
`);
|
|
554
|
-
process.exit(0);
|
|
555
|
-
}
|
|
556
|
-
{
|
|
557
|
-
const output = await api.listProcessors(modelId, format);
|
|
558
|
-
console.log(output);
|
|
559
|
-
}
|
|
560
|
-
break;
|
|
561
|
-
case 'scenarios':
|
|
562
|
-
if (helpRequested) {
|
|
563
|
-
console.log(`
|
|
564
|
-
eventmodeler list scenarios - List all scenarios
|
|
565
|
-
|
|
566
|
-
USAGE:
|
|
567
|
-
eventmodeler list scenarios [--format xml|json]
|
|
568
|
-
|
|
569
|
-
OUTPUT:
|
|
570
|
-
- Scenario name
|
|
571
|
-
- Parent slice
|
|
572
|
-
- Then type (events, error, command, etc.)
|
|
573
|
-
|
|
574
|
-
EXAMPLES:
|
|
575
|
-
eventmodeler list scenarios
|
|
576
|
-
eventmodeler list scenarios --format json
|
|
577
|
-
`);
|
|
578
|
-
process.exit(0);
|
|
579
|
-
}
|
|
580
|
-
{
|
|
581
|
-
const output = await api.listScenarios(modelId, format);
|
|
582
|
-
console.log(output);
|
|
583
|
-
}
|
|
584
|
-
break;
|
|
585
|
-
default:
|
|
586
|
-
console.error(`Unknown list target: ${subcommand}`);
|
|
587
|
-
console.error('Valid targets: slices, events, commands, chapters, aggregates, actors, readmodels, screens, processors, scenarios');
|
|
588
|
-
console.error('Run "eventmodeler list --help" for more information.');
|
|
589
|
-
process.exit(1);
|
|
590
|
-
}
|
|
591
|
-
break;
|
|
592
|
-
case 'show':
|
|
593
|
-
if (helpRequested && !subcommand) {
|
|
594
|
-
console.log(`
|
|
595
|
-
eventmodeler show - Show detailed information about entities
|
|
596
|
-
|
|
597
|
-
USAGE:
|
|
598
|
-
eventmodeler show <type> <name> [options]
|
|
599
|
-
|
|
600
|
-
TYPES:
|
|
601
|
-
slice Show slice with components and flows
|
|
602
|
-
event Show event with all fields
|
|
603
|
-
command Show command with all fields
|
|
604
|
-
chapter Show chapter with slices and dependencies
|
|
605
|
-
information-completeness Show information completeness of all flows
|
|
606
|
-
(with element name: show per-element completeness)
|
|
607
|
-
aggregate-completeness Show if events have aggregate ID field
|
|
608
|
-
actor Show actor with screens
|
|
609
|
-
readmodel Show read model with fields and flows
|
|
610
|
-
screen Show screen with fields and connections
|
|
611
|
-
processor Show processor with subscriptions and commands
|
|
612
|
-
aggregate Show aggregate with events and ID field status
|
|
613
|
-
scenario Show scenario with Given-When-Then details
|
|
614
|
-
|
|
615
|
-
OPTIONS:
|
|
616
|
-
--format xml|json Output format (default: xml)
|
|
617
|
-
|
|
618
|
-
EXAMPLES:
|
|
619
|
-
eventmodeler show slice "Place Order"
|
|
620
|
-
eventmodeler show event OrderPlaced
|
|
621
|
-
eventmodeler show information-completeness OrderSummary
|
|
622
|
-
|
|
623
|
-
Run "eventmodeler show <type> --help" for type-specific help.
|
|
624
|
-
`);
|
|
625
|
-
process.exit(0);
|
|
626
|
-
}
|
|
627
|
-
switch (subcommand) {
|
|
628
|
-
case 'slice':
|
|
629
|
-
if (helpRequested) {
|
|
630
|
-
console.log(`
|
|
631
|
-
eventmodeler show slice - Show detailed slice information
|
|
632
|
-
|
|
633
|
-
USAGE:
|
|
634
|
-
eventmodeler show slice <name> [--format xml|json]
|
|
635
|
-
|
|
636
|
-
ARGUMENTS:
|
|
637
|
-
<name> Slice name (spaces allowed without quotes)
|
|
638
|
-
|
|
639
|
-
OUTPUT INCLUDES:
|
|
640
|
-
- Slice type (state-change, automation, state-view)
|
|
641
|
-
- Status (created, in-progress, blocked, done)
|
|
642
|
-
- Components: screens, commands, events, read models, processors
|
|
643
|
-
- Each component's fields with types and flags
|
|
644
|
-
- Flow annotations and swimlane positions
|
|
645
|
-
- Inbound/outbound dependencies
|
|
646
|
-
- Scenarios (Given-When-Then specifications)
|
|
647
|
-
|
|
648
|
-
EXAMPLES:
|
|
649
|
-
eventmodeler show slice "Place Order"
|
|
650
|
-
eventmodeler show slice Place Order
|
|
651
|
-
eventmodeler show slice "Place Order" --format json
|
|
652
|
-
`);
|
|
653
|
-
process.exit(0);
|
|
654
|
-
}
|
|
655
|
-
if (!target) {
|
|
656
|
-
console.error('Usage: eventmodeler show slice <name>');
|
|
657
|
-
console.error('Run "eventmodeler show slice --help" for more information.');
|
|
658
|
-
process.exit(1);
|
|
659
|
-
}
|
|
660
|
-
{
|
|
661
|
-
const result = await api.showSlice(modelId, target, format);
|
|
662
|
-
console.log(result);
|
|
663
|
-
}
|
|
664
|
-
break;
|
|
665
|
-
case 'event':
|
|
666
|
-
if (helpRequested) {
|
|
667
|
-
console.log(`
|
|
668
|
-
eventmodeler show event - Show detailed event information
|
|
669
|
-
|
|
670
|
-
USAGE:
|
|
671
|
-
eventmodeler show event <name> [--format xml|json]
|
|
672
|
-
|
|
673
|
-
ARGUMENTS:
|
|
674
|
-
<name> Event name (spaces allowed without quotes)
|
|
675
|
-
|
|
676
|
-
OUTPUT INCLUDES:
|
|
677
|
-
- Event name and aggregate
|
|
678
|
-
- All fields with:
|
|
679
|
-
- name: Field name
|
|
680
|
-
- type: UUID, String, Int, Long, Double, Decimal, Boolean, Date, DateTime, Custom
|
|
681
|
-
- isList: Whether field is an array
|
|
682
|
-
- isOptional: Whether field can be null
|
|
683
|
-
- isGenerated: Whether field is computed (not mapped from source)
|
|
684
|
-
- subfields: Nested fields for Custom types (recursive, with all flags)
|
|
685
|
-
|
|
686
|
-
FIELD OUTPUT FORMAT (XML):
|
|
687
|
-
<field name="orderId" type="UUID"/>
|
|
688
|
-
<field name="total" type="Decimal" isGenerated="true"/>
|
|
689
|
-
<field name="items" type="Custom" isList="true">
|
|
690
|
-
<field name="productId" type="UUID"/>
|
|
691
|
-
<field name="lineTotal" type="Decimal" isGenerated="true"/>
|
|
692
|
-
</field>
|
|
693
|
-
|
|
694
|
-
EXAMPLES:
|
|
695
|
-
eventmodeler show event OrderPlaced
|
|
696
|
-
eventmodeler show event "Order Placed" --format json
|
|
697
|
-
`);
|
|
698
|
-
process.exit(0);
|
|
699
|
-
}
|
|
700
|
-
if (!target) {
|
|
701
|
-
console.error('Usage: eventmodeler show event <name>');
|
|
702
|
-
console.error('Run "eventmodeler show event --help" for more information.');
|
|
703
|
-
process.exit(1);
|
|
704
|
-
}
|
|
705
|
-
{
|
|
706
|
-
const result = await api.showEvent(modelId, target, format);
|
|
707
|
-
console.log(result);
|
|
708
|
-
}
|
|
709
|
-
break;
|
|
710
|
-
case 'command':
|
|
711
|
-
if (helpRequested) {
|
|
712
|
-
console.log(`
|
|
713
|
-
eventmodeler show command - Show detailed command information
|
|
714
|
-
|
|
715
|
-
USAGE:
|
|
716
|
-
eventmodeler show command <name> [--format xml|json]
|
|
717
|
-
|
|
718
|
-
ARGUMENTS:
|
|
719
|
-
<name> Command name (spaces allowed without quotes)
|
|
720
|
-
|
|
721
|
-
OUTPUT INCLUDES:
|
|
722
|
-
- Command name and aggregate
|
|
723
|
-
- All fields with types, flags, and nested subfields
|
|
724
|
-
|
|
725
|
-
EXAMPLES:
|
|
726
|
-
eventmodeler show command PlaceOrder
|
|
727
|
-
eventmodeler show command "Place Order" --format json
|
|
728
|
-
`);
|
|
729
|
-
process.exit(0);
|
|
730
|
-
}
|
|
731
|
-
if (!target) {
|
|
732
|
-
console.error('Usage: eventmodeler show command <name>');
|
|
733
|
-
console.error('Run "eventmodeler show command --help" for more information.');
|
|
734
|
-
process.exit(1);
|
|
735
|
-
}
|
|
736
|
-
{
|
|
737
|
-
const result = await api.showCommand(modelId, target, format);
|
|
738
|
-
console.log(result);
|
|
739
|
-
}
|
|
740
|
-
break;
|
|
741
|
-
case 'chapter':
|
|
742
|
-
if (helpRequested) {
|
|
743
|
-
console.log(`
|
|
744
|
-
eventmodeler show chapter - Show detailed chapter information
|
|
745
|
-
|
|
746
|
-
USAGE:
|
|
747
|
-
eventmodeler show chapter <name> [--format xml|json]
|
|
748
|
-
|
|
749
|
-
ARGUMENTS:
|
|
750
|
-
<name> Chapter name
|
|
751
|
-
|
|
752
|
-
OUTPUT INCLUDES:
|
|
753
|
-
- All slices in the chapter
|
|
754
|
-
- Flow graph showing internal dependencies
|
|
755
|
-
- External dependencies (inbound/outbound)
|
|
756
|
-
|
|
757
|
-
EXAMPLES:
|
|
758
|
-
eventmodeler show chapter "Order Management"
|
|
759
|
-
eventmodeler show chapter "Order Management" --format json
|
|
760
|
-
`);
|
|
761
|
-
process.exit(0);
|
|
762
|
-
}
|
|
763
|
-
if (!target) {
|
|
764
|
-
console.error('Usage: eventmodeler show chapter <name>');
|
|
765
|
-
console.error('Run "eventmodeler show chapter --help" for more information.');
|
|
766
|
-
process.exit(1);
|
|
767
|
-
}
|
|
768
|
-
{
|
|
769
|
-
const result = await api.showChapter(modelId, target, format);
|
|
770
|
-
console.log(result);
|
|
771
|
-
}
|
|
772
|
-
break;
|
|
773
|
-
case 'information-completeness':
|
|
774
|
-
if (helpRequested) {
|
|
775
|
-
console.log(`
|
|
776
|
-
eventmodeler show information-completeness - Show information completeness
|
|
777
|
-
|
|
778
|
-
USAGE:
|
|
779
|
-
eventmodeler show information-completeness [--format xml|json]
|
|
780
|
-
eventmodeler show information-completeness --slice "Place Order"
|
|
781
|
-
eventmodeler show information-completeness --chapter "Ordering"
|
|
782
|
-
eventmodeler show information-completeness <element-name> [--format xml|json]
|
|
783
|
-
|
|
784
|
-
OUTPUT INCLUDES (model-wide):
|
|
785
|
-
- Summary of complete/incomplete flows across the whole model
|
|
786
|
-
- Incomplete flows grouped by slice, with untraceable fields
|
|
787
|
-
- Incomplete read models with untraceable fields and source events
|
|
788
|
-
|
|
789
|
-
OUTPUT INCLUDES (per-element):
|
|
790
|
-
- Total fields vs mapped fields
|
|
791
|
-
- List of unmapped fields needing attention
|
|
792
|
-
- Mapping sources for mapped fields
|
|
793
|
-
|
|
794
|
-
IMPORTANT - GENERATED FIELDS:
|
|
795
|
-
Fields with isGenerated=true are EXCLUDED from completeness checks.
|
|
796
|
-
Generated fields are computed/synthesized values that don't need
|
|
797
|
-
source mappings (e.g., calculated totals, timestamps, derived data).
|
|
798
|
-
|
|
799
|
-
NOTE: Generated and user-input fields are excluded from checks.
|
|
800
|
-
Auto-matching uses field name AND type.
|
|
801
|
-
|
|
802
|
-
EXAMPLES:
|
|
803
|
-
eventmodeler show information-completeness
|
|
804
|
-
eventmodeler show information-completeness --slice "Place Order"
|
|
805
|
-
eventmodeler show information-completeness --chapter "Ordering"
|
|
806
|
-
eventmodeler show information-completeness --format json
|
|
807
|
-
eventmodeler show information-completeness CreateOrder
|
|
808
|
-
eventmodeler show information-completeness "Order Summary" --format json
|
|
809
|
-
`);
|
|
810
|
-
process.exit(0);
|
|
811
|
-
}
|
|
812
|
-
{
|
|
813
|
-
if (target) {
|
|
814
|
-
// Per-element completeness
|
|
815
|
-
const result = await api.showElementCompleteness(modelId, target, format);
|
|
816
|
-
console.log(result);
|
|
817
|
-
}
|
|
818
|
-
else {
|
|
819
|
-
// Model-wide information completeness
|
|
820
|
-
const sliceFilter = getNamedArg(filteredArgs, '--slice');
|
|
821
|
-
const result = await api.showInformationCompleteness(modelId, format, sliceFilter, chapterArg ?? undefined);
|
|
822
|
-
console.log(result);
|
|
823
|
-
}
|
|
824
|
-
}
|
|
825
|
-
break;
|
|
826
|
-
case 'aggregate-completeness':
|
|
827
|
-
if (helpRequested) {
|
|
828
|
-
console.log(`
|
|
829
|
-
eventmodeler show aggregate-completeness - Check aggregate ID field presence
|
|
830
|
-
|
|
831
|
-
USAGE:
|
|
832
|
-
eventmodeler show aggregate-completeness <name> [--format xml|json]
|
|
833
|
-
|
|
834
|
-
ARGUMENTS:
|
|
835
|
-
<name> Aggregate name
|
|
836
|
-
|
|
837
|
-
OUTPUT:
|
|
838
|
-
Lists all events in the aggregate and whether each has the
|
|
839
|
-
aggregate ID field (e.g., "orderId" for "Order" aggregate).
|
|
840
|
-
|
|
841
|
-
EXAMPLES:
|
|
842
|
-
eventmodeler show aggregate-completeness Order
|
|
843
|
-
eventmodeler show aggregate-completeness "Order" --format json
|
|
844
|
-
`);
|
|
845
|
-
process.exit(0);
|
|
846
|
-
}
|
|
847
|
-
if (!target) {
|
|
848
|
-
console.error('Usage: eventmodeler show aggregate-completeness <aggregate-name>');
|
|
849
|
-
console.error('Run "eventmodeler show aggregate-completeness --help" for more information.');
|
|
850
|
-
process.exit(1);
|
|
851
|
-
}
|
|
852
|
-
{
|
|
853
|
-
const result = await api.showAggregateCompleteness(modelId, target, format);
|
|
854
|
-
console.log(result);
|
|
855
|
-
}
|
|
856
|
-
break;
|
|
857
|
-
case 'actor':
|
|
858
|
-
if (helpRequested) {
|
|
859
|
-
console.log(`
|
|
860
|
-
eventmodeler show actor - Show detailed actor information
|
|
861
|
-
|
|
862
|
-
USAGE:
|
|
863
|
-
eventmodeler show actor <name> [--format xml|json]
|
|
864
|
-
|
|
865
|
-
ARGUMENTS:
|
|
866
|
-
<name> Actor name
|
|
867
|
-
|
|
868
|
-
OUTPUT INCLUDES:
|
|
869
|
-
- Actor name
|
|
870
|
-
- All associated screens
|
|
871
|
-
|
|
872
|
-
EXAMPLES:
|
|
873
|
-
eventmodeler show actor Customer
|
|
874
|
-
eventmodeler show actor "Admin User" --format json
|
|
875
|
-
`);
|
|
876
|
-
process.exit(0);
|
|
877
|
-
}
|
|
878
|
-
if (!target) {
|
|
879
|
-
console.error('Usage: eventmodeler show actor <actor-name>');
|
|
880
|
-
console.error('Run "eventmodeler show actor --help" for more information.');
|
|
881
|
-
process.exit(1);
|
|
882
|
-
}
|
|
883
|
-
{
|
|
884
|
-
const result = await api.showActor(modelId, target, format);
|
|
885
|
-
console.log(result);
|
|
886
|
-
}
|
|
887
|
-
break;
|
|
888
|
-
case 'readmodel':
|
|
889
|
-
if (helpRequested) {
|
|
890
|
-
console.log(`
|
|
891
|
-
eventmodeler show readmodel - Show detailed read model information
|
|
892
|
-
|
|
893
|
-
USAGE:
|
|
894
|
-
eventmodeler show readmodel <name> [--format xml|json]
|
|
895
|
-
|
|
896
|
-
ARGUMENTS:
|
|
897
|
-
<name> Read model name
|
|
898
|
-
|
|
899
|
-
OUTPUT INCLUDES:
|
|
900
|
-
- Read model name and fields
|
|
901
|
-
- Events it consumes from (with field mappings)
|
|
902
|
-
- Screens/Processors it flows to
|
|
903
|
-
|
|
904
|
-
EXAMPLES:
|
|
905
|
-
eventmodeler show readmodel OrderSummary
|
|
906
|
-
eventmodeler show readmodel "Customer Profile" --format json
|
|
907
|
-
`);
|
|
908
|
-
process.exit(0);
|
|
909
|
-
}
|
|
910
|
-
if (!target) {
|
|
911
|
-
console.error('Usage: eventmodeler show readmodel <name>');
|
|
912
|
-
console.error('Run "eventmodeler show readmodel --help" for more information.');
|
|
913
|
-
process.exit(1);
|
|
914
|
-
}
|
|
915
|
-
{
|
|
916
|
-
const result = await api.showReadModel(modelId, target, format);
|
|
917
|
-
console.log(result);
|
|
918
|
-
}
|
|
919
|
-
break;
|
|
920
|
-
case 'screen':
|
|
921
|
-
if (helpRequested) {
|
|
922
|
-
console.log(`
|
|
923
|
-
eventmodeler show screen - Show detailed screen information
|
|
924
|
-
|
|
925
|
-
USAGE:
|
|
926
|
-
eventmodeler show screen <name> [--format xml|json]
|
|
927
|
-
|
|
928
|
-
ARGUMENTS:
|
|
929
|
-
<name> Screen name
|
|
930
|
-
|
|
931
|
-
OUTPUT INCLUDES:
|
|
932
|
-
- Screen name and fields
|
|
933
|
-
- Actor (if contained in one)
|
|
934
|
-
- Read models it displays from
|
|
935
|
-
- Commands it triggers
|
|
936
|
-
|
|
937
|
-
EXAMPLES:
|
|
938
|
-
eventmodeler show screen "Order Form"
|
|
939
|
-
eventmodeler show screen Dashboard --format json
|
|
940
|
-
`);
|
|
941
|
-
process.exit(0);
|
|
942
|
-
}
|
|
943
|
-
if (!target) {
|
|
944
|
-
console.error('Usage: eventmodeler show screen <name>');
|
|
945
|
-
console.error('Run "eventmodeler show screen --help" for more information.');
|
|
946
|
-
process.exit(1);
|
|
947
|
-
}
|
|
948
|
-
{
|
|
949
|
-
const result = await api.showScreen(modelId, target, format);
|
|
950
|
-
console.log(result);
|
|
951
|
-
}
|
|
952
|
-
break;
|
|
953
|
-
case 'processor':
|
|
954
|
-
if (helpRequested) {
|
|
955
|
-
console.log(`
|
|
956
|
-
eventmodeler show processor - Show detailed processor information
|
|
957
|
-
|
|
958
|
-
USAGE:
|
|
959
|
-
eventmodeler show processor <name> [--format xml|json]
|
|
960
|
-
|
|
961
|
-
ARGUMENTS:
|
|
962
|
-
<name> Processor name
|
|
963
|
-
|
|
964
|
-
OUTPUT INCLUDES:
|
|
965
|
-
- Processor name and fields
|
|
966
|
-
- Read models it subscribes to
|
|
967
|
-
- Commands it triggers
|
|
968
|
-
|
|
969
|
-
EXAMPLES:
|
|
970
|
-
eventmodeler show processor "Order Validator"
|
|
971
|
-
eventmodeler show processor NotificationSender --format json
|
|
972
|
-
`);
|
|
973
|
-
process.exit(0);
|
|
974
|
-
}
|
|
975
|
-
if (!target) {
|
|
976
|
-
console.error('Usage: eventmodeler show processor <name>');
|
|
977
|
-
console.error('Run "eventmodeler show processor --help" for more information.');
|
|
978
|
-
process.exit(1);
|
|
979
|
-
}
|
|
980
|
-
{
|
|
981
|
-
const result = await api.showProcessor(modelId, target, format);
|
|
982
|
-
console.log(result);
|
|
983
|
-
}
|
|
984
|
-
break;
|
|
985
|
-
case 'aggregate':
|
|
986
|
-
if (helpRequested) {
|
|
987
|
-
console.log(`
|
|
988
|
-
eventmodeler show aggregate - Show detailed aggregate information
|
|
989
|
-
|
|
990
|
-
USAGE:
|
|
991
|
-
eventmodeler show aggregate <name> [--format xml|json]
|
|
992
|
-
|
|
993
|
-
ARGUMENTS:
|
|
994
|
-
<name> Aggregate name
|
|
995
|
-
|
|
996
|
-
OUTPUT INCLUDES:
|
|
997
|
-
- Aggregate name
|
|
998
|
-
- ID field configuration (if set)
|
|
999
|
-
- All contained events
|
|
1000
|
-
- ID field completeness status
|
|
1001
|
-
|
|
1002
|
-
EXAMPLES:
|
|
1003
|
-
eventmodeler show aggregate Order
|
|
1004
|
-
eventmodeler show aggregate "User Account" --format json
|
|
1005
|
-
`);
|
|
1006
|
-
process.exit(0);
|
|
1007
|
-
}
|
|
1008
|
-
if (!target) {
|
|
1009
|
-
console.error('Usage: eventmodeler show aggregate <name>');
|
|
1010
|
-
console.error('Run "eventmodeler show aggregate --help" for more information.');
|
|
1011
|
-
process.exit(1);
|
|
1012
|
-
}
|
|
1013
|
-
{
|
|
1014
|
-
const result = await api.showAggregate(modelId, target, format);
|
|
1015
|
-
console.log(result);
|
|
1016
|
-
}
|
|
1017
|
-
break;
|
|
1018
|
-
case 'scenario':
|
|
1019
|
-
if (helpRequested) {
|
|
1020
|
-
console.log(`
|
|
1021
|
-
eventmodeler show scenario - Show detailed scenario information
|
|
1022
|
-
|
|
1023
|
-
USAGE:
|
|
1024
|
-
eventmodeler show scenario <name> [--format xml|json]
|
|
1025
|
-
|
|
1026
|
-
ARGUMENTS:
|
|
1027
|
-
<name> Scenario name
|
|
1028
|
-
|
|
1029
|
-
OUTPUT INCLUDES:
|
|
1030
|
-
- Scenario name and description
|
|
1031
|
-
- Parent slice
|
|
1032
|
-
- Given events (with field values)
|
|
1033
|
-
- When command or events (with field values)
|
|
1034
|
-
- Then expectations (events, error, command, etc.)
|
|
1035
|
-
|
|
1036
|
-
EXAMPLES:
|
|
1037
|
-
eventmodeler show scenario "Happy path"
|
|
1038
|
-
eventmodeler show scenario "Invalid input" --format json
|
|
1039
|
-
`);
|
|
1040
|
-
process.exit(0);
|
|
1041
|
-
}
|
|
1042
|
-
if (!target) {
|
|
1043
|
-
console.error('Usage: eventmodeler show scenario <name>');
|
|
1044
|
-
console.error('Run "eventmodeler show scenario --help" for more information.');
|
|
1045
|
-
process.exit(1);
|
|
1046
|
-
}
|
|
1047
|
-
{
|
|
1048
|
-
const result = await api.showScenario(modelId, target, format);
|
|
1049
|
-
console.log(result);
|
|
1050
|
-
}
|
|
1051
|
-
break;
|
|
1052
|
-
default:
|
|
1053
|
-
console.error(`Unknown show target: ${subcommand}`);
|
|
1054
|
-
console.error('Valid targets: slice, event, command, chapter, information-completeness, aggregate-completeness, actor, readmodel, screen, processor, aggregate, scenario');
|
|
1055
|
-
console.error('Run "eventmodeler show --help" for more information.');
|
|
1056
|
-
process.exit(1);
|
|
1057
|
-
}
|
|
1058
|
-
break;
|
|
1059
|
-
case 'search':
|
|
1060
|
-
if (helpRequested) {
|
|
1061
|
-
console.log(`
|
|
1062
|
-
eventmodeler search - Search for entities by name
|
|
1063
|
-
|
|
1064
|
-
USAGE:
|
|
1065
|
-
eventmodeler search <term> [--format xml|json]
|
|
1066
|
-
|
|
1067
|
-
ARGUMENTS:
|
|
1068
|
-
<term> Search term (case-insensitive partial match)
|
|
1069
|
-
|
|
1070
|
-
OPTIONS:
|
|
1071
|
-
--format <format> Output format: xml (default) or json
|
|
1072
|
-
|
|
1073
|
-
SEARCHES ACROSS:
|
|
1074
|
-
- Slices
|
|
1075
|
-
- Events
|
|
1076
|
-
- Commands
|
|
1077
|
-
- Read Models
|
|
1078
|
-
- Screens
|
|
1079
|
-
- Processors
|
|
1080
|
-
- Chapters
|
|
1081
|
-
- Aggregates
|
|
1082
|
-
- Actors
|
|
1083
|
-
|
|
1084
|
-
EXAMPLES:
|
|
1085
|
-
eventmodeler search order
|
|
1086
|
-
eventmodeler search "payment" --format json
|
|
1087
|
-
`);
|
|
1088
|
-
process.exit(0);
|
|
1089
|
-
}
|
|
1090
|
-
if (!subcommand) {
|
|
1091
|
-
console.error('Usage: eventmodeler search <term>');
|
|
1092
|
-
console.error('Run "eventmodeler search --help" for more information.');
|
|
1093
|
-
process.exit(1);
|
|
1094
|
-
}
|
|
1095
|
-
{
|
|
1096
|
-
const searchTerm = target ? `${subcommand} ${target}` : subcommand;
|
|
1097
|
-
const response = await api.search(modelId, searchTerm);
|
|
1098
|
-
if (format === 'json') {
|
|
1099
|
-
console.log(JSON.stringify(response, null, 2));
|
|
1100
|
-
}
|
|
1101
|
-
else {
|
|
1102
|
-
const xb = new XMLBuilder({ ignoreAttributes: false, attributeNamePrefix: '@_', suppressEmptyNode: true });
|
|
1103
|
-
const results = response.results.map(r => {
|
|
1104
|
-
const tag = r.type === 'readmodel' ? 'read-model' : r.type;
|
|
1105
|
-
const attrs = {};
|
|
1106
|
-
if (r.id)
|
|
1107
|
-
attrs['@_id'] = r.id;
|
|
1108
|
-
if (r.name)
|
|
1109
|
-
attrs['@_name'] = r.name;
|
|
1110
|
-
if (r.chapterId)
|
|
1111
|
-
attrs['@_chapter-id'] = r.chapterId;
|
|
1112
|
-
if (r.chapterName)
|
|
1113
|
-
attrs['@_chapter-name'] = r.chapterName;
|
|
1114
|
-
if (r.sliceId)
|
|
1115
|
-
attrs['@_slice-id'] = r.sliceId;
|
|
1116
|
-
if (r.sliceName)
|
|
1117
|
-
attrs['@_slice-name'] = r.sliceName;
|
|
1118
|
-
if (r.sliceStatus)
|
|
1119
|
-
attrs['@_slice-status'] = r.sliceStatus;
|
|
1120
|
-
if (r.parentChapterId)
|
|
1121
|
-
attrs['@_parent-chapter-id'] = r.parentChapterId;
|
|
1122
|
-
if (r.parentChapterName)
|
|
1123
|
-
attrs['@_parent-chapter-name'] = r.parentChapterName;
|
|
1124
|
-
return ` ${xb.build({ [tag]: attrs }).trim()}`;
|
|
1125
|
-
});
|
|
1126
|
-
const wrapper = xb.build({ 'search-results': { '@_query': searchTerm, '@_count': String(response.results.length) } });
|
|
1127
|
-
// Replace self-closing tag with children
|
|
1128
|
-
const open = wrapper.replace(/\/>$/, '>').trim();
|
|
1129
|
-
console.log([open, ...results, '</search-results>'].join('\n'));
|
|
1130
|
-
}
|
|
1131
|
-
}
|
|
1132
|
-
break;
|
|
1133
|
-
case 'mark': {
|
|
1134
|
-
if (helpRequested) {
|
|
1135
|
-
console.log(`
|
|
1136
|
-
eventmodeler mark - Mark a slice's status
|
|
1137
|
-
|
|
1138
|
-
USAGE:
|
|
1139
|
-
eventmodeler mark <slice-name> <status>
|
|
1140
|
-
|
|
1141
|
-
ARGUMENTS:
|
|
1142
|
-
<slice-name> Slice name (can include spaces)
|
|
1143
|
-
<status> One of: created, in-progress, blocked, done
|
|
1144
|
-
|
|
1145
|
-
STATUSES:
|
|
1146
|
-
created Initial state, not yet started
|
|
1147
|
-
in-progress Currently being worked on
|
|
1148
|
-
blocked Work paused due to dependency or issue
|
|
1149
|
-
done Completed
|
|
1150
|
-
|
|
1151
|
-
EXAMPLES:
|
|
1152
|
-
eventmodeler mark "Place Order" done
|
|
1153
|
-
eventmodeler mark "Process Payment" in-progress
|
|
1154
|
-
eventmodeler mark "Ship Order" blocked
|
|
1155
|
-
`);
|
|
1156
|
-
process.exit(0);
|
|
1157
|
-
}
|
|
1158
|
-
// mark <slice-name> <status> - status is last arg, slice name is everything before
|
|
1159
|
-
// Note: subcommand contains first part of slice name, remainingArgs has the rest
|
|
1160
|
-
const validStatuses = ['created', 'in-progress', 'blocked', 'done'];
|
|
1161
|
-
const allArgs = subcommand ? [subcommand, ...remainingArgs] : remainingArgs;
|
|
1162
|
-
const lastArg = allArgs[allArgs.length - 1];
|
|
1163
|
-
if (allArgs.length < 2 || !validStatuses.includes(lastArg)) {
|
|
1164
|
-
console.error('Usage: eventmodeler mark <slice-name> <status>');
|
|
1165
|
-
console.error('Valid statuses: created, in-progress, blocked, done');
|
|
1166
|
-
console.error('Run "eventmodeler mark --help" for more information.');
|
|
1167
|
-
process.exit(1);
|
|
1168
|
-
}
|
|
1169
|
-
const sliceName = allArgs.slice(0, -1).join(' ');
|
|
1170
|
-
const status = lastArg;
|
|
1171
|
-
await api.markSliceStatus(modelId, sliceName, status);
|
|
1172
|
-
console.log(`Marked slice "${sliceName}" as ${status}`);
|
|
1173
|
-
break;
|
|
1174
|
-
}
|
|
1175
|
-
case 'summary':
|
|
1176
|
-
if (helpRequested) {
|
|
1177
|
-
console.log(`
|
|
1178
|
-
eventmodeler summary - Show model summary statistics
|
|
1179
|
-
|
|
1180
|
-
USAGE:
|
|
1181
|
-
eventmodeler summary [--format xml|json]
|
|
1182
|
-
|
|
1183
|
-
OPTIONS:
|
|
1184
|
-
--format <format> Output format: xml (default) or json
|
|
1185
|
-
|
|
1186
|
-
OUTPUT:
|
|
1187
|
-
Aggregate statistics including:
|
|
1188
|
-
- Total counts (slices, events, commands, read models, screens, etc.)
|
|
1189
|
-
- Slices by type (state-change, automation, state-view)
|
|
1190
|
-
- Slices by status (created, in-progress, blocked, done)
|
|
1191
|
-
- Chapter summary
|
|
1192
|
-
|
|
1193
|
-
EXAMPLES:
|
|
1194
|
-
eventmodeler summary
|
|
1195
|
-
eventmodeler summary --format json
|
|
1196
|
-
`);
|
|
1197
|
-
process.exit(0);
|
|
1198
|
-
}
|
|
1199
|
-
{
|
|
1200
|
-
const summary = await api.getSummary(modelId);
|
|
1201
|
-
if (format === 'json') {
|
|
1202
|
-
console.log(JSON.stringify(summary, null, 2));
|
|
1203
|
-
}
|
|
1204
|
-
else {
|
|
1205
|
-
const xb = new XMLBuilder({ ignoreAttributes: false, attributeNamePrefix: '@_', format: true, indentBy: ' ', suppressEmptyNode: true });
|
|
1206
|
-
console.log(xb.build({
|
|
1207
|
-
model: {
|
|
1208
|
-
'@_name': summary.modelName || '',
|
|
1209
|
-
slices: { '@_count': String(summary.slices.total) },
|
|
1210
|
-
commands: { '@_count': String(summary.commands) },
|
|
1211
|
-
events: { '@_count': String(summary.events) },
|
|
1212
|
-
'read-models': { '@_count': String(summary.readModels) },
|
|
1213
|
-
screens: { '@_count': String(summary.screens) },
|
|
1214
|
-
processors: { '@_count': String(summary.processors) },
|
|
1215
|
-
aggregates: { '@_count': String(summary.aggregates) },
|
|
1216
|
-
actors: { '@_count': String(summary.actors) },
|
|
1217
|
-
scenarios: { '@_count': String(summary.scenarios) },
|
|
1218
|
-
flows: { '@_count': String(summary.flows) },
|
|
1219
|
-
},
|
|
1220
|
-
}).trim());
|
|
1221
|
-
}
|
|
1222
|
-
}
|
|
1223
|
-
break;
|
|
1224
|
-
case 'export':
|
|
1225
|
-
if (helpRequested && !subcommand) {
|
|
1226
|
-
console.log(`
|
|
1227
|
-
eventmodeler export - Export the model
|
|
1228
|
-
|
|
1229
|
-
USAGE:
|
|
1230
|
-
eventmodeler export <format>
|
|
1231
|
-
|
|
1232
|
-
FORMATS:
|
|
1233
|
-
json Export entire model as JSON
|
|
1234
|
-
|
|
1235
|
-
Run "eventmodeler export json --help" for detailed help.
|
|
1236
|
-
`);
|
|
1237
|
-
process.exit(0);
|
|
1238
|
-
}
|
|
1239
|
-
switch (subcommand) {
|
|
1240
|
-
case 'json':
|
|
1241
|
-
if (helpRequested) {
|
|
1242
|
-
console.log(`
|
|
1243
|
-
eventmodeler export json - Export entire model as JSON
|
|
1244
|
-
|
|
1245
|
-
USAGE:
|
|
1246
|
-
eventmodeler export json
|
|
1247
|
-
|
|
1248
|
-
OUTPUT:
|
|
1249
|
-
Complete event model as JSON to stdout, including:
|
|
1250
|
-
- All entities (slices, events, commands, read models, screens, etc.)
|
|
1251
|
-
- All flows and field mappings
|
|
1252
|
-
- All scenarios
|
|
1253
|
-
- Metadata (chapters, aggregates, actors)
|
|
1254
|
-
|
|
1255
|
-
EXAMPLES:
|
|
1256
|
-
eventmodeler export json
|
|
1257
|
-
eventmodeler export json > model.json
|
|
1258
|
-
eventmodeler export json | jq '.events'
|
|
1259
|
-
`);
|
|
1260
|
-
process.exit(0);
|
|
1261
|
-
}
|
|
1262
|
-
{
|
|
1263
|
-
const result = await api.exportJson(modelId);
|
|
1264
|
-
console.log(JSON.stringify(JSON.parse(result), null, 2));
|
|
1265
|
-
}
|
|
1266
|
-
break;
|
|
1267
|
-
default:
|
|
1268
|
-
console.error(`Unknown export format: ${subcommand}`);
|
|
1269
|
-
console.error('Valid formats: json');
|
|
1270
|
-
console.error('Run "eventmodeler export --help" for more information.');
|
|
1271
|
-
process.exit(1);
|
|
1272
|
-
}
|
|
1273
|
-
break;
|
|
1274
|
-
case 'add':
|
|
1275
|
-
if (helpRequested && !subcommand) {
|
|
1276
|
-
console.log(`
|
|
1277
|
-
eventmodeler add - Add entities to the model
|
|
1278
|
-
|
|
1279
|
-
USAGE:
|
|
1280
|
-
eventmodeler add <type> [options]
|
|
1281
|
-
|
|
1282
|
-
TYPES:
|
|
1283
|
-
scenario Add Given-When-Then scenario to a slice
|
|
1284
|
-
field Add field to command, event, read model, screen, or processor
|
|
1285
|
-
|
|
1286
|
-
Run "eventmodeler add <type> --help" for type-specific help.
|
|
1287
|
-
`);
|
|
1288
|
-
process.exit(0);
|
|
1289
|
-
}
|
|
1290
|
-
switch (subcommand) {
|
|
1291
|
-
case 'scenario': {
|
|
1292
|
-
if (helpRequested) {
|
|
1293
|
-
console.log(`
|
|
1294
|
-
eventmodeler add scenario - Add a scenario to a slice
|
|
1295
|
-
|
|
1296
|
-
USAGE:
|
|
1297
|
-
eventmodeler add scenario --slice <name> --json|--xml <data>
|
|
1298
|
-
|
|
1299
|
-
OPTIONS:
|
|
1300
|
-
--slice <name> Target slice name (required)
|
|
1301
|
-
--json <data> Scenario in JSON format
|
|
1302
|
-
--xml <data> Scenario in XML format
|
|
1303
|
-
|
|
1304
|
-
JSON FORMAT:
|
|
1305
|
-
{
|
|
1306
|
-
"name": "Scenario name",
|
|
1307
|
-
"given": { // Optional: preconditions
|
|
1308
|
-
"type": "events",
|
|
1309
|
-
"events": ["EventName1", "EventName2"]
|
|
1310
|
-
},
|
|
1311
|
-
"when": { // Optional: trigger
|
|
1312
|
-
"type": "command",
|
|
1313
|
-
"command": "CommandName"
|
|
1314
|
-
},
|
|
1315
|
-
"then": { // Required: expected outcome
|
|
1316
|
-
"type": "events",
|
|
1317
|
-
"events": ["ExpectedEvent"]
|
|
1318
|
-
}
|
|
1319
|
-
}
|
|
1320
|
-
|
|
1321
|
-
XML FORMAT:
|
|
1322
|
-
<scenario name="Scenario name">
|
|
1323
|
-
<given type="events">
|
|
1324
|
-
<event>EventName1</event>
|
|
1325
|
-
</given>
|
|
1326
|
-
<when type="command">
|
|
1327
|
-
<command>CommandName</command>
|
|
1328
|
-
</when>
|
|
1329
|
-
<then type="events">
|
|
1330
|
-
<event>ExpectedEvent</event>
|
|
1331
|
-
</then>
|
|
1332
|
-
</scenario>
|
|
1333
|
-
|
|
1334
|
-
EXAMPLES:
|
|
1335
|
-
eventmodeler add scenario --slice "Place Order" --json '{"name": "Happy path", "then": {"type": "events", "events": ["OrderPlaced"]}}'
|
|
1336
|
-
|
|
1337
|
-
eventmodeler add scenario --slice "Place Order" --xml '<scenario name="Out of stock"><given type="events"><event>ProductOutOfStock</event></given><then type="events"><event>OrderRejected</event></then></scenario>'
|
|
1338
|
-
`);
|
|
1339
|
-
process.exit(0);
|
|
1340
|
-
}
|
|
1341
|
-
const sliceArg = getNamedArg(filteredArgs, '--slice');
|
|
1342
|
-
const jsonArg = getNamedArg(filteredArgs, '--json');
|
|
1343
|
-
const xmlArg = getNamedArg(filteredArgs, '--xml');
|
|
1344
|
-
const inputData = jsonArg ?? xmlArg;
|
|
1345
|
-
if (!sliceArg) {
|
|
1346
|
-
console.error('Error: --slice is required');
|
|
1347
|
-
console.error('Usage: eventmodeler add scenario --slice <name> --json|--xml <data>');
|
|
1348
|
-
console.error('Run "eventmodeler add scenario --help" for detailed format.');
|
|
1349
|
-
process.exit(1);
|
|
1350
|
-
}
|
|
1351
|
-
if (!inputData) {
|
|
1352
|
-
console.error('Error: --json or --xml is required');
|
|
1353
|
-
console.error('Usage: eventmodeler add scenario --slice <name> --json|--xml <data>');
|
|
1354
|
-
console.error('Run "eventmodeler add scenario --help" for detailed format.');
|
|
1355
|
-
process.exit(1);
|
|
1356
|
-
}
|
|
1357
|
-
{
|
|
1358
|
-
let parsedScenario;
|
|
1359
|
-
try {
|
|
1360
|
-
parsedScenario = parseScenarioInput(inputData);
|
|
1361
|
-
}
|
|
1362
|
-
catch (err) {
|
|
1363
|
-
console.error(`Error parsing scenario data: ${err.message}`);
|
|
1364
|
-
process.exit(1);
|
|
1365
|
-
}
|
|
1366
|
-
const scenario = {
|
|
1367
|
-
name: parsedScenario.name,
|
|
1368
|
-
description: parsedScenario.description,
|
|
1369
|
-
given: parsedScenario.given,
|
|
1370
|
-
when: parsedScenario.when
|
|
1371
|
-
? {
|
|
1372
|
-
command: parsedScenario.when.command
|
|
1373
|
-
? {
|
|
1374
|
-
command: parsedScenario.when.command,
|
|
1375
|
-
fieldValues: parsedScenario.when.commandFieldValues,
|
|
1376
|
-
}
|
|
1377
|
-
: undefined,
|
|
1378
|
-
events: parsedScenario.when.events,
|
|
1379
|
-
}
|
|
1380
|
-
: undefined,
|
|
1381
|
-
then: {
|
|
1382
|
-
type: parsedScenario.then.type,
|
|
1383
|
-
events: parsedScenario.then.events,
|
|
1384
|
-
errorMessage: parsedScenario.then.errorMessage,
|
|
1385
|
-
errorType: parsedScenario.then.errorType,
|
|
1386
|
-
command: parsedScenario.then.command
|
|
1387
|
-
? {
|
|
1388
|
-
command: parsedScenario.then.command,
|
|
1389
|
-
fieldValues: parsedScenario.then.commandFieldValues,
|
|
1390
|
-
}
|
|
1391
|
-
: undefined,
|
|
1392
|
-
readModelAssertion: parsedScenario.then.readModel
|
|
1393
|
-
? {
|
|
1394
|
-
readModel: parsedScenario.then.readModel,
|
|
1395
|
-
givenEvents: parsedScenario.then.givenEvents,
|
|
1396
|
-
expectedFieldValues: parsedScenario.then.expected,
|
|
1397
|
-
}
|
|
1398
|
-
: undefined,
|
|
1399
|
-
},
|
|
1400
|
-
};
|
|
1401
|
-
await api.createScenario(modelId, sliceArg, scenario);
|
|
1402
|
-
console.log(`Created scenario "${scenario.name}" in slice "${sliceArg}"`);
|
|
1403
|
-
}
|
|
1404
|
-
break;
|
|
1405
|
-
}
|
|
1406
|
-
case 'field': {
|
|
1407
|
-
if (helpRequested) {
|
|
1408
|
-
console.log(`
|
|
1409
|
-
eventmodeler add field - Add a field to an entity
|
|
1410
|
-
|
|
1411
|
-
USAGE:
|
|
1412
|
-
eventmodeler add field <element-name> --json|--xml <data>
|
|
1413
|
-
|
|
1414
|
-
OPTIONS:
|
|
1415
|
-
<element-name> Name of the command, event, read model, screen, or processor
|
|
1416
|
-
--json <data> Field definition in JSON format
|
|
1417
|
-
--xml <data> Field definition in XML format
|
|
1418
|
-
|
|
1419
|
-
FIELD TYPES:
|
|
1420
|
-
UUID, String, Int, Long, Double, Decimal, Boolean, Date, DateTime, Custom
|
|
1421
|
-
|
|
1422
|
-
FIELD FLAGS (work on ALL fields including nested subfields):
|
|
1423
|
-
isList - Field contains multiple values (array)
|
|
1424
|
-
isOptional - Field may be null/missing
|
|
1425
|
-
isGenerated - Field is computed/synthesized, not mapped from source
|
|
1426
|
-
isUserInput - (Screen only) Field is entered by user
|
|
1427
|
-
|
|
1428
|
-
JSON FORMAT:
|
|
1429
|
-
Simple field:
|
|
1430
|
-
{"name": "orderId", "type": "UUID"}
|
|
1431
|
-
|
|
1432
|
-
Field with flags:
|
|
1433
|
-
{"name": "notes", "type": "String", "isOptional": true}
|
|
1434
|
-
{"name": "tags", "type": "String", "isList": true}
|
|
1435
|
-
{"name": "total", "type": "Decimal", "isGenerated": true}
|
|
1436
|
-
|
|
1437
|
-
Nested Custom field with subfields (ALL flags work on subfields):
|
|
1438
|
-
{
|
|
1439
|
-
"name": "lineItem",
|
|
1440
|
-
"type": "Custom",
|
|
1441
|
-
"subfields": [
|
|
1442
|
-
{"name": "productId", "type": "UUID"},
|
|
1443
|
-
{"name": "quantity", "type": "Int"},
|
|
1444
|
-
{"name": "unitPrice", "type": "Decimal"},
|
|
1445
|
-
{"name": "lineTotal", "type": "Decimal", "isGenerated": true}
|
|
1446
|
-
]
|
|
1447
|
-
}
|
|
1448
|
-
|
|
1449
|
-
List of Custom with generated subfields:
|
|
1450
|
-
{
|
|
1451
|
-
"name": "items",
|
|
1452
|
-
"type": "Custom",
|
|
1453
|
-
"isList": true,
|
|
1454
|
-
"subfields": [
|
|
1455
|
-
{"name": "sku", "type": "String"},
|
|
1456
|
-
{"name": "qty", "type": "Int"},
|
|
1457
|
-
{"name": "calculatedPrice", "type": "Decimal", "isGenerated": true}
|
|
1458
|
-
]
|
|
1459
|
-
}
|
|
1460
|
-
|
|
1461
|
-
XML FORMAT:
|
|
1462
|
-
Simple field:
|
|
1463
|
-
<field name="orderId" type="UUID"/>
|
|
1464
|
-
|
|
1465
|
-
Field with flags:
|
|
1466
|
-
<field name="notes" type="String" isOptional="true"/>
|
|
1467
|
-
<field name="tags" type="String" isList="true"/>
|
|
1468
|
-
<field name="total" type="Decimal" isGenerated="true"/>
|
|
1469
|
-
|
|
1470
|
-
Nested Custom field (ALL flags work on subfields):
|
|
1471
|
-
<field name="lineItem" type="Custom">
|
|
1472
|
-
<field name="productId" type="UUID"/>
|
|
1473
|
-
<field name="quantity" type="Int"/>
|
|
1474
|
-
<field name="unitPrice" type="Decimal"/>
|
|
1475
|
-
<field name="lineTotal" type="Decimal" isGenerated="true"/>
|
|
1476
|
-
</field>
|
|
1477
|
-
|
|
1478
|
-
List of Custom with flags on subfields:
|
|
1479
|
-
<field name="items" type="Custom" isList="true">
|
|
1480
|
-
<field name="sku" type="String"/>
|
|
1481
|
-
<field name="qty" type="Int"/>
|
|
1482
|
-
<field name="calculatedPrice" type="Decimal" isGenerated="true"/>
|
|
1483
|
-
<field name="notes" type="String" isOptional="true"/>
|
|
1484
|
-
</field>
|
|
1485
|
-
|
|
1486
|
-
NOTES:
|
|
1487
|
-
- Generated fields are excluded from completeness checks
|
|
1488
|
-
- Custom type fields must have subfields defined
|
|
1489
|
-
- Subfields support arbitrary nesting depth
|
|
1490
|
-
|
|
1491
|
-
EXAMPLES:
|
|
1492
|
-
eventmodeler add field OrderPlaced --json '{"name": "orderId", "type": "UUID"}'
|
|
1493
|
-
eventmodeler add field OrderSummary --json '{"name": "totalWithTax", "type": "Decimal", "isGenerated": true}'
|
|
1494
|
-
eventmodeler add field OrderPlaced --xml '<field name="item" type="Custom"><field name="price" type="Decimal"/><field name="tax" type="Decimal" isGenerated="true"/></field>'
|
|
1495
|
-
`);
|
|
1496
|
-
process.exit(0);
|
|
1497
|
-
}
|
|
1498
|
-
const jsonArg = getNamedArg(filteredArgs, '--json');
|
|
1499
|
-
const xmlArg = getNamedArg(filteredArgs, '--xml');
|
|
1500
|
-
const inputData = jsonArg ?? xmlArg;
|
|
1501
|
-
// Element name is the first positional arg after command+subcommand (not a flag or flag value)
|
|
1502
|
-
const elementName = remainingArgs.find((a, i) => !a.startsWith('-') && (i === 0 || !['--json', '--xml'].includes(remainingArgs[i - 1])));
|
|
1503
|
-
if (!elementName) {
|
|
1504
|
-
console.error('Error: Element name is required');
|
|
1505
|
-
console.error('Usage: eventmodeler add field <element-name> --json|--xml <data>');
|
|
1506
|
-
console.error('Run "eventmodeler add field --help" for detailed format documentation.');
|
|
1507
|
-
process.exit(1);
|
|
1508
|
-
}
|
|
1509
|
-
if (!inputData) {
|
|
1510
|
-
console.error('Error: --json or --xml is required');
|
|
1511
|
-
console.error('Usage: eventmodeler add field <element-name> --json|--xml <data>');
|
|
1512
|
-
console.error('Run "eventmodeler add field --help" for detailed format documentation.');
|
|
1513
|
-
process.exit(1);
|
|
1514
|
-
}
|
|
1515
|
-
{
|
|
1516
|
-
// Parse field data
|
|
1517
|
-
let field;
|
|
1518
|
-
const toApiFieldFromJson = (f) => ({
|
|
1519
|
-
name: f.name,
|
|
1520
|
-
fieldType: f.type ?? f.fieldType ?? 'String',
|
|
1521
|
-
isList: f.isList,
|
|
1522
|
-
isOptional: f.isOptional,
|
|
1523
|
-
isGenerated: f.isGenerated,
|
|
1524
|
-
isUserInput: f.isUserInput,
|
|
1525
|
-
subfields: f.subfields?.map(toApiFieldFromJson),
|
|
1526
|
-
});
|
|
1527
|
-
try {
|
|
1528
|
-
if (jsonArg) {
|
|
1529
|
-
const parsed = JSON.parse(inputData);
|
|
1530
|
-
field = toApiFieldFromJson(parsed);
|
|
1531
|
-
}
|
|
1532
|
-
else {
|
|
1533
|
-
const parser = await import('./lib/slice-utils.js');
|
|
1534
|
-
const parsed = parser.parseFieldsFromXml(inputData);
|
|
1535
|
-
if (parsed.length === 0) {
|
|
1536
|
-
throw new Error('No <field> element found in XML');
|
|
1537
|
-
}
|
|
1538
|
-
const toApiField = (f) => ({
|
|
1539
|
-
name: f.name,
|
|
1540
|
-
fieldType: f.type,
|
|
1541
|
-
isList: f.isList,
|
|
1542
|
-
isOptional: f.isOptional,
|
|
1543
|
-
isGenerated: f.isGenerated,
|
|
1544
|
-
isUserInput: f.isUserInput,
|
|
1545
|
-
subfields: f.subfields?.map(toApiField),
|
|
1546
|
-
});
|
|
1547
|
-
field = toApiField(parsed[0]);
|
|
1548
|
-
}
|
|
1549
|
-
}
|
|
1550
|
-
catch (err) {
|
|
1551
|
-
console.error(`Error parsing field data: ${err.message}`);
|
|
1552
|
-
process.exit(1);
|
|
1553
|
-
}
|
|
1554
|
-
await api.addField(modelId, elementName, field);
|
|
1555
|
-
console.log(`Added field "${field.name}" to "${elementName}"`);
|
|
1556
|
-
}
|
|
1557
|
-
break;
|
|
1558
|
-
}
|
|
1559
|
-
default:
|
|
1560
|
-
console.error(`Unknown add target: ${subcommand}`);
|
|
1561
|
-
console.error('Valid targets: scenario, field');
|
|
1562
|
-
process.exit(1);
|
|
1563
|
-
}
|
|
1564
|
-
break;
|
|
1565
|
-
case 'remove':
|
|
1566
|
-
if (helpRequested && !subcommand) {
|
|
1567
|
-
console.log(`
|
|
1568
|
-
eventmodeler remove - Remove entities from the model
|
|
1569
|
-
|
|
1570
|
-
USAGE:
|
|
1571
|
-
eventmodeler remove <type> [options]
|
|
1572
|
-
|
|
1573
|
-
TYPES:
|
|
1574
|
-
scenario Remove a scenario from a slice
|
|
1575
|
-
field Remove a field from an entity
|
|
1576
|
-
flow Remove a flow between elements
|
|
1577
|
-
|
|
1578
|
-
Run "eventmodeler remove <type> --help" for type-specific help.
|
|
1579
|
-
`);
|
|
1580
|
-
process.exit(0);
|
|
1581
|
-
}
|
|
1582
|
-
switch (subcommand) {
|
|
1583
|
-
case 'scenario': {
|
|
1584
|
-
if (helpRequested) {
|
|
1585
|
-
console.log(`
|
|
1586
|
-
eventmodeler remove scenario - Remove a scenario from a slice
|
|
1587
|
-
|
|
1588
|
-
USAGE:
|
|
1589
|
-
eventmodeler remove scenario <name> [--slice <slice-name>]
|
|
1590
|
-
|
|
1591
|
-
ARGUMENTS:
|
|
1592
|
-
<name> Scenario name to remove
|
|
1593
|
-
|
|
1594
|
-
OPTIONS:
|
|
1595
|
-
--slice <name> Limit search to specific slice (optional)
|
|
1596
|
-
|
|
1597
|
-
EXAMPLES:
|
|
1598
|
-
eventmodeler remove scenario "Happy path"
|
|
1599
|
-
eventmodeler remove scenario "Edge case" --slice "Place Order"
|
|
1600
|
-
`);
|
|
1601
|
-
process.exit(0);
|
|
1602
|
-
}
|
|
1603
|
-
const sliceArg = getNamedArg(filteredArgs, '--slice');
|
|
1604
|
-
// Filter out --slice and its value from remaining args to get scenario name
|
|
1605
|
-
const scenarioArgs = filteredArgs.slice(2).filter((arg, i, arr) => {
|
|
1606
|
-
if (arg === '--slice')
|
|
1607
|
-
return false;
|
|
1608
|
-
if (i > 0 && arr[i - 1] === '--slice')
|
|
1609
|
-
return false;
|
|
1610
|
-
return true;
|
|
1611
|
-
});
|
|
1612
|
-
const scenarioName = scenarioArgs.length > 0 ? scenarioArgs.join(' ') : undefined;
|
|
1613
|
-
if (!scenarioName) {
|
|
1614
|
-
console.error('Usage: eventmodeler remove scenario <name> [--slice <slice-name>]');
|
|
1615
|
-
console.error('Run "eventmodeler remove scenario --help" for more information.');
|
|
1616
|
-
process.exit(1);
|
|
1617
|
-
}
|
|
1618
|
-
await api.removeScenario(modelId, scenarioName, sliceArg);
|
|
1619
|
-
console.log(`Removed scenario "${scenarioName}"${sliceArg ? ` from slice "${sliceArg}"` : ''}`);
|
|
1620
|
-
break;
|
|
1621
|
-
}
|
|
1622
|
-
case 'field': {
|
|
1623
|
-
if (helpRequested) {
|
|
1624
|
-
console.log(`
|
|
1625
|
-
eventmodeler remove field - Remove a field from an entity
|
|
1626
|
-
|
|
1627
|
-
USAGE:
|
|
1628
|
-
eventmodeler remove field <element-name> --field <field-name>
|
|
1629
|
-
|
|
1630
|
-
OPTIONS:
|
|
1631
|
-
<element-name> Name of the command, event, read model, screen, or processor
|
|
1632
|
-
--field <name> Field name to remove (required)
|
|
1633
|
-
|
|
1634
|
-
EXAMPLES:
|
|
1635
|
-
eventmodeler remove field OrderPlaced --field orderId
|
|
1636
|
-
eventmodeler remove field "Order Summary" --field notes
|
|
1637
|
-
`);
|
|
1638
|
-
process.exit(0);
|
|
1639
|
-
}
|
|
1640
|
-
const fieldArg = getNamedArg(filteredArgs, '--field');
|
|
1641
|
-
// Element name is the first positional arg after command+subcommand (not a flag or flag value)
|
|
1642
|
-
const elementName = remainingArgs.find((a, i) => !a.startsWith('-') && (i === 0 || !['--field'].includes(remainingArgs[i - 1])));
|
|
1643
|
-
if (!fieldArg) {
|
|
1644
|
-
console.error('Error: --field is required');
|
|
1645
|
-
console.error('Usage: eventmodeler remove field <element-name> --field <field-name>');
|
|
1646
|
-
console.error('Run "eventmodeler remove field --help" for more information.');
|
|
1647
|
-
process.exit(1);
|
|
1648
|
-
}
|
|
1649
|
-
if (!elementName) {
|
|
1650
|
-
console.error('Error: Element name is required');
|
|
1651
|
-
console.error('Usage: eventmodeler remove field <element-name> --field <field-name>');
|
|
1652
|
-
console.error('Run "eventmodeler remove field --help" for more information.');
|
|
1653
|
-
process.exit(1);
|
|
1654
|
-
}
|
|
1655
|
-
{
|
|
1656
|
-
await api.removeField(modelId, elementName, fieldArg);
|
|
1657
|
-
console.log(`Removed field "${fieldArg}" from "${elementName}"`);
|
|
1658
|
-
}
|
|
1659
|
-
break;
|
|
1660
|
-
}
|
|
1661
|
-
case 'flow': {
|
|
1662
|
-
if (helpRequested) {
|
|
1663
|
-
console.log(`
|
|
1664
|
-
eventmodeler remove flow - Remove a flow between elements
|
|
1665
|
-
|
|
1666
|
-
USAGE:
|
|
1667
|
-
eventmodeler remove flow --from <source> --to <target>
|
|
1668
|
-
|
|
1669
|
-
OPTIONS:
|
|
1670
|
-
--from <name> Source element name (required)
|
|
1671
|
-
--to <name> Target element name (required)
|
|
1672
|
-
|
|
1673
|
-
EXAMPLES:
|
|
1674
|
-
eventmodeler remove flow --from OrderPlaced --to OrderSummary
|
|
1675
|
-
eventmodeler remove flow --from "Order Summary" --to "Order Dashboard Screen"
|
|
1676
|
-
`);
|
|
1677
|
-
process.exit(0);
|
|
1678
|
-
}
|
|
1679
|
-
const fromArg = getNamedArg(filteredArgs, '--from');
|
|
1680
|
-
const toArg = getNamedArg(filteredArgs, '--to');
|
|
1681
|
-
if (!fromArg || !toArg) {
|
|
1682
|
-
console.error('Error: --from and --to are required');
|
|
1683
|
-
console.error('Usage: eventmodeler remove flow --from <source> --to <target>');
|
|
1684
|
-
console.error('Run "eventmodeler remove flow --help" for more information.');
|
|
1685
|
-
process.exit(1);
|
|
1686
|
-
}
|
|
1687
|
-
await api.removeFlow(modelId, fromArg, toArg);
|
|
1688
|
-
console.log(`Removed flow from "${fromArg}" to "${toArg}"`);
|
|
1689
|
-
break;
|
|
1690
|
-
}
|
|
1691
|
-
default:
|
|
1692
|
-
console.error(`Unknown remove target: ${subcommand}`);
|
|
1693
|
-
console.error('Valid targets: scenario, field, flow');
|
|
1694
|
-
console.error('Run "eventmodeler remove --help" for more information.');
|
|
1695
|
-
process.exit(1);
|
|
1696
|
-
}
|
|
1697
|
-
break;
|
|
1698
|
-
case 'map':
|
|
1699
|
-
if (helpRequested && !subcommand) {
|
|
1700
|
-
console.log(`
|
|
1701
|
-
eventmodeler map - Set field mappings
|
|
1702
|
-
|
|
1703
|
-
USAGE:
|
|
1704
|
-
eventmodeler map <type> [options]
|
|
1705
|
-
|
|
1706
|
-
TYPES:
|
|
1707
|
-
fields Set field mappings on a flow
|
|
1708
|
-
|
|
1709
|
-
Run "eventmodeler map fields --help" for detailed help.
|
|
1710
|
-
`);
|
|
1711
|
-
process.exit(0);
|
|
1712
|
-
}
|
|
1713
|
-
switch (subcommand) {
|
|
1714
|
-
case 'fields': {
|
|
1715
|
-
if (helpRequested) {
|
|
1716
|
-
console.log(`
|
|
1717
|
-
eventmodeler map fields - Set field mappings on a flow
|
|
1718
|
-
|
|
1719
|
-
USAGE:
|
|
1720
|
-
eventmodeler map fields --flow <source→target> --json|--xml <mappings>
|
|
1721
|
-
|
|
1722
|
-
OPTIONS:
|
|
1723
|
-
--flow <spec> Flow as "SourceName→TargetName" (use → or ->)
|
|
1724
|
-
--json <data> Mappings in JSON format
|
|
1725
|
-
--xml <data> Mappings in XML format
|
|
1726
|
-
|
|
1727
|
-
JSON FORMAT:
|
|
1728
|
-
[
|
|
1729
|
-
{"from": "sourceField", "to": "targetField"},
|
|
1730
|
-
{"from": "amount", "to": "orderTotal"}
|
|
1731
|
-
]
|
|
1732
|
-
|
|
1733
|
-
XML FORMAT:
|
|
1734
|
-
<mappings>
|
|
1735
|
-
<mapping from="sourceField" to="targetField"/>
|
|
1736
|
-
<mapping from="amount" to="orderTotal"/>
|
|
1737
|
-
</mappings>
|
|
1738
|
-
|
|
1739
|
-
NOTES:
|
|
1740
|
-
- Mappings define how fields flow from source to target
|
|
1741
|
-
- Fields marked as isGenerated=true don't need mappings
|
|
1742
|
-
- Use "show information-completeness <name>" to check mapping status
|
|
1743
|
-
|
|
1744
|
-
EXAMPLES:
|
|
1745
|
-
eventmodeler map fields --flow "OrderPlaced→OrderSummary" --json '[{"from": "total", "to": "totalAmount"}]'
|
|
1746
|
-
|
|
1747
|
-
eventmodeler map fields --flow "OrderPlaced->OrderSummary" --xml '<mappings><mapping from="total" to="totalAmount"/></mappings>'
|
|
1748
|
-
`);
|
|
1749
|
-
process.exit(0);
|
|
1750
|
-
}
|
|
1751
|
-
const flowArg = getNamedArg(filteredArgs, '--flow');
|
|
1752
|
-
const jsonArg = getNamedArg(filteredArgs, '--json');
|
|
1753
|
-
const xmlArg = getNamedArg(filteredArgs, '--xml');
|
|
1754
|
-
const inputData = jsonArg ?? xmlArg;
|
|
1755
|
-
if (!flowArg) {
|
|
1756
|
-
console.error('Error: --flow is required');
|
|
1757
|
-
console.error('Usage: eventmodeler map fields --flow <source→target> --json|--xml <mappings>');
|
|
1758
|
-
console.error('Run "eventmodeler map fields --help" for detailed format.');
|
|
1759
|
-
process.exit(1);
|
|
1760
|
-
}
|
|
1761
|
-
if (!inputData) {
|
|
1762
|
-
console.error('Error: --json or --xml is required');
|
|
1763
|
-
console.error('Usage: eventmodeler map fields --flow <source→target> --json|--xml <mappings>');
|
|
1764
|
-
console.error('Run "eventmodeler map fields --help" for detailed format.');
|
|
1765
|
-
process.exit(1);
|
|
1766
|
-
}
|
|
1767
|
-
{
|
|
1768
|
-
// Parse flow argument to extract source and target names
|
|
1769
|
-
const flowParts = flowArg.split(/→|->/).map(s => s.trim());
|
|
1770
|
-
if (flowParts.length !== 2) {
|
|
1771
|
-
console.error('Error: --flow must be in format "SourceName→TargetName" or "SourceName->TargetName"');
|
|
1772
|
-
process.exit(1);
|
|
1773
|
-
}
|
|
1774
|
-
const [sourceName, targetName] = flowParts;
|
|
1775
|
-
// Parse mappings from JSON or XML
|
|
1776
|
-
let mappings;
|
|
1777
|
-
try {
|
|
1778
|
-
if (jsonArg) {
|
|
1779
|
-
mappings = JSON.parse(inputData);
|
|
1780
|
-
}
|
|
1781
|
-
else {
|
|
1782
|
-
const xp = new XMLParser({ ignoreAttributes: false, attributeNamePrefix: '@_', isArray: (name) => name === 'mapping' });
|
|
1783
|
-
const parsed = xp.parse(inputData);
|
|
1784
|
-
const root = parsed['mappings'];
|
|
1785
|
-
const nodes = root ? (Array.isArray(root['mapping']) ? root['mapping'] : root['mapping'] ? [root['mapping']] : []) : [];
|
|
1786
|
-
mappings = nodes.map(m => ({
|
|
1787
|
-
from: m['@_from'] ?? '',
|
|
1788
|
-
to: m['@_to'] ?? '',
|
|
1789
|
-
}));
|
|
1790
|
-
}
|
|
1791
|
-
}
|
|
1792
|
-
catch (err) {
|
|
1793
|
-
console.error(`Error parsing mappings: ${err.message}`);
|
|
1794
|
-
process.exit(1);
|
|
1795
|
-
}
|
|
1796
|
-
await api.mapFields(modelId, sourceName, targetName, mappings);
|
|
1797
|
-
console.log(`Mapped ${mappings.length} field(s) from "${sourceName}" to "${targetName}"`);
|
|
1798
|
-
}
|
|
1799
|
-
break;
|
|
1800
|
-
}
|
|
1801
|
-
default:
|
|
1802
|
-
console.error(`Unknown map target: ${subcommand}`);
|
|
1803
|
-
console.error('Valid targets: fields');
|
|
1804
|
-
console.error('Run "eventmodeler map --help" for more information.');
|
|
1805
|
-
process.exit(1);
|
|
1806
|
-
}
|
|
1807
|
-
break;
|
|
1808
|
-
case 'update':
|
|
1809
|
-
if (helpRequested && !subcommand) {
|
|
1810
|
-
console.log(`
|
|
1811
|
-
eventmodeler update - Update entities in the model
|
|
1812
|
-
|
|
1813
|
-
USAGE:
|
|
1814
|
-
eventmodeler update <type> [options]
|
|
1815
|
-
|
|
1816
|
-
TYPES:
|
|
1817
|
-
field Update field properties
|
|
1818
|
-
|
|
1819
|
-
Run "eventmodeler update field --help" for detailed help.
|
|
1820
|
-
`);
|
|
1821
|
-
process.exit(0);
|
|
1822
|
-
}
|
|
1823
|
-
switch (subcommand) {
|
|
1824
|
-
case 'field': {
|
|
1825
|
-
if (helpRequested) {
|
|
1826
|
-
console.log(`
|
|
1827
|
-
eventmodeler update field - Update field properties
|
|
1828
|
-
|
|
1829
|
-
USAGE:
|
|
1830
|
-
eventmodeler update field <element-name> --field <field-name> [updates]
|
|
1831
|
-
|
|
1832
|
-
OPTIONS:
|
|
1833
|
-
<element-name> Name of the command, event, read model, screen, or processor
|
|
1834
|
-
|
|
1835
|
-
REQUIRED:
|
|
1836
|
-
--field <name> Field to update (use dot-notation for nested subfields: "parent.child")
|
|
1837
|
-
|
|
1838
|
-
UPDATE OPTIONS (at least one required):
|
|
1839
|
-
--optional true|false Set isOptional flag
|
|
1840
|
-
--generated true|false Set isGenerated flag
|
|
1841
|
-
--user-input true|false Set isUserInput flag
|
|
1842
|
-
--type <type> Change field type
|
|
1843
|
-
|
|
1844
|
-
FIELD FLAGS EXPLAINED:
|
|
1845
|
-
isOptional Field may be null/missing
|
|
1846
|
-
isGenerated Field is computed, excluded from completeness checks
|
|
1847
|
-
isUserInput (Screen only) Field entered by user vs displayed
|
|
1848
|
-
|
|
1849
|
-
EXAMPLES:
|
|
1850
|
-
# Mark field as optional
|
|
1851
|
-
eventmodeler update field OrderSummary --field notes --optional true
|
|
1852
|
-
|
|
1853
|
-
# Mark field as generated (computed value, no mapping needed)
|
|
1854
|
-
eventmodeler update field OrderSummary --field totalWithTax --generated true
|
|
1855
|
-
|
|
1856
|
-
# Mark screen field as user input
|
|
1857
|
-
eventmodeler update field "Order Form" --field quantity --user-input true
|
|
1858
|
-
|
|
1859
|
-
# Change field type
|
|
1860
|
-
eventmodeler update field OrderPlaced --field amount --type Decimal
|
|
1861
|
-
|
|
1862
|
-
# Update a nested subfield using dot-notation
|
|
1863
|
-
eventmodeler update field OrderPlaced --field "shippingAddress.zipCode" --optional true
|
|
1864
|
-
`);
|
|
1865
|
-
process.exit(0);
|
|
1866
|
-
}
|
|
1867
|
-
const fieldArg = getNamedArg(filteredArgs, '--field');
|
|
1868
|
-
const optionalArg = getNamedArg(filteredArgs, '--optional');
|
|
1869
|
-
const generatedArg = getNamedArg(filteredArgs, '--generated');
|
|
1870
|
-
const userInputArg = getNamedArg(filteredArgs, '--user-input');
|
|
1871
|
-
const typeArg = getNamedArg(filteredArgs, '--type');
|
|
1872
|
-
// Element name is the first positional arg after command+subcommand (not a flag or flag value)
|
|
1873
|
-
const flagsWithValues = ['--field', '--optional', '--generated', '--user-input', '--type'];
|
|
1874
|
-
const elementName = remainingArgs.find((a, i) => !a.startsWith('-') && (i === 0 || !flagsWithValues.includes(remainingArgs[i - 1])));
|
|
1875
|
-
if (!fieldArg) {
|
|
1876
|
-
console.error('Error: --field is required');
|
|
1877
|
-
console.error('Usage: eventmodeler update field <element-name> --field <field-name> [--optional true|false] [--generated true|false] [--user-input true|false]');
|
|
1878
|
-
console.error('Run "eventmodeler update field --help" for detailed options.');
|
|
1879
|
-
process.exit(1);
|
|
1880
|
-
}
|
|
1881
|
-
if (!elementName) {
|
|
1882
|
-
console.error('Error: Element name is required');
|
|
1883
|
-
console.error('Usage: eventmodeler update field <element-name> --field <field-name> [--optional true|false] [--generated true|false] [--user-input true|false]');
|
|
1884
|
-
console.error('Run "eventmodeler update field --help" for detailed options.');
|
|
1885
|
-
process.exit(1);
|
|
1886
|
-
}
|
|
1887
|
-
const updates = {};
|
|
1888
|
-
if (optionalArg !== undefined) {
|
|
1889
|
-
updates.optional = optionalArg === 'true';
|
|
1890
|
-
}
|
|
1891
|
-
if (generatedArg !== undefined) {
|
|
1892
|
-
updates.generated = generatedArg === 'true';
|
|
1893
|
-
}
|
|
1894
|
-
if (userInputArg !== undefined) {
|
|
1895
|
-
updates.userInput = userInputArg === 'true';
|
|
1896
|
-
}
|
|
1897
|
-
if (typeArg !== undefined) {
|
|
1898
|
-
updates.type = typeArg;
|
|
1899
|
-
}
|
|
1900
|
-
if (Object.keys(updates).length === 0) {
|
|
1901
|
-
console.error('Error: Must specify at least one update (--optional, --generated, --user-input, or --type)');
|
|
1902
|
-
console.error('Run "eventmodeler update field --help" for available options.');
|
|
1903
|
-
process.exit(1);
|
|
1904
|
-
}
|
|
1905
|
-
{
|
|
1906
|
-
// Convert updates to API format
|
|
1907
|
-
const fieldUpdates = {};
|
|
1908
|
-
if (updates.optional !== undefined)
|
|
1909
|
-
fieldUpdates.isOptional = updates.optional;
|
|
1910
|
-
if (updates.generated !== undefined)
|
|
1911
|
-
fieldUpdates.isGenerated = updates.generated;
|
|
1912
|
-
if (updates.userInput !== undefined)
|
|
1913
|
-
fieldUpdates.isUserInput = updates.userInput;
|
|
1914
|
-
if (updates.type !== undefined)
|
|
1915
|
-
fieldUpdates.fieldType = updates.type;
|
|
1916
|
-
await api.updateField(modelId, elementName, fieldArg, fieldUpdates);
|
|
1917
|
-
console.log(`Updated field "${fieldArg}" on "${elementName}"`);
|
|
1918
|
-
}
|
|
1919
|
-
break;
|
|
1920
|
-
}
|
|
1921
|
-
default:
|
|
1922
|
-
console.error(`Unknown update target: ${subcommand}`);
|
|
1923
|
-
console.error('Valid targets: field');
|
|
1924
|
-
console.error('Run "eventmodeler update --help" for more information.');
|
|
1925
|
-
process.exit(1);
|
|
1926
|
-
}
|
|
1927
|
-
break;
|
|
1928
|
-
case 'create':
|
|
1929
|
-
if (helpRequested && !subcommand) {
|
|
1930
|
-
console.log(`
|
|
1931
|
-
eventmodeler create - Create new slices and flows
|
|
1932
|
-
|
|
1933
|
-
USAGE:
|
|
1934
|
-
eventmodeler create <type> [options]
|
|
1935
|
-
|
|
1936
|
-
TYPES:
|
|
1937
|
-
state-change-slice Create Screen → Command → Event slice
|
|
1938
|
-
automation-slice Create ReadModel → Processor → Command → Event slice
|
|
1939
|
-
state-view-slice Create ReadModel-only slice
|
|
1940
|
-
flow Create flow between elements
|
|
1941
|
-
|
|
1942
|
-
Run "eventmodeler create <type> --help" for type-specific help.
|
|
1943
|
-
`);
|
|
1944
|
-
process.exit(0);
|
|
1945
|
-
}
|
|
1946
|
-
switch (subcommand) {
|
|
1947
|
-
case 'state-change-slice': {
|
|
1948
|
-
if (helpRequested) {
|
|
1949
|
-
console.log(`
|
|
1950
|
-
eventmodeler create state-change-slice - Create a state-change slice
|
|
1951
|
-
|
|
1952
|
-
A state-change slice represents user action: Screen → Command → Event
|
|
1953
|
-
|
|
1954
|
-
USAGE:
|
|
1955
|
-
eventmodeler create state-change-slice --xml <data>
|
|
1956
|
-
|
|
1957
|
-
XML FORMAT:
|
|
1958
|
-
<state-change-slice name="Slice Name" [after="Slice Name"] [before="Slice Name"]>
|
|
1959
|
-
<screen name="Screen Name" actor="Actor Name">
|
|
1960
|
-
<field name="fieldName" type="Type" [flags]/>
|
|
1961
|
-
</screen>
|
|
1962
|
-
<command name="CommandName">
|
|
1963
|
-
<field name="fieldName" type="Type" [flags]/>
|
|
1964
|
-
</command>
|
|
1965
|
-
<event name="EventName">
|
|
1966
|
-
<field name="fieldName" type="Type" [flags]/>
|
|
1967
|
-
</event>
|
|
1968
|
-
</state-change-slice>
|
|
1969
|
-
|
|
1970
|
-
POSITIONING (IMPORTANT):
|
|
1971
|
-
after="Slice Name" Place this slice immediately after the named slice
|
|
1972
|
-
before="Slice Name" Place this slice immediately before the named slice
|
|
1973
|
-
(shifts existing slices to the right)
|
|
1974
|
-
|
|
1975
|
-
If neither is specified, the slice is placed at the rightmost position.
|
|
1976
|
-
Use "eventmodeler list slices" to see existing slice names for positioning.
|
|
1977
|
-
|
|
1978
|
-
FIELD TYPES:
|
|
1979
|
-
UUID, String, Int, Long, Double, Decimal, Boolean, Date, DateTime, Custom
|
|
1980
|
-
|
|
1981
|
-
FIELD FLAGS (work on ALL fields and nested subfields):
|
|
1982
|
-
isList="true" Array/list of values
|
|
1983
|
-
isOptional="true" Nullable field
|
|
1984
|
-
isGenerated="true" Computed field (excluded from mapping completeness)
|
|
1985
|
-
isUserInput="true" User-entered field (screen fields only)
|
|
1986
|
-
|
|
1987
|
-
NESTED CUSTOM FIELDS:
|
|
1988
|
-
<field name="address" type="Custom">
|
|
1989
|
-
<field name="street" type="String"/>
|
|
1990
|
-
<field name="city" type="String"/>
|
|
1991
|
-
<field name="formattedFull" type="String" isGenerated="true"/>
|
|
1992
|
-
</field>
|
|
1993
|
-
|
|
1994
|
-
EXAMPLES:
|
|
1995
|
-
# Create slice at the end (default)
|
|
1996
|
-
eventmodeler create state-change-slice --xml '
|
|
1997
|
-
<state-change-slice name="Place Order">
|
|
1998
|
-
<screen name="Order Form" actor="Customer">
|
|
1999
|
-
<field name="productId" type="UUID" isUserInput="true"/>
|
|
2000
|
-
</screen>
|
|
2001
|
-
<command name="PlaceOrder">
|
|
2002
|
-
<field name="productId" type="UUID"/>
|
|
2003
|
-
</command>
|
|
2004
|
-
<event name="OrderPlaced">
|
|
2005
|
-
<field name="orderId" type="UUID"/>
|
|
2006
|
-
<field name="productId" type="UUID"/>
|
|
2007
|
-
</event>
|
|
2008
|
-
</state-change-slice>'
|
|
2009
|
-
|
|
2010
|
-
# Create slice after an existing slice
|
|
2011
|
-
eventmodeler create state-change-slice --xml '
|
|
2012
|
-
<state-change-slice name="Confirm Order" after="Place Order">
|
|
2013
|
-
...
|
|
2014
|
-
</state-change-slice>'
|
|
2015
|
-
|
|
2016
|
-
# Create slice before an existing slice (shifts others right)
|
|
2017
|
-
eventmodeler create state-change-slice --xml '
|
|
2018
|
-
<state-change-slice name="Review Cart" before="Place Order">
|
|
2019
|
-
...
|
|
2020
|
-
</state-change-slice>'
|
|
2021
|
-
`);
|
|
2022
|
-
process.exit(0);
|
|
2023
|
-
}
|
|
2024
|
-
const xmlArg = getNamedArg(filteredArgs, '--xml');
|
|
2025
|
-
if (!xmlArg) {
|
|
2026
|
-
console.error('Error: --xml is required');
|
|
2027
|
-
console.error('Usage: eventmodeler create state-change-slice --xml \'<state-change-slice>...</state-change-slice>\'');
|
|
2028
|
-
console.error('Run "eventmodeler create state-change-slice --help" for detailed format.');
|
|
2029
|
-
process.exit(1);
|
|
2030
|
-
}
|
|
2031
|
-
{
|
|
2032
|
-
// Parse XML input to extract structured data
|
|
2033
|
-
const parser = await import('./lib/slice-utils.js');
|
|
2034
|
-
const parsed = parser.parseStateChangeSliceXml(xmlArg);
|
|
2035
|
-
const sliceInput = {
|
|
2036
|
-
sliceName: parsed.sliceName,
|
|
2037
|
-
after: parsed.after,
|
|
2038
|
-
before: parsed.before,
|
|
2039
|
-
screen: { name: parsed.screen.name, fields: toCompoundFields(parsed.screen.fields) },
|
|
2040
|
-
command: { name: parsed.command.name, fields: toCompoundFields(parsed.command.fields) },
|
|
2041
|
-
event: { name: parsed.event.name, fields: toCompoundFields(parsed.event.fields) },
|
|
2042
|
-
};
|
|
2043
|
-
const result = await api.createStateChangeSlice(modelId, sliceInput);
|
|
2044
|
-
console.log(`Created state-change slice "${parsed.sliceName}"`);
|
|
2045
|
-
console.log(` Screen: ${parsed.screen.name} (${parsed.screen.fields.length} fields)`);
|
|
2046
|
-
console.log(` Command: ${parsed.command.name} (${parsed.command.fields.length} fields)`);
|
|
2047
|
-
console.log(` Event: ${parsed.event.name} (${parsed.event.fields.length} fields)`);
|
|
2048
|
-
console.log(` Screen -> Command mappings: ${result.screenToCommandMappings}`);
|
|
2049
|
-
console.log(` Command -> Event mappings: ${result.commandToEventMappings}`);
|
|
2050
|
-
}
|
|
2051
|
-
break;
|
|
2052
|
-
}
|
|
2053
|
-
case 'automation-slice': {
|
|
2054
|
-
if (helpRequested) {
|
|
2055
|
-
console.log(`
|
|
2056
|
-
eventmodeler create automation-slice - Create an automation slice
|
|
2057
|
-
|
|
2058
|
-
An automation slice represents system automation: ReadModel → Processor → Command → Event
|
|
2059
|
-
|
|
2060
|
-
USAGE:
|
|
2061
|
-
eventmodeler create automation-slice --xml <data>
|
|
2062
|
-
|
|
2063
|
-
XML FORMAT:
|
|
2064
|
-
<automation-slice name="Slice Name" [after="Slice Name"] [before="Slice Name"]>
|
|
2065
|
-
<read-model name="ReadModelName">
|
|
2066
|
-
<field name="fieldName" type="Type" [flags]/>
|
|
2067
|
-
</read-model>
|
|
2068
|
-
<processor name="ProcessorName">
|
|
2069
|
-
<field name="fieldName" type="Type" [flags]/>
|
|
2070
|
-
</processor>
|
|
2071
|
-
<command name="CommandName">
|
|
2072
|
-
<field name="fieldName" type="Type" [flags]/>
|
|
2073
|
-
</command>
|
|
2074
|
-
<event name="EventName">
|
|
2075
|
-
<field name="fieldName" type="Type" [flags]/>
|
|
2076
|
-
</event>
|
|
2077
|
-
</automation-slice>
|
|
2078
|
-
|
|
2079
|
-
POSITIONING (IMPORTANT):
|
|
2080
|
-
after="Slice Name" Place this slice immediately after the named slice
|
|
2081
|
-
before="Slice Name" Place this slice immediately before the named slice
|
|
2082
|
-
(shifts existing slices to the right)
|
|
2083
|
-
|
|
2084
|
-
If neither is specified, the slice is placed at the rightmost position.
|
|
2085
|
-
Use "eventmodeler list slices" to see existing slice names for positioning.
|
|
2086
|
-
|
|
2087
|
-
FIELD TYPES:
|
|
2088
|
-
UUID, String, Int, Long, Double, Decimal, Boolean, Date, DateTime, Custom
|
|
2089
|
-
|
|
2090
|
-
FIELD FLAGS (work on ALL fields and nested subfields):
|
|
2091
|
-
isList="true" Array/list of values
|
|
2092
|
-
isOptional="true" Nullable field
|
|
2093
|
-
isGenerated="true" Computed field (excluded from mapping completeness)
|
|
2094
|
-
|
|
2095
|
-
EXAMPLES:
|
|
2096
|
-
# Create automation slice after "Place Order" slice
|
|
2097
|
-
eventmodeler create automation-slice --xml '
|
|
2098
|
-
<automation-slice name="Auto-ship Order" after="Place Order">
|
|
2099
|
-
<read-model name="OrderReadyForShipment">
|
|
2100
|
-
<field name="orderId" type="UUID"/>
|
|
2101
|
-
<field name="shippingAddress" type="String"/>
|
|
2102
|
-
</read-model>
|
|
2103
|
-
<processor name="ShipmentScheduler">
|
|
2104
|
-
<field name="orderId" type="UUID"/>
|
|
2105
|
-
</processor>
|
|
2106
|
-
<command name="ScheduleShipment">
|
|
2107
|
-
<field name="orderId" type="UUID"/>
|
|
2108
|
-
</command>
|
|
2109
|
-
<event name="ShipmentScheduled">
|
|
2110
|
-
<field name="shipmentId" type="UUID" isGenerated="true"/>
|
|
2111
|
-
<field name="orderId" type="UUID"/>
|
|
2112
|
-
<field name="scheduledAt" type="DateTime" isGenerated="true"/>
|
|
2113
|
-
</event>
|
|
2114
|
-
</automation-slice>'
|
|
2115
|
-
|
|
2116
|
-
# Create automation slice before another slice
|
|
2117
|
-
eventmodeler create automation-slice --xml '
|
|
2118
|
-
<automation-slice name="Validate Inventory" before="Auto-ship Order">
|
|
2119
|
-
...
|
|
2120
|
-
</automation-slice>'
|
|
2121
|
-
`);
|
|
2122
|
-
process.exit(0);
|
|
2123
|
-
}
|
|
2124
|
-
const xmlArg = getNamedArg(filteredArgs, '--xml');
|
|
2125
|
-
if (!xmlArg) {
|
|
2126
|
-
console.error('Error: --xml is required');
|
|
2127
|
-
console.error('Usage: eventmodeler create automation-slice --xml \'<automation-slice>...</automation-slice>\'');
|
|
2128
|
-
console.error('Run "eventmodeler create automation-slice --help" for detailed format.');
|
|
2129
|
-
process.exit(1);
|
|
2130
|
-
}
|
|
2131
|
-
{
|
|
2132
|
-
// Parse XML input to extract structured data
|
|
2133
|
-
const parser = await import('./lib/slice-utils.js');
|
|
2134
|
-
const parsed = parser.parseAutomationSliceXml(xmlArg);
|
|
2135
|
-
const sliceInput = {
|
|
2136
|
-
sliceName: parsed.sliceName,
|
|
2137
|
-
after: parsed.after,
|
|
2138
|
-
before: parsed.before,
|
|
2139
|
-
readModel: { name: parsed.readModel.name, fields: toCompoundFields(parsed.readModel.fields) },
|
|
2140
|
-
processor: { name: parsed.processor.name },
|
|
2141
|
-
command: { name: parsed.command.name, fields: toCompoundFields(parsed.command.fields) },
|
|
2142
|
-
event: { name: parsed.event.name, fields: toCompoundFields(parsed.event.fields) },
|
|
2143
|
-
};
|
|
2144
|
-
const result = await api.createAutomationSlice(modelId, sliceInput);
|
|
2145
|
-
console.log(`Created automation slice "${parsed.sliceName}"`);
|
|
2146
|
-
console.log(` ReadModel: ${parsed.readModel.name} (${parsed.readModel.fields.length} fields)`);
|
|
2147
|
-
console.log(` Processor: ${parsed.processor.name}`);
|
|
2148
|
-
console.log(` Command: ${parsed.command.name} (${parsed.command.fields.length} fields)`);
|
|
2149
|
-
console.log(` Event: ${parsed.event.name} (${parsed.event.fields.length} fields)`);
|
|
2150
|
-
console.log(` ReadModel -> Command mappings: ${result.readModelToCommandMappings}`);
|
|
2151
|
-
console.log(` Command -> Event mappings: ${result.commandToEventMappings}`);
|
|
2152
|
-
}
|
|
2153
|
-
break;
|
|
2154
|
-
}
|
|
2155
|
-
case 'state-view-slice': {
|
|
2156
|
-
if (helpRequested) {
|
|
2157
|
-
console.log(`
|
|
2158
|
-
eventmodeler create state-view-slice - Create a state-view slice
|
|
2159
|
-
|
|
2160
|
-
A state-view slice represents a read model for displaying data.
|
|
2161
|
-
|
|
2162
|
-
USAGE:
|
|
2163
|
-
eventmodeler create state-view-slice --xml <data>
|
|
2164
|
-
|
|
2165
|
-
XML FORMAT:
|
|
2166
|
-
<state-view-slice name="Slice Name" [after="Slice Name"] [before="Slice Name"]>
|
|
2167
|
-
<read-model name="ReadModelName">
|
|
2168
|
-
<field name="fieldName" type="Type" [flags]/>
|
|
2169
|
-
</read-model>
|
|
2170
|
-
</state-view-slice>
|
|
2171
|
-
|
|
2172
|
-
POSITIONING (IMPORTANT):
|
|
2173
|
-
after="Slice Name" Place this slice immediately after the named slice
|
|
2174
|
-
before="Slice Name" Place this slice immediately before the named slice
|
|
2175
|
-
(shifts existing slices to the right)
|
|
2176
|
-
|
|
2177
|
-
If neither is specified, the slice is placed at the rightmost position.
|
|
2178
|
-
Use "eventmodeler list slices" to see existing slice names for positioning.
|
|
2179
|
-
|
|
2180
|
-
FIELD TYPES:
|
|
2181
|
-
UUID, String, Int, Long, Double, Decimal, Boolean, Date, DateTime, Custom
|
|
2182
|
-
|
|
2183
|
-
FIELD FLAGS (work on ALL fields and nested subfields):
|
|
2184
|
-
isList="true" Array/list of values
|
|
2185
|
-
isOptional="true" Nullable field
|
|
2186
|
-
isGenerated="true" Computed/aggregated field (common for dashboards)
|
|
2187
|
-
|
|
2188
|
-
EXAMPLES:
|
|
2189
|
-
# Create state-view slice after "Place Order" slice
|
|
2190
|
-
eventmodeler create state-view-slice --xml '
|
|
2191
|
-
<state-view-slice name="Order Dashboard" after="Place Order">
|
|
2192
|
-
<read-model name="OrderDashboard">
|
|
2193
|
-
<field name="totalOrders" type="Int" isGenerated="true"/>
|
|
2194
|
-
<field name="totalRevenue" type="Decimal" isGenerated="true"/>
|
|
2195
|
-
<field name="averageOrderValue" type="Decimal" isGenerated="true"/>
|
|
2196
|
-
<field name="recentOrders" type="Custom" isList="true">
|
|
2197
|
-
<field name="orderId" type="UUID"/>
|
|
2198
|
-
<field name="total" type="Decimal"/>
|
|
2199
|
-
<field name="status" type="String"/>
|
|
2200
|
-
</field>
|
|
2201
|
-
</read-model>
|
|
2202
|
-
</state-view-slice>'
|
|
2203
|
-
|
|
2204
|
-
# Create state-view slice before another slice
|
|
2205
|
-
eventmodeler create state-view-slice --xml '
|
|
2206
|
-
<state-view-slice name="Customer Summary" before="Order Dashboard">
|
|
2207
|
-
...
|
|
2208
|
-
</state-view-slice>'
|
|
2209
|
-
`);
|
|
2210
|
-
process.exit(0);
|
|
2211
|
-
}
|
|
2212
|
-
const xmlArg = getNamedArg(filteredArgs, '--xml');
|
|
2213
|
-
if (!xmlArg) {
|
|
2214
|
-
console.error('Error: --xml is required');
|
|
2215
|
-
console.error('Usage: eventmodeler create state-view-slice --xml \'<state-view-slice>...</state-view-slice>\'');
|
|
2216
|
-
console.error('Run "eventmodeler create state-view-slice --help" for detailed format.');
|
|
2217
|
-
process.exit(1);
|
|
2218
|
-
}
|
|
2219
|
-
{
|
|
2220
|
-
// Parse XML input to extract structured data
|
|
2221
|
-
const parser = await import('./lib/slice-utils.js');
|
|
2222
|
-
const parsed = parser.parseStateViewSliceXml(xmlArg);
|
|
2223
|
-
const sliceInput = {
|
|
2224
|
-
sliceName: parsed.sliceName,
|
|
2225
|
-
after: parsed.after,
|
|
2226
|
-
before: parsed.before,
|
|
2227
|
-
readModel: { name: parsed.readModel.name, fields: toCompoundFields(parsed.readModel.fields) },
|
|
2228
|
-
};
|
|
2229
|
-
const result = await api.createStateViewSlice(modelId, sliceInput);
|
|
2230
|
-
console.log(`Created state-view slice "${parsed.sliceName}"`);
|
|
2231
|
-
console.log(` ReadModel: ${parsed.readModel.name} (${parsed.readModel.fields.length} fields)`);
|
|
2232
|
-
}
|
|
2233
|
-
break;
|
|
2234
|
-
}
|
|
2235
|
-
case 'flow': {
|
|
2236
|
-
if (helpRequested) {
|
|
2237
|
-
console.log(`
|
|
2238
|
-
eventmodeler create flow - Create a flow between elements
|
|
2239
|
-
|
|
2240
|
-
USAGE:
|
|
2241
|
-
eventmodeler create flow --from <source> --to <target>
|
|
2242
|
-
|
|
2243
|
-
OPTIONS:
|
|
2244
|
-
--from <name> Source element name (required)
|
|
2245
|
-
--to <name> Target element name (required)
|
|
2246
|
-
|
|
2247
|
-
VALID FLOW TYPES:
|
|
2248
|
-
Event → ReadModel Event data projects into read model
|
|
2249
|
-
ReadModel → Screen Read model provides data to UI
|
|
2250
|
-
ReadModel → Processor Read model triggers automation
|
|
2251
|
-
|
|
2252
|
-
EXAMPLES:
|
|
2253
|
-
eventmodeler create flow --from OrderPlaced --to OrderSummary
|
|
2254
|
-
eventmodeler create flow --from "Order Summary" --to "Order Dashboard Screen"
|
|
2255
|
-
eventmodeler create flow --from OrderReadyForShipment --to ShipmentProcessor
|
|
2256
|
-
`);
|
|
2257
|
-
process.exit(0);
|
|
2258
|
-
}
|
|
2259
|
-
const fromArg = getNamedArg(filteredArgs, '--from');
|
|
2260
|
-
const toArg = getNamedArg(filteredArgs, '--to');
|
|
2261
|
-
if (!fromArg || !toArg) {
|
|
2262
|
-
console.error('Error: --from and --to are required');
|
|
2263
|
-
console.error('Usage: eventmodeler create flow --from <source> --to <target>');
|
|
2264
|
-
console.error('Run "eventmodeler create flow --help" for more information.');
|
|
2265
|
-
process.exit(1);
|
|
2266
|
-
}
|
|
2267
|
-
await api.createFlow(modelId, fromArg, toArg);
|
|
2268
|
-
console.log(`Created flow from "${fromArg}" to "${toArg}"`);
|
|
2269
|
-
break;
|
|
2270
|
-
}
|
|
2271
|
-
default:
|
|
2272
|
-
console.error(`Unknown create target: ${subcommand}`);
|
|
2273
|
-
console.error('Valid targets: state-change-slice, automation-slice, state-view-slice, flow');
|
|
2274
|
-
console.error('Run "eventmodeler create --help" for more information.');
|
|
2275
|
-
process.exit(1);
|
|
2276
|
-
}
|
|
2277
|
-
break;
|
|
2278
|
-
case 'codegen':
|
|
2279
|
-
if (helpRequested && !subcommand) {
|
|
2280
|
-
console.log(`
|
|
2281
|
-
eventmodeler codegen - Generate code-ready output
|
|
2282
|
-
|
|
2283
|
-
USAGE:
|
|
2284
|
-
eventmodeler codegen <type> [options]
|
|
2285
|
-
|
|
2286
|
-
TYPES:
|
|
2287
|
-
slice Generate comprehensive JSON for a slice
|
|
2288
|
-
events Generate deduplicated events for a chapter or entire model
|
|
2289
|
-
|
|
2290
|
-
Run "eventmodeler codegen <type> --help" for detailed help.
|
|
2291
|
-
`);
|
|
2292
|
-
process.exit(0);
|
|
2293
|
-
}
|
|
2294
|
-
switch (subcommand) {
|
|
2295
|
-
case 'slice': {
|
|
2296
|
-
if (helpRequested) {
|
|
2297
|
-
console.log(`
|
|
2298
|
-
eventmodeler codegen slice - Generate code-ready JSON for a slice
|
|
2299
|
-
|
|
2300
|
-
USAGE:
|
|
2301
|
-
eventmodeler codegen slice <name>
|
|
2302
|
-
|
|
2303
|
-
ARGUMENTS:
|
|
2304
|
-
<name> Slice name
|
|
2305
|
-
|
|
2306
|
-
OUTPUT:
|
|
2307
|
-
Comprehensive JSON including:
|
|
2308
|
-
- Slice metadata (name, type, chapter, aggregate)
|
|
2309
|
-
- All components with full field definitions
|
|
2310
|
-
- Fields include: name, type, isList, isOptional, isGenerated
|
|
2311
|
-
- Nested subfields for Custom types (all flags preserved)
|
|
2312
|
-
- Field mappings between components
|
|
2313
|
-
- Scenarios (Given-When-Then specifications)
|
|
2314
|
-
- Dependencies (inbound/outbound flows)
|
|
2315
|
-
|
|
2316
|
-
This output is designed for code generation tools and includes
|
|
2317
|
-
all information needed to generate implementation code.
|
|
2318
|
-
|
|
2319
|
-
EXAMPLES:
|
|
2320
|
-
eventmodeler codegen slice "Place Order"
|
|
2321
|
-
eventmodeler codegen slice PlaceOrder > slice.json
|
|
2322
|
-
`);
|
|
2323
|
-
process.exit(0);
|
|
2324
|
-
}
|
|
2325
|
-
const sliceName = target;
|
|
2326
|
-
if (!sliceName) {
|
|
2327
|
-
console.error('Error: slice name is required');
|
|
2328
|
-
console.error('Usage: eventmodeler codegen slice <name>');
|
|
2329
|
-
console.error('Run "eventmodeler codegen slice --help" for more information.');
|
|
2330
|
-
process.exit(1);
|
|
2331
|
-
}
|
|
2332
|
-
{
|
|
2333
|
-
const result = await api.codegenSlice(modelId, sliceName);
|
|
2334
|
-
console.log(JSON.stringify(JSON.parse(result), null, 2));
|
|
2335
|
-
}
|
|
2336
|
-
break;
|
|
2337
|
-
}
|
|
2338
|
-
case 'events': {
|
|
2339
|
-
if (helpRequested) {
|
|
2340
|
-
console.log(`
|
|
2341
|
-
eventmodeler codegen events - Generate deduplicated events for scaffolding
|
|
2342
|
-
|
|
2343
|
-
USAGE:
|
|
2344
|
-
eventmodeler codegen events [--chapter <chapter-name>]
|
|
2345
|
-
eventmodeler codegen events <chapter-name>
|
|
2346
|
-
|
|
2347
|
-
ARGUMENTS:
|
|
2348
|
-
<chapter-name> Optional chapter name (if omitted, all model events are returned)
|
|
2349
|
-
|
|
2350
|
-
OUTPUT:
|
|
2351
|
-
JSON payload including:
|
|
2352
|
-
- chapter hierarchy metadata (when chapter-scoped)
|
|
2353
|
-
- all relevant slices
|
|
2354
|
-
- deduplicated events across those slices
|
|
2355
|
-
- sourceSlices per event (where each event appears)
|
|
2356
|
-
|
|
2357
|
-
This is designed for event scaffolding flows (e.g. events.kt generation).
|
|
2358
|
-
|
|
2359
|
-
EXAMPLES:
|
|
2360
|
-
eventmodeler codegen events --chapter "Register Products"
|
|
2361
|
-
eventmodeler codegen events "Register Products"
|
|
2362
|
-
eventmodeler codegen events > model-events.json
|
|
2363
|
-
`);
|
|
2364
|
-
process.exit(0);
|
|
2365
|
-
}
|
|
2366
|
-
const chapterName = chapterArg ?? target;
|
|
2367
|
-
{
|
|
2368
|
-
const output = await api.codegenEvents(modelId, chapterName);
|
|
2369
|
-
console.log(JSON.stringify(output, null, 2));
|
|
2370
|
-
}
|
|
2371
|
-
break;
|
|
2372
|
-
}
|
|
2373
|
-
default:
|
|
2374
|
-
console.error(`Unknown codegen target: ${subcommand}`);
|
|
2375
|
-
console.error('Valid targets: slice, events');
|
|
2376
|
-
console.error('Run "eventmodeler codegen --help" for more information.');
|
|
2377
|
-
process.exit(1);
|
|
2378
|
-
}
|
|
2379
|
-
break;
|
|
2380
|
-
default:
|
|
2381
|
-
console.error(`Unknown command: ${command}`);
|
|
2382
|
-
printHelp();
|
|
2383
|
-
process.exit(1);
|
|
2384
|
-
}
|
|
2385
|
-
}
|
|
2386
|
-
main().catch((err) => {
|
|
9
|
+
import { setProgram } from './lib/globals';
|
|
10
|
+
import { registerAuthCommands } from './commands/auth';
|
|
11
|
+
import { registerInitCommands } from './commands/init';
|
|
12
|
+
import { registerGuideCommands } from './commands/guide';
|
|
13
|
+
import { registerListCommands } from './commands/list';
|
|
14
|
+
import { registerShowCommands } from './commands/show';
|
|
15
|
+
import { registerSearchCommands } from './commands/search';
|
|
16
|
+
import { registerSummaryCommands } from './commands/summary';
|
|
17
|
+
import { registerMarkCommands } from './commands/mark';
|
|
18
|
+
import { registerAddCommands } from './commands/add';
|
|
19
|
+
import { registerRemoveCommands } from './commands/remove';
|
|
20
|
+
import { registerRenameCommands } from './commands/rename';
|
|
21
|
+
import { registerMoveCommands } from './commands/move';
|
|
22
|
+
import { registerCreateCommands } from './commands/create';
|
|
23
|
+
import { registerUpdateCommands } from './commands/update';
|
|
24
|
+
import { registerMapCommands } from './commands/map';
|
|
25
|
+
import { registerDesignCommands } from './commands/design';
|
|
26
|
+
import { registerSetCommands } from './commands/set';
|
|
27
|
+
import { registerLoopCommands } from './commands/loop';
|
|
28
|
+
const program = new Command()
|
|
29
|
+
.name('eventmodeler')
|
|
30
|
+
.version(packageJson.version)
|
|
31
|
+
.description('CLI tool for interacting with Event Model files')
|
|
32
|
+
.option('--id <uuid>', 'Skip name resolution, use UUID directly');
|
|
33
|
+
setProgram(program);
|
|
34
|
+
// Register all commands
|
|
35
|
+
registerAuthCommands(program);
|
|
36
|
+
registerInitCommands(program);
|
|
37
|
+
registerGuideCommands(program);
|
|
38
|
+
registerListCommands(program);
|
|
39
|
+
registerShowCommands(program);
|
|
40
|
+
registerSearchCommands(program);
|
|
41
|
+
registerSummaryCommands(program);
|
|
42
|
+
registerMarkCommands(program);
|
|
43
|
+
registerAddCommands(program);
|
|
44
|
+
registerRemoveCommands(program);
|
|
45
|
+
registerRenameCommands(program);
|
|
46
|
+
registerMoveCommands(program);
|
|
47
|
+
registerCreateCommands(program);
|
|
48
|
+
registerUpdateCommands(program);
|
|
49
|
+
registerMapCommands(program);
|
|
50
|
+
registerDesignCommands(program);
|
|
51
|
+
registerSetCommands(program);
|
|
52
|
+
registerLoopCommands(program);
|
|
53
|
+
program.parseAsync(process.argv).catch((err) => {
|
|
2387
54
|
console.error('Error:', err.message);
|
|
2388
55
|
process.exit(1);
|
|
2389
56
|
});
|