eventmodeler 0.6.0 → 0.6.2

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 (73) hide show
  1. package/dist/index.js +7133 -34
  2. package/package.json +5 -4
  3. package/dist/api/client-config.js +0 -10
  4. package/dist/api/generated/client/client.gen.js +0 -235
  5. package/dist/api/generated/client/index.js +0 -6
  6. package/dist/api/generated/client/types.gen.js +0 -2
  7. package/dist/api/generated/client/utils.gen.js +0 -228
  8. package/dist/api/generated/client.gen.js +0 -4
  9. package/dist/api/generated/core/auth.gen.js +0 -14
  10. package/dist/api/generated/core/bodySerializer.gen.js +0 -57
  11. package/dist/api/generated/core/params.gen.js +0 -100
  12. package/dist/api/generated/core/pathSerializer.gen.js +0 -106
  13. package/dist/api/generated/core/queryKeySerializer.gen.js +0 -92
  14. package/dist/api/generated/core/serverSentEvents.gen.js +0 -133
  15. package/dist/api/generated/core/types.gen.js +0 -2
  16. package/dist/api/generated/core/utils.gen.js +0 -87
  17. package/dist/api/generated/index.js +0 -2
  18. package/dist/api/generated/sdk.gen.js +0 -4222
  19. package/dist/api/generated/types.gen.js +0 -2
  20. package/dist/api/generated/zod.gen.js +0 -7217
  21. package/dist/commands/add.js +0 -315
  22. package/dist/commands/auth.js +0 -14
  23. package/dist/commands/create.js +0 -192
  24. package/dist/commands/design.js +0 -108
  25. package/dist/commands/guide.js +0 -15
  26. package/dist/commands/init.js +0 -21
  27. package/dist/commands/list-schemas.js +0 -177
  28. package/dist/commands/list.js +0 -39
  29. package/dist/commands/loop.js +0 -101
  30. package/dist/commands/map.js +0 -40
  31. package/dist/commands/mark.js +0 -27
  32. package/dist/commands/move.js +0 -35
  33. package/dist/commands/remove.js +0 -170
  34. package/dist/commands/rename.js +0 -53
  35. package/dist/commands/resize.js +0 -30
  36. package/dist/commands/search.js +0 -14
  37. package/dist/commands/set.js +0 -199
  38. package/dist/commands/show-schemas.js +0 -259
  39. package/dist/commands/show.js +0 -56
  40. package/dist/commands/summary.js +0 -13
  41. package/dist/commands/update.js +0 -240
  42. package/dist/lib/auth.js +0 -331
  43. package/dist/lib/config.js +0 -80
  44. package/dist/lib/excalidraw-schema.js +0 -66
  45. package/dist/lib/globals.js +0 -8
  46. package/dist/lib/model.js +0 -11
  47. package/dist/lib/project-config.js +0 -103
  48. package/dist/lib/resolve.js +0 -59
  49. package/dist/lib/scenario.js +0 -15
  50. package/dist/slices/add-scenario/index.js +0 -103
  51. package/dist/slices/guide/guides/codegen.js +0 -339
  52. package/dist/slices/guide/guides/connect-slices.js +0 -202
  53. package/dist/slices/guide/guides/create-slices.js +0 -273
  54. package/dist/slices/guide/guides/explore.js +0 -238
  55. package/dist/slices/guide/guides/information-flow.js +0 -304
  56. package/dist/slices/guide/guides/scenarios.js +0 -214
  57. package/dist/slices/guide/index.js +0 -40
  58. package/dist/slices/help/index.js +0 -96
  59. package/dist/slices/help/topics/build-codegen.js +0 -109
  60. package/dist/slices/help/topics/build-slice.js +0 -147
  61. package/dist/slices/help/topics/check-completeness.js +0 -57
  62. package/dist/slices/help/topics/connect-slices.js +0 -99
  63. package/dist/slices/help/topics/explore-model.js +0 -112
  64. package/dist/slices/help/topics/json-reference.js +0 -188
  65. package/dist/slices/help/topics/linked-copies.js +0 -89
  66. package/dist/slices/help/topics/manipulate-canvas.js +0 -150
  67. package/dist/slices/help/topics/write-scenarios.js +0 -162
  68. package/dist/slices/init/index.js +0 -86
  69. package/dist/slices/init/loop.js +0 -60
  70. package/dist/slices/login/index.js +0 -20
  71. package/dist/slices/logout/index.js +0 -14
  72. package/dist/slices/open-app/index.js +0 -36
  73. package/dist/slices/whoami/index.js +0 -19
