eventmodeler 0.4.3 → 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,24 +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
- console.log(`<search-results query="${esc(subcommand)}" count="${response.results.length}">`);
1514
- for (const r of response.results) {
1092
+ const xb = new XMLBuilder({ ignoreAttributes: false, attributeNamePrefix: '@_', suppressEmptyNode: true });
1093
+ const results = response.results.map(r => {
1515
1094
  const tag = r.type === 'readmodel' ? 'read-model' : r.type;
1516
- console.log(` <${tag} name="${esc(r.name)}"/>`);
1517
- }
1518
- 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'));
1519
1120
  }
1520
1121
  }
1521
- else {
1522
- search(model, subcommand, format);
1523
- }
1524
1122
  break;
1525
1123
  case 'mark': {
1526
1124
  if (helpRequested) {
@@ -1560,15 +1158,8 @@ EXAMPLES:
1560
1158
  }
1561
1159
  const sliceName = allArgs.slice(0, -1).join(' ');
1562
1160
  const status = lastArg;
1563
- if (isCloudMode) {
1564
- // Cloud mode - backend resolves name to ID
1565
- await cloudSlices.markSliceStatus(modelId, sliceName, status);
1566
- console.log(`Marked slice "${sliceName}" as ${status}`);
1567
- }
1568
- else {
1569
- // Local mode
1570
- markSliceStatus(model, filePath, sliceName, status);
1571
- }
1161
+ await api.markSliceStatus(modelId, sliceName, status);
1162
+ console.log(`Marked slice "${sliceName}" as ${status}`);
1572
1163
  break;
1573
1164
  }
1574
1165
  case 'summary':
@@ -1595,30 +1186,30 @@ EXAMPLES:
1595
1186
  `);
1596
1187
  process.exit(0);
1597
1188
  }
1598
- if (isCloudMode) {
1599
- const summary = await cloudSlices.getSummary(modelId);
1189
+ {
1190
+ const summary = await api.getSummary(modelId);
1600
1191
  if (format === 'json') {
1601
1192
  console.log(JSON.stringify(summary, null, 2));
1602
1193
  }
1603
1194
  else {
1604
- const name = summary.modelName || '';
1605
- console.log(`<model name="${name}">`);
1606
- console.log(` <slices count="${summary.slices.total}"/>`);
1607
- console.log(` <commands count="${summary.commands}"/>`);
1608
- console.log(` <events count="${summary.events}"/>`);
1609
- console.log(` <read-models count="${summary.readModels}"/>`);
1610
- console.log(` <screens count="${summary.screens}"/>`);
1611
- console.log(` <processors count="${summary.processors}"/>`);
1612
- console.log(` <aggregates count="${summary.aggregates}"/>`);
1613
- console.log(` <actors count="${summary.actors}"/>`);
1614
- console.log(` <scenarios count="${summary.scenarios}"/>`);
1615
- console.log(` <flows count="${summary.flows}"/>`);
1616
- 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());
1617
1211
  }
1618
1212
  }
1619
- else {
1620
- showModelSummary(model, format);
1621
- }
1622
1213
  break;
1623
1214
  case 'export':
1624
1215
  if (helpRequested && !subcommand) {
@@ -1658,13 +1249,10 @@ EXAMPLES:
1658
1249
  `);
1659
1250
  process.exit(0);
1660
1251
  }
1661
- if (isCloudMode) {
1662
- const result = await cloudSlices.exportJson(modelId);
1252
+ {
1253
+ const result = await api.exportJson(modelId);
1663
1254
  console.log(JSON.stringify(JSON.parse(result), null, 2));
1664
1255
  }
1665
- else {
1666
- exportEventmodelToJson(model);
1667
- }
1668
1256
  break;
1669
1257
  default:
1670
1258
  console.error(`Unknown export format: ${subcommand}`);
@@ -1756,7 +1344,7 @@ EXAMPLES:
1756
1344
  console.error('Run "eventmodeler add scenario --help" for detailed format.');
1757
1345
  process.exit(1);
1758
1346
  }
1759
- if (isCloudMode) {
1347
+ {
1760
1348
  let parsedScenario;
1761
1349
  try {
1762
1350
  parsedScenario = parseScenarioInput(inputData);
@@ -1800,12 +1388,9 @@ EXAMPLES:
1800
1388
  : undefined,
1801
1389
  },
1802
1390
  };
1803
- await cloudSlices.createScenario(modelId, sliceArg, scenario);
1391
+ await api.createScenario(modelId, sliceArg, scenario);
1804
1392
  console.log(`Created scenario "${scenario.name}" in slice "${sliceArg}"`);
1805
1393
  }
1806
- else {
1807
- addScenario(model, filePath, sliceArg, inputData);
1808
- }
1809
1394
  break;
1810
1395
  }
1811
1396
  case 'field': {
@@ -1814,14 +1399,10 @@ EXAMPLES:
1814
1399
  eventmodeler add field - Add a field to an entity
1815
1400
 
1816
1401
  USAGE:
1817
- eventmodeler add field --command|--event|--read-model|--screen|--processor <name> --json|--xml <data>
1402
+ eventmodeler add field <element-name> --json|--xml <data>
1818
1403
 
1819
1404
  OPTIONS:
1820
- --command <name> Target command name
1821
- --event <name> Target event name
1822
- --read-model <name> Target read model name
1823
- --screen <name> Target screen name
1824
- --processor <name> Target processor name
1405
+ <element-name> Name of the command, event, read model, screen, or processor
1825
1406
  --json <data> Field definition in JSON format
1826
1407
  --xml <data> Field definition in XML format
1827
1408
 
@@ -1898,28 +1479,31 @@ NOTES:
1898
1479
  - Subfields support arbitrary nesting depth
1899
1480
 
1900
1481
  EXAMPLES:
1901
- eventmodeler add field --event OrderPlaced --json '{"name": "orderId", "type": "UUID"}'
1902
- eventmodeler add field --read-model OrderSummary --json '{"name": "totalWithTax", "type": "Decimal", "isGenerated": true}'
1903
- 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>'
1904
1485
  `);
1905
1486
  process.exit(0);
1906
1487
  }
1907
- const commandArg = getNamedArg(filteredArgs, '--command');
1908
- const eventArg = getNamedArg(filteredArgs, '--event');
1909
- const readModelArg = getNamedArg(filteredArgs, '--read-model');
1910
- const screenArg = getNamedArg(filteredArgs, '--screen');
1911
- const processorArg = getNamedArg(filteredArgs, '--processor');
1912
1488
  const jsonArg = getNamedArg(filteredArgs, '--json');
1913
1489
  const xmlArg = getNamedArg(filteredArgs, '--xml');
1914
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
+ }
1915
1499
  if (!inputData) {
1916
1500
  console.error('Error: --json or --xml is required');
1917
- 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>');
1918
1502
  console.error('Run "eventmodeler add field --help" for detailed format documentation.');
1919
1503
  process.exit(1);
1920
1504
  }
1921
- if (isCloudMode) {
1922
- // Parse field data and determine element type
1505
+ {
1506
+ // Parse field data
1923
1507
  let field;
1924
1508
  try {
1925
1509
  if (jsonArg) {
@@ -1935,59 +1519,29 @@ EXAMPLES:
1935
1519
  };
1936
1520
  }
1937
1521
  else {
1938
- // XML parsing - extract field attributes
1939
- const nameMatch = inputData.match(/name="([^"]*)"/);
1940
- const typeMatch = inputData.match(/type="([^"]*)"/);
1941
- const isListMatch = inputData.match(/isList="([^"]*)"/);
1942
- const isOptionalMatch = inputData.match(/isOptional="([^"]*)"/);
1943
- const isGeneratedMatch = inputData.match(/isGenerated="([^"]*)"/);
1944
- const isUserInputMatch = inputData.match(/isUserInput="([^"]*)"/);
1945
- field = {
1946
- name: nameMatch?.[1] ?? '',
1947
- fieldType: typeMatch?.[1] ?? 'String',
1948
- isList: isListMatch?.[1] === 'true',
1949
- isOptional: isOptionalMatch?.[1] === 'true',
1950
- isGenerated: isGeneratedMatch?.[1] === 'true',
1951
- isUserInput: isUserInputMatch?.[1] === 'true',
1952
- };
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]);
1953
1537
  }
1954
1538
  }
1955
1539
  catch (err) {
1956
1540
  console.error(`Error parsing field data: ${err.message}`);
1957
1541
  process.exit(1);
1958
1542
  }
1959
- // Determine element type and name
1960
- let elementType;
1961
- let elementName;
1962
- if (commandArg) {
1963
- elementType = 'command';
1964
- elementName = commandArg;
1965
- }
1966
- else if (eventArg) {
1967
- elementType = 'event';
1968
- elementName = eventArg;
1969
- }
1970
- else if (readModelArg) {
1971
- elementType = 'readModel';
1972
- elementName = readModelArg;
1973
- }
1974
- else if (screenArg) {
1975
- elementType = 'screen';
1976
- elementName = screenArg;
1977
- }
1978
- else if (processorArg) {
1979
- elementType = 'processor';
1980
- elementName = processorArg;
1981
- }
1982
- else {
1983
- console.error('Error: Must specify one of --command, --event, --read-model, --screen, or --processor');
1984
- process.exit(1);
1985
- }
1986
- await cloudSlices.addField(modelId, elementType, elementName, field);
1987
- console.log(`Added field "${field.name}" to ${elementType} "${elementName}"`);
1988
- }
1989
- else {
1990
- 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}"`);
1991
1545
  }
1992
1546
  break;
1993
1547
  }
@@ -2049,13 +1603,8 @@ EXAMPLES:
2049
1603
  console.error('Run "eventmodeler remove scenario --help" for more information.');
2050
1604
  process.exit(1);
2051
1605
  }
2052
- if (isCloudMode) {
2053
- await cloudSlices.removeScenario(modelId, scenarioName, sliceArg);
2054
- console.log(`Removed scenario "${scenarioName}"${sliceArg ? ` from slice "${sliceArg}"` : ''}`);
2055
- }
2056
- else {
2057
- removeScenario(model, filePath, scenarioName, sliceArg);
2058
- }
1606
+ await api.removeScenario(modelId, scenarioName, sliceArg);
1607
+ console.log(`Removed scenario "${scenarioName}"${sliceArg ? ` from slice "${sliceArg}"` : ''}`);
2059
1608
  break;
2060
1609
  }
2061
1610
  case 'field': {
@@ -2064,67 +1613,36 @@ EXAMPLES:
2064
1613
  eventmodeler remove field - Remove a field from an entity
2065
1614
 
2066
1615
  USAGE:
2067
- eventmodeler remove field --command|--event|--read-model|--screen|--processor <name> --field <field-name>
1616
+ eventmodeler remove field <element-name> --field <field-name>
2068
1617
 
2069
1618
  OPTIONS:
2070
- --command <name> Target command name
2071
- --event <name> Target event name
2072
- --read-model <name> Target read model name
2073
- --screen <name> Target screen name
2074
- --processor <name> Target processor name
1619
+ <element-name> Name of the command, event, read model, screen, or processor
2075
1620
  --field <name> Field name to remove (required)
2076
1621
 
2077
1622
  EXAMPLES:
2078
- eventmodeler remove field --event OrderPlaced --field orderId
2079
- eventmodeler remove field --read-model "Order Summary" --field notes
1623
+ eventmodeler remove field OrderPlaced --field orderId
1624
+ eventmodeler remove field "Order Summary" --field notes
2080
1625
  `);
2081
1626
  process.exit(0);
2082
1627
  }
2083
- const commandArg = getNamedArg(filteredArgs, '--command');
2084
- const eventArg = getNamedArg(filteredArgs, '--event');
2085
- const readModelArg = getNamedArg(filteredArgs, '--read-model');
2086
- const screenArg = getNamedArg(filteredArgs, '--screen');
2087
- const processorArg = getNamedArg(filteredArgs, '--processor');
2088
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])));
2089
1631
  if (!fieldArg) {
2090
1632
  console.error('Error: --field is required');
2091
- 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>');
2092
1634
  console.error('Run "eventmodeler remove field --help" for more information.');
2093
1635
  process.exit(1);
2094
1636
  }
2095
- if (isCloudMode) {
2096
- // Determine element type and name
2097
- let elementType;
2098
- let elementName;
2099
- if (commandArg) {
2100
- elementType = 'command';
2101
- elementName = commandArg;
2102
- }
2103
- else if (eventArg) {
2104
- elementType = 'event';
2105
- elementName = eventArg;
2106
- }
2107
- else if (readModelArg) {
2108
- elementType = 'readModel';
2109
- elementName = readModelArg;
2110
- }
2111
- else if (screenArg) {
2112
- elementType = 'screen';
2113
- elementName = screenArg;
2114
- }
2115
- else if (processorArg) {
2116
- elementType = 'processor';
2117
- elementName = processorArg;
2118
- }
2119
- else {
2120
- console.error('Error: Must specify one of --command, --event, --read-model, --screen, or --processor');
2121
- process.exit(1);
2122
- }
2123
- await cloudSlices.removeField(modelId, elementType, elementName, fieldArg);
2124
- 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);
2125
1642
  }
2126
- else {
2127
- 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}"`);
2128
1646
  }
