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.
- package/dist/cloud/slices/index.d.ts +215 -0
- package/dist/cloud/slices/index.js +247 -0
- package/dist/index.js +993 -40
- package/dist/lib/auth.d.ts +24 -0
- package/dist/lib/auth.js +332 -0
- package/dist/lib/backend.d.ts +48 -0
- package/dist/lib/backend.js +103 -0
- package/dist/lib/cloud-client.d.ts +70 -0
- package/dist/lib/cloud-client.js +528 -0
- package/dist/lib/config.d.ts +27 -0
- package/dist/lib/config.js +80 -11
- package/dist/lib/diff/three-way-merge.js +4 -4
- package/dist/lib/file-loader.js +43 -12
- package/dist/lib/project-config.d.ts +30 -0
- package/dist/lib/project-config.js +90 -0
- package/dist/lib/slice-utils.d.ts +28 -0
- package/dist/lib/slice-utils.js +80 -0
- package/dist/local/slices/index.d.ts +11 -0
- package/dist/local/slices/index.js +13 -0
- package/dist/projection.js +372 -371
- package/dist/slices/add-field/index.js +25 -15
- package/dist/slices/add-scenario/index.js +34 -22
- package/dist/slices/codegen-slice/index.js +5 -3
- package/dist/slices/create-automation-slice/index.js +93 -65
- package/dist/slices/create-flow/index.js +24 -18
- package/dist/slices/create-state-change-slice/index.js +77 -53
- package/dist/slices/create-state-view-slice/index.js +25 -17
- package/dist/slices/import/index.d.ts +8 -0
- package/dist/slices/import/index.js +63 -0
- package/dist/slices/init/index.d.ts +4 -0
- package/dist/slices/init/index.js +133 -0
- package/dist/slices/list-processors/index.d.ts +3 -0
- package/dist/slices/list-processors/index.js +20 -0
- package/dist/slices/list-readmodels/index.d.ts +3 -0
- package/dist/slices/list-readmodels/index.js +21 -0
- package/dist/slices/list-scenarios/index.d.ts +3 -0
- package/dist/slices/list-scenarios/index.js +35 -0
- package/dist/slices/list-screens/index.d.ts +3 -0
- package/dist/slices/list-screens/index.js +47 -0
- package/dist/slices/login/index.d.ts +1 -0
- package/dist/slices/login/index.js +24 -0
- package/dist/slices/logout/index.d.ts +1 -0
- package/dist/slices/logout/index.js +14 -0
- package/dist/slices/map-fields/index.js +5 -3
- package/dist/slices/mark-slice-status/index.js +4 -2
- package/dist/slices/remove-field/index.js +25 -15
- package/dist/slices/remove-scenario/index.js +8 -4
- package/dist/slices/show-aggregate/index.d.ts +3 -0
- package/dist/slices/show-aggregate/index.js +108 -0
- package/dist/slices/show-processor/index.d.ts +3 -0
- package/dist/slices/show-processor/index.js +111 -0
- package/dist/slices/show-readmodel/index.d.ts +3 -0
- package/dist/slices/show-readmodel/index.js +158 -0
- package/dist/slices/show-scenario/index.d.ts +3 -0
- package/dist/slices/show-scenario/index.js +196 -0
- package/dist/slices/show-screen/index.d.ts +3 -0
- package/dist/slices/show-screen/index.js +139 -0
- package/dist/slices/update-field/index.js +30 -20
- package/dist/slices/whoami/index.d.ts +2 -0
- package/dist/slices/whoami/index.js +35 -0
- package/dist/types.d.ts +1 -2
- 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
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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, '&').replace(/"/g, '"').replace(/</g, '<').replace(/>/g, '>');
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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:
|