@@ -1,188 +0,0 @@
1
- export const meta = {
2
- name: 'json-reference',
3
- keywords: ['json', 'shape', 'schema', 'reference', 'format', 'payload', 'body', 'all', 'commands', 'cheatsheet', 'syntax'],
4
- description: 'All JSON shapes for every CLI command in one place',
5
- };
6
- export const content = `
7
- # JSON Reference
8
-
9
- WHEN TO USE: You need the exact JSON shape for a CLI command.
10
-
11
- ## create slice '<json>'
12
-
13
- eventmodeler create slice '<json>'
14
-
15
- {
16
- "sliceName": "Name",
17
- "elements": [
18
- {
19
- "id": "<uuid>",
20
- "type": "screen | command | event | readmodel | processor | external-event",
21
- "name": "ElementName",
22
- "fields": [
23
- { "name": "fieldName", "type": "String" }
24
- ]
25
- }
26
- ],
27
- "flows": [
28
- { "id": "<uuid>", "from": "SourceName", "to": "TargetName" }
29
- ]
30
- }
31
-
32
- ## add field [elementName] '<json>'
33
-
34
- eventmodeler add field "ElementName" '{"name": "fieldName", "type": "String"}'
35
- eventmodeler --id <uuid> add field '{"name": "fieldName", "type": "String"}'
36
-
37
- FIELD JSON: { "name": "fieldName", "type": "String" }
38
-
39
- Field types: UUID, String, Int, Long, Double, Decimal, Boolean, Date, DateTime, Custom
40
-
41
- Optional attributes (add to same JSON object):
42
- "isOptional": true
43
- "isGenerated": true
44
- "isList": true
45
- "isUserInput": true (screens only)
46
-
47
- Custom type with subfields:
48
- {
49
- "name": "address",
50
- "type": "Custom",
51
- "subfields": [
52
- { "name": "street", "type": "String" },
53
- { "name": "city", "type": "String" }
54
- ]
55
- }
56
-
57
- List of custom objects:
58
- {
59
- "name": "lineItems",
60
- "type": "Custom",
61
- "isList": true,
62
- "subfields": [
63
- { "name": "productId", "type": "UUID" },
64
- { "name": "quantity", "type": "Int" }
65
- ]
66
- }
67
-
68
- ## add subfield [elementName] '<json>' --field <parentFieldName>
69
-
70
- eventmodeler add subfield "ElementName" '{"name": "zip", "type": "String"}' --field "address"
71
-
72
- SUBFIELD JSON: { "name": "subfieldName", "type": "String" }
73
-
74
- ## update field [elementName] --field <name> [--name <new>] [--type <new>] [--optional true|false] [--generated true|false] [--list true|false] [--user-input true|false]
75
-
76
- eventmodeler update field "OrderPlaced" --field "total" --type Decimal
77
- eventmodeler update field "OrderPlaced" --field "promoCode" --optional true
78
- eventmodeler update field "Checkout" --field "email" --user-input true
79
-
80
- No JSON — uses flags directly.
81
-
82
- ## update subfield [elementName] --subfield <id> [--name <new>] [--type <new>]
83
-
84
- eventmodeler update subfield "OrderPlaced" --subfield <subfieldId> --name "zipCode"
85
-
86
- No JSON — uses flags directly. Subfield ID from show output.
87
-
88
- ## update reorder [elementName] --field <name> --position <n>
89
-
90
- eventmodeler update reorder "OrderPlaced" --field "orderId" --position 0
91
-
92
- ## map fields '<json>' --from <source> --to <target>
93
-
94
- eventmodeler map fields '[{"source": "orderId", "target": "orderId"}]' --from "OrderPlaced" --to "OrderSummary"
95
-
96
- MAPPINGS JSON: [
97
- { "source": "sourceFieldName", "target": "targetFieldName" }
98
- ]
99
-
100
- ## add scenario '<json>' --slice <sliceName>
101
-
102
- eventmodeler add scenario '<json>' --slice "Place Order"
103
-
104
- SCENARIO JSON:
105
- {
106
- "name": "Scenario name",
107
- "description": "Optional description",
108
- "given": [
109
- { "entryType": "event", "elementName": "EventName", "fieldValues": { "field": "value" } },
110
- { "entryType": "readmodel", "elementName": "ReadModelName", "fieldValues": { "field": "value" } }
111
- ],
112
- "when": [
113
- { "entryType": "command", "elementName": "CommandName", "fieldValues": { "field": "value" } },
114
- { "entryType": "event", "elementName": "EventName", "fieldValues": { "field": "value" } }
115
- ],
116
- "then": [
117
- { "entryType": "event", "elementName": "EventName", "fieldValues": { "field": "value" } },
118
- { "entryType": "command", "elementName": "CommandName", "fieldValues": { "field": "value" } },
119
- { "entryType": "readmodel", "elementName": "ReadModelName", "fieldValues": { "field": "value" } },
120
- { "entryType": "error", "errorType": "ErrorType", "errorMessage": "Error description" }
121
- ]
122
- }
123
-
124
- given/when/then are all optional — omit sections you don't need.
125
- Given entry types: event, readmodel
126
- When entry types: command, event
127
- Then entry types: event, command, readmodel, error
128
-
129
- fieldValues holds both scalar and list values. Pass an array for fields marked
130
- isList=true; a string otherwise:
131
- { "entryType": "command", "elementName": "PlaceBulkOrder",
132
- "fieldValues": { "customerId": "cust-001", "productIds": ["p-1", "p-2"], "tags": ["urgent"] } }
133
-
134
- ## create flow --from <source> --to <target>
135
-
136
- eventmodeler create flow --from "PlaceOrder" --to "OrderPlaced"
137
-
138
- No JSON. Valid flow pairs:
139
- screen -> command
140
- command -> event
141
- command -> external-event
142
- event -> readmodel
143
- readmodel -> screen
144
- readmodel -> processor
145
- processor -> command
146
- external-event -> processor
147
-
148
- ## create place <type> <name> --x <n> --y <n>
149
-
150
- eventmodeler create place command "PlaceOrder" --x 2040 --y 460
151
- eventmodeler create place slice "Place Order" --x 2000 --y 80
152
-
153
- No JSON. Types: command, event, readmodel, screen, processor, external-event,
154
- aggregate, actor, chapter, context, note, swimlane, slice
155
-
156
- ## create place-copy <type> [originalName] --x <n> --y <n>
157
-
158
- eventmodeler create place-copy event "OrderPlaced" --x 3000 --y 860
159
- eventmodeler --id <original-uuid> create place-copy event --x 3000 --y 860
160
-
161
- No JSON. Types: event, readmodel, screen, external-event
162
-
163
- ## The --id Flag
164
-
165
- All name-based commands accept --id <uuid> as a GLOBAL flag (before the command):
166
- eventmodeler --id <uuid> show event
167
- eventmodeler --id <uuid> add field '{"name": "f", "type": "String"}'
168
- eventmodeler --id <uuid> move event --x 100 --y 860
169
- eventmodeler --id <uuid> remove event
170
- eventmodeler --id <uuid> create place-copy event --x 3000 --y 860
171
-
172
- Essential for linked copies which share names with originals.
173
-
174
- ## Canvas Coordinates
175
-
176
- Y Bands:
177
- screen / processor: y = 120
178
- command / readmodel: y = 460
179
- event / external-event: y = 860
180
-
181
- Element dimensions are fixed by the CLI (not configurable):
182
- command / event / readmodel / external-event: 160 x 100
183
- screen: 180 x 120
184
- processor: 120 x 120
185
- slice / aggregate / actor / context / swimlane: 300 x 200
186
- chapter: 800 x 1200, note: 200 x 150
187
- X spacing between stickies: 200
188
- `;
@@ -1,89 +0,0 @@
1
- export const meta = {
2
- name: 'linked-copies',
3
- keywords: ['linked', 'copy', 'cross-slice', 'duplicate', 'reuse', 'shared', 'proxy', 'event', 'readmodel', 'screen', 'external-event', 'place-copy', 'move-copy', 'remove-copy', 'original'],
4
- description: 'Create and work with cross-slice linked copies of elements',
5
- };
6
- export const content = `
7
- # Linked Copies
8
-
9
- WHEN TO USE: You need the same element to appear in multiple slices (e.g., an event produced in one slice consumed in another).
10
-
11
- ## What are Linked Copies?
12
-
13
- A linked copy is a visual reference to an element that lives in another slice. The copy shares the original's name and fields but has its own UUID and position on the canvas. Changes to the original's fields propagate to all copies.
14
-
15
- LINKABLE TYPES:
16
- event, readmodel, screen, external-event
17
-
18
- NON-LINKABLE (always unique to their slice):
19
- command, processor
20
-
21
- ## Task: Create a linked copy
22
-
23
- COMMAND:
24
- eventmodeler create place-copy <type> [originalName] --x <n> --y <n> [--width <n>] [--height <n>]
25
-
26
- EXAMPLES:
27
- eventmodeler create place-copy event "OrderPlaced" --x 3000 --y 860
28
- eventmodeler create place-copy readmodel "OrderSummary" --x 3000 --y 460
29
- eventmodeler create place-copy event --id <original-uuid> --x 3000 --y 860
30
-
31
- NOTES:
32
- - The copy gets a new UUID but references the original
33
- - Place the copy in the correct Y band for its type (see "help manipulate-canvas")
34
- - Use --id when multiple elements share the same name
35
-
36
- ## Task: Move a linked copy
37
-
38
- COMMAND:
39
- eventmodeler create move-copy <type> [name] --x <n> --y <n>
40
-
41
- EXAMPLES:
42
- eventmodeler create move-copy event --id <copy-uuid> --x 3200 --y 860
43
-
44
- NOTES:
45
- - Use --id to target the specific copy (copies share names with their original)
46
-
47
- ## Task: Remove a linked copy
48
-
49
- COMMAND:
50
- eventmodeler create remove-copy <type> [name]
51
-
52
- EXAMPLES:
53
- eventmodeler create remove-copy event --id <copy-uuid>
54
-
55
- NOTES:
56
- - Removing a copy does NOT remove the original
57
- - Use --id — name resolution may hit the original instead of the copy
58
-
59
- ## Task: Identify copies in output
60
-
61
- The list and show commands distinguish copies from originals:
62
-
63
- COMMAND:
64
- eventmodeler list events (shows isLinkedCopy: true, originalId for copies)
65
- eventmodeler show slice "<name>" (copies marked with linkedCopy: true, originalId, originalSlice)
66
-
67
- ## Common Pattern: Event Produced in Slice A, Consumed in Slice B
68
-
69
- 1. Slice A produces "OrderPlaced" event (via create slice or create place)
70
- 2. In Slice B, create a linked copy of the event:
71
- eventmodeler create place-copy event "OrderPlaced" --x 3000 --y 860
72
- 3. Find the copy's UUID from list output:
73
- eventmodeler list events
74
- 4. Create a flow from the copy to the consuming readmodel:
75
- eventmodeler create flow --from "OrderPlaced" --to "OrderHistory"
76
- (or use --id <copy-uuid> if ambiguous:)
77
- eventmodeler --id <copy-uuid> create flow --from "OrderPlaced" --to "OrderHistory"
78
- 5. Map fields on the flow:
79
- eventmodeler map fields '[{"source": "orderId", "target": "orderId"}]' --from "OrderPlaced" --to "OrderHistory"
80
-
81
- ## Why Linked Copies Exist
82
-
83
- In event modeling, the same event often feeds multiple read models across different slices. Instead of duplicating the event definition, you create linked copies:
84
- - The original event stays in its source slice
85
- - Copies appear in consuming slices as visual references
86
- - All copies share the same name and fields
87
- - Each copy can be independently positioned on the canvas
88
- - Flows connect from copies to local readmodels
89
- `;
@@ -1,150 +0,0 @@
1
- export const meta = {
2
- name: 'manipulate-canvas',
3
- keywords: ['canvas', 'place', 'move', 'remove', 'position', 'layout', 'coordinate', 'x', 'y', 'band', 'spacing', 'slice', 'aggregate', 'actor', 'chapter', 'context', 'swimlane', 'note', 'overlap', 'create'],
4
- description: 'Place, move, and remove elements on the visual canvas',
5
- };
6
- export const content = `
7
- # Manipulating the Canvas
8
-
9
- WHEN TO USE: You need to position, move, or remove elements on the visual canvas.
10
-
11
- ## Canvas Layout Constants
12
-
13
- ELEMENT DIMENSIONS (fixed — not configurable from the CLI):
14
- command / event / readmodel / external-event: 160 x 100
15
- screen: 180 x 120
16
- processor: 120 x 120
17
- slice / aggregate / actor / context / swimlane: 300 x 200
18
- chapter: 800 x 1200
19
- note: 200 x 150
20
-
21
- PADDING = 40
22
- X_SPACING = 200 (sticky width + padding)
23
-
24
- Y BANDS (vertical lanes — where element types live):
25
- screen / processor: y = 120
26
- command / readmodel: y = 460
27
- event / external-event: y = 860
28
-
29
- ## Placing Elements in a Slice
30
-
31
- A typical slice at x=1000 would place elements like this:
32
-
33
- Screen: x=1040, y=120 (PADDING inside slice)
34
- Command: x=1040, y=460
35
- Event: x=1240, y=860 (offset by X_SPACING for second column)
36
- ReadModel: x=1440, y=460
37
-
38
- Pattern: elements flow left-to-right within the slice, staying in their Y band.
39
- Multiple elements of the same type space out by X_SPACING.
40
-
41
- EXAMPLE (placing a state-change slice at x=2000):
42
- Slice container: x=2000, y=80
43
- Screen "OrderForm": x=2040, y=120 (PADDING offset from slice x)
44
- Command "PlaceOrder": x=2040, y=460
45
- Event "OrderPlaced": x=2040, y=860
46
- ReadModel "OrderView": x=2240, y=460 (next column)
47
-
48
- ## Task: Place a new element on the canvas
49
-
50
- COMMAND:
51
- eventmodeler create place <type> <name> --x <n> --y <n>
52
-
53
- TYPES: command, event, readmodel, screen, processor, external-event,
54
- aggregate, actor, chapter, context, note, swimlane, slice
55
-
56
- EXAMPLES:
57
- eventmodeler create place command "PlaceOrder" --x 2040 --y 460
58
- eventmodeler create place event "OrderPlaced" --x 2040 --y 860
59
- eventmodeler create place screen "OrderForm" --x 2040 --y 120
60
- eventmodeler create place readmodel "OrderView" --x 2240 --y 460
61
- eventmodeler create place slice "Place Order" --x 2000 --y 80
62
- eventmodeler create place aggregate "Order" --x 2000 --y 780 --id-field-name orderId --id-field-type UUID
63
-
64
- NOTES:
65
- - All element sizes are fixed by the CLI — you cannot specify width/height
66
- - Use Y bands above to position element types correctly
67
- - Aggregate also accepts --id-field-name and --id-field-type (default: id, UUID)
68
- - Note uses "title" internally but you just pass the name as the positional arg
69
-
70
- ## Task: Move an element to a new position
71
-
72
- COMMAND:
73
- eventmodeler move <type> [name] --x <n> --y <n>
74
-
75
- EXAMPLES:
76
- eventmodeler move command "PlaceOrder" --x 2200 --y 460
77
- eventmodeler move slice "Place Order" --x 3000 --y 80
78
- eventmodeler move event --id <uuid> --x 2400 --y 860
79
-
80
- NOTES:
81
- - Sets new absolute position (not relative)
82
- - Keep stickies in their correct Y band when moving horizontally
83
- - Use --id to target specific element when names are ambiguous
84
-
85
- ## Task: Remove an element
86
-
87
- COMMAND:
88
- eventmodeler remove <type> [name]
89
-
90
- EXAMPLES:
91
- eventmodeler remove event "OrderPlaced"
92
- eventmodeler remove slice "Place Order"
93
- eventmodeler remove command --id <uuid>
94
-
95
- NOTES:
96
- - Removing an element also removes its flows
97
- - Use --id to target a specific element when names collide
98
- - All element types supported: command, event, readmodel, screen, processor,
99
- external-event, slice, aggregate, actor, chapter, context, note, swimlane
100
-
101
- ## Task: Rename an element
102
-
103
- COMMAND:
104
- eventmodeler rename <type> <currentName> <newName>
105
-
106
- EXAMPLES:
107
- eventmodeler rename event "OrderPlaced" "OrderCreated"
108
- eventmodeler rename slice "Place Order" "Create Order"
109
-
110
- ## Reading the Canvas (show output includes full bounding boxes)
111
-
112
- Every element in show output includes x, y, width, height:
113
-
114
- eventmodeler show slice "Place Order"
115
- → {
116
- "x": 2000, "y": 80, "width": 300, "height": 200,
117
- "elements": [
118
- { "name": "PlaceOrder", "elementType": "command",
119
- "x": 2040, "y": 460, "width": 160, "height": 100, ... }
120
- ]
121
- }
122
-
123
- Use these bounding boxes to:
124
- - Find the next available x position (rightmost element x + width + PADDING)
125
- - Check if a new element would overlap existing ones
126
- - Verify containment (an element is "inside" a container if its center is within the container bounds)
127
-
128
- CONTAINMENT RULE:
129
- An element is considered inside a container when its CENTER POINT is within the container's bounds:
130
- centerX = element.x + element.width / 2
131
- centerY = element.y + element.height / 2
132
- The center must be between container.x..container.x+container.width
133
- and container.y..container.y+container.height.
134
-
135
- This means an element can have its top-left corner inside a container but NOT be contained
136
- if most of its body extends outside. Always check center-point, not top-left.
137
-
138
- ## Avoiding Overlaps
139
-
140
- RULES:
141
- - Stickies in the same Y band must be >= X_SPACING (200px) apart horizontally
142
- - Containers must not overlap other containers of the same type
143
- - Before placing, check existing positions:
144
- eventmodeler show slice "<name>" (shows x, y, width, height of all elements)
145
- eventmodeler list slices (shows x, y, width, height of all slices)
146
- - Place new elements at the next available x offset
147
-
148
- EXAMPLE (adding a second event to a slice that already has one at x=2040):
149
- eventmodeler create place event "OrderCancelled" --x 2240 --y 860
150
- `;
@@ -1,162 +0,0 @@
1
- export const meta = {
2
- name: 'write-scenarios',
3
- keywords: ['scenario', 'test', 'given', 'when', 'then', 'GWT', 'behavior', 'error', 'assertion', 'add', 'remove', 'entry', 'example', 'field', 'value', 'description', 'reorder', 'position'],
4
- description: 'Add Given-When-Then scenarios to slices',
5
- };
6
- export const content = `
7
- # Writing Scenarios
8
-
9
- WHEN TO USE: You need to specify slice behavior as Given-When-Then test cases.
10
-
11
- ## Task: Add a full scenario to a slice (compound command)
12
-
13
- COMMAND:
14
- eventmodeler add scenario '<json>' --slice <sliceName>
15
-
16
- EXAMPLE (happy path — state-change slice):
17
- eventmodeler add scenario '{
18
- "name": "Successfully place order",
19
- "given": [
20
- {"entryType": "event", "elementName": "CustomerRegistered", "fieldValues": {"customerId": "cust-001"}}
21
- ],
22
- "when": [
23
- {"entryType": "command", "elementName": "PlaceOrder", "fieldValues": {"customerId": "cust-001", "productId": "prod-42"}}
24
- ],
25
- "then": [
26
- {"entryType": "event", "elementName": "OrderPlaced", "fieldValues": {"orderId": "ord-001", "customerId": "cust-001"}}
27
- ]
28
- }' --slice "Place Order"
29
-
30
- EXAMPLE (error case):
31
- eventmodeler add scenario '{
32
- "name": "Reject order with no items",
33
- "when": [
34
- {"entryType": "command", "elementName": "PlaceOrder", "fieldValues": {"customerId": "cust-001"}}
35
- ],
36
- "then": [
37
- {"entryType": "error", "errorType": "ValidationError", "errorMessage": "Order must contain at least one item"}
38
- ]
39
- }' --slice "Place Order"
40
-
41
- EXAMPLE (readmodel assertion in then):
42
- eventmodeler add scenario '{
43
- "name": "Order appears in summary",
44
- "given": [
45
- {"entryType": "event", "elementName": "OrderPlaced", "fieldValues": {"orderId": "ord-001", "customerId": "cust-001"}}
46
- ],
47
- "then": [
48
- {"entryType": "readmodel", "elementName": "OrderSummary", "fieldValues": {"orderId": "ord-001", "status": "pending"}}
49
- ]
50
- }' --slice "View Orders"
51
-
52
- SCENARIO JSON:
53
- {
54
- "name": "Scenario name",
55
- "description": "Optional description text",
56
- "given": [ <entries> ],
57
- "when": [ <entries> ],
58
- "then": [ <entries> ]
59
- }
60
-
61
- All sections (given/when/then) are optional — omit what you don't need.
62
- Scenario is auto-positioned below its slice.
63
-
64
- ENTRY TYPES BY SECTION:
65
- given: event, readmodel
66
- when: command, event
67
- then: event, command, readmodel, error
68
-
69
- ENTRY SHAPES:
70
- {"entryType": "event", "elementName": "EventName", "fieldValues": {"field": "value", "tags": ["a", "b"]}}
71
- {"entryType": "command", "elementName": "CommandName", "fieldValues": {"field": "value", "tags": ["a", "b"]}}
72
- {"entryType": "readmodel", "elementName": "ReadModelName", "fieldValues": {"field": "value", "tags": ["a", "b"]}}
73
- {"entryType": "error", "errorType": "ErrorType", "errorMessage": "Description"}
74
-
75
- fieldValues holds both scalar and list values. Pass an array for fields marked
76
- as list (isList=true); a string otherwise. Setting a list value replaces the
77
- entire list. The backend rejects array vs scalar mismatches against isList.
78
-
79
- NOTES:
80
- - "given" = preconditions (events that already happened, readmodel state)
81
- - "when" = trigger (usually a command, sometimes an event for automation)
82
- - "then" = expected outcome (produced events, readmodel assertions, or errors)
83
- - Error entries have no elementName — just errorType and errorMessage
84
- - Use realistic sample data, not placeholders like "string" or "value"
85
-
86
- ## Task: Add a single entry to an existing scenario
87
-
88
- COMMAND:
89
- eventmodeler add entry --scenario <name> --section given|when|then --type <entryType> --element <elementName>
90
-
91
- EXAMPLES:
92
- eventmodeler add entry --scenario "Successfully place order" --section given --type event --element "CustomerRegistered"
93
- eventmodeler add entry --scenario "Reject empty order" --section then --type error --error-type "ValidationError" --error-message "No items"
94
-
95
- NOTES:
96
- - --element not needed for --type error (use --error-type and --error-message instead)
97
- - --position <n> optional (appends to end by default)
98
-
99
- ## Task: Set a field example value on a scenario entry (scalar or list)
100
-
101
- COMMAND:
102
- Scalar: eventmodeler set example --scenario <name> --entry <entryId> --type <entryType> --field <fieldName> --value <val>
103
- List: eventmodeler set example --scenario <name> --entry <entryId> --type <entryType> --field <fieldName> --value <v> --value <v> ...
104
- eventmodeler set example --scenario <name> --entry <entryId> --type <entryType> --field <fieldName> --values "a,b,c"
105
-
106
- EXAMPLES:
107
- eventmodeler set example --scenario "Successfully place order" --entry <entryId> --type event --field "orderId" --value "ord-001"
108
- eventmodeler set example --scenario "Place bulk order" --entry <entryId> --type command --field "productIds" --value "p-1" --value "p-2"
109
- eventmodeler set example --scenario "Place bulk order" --entry <entryId> --type command --field "tags" --values "urgent,paid"
110
-
111
- NOTES:
112
- - Entry ID comes from "show slice" or "show scenario" output (entryId field)
113
- - --type must match the entry's element type: event, command, or readmodel
114
- - List mode is auto-detected when --values is given or --value is repeated
115
- - List mode replaces the entire list (set-whole-list semantics) and requires the field to be marked isList=true
116
-
117
- ## Task: Remove a field example value
118
-
119
- COMMAND:
120
- eventmodeler remove example --scenario <name> --entry <entryId> --type <entryType> --field <fieldName>
121
-
122
- ## Task: Remove an entry from a scenario
123
-
124
- COMMAND:
125
- eventmodeler remove entry --scenario <name> --section given|when|then --entry <entryId>
126
-
127
- ## Task: Reorder an entry within its section
128
-
129
- COMMAND:
130
- eventmodeler set position --scenario <name> --section given|when|then --entry <entryId> --position <n>
131
-
132
- ## Task: Set scenario description
133
-
134
- COMMAND:
135
- eventmodeler set description --scenario <name> --text "Description text"
136
-
137
- ## Task: Remove a scenario
138
-
139
- COMMAND:
140
- eventmodeler remove scenario [name]
141
-
142
- ## Task: Rename a scenario
143
-
144
- COMMAND:
145
- eventmodeler rename scenario "Old Name" "New Name"
146
-
147
- ## Scenario Patterns by Slice Type
148
-
149
- STATE-CHANGE (Screen -> Command -> Event):
150
- given: events that establish preconditions
151
- when: the command being tested
152
- then: expected event(s) or error
153
-
154
- AUTOMATION (ReadModel -> Processor -> Command -> Event):
155
- given: events that build up the processor's readmodel
156
- when: (often empty — the processor triggers automatically)
157
- then: command the processor should dispatch, or events produced
158
-
159
- STATE-VIEW (ReadModel fed by events):
160
- given: events that project into the readmodel
161
- then: readmodel assertion showing expected state
162
- `;
@@ -1,86 +0,0 @@
1
- import * as readline from 'node:readline';
2
- import { isAuthenticated } from '../../lib/config';
3
- import { listModels } from '../../api/generated/sdk.gen';
4
- import { saveProjectConfig, getProjectRoot, isInProject } from '../../lib/project-config';
5
- /**
6
- * Interactive init command to set up a project.
7
- * Connects the current directory to an event model.
8
- */
9
- export async function init() {
10
- if (isInProject()) {
11
- console.log('This project is already initialized.');
12
- console.log('To reconfigure, delete .eventmodeler.json and run init again.');
13
- return;
14
- }
15
- const projectRoot = getProjectRoot();
16
- console.log(`Initializing event model project in: ${projectRoot}\n`);
17
- if (!isAuthenticated()) {
18
- console.log('You need to be logged in first.');
19
- console.log('Run "eventmodeler login" first, then try init again.');
20
- return;
21
- }
22
- const rl = readline.createInterface({
23
- input: process.stdin,
24
- output: process.stdout,
25
- });
26
- const question = (prompt) => {
27
- return new Promise((resolve) => {
28
- rl.question(prompt, (answer) => {
29
- resolve(answer.trim());
30
- });
31
- });
32
- };
33
- try {
34
- console.log('Fetching your event models...\n');
35
- const result = await listModels();
36
- if (result.error || !result.data) {
37
- console.log('Failed to fetch models. Are you logged in?');
38
- rl.close();
39
- return;
40
- }
41
- const models = result.data.items;
42
- if (models.length === 0) {
43
- console.log('You don\'t have any event models yet.');
44
- console.log('Create one at https://eventmodeler.app first, then run init again.');
45
- rl.close();
46
- return;
47
- }
48
- console.log('Your event models:\n');
49
- models.forEach((model, index) => {
50
- console.log(` ${index + 1}. ${model.name} (${model.modelId})`);
51
- });
52
- console.log(` ${models.length + 1}. Create a new model\n`);
53
- const modelChoice = await question(`Select a model (1-${models.length + 1}): `);
54
- const modelIndex = parseInt(modelChoice, 10) - 1;
55
- let selectedModel;
56
- if (modelIndex === models.length) {
57
- console.log('\nTo create a new model, visit https://eventmodeler.app');
58
- console.log('After creating it, run init again to link it to this project.');
59
- rl.close();
60
- return;
61
- }
62
- else if (modelIndex >= 0 && modelIndex < models.length) {
63
- selectedModel = models[modelIndex];
64
- }
65
- else {
66
- console.log('\nInvalid choice. Please run init again.');
67
- rl.close();
68
- return;
69
- }
70
- const config = {
71
- type: 'cloud',
72
- modelId: selectedModel.modelId,
73
- modelName: selectedModel.name,
74
- };
75
- const configPath = saveProjectConfig(config, projectRoot);
76
- console.log(`\nProject initialized successfully!`);
77
- console.log(`Config saved to: ${configPath}`);
78
- console.log(`\nLinked to model: ${selectedModel.name}`);
79
- console.log('\nYou can now use eventmodeler commands in this directory.');
80
- rl.close();
81
- }
82
- catch (err) {
83
- rl.close();
84
- throw err;
85
- }
86
- }