2129
1647
  break;
2130
1648
  }
@@ -2179,7 +1697,7 @@ XML FORMAT:
2179
1697
  NOTES:
2180
1698
  - Mappings define how fields flow from source to target
2181
1699
  - Fields marked as isGenerated=true don't need mappings
2182
- - Use "show completeness" to check mapping status
1700
+ - Use "show information-completeness <name>" to check mapping status
2183
1701
 
2184
1702
  EXAMPLES:
2185
1703
  eventmodeler map fields --flow "OrderPlaced→OrderSummary" --json '[{"from": "total", "to": "totalAmount"}]'
@@ -2204,7 +1722,7 @@ EXAMPLES:
2204
1722
  console.error('Run "eventmodeler map fields --help" for detailed format.');
2205
1723
  process.exit(1);
2206
1724
  }
2207
- if (isCloudMode) {
1725
+ {
2208
1726
  // Parse flow argument to extract source and target names
2209
1727
  const flowParts = flowArg.split(/→|->/).map(s => s.trim());
2210
1728
  if (flowParts.length !== 2) {
@@ -2219,28 +1737,23 @@ EXAMPLES:
2219
1737
  mappings = JSON.parse(inputData);
2220
1738
  }
2221
1739
  else {
2222
- // XML parsing - extract mapping attributes
2223
- const mappingMatches = inputData.match(/<mapping[^>]+>/g) || [];
2224
- mappings = mappingMatches.map(m => {
2225
- const fromMatch = m.match(/from="([^"]*)"/);
2226
- const toMatch = m.match(/to="([^"]*)"/);
2227
- return {
2228
- from: fromMatch?.[1] ?? '',
2229
- to: toMatch?.[1] ?? '',
2230
- };
2231
- });
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
+ }));
2232
1748
  }
2233
1749
  }
2234
1750
  catch (err) {
2235
1751
  console.error(`Error parsing mappings: ${err.message}`);
2236
1752
  process.exit(1);
2237
1753
  }
2238
- await cloudSlices.mapFields(modelId, sourceName, targetName, mappings);
1754
+ await api.mapFields(modelId, sourceName, targetName, mappings);
2239
1755
  console.log(`Mapped ${mappings.length} field(s) from "${sourceName}" to "${targetName}"`);
2240
1756
  }
2241
- else {
2242
- mapFields(model, filePath, flowArg, inputData);
2243
- }
2244
1757
  break;
2245
1758
  }
2246
1759
  default:
@@ -2272,22 +1785,18 @@ Run "eventmodeler update field --help" for detailed help.
2272
1785
  eventmodeler update field - Update field properties
2273
1786
 
2274
1787
  USAGE:
2275
- eventmodeler update field --command|--event|--read-model|--screen|--processor <name> --field <field-name> [updates]
1788
+ eventmodeler update field <element-name> --field <field-name> [updates]
2276
1789
 
2277
- TARGET OPTIONS (one required):
2278
- --command <name> Target command
2279
- --event <name> Target event
2280
- --read-model <name> Target read model
2281
- --screen <name> Target screen
2282
- --processor <name> Target processor
1790
+ OPTIONS:
1791
+ <element-name> Name of the command, event, read model, screen, or processor
2283
1792
 
