eventmodeler 0.4.4 → 0.4.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/api/index.d.ts +282 -0
- package/dist/api/index.js +320 -0
- package/dist/index.js +256 -809
- package/dist/lib/config.d.ts +2 -1
- package/dist/lib/project-config.d.ts +0 -3
- package/dist/lib/project-config.js +1 -8
- package/dist/lib/slice-utils.d.ts +0 -79
- package/dist/lib/slice-utils.js +87 -237
- package/dist/projection.js +0 -30
- package/dist/slices/add-scenario/index.d.ts +0 -2
- package/dist/slices/add-scenario/index.js +120 -318
- package/dist/slices/init/index.d.ts +1 -0
- package/dist/slices/init/index.js +40 -93
- package/dist/slices/whoami/index.d.ts +1 -1
- package/dist/slices/whoami/index.js +19 -10
- package/package.json +5 -2
package/dist/index.js
CHANGED
|
@@ -2,61 +2,20 @@
|
|
|
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 { findEventModelFile, loadModel } from './lib/file-loader.js';
|
|
6
5
|
import { getDefaultFormat } from './lib/config.js';
|
|
7
6
|
const __filename = fileURLToPath(import.meta.url);
|
|
8
7
|
const __dirname = path.dirname(__filename);
|
|
9
8
|
const packageJson = JSON.parse(fs.readFileSync(path.join(__dirname, '..', 'package.json'), 'utf-8'));
|
|
10
9
|
const VERSION = packageJson.version;
|
|
11
|
-
//
|
|
12
|
-
import { listSlices } from './slices/list-slices/index.js';
|
|
13
|
-
import { listEvents } from './slices/list-events/index.js';
|
|
14
|
-
import { listCommands } from './slices/list-commands/index.js';
|
|
15
|
-
import { showSlice } from './slices/show-slice/index.js';
|
|
16
|
-
import { showEvent } from './slices/show-event/index.js';
|
|
17
|
-
import { showCommand } from './slices/show-command/index.js';
|
|
18
|
-
import { markSliceStatus } from './slices/mark-slice-status/index.js';
|
|
19
|
-
import { showModelSummary } from './slices/show-model-summary/index.js';
|
|
20
|
-
import { exportEventmodelToJson } from './slices/export-eventmodel-to-json/index.js';
|
|
10
|
+
// Utilities
|
|
21
11
|
import { openApp } from './slices/open-app/index.js';
|
|
22
|
-
import {
|
|
23
|
-
import { listChapters } from './slices/list-chapters/index.js';
|
|
24
|
-
import { showChapter } from './slices/show-chapter/index.js';
|
|
25
|
-
import { addScenario, parseScenarioInput } from './slices/add-scenario/index.js';
|
|
26
|
-
import { addField } from './slices/add-field/index.js';
|
|
27
|
-
import { removeScenario } from './slices/remove-scenario/index.js';
|
|
28
|
-
import { removeField } from './slices/remove-field/index.js';
|
|
29
|
-
import { showCompleteness, showModelCompleteness } from './slices/show-completeness/index.js';
|
|
30
|
-
import { mapFields } from './slices/map-fields/index.js';
|
|
31
|
-
import { updateField } from './slices/update-field/index.js';
|
|
32
|
-
import { showAggregateCompleteness, listAggregates } from './slices/show-aggregate-completeness/index.js';
|
|
33
|
-
import { showActor, listActors } from './slices/show-actor/index.js';
|
|
34
|
-
import { listReadModels } from './slices/list-readmodels/index.js';
|
|
35
|
-
import { listScreens } from './slices/list-screens/index.js';
|
|
36
|
-
import { listProcessors } from './slices/list-processors/index.js';
|
|
37
|
-
import { listScenarios } from './slices/list-scenarios/index.js';
|
|
38
|
-
import { showReadModel } from './slices/show-readmodel/index.js';
|
|
39
|
-
import { showScreen } from './slices/show-screen/index.js';
|
|
40
|
-
import { showProcessor } from './slices/show-processor/index.js';
|
|
41
|
-
import { showAggregate } from './slices/show-aggregate/index.js';
|
|
42
|
-
import { showScenario } from './slices/show-scenario/index.js';
|
|
43
|
-
import { createStateChangeSlice } from './slices/create-state-change-slice/index.js';
|
|
44
|
-
import { createAutomationSlice } from './slices/create-automation-slice/index.js';
|
|
45
|
-
import { createStateViewSlice } from './slices/create-state-view-slice/index.js';
|
|
46
|
-
import { createFlow } from './slices/create-flow/index.js';
|
|
47
|
-
import { codegenSlice } from './slices/codegen-slice/index.js';
|
|
48
|
-
import { codegenEvents } from './slices/codegen-chapter-events/index.js';
|
|
49
|
-
import { diff } from './slices/diff/index.js';
|
|
50
|
-
import { merge } from './slices/merge/index.js';
|
|
51
|
-
import { gitSetup, gitStatus } from './slices/git/index.js';
|
|
52
|
-
import { importModel } from './slices/import/index.js';
|
|
53
|
-
// Auth and cloud commands
|
|
12
|
+
import { parseScenarioInput } from './slices/add-scenario/index.js';
|
|
54
13
|
import { login } from './slices/login/index.js';
|
|
55
14
|
import { logout } from './slices/logout/index.js';
|
|
56
15
|
import { whoami } from './slices/whoami/index.js';
|
|
57
16
|
import { init } from './slices/init/index.js';
|
|
58
|
-
|
|
59
|
-
import
|
|
17
|
+
import * as api from './api/index.js';
|
|
18
|
+
import { XMLBuilder, XMLParser } from 'fast-xml-parser';
|
|
60
19
|
import { loadProjectConfig } from './lib/project-config.js';
|
|
61
20
|
const args = process.argv.slice(2);
|
|
62
21
|
function getNamedArg(argList, ...names) {
|
|
@@ -95,7 +54,7 @@ AUTHENTICATION:
|
|
|
95
54
|
whoami Show authentication status
|
|
96
55
|
|
|
97
56
|
PROJECT SETUP:
|
|
98
|
-
init Initialize project (link to
|
|
57
|
+
init Initialize project (link to a model)
|
|
99
58
|
|
|
100
59
|
COMMANDS:
|
|
101
60
|
list slices [--chapter <name>] List all slices (optionally filtered by chapter)
|
|
@@ -115,8 +74,9 @@ COMMANDS:
|
|
|
115
74
|
show command <name> Show detailed XML view of a command
|
|
116
75
|
show chapter <name> Show chapter with slices, flow graph, and
|
|
117
76
|
external dependencies
|
|
118
|
-
show completeness
|
|
119
|
-
show
|
|
77
|
+
show information-completeness Show information completeness of all flows
|
|
78
|
+
show information-completeness <name>
|
|
79
|
+
Show field mapping completeness for an element
|
|
120
80
|
show aggregate-completeness <name>
|
|
121
81
|
Show if events in aggregate have the ID field
|
|
122
82
|
show actor <name> Show actor with its screens
|
|
@@ -133,18 +93,18 @@ COMMANDS:
|
|
|
133
93
|
|
|
134
94
|
add scenario --slice <name> --json|--xml <data>
|
|
135
95
|
Add a scenario to a slice
|
|
136
|
-
add field
|
|
96
|
+
add field <element-name> --json|--xml <data>
|
|
137
97
|
Add a field to an entity
|
|
138
98
|
|
|
139
99
|
remove scenario <name> [--slice <name>]
|
|
140
100
|
Remove a scenario by name
|
|
141
|
-
remove field
|
|
101
|
+
remove field <element-name> --field <name>
|
|
142
102
|
Remove a field from an entity
|
|
143
103
|
|
|
144
104
|
map fields --flow <source→target> --json|--xml <mappings>
|
|
145
105
|
Set field mappings on a flow
|
|
146
106
|
|
|
147
|
-
update field
|
|
107
|
+
update field <element-name> --field <name> [--optional true|false] [--generated true|false] [--user-input true|false]
|
|
148
108
|
Update field properties
|
|
149
109
|
|
|
150
110
|
create state-change-slice --xml <data>
|
|
@@ -164,27 +124,7 @@ COMMANDS:
|
|
|
164
124
|
|
|
165
125
|
export json Export entire model as JSON
|
|
166
126
|
|
|
167
|
-
IMPORT/EXPORT:
|
|
168
|
-
import <file> [--name <name>] Import .eventmodel file to cloud (creates new model)
|
|
169
|
-
|
|
170
|
-
GIT INTEGRATION:
|
|
171
|
-
git setup Configure git to use semantic diff/merge for .eventmodel files
|
|
172
|
-
git setup --global Configure globally (for all repos)
|
|
173
|
-
git status Show git integration status
|
|
174
|
-
|
|
175
|
-
diff <file1> <file2> Compare two event model files semantically
|
|
176
|
-
diff <file> [--ref <gitref>] Compare working copy against git ref (default: HEAD)
|
|
177
|
-
diff ... --format text Human-readable output (default for git)
|
|
178
|
-
diff ... --format xml|json Structured output
|
|
179
|
-
|
|
180
|
-
merge --base <file> --ours <file> --theirs <file> --output <file>
|
|
181
|
-
Three-way merge of event model files
|
|
182
|
-
merge ... --strategy ours|theirs
|
|
183
|
-
Auto-resolve conflicts with given strategy
|
|
184
|
-
merge ... --dry-run Show conflicts without writing output
|
|
185
|
-
|
|
186
127
|
OPTIONS:
|
|
187
|
-
-f, --file <path> Path to .eventmodel file (default: auto-detect)
|
|
188
128
|
--format <xml|json> Output format (default: xml, or from config)
|
|
189
129
|
-h, --help Show this help message
|
|
190
130
|
-v, --version Show version number
|
|
@@ -199,25 +139,21 @@ EXAMPLES:
|
|
|
199
139
|
eventmodeler show slice "Place Order"
|
|
200
140
|
eventmodeler mark "Place Order" done
|
|
201
141
|
eventmodeler add scenario --slice "Place Order" --json '{"name": "Happy path", "then": {"type": "events", "events": []}}'
|
|
202
|
-
eventmodeler add field
|
|
203
|
-
eventmodeler remove field
|
|
204
|
-
eventmodeler show completeness
|
|
205
|
-
eventmodeler show
|
|
142
|
+
eventmodeler add field "OrderPlaced" --json '{"name": "orderId", "type": "UUID"}'
|
|
143
|
+
eventmodeler remove field "OrderPlaced" --field "orderId"
|
|
144
|
+
eventmodeler show information-completeness
|
|
145
|
+
eventmodeler show information-completeness "OrderSummary"
|
|
206
146
|
eventmodeler map fields --flow "OrderPlaced→OrderSummary" --json '[{"from": "total", "to": "totalAmount"}]'
|
|
207
|
-
eventmodeler update field
|
|
147
|
+
eventmodeler update field "OrderSummary" --field "notes" --optional true
|
|
208
148
|
`);
|
|
209
149
|
}
|
|
210
150
|
async function main() {
|
|
211
|
-
let fileArg = null;
|
|
212
151
|
let formatArg = null;
|
|
213
152
|
let chapterArg = null;
|
|
214
153
|
const filteredArgs = [];
|
|
215
154
|
let helpRequested = false;
|
|
216
155
|
for (let i = 0; i < args.length; i++) {
|
|
217
|
-
if (args[i] === '
|
|
218
|
-
fileArg = args[++i];
|
|
219
|
-
}
|
|
220
|
-
else if (args[i] === '--format') {
|
|
156
|
+
if (args[i] === '--format') {
|
|
221
157
|
formatArg = args[++i];
|
|
222
158
|
}
|
|
223
159
|
else if (args[i] === '--chapter') {
|
|
@@ -254,144 +190,6 @@ async function main() {
|
|
|
254
190
|
openApp();
|
|
255
191
|
return;
|
|
256
192
|
}
|
|
257
|
-
// Handle diff and merge commands separately (they manage their own file loading)
|
|
258
|
-
if (command === 'diff') {
|
|
259
|
-
if (helpRequested) {
|
|
260
|
-
console.log(`
|
|
261
|
-
eventmodeler diff - Compare event model files semantically
|
|
262
|
-
|
|
263
|
-
USAGE:
|
|
264
|
-
eventmodeler diff <file1> <file2> [--format text|xml|json]
|
|
265
|
-
eventmodeler diff <file> [--ref <gitref>] [--format text|xml|json]
|
|
266
|
-
eventmodeler diff --base <file> --compare <file> [--format text|xml|json]
|
|
267
|
-
|
|
268
|
-
ARGUMENTS:
|
|
269
|
-
<file1> <file2> Two files to compare
|
|
270
|
-
<file> Single file to compare against git ref
|
|
271
|
-
|
|
272
|
-
OPTIONS:
|
|
273
|
-
--ref <gitref> Git reference to compare against (default: HEAD)
|
|
274
|
-
--base <file> Base file (alternative syntax)
|
|
275
|
-
--compare <file> Compare file (alternative syntax)
|
|
276
|
-
--format <format> Output format: text (default), xml, or json
|
|
277
|
-
|
|
278
|
-
OUTPUT:
|
|
279
|
-
Semantic differences between models:
|
|
280
|
-
- Added/removed/modified entities
|
|
281
|
-
- Field changes (with flag changes like isGenerated)
|
|
282
|
-
- Flow changes
|
|
283
|
-
- Scenario changes
|
|
284
|
-
|
|
285
|
-
Unlike line-based diff, this understands event model structure.
|
|
286
|
-
|
|
287
|
-
EXAMPLES:
|
|
288
|
-
eventmodeler diff model-v1.eventmodel model-v2.eventmodel
|
|
289
|
-
eventmodeler diff mymodel.eventmodel --ref HEAD~1
|
|
290
|
-
eventmodeler diff mymodel.eventmodel --ref main
|
|
291
|
-
eventmodeler diff model.eventmodel --format json
|
|
292
|
-
`);
|
|
293
|
-
process.exit(0);
|
|
294
|
-
}
|
|
295
|
-
const baseArg = getNamedArg(filteredArgs, '--base');
|
|
296
|
-
const compareArg = getNamedArg(filteredArgs, '--compare');
|
|
297
|
-
const refArg = getNamedArg(filteredArgs, '--ref');
|
|
298
|
-
// Diff supports 'text' format in addition to xml/json
|
|
299
|
-
const diffFormat = formatArg === 'json' ? 'json'
|
|
300
|
-
: formatArg === 'xml' ? 'xml'
|
|
301
|
-
: formatArg === 'text' ? 'text'
|
|
302
|
-
: 'text'; // Default to text for human-readable output
|
|
303
|
-
// Two-file mode: diff file1 file2 OR diff --base file1 --compare file2
|
|
304
|
-
if (baseArg && compareArg) {
|
|
305
|
-
diff(baseArg, compareArg, diffFormat);
|
|
306
|
-
return;
|
|
307
|
-
}
|
|
308
|
-
// Positional args: diff file1 file2
|
|
309
|
-
const file1 = filteredArgs[1];
|
|
310
|
-
const file2 = filteredArgs[2];
|
|
311
|
-
if (file1 && file2 && !file1.startsWith('--') && !file2.startsWith('--')) {
|
|
312
|
-
diff(file1, file2, diffFormat);
|
|
313
|
-
return;
|
|
314
|
-
}
|
|
315
|
-
// Single file mode: diff file [--ref HEAD]
|
|
316
|
-
if (file1 && !file1.startsWith('--')) {
|
|
317
|
-
diff(file1, undefined, diffFormat, refArg);
|
|
318
|
-
return;
|
|
319
|
-
}
|
|
320
|
-
console.error('Usage: eventmodeler diff <file1> <file2>');
|
|
321
|
-
console.error(' eventmodeler diff <file> [--ref <gitref>]');
|
|
322
|
-
console.error(' eventmodeler diff --base <file> --compare <file>');
|
|
323
|
-
console.error('Run "eventmodeler diff --help" for more information.');
|
|
324
|
-
process.exit(1);
|
|
325
|
-
}
|
|
326
|
-
if (command === 'merge') {
|
|
327
|
-
if (helpRequested) {
|
|
328
|
-
console.log(`
|
|
329
|
-
eventmodeler merge - Three-way merge of event model files
|
|
330
|
-
|
|
331
|
-
USAGE:
|
|
332
|
-
eventmodeler merge --base <file> --ours <file> --theirs <file> --output <file>
|
|
333
|
-
|
|
334
|
-
OPTIONS:
|
|
335
|
-
--base <file> Common ancestor file (required)
|
|
336
|
-
--ours <file> Our version file (required)
|
|
337
|
-
--theirs <file> Their version file (required)
|
|
338
|
-
--output <file> Output file path (required unless --dry-run)
|
|
339
|
-
--strategy <s> Auto-resolve conflicts: ours or theirs
|
|
340
|
-
--dry-run Show result without writing file
|
|
341
|
-
--format xml|json Output format for conflict reporting
|
|
342
|
-
|
|
343
|
-
HOW IT WORKS:
|
|
344
|
-
Performs semantic three-way merge:
|
|
345
|
-
1. Identifies changes in "ours" vs base
|
|
346
|
-
2. Identifies changes in "theirs" vs base
|
|
347
|
-
3. Auto-merges non-conflicting changes
|
|
348
|
-
4. Reports conflicts for manual resolution
|
|
349
|
-
|
|
350
|
-
CONFLICT RESOLUTION:
|
|
351
|
-
--strategy ours Keep our changes when conflicts occur
|
|
352
|
-
--strategy theirs Keep their changes when conflicts occur
|
|
353
|
-
|
|
354
|
-
EXAMPLES:
|
|
355
|
-
# Standard merge
|
|
356
|
-
eventmodeler merge --base base.eventmodel --ours mine.eventmodel --theirs theirs.eventmodel --output merged.eventmodel
|
|
357
|
-
|
|
358
|
-
# Auto-resolve with our changes taking precedence
|
|
359
|
-
eventmodeler merge --base base.eventmodel --ours mine.eventmodel --theirs theirs.eventmodel --output merged.eventmodel --strategy ours
|
|
360
|
-
|
|
361
|
-
# Preview merge without writing
|
|
362
|
-
eventmodeler merge --base base.eventmodel --ours mine.eventmodel --theirs theirs.eventmodel --dry-run
|
|
363
|
-
`);
|
|
364
|
-
process.exit(0);
|
|
365
|
-
}
|
|
366
|
-
const baseArg = getNamedArg(filteredArgs, '--base');
|
|
367
|
-
const oursArg = getNamedArg(filteredArgs, '--ours');
|
|
368
|
-
const theirsArg = getNamedArg(filteredArgs, '--theirs');
|
|
369
|
-
const outputArg = getNamedArg(filteredArgs, '--output');
|
|
370
|
-
const strategyArg = getNamedArg(filteredArgs, '--strategy');
|
|
371
|
-
const dryRun = filteredArgs.includes('--dry-run');
|
|
372
|
-
if (!baseArg || !oursArg || !theirsArg) {
|
|
373
|
-
console.error('Usage: eventmodeler merge --base <file> --ours <file> --theirs <file> --output <file>');
|
|
374
|
-
console.error('Options:');
|
|
375
|
-
console.error(' --strategy ours|theirs Auto-resolve conflicts');
|
|
376
|
-
console.error(' --dry-run Show result without writing');
|
|
377
|
-
console.error('Run "eventmodeler merge --help" for more information.');
|
|
378
|
-
process.exit(1);
|
|
379
|
-
}
|
|
380
|
-
if (!outputArg && !dryRun) {
|
|
381
|
-
console.error('Error: --output is required (or use --dry-run)');
|
|
382
|
-
process.exit(1);
|
|
383
|
-
}
|
|
384
|
-
merge({
|
|
385
|
-
basePath: baseArg,
|
|
386
|
-
oursPath: oursArg,
|
|
387
|
-
theirsPath: theirsArg,
|
|
388
|
-
outputPath: outputArg ?? '',
|
|
389
|
-
strategy: strategyArg === 'ours' || strategyArg === 'theirs' ? strategyArg : undefined,
|
|
390
|
-
dryRun,
|
|
391
|
-
format,
|
|
392
|
-
});
|
|
393
|
-
return;
|
|
394
|
-
}
|
|
395
193
|
// Auth commands (no file needed)
|
|
396
194
|
if (command === 'login') {
|
|
397
195
|
if (helpRequested) {
|
|
@@ -405,8 +203,7 @@ Opens your browser for authentication via Keycloak.
|
|
|
405
203
|
Credentials are stored securely in ~/.eventmodeler/config.json
|
|
406
204
|
|
|
407
205
|
After login, you can:
|
|
408
|
-
- Use "eventmodeler init" to connect a project to a
|
|
409
|
-
- Access cloud-hosted event models
|
|
206
|
+
- Use "eventmodeler init" to connect a project to a model
|
|
410
207
|
|
|
411
208
|
EXAMPLES:
|
|
412
209
|
eventmodeler login
|
|
@@ -468,12 +265,8 @@ USAGE:
|
|
|
468
265
|
Interactive setup to connect this directory to an event model.
|
|
469
266
|
Creates a .eventmodeler.json config file in your project root.
|
|
470
267
|
|
|
471
|
-
OPTIONS:
|
|
472
|
-
1. Cloud - Link to an event model on eventmodeler.app
|
|
473
|
-
2. Local - Use a local .eventmodel file
|
|
474
|
-
|
|
475
268
|
PREREQUISITES:
|
|
476
|
-
-
|
|
269
|
+
- You must be logged in (run "eventmodeler login" first)
|
|
477
270
|
|
|
478
271
|
EXAMPLES:
|
|
479
272
|
cd my-project
|
|
@@ -484,151 +277,13 @@ EXAMPLES:
|
|
|
484
277
|
await init();
|
|
485
278
|
return;
|
|
486
279
|
}
|
|
487
|
-
if (command === 'import') {
|
|
488
|
-
if (helpRequested) {
|
|
489
|
-
console.log(`
|
|
490
|
-
eventmodeler import - Import .eventmodel file to cloud
|
|
491
|
-
|
|
492
|
-
USAGE:
|
|
493
|
-
eventmodeler import <file> [--name <name>]
|
|
494
|
-
|
|
495
|
-
ARGUMENTS:
|
|
496
|
-
<file> Path to .eventmodel file to import
|
|
497
|
-
|
|
498
|
-
OPTIONS:
|
|
499
|
-
--name <name> Override model name (default: derived from file or EventModelCreated event)
|
|
500
|
-
|
|
501
|
-
DESCRIPTION:
|
|
502
|
-
Imports a local .eventmodel file to the cloud backend, creating a new
|
|
503
|
-
cloud-hosted model. All events are preserved except EventModelCreated,
|
|
504
|
-
which is regenerated with a new modelId.
|
|
505
|
-
|
|
506
|
-
PREREQUISITES:
|
|
507
|
-
- Must be logged in (run "eventmodeler login" first)
|
|
508
|
-
|
|
509
|
-
EXAMPLES:
|
|
510
|
-
eventmodeler import mymodel.eventmodel
|
|
511
|
-
eventmodeler import ./models/order-system.eventmodel --name "Order System"
|
|
512
|
-
`);
|
|
513
|
-
process.exit(0);
|
|
514
|
-
}
|
|
515
|
-
const importFilePath = subcommand;
|
|
516
|
-
if (!importFilePath) {
|
|
517
|
-
console.error('Usage: eventmodeler import <file> [--name <name>]');
|
|
518
|
-
console.error('Run "eventmodeler import --help" for more information.');
|
|
519
|
-
process.exit(1);
|
|
520
|
-
}
|
|
521
|
-
const importName = getNamedArg(filteredArgs, '--name', '-n');
|
|
522
|
-
await importModel(importFilePath, { name: importName });
|
|
523
|
-
return;
|
|
524
|
-
}
|
|
525
|
-
if (command === 'git') {
|
|
526
|
-
const gitCommand = filteredArgs[1];
|
|
527
|
-
const globalFlag = filteredArgs.includes('--global');
|
|
528
|
-
if (helpRequested && !gitCommand) {
|
|
529
|
-
console.log(`
|
|
530
|
-
eventmodeler git - Git integration commands
|
|
531
|
-
|
|
532
|
-
USAGE:
|
|
533
|
-
eventmodeler git <command> [options]
|
|
534
|
-
|
|
535
|
-
COMMANDS:
|
|
536
|
-
setup Configure git for semantic diff/merge of .eventmodel files
|
|
537
|
-
status Show current git integration status
|
|
538
|
-
|
|
539
|
-
Run "eventmodeler git <command> --help" for command-specific help.
|
|
540
|
-
`);
|
|
541
|
-
process.exit(0);
|
|
542
|
-
}
|
|
543
|
-
switch (gitCommand) {
|
|
544
|
-
case 'setup':
|
|
545
|
-
if (helpRequested) {
|
|
546
|
-
console.log(`
|
|
547
|
-
eventmodeler git setup - Configure git for semantic diff/merge
|
|
548
|
-
|
|
549
|
-
USAGE:
|
|
550
|
-
eventmodeler git setup [--global]
|
|
551
|
-
|
|
552
|
-
OPTIONS:
|
|
553
|
-
--global Configure globally (for all repositories)
|
|
554
|
-
|
|
555
|
-
WHAT IT DOES:
|
|
556
|
-
1. Adds .gitattributes entry: *.eventmodel diff=eventmodel merge=eventmodel
|
|
557
|
-
2. Configures git diff driver for semantic comparison
|
|
558
|
-
3. Configures git merge driver for semantic merging
|
|
559
|
-
|
|
560
|
-
After setup:
|
|
561
|
-
- "git diff" shows semantic differences for .eventmodel files
|
|
562
|
-
- "git merge" performs semantic merging
|
|
563
|
-
- Conflicts are reported at entity level, not line level
|
|
564
|
-
|
|
565
|
-
LOCAL VS GLOBAL:
|
|
566
|
-
Without --global: Configures current repository only
|
|
567
|
-
With --global: Configures for all repositories (user-level)
|
|
568
|
-
|
|
569
|
-
EXAMPLES:
|
|
570
|
-
eventmodeler git setup # Configure current repo
|
|
571
|
-
eventmodeler git setup --global # Configure globally
|
|
572
|
-
`);
|
|
573
|
-
process.exit(0);
|
|
574
|
-
}
|
|
575
|
-
gitSetup(globalFlag);
|
|
576
|
-
return;
|
|
577
|
-
case 'status':
|
|
578
|
-
if (helpRequested) {
|
|
579
|
-
console.log(`
|
|
580
|
-
eventmodeler git status - Show git integration status
|
|
581
|
-
|
|
582
|
-
USAGE:
|
|
583
|
-
eventmodeler git status
|
|
584
|
-
|
|
585
|
-
OUTPUT:
|
|
586
|
-
Shows current configuration:
|
|
587
|
-
- Whether git drivers are configured
|
|
588
|
-
- Local vs global configuration status
|
|
589
|
-
- .gitattributes configuration status
|
|
590
|
-
|
|
591
|
-
EXAMPLES:
|
|
592
|
-
eventmodeler git status
|
|
593
|
-
`);
|
|
594
|
-
process.exit(0);
|
|
595
|
-
}
|
|
596
|
-
gitStatus();
|
|
597
|
-
return;
|
|
598
|
-
default:
|
|
599
|
-
console.error('Usage: eventmodeler git setup [--global]');
|
|
600
|
-
console.error(' eventmodeler git status');
|
|
601
|
-
console.error('Run "eventmodeler git --help" for more information.');
|
|
602
|
-
process.exit(1);
|
|
603
|
-
}
|
|
604
|
-
}
|
|
605
|
-
// Determine backend mode: cloud or local
|
|
606
280
|
const projectConfig = loadProjectConfig();
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
let model = null;
|
|
612
|
-
let filePath = null;
|
|
613
|
-
if (!isCloudMode) {
|
|
614
|
-
// Local mode - load model from file
|
|
615
|
-
if (projectConfig?.type === 'local') {
|
|
616
|
-
filePath = fileArg ?? projectConfig.file;
|
|
617
|
-
}
|
|
618
|
-
else {
|
|
619
|
-
filePath = fileArg ?? await findEventModelFile();
|
|
620
|
-
}
|
|
621
|
-
if (!filePath) {
|
|
622
|
-
console.error('Error: No .eventmodel file found in current directory.');
|
|
623
|
-
console.error('Use -f <path> to specify a file or run "eventmodeler init" to set up a project.');
|
|
624
|
-
process.exit(1);
|
|
625
|
-
}
|
|
626
|
-
if (!fs.existsSync(filePath)) {
|
|
627
|
-
console.error(`Error: File not found: ${filePath}`);
|
|
628
|
-
process.exit(1);
|
|
629
|
-
}
|
|
630
|
-
model = loadModel(filePath);
|
|
281
|
+
if (!projectConfig || projectConfig.type !== 'cloud') {
|
|
282
|
+
console.error('Error: No project configured.');
|
|
283
|
+
console.error('Run "eventmodeler init" to connect this directory to a model.');
|
|
284
|
+
process.exit(1);
|
|
631
285
|
}
|
|
286
|
+
const modelId = projectConfig.modelId;
|
|
632
287
|
switch (command) {
|
|
633
288
|
case 'list':
|
|
634
289
|
if (helpRequested && !subcommand) {
|
|
@@ -688,13 +343,10 @@ EXAMPLES:
|
|
|
688
343
|
`);
|
|
689
344
|
process.exit(0);
|
|
690
345
|
}
|
|
691
|
-
|
|
692
|
-
const output = await
|
|
346
|
+
{
|
|
347
|
+
const output = await api.listSlices(modelId, format, chapterArg ?? undefined);
|
|
693
348
|
console.log(output);
|
|
694
349
|
}
|
|
695
|
-
else {
|
|
696
|
-
listSlices(model, format, chapterArg ?? undefined);
|
|
697
|
-
}
|
|
698
350
|
break;
|
|
699
351
|
case 'events':
|
|
700
352
|
if (helpRequested) {
|
|
@@ -719,13 +371,10 @@ EXAMPLES:
|
|
|
719
371
|
`);
|
|
720
372
|
process.exit(0);
|
|
721
373
|
}
|
|
722
|
-
|
|
723
|
-
const output = await
|
|
374
|
+
{
|
|
375
|
+
const output = await api.listEvents(modelId, format);
|
|
724
376
|
console.log(output);
|
|
725
377
|
}
|
|
726
|
-
else {
|
|
727
|
-
listEvents(model, format);
|
|
728
|
-
}
|
|
729
378
|
break;
|
|
730
379
|
case 'commands':
|
|
731
380
|
if (helpRequested) {
|
|
@@ -748,13 +397,10 @@ EXAMPLES:
|
|
|
748
397
|
`);
|
|
749
398
|
process.exit(0);
|
|
750
399
|
}
|
|
751
|
-
|
|
752
|
-
const output = await
|
|
400
|
+
{
|
|
401
|
+
const output = await api.listCommands(modelId, format);
|
|
753
402
|
console.log(output);
|
|
754
403
|
}
|
|
755
|
-
else {
|
|
756
|
-
listCommands(model, format);
|
|
757
|
-
}
|
|
758
404
|
break;
|
|
759
405
|
case 'chapters':
|
|
760
406
|
if (helpRequested) {
|
|
@@ -777,13 +423,10 @@ EXAMPLES:
|
|
|
777
423
|
`);
|
|
778
424
|
process.exit(0);
|
|
779
425
|
}
|
|
780
|
-
|
|
781
|
-
const output = await
|
|
426
|
+
{
|
|
427
|
+
const output = await api.listChapters(modelId, format);
|
|
782
428
|
console.log(output);
|
|
783
429
|
}
|
|
784
|
-
else {
|
|
785
|
-
listChapters(model, format);
|
|
786
|
-
}
|
|
787
430
|
break;
|
|
788
431
|
case 'aggregates':
|
|
789
432
|
if (helpRequested) {
|
|
@@ -807,13 +450,10 @@ EXAMPLES:
|
|
|
807
450
|
`);
|
|
808
451
|
process.exit(0);
|
|
809
452
|
}
|
|
810
|
-
|
|
811
|
-
const result = await
|
|
453
|
+
{
|
|
454
|
+
const result = await api.listAggregates(modelId, format);
|
|
812
455
|
console.log(result);
|
|
813
456
|
}
|
|
814
|
-
else {
|
|
815
|
-
listAggregates(model, format);
|
|
816
|
-
}
|
|
817
457
|
break;
|
|
818
458
|
case 'actors':
|
|
819
459
|
if (helpRequested) {
|
|
@@ -836,12 +476,10 @@ EXAMPLES:
|
|
|
836
476
|
`);
|
|
837
477
|
process.exit(0);
|
|
838
478
|
}
|
|
839
|
-
|
|
840
|
-
const output = await
|
|
479
|
+
{
|
|
480
|
+
const output = await api.listActors(modelId, format);
|
|
841
481
|
console.log(output);
|
|
842
|
-
break;
|
|
843
482
|
}
|
|
844
|
-
listActors(model, format);
|
|
845
483
|
break;
|
|
846
484
|
case 'readmodels':
|
|
847
485
|
if (helpRequested) {
|
|
@@ -861,12 +499,10 @@ EXAMPLES:
|
|
|
861
499
|
`);
|
|
862
500
|
process.exit(0);
|
|
863
501
|
}
|
|
864
|
-
|
|
865
|
-
const output = await
|
|
502
|
+
{
|
|
503
|
+
const output = await api.listReadModels(modelId, format);
|
|
866
504
|
console.log(output);
|
|
867
|
-
break;
|
|
868
505
|
}
|
|
869
|
-
listReadModels(model, format);
|
|
870
506
|
break;
|
|
871
507
|
case 'screens':
|
|
872
508
|
if (helpRequested) {
|
|
@@ -886,12 +522,10 @@ EXAMPLES:
|
|
|
886
522
|
`);
|
|
887
523
|
process.exit(0);
|
|
888
524
|
}
|
|
889
|
-
|
|
890
|
-
const output = await
|
|
525
|
+
{
|
|
526
|
+
const output = await api.listScreens(modelId, format);
|
|
891
527
|
console.log(output);
|
|
892
|
-
break;
|
|
893
528
|
}
|
|
894
|
-
listScreens(model, format);
|
|
895
529
|
break;
|
|
896
530
|
case 'processors':
|
|
897
531
|
if (helpRequested) {
|
|
@@ -910,12 +544,10 @@ EXAMPLES:
|
|
|
910
544
|
`);
|
|
911
545
|
process.exit(0);
|
|
912
546
|
}
|
|
913
|
-
|
|
914
|
-
const output = await
|
|
547
|
+
{
|
|
548
|
+
const output = await api.listProcessors(modelId, format);
|
|
915
549
|
console.log(output);
|
|
916
|
-
break;
|
|
917
550
|
}
|
|
918
|
-
listProcessors(model, format);
|
|
919
551
|
break;
|
|
920
552
|
case 'scenarios':
|
|
921
553
|
if (helpRequested) {
|
|
@@ -936,12 +568,10 @@ EXAMPLES:
|
|
|
936
568
|
`);
|
|
937
569
|
process.exit(0);
|
|
938
570
|
}
|
|
939
|
-
|
|
940
|
-
const output = await
|
|
571
|
+
{
|
|
572
|
+
const output = await api.listScenarios(modelId, format);
|
|
941
573
|
console.log(output);
|
|
942
|
-
break;
|
|
943
574
|
}
|
|
944
|
-
listScenarios(model, format);
|
|
945
575
|
break;
|
|
946
576
|
default:
|
|
947
577
|
console.error(`Unknown list target: ${subcommand}`);
|
|
@@ -963,8 +593,8 @@ TYPES:
|
|
|
963
593
|
event Show event with all fields
|
|
964
594
|
command Show command with all fields
|
|
965
595
|
chapter Show chapter with slices and dependencies
|
|
966
|
-
completeness
|
|
967
|
-
|
|
596
|
+
information-completeness Show information completeness of all flows
|
|
597
|
+
(with element name: show per-element completeness)
|
|
968
598
|
aggregate-completeness Show if events have aggregate ID field
|
|
969
599
|
actor Show actor with screens
|
|
970
600
|
readmodel Show read model with fields and flows
|
|
@@ -979,7 +609,7 @@ OPTIONS:
|
|
|
979
609
|
EXAMPLES:
|
|
980
610
|
eventmodeler show slice "Place Order"
|
|
981
611
|
eventmodeler show event OrderPlaced
|
|
982
|
-
eventmodeler show completeness OrderSummary
|
|
612
|
+
eventmodeler show information-completeness OrderSummary
|
|
983
613
|
|
|
984
614
|
Run "eventmodeler show <type> --help" for type-specific help.
|
|
985
615
|
`);
|
|
@@ -1018,13 +648,10 @@ EXAMPLES:
|
|
|
1018
648
|
console.error('Run "eventmodeler show slice --help" for more information.');
|
|
1019
649
|
process.exit(1);
|
|
1020
650
|
}
|
|
1021
|
-
|
|
1022
|
-
const result = await
|
|
651
|
+
{
|
|
652
|
+
const result = await api.showSlice(modelId, target, format);
|
|
1023
653
|
console.log(result);
|
|
1024
654
|
}
|
|
1025
|
-
else {
|
|
1026
|
-
showSlice(model, target, format);
|
|
1027
|
-
}
|
|
1028
655
|
break;
|
|
1029
656
|
case 'event':
|
|
1030
657
|
if (helpRequested) {
|
|
@@ -1066,13 +693,10 @@ EXAMPLES:
|
|
|
1066
693
|
console.error('Run "eventmodeler show event --help" for more information.');
|
|
1067
694
|
process.exit(1);
|
|
1068
695
|
}
|
|
1069
|
-
|
|
1070
|
-
const result = await
|
|
696
|
+
{
|
|
697
|
+
const result = await api.showEvent(modelId, target, format);
|
|
1071
698
|
console.log(result);
|
|
1072
699
|
}
|
|
1073
|
-
else {
|
|
1074
|
-
showEvent(model, target, format);
|
|
1075
|
-
}
|
|
1076
700
|
break;
|
|
1077
701
|
case 'command':
|
|
1078
702
|
if (helpRequested) {
|
|
@@ -1100,13 +724,10 @@ EXAMPLES:
|
|
|
1100
724
|
console.error('Run "eventmodeler show command --help" for more information.');
|
|
1101
725
|
process.exit(1);
|
|
1102
726
|
}
|
|
1103
|
-
|
|
1104
|
-
const result = await
|
|
727
|
+
{
|
|
728
|
+
const result = await api.showCommand(modelId, target, format);
|
|
1105
729
|
console.log(result);
|
|
1106
730
|
}
|
|
1107
|
-
else {
|
|
1108
|
-
showCommand(model, target, format);
|
|
1109
|
-
}
|
|
1110
731
|
break;
|
|
1111
732
|
case 'chapter':
|
|
1112
733
|
if (helpRequested) {
|
|
@@ -1135,26 +756,28 @@ EXAMPLES:
|
|
|
1135
756
|
console.error('Run "eventmodeler show chapter --help" for more information.');
|
|
1136
757
|
process.exit(1);
|
|
1137
758
|
}
|
|
1138
|
-
|
|
1139
|
-
const result = await
|
|
759
|
+
{
|
|
760
|
+
const result = await api.showChapter(modelId, target, format);
|
|
1140
761
|
console.log(result);
|
|
1141
762
|
}
|
|
1142
|
-
else {
|
|
1143
|
-
showChapter(model, target, format);
|
|
1144
|
-
}
|
|
1145
763
|
break;
|
|
1146
|
-
case 'completeness':
|
|
764
|
+
case 'information-completeness':
|
|
1147
765
|
if (helpRequested) {
|
|
1148
766
|
console.log(`
|
|
1149
|
-
eventmodeler show completeness - Show
|
|
767
|
+
eventmodeler show information-completeness - Show information completeness
|
|
1150
768
|
|
|
1151
769
|
USAGE:
|
|
1152
|
-
eventmodeler show completeness
|
|
770
|
+
eventmodeler show information-completeness [--format xml|json]
|
|
771
|
+
eventmodeler show information-completeness --slice "Place Order"
|
|
772
|
+
eventmodeler show information-completeness --chapter "Ordering"
|
|
773
|
+
eventmodeler show information-completeness <element-name> [--format xml|json]
|
|
1153
774
|
|
|
1154
|
-
|
|
1155
|
-
|
|
775
|
+
OUTPUT INCLUDES (model-wide):
|
|
776
|
+
- Summary of complete/incomplete flows across the whole model
|
|
777
|
+
- Incomplete flows grouped by slice, with untraceable fields
|
|
778
|
+
- Incomplete read models with untraceable fields and source events
|
|
1156
779
|
|
|
1157
|
-
OUTPUT INCLUDES:
|
|
780
|
+
OUTPUT INCLUDES (per-element):
|
|
1158
781
|
- Total fields vs mapped fields
|
|
1159
782
|
- List of unmapped fields needing attention
|
|
1160
783
|
- Mapping sources for mapped fields
|
|
@@ -1164,53 +787,31 @@ IMPORTANT - GENERATED FIELDS:
|
|
|
1164
787
|
Generated fields are computed/synthesized values that don't need
|
|
1165
788
|
source mappings (e.g., calculated totals, timestamps, derived data).
|
|
1166
789
|
|
|
1167
|
-
|
|
1168
|
-
|
|
1169
|
-
eventmodeler show completeness "Order Summary" --format json
|
|
1170
|
-
`);
|
|
1171
|
-
process.exit(0);
|
|
1172
|
-
}
|
|
1173
|
-
if (!target) {
|
|
1174
|
-
console.error('Usage: eventmodeler show completeness <element-name>');
|
|
1175
|
-
console.error('Searches: commands, events, read models, screens, processors');
|
|
1176
|
-
console.error('Run "eventmodeler show completeness --help" for more information.');
|
|
1177
|
-
process.exit(1);
|
|
1178
|
-
}
|
|
1179
|
-
if (isCloudMode) {
|
|
1180
|
-
const result = await cloudSlices.showCompleteness(modelId, target, format);
|
|
1181
|
-
console.log(result);
|
|
1182
|
-
}
|
|
1183
|
-
else {
|
|
1184
|
-
showCompleteness(model, target, format);
|
|
1185
|
-
}
|
|
1186
|
-
break;
|
|
1187
|
-
case 'model-completeness':
|
|
1188
|
-
if (helpRequested) {
|
|
1189
|
-
console.log(`
|
|
1190
|
-
eventmodeler show model-completeness - Show completeness of all flows
|
|
1191
|
-
|
|
1192
|
-
USAGE:
|
|
1193
|
-
eventmodeler show model-completeness [--format xml|json]
|
|
1194
|
-
|
|
1195
|
-
OUTPUT INCLUDES:
|
|
1196
|
-
- Complete flows (all required fields mapped)
|
|
1197
|
-
- Incomplete flows with missing mappings
|
|
1198
|
-
- Overall completeness percentage
|
|
1199
|
-
|
|
1200
|
-
NOTE: Generated fields (isGenerated=true) are excluded from checks.
|
|
790
|
+
NOTE: Generated and user-input fields are excluded from checks.
|
|
791
|
+
Auto-matching uses field name AND type.
|
|
1201
792
|
|
|
1202
793
|
EXAMPLES:
|
|
1203
|
-
eventmodeler show
|
|
1204
|
-
eventmodeler show
|
|
794
|
+
eventmodeler show information-completeness
|
|
795
|
+
eventmodeler show information-completeness --slice "Place Order"
|
|
796
|
+
eventmodeler show information-completeness --chapter "Ordering"
|
|
797
|
+
eventmodeler show information-completeness --format json
|
|
798
|
+
eventmodeler show information-completeness CreateOrder
|
|
799
|
+
eventmodeler show information-completeness "Order Summary" --format json
|
|
1205
800
|
`);
|
|
1206
801
|
process.exit(0);
|
|
1207
802
|
}
|
|
1208
|
-
|
|
1209
|
-
|
|
1210
|
-
|
|
1211
|
-
|
|
1212
|
-
|
|
1213
|
-
|
|
803
|
+
{
|
|
804
|
+
if (target) {
|
|
805
|
+
// Per-element completeness
|
|
806
|
+
const result = await api.showElementCompleteness(modelId, target, format);
|
|
807
|
+
console.log(result);
|
|
808
|
+
}
|
|
809
|
+
else {
|
|
810
|
+
// Model-wide information completeness
|
|
811
|
+
const sliceFilter = getNamedArg(filteredArgs, '--slice');
|
|
812
|
+
const result = await api.showInformationCompleteness(modelId, format, sliceFilter, chapterArg ?? undefined);
|
|
813
|
+
console.log(result);
|
|
814
|
+
}
|
|
1214
815
|
}
|
|
1215
816
|
break;
|
|
1216
817
|
case 'aggregate-completeness':
|
|
@@ -1239,13 +840,10 @@ EXAMPLES:
|
|
|
1239
840
|
console.error('Run "eventmodeler show aggregate-completeness --help" for more information.');
|
|
1240
841
|
process.exit(1);
|
|
1241
842
|
}
|
|
1242
|
-
|
|
1243
|
-
const result = await
|
|
843
|
+
{
|
|
844
|
+
const result = await api.showAggregateCompleteness(modelId, target, format);
|
|
1244
845
|
console.log(result);
|
|
1245
846
|
}
|
|
1246
|
-
else {
|
|
1247
|
-
showAggregateCompleteness(model, target, format);
|
|
1248
|
-
}
|
|
1249
847
|
break;
|
|
1250
848
|
case 'actor':
|
|
1251
849
|
if (helpRequested) {
|
|
@@ -1273,13 +871,10 @@ EXAMPLES:
|
|
|
1273
871
|
console.error('Run "eventmodeler show actor --help" for more information.');
|
|
1274
872
|
process.exit(1);
|
|
1275
873
|
}
|
|
1276
|
-
|
|
1277
|
-
const result = await
|
|
874
|
+
{
|
|
875
|
+
const result = await api.showActor(modelId, target, format);
|
|
1278
876
|
console.log(result);
|
|
1279
877
|
}
|
|
1280
|
-
else {
|
|
1281
|
-
showActor(model, target, format);
|
|
1282
|
-
}
|
|
1283
878
|
break;
|
|
1284
879
|
case 'readmodel':
|
|
1285
880
|
if (helpRequested) {
|
|
@@ -1308,13 +903,10 @@ EXAMPLES:
|
|
|
1308
903
|
console.error('Run "eventmodeler show readmodel --help" for more information.');
|
|
1309
904
|
process.exit(1);
|
|
1310
905
|
}
|
|
1311
|
-
|
|
1312
|
-
const result = await
|
|
906
|
+
{
|
|
907
|
+
const result = await api.showReadModel(modelId, target, format);
|
|
1313
908
|
console.log(result);
|
|
1314
909
|
}
|
|
1315
|
-
else {
|
|
1316
|
-
showReadModel(model, target, format);
|
|
1317
|
-
}
|
|
1318
910
|
break;
|
|
1319
911
|
case 'screen':
|
|
1320
912
|
if (helpRequested) {
|
|
@@ -1344,13 +936,10 @@ EXAMPLES:
|
|
|
1344
936
|
console.error('Run "eventmodeler show screen --help" for more information.');
|
|
1345
937
|
process.exit(1);
|
|
1346
938
|
}
|
|
1347
|
-
|
|
1348
|
-
const result = await
|
|
939
|
+
{
|
|
940
|
+
const result = await api.showScreen(modelId, target, format);
|
|
1349
941
|
console.log(result);
|
|
1350
942
|
}
|
|
1351
|
-
else {
|
|
1352
|
-
showScreen(model, target, format);
|
|
1353
|
-
}
|
|
1354
943
|
break;
|
|
1355
944
|
case 'processor':
|
|
1356
945
|
if (helpRequested) {
|
|
@@ -1379,13 +968,10 @@ EXAMPLES:
|
|
|
1379
968
|
console.error('Run "eventmodeler show processor --help" for more information.');
|
|
1380
969
|
process.exit(1);
|
|
1381
970
|
}
|
|
1382
|
-
|
|
1383
|
-
const result = await
|
|
971
|
+
{
|
|
972
|
+
const result = await api.showProcessor(modelId, target, format);
|
|
1384
973
|
console.log(result);
|
|
1385
974
|
}
|
|
1386
|
-
else {
|
|
1387
|
-
showProcessor(model, target, format);
|
|
1388
|
-
}
|
|
1389
975
|
break;
|
|
1390
976
|
case 'aggregate':
|
|
1391
977
|
if (helpRequested) {
|
|
@@ -1415,13 +1001,10 @@ EXAMPLES:
|
|
|
1415
1001
|
console.error('Run "eventmodeler show aggregate --help" for more information.');
|
|
1416
1002
|
process.exit(1);
|
|
1417
1003
|
}
|
|
1418
|
-
|
|
1419
|
-
const result = await
|
|
1004
|
+
{
|
|
1005
|
+
const result = await api.showAggregate(modelId, target, format);
|
|
1420
1006
|
console.log(result);
|
|
1421
1007
|
}
|
|
1422
|
-
else {
|
|
1423
|
-
showAggregate(model, target, format);
|
|
1424
|
-
}
|
|
1425
1008
|
break;
|
|
1426
1009
|
case 'scenario':
|
|
1427
1010
|
if (helpRequested) {
|
|
@@ -1452,17 +1035,14 @@ EXAMPLES:
|
|
|
1452
1035
|
console.error('Run "eventmodeler show scenario --help" for more information.');
|
|
1453
1036
|
process.exit(1);
|
|
1454
1037
|
}
|
|
1455
|
-
|
|
1456
|
-
const result = await
|
|
1038
|
+
{
|
|
1039
|
+
const result = await api.showScenario(modelId, target, format);
|
|
1457
1040
|
console.log(result);
|
|
1458
1041
|
}
|
|
1459
|
-
else {
|
|
1460
|
-
showScenario(model, target, format);
|
|
1461
|
-
}
|
|
1462
1042
|
break;
|
|
1463
1043
|
default:
|
|
1464
1044
|
console.error(`Unknown show target: ${subcommand}`);
|
|
1465
|
-
console.error('Valid targets: slice, event, command, chapter,
|
|
1045
|
+
console.error('Valid targets: slice, event, command, chapter, information-completeness, aggregate-completeness, actor, readmodel, screen, processor, aggregate, scenario');
|
|
1466
1046
|
console.error('Run "eventmodeler show --help" for more information.');
|
|
1467
1047
|
process.exit(1);
|
|
1468
1048
|
}
|
|
@@ -1503,35 +1083,42 @@ EXAMPLES:
|
|
|
1503
1083
|
console.error('Run "eventmodeler search --help" for more information.');
|
|
1504
1084
|
process.exit(1);
|
|
1505
1085
|
}
|
|
1506
|
-
|
|
1507
|
-
const response = await
|
|
1086
|
+
{
|
|
1087
|
+
const response = await api.search(modelId, subcommand);
|
|
1508
1088
|
if (format === 'json') {
|
|
1509
1089
|
console.log(JSON.stringify(response, null, 2));
|
|
1510
1090
|
}
|
|
1511
1091
|
else {
|
|
1512
|
-
const
|
|
1513
|
-
const
|
|
1514
|
-
console.log(`<search-results query="${esc(subcommand)}" count="${response.results.length}">`);
|
|
1515
|
-
for (const r of response.results) {
|
|
1092
|
+
const xb = new XMLBuilder({ ignoreAttributes: false, attributeNamePrefix: '@_', suppressEmptyNode: true });
|
|
1093
|
+
const results = response.results.map(r => {
|
|
1516
1094
|
const tag = r.type === 'readmodel' ? 'read-model' : r.type;
|
|
1517
|
-
|
|
1518
|
-
|
|
1519
|
-
|
|
1520
|
-
|
|
1521
|
-
|
|
1522
|
-
|
|
1523
|
-
|
|
1524
|
-
|
|
1525
|
-
|
|
1526
|
-
|
|
1527
|
-
'
|
|
1528
|
-
|
|
1529
|
-
|
|
1095
|
+
const attrs = {};
|
|
1096
|
+
if (r.id)
|
|
1097
|
+
attrs['@_id'] = r.id;
|
|
1098
|
+
if (r.name)
|
|
1099
|
+
attrs['@_name'] = r.name;
|
|
1100
|
+
if (r.chapterId)
|
|
1101
|
+
attrs['@_chapter-id'] = r.chapterId;
|
|
1102
|
+
if (r.chapterName)
|
|
1103
|
+
attrs['@_chapter-name'] = r.chapterName;
|
|
1104
|
+
if (r.sliceId)
|
|
1105
|
+
attrs['@_slice-id'] = r.sliceId;
|
|
1106
|
+
if (r.sliceName)
|
|
1107
|
+
attrs['@_slice-name'] = r.sliceName;
|
|
1108
|
+
if (r.sliceStatus)
|
|
1109
|
+
attrs['@_slice-status'] = r.sliceStatus;
|
|
1110
|
+
if (r.parentChapterId)
|
|
1111
|
+
attrs['@_parent-chapter-id'] = r.parentChapterId;
|
|
1112
|
+
if (r.parentChapterName)
|
|
1113
|
+
attrs['@_parent-chapter-name'] = r.parentChapterName;
|
|
1114
|
+
return ` ${xb.build({ [tag]: attrs }).trim()}`;
|
|
1115
|
+
});
|
|
1116
|
+
const wrapper = xb.build({ 'search-results': { '@_query': subcommand, '@_count': String(response.results.length) } });
|
|
1117
|
+
// Replace self-closing tag with children
|
|
1118
|
+
const open = wrapper.replace(/\/>$/, '>').trim();
|
|
1119
|
+
console.log([open, ...results, '</search-results>'].join('\n'));
|
|
1530
1120
|
}
|
|
1531
1121
|
}
|
|
1532
|
-
else {
|
|
1533
|
-
search(model, subcommand, format);
|
|
1534
|
-
}
|
|
1535
1122
|
break;
|
|
1536
1123
|
case 'mark': {
|
|
1537
1124
|
if (helpRequested) {
|
|
@@ -1571,15 +1158,8 @@ EXAMPLES:
|
|
|
1571
1158
|
}
|
|
1572
1159
|
const sliceName = allArgs.slice(0, -1).join(' ');
|
|
1573
1160
|
const status = lastArg;
|
|
1574
|
-
|
|
1575
|
-
|
|
1576
|
-
await cloudSlices.markSliceStatus(modelId, sliceName, status);
|
|
1577
|
-
console.log(`Marked slice "${sliceName}" as ${status}`);
|
|
1578
|
-
}
|
|
1579
|
-
else {
|
|
1580
|
-
// Local mode
|
|
1581
|
-
markSliceStatus(model, filePath, sliceName, status);
|
|
1582
|
-
}
|
|
1161
|
+
await api.markSliceStatus(modelId, sliceName, status);
|
|
1162
|
+
console.log(`Marked slice "${sliceName}" as ${status}`);
|
|
1583
1163
|
break;
|
|
1584
1164
|
}
|
|
1585
1165
|
case 'summary':
|
|
@@ -1606,30 +1186,30 @@ EXAMPLES:
|
|
|
1606
1186
|
`);
|
|
1607
1187
|
process.exit(0);
|
|
1608
1188
|
}
|
|
1609
|
-
|
|
1610
|
-
const summary = await
|
|
1189
|
+
{
|
|
1190
|
+
const summary = await api.getSummary(modelId);
|
|
1611
1191
|
if (format === 'json') {
|
|
1612
1192
|
console.log(JSON.stringify(summary, null, 2));
|
|
1613
1193
|
}
|
|
1614
1194
|
else {
|
|
1615
|
-
const
|
|
1616
|
-
console.log(
|
|
1617
|
-
|
|
1618
|
-
|
|
1619
|
-
|
|
1620
|
-
|
|
1621
|
-
|
|
1622
|
-
|
|
1623
|
-
|
|
1624
|
-
|
|
1625
|
-
|
|
1626
|
-
|
|
1627
|
-
|
|
1195
|
+
const xb = new XMLBuilder({ ignoreAttributes: false, attributeNamePrefix: '@_', format: true, indentBy: ' ', suppressEmptyNode: true });
|
|
1196
|
+
console.log(xb.build({
|
|
1197
|
+
model: {
|
|
1198
|
+
'@_name': summary.modelName || '',
|
|
1199
|
+
slices: { '@_count': String(summary.slices.total) },
|
|
1200
|
+
commands: { '@_count': String(summary.commands) },
|
|
1201
|
+
events: { '@_count': String(summary.events) },
|
|
1202
|
+
'read-models': { '@_count': String(summary.readModels) },
|
|
1203
|
+
screens: { '@_count': String(summary.screens) },
|
|
1204
|
+
processors: { '@_count': String(summary.processors) },
|
|
1205
|
+
aggregates: { '@_count': String(summary.aggregates) },
|
|
1206
|
+
actors: { '@_count': String(summary.actors) },
|
|
1207
|
+
scenarios: { '@_count': String(summary.scenarios) },
|
|
1208
|
+
flows: { '@_count': String(summary.flows) },
|
|
1209
|
+
},
|
|
1210
|
+
}).trim());
|
|
1628
1211
|
}
|
|
1629
1212
|
}
|
|
1630
|
-
else {
|
|
1631
|
-
showModelSummary(model, format);
|
|
1632
|
-
}
|
|
1633
1213
|
break;
|
|
1634
1214
|
case 'export':
|
|
1635
1215
|
if (helpRequested && !subcommand) {
|
|
@@ -1669,13 +1249,10 @@ EXAMPLES:
|
|
|
1669
1249
|
`);
|
|
1670
1250
|
process.exit(0);
|
|
1671
1251
|
}
|
|
1672
|
-
|
|
1673
|
-
const result = await
|
|
1252
|
+
{
|
|
1253
|
+
const result = await api.exportJson(modelId);
|
|
1674
1254
|
console.log(JSON.stringify(JSON.parse(result), null, 2));
|
|
1675
1255
|
}
|
|
1676
|
-
else {
|
|
1677
|
-
exportEventmodelToJson(model);
|
|
1678
|
-
}
|
|
1679
1256
|
break;
|
|
1680
1257
|
default:
|
|
1681
1258
|
console.error(`Unknown export format: ${subcommand}`);
|
|
@@ -1767,7 +1344,7 @@ EXAMPLES:
|
|
|
1767
1344
|
console.error('Run "eventmodeler add scenario --help" for detailed format.');
|
|
1768
1345
|
process.exit(1);
|
|
1769
1346
|
}
|
|
1770
|
-
|
|
1347
|
+
{
|
|
1771
1348
|
let parsedScenario;
|
|
1772
1349
|
try {
|
|
1773
1350
|
parsedScenario = parseScenarioInput(inputData);
|
|
@@ -1811,12 +1388,9 @@ EXAMPLES:
|
|
|
1811
1388
|
: undefined,
|
|
1812
1389
|
},
|
|
1813
1390
|
};
|
|
1814
|
-
await
|
|
1391
|
+
await api.createScenario(modelId, sliceArg, scenario);
|
|
1815
1392
|
console.log(`Created scenario "${scenario.name}" in slice "${sliceArg}"`);
|
|
1816
1393
|
}
|
|
1817
|
-
else {
|
|
1818
|
-
addScenario(model, filePath, sliceArg, inputData);
|
|
1819
|
-
}
|
|
1820
1394
|
break;
|
|
1821
1395
|
}
|
|
1822
1396
|
case 'field': {
|
|
@@ -1825,14 +1399,10 @@ EXAMPLES:
|
|
|
1825
1399
|
eventmodeler add field - Add a field to an entity
|
|
1826
1400
|
|
|
1827
1401
|
USAGE:
|
|
1828
|
-
eventmodeler add field
|
|
1402
|
+
eventmodeler add field <element-name> --json|--xml <data>
|
|
1829
1403
|
|
|
1830
1404
|
OPTIONS:
|
|
1831
|
-
|
|
1832
|
-
--event <name> Target event name
|
|
1833
|
-
--read-model <name> Target read model name
|
|
1834
|
-
--screen <name> Target screen name
|
|
1835
|
-
--processor <name> Target processor name
|
|
1405
|
+
<element-name> Name of the command, event, read model, screen, or processor
|
|
1836
1406
|
--json <data> Field definition in JSON format
|
|
1837
1407
|
--xml <data> Field definition in XML format
|
|
1838
1408
|
|
|
@@ -1909,28 +1479,31 @@ NOTES:
|
|
|
1909
1479
|
- Subfields support arbitrary nesting depth
|
|
1910
1480
|
|
|
1911
1481
|
EXAMPLES:
|
|
1912
|
-
eventmodeler add field
|
|
1913
|
-
eventmodeler add field
|
|
1914
|
-
eventmodeler add field
|
|
1482
|
+
eventmodeler add field OrderPlaced --json '{"name": "orderId", "type": "UUID"}'
|
|
1483
|
+
eventmodeler add field OrderSummary --json '{"name": "totalWithTax", "type": "Decimal", "isGenerated": true}'
|
|
1484
|
+
eventmodeler add field OrderPlaced --xml '<field name="item" type="Custom"><field name="price" type="Decimal"/><field name="tax" type="Decimal" isGenerated="true"/></field>'
|
|
1915
1485
|
`);
|
|
1916
1486
|
process.exit(0);
|
|
1917
1487
|
}
|
|
1918
|
-
const commandArg = getNamedArg(filteredArgs, '--command');
|
|
1919
|
-
const eventArg = getNamedArg(filteredArgs, '--event');
|
|
1920
|
-
const readModelArg = getNamedArg(filteredArgs, '--read-model');
|
|
1921
|
-
const screenArg = getNamedArg(filteredArgs, '--screen');
|
|
1922
|
-
const processorArg = getNamedArg(filteredArgs, '--processor');
|
|
1923
1488
|
const jsonArg = getNamedArg(filteredArgs, '--json');
|
|
1924
1489
|
const xmlArg = getNamedArg(filteredArgs, '--xml');
|
|
1925
1490
|
const inputData = jsonArg ?? xmlArg;
|
|
1491
|
+
// Element name is the first positional arg (not a flag or flag value)
|
|
1492
|
+
const elementName = filteredArgs.find((a, i) => !a.startsWith('-') && (i === 0 || !['--json', '--xml'].includes(filteredArgs[i - 1])));
|
|
1493
|
+
if (!elementName) {
|
|
1494
|
+
console.error('Error: Element name is required');
|
|
1495
|
+
console.error('Usage: eventmodeler add field <element-name> --json|--xml <data>');
|
|
1496
|
+
console.error('Run "eventmodeler add field --help" for detailed format documentation.');
|
|
1497
|
+
process.exit(1);
|
|
1498
|
+
}
|
|
1926
1499
|
if (!inputData) {
|
|
1927
1500
|
console.error('Error: --json or --xml is required');
|
|
1928
|
-
console.error('Usage: eventmodeler add field
|
|
1501
|
+
console.error('Usage: eventmodeler add field <element-name> --json|--xml <data>');
|
|
1929
1502
|
console.error('Run "eventmodeler add field --help" for detailed format documentation.');
|
|
1930
1503
|
process.exit(1);
|
|
1931
1504
|
}
|
|
1932
|
-
|
|
1933
|
-
// Parse field data
|
|
1505
|
+
{
|
|
1506
|
+
// Parse field data
|
|
1934
1507
|
let field;
|
|
1935
1508
|
try {
|
|
1936
1509
|
if (jsonArg) {
|
|
@@ -1946,59 +1519,29 @@ EXAMPLES:
|
|
|
1946
1519
|
};
|
|
1947
1520
|
}
|
|
1948
1521
|
else {
|
|
1949
|
-
|
|
1950
|
-
const
|
|
1951
|
-
|
|
1952
|
-
|
|
1953
|
-
|
|
1954
|
-
const
|
|
1955
|
-
|
|
1956
|
-
|
|
1957
|
-
|
|
1958
|
-
|
|
1959
|
-
|
|
1960
|
-
|
|
1961
|
-
|
|
1962
|
-
|
|
1963
|
-
|
|
1522
|
+
const parser = await import('./lib/slice-utils.js');
|
|
1523
|
+
const parsed = parser.parseFieldsFromXml(inputData);
|
|
1524
|
+
if (parsed.length === 0) {
|
|
1525
|
+
throw new Error('No <field> element found in XML');
|
|
1526
|
+
}
|
|
1527
|
+
const toApiField = (f) => ({
|
|
1528
|
+
name: f.name,
|
|
1529
|
+
fieldType: f.type,
|
|
1530
|
+
isList: f.isList,
|
|
1531
|
+
isOptional: f.isOptional,
|
|
1532
|
+
isGenerated: f.isGenerated,
|
|
1533
|
+
isUserInput: f.isUserInput,
|
|
1534
|
+
subfields: f.subfields?.map(toApiField),
|
|
1535
|
+
});
|
|
1536
|
+
field = toApiField(parsed[0]);
|
|
1964
1537
|
}
|
|
1965
1538
|
}
|
|
1966
1539
|
catch (err) {
|
|
1967
1540
|
console.error(`Error parsing field data: ${err.message}`);
|
|
1968
1541
|
process.exit(1);
|
|
1969
1542
|
}
|
|
1970
|
-
|
|
1971
|
-
|
|
1972
|
-
let elementName;
|
|
1973
|
-
if (commandArg) {
|
|
1974
|
-
elementType = 'command';
|
|
1975
|
-
elementName = commandArg;
|
|
1976
|
-
}
|
|
1977
|
-
else if (eventArg) {
|
|
1978
|
-
elementType = 'event';
|
|
1979
|
-
elementName = eventArg;
|
|
1980
|
-
}
|
|
1981
|
-
else if (readModelArg) {
|
|
1982
|
-
elementType = 'readModel';
|
|
1983
|
-
elementName = readModelArg;
|
|
1984
|
-
}
|
|
1985
|
-
else if (screenArg) {
|
|
1986
|
-
elementType = 'screen';
|
|
1987
|
-
elementName = screenArg;
|
|
1988
|
-
}
|
|
1989
|
-
else if (processorArg) {
|
|
1990
|
-
elementType = 'processor';
|
|
1991
|
-
elementName = processorArg;
|
|
1992
|
-
}
|
|
1993
|
-
else {
|
|
1994
|
-
console.error('Error: Must specify one of --command, --event, --read-model, --screen, or --processor');
|
|
1995
|
-
process.exit(1);
|
|
1996
|
-
}
|
|
1997
|
-
await cloudSlices.addField(modelId, elementType, elementName, field);
|
|
1998
|
-
console.log(`Added field "${field.name}" to ${elementType} "${elementName}"`);
|
|
1999
|
-
}
|
|
2000
|
-
else {
|
|
2001
|
-
addField(model, filePath, { command: commandArg, event: eventArg, readModel: readModelArg, screen: screenArg, processor: processorArg }, inputData);
|
|
1543
|
+
await api.addField(modelId, elementName, field);
|
|
1544
|
+
console.log(`Added field "${field.name}" to "${elementName}"`);
|
|
2002
1545
|
}
|
|
2003
1546
|
break;
|
|
2004
1547
|
}
|
|
@@ -2060,13 +1603,8 @@ EXAMPLES:
|
|
|
2060
1603
|
console.error('Run "eventmodeler remove scenario --help" for more information.');
|
|
2061
1604
|
process.exit(1);
|
|
2062
1605
|
}
|
|
2063
|
-
|
|
2064
|
-
|
|
2065
|
-
console.log(`Removed scenario "${scenarioName}"${sliceArg ? ` from slice "${sliceArg}"` : ''}`);
|
|
2066
|
-
}
|
|
2067
|
-
else {
|
|
2068
|
-
removeScenario(model, filePath, scenarioName, sliceArg);
|
|
2069
|
-
}
|
|
1606
|
+
await api.removeScenario(modelId, scenarioName, sliceArg);
|
|
1607
|
+
console.log(`Removed scenario "${scenarioName}"${sliceArg ? ` from slice "${sliceArg}"` : ''}`);
|
|
2070
1608
|
break;
|
|
2071
1609
|
}
|
|
2072
1610
|
case 'field': {
|
|
@@ -2075,67 +1613,36 @@ EXAMPLES:
|
|
|
2075
1613
|
eventmodeler remove field - Remove a field from an entity
|
|
2076
1614
|
|
|
2077
1615
|
USAGE:
|
|
2078
|
-
eventmodeler remove field
|
|
1616
|
+
eventmodeler remove field <element-name> --field <field-name>
|
|
2079
1617
|
|
|
2080
1618
|
OPTIONS:
|
|
2081
|
-
|
|
2082
|
-
--event <name> Target event name
|
|
2083
|
-
--read-model <name> Target read model name
|
|
2084
|
-
--screen <name> Target screen name
|
|
2085
|
-
--processor <name> Target processor name
|
|
1619
|
+
<element-name> Name of the command, event, read model, screen, or processor
|
|
2086
1620
|
--field <name> Field name to remove (required)
|
|
2087
1621
|
|
|
2088
1622
|
EXAMPLES:
|
|
2089
|
-
eventmodeler remove field
|
|
2090
|
-
eventmodeler remove field
|
|
1623
|
+
eventmodeler remove field OrderPlaced --field orderId
|
|
1624
|
+
eventmodeler remove field "Order Summary" --field notes
|
|
2091
1625
|
`);
|
|
2092
1626
|
process.exit(0);
|
|
2093
1627
|
}
|
|
2094
|
-
const commandArg = getNamedArg(filteredArgs, '--command');
|
|
2095
|
-
const eventArg = getNamedArg(filteredArgs, '--event');
|
|
2096
|
-
const readModelArg = getNamedArg(filteredArgs, '--read-model');
|
|
2097
|
-
const screenArg = getNamedArg(filteredArgs, '--screen');
|
|
2098
|
-
const processorArg = getNamedArg(filteredArgs, '--processor');
|
|
2099
1628
|
const fieldArg = getNamedArg(filteredArgs, '--field');
|
|
1629
|
+
// Element name is the first positional arg (not a flag or flag value)
|
|
1630
|
+
const elementName = filteredArgs.find((a, i) => !a.startsWith('-') && (i === 0 || !['--field'].includes(filteredArgs[i - 1])));
|
|
2100
1631
|
if (!fieldArg) {
|
|
2101
1632
|
console.error('Error: --field is required');
|
|
2102
|
-
console.error('Usage: eventmodeler remove field
|
|
1633
|
+
console.error('Usage: eventmodeler remove field <element-name> --field <field-name>');
|
|
2103
1634
|
console.error('Run "eventmodeler remove field --help" for more information.');
|
|
2104
1635
|
process.exit(1);
|
|
2105
1636
|
}
|
|
2106
|
-
if (
|
|
2107
|
-
|
|
2108
|
-
|
|
2109
|
-
|
|
2110
|
-
|
|
2111
|
-
elementType = 'command';
|
|
2112
|
-
elementName = commandArg;
|
|
2113
|
-
}
|
|
2114
|
-
else if (eventArg) {
|
|
2115
|
-
elementType = 'event';
|
|
2116
|
-
elementName = eventArg;
|
|
2117
|
-
}
|
|
2118
|
-
else if (readModelArg) {
|
|
2119
|
-
elementType = 'readModel';
|
|
2120
|
-
elementName = readModelArg;
|
|
2121
|
-
}
|
|
2122
|
-
else if (screenArg) {
|
|
2123
|
-
elementType = 'screen';
|
|
2124
|
-
elementName = screenArg;
|
|
2125
|
-
}
|
|
2126
|
-
else if (processorArg) {
|
|
2127
|
-
elementType = 'processor';
|
|
2128
|
-
elementName = processorArg;
|
|
2129
|
-
}
|
|
2130
|
-
else {
|
|
2131
|
-
console.error('Error: Must specify one of --command, --event, --read-model, --screen, or --processor');
|
|
2132
|
-
process.exit(1);
|
|
2133
|
-
}
|
|
2134
|
-
await cloudSlices.removeField(modelId, elementType, elementName, fieldArg);
|
|
2135
|
-
console.log(`Removed field "${fieldArg}" from ${elementType} "${elementName}"`);
|
|
1637
|
+
if (!elementName) {
|
|
1638
|
+
console.error('Error: Element name is required');
|
|
1639
|
+
console.error('Usage: eventmodeler remove field <element-name> --field <field-name>');
|
|
1640
|
+
console.error('Run "eventmodeler remove field --help" for more information.');
|
|
1641
|
+
process.exit(1);
|
|
2136
1642
|
}
|
|
2137
|
-
|
|
2138
|
-
removeField(
|
|
1643
|
+
{
|
|
1644
|
+
await api.removeField(modelId, elementName, fieldArg);
|
|
1645
|
+
console.log(`Removed field "${fieldArg}" from "${elementName}"`);
|
|
2139
1646
|
}
|
|
2140
1647
|
break;
|
|
2141
1648
|
}
|
|
@@ -2190,7 +1697,7 @@ XML FORMAT:
|
|
|
2190
1697
|
NOTES:
|
|
2191
1698
|
- Mappings define how fields flow from source to target
|
|
2192
1699
|
- Fields marked as isGenerated=true don't need mappings
|
|
2193
|
-
- Use "show completeness" to check mapping status
|
|
1700
|
+
- Use "show information-completeness <name>" to check mapping status
|
|
2194
1701
|
|
|
2195
1702
|
EXAMPLES:
|
|
2196
1703
|
eventmodeler map fields --flow "OrderPlaced→OrderSummary" --json '[{"from": "total", "to": "totalAmount"}]'
|
|
@@ -2215,7 +1722,7 @@ EXAMPLES:
|
|
|
2215
1722
|
console.error('Run "eventmodeler map fields --help" for detailed format.');
|
|
2216
1723
|
process.exit(1);
|
|
2217
1724
|
}
|
|
2218
|
-
|
|
1725
|
+
{
|
|
2219
1726
|
// Parse flow argument to extract source and target names
|
|
2220
1727
|
const flowParts = flowArg.split(/→|->/).map(s => s.trim());
|
|
2221
1728
|
if (flowParts.length !== 2) {
|
|
@@ -2230,28 +1737,23 @@ EXAMPLES:
|
|
|
2230
1737
|
mappings = JSON.parse(inputData);
|
|
2231
1738
|
}
|
|
2232
1739
|
else {
|
|
2233
|
-
|
|
2234
|
-
const
|
|
2235
|
-
|
|
2236
|
-
|
|
2237
|
-
|
|
2238
|
-
|
|
2239
|
-
|
|
2240
|
-
|
|
2241
|
-
};
|
|
2242
|
-
});
|
|
1740
|
+
const xp = new XMLParser({ ignoreAttributes: false, attributeNamePrefix: '@_', isArray: (name) => name === 'mapping' });
|
|
1741
|
+
const parsed = xp.parse(inputData);
|
|
1742
|
+
const root = parsed['mappings'];
|
|
1743
|
+
const nodes = root ? (Array.isArray(root['mapping']) ? root['mapping'] : root['mapping'] ? [root['mapping']] : []) : [];
|
|
1744
|
+
mappings = nodes.map(m => ({
|
|
1745
|
+
from: m['@_from'] ?? '',
|
|
1746
|
+
to: m['@_to'] ?? '',
|
|
1747
|
+
}));
|
|
2243
1748
|
}
|
|
2244
1749
|
}
|
|
2245
1750
|
catch (err) {
|
|
2246
1751
|
console.error(`Error parsing mappings: ${err.message}`);
|
|
2247
1752
|
process.exit(1);
|
|
2248
1753
|
}
|
|
2249
|
-
await
|
|
1754
|
+
await api.mapFields(modelId, sourceName, targetName, mappings);
|
|
2250
1755
|
console.log(`Mapped ${mappings.length} field(s) from "${sourceName}" to "${targetName}"`);
|
|
2251
1756
|
}
|
|
2252
|
-
else {
|
|
2253
|
-
mapFields(model, filePath, flowArg, inputData);
|
|
2254
|
-
}
|
|
2255
1757
|
break;
|
|
2256
1758
|
}
|
|
2257
1759
|
default:
|
|
@@ -2283,22 +1785,18 @@ Run "eventmodeler update field --help" for detailed help.
|
|
|
2283
1785
|
eventmodeler update field - Update field properties
|
|
2284
1786
|
|
|
2285
1787
|
USAGE:
|
|
2286
|
-
eventmodeler update field
|
|
1788
|
+
eventmodeler update field <element-name> --field <field-name> [updates]
|
|
2287
1789
|
|
|
2288
|
-
|
|
2289
|
-
|
|
2290
|
-
--event <name> Target event
|
|
2291
|
-
--read-model <name> Target read model
|
|
2292
|
-
--screen <name> Target screen
|
|
2293
|
-
--processor <name> Target processor
|
|
1790
|
+
OPTIONS:
|
|
1791
|
+
<element-name> Name of the command, event, read model, screen, or processor
|
|
2294
1792
|
|
|
2295
1793
|
REQUIRED:
|
|
2296
|
-
--field <name>
|
|
1794
|
+
--field <name> Field to update
|
|
2297
1795
|
|
|
2298
1796
|
UPDATE OPTIONS (at least one required):
|
|
2299
1797
|
--optional true|false Set isOptional flag
|
|
2300
1798
|
--generated true|false Set isGenerated flag
|
|
2301
|
-
--user-input true|false Set isUserInput flag
|
|
1799
|
+
--user-input true|false Set isUserInput flag
|
|
2302
1800
|
--type <type> Change field type
|
|
2303
1801
|
|
|
2304
1802
|
FIELD FLAGS EXPLAINED:
|
|
@@ -2308,38 +1806,37 @@ FIELD FLAGS EXPLAINED:
|
|
|
2308
1806
|
|
|
2309
1807
|
EXAMPLES:
|
|
2310
1808
|
# Mark field as optional
|
|
2311
|
-
eventmodeler update field
|
|
1809
|
+
eventmodeler update field OrderSummary --field notes --optional true
|
|
2312
1810
|
|
|
2313
1811
|
# Mark field as generated (computed value, no mapping needed)
|
|
2314
|
-
eventmodeler update field
|
|
1812
|
+
eventmodeler update field OrderSummary --field totalWithTax --generated true
|
|
2315
1813
|
|
|
2316
1814
|
# Mark screen field as user input
|
|
2317
|
-
eventmodeler update field
|
|
1815
|
+
eventmodeler update field "Order Form" --field quantity --user-input true
|
|
2318
1816
|
|
|
2319
1817
|
# Change field type
|
|
2320
|
-
eventmodeler update field
|
|
1818
|
+
eventmodeler update field OrderPlaced --field amount --type Decimal
|
|
2321
1819
|
`);
|
|
2322
1820
|
process.exit(0);
|
|
2323
1821
|
}
|
|
2324
|
-
const commandArg = getNamedArg(filteredArgs, '--command');
|
|
2325
|
-
const eventArg = getNamedArg(filteredArgs, '--event');
|
|
2326
|
-
const readModelArg = getNamedArg(filteredArgs, '--read-model');
|
|
2327
|
-
const screenArg = getNamedArg(filteredArgs, '--screen');
|
|
2328
|
-
const processorArg = getNamedArg(filteredArgs, '--processor');
|
|
2329
1822
|
const fieldArg = getNamedArg(filteredArgs, '--field');
|
|
2330
1823
|
const optionalArg = getNamedArg(filteredArgs, '--optional');
|
|
2331
1824
|
const generatedArg = getNamedArg(filteredArgs, '--generated');
|
|
2332
1825
|
const userInputArg = getNamedArg(filteredArgs, '--user-input');
|
|
2333
1826
|
const typeArg = getNamedArg(filteredArgs, '--type');
|
|
1827
|
+
// Element name is the first positional arg (not a flag or flag value)
|
|
1828
|
+
const flagsWithValues = ['--field', '--optional', '--generated', '--user-input', '--type'];
|
|
1829
|
+
const elementName = filteredArgs.find((a, i) => !a.startsWith('-') && (i === 0 || !flagsWithValues.includes(filteredArgs[i - 1])));
|
|
2334
1830
|
if (!fieldArg) {
|
|
2335
1831
|
console.error('Error: --field is required');
|
|
2336
|
-
console.error('Usage: eventmodeler update field
|
|
1832
|
+
console.error('Usage: eventmodeler update field <element-name> --field <field-name> [--optional true|false] [--generated true|false] [--user-input true|false]');
|
|
2337
1833
|
console.error('Run "eventmodeler update field --help" for detailed options.');
|
|
2338
1834
|
process.exit(1);
|
|
2339
1835
|
}
|
|
2340
|
-
|
|
2341
|
-
|
|
2342
|
-
console.error('
|
|
1836
|
+
if (!elementName) {
|
|
1837
|
+
console.error('Error: Element name is required');
|
|
1838
|
+
console.error('Usage: eventmodeler update field <element-name> --field <field-name> [--optional true|false] [--generated true|false] [--user-input true|false]');
|
|
1839
|
+
console.error('Run "eventmodeler update field --help" for detailed options.');
|
|
2343
1840
|
process.exit(1);
|
|
2344
1841
|
}
|
|
2345
1842
|
const updates = {};
|
|
@@ -2360,49 +1857,19 @@ EXAMPLES:
|
|
|
2360
1857
|
console.error('Run "eventmodeler update field --help" for available options.');
|
|
2361
1858
|
process.exit(1);
|
|
2362
1859
|
}
|
|
2363
|
-
|
|
2364
|
-
//
|
|
2365
|
-
|
|
2366
|
-
let elementName;
|
|
2367
|
-
if (commandArg) {
|
|
2368
|
-
elementType = 'command';
|
|
2369
|
-
elementName = commandArg;
|
|
2370
|
-
}
|
|
2371
|
-
else if (eventArg) {
|
|
2372
|
-
elementType = 'event';
|
|
2373
|
-
elementName = eventArg;
|
|
2374
|
-
}
|
|
2375
|
-
else if (readModelArg) {
|
|
2376
|
-
elementType = 'readModel';
|
|
2377
|
-
elementName = readModelArg;
|
|
2378
|
-
}
|
|
2379
|
-
else if (screenArg) {
|
|
2380
|
-
elementType = 'screen';
|
|
2381
|
-
elementName = screenArg;
|
|
2382
|
-
}
|
|
2383
|
-
else if (processorArg) {
|
|
2384
|
-
elementType = 'processor';
|
|
2385
|
-
elementName = processorArg;
|
|
2386
|
-
}
|
|
2387
|
-
else {
|
|
2388
|
-
console.error('Error: Must specify one of --command, --event, --read-model, --screen, or --processor');
|
|
2389
|
-
process.exit(1);
|
|
2390
|
-
}
|
|
2391
|
-
// Convert local updates format to cloud format
|
|
2392
|
-
const cloudUpdates = {};
|
|
1860
|
+
{
|
|
1861
|
+
// Convert updates to API format
|
|
1862
|
+
const fieldUpdates = {};
|
|
2393
1863
|
if (updates.optional !== undefined)
|
|
2394
|
-
|
|
1864
|
+
fieldUpdates.isOptional = updates.optional;
|
|
2395
1865
|
if (updates.generated !== undefined)
|
|
2396
|
-
|
|
1866
|
+
fieldUpdates.isGenerated = updates.generated;
|
|
2397
1867
|
if (updates.userInput !== undefined)
|
|
2398
|
-
|
|
1868
|
+
fieldUpdates.isUserInput = updates.userInput;
|
|
2399
1869
|
if (updates.type !== undefined)
|
|
2400
|
-
|
|
2401
|
-
await
|
|
2402
|
-
console.log(`Updated field "${fieldArg}" on
|
|
2403
|
-
}
|
|
2404
|
-
else {
|
|
2405
|
-
updateField(model, filePath, { command: commandArg, event: eventArg, readModel: readModelArg, screen: screenArg, processor: processorArg }, fieldArg, updates);
|
|
1870
|
+
fieldUpdates.fieldType = updates.type;
|
|
1871
|
+
await api.updateField(modelId, elementName, fieldArg, fieldUpdates);
|
|
1872
|
+
console.log(`Updated field "${fieldArg}" on "${elementName}"`);
|
|
2406
1873
|
}
|
|
2407
1874
|
break;
|
|
2408
1875
|
}
|
|
@@ -2516,11 +1983,11 @@ EXAMPLES:
|
|
|
2516
1983
|
console.error('Run "eventmodeler create state-change-slice --help" for detailed format.');
|
|
2517
1984
|
process.exit(1);
|
|
2518
1985
|
}
|
|
2519
|
-
|
|
1986
|
+
{
|
|
2520
1987
|
// Parse XML input to extract structured data
|
|
2521
1988
|
const parser = await import('./lib/slice-utils.js');
|
|
2522
1989
|
const parsed = parser.parseStateChangeSliceXml(xmlArg);
|
|
2523
|
-
const
|
|
1990
|
+
const sliceInput = {
|
|
2524
1991
|
sliceName: parsed.sliceName,
|
|
2525
1992
|
after: parsed.after,
|
|
2526
1993
|
before: parsed.before,
|
|
@@ -2528,7 +1995,7 @@ EXAMPLES:
|
|
|
2528
1995
|
command: { name: parsed.command.name, fields: toCompoundFields(parsed.command.fields) },
|
|
2529
1996
|
event: { name: parsed.event.name, fields: toCompoundFields(parsed.event.fields) },
|
|
2530
1997
|
};
|
|
2531
|
-
const result = await
|
|
1998
|
+
const result = await api.createStateChangeSlice(modelId, sliceInput);
|
|
2532
1999
|
console.log(`Created state-change slice "${parsed.sliceName}"`);
|
|
2533
2000
|
console.log(` Screen: ${parsed.screen.name} (${parsed.screen.fields.length} fields)`);
|
|
2534
2001
|
console.log(` Command: ${parsed.command.name} (${parsed.command.fields.length} fields)`);
|
|
@@ -2536,9 +2003,6 @@ EXAMPLES:
|
|
|
2536
2003
|
console.log(` Screen -> Command mappings: ${result.screenToCommandMappings}`);
|
|
2537
2004
|
console.log(` Command -> Event mappings: ${result.commandToEventMappings}`);
|
|
2538
2005
|
}
|
|
2539
|
-
else {
|
|
2540
|
-
createStateChangeSlice(model, filePath, xmlArg);
|
|
2541
|
-
}
|
|
2542
2006
|
break;
|
|
2543
2007
|
}
|
|
2544
2008
|
case 'automation-slice': {
|
|
@@ -2619,11 +2083,11 @@ EXAMPLES:
|
|
|
2619
2083
|
console.error('Run "eventmodeler create automation-slice --help" for detailed format.');
|
|
2620
2084
|
process.exit(1);
|
|
2621
2085
|
}
|
|
2622
|
-
|
|
2086
|
+
{
|
|
2623
2087
|
// Parse XML input to extract structured data
|
|
2624
2088
|
const parser = await import('./lib/slice-utils.js');
|
|
2625
2089
|
const parsed = parser.parseAutomationSliceXml(xmlArg);
|
|
2626
|
-
const
|
|
2090
|
+
const sliceInput = {
|
|
2627
2091
|
sliceName: parsed.sliceName,
|
|
2628
2092
|
after: parsed.after,
|
|
2629
2093
|
before: parsed.before,
|
|
@@ -2632,7 +2096,7 @@ EXAMPLES:
|
|
|
2632
2096
|
command: { name: parsed.command.name, fields: toCompoundFields(parsed.command.fields) },
|
|
2633
2097
|
event: { name: parsed.event.name, fields: toCompoundFields(parsed.event.fields) },
|
|
2634
2098
|
};
|
|
2635
|
-
const result = await
|
|
2099
|
+
const result = await api.createAutomationSlice(modelId, sliceInput);
|
|
2636
2100
|
console.log(`Created automation slice "${parsed.sliceName}"`);
|
|
2637
2101
|
console.log(` ReadModel: ${parsed.readModel.name} (${parsed.readModel.fields.length} fields)`);
|
|
2638
2102
|
console.log(` Processor: ${parsed.processor.name}`);
|
|
@@ -2641,9 +2105,6 @@ EXAMPLES:
|
|
|
2641
2105
|
console.log(` ReadModel -> Command mappings: ${result.readModelToCommandMappings}`);
|
|
2642
2106
|
console.log(` Command -> Event mappings: ${result.commandToEventMappings}`);
|
|
2643
2107
|
}
|
|
2644
|
-
else {
|
|
2645
|
-
createAutomationSlice(model, filePath, xmlArg);
|
|
2646
|
-
}
|
|
2647
2108
|
break;
|
|
2648
2109
|
}
|
|
2649
2110
|
case 'state-view-slice': {
|
|
@@ -2710,23 +2171,20 @@ EXAMPLES:
|
|
|
2710
2171
|
console.error('Run "eventmodeler create state-view-slice --help" for detailed format.');
|
|
2711
2172
|
process.exit(1);
|
|
2712
2173
|
}
|
|
2713
|
-
|
|
2174
|
+
{
|
|
2714
2175
|
// Parse XML input to extract structured data
|
|
2715
2176
|
const parser = await import('./lib/slice-utils.js');
|
|
2716
2177
|
const parsed = parser.parseStateViewSliceXml(xmlArg);
|
|
2717
|
-
const
|
|
2178
|
+
const sliceInput = {
|
|
2718
2179
|
sliceName: parsed.sliceName,
|
|
2719
2180
|
after: parsed.after,
|
|
2720
2181
|
before: parsed.before,
|
|
2721
2182
|
readModel: { name: parsed.readModel.name, fields: toCompoundFields(parsed.readModel.fields) },
|
|
2722
2183
|
};
|
|
2723
|
-
const result = await
|
|
2184
|
+
const result = await api.createStateViewSlice(modelId, sliceInput);
|
|
2724
2185
|
console.log(`Created state-view slice "${parsed.sliceName}"`);
|
|
2725
2186
|
console.log(` ReadModel: ${parsed.readModel.name} (${parsed.readModel.fields.length} fields)`);
|
|
2726
2187
|
}
|
|
2727
|
-
else {
|
|
2728
|
-
createStateViewSlice(model, filePath, xmlArg);
|
|
2729
|
-
}
|
|
2730
2188
|
break;
|
|
2731
2189
|
}
|
|
2732
2190
|
case 'flow': {
|
|
@@ -2761,13 +2219,8 @@ EXAMPLES:
|
|
|
2761
2219
|
console.error('Run "eventmodeler create flow --help" for more information.');
|
|
2762
2220
|
process.exit(1);
|
|
2763
2221
|
}
|
|
2764
|
-
|
|
2765
|
-
|
|
2766
|
-
console.log(`Created flow from "${fromArg}" to "${toArg}"`);
|
|
2767
|
-
}
|
|
2768
|
-
else {
|
|
2769
|
-
createFlow(model, filePath, fromArg, toArg);
|
|
2770
|
-
}
|
|
2222
|
+
await api.createFlow(modelId, fromArg, toArg);
|
|
2223
|
+
console.log(`Created flow from "${fromArg}" to "${toArg}"`);
|
|
2771
2224
|
break;
|
|
2772
2225
|
}
|
|
2773
2226
|
default:
|
|
@@ -2831,13 +2284,10 @@ EXAMPLES:
|
|
|
2831
2284
|
console.error('Run "eventmodeler codegen slice --help" for more information.');
|
|
2832
2285
|
process.exit(1);
|
|
2833
2286
|
}
|
|
2834
|
-
|
|
2835
|
-
const result = await
|
|
2287
|
+
{
|
|
2288
|
+
const result = await api.codegenSlice(modelId, sliceName);
|
|
2836
2289
|
console.log(JSON.stringify(JSON.parse(result), null, 2));
|
|
2837
2290
|
}
|
|
2838
|
-
else {
|
|
2839
|
-
codegenSlice(model, sliceName);
|
|
2840
|
-
}
|
|
2841
2291
|
break;
|
|
2842
2292
|
}
|
|
2843
2293
|
case 'events': {
|
|
@@ -2869,13 +2319,10 @@ EXAMPLES:
|
|
|
2869
2319
|
process.exit(0);
|
|
2870
2320
|
}
|
|
2871
2321
|
const chapterName = chapterArg ?? target;
|
|
2872
|
-
|
|
2873
|
-
const output = await
|
|
2322
|
+
{
|
|
2323
|
+
const output = await api.codegenEvents(modelId, chapterName);
|
|
2874
2324
|
console.log(JSON.stringify(output, null, 2));
|
|
2875
2325
|
}
|
|
2876
|
-
else {
|
|
2877
|
-
codegenEvents(model, chapterName);
|
|
2878
|
-
}
|
|
2879
2326
|
break;
|
|
2880
2327
|
}
|
|
2881
2328
|
default:
|