eventmodeler 0.3.10 → 0.4.1

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.
Files changed (62) hide show
  1. package/dist/cloud/slices/index.d.ts +215 -0
  2. package/dist/cloud/slices/index.js +247 -0
  3. package/dist/index.js +993 -40
  4. package/dist/lib/auth.d.ts +24 -0
  5. package/dist/lib/auth.js +332 -0
  6. package/dist/lib/backend.d.ts +48 -0
  7. package/dist/lib/backend.js +103 -0
  8. package/dist/lib/cloud-client.d.ts +70 -0
  9. package/dist/lib/cloud-client.js +528 -0
  10. package/dist/lib/config.d.ts +27 -0
  11. package/dist/lib/config.js +80 -11
  12. package/dist/lib/diff/three-way-merge.js +4 -4
  13. package/dist/lib/file-loader.js +43 -12
  14. package/dist/lib/project-config.d.ts +30 -0
  15. package/dist/lib/project-config.js +90 -0
  16. package/dist/lib/slice-utils.d.ts +28 -0
  17. package/dist/lib/slice-utils.js +80 -0
  18. package/dist/local/slices/index.d.ts +11 -0
  19. package/dist/local/slices/index.js +13 -0
  20. package/dist/projection.js +372 -371
  21. package/dist/slices/add-field/index.js +25 -15
  22. package/dist/slices/add-scenario/index.js +34 -22
  23. package/dist/slices/codegen-slice/index.js +5 -3
  24. package/dist/slices/create-automation-slice/index.js +93 -65
  25. package/dist/slices/create-flow/index.js +24 -18
  26. package/dist/slices/create-state-change-slice/index.js +77 -53
  27. package/dist/slices/create-state-view-slice/index.js +25 -17
  28. package/dist/slices/import/index.d.ts +8 -0
  29. package/dist/slices/import/index.js +63 -0
  30. package/dist/slices/init/index.d.ts +4 -0
  31. package/dist/slices/init/index.js +133 -0
  32. package/dist/slices/list-processors/index.d.ts +3 -0
  33. package/dist/slices/list-processors/index.js +20 -0
  34. package/dist/slices/list-readmodels/index.d.ts +3 -0
  35. package/dist/slices/list-readmodels/index.js +21 -0
  36. package/dist/slices/list-scenarios/index.d.ts +3 -0
  37. package/dist/slices/list-scenarios/index.js +35 -0
  38. package/dist/slices/list-screens/index.d.ts +3 -0
  39. package/dist/slices/list-screens/index.js +47 -0
  40. package/dist/slices/login/index.d.ts +1 -0
  41. package/dist/slices/login/index.js +24 -0
  42. package/dist/slices/logout/index.d.ts +1 -0
  43. package/dist/slices/logout/index.js +14 -0
  44. package/dist/slices/map-fields/index.js +5 -3
  45. package/dist/slices/mark-slice-status/index.js +4 -2
  46. package/dist/slices/remove-field/index.js +25 -15
  47. package/dist/slices/remove-scenario/index.js +8 -4
  48. package/dist/slices/show-aggregate/index.d.ts +3 -0
  49. package/dist/slices/show-aggregate/index.js +108 -0
  50. package/dist/slices/show-processor/index.d.ts +3 -0
  51. package/dist/slices/show-processor/index.js +111 -0
  52. package/dist/slices/show-readmodel/index.d.ts +3 -0
  53. package/dist/slices/show-readmodel/index.js +158 -0
  54. package/dist/slices/show-scenario/index.d.ts +3 -0
  55. package/dist/slices/show-scenario/index.js +196 -0
  56. package/dist/slices/show-screen/index.d.ts +3 -0
  57. package/dist/slices/show-screen/index.js +139 -0
  58. package/dist/slices/update-field/index.js +30 -20
  59. package/dist/slices/whoami/index.d.ts +2 -0
  60. package/dist/slices/whoami/index.js +35 -0
  61. package/dist/types.d.ts +1 -2
  62. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -31,6 +31,15 @@ import { mapFields } from './slices/map-fields/index.js';
31
31
  import { updateField } from './slices/update-field/index.js';
32
32
  import { showAggregateCompleteness, listAggregates } from './slices/show-aggregate-completeness/index.js';
33
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';
34
43
  import { createStateChangeSlice } from './slices/create-state-change-slice/index.js';
35
44
  import { createAutomationSlice } from './slices/create-automation-slice/index.js';
36
45
  import { createStateViewSlice } from './slices/create-state-view-slice/index.js';
@@ -39,6 +48,15 @@ import { codegenSlice } from './slices/codegen-slice/index.js';
39
48
  import { diff } from './slices/diff/index.js';
40
49
  import { merge } from './slices/merge/index.js';
41
50
  import { gitSetup, gitStatus } from './slices/git/index.js';
51
+ import { importModel } from './slices/import/index.js';
52
+ // Auth and cloud commands
53
+ import { login } from './slices/login/index.js';
54
+ import { logout } from './slices/logout/index.js';
55
+ import { whoami } from './slices/whoami/index.js';
56
+ import { init } from './slices/init/index.js';
57
+ // Cloud slices
58
+ import * as cloudSlices from './cloud/slices/index.js';
59
+ import { loadProjectConfig } from './lib/project-config.js';
42
60
  const args = process.argv.slice(2);
43
61
  function getNamedArg(argList, ...names) {
44
62
  for (let i = 0; i < argList.length; i++) {
@@ -59,6 +77,14 @@ USAGE:
59
77
  eventmodeler Open the Event Modeling app in browser
60
78
  eventmodeler <command> [options] Run a CLI command
61
79
 
80
+ AUTHENTICATION:
81
+ login Authenticate with eventmodeler.app
82
+ logout Sign out
83
+ whoami Show authentication status
84
+
85
+ PROJECT SETUP:
86
+ init Initialize project (link to cloud or local model)
87
+
62
88
  COMMANDS:
63
89
  list slices [--chapter <name>] List all slices (optionally filtered by chapter)
64
90
  list events List all events
@@ -66,6 +92,10 @@ COMMANDS:
66
92
  list chapters List all chapters
67
93
  list aggregates List all aggregates
68
94
  list actors List all actors
95
+ list readmodels List all read models
96
+ list screens List all screens
97
+ list processors List all processors
98
+ list scenarios List all scenarios
69
99
 
70
100
  show slice <name> Show slice with components, flow annotations, and
71
101
  inbound/outbound dependencies
@@ -78,6 +108,11 @@ COMMANDS:
78
108
  show aggregate-completeness <name>
79
109
  Show if events in aggregate have the ID field
80
110
  show actor <name> Show actor with its screens
111
+ show readmodel <name> Show read model with fields and flows
112
+ show screen <name> Show screen with fields and connections
113
+ show processor <name> Show processor with subscriptions and commands
114
+ show aggregate <name> Show aggregate with events and ID field status
115
+ show scenario <name> Show scenario with Given-When-Then details
81
116
 
82
117
  search <term> Search for entities by name
83
118
 
@@ -115,6 +150,9 @@ COMMANDS:
115
150
 
116
151
  export json Export entire model as JSON
117
152
 
153
+ IMPORT/EXPORT:
154
+ import <file> [--name <name>] Import .eventmodel file to cloud (creates new model)
155
+
118
156
  GIT INTEGRATION:
119
157
  git setup Configure git to use semantic diff/merge for .eventmodel files
120
158
  git setup --global Configure globally (for all repos)
@@ -340,6 +378,136 @@ EXAMPLES:
340
378
  });