2284
1793
  REQUIRED:
2285
- --field <name> Field to update
1794
+ --field <name> Field to update
2286
1795
 
2287
1796
  UPDATE OPTIONS (at least one required):
2288
1797
  --optional true|false Set isOptional flag
2289
1798
  --generated true|false Set isGenerated flag
2290
- --user-input true|false Set isUserInput flag (screen only)
1799
+ --user-input true|false Set isUserInput flag
2291
1800
  --type <type> Change field type
2292
1801
 
2293
1802
  FIELD FLAGS EXPLAINED:
@@ -2297,38 +1806,37 @@ FIELD FLAGS EXPLAINED:
2297
1806
 
2298
1807
  EXAMPLES:
2299
1808
  # Mark field as optional
2300
- eventmodeler update field --read-model OrderSummary --field notes --optional true
1809
+ eventmodeler update field OrderSummary --field notes --optional true
2301
1810
 
2302
1811
  # Mark field as generated (computed value, no mapping needed)
2303
- eventmodeler update field --read-model OrderSummary --field totalWithTax --generated true
1812
+ eventmodeler update field OrderSummary --field totalWithTax --generated true
2304
1813
 
2305
1814
  # Mark screen field as user input
2306
- eventmodeler update field --screen "Order Form" --field quantity --user-input true
1815
+ eventmodeler update field "Order Form" --field quantity --user-input true
2307
1816
 
2308
1817
  # Change field type
2309
- eventmodeler update field --event OrderPlaced --field amount --type Decimal
1818
+ eventmodeler update field OrderPlaced --field amount --type Decimal
2310
1819
  `);
2311
1820
  process.exit(0);
2312
1821
  }
2313
- const commandArg = getNamedArg(filteredArgs, '--command');
2314
- const eventArg = getNamedArg(filteredArgs, '--event');
2315
- const readModelArg = getNamedArg(filteredArgs, '--read-model');
2316
- const screenArg = getNamedArg(filteredArgs, '--screen');
2317
- const processorArg = getNamedArg(filteredArgs, '--processor');
2318
1822
  const fieldArg = getNamedArg(filteredArgs, '--field');
2319
1823
  const optionalArg = getNamedArg(filteredArgs, '--optional');
2320
1824
  const generatedArg = getNamedArg(filteredArgs, '--generated');
2321
1825
  const userInputArg = getNamedArg(filteredArgs, '--user-input');
2322
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])));
2323
1830
  if (!fieldArg) {
2324
1831
  console.error('Error: --field is required');
2325
- 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]');
2326
1833
  console.error('Run "eventmodeler update field --help" for detailed options.');
2327
1834
  process.exit(1);
2328
1835
  }
2329
- // --user-input is only valid for screens
2330
- if (userInputArg !== undefined && !screenArg) {
2331
- 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.');
2332
1840
  process.exit(1);
2333
1841
  }
2334
1842
  const updates = {};
@@ -2349,49 +1857,19 @@ EXAMPLES:
2349
1857
  console.error('Run "eventmodeler update field --help" for available options.');
2350
1858
  process.exit(1);
2351
1859
  }
2352
- if (isCloudMode) {
2353
- // Determine element type and name
2354
- let elementType;
2355
- let elementName;
2356
- if (commandArg) {
2357
- elementType = 'command';
2358
- elementName = commandArg;
2359
- }
2360
- else if (eventArg) {
2361
- elementType = 'event';
2362
- elementName = eventArg;
2363
- }
2364
- else if (readModelArg) {
2365
- elementType = 'readModel';
2366
- elementName = readModelArg;
2367
- }
2368
- else if (screenArg) {
2369
- elementType = 'screen';
2370
- elementName = screenArg;
2371
- }
2372
- else if (processorArg) {
2373
- elementType = 'processor';
2374
- elementName = processorArg;
2375
- }
2376
- else {
2377
- console.error('Error: Must specify one of --command, --event, --read-model, --screen, or --processor');
2378
- process.exit(1);
2379
- }
2380
- // Convert local updates format to cloud format
2381
- const cloudUpdates = {};
1860
+ {
1861
+ // Convert updates to API format
1862
+ const fieldUpdates = {};
2382
1863
  if (updates.optional !== undefined)
2383
- cloudUpdates.isOptional = updates.optional;
1864
+ fieldUpdates.isOptional = updates.optional;
2384
1865
  if (updates.generated !== undefined)
2385
- cloudUpdates.isGenerated = updates.generated;
1866
+ fieldUpdates.isGenerated = updates.generated;
2386
1867
  if (updates.userInput !== undefined)
2387
- cloudUpdates.isUserInput = updates.userInput;
1868
+ fieldUpdates.isUserInput = updates.userInput;
2388
1869
  if (updates.type !== undefined)
2389
- cloudUpdates.fieldType = updates.type;
2390
- await cloudSlices.updateField(modelId, elementType, elementName, fieldArg, cloudUpdates);
2391
- console.log(`Updated field "${fieldArg}" on ${elementType} "${elementName}"`);
2392
- }
2393
- else {
2394
- 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}"`);
2395
1873
  }
2396
1874
  break;
2397
1875
  }
@@ -2505,11 +1983,11 @@ EXAMPLES:
2505
1983
  console.error('Run "eventmodeler create state-change-slice --help" for detailed format.');
2506
1984
  process.exit(1);
2507
1985
  }
2508
- if (isCloudMode) {
1986
+ {
2509
1987
  // Parse XML input to extract structured data
2510
1988
  const parser = await import('./lib/slice-utils.js');
2511
1989
  const parsed = parser.parseStateChangeSliceXml(xmlArg);
2512
- const cloudInput = {
1990
+ const sliceInput = {
2513
1991
  sliceName: parsed.sliceName,
2514
1992
  after: parsed.after,
2515
1993
  before: parsed.before,
@@ -2517,7 +1995,7 @@ EXAMPLES:
2517
1995
  command: { name: parsed.command.name, fields: toCompoundFields(parsed.command.fields) },
2518
1996
  event: { name: parsed.event.name, fields: toCompoundFields(parsed.event.fields) },
2519
1997
  };
2520
- const result = await cloudSlices.createStateChangeSlice(modelId, cloudInput);
1998
+ const result = await api.createStateChangeSlice(modelId, sliceInput);
2521
1999
  console.log(`Created state-change slice "${parsed.sliceName}"`);
2522
2000
  console.log(` Screen: ${parsed.screen.name} (${parsed.screen.fields.length} fields)`);
2523
2001
  console.log(` Command: ${parsed.command.name} (${parsed.command.fields.length} fields)`);
@@ -2525,9 +2003,6 @@ EXAMPLES:
2525
2003
  console.log(` Screen -> Command mappings: ${result.screenToCommandMappings}`);
2526
2004
  console.log(` Command -> Event mappings: ${result.commandToEventMappings}`);
2527
2005
  }
2528
- else {
2529
- createStateChangeSlice(model, filePath, xmlArg);
2530
- }
2531
2006
  break;
2532
2007
  }
2533
2008
  case 'automation-slice': {
@@ -2608,11 +2083,11 @@ EXAMPLES:
2608
2083
  console.error('Run "eventmodeler create automation-slice --help" for detailed format.');
2609
2084
  process.exit(1);
2610
2085
  }
2611
- if (isCloudMode) {
2086
+ {
2612
2087
  // Parse XML input to extract structured data
2613
2088
  const parser = await import('./lib/slice-utils.js');
2614
2089
  const parsed = parser.parseAutomationSliceXml(xmlArg);
2615
- const cloudInput = {
2090
+ const sliceInput = {
2616
2091
  sliceName: parsed.sliceName,
2617
2092
  after: parsed.after,
2618
2093
  before: parsed.before,
@@ -2621,7 +2096,7 @@ EXAMPLES:
2621
2096
  command: { name: parsed.command.name, fields: toCompoundFields(parsed.command.fields) },
2622
2097
  event: { name: parsed.event.name, fields: toCompoundFields(parsed.event.fields) },
2623
2098
  };
2624
- const result = await cloudSlices.createAutomationSlice(modelId, cloudInput);
2099
+ const result = await api.createAutomationSlice(modelId, sliceInput);
2625
2100
  console.log(`Created automation slice "${parsed.sliceName}"`);
2626
2101
  console.log(` ReadModel: ${parsed.readModel.name} (${parsed.readModel.fields.length} fields)`);
2627
2102
  console.log(` Processor: ${parsed.processor.name}`);
@@ -2630,9 +2105,6 @@ EXAMPLES:
2630
2105
  console.log(` ReadModel -> Command mappings: ${result.readModelToCommandMappings}`);
2631
2106
  console.log(` Command -> Event mappings: ${result.commandToEventMappings}`);
2632
2107
  }
2633
- else {
2634
- createAutomationSlice(model, filePath, xmlArg);
2635
- }
2636
2108
  break;
2637
2109
  }
2638
2110
  case 'state-view-slice': {
@@ -2699,23 +2171,20 @@ EXAMPLES:
2699
2171
  console.error('Run "eventmodeler create state-view-slice --help" for detailed format.');
2700
2172
  process.exit(1);
2701
2173
  }
2702
- if (isCloudMode) {
2174
+ {
2703
2175
  // Parse XML input to extract structured data
2704
2176
  const parser = await import('./lib/slice-utils.js');
2705
2177
  const parsed = parser.parseStateViewSliceXml(xmlArg);
2706
- const cloudInput = {
2178
+ const sliceInput = {
2707
2179
  sliceName: parsed.sliceName,
2708
2180
  after: parsed.after,
2709
2181
  before: parsed.before,
2710
2182
  readModel: { name: parsed.readModel.name, fields: toCompoundFields(parsed.readModel.fields) },
2711
2183
  };
2712
- const result = await cloudSlices.createStateViewSlice(modelId, cloudInput);
2184
+ const result = await api.createStateViewSlice(modelId, sliceInput);
2713
2185
  console.log(`Created state-view slice "${parsed.sliceName}"`);
2714
2186
  console.log(` ReadModel: ${parsed.readModel.name} (${parsed.readModel.fields.length} fields)`);
2715
2187
  }
2716
- else {
2717
- createStateViewSlice(model, filePath, xmlArg);
2718
- }
2719
2188
  break;
2720
2189
  }
2721
2190
  case 'flow': {
@@ -2750,13 +2219,8 @@ EXAMPLES:
2750
2219
  console.error('Run "eventmodeler create flow --help" for more information.');
2751
2220
  process.exit(1);
2752
2221
  }
2753
- if (isCloudMode) {
2754
- await cloudSlices.createFlow(modelId, fromArg, toArg);
2755
- console.log(`Created flow from "${fromArg}" to "${toArg}"`);
2756
- }
2757
- else {
2758
- createFlow(model, filePath, fromArg, toArg);
2759
- }
2222
+ await api.createFlow(modelId, fromArg, toArg);
2223
+ console.log(`Created flow from "${fromArg}" to "${toArg}"`);
2760
2224
  break;
2761
2225
  }
2762
2226
  default:
@@ -2820,13 +2284,10 @@ EXAMPLES:
2820
2284
  console.error('Run "eventmodeler codegen slice --help" for more information.');
2821
2285
  process.exit(1);
2822
2286
  }
2823
- if (isCloudMode) {
2824
- const result = await cloudSlices.codegenSlice(modelId, sliceName);
2287
+ {
2288
+ const result = await api.codegenSlice(modelId, sliceName);
2825
2289
  console.log(JSON.stringify(JSON.parse(result), null, 2));
2826
2290
  }
2827
- else {
2828
- codegenSlice(model, sliceName);
2829
- }
2830
2291
  break;
2831
2292
  }
2832
2293
  case 'events': {
@@ -2858,13 +2319,10 @@ EXAMPLES:
2858
2319
  process.exit(0);
2859
2320
  }
2860
2321
  const chapterName = chapterArg ?? target;
2861
- if (isCloudMode) {
2862
- const output = await cloudSlices.codegenEvents(modelId, chapterName);
2322
+ {
2323
+ const output = await api.codegenEvents(modelId, chapterName);
2863
2324
  console.log(JSON.stringify(output, null, 2));
2864
2325
  }
2865
- else {
2866
- codegenEvents(model, chapterName);
2867
- }
2868
2326
  break;
2869
2327
  }
2870
2328
  default: