eventmodeler 0.4.7 → 0.6.0

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 (204) hide show
  1. package/dist/api/client-config.js +10 -0
  2. package/dist/api/generated/client/client.gen.js +235 -0
  3. package/dist/api/generated/client/index.js +6 -0
  4. package/dist/api/generated/client/types.gen.js +2 -0
  5. package/dist/api/generated/client/utils.gen.js +228 -0
  6. package/dist/api/generated/client.gen.js +4 -0
  7. package/dist/api/generated/core/auth.gen.js +14 -0
  8. package/dist/api/generated/core/bodySerializer.gen.js +57 -0
  9. package/dist/api/generated/core/params.gen.js +100 -0
  10. package/dist/api/generated/core/pathSerializer.gen.js +106 -0
  11. package/dist/api/generated/core/queryKeySerializer.gen.js +92 -0
  12. package/dist/api/generated/core/serverSentEvents.gen.js +133 -0
  13. package/dist/api/generated/core/types.gen.js +2 -0
  14. package/dist/api/generated/core/utils.gen.js +87 -0
  15. package/dist/api/generated/index.js +2 -0
  16. package/dist/api/generated/sdk.gen.js +4222 -0
  17. package/dist/api/generated/types.gen.js +2 -0
  18. package/dist/api/generated/zod.gen.js +7217 -0
  19. package/dist/commands/add.js +315 -0
  20. package/dist/commands/auth.js +14 -0
  21. package/dist/commands/create.js +192 -0
  22. package/dist/commands/design.js +108 -0
  23. package/dist/commands/guide.js +15 -0
  24. package/dist/commands/init.js +21 -0
  25. package/dist/commands/list-schemas.js +177 -0
  26. package/dist/commands/list.js +39 -0
  27. package/dist/commands/loop.js +101 -0
  28. package/dist/commands/map.js +40 -0
  29. package/dist/commands/mark.js +27 -0
  30. package/dist/commands/move.js +35 -0
  31. package/dist/commands/remove.js +170 -0
  32. package/dist/commands/rename.js +53 -0
  33. package/dist/commands/resize.js +30 -0
  34. package/dist/commands/search.js +14 -0
  35. package/dist/commands/set.js +199 -0
  36. package/dist/commands/show-schemas.js +259 -0
  37. package/dist/commands/show.js +56 -0
  38. package/dist/commands/summary.js +13 -0
  39. package/dist/commands/update.js +240 -0
  40. package/dist/index.js +46 -2379
  41. package/dist/lib/auth.js +1 -1
  42. package/dist/lib/config.js +0 -15
  43. package/dist/lib/excalidraw-schema.js +66 -0
  44. package/dist/lib/globals.js +8 -0
  45. package/dist/lib/model.js +11 -0
  46. package/dist/lib/project-config.js +20 -0
  47. package/dist/lib/resolve.js +59 -0
  48. package/dist/lib/scenario.js +15 -0
  49. package/dist/slices/add-scenario/index.js +2 -206
  50. package/dist/slices/guide/guides/codegen.js +1 -1
  51. package/dist/slices/guide/guides/connect-slices.js +12 -37
  52. package/dist/slices/guide/guides/create-slices.js +110 -140
  53. package/dist/slices/guide/guides/explore.js +37 -26
  54. package/dist/slices/guide/guides/information-flow.js +70 -82
  55. package/dist/slices/guide/guides/scenarios.js +82 -137
  56. package/dist/slices/guide/index.js +6 -6
  57. package/dist/slices/help/index.js +96 -0
  58. package/dist/slices/help/topics/build-codegen.js +109 -0
  59. package/dist/slices/help/topics/build-slice.js +147 -0
  60. package/dist/slices/help/topics/check-completeness.js +57 -0
  61. package/dist/slices/help/topics/connect-slices.js +99 -0
  62. package/dist/slices/help/topics/explore-model.js +112 -0
  63. package/dist/slices/help/topics/json-reference.js +188 -0
  64. package/dist/slices/help/topics/linked-copies.js +89 -0
  65. package/dist/slices/help/topics/manipulate-canvas.js +150 -0
  66. package/dist/slices/help/topics/write-scenarios.js +162 -0
  67. package/dist/slices/init/index.js +10 -4
  68. package/dist/slices/init/loop.js +60 -0
  69. package/dist/slices/login/index.js +2 -2
  70. package/dist/slices/logout/index.js +2 -2
  71. package/dist/slices/whoami/index.js +11 -36
  72. package/package.json +8 -3
  73. package/dist/api/index.d.ts +0 -285
  74. package/dist/api/index.js +0 -323
  75. package/dist/cloud/slices/index.d.ts +0 -276
  76. package/dist/cloud/slices/index.js +0 -406
  77. package/dist/eventmodeler.js +0 -5646
  78. package/dist/formatters.d.ts +0 -17
  79. package/dist/formatters.js +0 -482
  80. package/dist/index.d.ts +0 -2
  81. package/dist/lib/auth.d.ts +0 -24
  82. package/dist/lib/backend.d.ts +0 -43
  83. package/dist/lib/backend.js +0 -73
  84. package/dist/lib/chapter-utils.d.ts +0 -13
  85. package/dist/lib/chapter-utils.js +0 -71
  86. package/dist/lib/cloud-client.d.ts +0 -69
  87. package/dist/lib/cloud-client.js +0 -364
  88. package/dist/lib/config.d.ts +0 -30
  89. package/dist/lib/diff/merge-rules.d.ts +0 -45
  90. package/dist/lib/diff/merge-rules.js +0 -210
  91. package/dist/lib/diff/model-differ.d.ts +0 -8
  92. package/dist/lib/diff/model-differ.js +0 -568
  93. package/dist/lib/diff/three-way-merge.d.ts +0 -7
  94. package/dist/lib/diff/three-way-merge.js +0 -390
  95. package/dist/lib/diff/types.d.ts +0 -75
  96. package/dist/lib/diff/types.js +0 -1
  97. package/dist/lib/element-lookup.d.ts +0 -58
  98. package/dist/lib/element-lookup.js +0 -126
  99. package/dist/lib/file-loader.d.ts +0 -8
  100. package/dist/lib/file-loader.js +0 -108
  101. package/dist/lib/flow-utils.d.ts +0 -53
  102. package/dist/lib/flow-utils.js +0 -348
  103. package/dist/lib/format.d.ts +0 -10
  104. package/dist/lib/format.js +0 -23
  105. package/dist/lib/project-config.d.ts +0 -27
  106. package/dist/lib/slice-utils.d.ts +0 -59
  107. package/dist/lib/slice-utils.js +0 -140
  108. package/dist/local/slices/index.d.ts +0 -11
  109. package/dist/local/slices/index.js +0 -13
  110. package/dist/projection.d.ts +0 -3
  111. package/dist/projection.js +0 -828
  112. package/dist/slices/add-field/index.d.ts +0 -8
  113. package/dist/slices/add-field/index.js +0 -211
  114. package/dist/slices/add-scenario/index.d.ts +0 -27
  115. package/dist/slices/codegen-chapter-events/index.d.ts +0 -2
  116. package/dist/slices/codegen-chapter-events/index.js +0 -145
  117. package/dist/slices/codegen-slice/index.d.ts +0 -2
  118. package/dist/slices/codegen-slice/index.js +0 -448
  119. package/dist/slices/create-automation-slice/index.d.ts +0 -2
  120. package/dist/slices/create-automation-slice/index.js +0 -304
  121. package/dist/slices/create-flow/index.d.ts +0 -2
  122. package/dist/slices/create-flow/index.js +0 -183
  123. package/dist/slices/create-state-change-slice/index.d.ts +0 -2
  124. package/dist/slices/create-state-change-slice/index.js +0 -263
  125. package/dist/slices/create-state-view-slice/index.d.ts +0 -2
  126. package/dist/slices/create-state-view-slice/index.js +0 -128
  127. package/dist/slices/diff/index.d.ts +0 -11
  128. package/dist/slices/diff/index.js +0 -293
  129. package/dist/slices/export-eventmodel-to-json/index.d.ts +0 -2
  130. package/dist/slices/export-eventmodel-to-json/index.js +0 -355
  131. package/dist/slices/git/index.d.ts +0 -2
  132. package/dist/slices/git/index.js +0 -125
  133. package/dist/slices/guide/guides/codegen.d.ts +0 -5
  134. package/dist/slices/guide/guides/connect-slices.d.ts +0 -5
  135. package/dist/slices/guide/guides/create-slices.d.ts +0 -5
  136. package/dist/slices/guide/guides/explore.d.ts +0 -5
  137. package/dist/slices/guide/guides/information-flow.d.ts +0 -5
  138. package/dist/slices/guide/guides/scenarios.d.ts +0 -5
  139. package/dist/slices/guide/index.d.ts +0 -1
  140. package/dist/slices/import/index.d.ts +0 -8
  141. package/dist/slices/import/index.js +0 -63
  142. package/dist/slices/init/index.d.ts +0 -5
  143. package/dist/slices/list-chapters/index.d.ts +0 -3
  144. package/dist/slices/list-chapters/index.js +0 -21
  145. package/dist/slices/list-commands/index.d.ts +0 -3
  146. package/dist/slices/list-commands/index.js +0 -20
  147. package/dist/slices/list-events/index.d.ts +0 -3
  148. package/dist/slices/list-events/index.js +0 -98
  149. package/dist/slices/list-processors/index.d.ts +0 -3
  150. package/dist/slices/list-processors/index.js +0 -20
  151. package/dist/slices/list-readmodels/index.d.ts +0 -3
  152. package/dist/slices/list-readmodels/index.js +0 -21
  153. package/dist/slices/list-scenarios/index.d.ts +0 -3
  154. package/dist/slices/list-scenarios/index.js +0 -35
  155. package/dist/slices/list-screens/index.d.ts +0 -3
  156. package/dist/slices/list-screens/index.js +0 -47
  157. package/dist/slices/list-slices/index.d.ts +0 -3
  158. package/dist/slices/list-slices/index.js +0 -35
  159. package/dist/slices/login/index.d.ts +0 -1
  160. package/dist/slices/logout/index.d.ts +0 -1
  161. package/dist/slices/map-fields/index.d.ts +0 -2
  162. package/dist/slices/map-fields/index.js +0 -269
  163. package/dist/slices/mark-slice-status/index.d.ts +0 -2
  164. package/dist/slices/mark-slice-status/index.js +0 -31
  165. package/dist/slices/merge/index.d.ts +0 -19
  166. package/dist/slices/merge/index.js +0 -147
  167. package/dist/slices/open-app/index.d.ts +0 -1
  168. package/dist/slices/remove-field/index.d.ts +0 -8
  169. package/dist/slices/remove-field/index.js +0 -167
  170. package/dist/slices/remove-scenario/index.d.ts +0 -2
  171. package/dist/slices/remove-scenario/index.js +0 -77
  172. package/dist/slices/search/index.d.ts +0 -3
  173. package/dist/slices/search/index.js +0 -302
  174. package/dist/slices/show-actor/index.d.ts +0 -4
  175. package/dist/slices/show-actor/index.js +0 -115
  176. package/dist/slices/show-aggregate/index.d.ts +0 -3
  177. package/dist/slices/show-aggregate/index.js +0 -108
  178. package/dist/slices/show-aggregate-completeness/index.d.ts +0 -4
  179. package/dist/slices/show-aggregate-completeness/index.js +0 -181
  180. package/dist/slices/show-chapter/index.d.ts +0 -3
  181. package/dist/slices/show-chapter/index.js +0 -195
  182. package/dist/slices/show-command/index.d.ts +0 -3
  183. package/dist/slices/show-command/index.js +0 -133
  184. package/dist/slices/show-completeness/index.d.ts +0 -4
  185. package/dist/slices/show-completeness/index.js +0 -731
  186. package/dist/slices/show-event/index.d.ts +0 -3
  187. package/dist/slices/show-event/index.js +0 -118
  188. package/dist/slices/show-model-summary/index.d.ts +0 -3
  189. package/dist/slices/show-model-summary/index.js +0 -31
  190. package/dist/slices/show-processor/index.d.ts +0 -3
  191. package/dist/slices/show-processor/index.js +0 -111
  192. package/dist/slices/show-readmodel/index.d.ts +0 -3
  193. package/dist/slices/show-readmodel/index.js +0 -158
  194. package/dist/slices/show-scenario/index.d.ts +0 -3
  195. package/dist/slices/show-scenario/index.js +0 -196
  196. package/dist/slices/show-screen/index.d.ts +0 -3
  197. package/dist/slices/show-screen/index.js +0 -139
  198. package/dist/slices/show-slice/index.d.ts +0 -3
  199. package/dist/slices/show-slice/index.js +0 -696
  200. package/dist/slices/update-field/index.d.ts +0 -15
  201. package/dist/slices/update-field/index.js +0 -208
  202. package/dist/slices/whoami/index.d.ts +0 -2
  203. package/dist/types.d.ts +0 -195
  204. package/dist/types.js +0 -1
package/dist/index.js CHANGED
@@ -2,2388 +2,55 @@
2
2
  import * as fs from 'node:fs';
3
3
  import * as path from 'node:path';
4
4
  import { fileURLToPath } from 'node:url';
5
- import { getDefaultFormat } from './lib/config.js';
5
+ import { Command } from 'commander';
6
6
  const __filename = fileURLToPath(import.meta.url);
7
7
  const __dirname = path.dirname(__filename);
8
8
  const packageJson = JSON.parse(fs.readFileSync(path.join(__dirname, '..', 'package.json'), 'utf-8'));
9
- const VERSION = packageJson.version;
10
- // Utilities
11
- import { openApp } from './slices/open-app/index.js';
12
- import { parseScenarioInput } from './slices/add-scenario/index.js';
13
- import { runGuide } from './slices/guide/index.js';
14
- import { login } from './slices/login/index.js';
15
- import { logout } from './slices/logout/index.js';
16
- import { whoami } from './slices/whoami/index.js';
17
- import { init } from './slices/init/index.js';
18
- import * as api from './api/index.js';
19
- import { XMLBuilder, XMLParser } from 'fast-xml-parser';
20
- import { loadProjectConfig } from './lib/project-config.js';
21
- const args = process.argv.slice(2);
22
- function getNamedArg(argList, ...names) {
23
- for (let i = 0; i < argList.length; i++) {
24
- if (names.includes(argList[i]) && i + 1 < argList.length) {
25
- return argList[i + 1];
26
- }
27
- }
28
- return undefined;
29
- }
30
- function hasHelpFlag(argList) {
31
- return argList.includes('-h') || argList.includes('--help');
32
- }
33
- function toCompoundFields(fields) {
34
- return fields.map(field => ({
35
- name: field.name,
36
- fieldType: field.type,
37
- isList: field.isList,
38
- isOptional: field.isOptional,
39
- isGenerated: field.isGenerated,
40
- isUserInput: field.isUserInput,
41
- subfields: field.subfields ? toCompoundFields(field.subfields) : undefined,
42
- }));
43
- }
44
- function printHelp() {
45
- console.log(`
46
- eventmodeler - CLI tool for interacting with Event Model files
47
-
48
- USAGE:
49
- eventmodeler Open the Event Modeling app in browser
50
- eventmodeler <command> [options] Run a CLI command
51
-
52
- AUTHENTICATION:
53
- login Authenticate with eventmodeler.app
54
- logout Sign out
55
- whoami Show authentication status
56
-
57
- PROJECT SETUP:
58
- init Initialize project (link to a model)
59
-
60
- COMMANDS:
61
- list slices [--chapter <name>] List all slices (optionally filtered by chapter)
62
- list events List all events
63
- list commands List all commands
64
- list chapters List all chapters
65
- list aggregates List all aggregates
66
- list actors List all actors
67
- list readmodels List all read models
68
- list screens List all screens
69
- list processors List all processors
70
- list scenarios List all scenarios
71
-
72
- show slice <name> Show slice with components, flow annotations, and
73
- inbound/outbound dependencies
74
- show event <name> Show detailed XML view of an event
75
- show command <name> Show detailed XML view of a command
76
- show chapter <name> Show chapter with slices, flow graph, and
77
- external dependencies
78
- show information-completeness Show information completeness of all flows
79
- show information-completeness <name>
80
- Show field mapping completeness for an element
81
- show aggregate-completeness <name>
82
- Show if events in aggregate have the ID field
83
- show actor <name> Show actor with its screens
84
- show readmodel <name> Show read model with fields and flows
85
- show screen <name> Show screen with fields and connections
86
- show processor <name> Show processor with subscriptions and commands
87
- show aggregate <name> Show aggregate with events and ID field status
88
- show scenario <name> Show scenario with Given-When-Then details
89
-
90
- search <term> Search for entities by name
91
-
92
- mark <slice-name> <status> Mark a slice's status
93
- Status: created | in-progress | blocked | done
94
-
95
- add scenario --slice <name> --json|--xml <data>
96
- Add a scenario to a slice
97
- add field <element-name> --json|--xml <data>
98
- Add a field to an entity
99
-
100
- remove scenario <name> [--slice <name>]
101
- Remove a scenario by name
102
- remove field <element-name> --field <name>
103
- Remove a field from an entity
104
-
105
- map fields --flow <source→target> --json|--xml <mappings>
106
- Set field mappings on a flow
107
-
108
- update field <element-name> --field <name> [--optional true|false] [--generated true|false] [--user-input true|false]
109
- Update field properties
110
-
111
- create state-change-slice --xml <data>
112
- Create a state-change slice (Screen → Command → Event)
113
- create automation-slice --xml <data>
114
- Create an automation slice (ReadModel → Processor → Command → Event)
115
- create state-view-slice --xml <data>
116
- Create a state-view slice (Read Model)
117
- create flow --from <source> --to <target>
118
- Create a flow between elements (Event→ReadModel, ReadModel→Screen/Processor)
119
-
120
- codegen slice <name> Generate code-ready JSON for a slice (includes dependencies, mappings, scenarios)
121
- codegen events [--chapter <name>]
122
- Generate deduplicated events for a chapter or the whole model
123
-
124
- summary Show model summary statistics
125
-
126
- export json Export entire model as JSON
127
-
128
- GUIDES:
129
- guide List available guides for AI agents and users
130
- guide <name> Read a conceptual guide (no auth required)
131
-
132
- OPTIONS:
133
- --format <xml|json> Output format (default: xml, or from config)
134
- -h, --help Show this help message
135
- -v, --version Show version number
136
-
137
- CONFIGURATION:
138
- Set default output format via:
139
- - Environment variable: EVENTMODELER_FORMAT=json
140
- - Config file: ~/.eventmodeler/config.json with {"format": "json"}
141
-
142
- EXAMPLES:
143
- eventmodeler list slices
144
- eventmodeler show slice "Place Order"
145
- eventmodeler mark "Place Order" done
146
- eventmodeler add scenario --slice "Place Order" --json '{"name": "Happy path", "then": {"type": "events", "events": []}}'
147
- eventmodeler add field "OrderPlaced" --json '{"name": "orderId", "type": "UUID"}'
148
- eventmodeler remove field "OrderPlaced" --field "orderId"
149
- eventmodeler show information-completeness
150
- eventmodeler show information-completeness "OrderSummary"
151
- eventmodeler map fields --flow "OrderPlaced→OrderSummary" --json '[{"from": "total", "to": "totalAmount"}]'
152
- eventmodeler update field "OrderSummary" --field "notes" --optional true
153
- `);
154
- }
155
- async function main() {
156
- let formatArg = null;
157
- let chapterArg = null;
158
- const filteredArgs = [];
159
- let helpRequested = false;
160
- for (let i = 0; i < args.length; i++) {
161
- if (args[i] === '--format') {
162
- formatArg = args[++i];
163
- }
164
- else if (args[i] === '--chapter') {
165
- chapterArg = args[++i];
166
- }
167
- else if (args[i] === '-v' || args[i] === '--version') {
168
- console.log(`eventmodeler ${VERSION}`);
169
- process.exit(0);
170
- }
171
- else if (args[i] === '-h' || args[i] === '--help') {
172
- helpRequested = true;
173
- }
174
- else {
175
- filteredArgs.push(args[i]);
176
- }
177
- }
178
- // Handle --help: if no command specified, show general help
179
- // Otherwise let command-specific help handle it
180
- if (helpRequested && filteredArgs.length === 0) {
181
- printHelp();
182
- process.exit(0);
183
- }
184
- // Determine output format
185
- const format = formatArg === 'json' ? 'json'
186
- : formatArg === 'xml' ? 'xml'
187
- : getDefaultFormat();
188
- const command = filteredArgs[0];
189
- const subcommand = filteredArgs[1];
190
- // Join remaining args as target (allows "show chapter Register Products" without quotes)
191
- // For commands with named args (--flag), those are already extracted by getNamedArg
192
- const remainingArgs = filteredArgs.slice(2);
193
- const target = remainingArgs.length > 0 ? remainingArgs.join(' ') : undefined;
194
- if (!command) {
195
- openApp();
196
- return;
197
- }
198
- // Auth commands (no file needed)
199
- if (command === 'login') {
200
- if (helpRequested) {
201
- console.log(`
202
- eventmodeler login - Authenticate with eventmodeler.app
203
-
204
- USAGE:
205
- eventmodeler login
206
-
207
- Opens your browser for authentication via Keycloak.
208
- Credentials are stored securely in ~/.eventmodeler/config.json
209
-
210
- After login, you can:
211
- - Use "eventmodeler init" to connect a project to a model
212
-
213
- EXAMPLES:
214
- eventmodeler login
215
- `);
216
- process.exit(0);
217
- }
218
- await login();
219
- return;
220
- }
221
- if (command === 'logout') {
222
- if (helpRequested) {
223
- console.log(`
224
- eventmodeler logout - Sign out of eventmodeler.app
225
-
226
- USAGE:
227
- eventmodeler logout
228
-
229
- Clears stored credentials from ~/.eventmodeler/config.json
230
-
231
- EXAMPLES:
232
- eventmodeler logout
233
- `);
234
- process.exit(0);
235
- }
236
- logout();
237
- return;
238
- }
239
- if (command === 'whoami') {
240
- if (helpRequested) {
241
- console.log(`
242
- eventmodeler whoami - Show current authentication status
243
-
244
- USAGE:
245
- eventmodeler whoami [--format xml|json]
246
-
247
- OPTIONS:
248
- --format <format> Output format: xml (default) or json
249
-
250
- OUTPUT:
251
- Shows whether you're logged in and your email address.
252
-
253
- EXAMPLES:
254
- eventmodeler whoami
255
- eventmodeler whoami --format json
256
- `);
257
- process.exit(0);
258
- }
259
- whoami(format);
260
- return;
261
- }
262
- if (command === 'init') {
263
- if (helpRequested) {
264
- console.log(`
265
- eventmodeler init - Initialize a project
266
-
267
- USAGE:
268
- eventmodeler init
269
-
270
- Interactive setup to connect this directory to an event model.
271
- Creates a .eventmodeler.json config file in your project root.
272
-
273
- PREREQUISITES:
274
- - You must be logged in (run "eventmodeler login" first)
275
-
276
- EXAMPLES:
277
- cd my-project
278
- eventmodeler init
279
- `);
280
- process.exit(0);
281
- }
282
- await init();
283
- return;
284
- }
285
- if (command === 'guide') {
286
- runGuide(subcommand);
287
- return;
288
- }
289
- const projectConfig = loadProjectConfig();
290
- if (!projectConfig || projectConfig.type !== 'cloud') {
291
- console.error('Error: No project configured.');
292
- console.error('Run "eventmodeler init" to connect this directory to a model.');
293
- process.exit(1);
294
- }
295
- const modelId = projectConfig.modelId;
296
- switch (command) {
297
- case 'list':
298
- if (helpRequested && !subcommand) {
299
- console.log(`
300
- eventmodeler list - List entities in the event model
301
-
302
- USAGE:
303
- eventmodeler list <type> [options]
304
-
305
- TYPES:
306
- slices List all slices (with optional --chapter filter)
307
- events List all events
308
- commands List all commands
309
- chapters List all chapters
310
- aggregates List all aggregates
311
- actors List all actors
312
- readmodels List all read models
313
- screens List all screens
314
- processors List all processors
315
-
316
- OPTIONS:
317
- --chapter <name> Filter slices by chapter (slices only)
318
- --format xml|json Output format (default: xml)
319
-
320
- EXAMPLES:
321
- eventmodeler list slices
322
- eventmodeler list slices --chapter "Order Management"
323
- eventmodeler list events --format json
324
-
325
- Run "eventmodeler list <type> --help" for type-specific help.
326
- `);
327
- process.exit(0);
328
- }
329
- switch (subcommand) {
330
- case 'slices':
331
- if (helpRequested) {
332
- console.log(`
333
- eventmodeler list slices - List all slices in the event model
334
-
335
- USAGE:
336
- eventmodeler list slices [--chapter <name>] [--format xml|json]
337
-
338
- OPTIONS:
339
- --chapter <name> Filter by chapter name
340
- --format <format> Output format: xml (default) or json
341
-
342
- OUTPUT FIELDS:
343
- name Slice name
344
- type state-change | automation | state-view
345
- status created | in-progress | blocked | done
346
- chapter Parent chapter name
347
-
348
- EXAMPLES:
349
- eventmodeler list slices
350
- eventmodeler list slices --chapter "Order Management"
351
- eventmodeler list slices --format json
352
- `);
353
- process.exit(0);
354
- }
355
- {
356
- const output = await api.listSlices(modelId, format, chapterArg ?? undefined);
357
- console.log(output);
358
- }
359
- break;
360
- case 'events':
361
- if (helpRequested) {
362
- console.log(`
363
- eventmodeler list events - List all events in the event model
364
-
365
- USAGE:
366
- eventmodeler list events [--format xml|json]
367
-
368
- OPTIONS:
369
- --format <format> Output format: xml (default) or json
370
-
371
- OUTPUT FIELDS:
372
- name Event name
373
- aggregate Parent aggregate name
374
-
375
- NOTE: Linked copies (events referencing a canonical original) are excluded.
376
-
377
- EXAMPLES:
378
- eventmodeler list events
379
- eventmodeler list events --format json
380
- `);
381
- process.exit(0);
382
- }
383
- {
384
- const output = await api.listEvents(modelId, format);
385
- console.log(output);
386
- }
387
- break;
388
- case 'commands':
389
- if (helpRequested) {
390
- console.log(`
391
- eventmodeler list commands - List all commands in the event model
392
-
393
- USAGE:
394
- eventmodeler list commands [--format xml|json]
395
-
396
- OPTIONS:
397
- --format <format> Output format: xml (default) or json
398
-
399
- OUTPUT FIELDS:
400
- name Command name
401
- aggregate Parent aggregate name
402
-
403
- EXAMPLES:
404
- eventmodeler list commands
405
- eventmodeler list commands --format json
406
- `);
407
- process.exit(0);
408
- }
409
- {
410
- const output = await api.listCommands(modelId, format);
411
- console.log(output);
412
- }
413
- break;
414
- case 'chapters':
415
- if (helpRequested) {
416
- console.log(`
417
- eventmodeler list chapters - List all chapters in the event model
418
-
419
- USAGE:
420
- eventmodeler list chapters [--format xml|json]
421
-
422
- OPTIONS:
423
- --format <format> Output format: xml (default) or json
424
-
425
- OUTPUT FIELDS:
426
- name Chapter name
427
- sliceCount Number of slices in chapter
428
-
429
- EXAMPLES:
430
- eventmodeler list chapters
431
- eventmodeler list chapters --format json
432
- `);
433
- process.exit(0);
434
- }
435
- {
436
- const output = await api.listChapters(modelId, format);
437
- console.log(output);
438
- }
439
- break;
440
- case 'aggregates':
441
- if (helpRequested) {
442
- console.log(`
443
- eventmodeler list aggregates - List all aggregates in the event model
444
-
445
- USAGE:
446
- eventmodeler list aggregates [--format xml|json]
447
-
448
- OPTIONS:
449
- --format <format> Output format: xml (default) or json
450
-
451
- OUTPUT FIELDS:
452
- name Aggregate name
453
- eventCount Number of events
454
- commandCount Number of commands
455
-
456
- EXAMPLES:
457
- eventmodeler list aggregates
458
- eventmodeler list aggregates --format json
459
- `);
460
- process.exit(0);
461
- }
462
- {
463
- const result = await api.listAggregates(modelId, format);
464
- console.log(result);
465
- }
466
- break;
467
- case 'actors':
468
- if (helpRequested) {
469
- console.log(`
470
- eventmodeler list actors - List all actors in the event model
471
-
472
- USAGE:
473
- eventmodeler list actors [--format xml|json]
474
-
475
- OPTIONS:
476
- --format <format> Output format: xml (default) or json
477
-
478
- OUTPUT FIELDS:
479
- name Actor name
480
- screenCount Number of screens
481
-
482
- EXAMPLES:
483
- eventmodeler list actors
484
- eventmodeler list actors --format json
485
- `);
486
- process.exit(0);
487
- }
488
- {
489
- const output = await api.listActors(modelId, format);
490
- console.log(output);
491
- }
492
- break;
493
- case 'readmodels':
494
- if (helpRequested) {
495
- console.log(`
496
- eventmodeler list readmodels - List all read models
497
-
498
- USAGE:
499
- eventmodeler list readmodels [--format xml|json]
500
-
501
- OUTPUT:
502
- Lists read models with id, name, and field count.
503
- Excludes linked copies (shows only canonical read models).
504
-
505
- EXAMPLES:
506
- eventmodeler list readmodels
507
- eventmodeler list readmodels --format json
508
- `);
509
- process.exit(0);
510
- }
511
- {
512
- const output = await api.listReadModels(modelId, format);
513
- console.log(output);
514
- }
515
- break;
516
- case 'screens':
517
- if (helpRequested) {
518
- console.log(`
519
- eventmodeler list screens - List all screens
520
-
521
- USAGE:
522
- eventmodeler list screens [--format xml|json]
523
-
524
- OUTPUT:
525
- Lists screens with id, name, field count, and actor (if in one).
526
- Excludes linked copies (shows only canonical screens).
527
-
528
- EXAMPLES:
529
- eventmodeler list screens
530
- eventmodeler list screens --format json
531
- `);
532
- process.exit(0);
533
- }
534
- {
535
- const output = await api.listScreens(modelId, format);
536
- console.log(output);
537
- }
538
- break;
539
- case 'processors':
540
- if (helpRequested) {
541
- console.log(`
542
- eventmodeler list processors - List all processors
543
-
544
- USAGE:
545
- eventmodeler list processors [--format xml|json]
546
-
547
- OUTPUT:
548
- Lists processors with id, name, and field count.
549
-
550
- EXAMPLES:
551
- eventmodeler list processors
552
- eventmodeler list processors --format json
553
- `);
554
- process.exit(0);
555
- }
556
- {
557
- const output = await api.listProcessors(modelId, format);
558
- console.log(output);
559
- }
560
- break;
561
- case 'scenarios':
562
- if (helpRequested) {
563
- console.log(`
564
- eventmodeler list scenarios - List all scenarios
565
-
566
- USAGE:
567
- eventmodeler list scenarios [--format xml|json]
568
-
569
- OUTPUT:
570
- - Scenario name
571
- - Parent slice
572
- - Then type (events, error, command, etc.)
573
-
574
- EXAMPLES:
575
- eventmodeler list scenarios
576
- eventmodeler list scenarios --format json
577
- `);
578
- process.exit(0);
579
- }
580
- {
581
- const output = await api.listScenarios(modelId, format);
582
- console.log(output);
583
- }
584
- break;
585
- default:
586
- console.error(`Unknown list target: ${subcommand}`);
587
- console.error('Valid targets: slices, events, commands, chapters, aggregates, actors, readmodels, screens, processors, scenarios');
588
- console.error('Run "eventmodeler list --help" for more information.');
589
- process.exit(1);
590
- }
591
- break;
592
- case 'show':
593
- if (helpRequested && !subcommand) {
594
- console.log(`
595
- eventmodeler show - Show detailed information about entities
596
-
597
- USAGE:
598
- eventmodeler show <type> <name> [options]
599
-
600
- TYPES:
601
- slice Show slice with components and flows
602
- event Show event with all fields
603
- command Show command with all fields
604
- chapter Show chapter with slices and dependencies
605
- information-completeness Show information completeness of all flows
606
- (with element name: show per-element completeness)
607
- aggregate-completeness Show if events have aggregate ID field
608
- actor Show actor with screens
609
- readmodel Show read model with fields and flows
610
- screen Show screen with fields and connections
611
- processor Show processor with subscriptions and commands
612
- aggregate Show aggregate with events and ID field status
613
- scenario Show scenario with Given-When-Then details
614
-
615
- OPTIONS:
616
- --format xml|json Output format (default: xml)
617
-
618
- EXAMPLES:
619
- eventmodeler show slice "Place Order"
620
- eventmodeler show event OrderPlaced
621
- eventmodeler show information-completeness OrderSummary
622
-
623
- Run "eventmodeler show <type> --help" for type-specific help.
624
- `);
625
- process.exit(0);
626
- }
627
- switch (subcommand) {
628
- case 'slice':
629
- if (helpRequested) {
630
- console.log(`
631
- eventmodeler show slice - Show detailed slice information
632
-
633
- USAGE:
634
- eventmodeler show slice <name> [--format xml|json]
635
-
636
- ARGUMENTS:
637
- <name> Slice name (spaces allowed without quotes)
638
-
639
- OUTPUT INCLUDES:
640
- - Slice type (state-change, automation, state-view)
641
- - Status (created, in-progress, blocked, done)
642
- - Components: screens, commands, events, read models, processors
643
- - Each component's fields with types and flags
644
- - Flow annotations and swimlane positions
645
- - Inbound/outbound dependencies
646
- - Scenarios (Given-When-Then specifications)
647
-
648
- EXAMPLES:
649
- eventmodeler show slice "Place Order"
650
- eventmodeler show slice Place Order
651
- eventmodeler show slice "Place Order" --format json
652
- `);
653
- process.exit(0);
654
- }
655
- if (!target) {
656
- console.error('Usage: eventmodeler show slice <name>');
657
- console.error('Run "eventmodeler show slice --help" for more information.');
658
- process.exit(1);
659
- }
660
- {
661
- const result = await api.showSlice(modelId, target, format);
662
- console.log(result);
663
- }
664
- break;
665
- case 'event':
666
- if (helpRequested) {
667
- console.log(`
668
- eventmodeler show event - Show detailed event information
669
-
670
- USAGE:
671
- eventmodeler show event <name> [--format xml|json]
672
-
673
- ARGUMENTS:
674
- <name> Event name (spaces allowed without quotes)
675
-
676
- OUTPUT INCLUDES:
677
- - Event name and aggregate
678
- - All fields with:
679
- - name: Field name
680
- - type: UUID, String, Int, Long, Double, Decimal, Boolean, Date, DateTime, Custom
681
- - isList: Whether field is an array
682
- - isOptional: Whether field can be null
683
- - isGenerated: Whether field is computed (not mapped from source)
684
- - subfields: Nested fields for Custom types (recursive, with all flags)
685
-
686
- FIELD OUTPUT FORMAT (XML):
687
- <field name="orderId" type="UUID"/>
688
- <field name="total" type="Decimal" isGenerated="true"/>
689
- <field name="items" type="Custom" isList="true">
690
- <field name="productId" type="UUID"/>
691
- <field name="lineTotal" type="Decimal" isGenerated="true"/>
692
- </field>
693
-
694
- EXAMPLES:
695
- eventmodeler show event OrderPlaced
696
- eventmodeler show event "Order Placed" --format json
697
- `);
698
- process.exit(0);
699
- }
700
- if (!target) {
701
- console.error('Usage: eventmodeler show event <name>');
702
- console.error('Run "eventmodeler show event --help" for more information.');
703
- process.exit(1);
704
- }
705
- {
706
- const result = await api.showEvent(modelId, target, format);
707
- console.log(result);
708
- }
709
- break;
710
- case 'command':
711
- if (helpRequested) {
712
- console.log(`
713
- eventmodeler show command - Show detailed command information
714
-
715
- USAGE:
716
- eventmodeler show command <name> [--format xml|json]
717
-
718
- ARGUMENTS:
719
- <name> Command name (spaces allowed without quotes)
720
-
721
- OUTPUT INCLUDES:
722
- - Command name and aggregate
723
- - All fields with types, flags, and nested subfields
724
-
725
- EXAMPLES:
726
- eventmodeler show command PlaceOrder
727
- eventmodeler show command "Place Order" --format json
728
- `);
729
- process.exit(0);
730
- }
731
- if (!target) {
732
- console.error('Usage: eventmodeler show command <name>');
733
- console.error('Run "eventmodeler show command --help" for more information.');
734
- process.exit(1);
735
- }
736
- {
737
- const result = await api.showCommand(modelId, target, format);
738
- console.log(result);
739
- }
740
- break;
741
- case 'chapter':
742
- if (helpRequested) {
743
- console.log(`
744
- eventmodeler show chapter - Show detailed chapter information
745
-
746
- USAGE:
747
- eventmodeler show chapter <name> [--format xml|json]
748
-
749
- ARGUMENTS:
750
- <name> Chapter name
751
-
752
- OUTPUT INCLUDES:
753
- - All slices in the chapter
754
- - Flow graph showing internal dependencies
755
- - External dependencies (inbound/outbound)
756
-
757
- EXAMPLES:
758
- eventmodeler show chapter "Order Management"
759
- eventmodeler show chapter "Order Management" --format json
760
- `);
761
- process.exit(0);
762
- }
763
- if (!target) {
764
- console.error('Usage: eventmodeler show chapter <name>');
765
- console.error('Run "eventmodeler show chapter --help" for more information.');
766
- process.exit(1);
767
- }
768
- {
769
- const result = await api.showChapter(modelId, target, format);
770
- console.log(result);
771
- }
772
- break;
773
- case 'information-completeness':
774
- if (helpRequested) {
775
- console.log(`
776
- eventmodeler show information-completeness - Show information completeness
777
-
778
- USAGE:
779
- eventmodeler show information-completeness [--format xml|json]
780
- eventmodeler show information-completeness --slice "Place Order"
781
- eventmodeler show information-completeness --chapter "Ordering"
782
- eventmodeler show information-completeness <element-name> [--format xml|json]
783
-
784
- OUTPUT INCLUDES (model-wide):
785
- - Summary of complete/incomplete flows across the whole model
786
- - Incomplete flows grouped by slice, with untraceable fields
787
- - Incomplete read models with untraceable fields and source events
788
-
789
- OUTPUT INCLUDES (per-element):
790
- - Total fields vs mapped fields
791
- - List of unmapped fields needing attention
792
- - Mapping sources for mapped fields
793
-
794
- IMPORTANT - GENERATED FIELDS:
795
- Fields with isGenerated=true are EXCLUDED from completeness checks.
796
- Generated fields are computed/synthesized values that don't need
797
- source mappings (e.g., calculated totals, timestamps, derived data).
798
-
799
- NOTE: Generated and user-input fields are excluded from checks.
800
- Auto-matching uses field name AND type.
801
-
802
- EXAMPLES:
803
- eventmodeler show information-completeness
804
- eventmodeler show information-completeness --slice "Place Order"
805
- eventmodeler show information-completeness --chapter "Ordering"
806
- eventmodeler show information-completeness --format json
807
- eventmodeler show information-completeness CreateOrder
808
- eventmodeler show information-completeness "Order Summary" --format json
809
- `);
810
- process.exit(0);
811
- }
812
- {
813
- if (target) {
814
- // Per-element completeness
815
- const result = await api.showElementCompleteness(modelId, target, format);
816
- console.log(result);
817
- }
818
- else {
819
- // Model-wide information completeness
820
- const sliceFilter = getNamedArg(filteredArgs, '--slice');
821
- const result = await api.showInformationCompleteness(modelId, format, sliceFilter, chapterArg ?? undefined);
822
- console.log(result);
823
- }
824
- }
825
- break;
826
- case 'aggregate-completeness':
827
- if (helpRequested) {
828
- console.log(`
829
- eventmodeler show aggregate-completeness - Check aggregate ID field presence
830
-
831
- USAGE:
832
- eventmodeler show aggregate-completeness <name> [--format xml|json]
833
-
834
- ARGUMENTS:
835
- <name> Aggregate name
836
-
837
- OUTPUT:
838
- Lists all events in the aggregate and whether each has the
839
- aggregate ID field (e.g., "orderId" for "Order" aggregate).
840
-
841
- EXAMPLES:
842
- eventmodeler show aggregate-completeness Order
843
- eventmodeler show aggregate-completeness "Order" --format json
844
- `);
845
- process.exit(0);
846
- }
847
- if (!target) {
848
- console.error('Usage: eventmodeler show aggregate-completeness <aggregate-name>');
849
- console.error('Run "eventmodeler show aggregate-completeness --help" for more information.');
850
- process.exit(1);
851
- }
852
- {
853
- const result = await api.showAggregateCompleteness(modelId, target, format);
854
- console.log(result);
855
- }
856
- break;
857
- case 'actor':
858
- if (helpRequested) {
859
- console.log(`
860
- eventmodeler show actor - Show detailed actor information
861
-
862
- USAGE:
863
- eventmodeler show actor <name> [--format xml|json]
864
-
865
- ARGUMENTS:
866
- <name> Actor name
867
-
868
- OUTPUT INCLUDES:
869
- - Actor name
870
- - All associated screens
871
-
872
- EXAMPLES:
873
- eventmodeler show actor Customer
874
- eventmodeler show actor "Admin User" --format json
875
- `);
876
- process.exit(0);
877
- }
878
- if (!target) {
879
- console.error('Usage: eventmodeler show actor <actor-name>');
880
- console.error('Run "eventmodeler show actor --help" for more information.');
881
- process.exit(1);
882
- }
883
- {
884
- const result = await api.showActor(modelId, target, format);
885
- console.log(result);
886
- }
887
- break;
888
- case 'readmodel':
889
- if (helpRequested) {
890
- console.log(`
891
- eventmodeler show readmodel - Show detailed read model information
892
-
893
- USAGE:
894
- eventmodeler show readmodel <name> [--format xml|json]
895
-
896
- ARGUMENTS:
897
- <name> Read model name
898
-
899
- OUTPUT INCLUDES:
900
- - Read model name and fields
901
- - Events it consumes from (with field mappings)
902
- - Screens/Processors it flows to
903
-
904
- EXAMPLES:
905
- eventmodeler show readmodel OrderSummary
906
- eventmodeler show readmodel "Customer Profile" --format json
907
- `);
908
- process.exit(0);
909
- }
910
- if (!target) {
911
- console.error('Usage: eventmodeler show readmodel <name>');
912
- console.error('Run "eventmodeler show readmodel --help" for more information.');
913
- process.exit(1);
914
- }
915
- {
916
- const result = await api.showReadModel(modelId, target, format);
917
- console.log(result);
918
- }
919
- break;
920
- case 'screen':
921
- if (helpRequested) {
922
- console.log(`
923
- eventmodeler show screen - Show detailed screen information
924
-
925
- USAGE:
926
- eventmodeler show screen <name> [--format xml|json]
927
-
928
- ARGUMENTS:
929
- <name> Screen name
930
-
931
- OUTPUT INCLUDES:
932
- - Screen name and fields
933
- - Actor (if contained in one)
934
- - Read models it displays from
935
- - Commands it triggers
936
-
937
- EXAMPLES:
938
- eventmodeler show screen "Order Form"
939
- eventmodeler show screen Dashboard --format json
940
- `);
941
- process.exit(0);
942
- }
943
- if (!target) {
944
- console.error('Usage: eventmodeler show screen <name>');
945
- console.error('Run "eventmodeler show screen --help" for more information.');
946
- process.exit(1);
947
- }
948
- {
949
- const result = await api.showScreen(modelId, target, format);
950
- console.log(result);
951
- }
952
- break;
953
- case 'processor':
954
- if (helpRequested) {
955
- console.log(`
956
- eventmodeler show processor - Show detailed processor information
957
-
958
- USAGE:
959
- eventmodeler show processor <name> [--format xml|json]
960
-
961
- ARGUMENTS:
962
- <name> Processor name
963
-
964
- OUTPUT INCLUDES:
965
- - Processor name and fields
966
- - Read models it subscribes to
967
- - Commands it triggers
968
-
969
- EXAMPLES:
970
- eventmodeler show processor "Order Validator"
971
- eventmodeler show processor NotificationSender --format json
972
- `);
973
- process.exit(0);
974
- }
975
- if (!target) {
976
- console.error('Usage: eventmodeler show processor <name>');
977
- console.error('Run "eventmodeler show processor --help" for more information.');
978
- process.exit(1);
979
- }
980
- {
981
- const result = await api.showProcessor(modelId, target, format);
982
- console.log(result);
983
- }
984
- break;
985
- case 'aggregate':
986
- if (helpRequested) {
987
- console.log(`
988
- eventmodeler show aggregate - Show detailed aggregate information
989
-
990
- USAGE:
991
- eventmodeler show aggregate <name> [--format xml|json]
992
-
993
- ARGUMENTS:
994
- <name> Aggregate name
995
-
996
- OUTPUT INCLUDES:
997
- - Aggregate name
998
- - ID field configuration (if set)
999
- - All contained events
1000
- - ID field completeness status
1001
-
1002
- EXAMPLES:
1003
- eventmodeler show aggregate Order
1004
- eventmodeler show aggregate "User Account" --format json
1005
- `);
1006
- process.exit(0);
1007
- }
1008
- if (!target) {
1009
- console.error('Usage: eventmodeler show aggregate <name>');
1010
- console.error('Run "eventmodeler show aggregate --help" for more information.');
1011
- process.exit(1);
1012
- }
1013
- {
1014
- const result = await api.showAggregate(modelId, target, format);
1015
- console.log(result);
1016
- }
1017
- break;
1018
- case 'scenario':
1019
- if (helpRequested) {
1020
- console.log(`
1021
- eventmodeler show scenario - Show detailed scenario information
1022
-
1023
- USAGE:
1024
- eventmodeler show scenario <name> [--format xml|json]
1025
-
1026
- ARGUMENTS:
1027
- <name> Scenario name
1028
-
1029
- OUTPUT INCLUDES:
1030
- - Scenario name and description
1031
- - Parent slice
1032
- - Given events (with field values)
1033
- - When command or events (with field values)
1034
- - Then expectations (events, error, command, etc.)
1035
-
1036
- EXAMPLES:
1037
- eventmodeler show scenario "Happy path"
1038
- eventmodeler show scenario "Invalid input" --format json
1039
- `);
1040
- process.exit(0);
1041
- }
1042
- if (!target) {
1043
- console.error('Usage: eventmodeler show scenario <name>');
1044
- console.error('Run "eventmodeler show scenario --help" for more information.');
1045
- process.exit(1);
1046
- }
1047
- {
1048
- const result = await api.showScenario(modelId, target, format);
1049
- console.log(result);
1050
- }
1051
- break;
1052
- default:
1053
- console.error(`Unknown show target: ${subcommand}`);
1054
- console.error('Valid targets: slice, event, command, chapter, information-completeness, aggregate-completeness, actor, readmodel, screen, processor, aggregate, scenario');
1055
- console.error('Run "eventmodeler show --help" for more information.');
1056
- process.exit(1);
1057
- }
1058
- break;
1059
- case 'search':
1060
- if (helpRequested) {
1061
- console.log(`
1062
- eventmodeler search - Search for entities by name
1063
-
1064
- USAGE:
1065
- eventmodeler search <term> [--format xml|json]
1066
-
1067
- ARGUMENTS:
1068
- <term> Search term (case-insensitive partial match)
1069
-
1070
- OPTIONS:
1071
- --format <format> Output format: xml (default) or json
1072
-
1073
- SEARCHES ACROSS:
1074
- - Slices
1075
- - Events
1076
- - Commands
1077
- - Read Models
1078
- - Screens
1079
- - Processors
1080
- - Chapters
1081
- - Aggregates
1082
- - Actors
1083
-
1084
- EXAMPLES:
1085
- eventmodeler search order
1086
- eventmodeler search "payment" --format json
1087
- `);
1088
- process.exit(0);
1089
- }
1090
- if (!subcommand) {
1091
- console.error('Usage: eventmodeler search <term>');
1092
- console.error('Run "eventmodeler search --help" for more information.');
1093
- process.exit(1);
1094
- }
1095
- {
1096
- const searchTerm = target ? `${subcommand} ${target}` : subcommand;
1097
- const response = await api.search(modelId, searchTerm);
1098
- if (format === 'json') {
1099
- console.log(JSON.stringify(response, null, 2));
1100
- }
1101
- else {
1102
- const xb = new XMLBuilder({ ignoreAttributes: false, attributeNamePrefix: '@_', suppressEmptyNode: true });
1103
- const results = response.results.map(r => {
1104
- const tag = r.type === 'readmodel' ? 'read-model' : r.type;
1105
- const attrs = {};
1106
- if (r.id)
1107
- attrs['@_id'] = r.id;
1108
- if (r.name)
1109
- attrs['@_name'] = r.name;
1110
- if (r.chapterId)
1111
- attrs['@_chapter-id'] = r.chapterId;
1112
- if (r.chapterName)
1113
- attrs['@_chapter-name'] = r.chapterName;
1114
- if (r.sliceId)
1115
- attrs['@_slice-id'] = r.sliceId;
1116
- if (r.sliceName)
1117
- attrs['@_slice-name'] = r.sliceName;
1118
- if (r.sliceStatus)
1119
- attrs['@_slice-status'] = r.sliceStatus;
1120
- if (r.parentChapterId)
1121
- attrs['@_parent-chapter-id'] = r.parentChapterId;
1122
- if (r.parentChapterName)
1123
- attrs['@_parent-chapter-name'] = r.parentChapterName;
1124
- return ` ${xb.build({ [tag]: attrs }).trim()}`;
1125
- });
1126
- const wrapper = xb.build({ 'search-results': { '@_query': searchTerm, '@_count': String(response.results.length) } });
1127
- // Replace self-closing tag with children
1128
- const open = wrapper.replace(/\/>$/, '>').trim();
1129
- console.log([open, ...results, '</search-results>'].join('\n'));
1130
- }
1131
- }
1132
- break;
1133
- case 'mark': {
1134
- if (helpRequested) {
1135
- console.log(`
1136
- eventmodeler mark - Mark a slice's status
1137
-
1138
- USAGE:
1139
- eventmodeler mark <slice-name> <status>
1140
-
1141
- ARGUMENTS:
1142
- <slice-name> Slice name (can include spaces)
1143
- <status> One of: created, in-progress, blocked, done
1144
-
1145
- STATUSES:
1146
- created Initial state, not yet started
1147
- in-progress Currently being worked on
1148
- blocked Work paused due to dependency or issue
1149
- done Completed
1150
-
1151
- EXAMPLES:
1152
- eventmodeler mark "Place Order" done
1153
- eventmodeler mark "Process Payment" in-progress
1154
- eventmodeler mark "Ship Order" blocked
1155
- `);
1156
- process.exit(0);
1157
- }
1158
- // mark <slice-name> <status> - status is last arg, slice name is everything before
1159
- // Note: subcommand contains first part of slice name, remainingArgs has the rest
1160
- const validStatuses = ['created', 'in-progress', 'blocked', 'done'];
1161
- const allArgs = subcommand ? [subcommand, ...remainingArgs] : remainingArgs;
1162
- const lastArg = allArgs[allArgs.length - 1];
1163
- if (allArgs.length < 2 || !validStatuses.includes(lastArg)) {
1164
- console.error('Usage: eventmodeler mark <slice-name> <status>');
1165
- console.error('Valid statuses: created, in-progress, blocked, done');
1166
- console.error('Run "eventmodeler mark --help" for more information.');
1167
- process.exit(1);
1168
- }
1169
- const sliceName = allArgs.slice(0, -1).join(' ');
1170
- const status = lastArg;
1171
- await api.markSliceStatus(modelId, sliceName, status);
1172
- console.log(`Marked slice "${sliceName}" as ${status}`);
1173
- break;
1174
- }
1175
- case 'summary':
1176
- if (helpRequested) {
1177
- console.log(`
1178
- eventmodeler summary - Show model summary statistics
1179
-
1180
- USAGE:
1181
- eventmodeler summary [--format xml|json]
1182
-
1183
- OPTIONS:
1184
- --format <format> Output format: xml (default) or json
1185
-
1186
- OUTPUT:
1187
- Aggregate statistics including:
1188
- - Total counts (slices, events, commands, read models, screens, etc.)
1189
- - Slices by type (state-change, automation, state-view)
1190
- - Slices by status (created, in-progress, blocked, done)
1191
- - Chapter summary
1192
-
1193
- EXAMPLES:
1194
- eventmodeler summary
1195
- eventmodeler summary --format json
1196
- `);
1197
- process.exit(0);
1198
- }
1199
- {
1200
- const summary = await api.getSummary(modelId);
1201
- if (format === 'json') {
1202
- console.log(JSON.stringify(summary, null, 2));
1203
- }
1204
- else {
1205
- const xb = new XMLBuilder({ ignoreAttributes: false, attributeNamePrefix: '@_', format: true, indentBy: ' ', suppressEmptyNode: true });
1206
- console.log(xb.build({
1207
- model: {
1208
- '@_name': summary.modelName || '',
1209
- slices: { '@_count': String(summary.slices.total) },
1210
- commands: { '@_count': String(summary.commands) },
1211
- events: { '@_count': String(summary.events) },
1212
- 'read-models': { '@_count': String(summary.readModels) },
1213
- screens: { '@_count': String(summary.screens) },
1214
- processors: { '@_count': String(summary.processors) },
1215
- aggregates: { '@_count': String(summary.aggregates) },
1216
- actors: { '@_count': String(summary.actors) },
1217
- scenarios: { '@_count': String(summary.scenarios) },
1218
- flows: { '@_count': String(summary.flows) },
1219
- },
1220
- }).trim());
1221
- }
1222
- }
1223
- break;
1224
- case 'export':
1225
- if (helpRequested && !subcommand) {
1226
- console.log(`
1227
- eventmodeler export - Export the model
1228
-
1229
- USAGE:
1230
- eventmodeler export <format>
1231
-
1232
- FORMATS:
1233
- json Export entire model as JSON
1234
-
1235
- Run "eventmodeler export json --help" for detailed help.
1236
- `);
1237
- process.exit(0);
1238
- }
1239
- switch (subcommand) {
1240
- case 'json':
1241
- if (helpRequested) {
1242
- console.log(`
1243
- eventmodeler export json - Export entire model as JSON
1244
-
1245
- USAGE:
1246
- eventmodeler export json
1247
-
1248
- OUTPUT:
1249
- Complete event model as JSON to stdout, including:
1250
- - All entities (slices, events, commands, read models, screens, etc.)
1251
- - All flows and field mappings
1252
- - All scenarios
1253
- - Metadata (chapters, aggregates, actors)
1254
-
1255
- EXAMPLES:
1256
- eventmodeler export json
1257
- eventmodeler export json > model.json
1258
- eventmodeler export json | jq '.events'
1259
- `);
1260
- process.exit(0);
1261
- }
1262
- {
1263
- const result = await api.exportJson(modelId);
1264
- console.log(JSON.stringify(JSON.parse(result), null, 2));
1265
- }
1266
- break;
1267
- default:
1268
- console.error(`Unknown export format: ${subcommand}`);
1269
- console.error('Valid formats: json');
1270
- console.error('Run "eventmodeler export --help" for more information.');
1271
- process.exit(1);
1272
- }
1273
- break;
1274
- case 'add':
1275
- if (helpRequested && !subcommand) {
1276
- console.log(`
1277
- eventmodeler add - Add entities to the model
1278
-
1279
- USAGE:
1280
- eventmodeler add <type> [options]
1281
-
1282
- TYPES:
1283
- scenario Add Given-When-Then scenario to a slice
1284
- field Add field to command, event, read model, screen, or processor
1285
-
1286
- Run "eventmodeler add <type> --help" for type-specific help.
1287
- `);
1288
- process.exit(0);
1289
- }
1290
- switch (subcommand) {
1291
- case 'scenario': {
1292
- if (helpRequested) {
1293
- console.log(`
1294
- eventmodeler add scenario - Add a scenario to a slice
1295
-
1296
- USAGE:
1297
- eventmodeler add scenario --slice <name> --json|--xml <data>
1298
-
1299
- OPTIONS:
1300
- --slice <name> Target slice name (required)
1301
- --json <data> Scenario in JSON format
1302
- --xml <data> Scenario in XML format
1303
-
1304
- JSON FORMAT:
1305
- {
1306
- "name": "Scenario name",
1307
- "given": { // Optional: preconditions
1308
- "type": "events",
1309
- "events": ["EventName1", "EventName2"]
1310
- },
1311
- "when": { // Optional: trigger
1312
- "type": "command",
1313
- "command": "CommandName"
1314
- },
1315
- "then": { // Required: expected outcome
1316
- "type": "events",
1317
- "events": ["ExpectedEvent"]
1318
- }
1319
- }
1320
-
1321
- XML FORMAT:
1322
- <scenario name="Scenario name">
1323
- <given type="events">
1324
- <event>EventName1</event>
1325
- </given>
1326
- <when type="command">
1327
- <command>CommandName</command>
1328
- </when>
1329
- <then type="events">
1330
- <event>ExpectedEvent</event>
1331
- </then>
1332
- </scenario>
1333
-
1334
- EXAMPLES:
1335
- eventmodeler add scenario --slice "Place Order" --json '{"name": "Happy path", "then": {"type": "events", "events": ["OrderPlaced"]}}'
1336
-
1337
- eventmodeler add scenario --slice "Place Order" --xml '<scenario name="Out of stock"><given type="events"><event>ProductOutOfStock</event></given><then type="events"><event>OrderRejected</event></then></scenario>'
1338
- `);
1339
- process.exit(0);
1340
- }
1341
- const sliceArg = getNamedArg(filteredArgs, '--slice');
1342
- const jsonArg = getNamedArg(filteredArgs, '--json');
1343
- const xmlArg = getNamedArg(filteredArgs, '--xml');
1344
- const inputData = jsonArg ?? xmlArg;
1345
- if (!sliceArg) {
1346
- console.error('Error: --slice is required');
1347
- console.error('Usage: eventmodeler add scenario --slice <name> --json|--xml <data>');
1348
- console.error('Run "eventmodeler add scenario --help" for detailed format.');
1349
- process.exit(1);
1350
- }
1351
- if (!inputData) {
1352
- console.error('Error: --json or --xml is required');
1353
- console.error('Usage: eventmodeler add scenario --slice <name> --json|--xml <data>');
1354
- console.error('Run "eventmodeler add scenario --help" for detailed format.');
1355
- process.exit(1);
1356
- }
1357
- {
1358
- let parsedScenario;
1359
- try {
1360
- parsedScenario = parseScenarioInput(inputData);
1361
- }
1362
- catch (err) {
1363
- console.error(`Error parsing scenario data: ${err.message}`);
1364
- process.exit(1);
1365
- }
1366
- const scenario = {
1367
- name: parsedScenario.name,
1368
- description: parsedScenario.description,
1369
- given: parsedScenario.given,
1370
- when: parsedScenario.when
1371
- ? {
1372
- command: parsedScenario.when.command
1373
- ? {
1374
- command: parsedScenario.when.command,
1375
- fieldValues: parsedScenario.when.commandFieldValues,
1376
- }
1377
- : undefined,
1378
- events: parsedScenario.when.events,
1379
- }
1380
- : undefined,
1381
- then: {
1382
- type: parsedScenario.then.type,
1383
- events: parsedScenario.then.events,
1384
- errorMessage: parsedScenario.then.errorMessage,
1385
- errorType: parsedScenario.then.errorType,
1386
- command: parsedScenario.then.command
1387
- ? {
1388
- command: parsedScenario.then.command,
1389
- fieldValues: parsedScenario.then.commandFieldValues,
1390
- }
1391
- : undefined,
1392
- readModelAssertion: parsedScenario.then.readModel
1393
- ? {
1394
- readModel: parsedScenario.then.readModel,
1395
- givenEvents: parsedScenario.then.givenEvents,
1396
- expectedFieldValues: parsedScenario.then.expected,
1397
- }
1398
- : undefined,
1399
- },
1400
- };
1401
- await api.createScenario(modelId, sliceArg, scenario);
1402
- console.log(`Created scenario "${scenario.name}" in slice "${sliceArg}"`);
1403
- }
1404
- break;
1405
- }
1406
- case 'field': {
1407
- if (helpRequested) {
1408
- console.log(`
1409
- eventmodeler add field - Add a field to an entity
1410
-
1411
- USAGE:
1412
- eventmodeler add field <element-name> --json|--xml <data>
1413
-
1414
- OPTIONS:
1415
- <element-name> Name of the command, event, read model, screen, or processor
1416
- --json <data> Field definition in JSON format
1417
- --xml <data> Field definition in XML format
1418
-
1419
- FIELD TYPES:
1420
- UUID, String, Int, Long, Double, Decimal, Boolean, Date, DateTime, Custom
1421
-
1422
- FIELD FLAGS (work on ALL fields including nested subfields):
1423
- isList - Field contains multiple values (array)
1424
- isOptional - Field may be null/missing
1425
- isGenerated - Field is computed/synthesized, not mapped from source
1426
- isUserInput - (Screen only) Field is entered by user
1427
-
1428
- JSON FORMAT:
1429
- Simple field:
1430
- {"name": "orderId", "type": "UUID"}
1431
-
1432
- Field with flags:
1433
- {"name": "notes", "type": "String", "isOptional": true}
1434
- {"name": "tags", "type": "String", "isList": true}
1435
- {"name": "total", "type": "Decimal", "isGenerated": true}
1436
-
1437
- Nested Custom field with subfields (ALL flags work on subfields):
1438
- {
1439
- "name": "lineItem",
1440
- "type": "Custom",
1441
- "subfields": [
1442
- {"name": "productId", "type": "UUID"},
1443
- {"name": "quantity", "type": "Int"},
1444
- {"name": "unitPrice", "type": "Decimal"},
1445
- {"name": "lineTotal", "type": "Decimal", "isGenerated": true}
1446
- ]
1447
- }
1448
-
1449
- List of Custom with generated subfields:
1450
- {
1451
- "name": "items",
1452
- "type": "Custom",
1453
- "isList": true,
1454
- "subfields": [
1455
- {"name": "sku", "type": "String"},
1456
- {"name": "qty", "type": "Int"},
1457
- {"name": "calculatedPrice", "type": "Decimal", "isGenerated": true}
1458
- ]
1459
- }
1460
-
1461
- XML FORMAT:
1462
- Simple field:
1463
- <field name="orderId" type="UUID"/>
1464
-
1465
- Field with flags:
1466
- <field name="notes" type="String" isOptional="true"/>
1467
- <field name="tags" type="String" isList="true"/>
1468
- <field name="total" type="Decimal" isGenerated="true"/>
1469
-
1470
- Nested Custom field (ALL flags work on subfields):
1471
- <field name="lineItem" type="Custom">
1472
- <field name="productId" type="UUID"/>
1473
- <field name="quantity" type="Int"/>
1474
- <field name="unitPrice" type="Decimal"/>
1475
- <field name="lineTotal" type="Decimal" isGenerated="true"/>
1476
- </field>
1477
-
1478
- List of Custom with flags on subfields:
1479
- <field name="items" type="Custom" isList="true">
1480
- <field name="sku" type="String"/>
1481
- <field name="qty" type="Int"/>
1482
- <field name="calculatedPrice" type="Decimal" isGenerated="true"/>
1483
- <field name="notes" type="String" isOptional="true"/>
1484
- </field>
1485
-
1486
- NOTES:
1487
- - Generated fields are excluded from completeness checks
1488
- - Custom type fields must have subfields defined
1489
- - Subfields support arbitrary nesting depth
1490
-
1491
- EXAMPLES:
1492
- eventmodeler add field OrderPlaced --json '{"name": "orderId", "type": "UUID"}'
1493
- eventmodeler add field OrderSummary --json '{"name": "totalWithTax", "type": "Decimal", "isGenerated": true}'
1494
- eventmodeler add field OrderPlaced --xml '<field name="item" type="Custom"><field name="price" type="Decimal"/><field name="tax" type="Decimal" isGenerated="true"/></field>'
1495
- `);
1496
- process.exit(0);
1497
- }
1498
- const jsonArg = getNamedArg(filteredArgs, '--json');
1499
- const xmlArg = getNamedArg(filteredArgs, '--xml');
1500
- const inputData = jsonArg ?? xmlArg;
1501
- // Element name is the first positional arg after command+subcommand (not a flag or flag value)
1502
- const elementName = remainingArgs.find((a, i) => !a.startsWith('-') && (i === 0 || !['--json', '--xml'].includes(remainingArgs[i - 1])));
1503
- if (!elementName) {
1504
- console.error('Error: Element name is required');
1505
- console.error('Usage: eventmodeler add field <element-name> --json|--xml <data>');
1506
- console.error('Run "eventmodeler add field --help" for detailed format documentation.');
1507
- process.exit(1);
1508
- }
1509
- if (!inputData) {
1510
- console.error('Error: --json or --xml is required');
1511
- console.error('Usage: eventmodeler add field <element-name> --json|--xml <data>');
1512
- console.error('Run "eventmodeler add field --help" for detailed format documentation.');
1513
- process.exit(1);
1514
- }
1515
- {
1516
- // Parse field data
1517
- let field;
1518
- const toApiFieldFromJson = (f) => ({
1519
- name: f.name,
1520
- fieldType: f.type ?? f.fieldType ?? 'String',
1521
- isList: f.isList,
1522
- isOptional: f.isOptional,
1523
- isGenerated: f.isGenerated,
1524
- isUserInput: f.isUserInput,
1525
- subfields: f.subfields?.map(toApiFieldFromJson),
1526
- });
1527
- try {
1528
- if (jsonArg) {
1529
- const parsed = JSON.parse(inputData);
1530
- field = toApiFieldFromJson(parsed);
1531
- }
1532
- else {
1533
- const parser = await import('./lib/slice-utils.js');
1534
- const parsed = parser.parseFieldsFromXml(inputData);
1535
- if (parsed.length === 0) {
1536
- throw new Error('No <field> element found in XML');
1537
- }
1538
- const toApiField = (f) => ({
1539
- name: f.name,
1540
- fieldType: f.type,
1541
- isList: f.isList,
1542
- isOptional: f.isOptional,
1543
- isGenerated: f.isGenerated,
1544
- isUserInput: f.isUserInput,
1545
- subfields: f.subfields?.map(toApiField),
1546
- });
1547
- field = toApiField(parsed[0]);
1548
- }
1549
- }
1550
- catch (err) {
1551
- console.error(`Error parsing field data: ${err.message}`);
1552
- process.exit(1);
1553
- }
1554
- await api.addField(modelId, elementName, field);
1555
- console.log(`Added field "${field.name}" to "${elementName}"`);
1556
- }
1557
- break;
1558
- }
1559
- default:
1560
- console.error(`Unknown add target: ${subcommand}`);
1561
- console.error('Valid targets: scenario, field');
1562
- process.exit(1);
1563
- }
1564
- break;
1565
- case 'remove':
1566
- if (helpRequested && !subcommand) {
1567
- console.log(`
1568
- eventmodeler remove - Remove entities from the model
1569
-
1570
- USAGE:
1571
- eventmodeler remove <type> [options]
1572
-
1573
- TYPES:
1574
- scenario Remove a scenario from a slice
1575
- field Remove a field from an entity
1576
- flow Remove a flow between elements
1577
-
1578
- Run "eventmodeler remove <type> --help" for type-specific help.
1579
- `);
1580
- process.exit(0);
1581
- }
1582
- switch (subcommand) {
1583
- case 'scenario': {
1584
- if (helpRequested) {
1585
- console.log(`
1586
- eventmodeler remove scenario - Remove a scenario from a slice
1587
-
1588
- USAGE:
1589
- eventmodeler remove scenario <name> [--slice <slice-name>]
1590
-
1591
- ARGUMENTS:
1592
- <name> Scenario name to remove
1593
-
1594
- OPTIONS:
1595
- --slice <name> Limit search to specific slice (optional)
1596
-
1597
- EXAMPLES:
1598
- eventmodeler remove scenario "Happy path"
1599
- eventmodeler remove scenario "Edge case" --slice "Place Order"
1600
- `);
1601
- process.exit(0);
1602
- }
1603
- const sliceArg = getNamedArg(filteredArgs, '--slice');
1604
- // Filter out --slice and its value from remaining args to get scenario name
1605
- const scenarioArgs = filteredArgs.slice(2).filter((arg, i, arr) => {
1606
- if (arg === '--slice')
1607
- return false;
1608
- if (i > 0 && arr[i - 1] === '--slice')
1609
- return false;
1610
- return true;
1611
- });
1612
- const scenarioName = scenarioArgs.length > 0 ? scenarioArgs.join(' ') : undefined;
1613
- if (!scenarioName) {
1614
- console.error('Usage: eventmodeler remove scenario <name> [--slice <slice-name>]');
1615
- console.error('Run "eventmodeler remove scenario --help" for more information.');
1616
- process.exit(1);
1617
- }
1618
- await api.removeScenario(modelId, scenarioName, sliceArg);
1619
- console.log(`Removed scenario "${scenarioName}"${sliceArg ? ` from slice "${sliceArg}"` : ''}`);
1620
- break;
1621
- }
1622
- case 'field': {
1623
- if (helpRequested) {
1624
- console.log(`
1625
- eventmodeler remove field - Remove a field from an entity
1626
-
1627
- USAGE:
1628
- eventmodeler remove field <element-name> --field <field-name>
1629
-
1630
- OPTIONS:
1631
- <element-name> Name of the command, event, read model, screen, or processor
1632
- --field <name> Field name to remove (required)
1633
-
1634
- EXAMPLES:
1635
- eventmodeler remove field OrderPlaced --field orderId
1636
- eventmodeler remove field "Order Summary" --field notes
1637
- `);
1638
- process.exit(0);
1639
- }
1640
- const fieldArg = getNamedArg(filteredArgs, '--field');
1641
- // Element name is the first positional arg after command+subcommand (not a flag or flag value)
1642
- const elementName = remainingArgs.find((a, i) => !a.startsWith('-') && (i === 0 || !['--field'].includes(remainingArgs[i - 1])));
1643
- if (!fieldArg) {
1644
- console.error('Error: --field is required');
1645
- console.error('Usage: eventmodeler remove field <element-name> --field <field-name>');
1646
- console.error('Run "eventmodeler remove field --help" for more information.');
1647
- process.exit(1);
1648
- }
1649
- if (!elementName) {
1650
- console.error('Error: Element name is required');
1651
- console.error('Usage: eventmodeler remove field <element-name> --field <field-name>');
1652
- console.error('Run "eventmodeler remove field --help" for more information.');
1653
- process.exit(1);
1654
- }
1655
- {
1656
- await api.removeField(modelId, elementName, fieldArg);
1657
- console.log(`Removed field "${fieldArg}" from "${elementName}"`);
1658
- }
1659
- break;
1660
- }
1661
- case 'flow': {
1662
- if (helpRequested) {
1663
- console.log(`
1664
- eventmodeler remove flow - Remove a flow between elements
1665
-
1666
- USAGE:
1667
- eventmodeler remove flow --from <source> --to <target>
1668
-
1669
- OPTIONS:
1670
- --from <name> Source element name (required)
1671
- --to <name> Target element name (required)
1672
-
1673
- EXAMPLES:
1674
- eventmodeler remove flow --from OrderPlaced --to OrderSummary
1675
- eventmodeler remove flow --from "Order Summary" --to "Order Dashboard Screen"
1676
- `);
1677
- process.exit(0);
1678
- }
1679
- const fromArg = getNamedArg(filteredArgs, '--from');
1680
- const toArg = getNamedArg(filteredArgs, '--to');
1681
- if (!fromArg || !toArg) {
1682
- console.error('Error: --from and --to are required');
1683
- console.error('Usage: eventmodeler remove flow --from <source> --to <target>');
1684
- console.error('Run "eventmodeler remove flow --help" for more information.');
1685
- process.exit(1);
1686
- }
1687
- await api.removeFlow(modelId, fromArg, toArg);
1688
- console.log(`Removed flow from "${fromArg}" to "${toArg}"`);
1689
- break;
1690
- }
1691
- default:
1692
- console.error(`Unknown remove target: ${subcommand}`);
1693
- console.error('Valid targets: scenario, field, flow');
1694
- console.error('Run "eventmodeler remove --help" for more information.');
1695
- process.exit(1);
1696
- }
1697
- break;
1698
- case 'map':
1699
- if (helpRequested && !subcommand) {
1700
- console.log(`
1701
- eventmodeler map - Set field mappings
1702
-
1703
- USAGE:
1704
- eventmodeler map <type> [options]
1705
-
1706
- TYPES:
1707
- fields Set field mappings on a flow
1708
-
1709
- Run "eventmodeler map fields --help" for detailed help.
1710
- `);
1711
- process.exit(0);
1712
- }
1713
- switch (subcommand) {
1714
- case 'fields': {
1715
- if (helpRequested) {
1716
- console.log(`
1717
- eventmodeler map fields - Set field mappings on a flow
1718
-
1719
- USAGE:
1720
- eventmodeler map fields --flow <source→target> --json|--xml <mappings>
1721
-
1722
- OPTIONS:
1723
- --flow <spec> Flow as "SourceName→TargetName" (use → or ->)
1724
- --json <data> Mappings in JSON format
1725
- --xml <data> Mappings in XML format
1726
-
1727
- JSON FORMAT:
1728
- [
1729
- {"from": "sourceField", "to": "targetField"},
1730
- {"from": "amount", "to": "orderTotal"}
1731
- ]
1732
-
1733
- XML FORMAT:
1734
- <mappings>
1735
- <mapping from="sourceField" to="targetField"/>
1736
- <mapping from="amount" to="orderTotal"/>
1737
- </mappings>
1738
-
1739
- NOTES:
1740
- - Mappings define how fields flow from source to target
1741
- - Fields marked as isGenerated=true don't need mappings
1742
- - Use "show information-completeness <name>" to check mapping status
1743
-
1744
- EXAMPLES:
1745
- eventmodeler map fields --flow "OrderPlaced→OrderSummary" --json '[{"from": "total", "to": "totalAmount"}]'
1746
-
1747
- eventmodeler map fields --flow "OrderPlaced->OrderSummary" --xml '<mappings><mapping from="total" to="totalAmount"/></mappings>'
1748
- `);
1749
- process.exit(0);
1750
- }
1751
- const flowArg = getNamedArg(filteredArgs, '--flow');
1752
- const jsonArg = getNamedArg(filteredArgs, '--json');
1753
- const xmlArg = getNamedArg(filteredArgs, '--xml');
1754
- const inputData = jsonArg ?? xmlArg;
1755
- if (!flowArg) {
1756
- console.error('Error: --flow is required');
1757
- console.error('Usage: eventmodeler map fields --flow <source→target> --json|--xml <mappings>');
1758
- console.error('Run "eventmodeler map fields --help" for detailed format.');
1759
- process.exit(1);
1760
- }
1761
- if (!inputData) {
1762
- console.error('Error: --json or --xml is required');
1763
- console.error('Usage: eventmodeler map fields --flow <source→target> --json|--xml <mappings>');
1764
- console.error('Run "eventmodeler map fields --help" for detailed format.');
1765
- process.exit(1);
1766
- }
1767
- {
1768
- // Parse flow argument to extract source and target names
1769
- const flowParts = flowArg.split(/→|->/).map(s => s.trim());
1770
- if (flowParts.length !== 2) {
1771
- console.error('Error: --flow must be in format "SourceName→TargetName" or "SourceName->TargetName"');
1772
- process.exit(1);
1773
- }
1774
- const [sourceName, targetName] = flowParts;
1775
- // Parse mappings from JSON or XML
1776
- let mappings;
1777
- try {
1778
- if (jsonArg) {
1779
- mappings = JSON.parse(inputData);
1780
- }
1781
- else {
1782
- const xp = new XMLParser({ ignoreAttributes: false, attributeNamePrefix: '@_', isArray: (name) => name === 'mapping' });
1783
- const parsed = xp.parse(inputData);
1784
- const root = parsed['mappings'];
1785
- const nodes = root ? (Array.isArray(root['mapping']) ? root['mapping'] : root['mapping'] ? [root['mapping']] : []) : [];
1786
- mappings = nodes.map(m => ({
1787
- from: m['@_from'] ?? '',
1788
- to: m['@_to'] ?? '',
1789
- }));
1790
- }
1791
- }
1792
- catch (err) {
1793
- console.error(`Error parsing mappings: ${err.message}`);
1794
- process.exit(1);
1795
- }
1796
- await api.mapFields(modelId, sourceName, targetName, mappings);
1797
- console.log(`Mapped ${mappings.length} field(s) from "${sourceName}" to "${targetName}"`);
1798
- }
1799
- break;
1800
- }
1801
- default:
1802
- console.error(`Unknown map target: ${subcommand}`);
1803
- console.error('Valid targets: fields');
1804
- console.error('Run "eventmodeler map --help" for more information.');
1805
- process.exit(1);
1806
- }
1807
- break;
1808
- case 'update':
1809
- if (helpRequested && !subcommand) {
1810
- console.log(`
1811
- eventmodeler update - Update entities in the model
1812
-
1813
- USAGE:
1814
- eventmodeler update <type> [options]
1815
-
1816
- TYPES:
1817
- field Update field properties
1818
-
1819
- Run "eventmodeler update field --help" for detailed help.
1820
- `);
1821
- process.exit(0);
1822
- }
1823
- switch (subcommand) {
1824
- case 'field': {
1825
- if (helpRequested) {
1826
- console.log(`
1827
- eventmodeler update field - Update field properties
1828
-
1829
- USAGE:
1830
- eventmodeler update field <element-name> --field <field-name> [updates]
1831
-
1832
- OPTIONS:
1833
- <element-name> Name of the command, event, read model, screen, or processor
1834
-
1835
- REQUIRED:
1836
- --field <name> Field to update (use dot-notation for nested subfields: "parent.child")
1837
-
1838
- UPDATE OPTIONS (at least one required):
1839
- --optional true|false Set isOptional flag
1840
- --generated true|false Set isGenerated flag
1841
- --user-input true|false Set isUserInput flag
1842
- --type <type> Change field type
1843
-
1844
- FIELD FLAGS EXPLAINED:
1845
- isOptional Field may be null/missing
1846
- isGenerated Field is computed, excluded from completeness checks
1847
- isUserInput (Screen only) Field entered by user vs displayed
1848
-
1849
- EXAMPLES:
1850
- # Mark field as optional
1851
- eventmodeler update field OrderSummary --field notes --optional true
1852
-
1853
- # Mark field as generated (computed value, no mapping needed)
1854
- eventmodeler update field OrderSummary --field totalWithTax --generated true
1855
-
1856
- # Mark screen field as user input
1857
- eventmodeler update field "Order Form" --field quantity --user-input true
1858
-
1859
- # Change field type
1860
- eventmodeler update field OrderPlaced --field amount --type Decimal
1861
-
1862
- # Update a nested subfield using dot-notation
1863
- eventmodeler update field OrderPlaced --field "shippingAddress.zipCode" --optional true
1864
- `);
1865
- process.exit(0);
1866
- }
1867
- const fieldArg = getNamedArg(filteredArgs, '--field');
1868
- const optionalArg = getNamedArg(filteredArgs, '--optional');
1869
- const generatedArg = getNamedArg(filteredArgs, '--generated');
1870
- const userInputArg = getNamedArg(filteredArgs, '--user-input');
1871
- const typeArg = getNamedArg(filteredArgs, '--type');
1872
- // Element name is the first positional arg after command+subcommand (not a flag or flag value)
1873
- const flagsWithValues = ['--field', '--optional', '--generated', '--user-input', '--type'];
1874
- const elementName = remainingArgs.find((a, i) => !a.startsWith('-') && (i === 0 || !flagsWithValues.includes(remainingArgs[i - 1])));
1875
- if (!fieldArg) {
1876
- console.error('Error: --field is required');
1877
- console.error('Usage: eventmodeler update field <element-name> --field <field-name> [--optional true|false] [--generated true|false] [--user-input true|false]');
1878
- console.error('Run "eventmodeler update field --help" for detailed options.');
1879
- process.exit(1);
1880
- }
1881
- if (!elementName) {
1882
- console.error('Error: Element name is required');
1883
- console.error('Usage: eventmodeler update field <element-name> --field <field-name> [--optional true|false] [--generated true|false] [--user-input true|false]');
1884
- console.error('Run "eventmodeler update field --help" for detailed options.');
1885
- process.exit(1);
1886
- }
1887
- const updates = {};
1888
- if (optionalArg !== undefined) {
1889
- updates.optional = optionalArg === 'true';
1890
- }
1891
- if (generatedArg !== undefined) {
1892
- updates.generated = generatedArg === 'true';
1893
- }
1894
- if (userInputArg !== undefined) {
1895
- updates.userInput = userInputArg === 'true';
1896
- }
1897
- if (typeArg !== undefined) {
1898
- updates.type = typeArg;
1899
- }
1900
- if (Object.keys(updates).length === 0) {
1901
- console.error('Error: Must specify at least one update (--optional, --generated, --user-input, or --type)');
1902
- console.error('Run "eventmodeler update field --help" for available options.');
1903
- process.exit(1);
1904
- }
1905
- {
1906
- // Convert updates to API format
1907
- const fieldUpdates = {};
1908
- if (updates.optional !== undefined)
1909
- fieldUpdates.isOptional = updates.optional;
1910
- if (updates.generated !== undefined)
1911
- fieldUpdates.isGenerated = updates.generated;
1912
- if (updates.userInput !== undefined)
1913
- fieldUpdates.isUserInput = updates.userInput;
1914
- if (updates.type !== undefined)
1915
- fieldUpdates.fieldType = updates.type;
1916
- await api.updateField(modelId, elementName, fieldArg, fieldUpdates);
1917
- console.log(`Updated field "${fieldArg}" on "${elementName}"`);
1918
- }
1919
- break;
1920
- }
1921
- default:
1922
- console.error(`Unknown update target: ${subcommand}`);
1923
- console.error('Valid targets: field');
1924
- console.error('Run "eventmodeler update --help" for more information.');
1925
- process.exit(1);
1926
- }
1927
- break;
1928
- case 'create':
1929
- if (helpRequested && !subcommand) {
1930
- console.log(`
1931
- eventmodeler create - Create new slices and flows
1932
-
1933
- USAGE:
1934
- eventmodeler create <type> [options]
1935
-
1936
- TYPES:
1937
- state-change-slice Create Screen → Command → Event slice
1938
- automation-slice Create ReadModel → Processor → Command → Event slice
1939
- state-view-slice Create ReadModel-only slice
1940
- flow Create flow between elements
1941
-
1942
- Run "eventmodeler create <type> --help" for type-specific help.
1943
- `);
1944
- process.exit(0);
1945
- }
1946
- switch (subcommand) {
1947
- case 'state-change-slice': {
1948
- if (helpRequested) {
1949
- console.log(`
1950
- eventmodeler create state-change-slice - Create a state-change slice
1951
-
1952
- A state-change slice represents user action: Screen → Command → Event
1953
-
1954
- USAGE:
1955
- eventmodeler create state-change-slice --xml <data>
1956
-
1957
- XML FORMAT:
1958
- <state-change-slice name="Slice Name" [after="Slice Name"] [before="Slice Name"]>
1959
- <screen name="Screen Name" actor="Actor Name">
1960
- <field name="fieldName" type="Type" [flags]/>
1961
- </screen>
1962
- <command name="CommandName">
1963
- <field name="fieldName" type="Type" [flags]/>
1964
- </command>
1965
- <event name="EventName">
1966
- <field name="fieldName" type="Type" [flags]/>
1967
- </event>
1968
- </state-change-slice>
1969
-
1970
- POSITIONING (IMPORTANT):
1971
- after="Slice Name" Place this slice immediately after the named slice
1972
- before="Slice Name" Place this slice immediately before the named slice
1973
- (shifts existing slices to the right)
1974
-
1975
- If neither is specified, the slice is placed at the rightmost position.
1976
- Use "eventmodeler list slices" to see existing slice names for positioning.
1977
-
1978
- FIELD TYPES:
1979
- UUID, String, Int, Long, Double, Decimal, Boolean, Date, DateTime, Custom
1980
-
1981
- FIELD FLAGS (work on ALL fields and nested subfields):
1982
- isList="true" Array/list of values
1983
- isOptional="true" Nullable field
1984
- isGenerated="true" Computed field (excluded from mapping completeness)
1985
- isUserInput="true" User-entered field (screen fields only)
1986
-
1987
- NESTED CUSTOM FIELDS:
1988
- <field name="address" type="Custom">
1989
- <field name="street" type="String"/>
1990
- <field name="city" type="String"/>
1991
- <field name="formattedFull" type="String" isGenerated="true"/>
1992
- </field>
1993
-
1994
- EXAMPLES:
1995
- # Create slice at the end (default)
1996
- eventmodeler create state-change-slice --xml '
1997
- <state-change-slice name="Place Order">
1998
- <screen name="Order Form" actor="Customer">
1999
- <field name="productId" type="UUID" isUserInput="true"/>
2000
- </screen>
2001
- <command name="PlaceOrder">
2002
- <field name="productId" type="UUID"/>
2003
- </command>
2004
- <event name="OrderPlaced">
2005
- <field name="orderId" type="UUID"/>
2006
- <field name="productId" type="UUID"/>
2007
- </event>
2008
- </state-change-slice>'
2009
-
2010
- # Create slice after an existing slice
2011
- eventmodeler create state-change-slice --xml '
2012
- <state-change-slice name="Confirm Order" after="Place Order">
2013
- ...
2014
- </state-change-slice>'
2015
-
2016
- # Create slice before an existing slice (shifts others right)
2017
- eventmodeler create state-change-slice --xml '
2018
- <state-change-slice name="Review Cart" before="Place Order">
2019
- ...
2020
- </state-change-slice>'
2021
- `);
2022
- process.exit(0);
2023
- }
2024
- const xmlArg = getNamedArg(filteredArgs, '--xml');
2025
- if (!xmlArg) {
2026
- console.error('Error: --xml is required');
2027
- console.error('Usage: eventmodeler create state-change-slice --xml \'<state-change-slice>...</state-change-slice>\'');
2028
- console.error('Run "eventmodeler create state-change-slice --help" for detailed format.');
2029
- process.exit(1);
2030
- }
2031
- {
2032
- // Parse XML input to extract structured data
2033
- const parser = await import('./lib/slice-utils.js');
2034
- const parsed = parser.parseStateChangeSliceXml(xmlArg);
2035
- const sliceInput = {
2036
- sliceName: parsed.sliceName,
2037
- after: parsed.after,
2038
- before: parsed.before,
2039
- screen: { name: parsed.screen.name, fields: toCompoundFields(parsed.screen.fields) },
2040
- command: { name: parsed.command.name, fields: toCompoundFields(parsed.command.fields) },
2041
- event: { name: parsed.event.name, fields: toCompoundFields(parsed.event.fields) },
2042
- };
2043
- const result = await api.createStateChangeSlice(modelId, sliceInput);
2044
- console.log(`Created state-change slice "${parsed.sliceName}"`);
2045
- console.log(` Screen: ${parsed.screen.name} (${parsed.screen.fields.length} fields)`);
2046
- console.log(` Command: ${parsed.command.name} (${parsed.command.fields.length} fields)`);
2047
- console.log(` Event: ${parsed.event.name} (${parsed.event.fields.length} fields)`);
2048
- console.log(` Screen -> Command mappings: ${result.screenToCommandMappings}`);
2049
- console.log(` Command -> Event mappings: ${result.commandToEventMappings}`);
2050
- }
2051
- break;
2052
- }
2053
- case 'automation-slice': {
2054
- if (helpRequested) {
2055
- console.log(`
2056
- eventmodeler create automation-slice - Create an automation slice
2057
-
2058
- An automation slice represents system automation: ReadModel → Processor → Command → Event
2059
-
2060
- USAGE:
2061
- eventmodeler create automation-slice --xml <data>
2062
-
2063
- XML FORMAT:
2064
- <automation-slice name="Slice Name" [after="Slice Name"] [before="Slice Name"]>
2065
- <read-model name="ReadModelName">
2066
- <field name="fieldName" type="Type" [flags]/>
2067
- </read-model>
2068
- <processor name="ProcessorName">
2069
- <field name="fieldName" type="Type" [flags]/>
2070
- </processor>
2071
- <command name="CommandName">
2072
- <field name="fieldName" type="Type" [flags]/>
2073
- </command>
2074
- <event name="EventName">
2075
- <field name="fieldName" type="Type" [flags]/>
2076
- </event>
2077
- </automation-slice>
2078
-
2079
- POSITIONING (IMPORTANT):
2080
- after="Slice Name" Place this slice immediately after the named slice
2081
- before="Slice Name" Place this slice immediately before the named slice
2082
- (shifts existing slices to the right)
2083
-
2084
- If neither is specified, the slice is placed at the rightmost position.
2085
- Use "eventmodeler list slices" to see existing slice names for positioning.
2086
-
2087
- FIELD TYPES:
2088
- UUID, String, Int, Long, Double, Decimal, Boolean, Date, DateTime, Custom
2089
-
2090
- FIELD FLAGS (work on ALL fields and nested subfields):
2091
- isList="true" Array/list of values
2092
- isOptional="true" Nullable field
2093
- isGenerated="true" Computed field (excluded from mapping completeness)
2094
-
2095
- EXAMPLES:
2096
- # Create automation slice after "Place Order" slice
2097
- eventmodeler create automation-slice --xml '
2098
- <automation-slice name="Auto-ship Order" after="Place Order">
2099
- <read-model name="OrderReadyForShipment">
2100
- <field name="orderId" type="UUID"/>
2101
- <field name="shippingAddress" type="String"/>
2102
- </read-model>
2103
- <processor name="ShipmentScheduler">
2104
- <field name="orderId" type="UUID"/>
2105
- </processor>
2106
- <command name="ScheduleShipment">
2107
- <field name="orderId" type="UUID"/>
2108
- </command>
2109
- <event name="ShipmentScheduled">
2110
- <field name="shipmentId" type="UUID" isGenerated="true"/>
2111
- <field name="orderId" type="UUID"/>
2112
- <field name="scheduledAt" type="DateTime" isGenerated="true"/>
2113
- </event>
2114
- </automation-slice>'
2115
-
2116
- # Create automation slice before another slice
2117
- eventmodeler create automation-slice --xml '
2118
- <automation-slice name="Validate Inventory" before="Auto-ship Order">
2119
- ...
2120
- </automation-slice>'
2121
- `);
2122
- process.exit(0);
2123
- }
2124
- const xmlArg = getNamedArg(filteredArgs, '--xml');
2125
- if (!xmlArg) {
2126
- console.error('Error: --xml is required');
2127
- console.error('Usage: eventmodeler create automation-slice --xml \'<automation-slice>...</automation-slice>\'');
2128
- console.error('Run "eventmodeler create automation-slice --help" for detailed format.');
2129
- process.exit(1);
2130
- }
2131
- {
2132
- // Parse XML input to extract structured data
2133
- const parser = await import('./lib/slice-utils.js');
2134
- const parsed = parser.parseAutomationSliceXml(xmlArg);
2135
- const sliceInput = {
2136
- sliceName: parsed.sliceName,
2137
- after: parsed.after,
2138
- before: parsed.before,
2139
- readModel: { name: parsed.readModel.name, fields: toCompoundFields(parsed.readModel.fields) },
2140
- processor: { name: parsed.processor.name },
2141
- command: { name: parsed.command.name, fields: toCompoundFields(parsed.command.fields) },
2142
- event: { name: parsed.event.name, fields: toCompoundFields(parsed.event.fields) },
2143
- };
2144
- const result = await api.createAutomationSlice(modelId, sliceInput);
2145
- console.log(`Created automation slice "${parsed.sliceName}"`);
2146
- console.log(` ReadModel: ${parsed.readModel.name} (${parsed.readModel.fields.length} fields)`);
2147
- console.log(` Processor: ${parsed.processor.name}`);
2148
- console.log(` Command: ${parsed.command.name} (${parsed.command.fields.length} fields)`);
2149
- console.log(` Event: ${parsed.event.name} (${parsed.event.fields.length} fields)`);
2150
- console.log(` ReadModel -> Command mappings: ${result.readModelToCommandMappings}`);
2151
- console.log(` Command -> Event mappings: ${result.commandToEventMappings}`);
2152
- }
2153
- break;
2154
- }
2155
- case 'state-view-slice': {
2156
- if (helpRequested) {
2157
- console.log(`
2158
- eventmodeler create state-view-slice - Create a state-view slice
2159
-
2160
- A state-view slice represents a read model for displaying data.
2161
-
2162
- USAGE:
2163
- eventmodeler create state-view-slice --xml <data>
2164
-
2165
- XML FORMAT:
2166
- <state-view-slice name="Slice Name" [after="Slice Name"] [before="Slice Name"]>
2167
- <read-model name="ReadModelName">
2168
- <field name="fieldName" type="Type" [flags]/>
2169
- </read-model>
2170
- </state-view-slice>
2171
-
2172
- POSITIONING (IMPORTANT):
2173
- after="Slice Name" Place this slice immediately after the named slice
2174
- before="Slice Name" Place this slice immediately before the named slice
2175
- (shifts existing slices to the right)
2176
-
2177
- If neither is specified, the slice is placed at the rightmost position.
2178
- Use "eventmodeler list slices" to see existing slice names for positioning.
2179
-
2180
- FIELD TYPES:
2181
- UUID, String, Int, Long, Double, Decimal, Boolean, Date, DateTime, Custom
2182
-
2183
- FIELD FLAGS (work on ALL fields and nested subfields):
2184
- isList="true" Array/list of values
2185
- isOptional="true" Nullable field
2186
- isGenerated="true" Computed/aggregated field (common for dashboards)
2187
-
2188
- EXAMPLES:
2189
- # Create state-view slice after "Place Order" slice
2190
- eventmodeler create state-view-slice --xml '
2191
- <state-view-slice name="Order Dashboard" after="Place Order">
2192
- <read-model name="OrderDashboard">
2193
- <field name="totalOrders" type="Int" isGenerated="true"/>
2194
- <field name="totalRevenue" type="Decimal" isGenerated="true"/>
2195
- <field name="averageOrderValue" type="Decimal" isGenerated="true"/>
2196
- <field name="recentOrders" type="Custom" isList="true">
2197
- <field name="orderId" type="UUID"/>
2198
- <field name="total" type="Decimal"/>
2199
- <field name="status" type="String"/>
2200
- </field>
2201
- </read-model>
2202
- </state-view-slice>'
2203
-
2204
- # Create state-view slice before another slice
2205
- eventmodeler create state-view-slice --xml '
2206
- <state-view-slice name="Customer Summary" before="Order Dashboard">
2207
- ...
2208
- </state-view-slice>'
2209
- `);
2210
- process.exit(0);
2211
- }
2212
- const xmlArg = getNamedArg(filteredArgs, '--xml');
2213
- if (!xmlArg) {
2214
- console.error('Error: --xml is required');
2215
- console.error('Usage: eventmodeler create state-view-slice --xml \'<state-view-slice>...</state-view-slice>\'');
2216
- console.error('Run "eventmodeler create state-view-slice --help" for detailed format.');
2217
- process.exit(1);
2218
- }
2219
- {
2220
- // Parse XML input to extract structured data
2221
- const parser = await import('./lib/slice-utils.js');
2222
- const parsed = parser.parseStateViewSliceXml(xmlArg);
2223
- const sliceInput = {
2224
- sliceName: parsed.sliceName,
2225
- after: parsed.after,
2226
- before: parsed.before,
2227
- readModel: { name: parsed.readModel.name, fields: toCompoundFields(parsed.readModel.fields) },
2228
- };
2229
- const result = await api.createStateViewSlice(modelId, sliceInput);
2230
- console.log(`Created state-view slice "${parsed.sliceName}"`);
2231
- console.log(` ReadModel: ${parsed.readModel.name} (${parsed.readModel.fields.length} fields)`);
2232
- }
2233
- break;
2234
- }
2235
- case 'flow': {
2236
- if (helpRequested) {
2237
- console.log(`
2238
- eventmodeler create flow - Create a flow between elements
2239
-
2240
- USAGE:
2241
- eventmodeler create flow --from <source> --to <target>
2242
-
2243
- OPTIONS:
2244
- --from <name> Source element name (required)
2245
- --to <name> Target element name (required)
2246
-
2247
- VALID FLOW TYPES:
2248
- Event → ReadModel Event data projects into read model
2249
- ReadModel → Screen Read model provides data to UI
2250
- ReadModel → Processor Read model triggers automation
2251
-
2252
- EXAMPLES:
2253
- eventmodeler create flow --from OrderPlaced --to OrderSummary
2254
- eventmodeler create flow --from "Order Summary" --to "Order Dashboard Screen"
2255
- eventmodeler create flow --from OrderReadyForShipment --to ShipmentProcessor
2256
- `);
2257
- process.exit(0);
2258
- }
2259
- const fromArg = getNamedArg(filteredArgs, '--from');
2260
- const toArg = getNamedArg(filteredArgs, '--to');
2261
- if (!fromArg || !toArg) {
2262
- console.error('Error: --from and --to are required');
2263
- console.error('Usage: eventmodeler create flow --from <source> --to <target>');
2264
- console.error('Run "eventmodeler create flow --help" for more information.');
2265
- process.exit(1);
2266
- }
2267
- await api.createFlow(modelId, fromArg, toArg);
2268
- console.log(`Created flow from "${fromArg}" to "${toArg}"`);
2269
- break;
2270
- }
2271
- default:
2272
- console.error(`Unknown create target: ${subcommand}`);
2273
- console.error('Valid targets: state-change-slice, automation-slice, state-view-slice, flow');
2274
- console.error('Run "eventmodeler create --help" for more information.');
2275
- process.exit(1);
2276
- }
2277
- break;
2278
- case 'codegen':
2279
- if (helpRequested && !subcommand) {
2280
- console.log(`
2281
- eventmodeler codegen - Generate code-ready output
2282
-
2283
- USAGE:
2284
- eventmodeler codegen <type> [options]
2285
-
2286
- TYPES:
2287
- slice Generate comprehensive JSON for a slice
2288
- events Generate deduplicated events for a chapter or entire model
2289
-
2290
- Run "eventmodeler codegen <type> --help" for detailed help.
2291
- `);
2292
- process.exit(0);
2293
- }
2294
- switch (subcommand) {
2295
- case 'slice': {
2296
- if (helpRequested) {
2297
- console.log(`
2298
- eventmodeler codegen slice - Generate code-ready JSON for a slice
2299
-
2300
- USAGE:
2301
- eventmodeler codegen slice <name>
2302
-
2303
- ARGUMENTS:
2304
- <name> Slice name
2305
-
2306
- OUTPUT:
2307
- Comprehensive JSON including:
2308
- - Slice metadata (name, type, chapter, aggregate)
2309
- - All components with full field definitions
2310
- - Fields include: name, type, isList, isOptional, isGenerated
2311
- - Nested subfields for Custom types (all flags preserved)
2312
- - Field mappings between components
2313
- - Scenarios (Given-When-Then specifications)
2314
- - Dependencies (inbound/outbound flows)
2315
-
2316
- This output is designed for code generation tools and includes
2317
- all information needed to generate implementation code.
2318
-
2319
- EXAMPLES:
2320
- eventmodeler codegen slice "Place Order"
2321
- eventmodeler codegen slice PlaceOrder > slice.json
2322
- `);
2323
- process.exit(0);
2324
- }
2325
- const sliceName = target;
2326
- if (!sliceName) {
2327
- console.error('Error: slice name is required');
2328
- console.error('Usage: eventmodeler codegen slice <name>');
2329
- console.error('Run "eventmodeler codegen slice --help" for more information.');
2330
- process.exit(1);
2331
- }
2332
- {
2333
- const result = await api.codegenSlice(modelId, sliceName);
2334
- console.log(JSON.stringify(JSON.parse(result), null, 2));
2335
- }
2336
- break;
2337
- }
2338
- case 'events': {
2339
- if (helpRequested) {
2340
- console.log(`
2341
- eventmodeler codegen events - Generate deduplicated events for scaffolding
2342
-
2343
- USAGE:
2344
- eventmodeler codegen events [--chapter <chapter-name>]
2345
- eventmodeler codegen events <chapter-name>
2346
-
2347
- ARGUMENTS:
2348
- <chapter-name> Optional chapter name (if omitted, all model events are returned)
2349
-
2350
- OUTPUT:
2351
- JSON payload including:
2352
- - chapter hierarchy metadata (when chapter-scoped)
2353
- - all relevant slices
2354
- - deduplicated events across those slices
2355
- - sourceSlices per event (where each event appears)
2356
-
2357
- This is designed for event scaffolding flows (e.g. events.kt generation).
2358
-
2359
- EXAMPLES:
2360
- eventmodeler codegen events --chapter "Register Products"
2361
- eventmodeler codegen events "Register Products"
2362
- eventmodeler codegen events > model-events.json
2363
- `);
2364
- process.exit(0);
2365
- }
2366
- const chapterName = chapterArg ?? target;
2367
- {
2368
- const output = await api.codegenEvents(modelId, chapterName);
2369
- console.log(JSON.stringify(output, null, 2));
2370
- }
2371
- break;
2372
- }
2373
- default:
2374
- console.error(`Unknown codegen target: ${subcommand}`);
2375
- console.error('Valid targets: slice, events');
2376
- console.error('Run "eventmodeler codegen --help" for more information.');
2377
- process.exit(1);
2378
- }
2379
- break;
2380
- default:
2381
- console.error(`Unknown command: ${command}`);
2382
- printHelp();
2383
- process.exit(1);
2384
- }
2385
- }
2386
- main().catch((err) => {
9
+ import { setProgram } from './lib/globals';
10
+ import { registerAuthCommands } from './commands/auth';
11
+ import { registerInitCommands } from './commands/init';
12
+ import { registerGuideCommands } from './commands/guide';
13
+ import { registerListCommands } from './commands/list';
14
+ import { registerShowCommands } from './commands/show';
15
+ import { registerSearchCommands } from './commands/search';
16
+ import { registerSummaryCommands } from './commands/summary';
17
+ import { registerMarkCommands } from './commands/mark';
18
+ import { registerAddCommands } from './commands/add';
19
+ import { registerRemoveCommands } from './commands/remove';
20
+ import { registerRenameCommands } from './commands/rename';
21
+ import { registerMoveCommands } from './commands/move';
22
+ import { registerCreateCommands } from './commands/create';
23
+ import { registerUpdateCommands } from './commands/update';
24
+ import { registerMapCommands } from './commands/map';
25
+ import { registerDesignCommands } from './commands/design';
26
+ import { registerSetCommands } from './commands/set';
27
+ import { registerLoopCommands } from './commands/loop';
28
+ const program = new Command()
29
+ .name('eventmodeler')
30
+ .version(packageJson.version)
31
+ .description('CLI tool for interacting with Event Model files')
32
+ .option('--id <uuid>', 'Skip name resolution, use UUID directly');
33
+ setProgram(program);
34
+ // Register all commands
35
+ registerAuthCommands(program);
36
+ registerInitCommands(program);
37
+ registerGuideCommands(program);
38
+ registerListCommands(program);
39
+ registerShowCommands(program);
40
+ registerSearchCommands(program);
41
+ registerSummaryCommands(program);
42
+ registerMarkCommands(program);
43
+ registerAddCommands(program);
44
+ registerRemoveCommands(program);
45
+ registerRenameCommands(program);
46
+ registerMoveCommands(program);
47
+ registerCreateCommands(program);
48
+ registerUpdateCommands(program);
49
+ registerMapCommands(program);
50
+ registerDesignCommands(program);
51
+ registerSetCommands(program);
52
+ registerLoopCommands(program);
53
+ program.parseAsync(process.argv).catch((err) => {
2387
54
  console.error('Error:', err.message);
2388
55
  process.exit(1);
2389
56
  });