341
379
  return;
342
380
  }
381
+ // Auth commands (no file needed)
382
+ if (command === 'login') {
383
+ if (helpRequested) {
384
+ console.log(`
385
+ eventmodeler login - Authenticate with eventmodeler.app
386
+
387
+ USAGE:
388
+ eventmodeler login
389
+
390
+ Opens your browser for authentication via Keycloak.
391
+ Credentials are stored securely in ~/.eventmodeler/config.json
392
+
393
+ After login, you can:
394
+ - Use "eventmodeler init" to connect a project to a cloud model
395
+ - Access cloud-hosted event models
396
+
397
+ EXAMPLES:
398
+ eventmodeler login
399
+ `);
400
+ process.exit(0);
401
+ }
402
+ await login();
403
+ return;
404
+ }
405
+ if (command === 'logout') {
406
+ if (helpRequested) {
407
+ console.log(`
408
+ eventmodeler logout - Sign out of eventmodeler.app
409
+
410
+ USAGE:
411
+ eventmodeler logout
412
+
413
+ Clears stored credentials from ~/.eventmodeler/config.json
414
+
415
+ EXAMPLES:
416
+ eventmodeler logout
417
+ `);
418
+ process.exit(0);
419
+ }
420
+ logout();
421
+ return;
422
+ }
423
+ if (command === 'whoami') {
424
+ if (helpRequested) {
425
+ console.log(`
426
+ eventmodeler whoami - Show current authentication status
427
+
428
+ USAGE:
429
+ eventmodeler whoami [--format xml|json]
430
+
431
+ OPTIONS:
432
+ --format <format> Output format: xml (default) or json
433
+
434
+ OUTPUT:
435
+ Shows whether you're logged in and your email address.
436
+
437
+ EXAMPLES:
438
+ eventmodeler whoami
439
+ eventmodeler whoami --format json
440
+ `);
441
+ process.exit(0);
442
+ }
443
+ whoami(format);
444
+ return;
445
+ }
446
+ if (command === 'init') {
447
+ if (helpRequested) {
448
+ console.log(`
449
+ eventmodeler init - Initialize a project
450
+
451
+ USAGE:
452
+ eventmodeler init
453
+
454
+ Interactive setup to connect this directory to an event model.
455
+ Creates a .eventmodeler.json config file in your project root.
456
+
457
+ OPTIONS:
458
+ 1. Cloud - Link to an event model on eventmodeler.app
459
+ 2. Local - Use a local .eventmodel file
460
+
461
+ PREREQUISITES:
462
+ - For cloud mode, you must be logged in (run "eventmodeler login" first)
463
+
464
+ EXAMPLES:
465
+ cd my-project
466
+ eventmodeler init
467
+ `);
468
+ process.exit(0);
469
+ }
470
+ await init();
471
+ return;
472
+ }
473
+ if (command === 'import') {
474
+ if (helpRequested) {
475
+ console.log(`
476
+ eventmodeler import - Import .eventmodel file to cloud
477
+
478
+ USAGE:
479
+ eventmodeler import <file> [--name <name>]
480
+
481
+ ARGUMENTS:
482
+ <file> Path to .eventmodel file to import
483
+
484
+ OPTIONS:
485
+ --name <name> Override model name (default: derived from file or EventModelCreated event)
486
+
487
+ DESCRIPTION:
488
+ Imports a local .eventmodel file to the cloud backend, creating a new
489
+ cloud-hosted model. All events are preserved except EventModelCreated,
490
+ which is regenerated with a new modelId.
491
+
492
+ PREREQUISITES:
493
+ - Must be logged in (run "eventmodeler login" first)
494
+
495
+ EXAMPLES:
496
+ eventmodeler import mymodel.eventmodel
497
+ eventmodeler import ./models/order-system.eventmodel --name "Order System"
498
+ `);
499
+ process.exit(0);
500
+ }
501
+ const importFilePath = subcommand;
502
+ if (!importFilePath) {
503
+ console.error('Usage: eventmodeler import <file> [--name <name>]');
504
+ console.error('Run "eventmodeler import --help" for more information.');
505
+ process.exit(1);
506
+ }
507
+ const importName = getNamedArg(filteredArgs, '--name', '-n');
508
+ await importModel(importFilePath, { name: importName });
509
+ return;
510
+ }
343
511
  if (command === 'git') {
344
512
  const gitCommand = filteredArgs[1];
345
513
  const globalFlag = filteredArgs.includes('--global');
@@ -420,17 +588,33 @@ EXAMPLES:
420
588
  process.exit(1);
421
589
  }
422
590
  }
423
- const filePath = fileArg ?? await findEventModelFile();
424
- if (!filePath) {
425
- console.error('Error: No .eventmodel file found in current directory.');
426
- console.error('Use -f <path> to specify a file or run in a directory with an .eventmodel file.');
427
- process.exit(1);
428
- }
429
- if (!fs.existsSync(filePath)) {
430
- console.error(`Error: File not found: ${filePath}`);
431
- process.exit(1);
591
+ // Determine backend mode: cloud or local
592
+ const projectConfig = loadProjectConfig();
593
+ const isCloudMode = projectConfig?.type === 'cloud' && !fileArg;
594
+ const modelId = isCloudMode ? projectConfig.modelId : null;
595
+ // For local mode, we need to load the model from file
596
+ // For cloud mode, we call backend endpoints directly (no model loading)
597
+ let model = null;
598
+ let filePath = null;
599
+ if (!isCloudMode) {
600
+ // Local mode - load model from file
601
+ if (projectConfig?.type === 'local') {
602
+ filePath = fileArg ?? projectConfig.file;
603
+ }
604
+ else {
605
+ filePath = fileArg ?? await findEventModelFile();
606
+ }
607
+ if (!filePath) {
608
+ console.error('Error: No .eventmodel file found in current directory.');
609
+ console.error('Use -f <path> to specify a file or run "eventmodeler init" to set up a project.');
610
+ process.exit(1);
611
+ }
612
+ if (!fs.existsSync(filePath)) {
613
+ console.error(`Error: File not found: ${filePath}`);
614
+ process.exit(1);
615
+ }
616
+ model = loadModel(filePath);
432
617
  }
433
- const model = loadModel(filePath);
434
618
  switch (command) {
435
619
  case 'list':
436
620
  if (helpRequested && !subcommand) {
@@ -447,6 +631,9 @@ TYPES:
447
631
  chapters List all chapters
448
632
  aggregates List all aggregates
449
633
  actors List all actors
634
+ readmodels List all read models
635
+ screens List all screens
636
+ processors List all processors
450
637
 
451
638
  OPTIONS:
452
639
  --chapter <name> Filter slices by chapter (slices only)
@@ -487,7 +674,13 @@ EXAMPLES:
487
674
  `);
488
675
  process.exit(0);
489
676
  }
490
- listSlices(model, format, chapterArg ?? undefined);
677
+ if (isCloudMode) {
678
+ const output = await cloudSlices.listSlices(modelId, format, chapterArg ?? undefined);
679
+ console.log(output);
680
+ }
681
+ else {
682
+ listSlices(model, format, chapterArg ?? undefined);
683
+ }
491
684
  break;
492
685
  case 'events':
493
686
  if (helpRequested) {
@@ -512,7 +705,13 @@ EXAMPLES:
512
705
  `);
513
706
  process.exit(0);
514
707
  }
515
- listEvents(model, format);
708
+ if (isCloudMode) {
709
+ const output = await cloudSlices.listEvents(modelId, format);
710
+ console.log(output);
711
+ }
712
+ else {
713
+ listEvents(model, format);
714
+ }
516
715
  break;
517
716
  case 'commands':
518
717
  if (helpRequested) {
@@ -535,7 +734,13 @@ EXAMPLES:
535
734
  `);
536
735
  process.exit(0);
537
736
  }
538
- listCommands(model, format);
737
+ if (isCloudMode) {
738
+ const output = await cloudSlices.listCommands(modelId, format);
739
+ console.log(output);
740
+ }
741
+ else {
742
+ listCommands(model, format);
743
+ }
539
744
  break;
540
745
  case 'chapters':
541
746
  if (helpRequested) {
@@ -558,7 +763,13 @@ EXAMPLES:
558
763
  `);
559
764
  process.exit(0);
560
765
  }
561
- listChapters(model, format);
766
+ if (isCloudMode) {
767
+ const output = await cloudSlices.listChapters(modelId, format);
768
+ console.log(output);
769
+ }
770
+ else {
771
+ listChapters(model, format);
772
+ }
562
773
  break;
563
774
  case 'aggregates':
564
775
  if (helpRequested) {
@@ -582,7 +793,13 @@ EXAMPLES:
582
793
  `);
583
794
  process.exit(0);
584
795
  }
585
- listAggregates(model, format);
796
+ if (isCloudMode) {
797
+ const result = await cloudSlices.listAggregates(modelId, format);
798
+ console.log(result);
799
+ }
800
+ else {
801
+ listAggregates(model, format);
802
+ }
586
803
  break;
587
804
  case 'actors':
588
805
  if (helpRequested) {
@@ -605,11 +822,116 @@ EXAMPLES:
605
822
  `);
606
823
  process.exit(0);
607
824
  }
825
+ if (isCloudMode) {
826
+ const output = await cloudSlices.listActors(modelId, format);
827
+ console.log(output);
828
+ break;
829
+ }
608
830
  listActors(model, format);
609
831
  break;
832
+ case 'readmodels':
833
+ if (helpRequested) {
834
+ console.log(`
835
+ eventmodeler list readmodels - List all read models
836
+
837
+ USAGE:
838
+ eventmodeler list readmodels [--format xml|json]
839
+
840
+ OUTPUT:
841
+ Lists read models with id, name, and field count.
842
+ Excludes linked copies (shows only canonical read models).
843
+
844
+ EXAMPLES:
845
+ eventmodeler list readmodels
846
+ eventmodeler list readmodels --format json
847
+ `);
848
+ process.exit(0);
849
+ }
850
+ if (isCloudMode) {
851
+ const output = await cloudSlices.listReadModels(modelId, format);
852
+ console.log(output);
853
+ break;
854
+ }
855
+ listReadModels(model, format);
856
+ break;
857
+ case 'screens':
858
+ if (helpRequested) {
859
+ console.log(`
860
+ eventmodeler list screens - List all screens
861
+
862
+ USAGE:
863
+ eventmodeler list screens [--format xml|json]
864
+
865
+ OUTPUT:
866
+ Lists screens with id, name, field count, and actor (if in one).
867
+ Excludes linked copies (shows only canonical screens).
868
+
869
+ EXAMPLES:
870
+ eventmodeler list screens
871
+ eventmodeler list screens --format json
872
+ `);
873
+ process.exit(0);
874
+ }
875
+ if (isCloudMode) {
876
+ const output = await cloudSlices.listScreens(modelId, format);
877
+ console.log(output);
878
+ break;
879
+ }
880
+ listScreens(model, format);
881
+ break;
882
+ case 'processors':
883
+ if (helpRequested) {
884
+ console.log(`
885
+ eventmodeler list processors - List all processors
886
+
887
+ USAGE:
888
+ eventmodeler list processors [--format xml|json]
889
+
890
+ OUTPUT:
891
+ Lists processors with id, name, and field count.
892
+
893
+ EXAMPLES:
894
+ eventmodeler list processors
895
+ eventmodeler list processors --format json
896
+ `);
897
+ process.exit(0);
898
+ }
899
+ if (isCloudMode) {
900
+ const output = await cloudSlices.listProcessors(modelId, format);
901
+ console.log(output);
902
+ break;
903
+ }
904
+ listProcessors(model, format);
905
+ break;
906
+ case 'scenarios':
907
+ if (helpRequested) {
908
+ console.log(`
909
+ eventmodeler list scenarios - List all scenarios
910
+
911
+ USAGE:
912
+ eventmodeler list scenarios [--format xml|json]
913
+
914
+ OUTPUT:
915
+ - Scenario name
916
+ - Parent slice
917
+ - Then type (events, error, command, etc.)
918
+
919
+ EXAMPLES:
920
+ eventmodeler list scenarios
921
+ eventmodeler list scenarios --format json
922
+ `);
923
+ process.exit(0);
924
+ }
925
+ if (isCloudMode) {
926
+ const output = await cloudSlices.listScenarios(modelId, format);
927
+ console.log(output);
928
+ break;
929
+ }
930
+ listScenarios(model, format);
931
+ break;
610
932
  default:
611
933
  console.error(`Unknown list target: ${subcommand}`);
612
- console.error('Valid targets: slices, events, commands, chapters, aggregates, actors');
934
+ console.error('Valid targets: slices, events, commands, chapters, aggregates, actors, readmodels, screens, processors, scenarios');
613
935
  console.error('Run "eventmodeler list --help" for more information.');
614
936
  process.exit(1);
615
937
  }
@@ -631,6 +953,11 @@ TYPES:
631
953
  model-completeness Show completeness of all flows
632
954
  aggregate-completeness Show if events have aggregate ID field
633
955
  actor Show actor with screens
956
+ readmodel Show read model with fields and flows
957
+ screen Show screen with fields and connections
958
+ processor Show processor with subscriptions and commands
959
+ aggregate Show aggregate with events and ID field status
960
+ scenario Show scenario with Given-When-Then details
634
961
 
635
962
  OPTIONS:
636
963
  --format xml|json Output format (default: xml)
@@ -677,7 +1004,13 @@ EXAMPLES:
677
1004
  console.error('Run "eventmodeler show slice --help" for more information.');
678
1005
  process.exit(1);
679
1006
  }
680
- showSlice(model, target, format);
1007
+ if (isCloudMode) {
1008
+ const result = await cloudSlices.showSlice(modelId, target, format);
1009
+ console.log(result);
1010
+ }
1011
+ else {
1012
+ showSlice(model, target, format);
1013
+ }
681
1014
  break;
682
1015
  case 'event':
683
1016
  if (helpRequested) {
@@ -719,7 +1052,13 @@ EXAMPLES:
719
1052
  console.error('Run "eventmodeler show event --help" for more information.');
720
1053
  process.exit(1);
721
1054
  }
