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/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
- // Import slices
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 { search } from './slices/search/index.js';
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
- // Cloud slices
59
- import * as cloudSlices from './cloud/slices/index.js';
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 cloud or local model)
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 <name> Show field mapping completeness for any element
119
- show model-completeness Show completeness of all flows in the model
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 --command|--event|--read-model|--screen|--processor <name> --json|--xml <data>
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 --command|--event|--read-model|--screen|--processor <name> --field <name>
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 --command|--event|--read-model|--screen|--processor <name> --field <name> [--optional true|false] [--generated true|false] [--user-input true|false (screen only)]
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 --event "OrderPlaced" --json '{"name": "orderId", "type": "UUID"}'
203
- eventmodeler remove field --event "OrderPlaced" --field "orderId"
204
- eventmodeler show completeness "OrderSummary"
205
- eventmodeler show model-completeness
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 --read-model "OrderSummary" --field "notes" --optional true
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] === '-f' || args[i] === '--file') {
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 cloud model
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
- - For cloud mode, you must be logged in (run "eventmodeler login" first)
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
- const isCloudMode = projectConfig?.type === 'cloud' && !fileArg;
608
- const modelId = isCloudMode ? projectConfig.modelId : null;
609
- // For local mode, we need to load the model from file
610
- // For cloud mode, we call backend endpoints directly (no model loading)
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
- if (isCloudMode) {
692
- const output = await cloudSlices.listSlices(modelId, format, chapterArg ?? undefined);
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
- if (isCloudMode) {
723
- const output = await cloudSlices.listEvents(modelId, format);
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
- if (isCloudMode) {
752
- const output = await cloudSlices.listCommands(modelId, format);
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
- if (isCloudMode) {
781
- const output = await cloudSlices.listChapters(modelId, format);
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
- if (isCloudMode) {
811
- const result = await cloudSlices.listAggregates(modelId, format);
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
- if (isCloudMode) {
840
- const output = await cloudSlices.listActors(modelId, format);
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
- if (isCloudMode) {
865
- const output = await cloudSlices.listReadModels(modelId, format);
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
- if (isCloudMode) {
890
- const output = await cloudSlices.listScreens(modelId, format);
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
- if (isCloudMode) {
914
- const output = await cloudSlices.listProcessors(modelId, format);
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
- if (isCloudMode) {
940
- const output = await cloudSlices.listScenarios(modelId, format);
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 Show field mapping completeness for any element
967
- model-completeness Show completeness of all flows
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
- if (isCloudMode) {
1022
- const result = await cloudSlices.showSlice(modelId, target, format);
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
- if (isCloudMode) {
1070
- const result = await cloudSlices.showEvent(modelId, target, format);
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
- if (isCloudMode) {
1104
- const result = await cloudSlices.showCommand(modelId, target, format);
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
- if (isCloudMode) {
1139
- const result = await cloudSlices.showChapter(modelId, target, format);
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 field mapping completeness
767
+ eventmodeler show information-completeness - Show information completeness
1150
768
 
1151
769
  USAGE:
1152
- eventmodeler show completeness <name> [--format xml|json]
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
- ARGUMENTS:
1155
- <name> Element name (command, event, read model, screen, or processor)
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
- EXAMPLES:
1168
- eventmodeler show completeness OrderSummary
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 model-completeness
1204
- eventmodeler show model-completeness --format json
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
- if (isCloudMode) {
1209
- const result = await cloudSlices.showModelCompleteness(modelId, format);
1210
- console.log(result);
1211
- }
1212
- else {
1213
- showModelCompleteness(model, format);
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
- if (isCloudMode) {
1243
- const result = await cloudSlices.showAggregateCompleteness(modelId, target, format);
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
- if (isCloudMode) {
1277
- const result = await cloudSlices.showActor(modelId, target, format);
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
- if (isCloudMode) {
1312
- const result = await cloudSlices.showReadModel(modelId, target, format);
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
- if (isCloudMode) {
1348
- const result = await cloudSlices.showScreen(modelId, target, format);
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
- if (isCloudMode) {
1383
- const result = await cloudSlices.showProcessor(modelId, target, format);
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
- if (isCloudMode) {
1419
- const result = await cloudSlices.showAggregate(modelId, target, format);
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
- if (isCloudMode) {
1456
- const result = await cloudSlices.showScenario(modelId, target, format);
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, completeness, model-completeness, aggregate-completeness, actor, readmodel, screen, processor, aggregate, scenario');
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
- if (isCloudMode) {
1507
- const response = await cloudSlices.search(modelId, subcommand);
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 esc = (s) => s.replace(/&/g, '&amp;').replace(/"/g, '&quot;').replace(/</g, '&lt;').replace(/>/g, '&gt;');
1513
- const attr = (name, value) => value ? ` ${name}="${esc(value)}"` : '';
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
- console.log(` <${tag}` +
1518
- `${attr('id', r.id)}` +
1519
- `${attr('name', r.name)}` +
1520
- `${attr('chapter-id', r.chapterId)}` +
1521
- `${attr('chapter-name', r.chapterName)}` +
1522
- `${attr('slice-id', r.sliceId)}` +
1523
- `${attr('slice-name', r.sliceName)}` +
1524
- `${attr('slice-status', r.sliceStatus)}` +
1525
- `${attr('parent-chapter-id', r.parentChapterId)}` +
1526
- `${attr('parent-chapter-name', r.parentChapterName)}` +
1527
- '/>');
1528
- }
1529
- console.log('</search-results>');
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
- if (isCloudMode) {
1575
- // Cloud mode - backend resolves name to ID
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
- if (isCloudMode) {
1610
- const summary = await cloudSlices.getSummary(modelId);
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 name = summary.modelName || '';
1616
- console.log(`<model name="${name}">`);
1617
- console.log(` <slices count="${summary.slices.total}"/>`);
1618
- console.log(` <commands count="${summary.commands}"/>`);
1619
- console.log(` <events count="${summary.events}"/>`);
1620
- console.log(` <read-models count="${summary.readModels}"/>`);
1621
- console.log(` <screens count="${summary.screens}"/>`);
1622
- console.log(` <processors count="${summary.processors}"/>`);
1623
- console.log(` <aggregates count="${summary.aggregates}"/>`);
1624
- console.log(` <actors count="${summary.actors}"/>`);
1625
- console.log(` <scenarios count="${summary.scenarios}"/>`);
1626
- console.log(` <flows count="${summary.flows}"/>`);
1627
- console.log('</model>');
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
- if (isCloudMode) {
1673
- const result = await cloudSlices.exportJson(modelId);
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
- if (isCloudMode) {
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 cloudSlices.createScenario(modelId, sliceArg, scenario);
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 --command|--event|--read-model|--screen|--processor <name> --json|--xml <data>
1402
+ eventmodeler add field <element-name> --json|--xml <data>
1829
1403
 
1830
1404
  OPTIONS:
1831
- --command <name> Target command name
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 --event OrderPlaced --json '{"name": "orderId", "type": "UUID"}'
1913
- eventmodeler add field --read-model OrderSummary --json '{"name": "totalWithTax", "type": "Decimal", "isGenerated": true}'
1914
- eventmodeler add field --event OrderPlaced --xml '<field name="item" type="Custom"><field name="price" type="Decimal"/><field name="tax" type="Decimal" isGenerated="true"/></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 --command|--event|--read-model|--screen|--processor <name> --json|--xml <data>');
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
- if (isCloudMode) {
1933
- // Parse field data and determine element type
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
- // XML parsing - extract field attributes
1950
- const nameMatch = inputData.match(/name="([^"]*)"/);
1951
- const typeMatch = inputData.match(/type="([^"]*)"/);
1952
- const isListMatch = inputData.match(/isList="([^"]*)"/);
1953
- const isOptionalMatch = inputData.match(/isOptional="([^"]*)"/);
1954
- const isGeneratedMatch = inputData.match(/isGenerated="([^"]*)"/);
1955
- const isUserInputMatch = inputData.match(/isUserInput="([^"]*)"/);
1956
- field = {
1957
- name: nameMatch?.[1] ?? '',
1958
- fieldType: typeMatch?.[1] ?? 'String',
1959
- isList: isListMatch?.[1] === 'true',
1960
- isOptional: isOptionalMatch?.[1] === 'true',
1961
- isGenerated: isGeneratedMatch?.[1] === 'true',
1962
- isUserInput: isUserInputMatch?.[1] === 'true',
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
- // Determine element type and name
1971
- let elementType;
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
- if (isCloudMode) {
2064
- await cloudSlices.removeScenario(modelId, scenarioName, sliceArg);
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 --command|--event|--read-model|--screen|--processor <name> --field <field-name>
1616
+ eventmodeler remove field <element-name> --field <field-name>
2079
1617
 
2080
1618
  OPTIONS:
2081
- --command <name> Target command name
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 --event OrderPlaced --field orderId
2090
- eventmodeler remove field --read-model "Order Summary" --field notes
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 --command|--event|--read-model|--screen|--processor <name> --field <field-name>');
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 (isCloudMode) {
2107
- // Determine element type and name
2108
- let elementType;
2109
- let elementName;
2110
- if (commandArg) {
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
- else {
2138
- removeField(model, filePath, { command: commandArg, event: eventArg, readModel: readModelArg, screen: screenArg, processor: processorArg }, fieldArg);
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
- if (isCloudMode) {
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
- // XML parsing - extract mapping attributes
2234
- const mappingMatches = inputData.match(/<mapping[^>]+>/g) || [];
2235
- mappings = mappingMatches.map(m => {
2236
- const fromMatch = m.match(/from="([^"]*)"/);
2237
- const toMatch = m.match(/to="([^"]*)"/);
2238
- return {
2239
- from: fromMatch?.[1] ?? '',
2240
- to: toMatch?.[1] ?? '',
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 cloudSlices.mapFields(modelId, sourceName, targetName, mappings);
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 --command|--event|--read-model|--screen|--processor <name> --field <field-name> [updates]
1788
+ eventmodeler update field <element-name> --field <field-name> [updates]
2287
1789
 
2288
- TARGET OPTIONS (one required):
2289
- --command <name> Target command
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> Field to update
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 (screen only)
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 --read-model OrderSummary --field notes --optional true
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 --read-model OrderSummary --field totalWithTax --generated true
1812
+ eventmodeler update field OrderSummary --field totalWithTax --generated true
2315
1813
 
2316
1814
  # Mark screen field as user input
2317
- eventmodeler update field --screen "Order Form" --field quantity --user-input true
1815
+ eventmodeler update field "Order Form" --field quantity --user-input true
2318
1816
 
2319
1817
  # Change field type
2320
- eventmodeler update field --event OrderPlaced --field amount --type Decimal
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 --command|--event|--read-model|--screen|--processor <name> --field <field-name> [--optional true|false] [--generated true|false] [--user-input true|false (screen only)]');
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
- // --user-input is only valid for screens
2341
- if (userInputArg !== undefined && !screenArg) {
2342
- console.error('Error: --user-input can only be used with --screen');
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
- if (isCloudMode) {
2364
- // Determine element type and name
2365
- let elementType;
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
- cloudUpdates.isOptional = updates.optional;
1864
+ fieldUpdates.isOptional = updates.optional;
2395
1865
  if (updates.generated !== undefined)
2396
- cloudUpdates.isGenerated = updates.generated;
1866
+ fieldUpdates.isGenerated = updates.generated;
2397
1867
  if (updates.userInput !== undefined)
2398
- cloudUpdates.isUserInput = updates.userInput;
1868
+ fieldUpdates.isUserInput = updates.userInput;
2399
1869
  if (updates.type !== undefined)
2400
- cloudUpdates.fieldType = updates.type;
2401
- await cloudSlices.updateField(modelId, elementType, elementName, fieldArg, cloudUpdates);
2402
- console.log(`Updated field "${fieldArg}" on ${elementType} "${elementName}"`);
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
- if (isCloudMode) {
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 cloudInput = {
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 cloudSlices.createStateChangeSlice(modelId, cloudInput);
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
- if (isCloudMode) {
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 cloudInput = {
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 cloudSlices.createAutomationSlice(modelId, cloudInput);
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
- if (isCloudMode) {
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 cloudInput = {
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 cloudSlices.createStateViewSlice(modelId, cloudInput);
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
- if (isCloudMode) {
2765
- await cloudSlices.createFlow(modelId, fromArg, toArg);
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
- if (isCloudMode) {
2835
- const result = await cloudSlices.codegenSlice(modelId, sliceName);
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
- if (isCloudMode) {
2873
- const output = await cloudSlices.codegenEvents(modelId, chapterName);
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: