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.
- package/dist/index.js +7133 -34
- package/package.json +5 -4
- package/dist/api/client-config.js +0 -10
- package/dist/api/generated/client/client.gen.js +0 -235
- package/dist/api/generated/client/index.js +0 -6
- package/dist/api/generated/client/types.gen.js +0 -2
- package/dist/api/generated/client/utils.gen.js +0 -228
- package/dist/api/generated/client.gen.js +0 -4
- package/dist/api/generated/core/auth.gen.js +0 -14
- package/dist/api/generated/core/bodySerializer.gen.js +0 -57
- package/dist/api/generated/core/params.gen.js +0 -100
- package/dist/api/generated/core/pathSerializer.gen.js +0 -106
- package/dist/api/generated/core/queryKeySerializer.gen.js +0 -92
- package/dist/api/generated/core/serverSentEvents.gen.js +0 -133
- package/dist/api/generated/core/types.gen.js +0 -2
- package/dist/api/generated/core/utils.gen.js +0 -87
- package/dist/api/generated/index.js +0 -2
- package/dist/api/generated/sdk.gen.js +0 -4222
- package/dist/api/generated/types.gen.js +0 -2
- package/dist/api/generated/zod.gen.js +0 -7217
- package/dist/commands/add.js +0 -315
- package/dist/commands/auth.js +0 -14
- package/dist/commands/create.js +0 -192
- package/dist/commands/design.js +0 -108
- package/dist/commands/guide.js +0 -15
- package/dist/commands/init.js +0 -21
- package/dist/commands/list-schemas.js +0 -177
- package/dist/commands/list.js +0 -39
- package/dist/commands/loop.js +0 -101
- package/dist/commands/map.js +0 -40
- package/dist/commands/mark.js +0 -27
- package/dist/commands/move.js +0 -35
- package/dist/commands/remove.js +0 -170
- package/dist/commands/rename.js +0 -53
- package/dist/commands/resize.js +0 -30
- package/dist/commands/search.js +0 -14
- package/dist/commands/set.js +0 -199
- package/dist/commands/show-schemas.js +0 -259
- package/dist/commands/show.js +0 -56
- package/dist/commands/summary.js +0 -13
- package/dist/commands/update.js +0 -240
- package/dist/lib/auth.js +0 -331
- package/dist/lib/config.js +0 -80
- package/dist/lib/excalidraw-schema.js +0 -66
- package/dist/lib/globals.js +0 -8
- package/dist/lib/model.js +0 -11
- package/dist/lib/project-config.js +0 -103
- package/dist/lib/resolve.js +0 -59
- package/dist/lib/scenario.js +0 -15
- package/dist/slices/add-scenario/index.js +0 -103
- package/dist/slices/guide/guides/codegen.js +0 -339
- package/dist/slices/guide/guides/connect-slices.js +0 -202
- package/dist/slices/guide/guides/create-slices.js +0 -273
- package/dist/slices/guide/guides/explore.js +0 -238
- package/dist/slices/guide/guides/information-flow.js +0 -304
- package/dist/slices/guide/guides/scenarios.js +0 -214
- package/dist/slices/guide/index.js +0 -40
- package/dist/slices/help/index.js +0 -96
- package/dist/slices/help/topics/build-codegen.js +0 -109
- package/dist/slices/help/topics/build-slice.js +0 -147
- package/dist/slices/help/topics/check-completeness.js +0 -57
- package/dist/slices/help/topics/connect-slices.js +0 -99
- package/dist/slices/help/topics/explore-model.js +0 -112
- package/dist/slices/help/topics/json-reference.js +0 -188
- package/dist/slices/help/topics/linked-copies.js +0 -89
- package/dist/slices/help/topics/manipulate-canvas.js +0 -150
- package/dist/slices/help/topics/write-scenarios.js +0 -162
- package/dist/slices/init/index.js +0 -86
- package/dist/slices/init/loop.js +0 -60
- package/dist/slices/login/index.js +0 -20
- package/dist/slices/logout/index.js +0 -14
- package/dist/slices/open-app/index.js +0 -36
- 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
|
-
}
|