722
- showEvent(model, target, format);
1055
+ if (isCloudMode) {
1056
+ const result = await cloudSlices.showEvent(modelId, target, format);
1057
+ console.log(result);
1058
+ }
1059
+ else {
1060
+ showEvent(model, target, format);
1061
+ }
723
1062
  break;
724
1063
  case 'command':
725
1064
  if (helpRequested) {
@@ -747,7 +1086,13 @@ EXAMPLES:
747
1086
  console.error('Run "eventmodeler show command --help" for more information.');
748
1087
  process.exit(1);
749
1088
  }
750
- showCommand(model, target, format);
1089
+ if (isCloudMode) {
1090
+ const result = await cloudSlices.showCommand(modelId, target, format);
1091
+ console.log(result);
1092
+ }
1093
+ else {
1094
+ showCommand(model, target, format);
1095
+ }
751
1096
  break;
752
1097
  case 'chapter':
753
1098
  if (helpRequested) {
@@ -776,7 +1121,13 @@ EXAMPLES:
776
1121
  console.error('Run "eventmodeler show chapter --help" for more information.');
777
1122
  process.exit(1);
778
1123
  }
779
- showChapter(model, target, format);
1124
+ if (isCloudMode) {
1125
+ const result = await cloudSlices.showChapter(modelId, target, format);
1126
+ console.log(result);
1127
+ }
1128
+ else {
1129
+ showChapter(model, target, format);
1130
+ }
780
1131
  break;
781
1132
  case 'completeness':
782
1133
  if (helpRequested) {
@@ -811,7 +1162,13 @@ EXAMPLES:
811
1162
  console.error('Run "eventmodeler show completeness --help" for more information.');
812
1163
  process.exit(1);
813
1164
  }
814
- showCompleteness(model, target, format);
1165
+ if (isCloudMode) {
1166
+ const result = await cloudSlices.showCompleteness(modelId, target, format);
1167
+ console.log(result);
1168
+ }
1169
+ else {
1170
+ showCompleteness(model, target, format);
1171
+ }
815
1172
  break;
816
1173
  case 'model-completeness':
817
1174
  if (helpRequested) {
@@ -834,7 +1191,13 @@ EXAMPLES:
834
1191
  `);
835
1192
  process.exit(0);
836
1193
  }
837
- showModelCompleteness(model, format);
1194
+ if (isCloudMode) {
1195
+ const result = await cloudSlices.showModelCompleteness(modelId, format);
1196
+ console.log(result);
1197
+ }
1198
+ else {
1199
+ showModelCompleteness(model, format);
1200
+ }
838
1201
  break;
839
1202
  case 'aggregate-completeness':
840
1203
  if (helpRequested) {
@@ -862,7 +1225,13 @@ EXAMPLES:
862
1225
  console.error('Run "eventmodeler show aggregate-completeness --help" for more information.');
863
1226
  process.exit(1);
864
1227
  }
865
- showAggregateCompleteness(model, target, format);
1228
+ if (isCloudMode) {
1229
+ const result = await cloudSlices.showAggregateCompleteness(modelId, target, format);
1230
+ console.log(result);
1231
+ }
1232
+ else {
1233
+ showAggregateCompleteness(model, target, format);
1234
+ }
866
1235
  break;
867
1236
  case 'actor':
868
1237
  if (helpRequested) {
@@ -890,11 +1259,196 @@ EXAMPLES:
890
1259
  console.error('Run "eventmodeler show actor --help" for more information.');
891
1260
  process.exit(1);
892
1261
  }
893
- showActor(model, target, format);
1262
+ if (isCloudMode) {
1263
+ const result = await cloudSlices.showActor(modelId, target, format);
1264
+ console.log(result);
1265
+ }
1266
+ else {
1267
+ showActor(model, target, format);
1268
+ }
1269
+ break;
1270
+ case 'readmodel':
1271
+ if (helpRequested) {
1272
+ console.log(`
1273
+ eventmodeler show readmodel - Show detailed read model information
1274
+
1275
+ USAGE:
1276
+ eventmodeler show readmodel <name> [--format xml|json]
1277
+
1278
+ ARGUMENTS:
1279
+ <name> Read model name
1280
+
1281
+ OUTPUT INCLUDES:
1282
+ - Read model name and fields
1283
+ - Events it consumes from (with field mappings)
1284
+ - Screens/Processors it flows to
1285
+
1286
+ EXAMPLES:
1287
+ eventmodeler show readmodel OrderSummary
1288
+ eventmodeler show readmodel "Customer Profile" --format json
1289
+ `);
1290
+ process.exit(0);
1291
+ }
1292
+ if (!target) {
1293
+ console.error('Usage: eventmodeler show readmodel <name>');
1294
+ console.error('Run "eventmodeler show readmodel --help" for more information.');
1295
+ process.exit(1);
1296
+ }
1297
+ if (isCloudMode) {
1298
+ const result = await cloudSlices.showReadModel(modelId, target, format);
1299
+ console.log(result);
1300
+ }
1301
+ else {
1302
+ showReadModel(model, target, format);
1303
+ }
1304
+ break;
1305
+ case 'screen':
1306
+ if (helpRequested) {
1307
+ console.log(`
1308
+ eventmodeler show screen - Show detailed screen information
1309
+
1310
+ USAGE:
1311
+ eventmodeler show screen <name> [--format xml|json]
1312
+
1313
+ ARGUMENTS:
1314
+ <name> Screen name
1315
+
1316
+ OUTPUT INCLUDES:
1317
+ - Screen name and fields
1318
+ - Actor (if contained in one)
1319
+ - Read models it displays from
1320
+ - Commands it triggers
1321
+
1322
+ EXAMPLES:
1323
+ eventmodeler show screen "Order Form"
1324
+ eventmodeler show screen Dashboard --format json
1325
+ `);
1326
+ process.exit(0);
1327
+ }
1328
+ if (!target) {
1329
+ console.error('Usage: eventmodeler show screen <name>');
1330
+ console.error('Run "eventmodeler show screen --help" for more information.');
1331
+ process.exit(1);
1332
+ }
1333
+ if (isCloudMode) {
1334
+ const result = await cloudSlices.showScreen(modelId, target, format);
1335
+ console.log(result);
1336
+ }
1337
+ else {
1338
+ showScreen(model, target, format);
1339
+ }
1340
+ break;
1341
+ case 'processor':
1342
+ if (helpRequested) {
1343
+ console.log(`
1344
+ eventmodeler show processor - Show detailed processor information
1345
+
1346
+ USAGE:
1347
+ eventmodeler show processor <name> [--format xml|json]
1348
+
1349
+ ARGUMENTS:
1350
+ <name> Processor name
1351
+
1352
+ OUTPUT INCLUDES:
1353
+ - Processor name and fields
1354
+ - Read models it subscribes to
1355
+ - Commands it triggers
1356
+
1357
+ EXAMPLES:
1358
+ eventmodeler show processor "Order Validator"
1359
+ eventmodeler show processor NotificationSender --format json
1360
+ `);
1361
+ process.exit(0);
1362
+ }
1363
+ if (!target) {
1364
+ console.error('Usage: eventmodeler show processor <name>');
1365
+ console.error('Run "eventmodeler show processor --help" for more information.');
1366
+ process.exit(1);
1367
+ }
1368
+ if (isCloudMode) {
1369
+ const result = await cloudSlices.showProcessor(modelId, target, format);
1370
+ console.log(result);
1371
+ }
1372
+ else {
1373
+ showProcessor(model, target, format);
1374
+ }
1375
+ break;
1376
+ case 'aggregate':
1377
+ if (helpRequested) {
1378
+ console.log(`
1379
+ eventmodeler show aggregate - Show detailed aggregate information
1380
+
1381
+ USAGE:
1382
+ eventmodeler show aggregate <name> [--format xml|json]
1383
+
1384
+ ARGUMENTS:
1385
+ <name> Aggregate name
1386
+
1387
+ OUTPUT INCLUDES:
1388
+ - Aggregate name
1389
+ - ID field configuration (if set)
1390
+ - All contained events
1391
+ - ID field completeness status
1392
+
1393
+ EXAMPLES:
1394
+ eventmodeler show aggregate Order
1395
+ eventmodeler show aggregate "User Account" --format json
1396
+ `);
1397
+ process.exit(0);
1398
+ }
1399
+ if (!target) {
1400
+ console.error('Usage: eventmodeler show aggregate <name>');
1401
+ console.error('Run "eventmodeler show aggregate --help" for more information.');
1402
+ process.exit(1);
1403
+ }
1404
+ if (isCloudMode) {
1405
+ const result = await cloudSlices.showAggregate(modelId, target, format);
1406
+ console.log(result);
1407
+ }
1408
+ else {
1409
+ showAggregate(model, target, format);
1410
+ }
1411
+ break;
1412
+ case 'scenario':
1413
+ if (helpRequested) {
1414
+ console.log(`
1415
+ eventmodeler show scenario - Show detailed scenario information
1416
+
1417
+ USAGE:
1418
+ eventmodeler show scenario <name> [--format xml|json]
1419
+
1420
+ ARGUMENTS:
1421
+ <name> Scenario name
1422
+
1423
+ OUTPUT INCLUDES:
1424
+ - Scenario name and description
1425
+ - Parent slice
1426
+ - Given events (with field values)
1427
+ - When command or events (with field values)
1428
+ - Then expectations (events, error, command, etc.)
1429
+
1430
+ EXAMPLES:
1431
+ eventmodeler show scenario "Happy path"
1432
+ eventmodeler show scenario "Invalid input" --format json
1433
+ `);
1434
+ process.exit(0);
1435
+ }
1436
+ if (!target) {
1437
+ console.error('Usage: eventmodeler show scenario <name>');
1438
+ console.error('Run "eventmodeler show scenario --help" for more information.');
1439
+ process.exit(1);
1440
+ }
1441
+ if (isCloudMode) {
1442
+ const result = await cloudSlices.showScenario(modelId, target, format);
1443
+ console.log(result);
1444
+ }
1445
+ else {
1446
+ showScenario(model, target, format);
1447
+ }
894
1448
  break;
895
1449
  default:
896
1450
  console.error(`Unknown show target: ${subcommand}`);
897
- console.error('Valid targets: slice, event, command, chapter, completeness, model-completeness, aggregate-completeness, actor');
1451
+ console.error('Valid targets: slice, event, command, chapter, completeness, model-completeness, aggregate-completeness, actor, readmodel, screen, processor, aggregate, scenario');
898
1452
  console.error('Run "eventmodeler show --help" for more information.');
899
1453
  process.exit(1);
900
1454
  }
@@ -935,7 +1489,24 @@ EXAMPLES:
935
1489
  console.error('Run "eventmodeler search --help" for more information.');
936
1490
  process.exit(1);
937
1491
  }
938
- search(model, subcommand, format);
1492
+ if (isCloudMode) {
1493
+ const response = await cloudSlices.search(modelId, subcommand);
1494
+ if (format === 'json') {
1495
+ console.log(JSON.stringify(response, null, 2));
1496
+ }
1497
+ else {
1498
+ const esc = (s) => s.replace(/&/g, '&amp;').replace(/"/g, '&quot;').replace(/</g, '&lt;').replace(/>/g, '&gt;');
1499
+ console.log(`<search-results query="${esc(subcommand)}" count="${response.results.length}">`);
1500
+ for (const r of response.results) {
1501
+ const tag = r.type === 'readmodel' ? 'read-model' : r.type;
1502
+ console.log(` <${tag} name="${esc(r.name)}"/>`);
1503
+ }
1504
+ console.log('</search-results>');
1505
+ }
1506
+ }
1507
+ else {
1508
+ search(model, subcommand, format);
1509
+ }
939
1510
  break;
940
1511
  case 'mark': {
941
1512
  if (helpRequested) {
@@ -975,7 +1546,15 @@ EXAMPLES:
975
1546
  }
976
1547
  const sliceName = allArgs.slice(0, -1).join(' ');
977
1548
  const status = lastArg;
978
- markSliceStatus(model, filePath, sliceName, status);
1549
+ if (isCloudMode) {
1550
+ // Cloud mode - backend resolves name to ID
1551
+ await cloudSlices.markSliceStatus(modelId, sliceName, status);
1552
+ console.log(`Marked slice "${sliceName}" as ${status}`);
1553
+ }
1554
+ else {
1555
+ // Local mode
1556
+ markSliceStatus(model, filePath, sliceName, status);
1557
+ }
979
1558
  break;
980
1559
  }
981
1560
  case 'summary':
@@ -1002,7 +1581,30 @@ EXAMPLES:
1002
1581
  `);
1003
1582
  process.exit(0);
1004
1583
  }
1005
- showModelSummary(model, format);
1584
+ if (isCloudMode) {
1585
+ const summary = await cloudSlices.getSummary(modelId);
1586
+ if (format === 'json') {
1587
+ console.log(JSON.stringify(summary, null, 2));
1588
+ }
1589
+ else {
1590
+ const name = summary.modelName || '';
1591
+ console.log(`<model name="${name}">`);
1592
+ console.log(` <slices count="${summary.slices.total}"/>`);
1593
+ console.log(` <commands count="${summary.commands}"/>`);
1594
+ console.log(` <events count="${summary.events}"/>`);
1595
+ console.log(` <read-models count="${summary.readModels}"/>`);
1596
+ console.log(` <screens count="${summary.screens}"/>`);
1597
+ console.log(` <processors count="${summary.processors}"/>`);
1598
+ console.log(` <aggregates count="${summary.aggregates}"/>`);
1599
+ console.log(` <actors count="${summary.actors}"/>`);
1600
+ console.log(` <scenarios count="${summary.scenarios}"/>`);
1601
+ console.log(` <flows count="${summary.flows}"/>`);
1602
+ console.log('</model>');
1603
+ }
1604
+ }
1605
+ else {
1606
+ showModelSummary(model, format);
1607
+ }
1006
1608
  break;
1007
1609
  case 'export':
1008
1610
  if (helpRequested && !subcommand) {
@@ -1042,7 +1644,13 @@ EXAMPLES:
1042
1644
  `);
1043
1645
  process.exit(0);
1044
1646
  }
1045
- exportEventmodelToJson(model);
1647
+ if (isCloudMode) {
1648
+ const result = await cloudSlices.exportJson(modelId);
1649
+ console.log(JSON.stringify(JSON.parse(result), null, 2));
1650
+ }
1651
+ else {
1652
+ exportEventmodelToJson(model);
1653
+ }
1046
1654
  break;
1047
1655
  default:
1048
1656
  console.error(`Unknown export format: ${subcommand}`);
@@ -1134,7 +1742,98 @@ EXAMPLES:
1134
1742
  console.error('Run "eventmodeler add scenario --help" for detailed format.');
1135
1743
  process.exit(1);
1136
1744
  }
1137
- addScenario(model, filePath, sliceArg, inputData);
1745
+ if (isCloudMode) {
1746
+ // Parse scenario data
1747
+ let scenario;
1748
+ try {
1749
+ if (jsonArg) {
1750
+ const parsed = JSON.parse(inputData);
1751
+ scenario = {
1752
+ name: parsed.name,
1753
+ description: parsed.description,
1754
+ given: parsed.given,
1755
+ when: parsed.when,
1756
+ then: parsed.then,
1757
+ };
1758
+ }
1759
+ else {
1760
+ // XML parsing - extract scenario attributes
1761
+ const nameMatch = inputData.match(/name="([^"]*)"/);
1762
+ const descMatch = inputData.match(/<description>([^<]*)<\/description>/);
1763
+ // Parse given events
1764
+ const givenMatch = inputData.match(/<given[^>]*type="events"[^>]*>([\s\S]*?)<\/given>/);
1765
+ let given;
1766
+ if (givenMatch) {
1767
+ const eventMatches = givenMatch[1].match(/<event>([^<]*)<\/event>/g);
1768
+ if (eventMatches) {
1769
+ given = {
1770
+ type: 'events',
1771
+ events: eventMatches.map(m => m.replace(/<\/?event>/g, '')),
1772
+ };
1773
+ }
1774
+ }
1775
+ // Parse when
1776
+ const whenCommandMatch = inputData.match(/<when[^>]*type="command"[^>]*>[\s\S]*?<command>([^<]*)<\/command>[\s\S]*?<\/when>/);
1777
+ const whenEventsMatch = inputData.match(/<when[^>]*type="events"[^>]*>([\s\S]*?)<\/when>/);
1778
+ let when;
1779
+ if (whenCommandMatch) {
1780
+ when = { type: 'command', command: whenCommandMatch[1] };
1781
+ }
1782
+ else if (whenEventsMatch) {
1783
+ const eventMatches = whenEventsMatch[1].match(/<event>([^<]*)<\/event>/g);
1784
+ if (eventMatches) {
1785
+ when = {
1786
+ type: 'events',
1787
+ events: eventMatches.map(m => m.replace(/<\/?event>/g, '')),
1788
+ };
1789
+ }
1790
+ }
1791
+ // Parse then
1792
+ const thenEventsMatch = inputData.match(/<then[^>]*type="events"[^>]*>([\s\S]*?)<\/then>/);
1793
+ const thenErrorMatch = inputData.match(/<then[^>]*type="error"[^>]*>([\s\S]*?)<\/then>/);
1794
+ const thenCommandMatch = inputData.match(/<then[^>]*type="command"[^>]*>[\s\S]*?<command>([^<]*)<\/command>[\s\S]*?<\/then>/);
1795
+ let then;
1796
+ if (thenEventsMatch) {
1797
+ const eventMatches = thenEventsMatch[1].match(/<event>([^<]*)<\/event>/g);
1798
+ then = {
1799
+ type: 'events',
1800
+ events: eventMatches ? eventMatches.map(m => m.replace(/<\/?event>/g, '')) : [],
1801
+ };
1802
+ }
1803
+ else if (thenErrorMatch) {
1804
+ const msgMatch = thenErrorMatch[1].match(/<message>([^<]*)<\/message>/);
1805
+ const typeMatch = thenErrorMatch[1].match(/<errorType>([^<]*)<\/errorType>/);
1806
+ then = {
1807
+ type: 'error',
1808
+ errorMessage: msgMatch?.[1],
1809
+ errorType: typeMatch?.[1],
1810
+ };
1811
+ }
1812
+ else if (thenCommandMatch) {
1813
+ then = { type: 'command', command: thenCommandMatch[1] };
1814
+ }
1815
+ else {
1816
+ throw new Error('Could not parse <then> element');
1817
+ }
1818
+ scenario = {
1819
+ name: nameMatch?.[1] ?? '',
1820
+ description: descMatch?.[1],
1821
+ given,
1822
+ when,
1823
+ then,
1824
+ };
1825
+ }
1826
+ }
1827
+ catch (err) {
1828
+ console.error(`Error parsing scenario data: ${err.message}`);
1829
+ process.exit(1);
1830
+ }
1831
+ await cloudSlices.createScenario(modelId, sliceArg, scenario);
1832
+ console.log(`Created scenario "${scenario.name}" in slice "${sliceArg}"`);
1833
+ }
1834
+ else {
1835
+ addScenario(model, filePath, sliceArg, inputData);
1836
+ }
1138
1837
  break;
1139
1838
  }
1140
1839
  case 'field': {
@@ -1247,7 +1946,77 @@ EXAMPLES:
1247
1946
  console.error('Run "eventmodeler add field --help" for detailed format documentation.');
1248
1947
  process.exit(1);
1249
1948
  }
1250
- addField(model, filePath, { command: commandArg, event: eventArg, readModel: readModelArg, screen: screenArg, processor: processorArg }, inputData);
1949
+ if (isCloudMode) {
1950
+ // Parse field data and determine element type
1951
+ let field;
1952
+ try {
1953
+ if (jsonArg) {
1954
+ const parsed = JSON.parse(inputData);
1955
+ field = {
1956
+ name: parsed.name,
1957
+ fieldType: parsed.type ?? parsed.fieldType ?? 'String',
1958
+ isList: parsed.isList,
1959
+ isOptional: parsed.isOptional,
1960
+ isGenerated: parsed.isGenerated,
1961
+ isUserInput: parsed.isUserInput,
1962
+ subfields: parsed.subfields,
1963
+ };
1964
+ }
1965
+ else {
1966
+ // XML parsing - extract field attributes
1967
+ const nameMatch = inputData.match(/name="([^"]*)"/);
1968
+ const typeMatch = inputData.match(/type="([^"]*)"/);
1969
+ const isListMatch = inputData.match(/isList="([^"]*)"/);
1970
+ const isOptionalMatch = inputData.match(/isOptional="([^"]*)"/);
1971
+ const isGeneratedMatch = inputData.match(/isGenerated="([^"]*)"/);
1972
+ const isUserInputMatch = inputData.match(/isUserInput="([^"]*)"/);
1973
+ field = {
1974
+ name: nameMatch?.[1] ?? '',
1975
+ fieldType: typeMatch?.[1] ?? 'String',
1976
+ isList: isListMatch?.[1] === 'true',
1977
+ isOptional: isOptionalMatch?.[1] === 'true',
1978
+ isGenerated: isGeneratedMatch?.[1] === 'true',
1979
+ isUserInput: isUserInputMatch?.[1] === 'true',
1980
+ };
1981
+ }
1982
+ }
1983
+ catch (err) {
1984
+ console.error(`Error parsing field data: ${err.message}`);
1985
+ process.exit(1);
1986
+ }
1987
+ // Determine element type and name
1988
+ let elementType;
1989
+ let elementName;
1990
+ if (commandArg) {
1991
+ elementType = 'command';
1992
+ elementName = commandArg;
1993
+ }
1994
+ else if (eventArg) {
1995
+ elementType = 'event';
1996
+ elementName = eventArg;
1997
+ }
1998
+ else if (readModelArg) {
1999
+ elementType = 'readModel';
2000
+ elementName = readModelArg;
2001
+ }
2002
+ else if (screenArg) {
2003
+ elementType = 'screen';
2004
+ elementName = screenArg;
2005
+ }
2006
+ else if (processorArg) {
2007
+ elementType = 'processor';
2008
+ elementName = processorArg;
2009
+ }
2010
+ else {
2011
+ console.error('Error: Must specify one of --command, --event, --read-model, --screen, or --processor');
2012
+ process.exit(1);
2013
+ }
2014
+ await cloudSlices.addField(modelId, elementType, elementName, field);
2015
+ console.log(`Added field "${field.name}" to ${elementType} "${elementName}"`);
2016
+ }
2017
+ else {
2018
+ addField(model, filePath, { command: commandArg, event: eventArg, readModel: readModelArg, screen: screenArg, processor: processorArg }, inputData);
2019
+ }
1251
2020
  break;
1252
2021
  }
1253
2022
  default:
@@ -1293,14 +2062,28 @@ EXAMPLES:
1293
2062
  `);
1294
2063
  process.exit(0);
1295
2064
  }
1296
- const scenarioName = target;
1297
2065
  const sliceArg = getNamedArg(filteredArgs, '--slice');
2066
+ // Filter out --slice and its value from remaining args to get scenario name
2067
+ const scenarioArgs = filteredArgs.slice(2).filter((arg, i, arr) => {
2068
+ if (arg === '--slice')
2069
+ return false;
2070
+ if (i > 0 && arr[i - 1] === '--slice')
2071
+ return false;
2072
+ return true;
2073
+ });
2074
+ const scenarioName = scenarioArgs.length > 0 ? scenarioArgs.join(' ') : undefined;
1298
2075
  if (!scenarioName) {
1299
2076
  console.error('Usage: eventmodeler remove scenario <name> [--slice <slice-name>]');
1300
2077
  console.error('Run "eventmodeler remove scenario --help" for more information.');
1301
2078
  process.exit(1);
1302
2079
  }
1303
- removeScenario(model, filePath, scenarioName, sliceArg);
2080
+ if (isCloudMode) {
2081
+ await cloudSlices.removeScenario(modelId, scenarioName, sliceArg);
2082
+ console.log(`Removed scenario "${scenarioName}"${sliceArg ? ` from slice "${sliceArg}"` : ''}`);
2083
+ }
2084
+ else {
2085
+ removeScenario(model, filePath, scenarioName, sliceArg);
2086
+ }
1304
2087
  break;
1305
2088
  }
1306
2089
  case 'field': {
@@ -1337,7 +2120,40 @@ EXAMPLES:
1337
2120
  console.error('Run "eventmodeler remove field --help" for more information.');
1338
2121
  process.exit(1);
1339
2122
  }
1340
- removeField(model, filePath, { command: commandArg, event: eventArg, readModel: readModelArg, screen: screenArg, processor: processorArg }, fieldArg);
2123
+ if (isCloudMode) {
2124
+ // Determine element type and name
2125
+ let elementType;
2126
+ let elementName;
2127
+ if (commandArg) {
2128
+ elementType = 'command';
2129
+ elementName = commandArg;
2130
+ }
2131
+ else if (eventArg) {
2132
+ elementType = 'event';
2133
+ elementName = eventArg;
2134
+ }
2135
+ else if (readModelArg) {
2136
+ elementType = 'readModel';
2137
+ elementName = readModelArg;
2138
+ }
2139
+ else if (screenArg) {
2140
+ elementType = 'screen';
2141
+ elementName = screenArg;
2142
+ }
2143
+ else if (processorArg) {
2144
+ elementType = 'processor';
2145
+ elementName = processorArg;
2146
+ }
2147
+ else {
2148
+ console.error('Error: Must specify one of --command, --event, --read-model, --screen, or --processor');
2149
+ process.exit(1);
2150
+ }
2151
+ await cloudSlices.removeField(modelId, elementType, elementName, fieldArg);
2152
+ console.log(`Removed field "${fieldArg}" from ${elementType} "${elementName}"`);
2153
+ }
2154
+ else {
2155
+ removeField(model, filePath, { command: commandArg, event: eventArg, readModel: readModelArg, screen: screenArg, processor: processorArg }, fieldArg);
2156
+ }
1341
2157
  break;
1342
2158
  }
1343
2159
  default:
@@ -1416,7 +2232,43 @@ EXAMPLES:
1416
2232
  console.error('Run "eventmodeler map fields --help" for detailed format.');
1417
2233
  process.exit(1);
1418
2234
  }
1419
- mapFields(model, filePath, flowArg, inputData);
2235
+ if (isCloudMode) {
2236
+ // Parse flow argument to extract source and target names
2237
+ const flowParts = flowArg.split(/→|->/).map(s => s.trim());
2238
+ if (flowParts.length !== 2) {
2239
+ console.error('Error: --flow must be in format "SourceName→TargetName" or "SourceName->TargetName"');
2240
+ process.exit(1);
2241
+ }
2242
+ const [sourceName, targetName] = flowParts;
2243
+ // Parse mappings from JSON or XML
2244
+ let mappings;
2245
+ try {
2246
+ if (jsonArg) {
2247
+ mappings = JSON.parse(inputData);
2248
+ }
2249
+ else {
2250
+ // XML parsing - extract mapping attributes
2251
+ const mappingMatches = inputData.match(/<mapping[^>]+>/g) || [];
2252
+ mappings = mappingMatches.map(m => {
2253
+ const fromMatch = m.match(/from="([^"]*)"/);
2254
+ const toMatch = m.match(/to="([^"]*)"/);
2255
+ return {
2256
+ from: fromMatch?.[1] ?? '',
2257
+ to: toMatch?.[1] ?? '',
2258
+ };
2259
+ });
2260
+ }
2261
+ }
2262
+ catch (err) {
2263
+ console.error(`Error parsing mappings: ${err.message}`);
2264
+ process.exit(1);
2265
+ }
2266
+ await cloudSlices.mapFields(modelId, sourceName, targetName, mappings);
2267
+ console.log(`Mapped ${mappings.length} field(s) from "${sourceName}" to "${targetName}"`);
2268
+ }
2269
+ else {
2270
+ mapFields(model, filePath, flowArg, inputData);
2271
+ }
1420
2272
  break;
1421
2273
  }
1422
2274
  default:
@@ -1525,7 +2377,50 @@ EXAMPLES:
1525
2377
  console.error('Run "eventmodeler update field --help" for available options.');
1526
2378
  process.exit(1);
1527
2379
  }
1528
- updateField(model, filePath, { command: commandArg, event: eventArg, readModel: readModelArg, screen: screenArg, processor: processorArg }, fieldArg, updates);
2380
+ if (isCloudMode) {
2381
+ // Determine element type and name
2382
+ let elementType;
2383
+ let elementName;
2384
+ if (commandArg) {
2385
+ elementType = 'command';
2386
+ elementName = commandArg;
2387
+ }
2388
+ else if (eventArg) {
2389
+ elementType = 'event';
2390
+ elementName = eventArg;
2391
+ }
2392
+ else if (readModelArg) {
2393
+ elementType = 'readModel';
2394
+ elementName = readModelArg;
2395
+ }
2396
+ else if (screenArg) {
2397
+ elementType = 'screen';
2398
+ elementName = screenArg;
2399
+ }
2400
+ else if (processorArg) {
2401
+ elementType = 'processor';
2402
+ elementName = processorArg;
2403
+ }
2404
+ else {
2405
+ console.error('Error: Must specify one of --command, --event, --read-model, --screen, or --processor');
2406
+ process.exit(1);
2407
+ }
2408
+ // Convert local updates format to cloud format
2409
+ const cloudUpdates = {};
2410
+ if (updates.optional !== undefined)
2411
+ cloudUpdates.isOptional = updates.optional;
2412
+ if (updates.generated !== undefined)
2413
+ cloudUpdates.isGenerated = updates.generated;
2414
+ if (updates.userInput !== undefined)
2415
+ cloudUpdates.isUserInput = updates.userInput;
2416
+ if (updates.type !== undefined)
2417
+ cloudUpdates.fieldType = updates.type;
2418
+ await cloudSlices.updateField(modelId, elementType, elementName, fieldArg, cloudUpdates);
2419
+ console.log(`Updated field "${fieldArg}" on ${elementType} "${elementName}"`);
2420
+ }
2421
+ else {
2422
+ updateField(model, filePath, { command: commandArg, event: eventArg, readModel: readModelArg, screen: screenArg, processor: processorArg }, fieldArg, updates);
2423
+ }
1529
2424
  break;
1530
2425
  }
1531
2426
  default:
@@ -1638,7 +2533,31 @@ EXAMPLES:
1638
2533
  console.error('Run "eventmodeler create state-change-slice --help" for detailed format.');
1639
2534
  process.exit(1);
1640
2535
  }
1641
- createStateChangeSlice(model, filePath, xmlArg);
2536
+ if (isCloudMode) {
2537
+ // Parse XML input to extract structured data
2538
+ const parser = await import('./lib/slice-utils.js');
2539
+ const parsed = parser.parseStateChangeSliceXml(xmlArg);
2540
+ // Convert FieldInput to CompoundFieldInput (rename 'type' to 'fieldType')
2541
+ const convertFields = (fields) => fields.map(f => ({ ...f, fieldType: f.type, type: undefined }));
2542
+ const cloudInput = {
2543
+ sliceName: parsed.sliceName,
2544
+ after: parsed.after,
2545
+ before: parsed.before,
2546
+ screen: { name: parsed.screen.name, fields: convertFields(parsed.screen.fields) },
2547
+ command: { name: parsed.command.name, fields: convertFields(parsed.command.fields) },
2548
+ event: { name: parsed.event.name, fields: convertFields(parsed.event.fields) },
2549
+ };
2550
+ const result = await cloudSlices.createStateChangeSlice(modelId, cloudInput);
2551
+ console.log(`Created state-change slice "${parsed.sliceName}"`);
2552
+ console.log(` Screen: ${parsed.screen.name} (${parsed.screen.fields.length} fields)`);
2553
+ console.log(` Command: ${parsed.command.name} (${parsed.command.fields.length} fields)`);
2554
+ console.log(` Event: ${parsed.event.name} (${parsed.event.fields.length} fields)`);
2555
+ console.log(` Screen -> Command mappings: ${result.screenToCommandMappings}`);
2556
+ console.log(` Command -> Event mappings: ${result.commandToEventMappings}`);
2557
+ }
2558
+ else {
2559
+ createStateChangeSlice(model, filePath, xmlArg);
2560
+ }
1642
2561
  break;
1643
2562
  }
1644
2563
  case 'automation-slice': {
@@ -1719,6 +2638,10 @@ EXAMPLES:
1719
2638
  console.error('Run "eventmodeler create automation-slice --help" for detailed format.');
1720
2639
  process.exit(1);
1721
2640
  }
2641
+ if (isCloudMode) {
2642
+ console.error('Error: create automation-slice is not yet supported in cloud mode.');
2643
+ process.exit(1);
2644
+ }
1722
2645
  createAutomationSlice(model, filePath, xmlArg);
1723
2646
  break;
1724
2647
  }
@@ -1786,7 +2709,25 @@ EXAMPLES:
1786
2709
  console.error('Run "eventmodeler create state-view-slice --help" for detailed format.');
1787
2710
  process.exit(1);
1788
2711
  }
1789
- createStateViewSlice(model, filePath, xmlArg);
2712
+ if (isCloudMode) {
2713
+ // Parse XML input to extract structured data
2714
+ const parser = await import('./lib/slice-utils.js');
2715
+ const parsed = parser.parseStateViewSliceXml(xmlArg);
2716
+ // Convert FieldInput to CompoundFieldInput (rename 'type' to 'fieldType')
2717
+ const convertFields = (fields) => fields.map(f => ({ ...f, fieldType: f.type, type: undefined }));
2718
+ const cloudInput = {
2719
+ sliceName: parsed.sliceName,
2720
+ after: parsed.after,
2721
+ before: parsed.before,
2722
+ readModel: { name: parsed.readModel.name, fields: convertFields(parsed.readModel.fields) },
2723
+ };
2724
+ const result = await cloudSlices.createStateViewSlice(modelId, cloudInput);
2725
+ console.log(`Created state-view slice "${parsed.sliceName}"`);
2726
+ console.log(` ReadModel: ${parsed.readModel.name} (${parsed.readModel.fields.length} fields)`);
2727
+ }
2728
+ else {
2729
+ createStateViewSlice(model, filePath, xmlArg);
2730
+ }
1790
2731
  break;
1791
2732
  }
1792
2733
  case 'flow': {
@@ -1821,7 +2762,13 @@ EXAMPLES:
1821
2762
  console.error('Run "eventmodeler create flow --help" for more information.');
1822
2763
  process.exit(1);
1823
2764
  }
1824
- createFlow(model, filePath, fromArg, toArg);
2765
+ if (isCloudMode) {
2766
+ await cloudSlices.createFlow(modelId, fromArg, toArg);
2767
+ console.log(`Created flow from "${fromArg}" to "${toArg}"`);
2768
+ }
2769
+ else {
2770
+ createFlow(model, filePath, fromArg, toArg);
2771
+ }
1825
2772
  break;
1826
2773
  }
1827
2774
  default:
@@ -1884,7 +2831,13 @@ EXAMPLES:
1884
2831
  console.error('Run "eventmodeler codegen slice --help" for more information.');
1885
2832
  process.exit(1);
1886
2833
  }
1887
- codegenSlice(model, sliceName);
2834
+ if (isCloudMode) {
2835
+ const result = await cloudSlices.codegenSlice(modelId, sliceName);
2836
+ console.log(JSON.stringify(JSON.parse(result), null, 2));
2837
+ }
2838
+ else {
2839
+ codegenSlice(model, sliceName);
2840
+ }
1888
2841
  break;
1889
2842
  }
1890
2843
  default: