eventmodeler 0.4.6 → 0.5.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.
@@ -0,0 +1,251 @@
1
+ export const meta = {
2
+ name: 'explore',
3
+ description: 'Navigate and query an event model: list, show, search, completeness',
4
+ };
5
+ export const content = `
6
+ # Exploring Event Models with the CLI
7
+
8
+ The \`eventmodeler\` CLI lets you query and explore event models linked to your project.
9
+
10
+ ## Getting an Overview
11
+
12
+ **Start here** to understand the model:
13
+
14
+ \`\`\`bash
15
+ eventmodeler summary
16
+ \`\`\`
17
+ Shows statistics: total slices, events, commands, read models, etc.
18
+
19
+ \`\`\`bash
20
+ eventmodeler list slices
21
+ \`\`\`
22
+ Lists all slices with their status (created, in-progress, blocked, done). Slices represent vertical features.
23
+
24
+ \`\`\`bash
25
+ eventmodeler list slices --chapter "<name>"
26
+ \`\`\`
27
+ Lists only slices within a specific chapter.
28
+
29
+ \`\`\`bash
30
+ eventmodeler list chapters
31
+ \`\`\`
32
+ Lists chapters - timeline sections that group slices.
33
+
34
+ ## Listing Elements
35
+
36
+ \`\`\`bash
37
+ eventmodeler list events # All events in the model
38
+ eventmodeler list commands # All commands in the model
39
+ eventmodeler list readmodels # All read models
40
+ eventmodeler list screens # All screens
41
+ eventmodeler list processors # All processors
42
+ eventmodeler list scenarios # All scenarios
43
+ eventmodeler list aggregates # All aggregates (event groupings)
44
+ eventmodeler list actors # All actors (user/system roles)
45
+ \`\`\`
46
+
47
+ All \`list\` commands support \`--format xml|json\`.
48
+
49
+ ## Searching
50
+
51
+ \`\`\`bash
52
+ eventmodeler search "<term>"
53
+ \`\`\`
54
+ Searches across all entity names: slices, events, commands, read models, aggregates, and actors.
55
+
56
+ ## Drilling Into Details
57
+
58
+ ### Show a Slice
59
+ \`\`\`bash
60
+ eventmodeler show slice "<name>"
61
+ \`\`\`
62
+ Returns XML with:
63
+ - All components in the slice (screens, commands, events, read-models, processors)
64
+ - **Inline flow annotations** on each component showing \`<flows-from>\` and \`<flows-to>\` connections
65
+ - Fields on each component with types and attributes
66
+ - Information flow (which components connect to which)
67
+ - **Inbound flows**: External elements flowing INTO this slice (with field mappings)
68
+ - **Outbound flows**: Elements in this slice flowing OUT to other slices (with field mappings)
69
+ - Scenarios (Given-When-Then test cases)
70
+
71
+ The inbound/outbound flows show cross-slice dependencies - crucial for understanding how a slice integrates with the rest of the system.
72
+
73
+ **Scenarios are key** - they define the slice's behavior and give it context. A slice's scenarios show:
74
+ - **Given**: What events have already occurred (the starting state)
75
+ - **When**: What command is being executed with what field values
76
+ - **Then**: The expected outcome - either:
77
+ - Events that should be produced
78
+ - An error that should occur
79
+ - A read model assertion (expected state)
80
+
81
+ Example scenario in slice output:
82
+ \`\`\`xml
83
+ <scenarios>
84
+ <scenario name="Successfully place order">
85
+ <given>
86
+ <event type="CustomerRegistered">customerId: "123"</event>
87
+ </given>
88
+ <when>
89
+ <command type="PlaceOrder">customerId: "123", items: [...]</command>
90
+ </when>
91
+ <then>
92
+ <event type="OrderPlaced">orderId: "456", customerId: "123"</event>
93
+ </then>
94
+ </scenario>
95
+ <scenario name="Cannot place order without items">
96
+ <when>
97
+ <command type="PlaceOrder">customerId: "123", items: []</command>
98
+ </when>
99
+ <then>
100
+ <error type="ValidationError">Order must contain at least one item</error>
101
+ </then>
102
+ </scenario>
103
+ </scenarios>
104
+ \`\`\`
105
+
106
+ Reading scenarios helps understand:
107
+ - What preconditions the slice expects
108
+ - What inputs the command accepts
109
+ - What the happy path looks like
110
+ - What error cases are handled
111
+
112
+ ### Show an Event or Command
113
+ \`\`\`bash
114
+ eventmodeler show event "<name>"
115
+ eventmodeler show command "<name>"
116
+ \`\`\`
117
+ Returns XML with the element's fields and connections.
118
+
119
+ ### Show Read Models, Screens, and Processors
120
+ \`\`\`bash
121
+ eventmodeler show readmodel "<name>"
122
+ eventmodeler show screen "<name>"
123
+ eventmodeler show processor "<name>"
124
+ \`\`\`
125
+ Use these for detailed flow context:
126
+ - \`show readmodel\`: fields, source events, and who consumes it
127
+ - \`show screen\`: fields, source read models, and triggered commands
128
+ - \`show processor\`: fields, source read models, and triggered commands
129
+
130
+ ### Show Aggregate and Scenario
131
+ \`\`\`bash
132
+ eventmodeler show aggregate "<name>"
133
+ eventmodeler show scenario "<name>"
134
+ \`\`\`
135
+ - \`show aggregate\`: aggregate ID configuration and contained events
136
+ - \`show scenario\`: complete Given-When-Then with field values
137
+
138
+ ### Show a Chapter
139
+ \`\`\`bash
140
+ eventmodeler show chapter "<name>"
141
+ \`\`\`
142
+ Shows the chapter with:
143
+ - All slices within the chapter
144
+ - **Flow graph**: How slices connect to each other (which events flow to which read models, etc.) with field mappings
145
+ - **External dependencies**:
146
+ - Inbound: Flows from outside the chapter into slices within it
147
+ - Outbound: Flows from slices in this chapter to elements outside it
148
+
149
+ Use \`show chapter\` to understand the relationships between slices in a feature area. Use \`list slices --chapter\` for a simple list without flow details.
150
+
151
+ ### Show an Actor
152
+ \`\`\`bash
153
+ eventmodeler show actor "<name>"
154
+ \`\`\`
155
+ Shows the actor and lists all screens associated with it.
156
+
157
+ ## Managing Slice Status
158
+
159
+ Slices have a status that tracks their progress: \`created\`, \`in-progress\`, \`blocked\`, \`done\`.
160
+
161
+ \`\`\`bash
162
+ # Mark a slice as in progress
163
+ eventmodeler mark "Place Order" in-progress
164
+
165
+ # Mark a slice as done
166
+ eventmodeler mark "Place Order" done
167
+
168
+ # Mark a slice as blocked
169
+ eventmodeler mark "Place Order" blocked
170
+
171
+ # Reset to created
172
+ eventmodeler mark "Place Order" created
173
+ \`\`\`
174
+
175
+ Use \`list slices\` to see current statuses.
176
+
177
+ ## Checking Information Completeness
178
+
179
+ Information completeness tracks whether fields flow correctly between connected elements.
180
+
181
+ ### Check a Specific Element
182
+ \`\`\`bash
183
+ eventmodeler show completeness "<name>"
184
+ \`\`\`
185
+ Auto-detects the element type (command, event, read model, screen, or processor) and shows:
186
+ - Incoming flows to that element
187
+ - Which fields are satisfied (have a source)
188
+ - Which fields are unsatisfied (missing a source)
189
+
190
+ ### Check the Entire Model
191
+ \`\`\`bash
192
+ eventmodeler show model-completeness
193
+ \`\`\`
194
+ Project-wide view of all information flows:
195
+ - Summary: complete count, incomplete count, total
196
+ - Lists all incomplete flows with their unsatisfied fields
197
+
198
+ ### Check Aggregate ID Fields
199
+ \`\`\`bash
200
+ eventmodeler show aggregate-completeness "<aggregate-name>"
201
+ \`\`\`
202
+ Checks if all events in an aggregate have the aggregate's ID field.
203
+
204
+ ## Using Element IDs Instead of Names
205
+
206
+ Every command that accepts an element name also accepts an element ID with the \`id:\` prefix. This works everywhere: \`show\`, \`add field\`, \`remove field\`, \`update field\`, \`add scenario\`, \`remove scenario\`, \`create flow\`, \`remove flow\`, \`map fields\`, \`mark\`, \`codegen\`, and \`search\`.
207
+
208
+ \`\`\`bash
209
+ # Use a full UUID
210
+ eventmodeler show event "id:abc12345-1234-5678-9abc-def012345678"
211
+
212
+ # Or just a unique prefix (first 8 chars is usually enough)
213
+ eventmodeler show event "id:abc12345"
214
+
215
+ # Works with any command
216
+ eventmodeler add field "id:abc12345" --xml '<field name="status" type="String"/>'
217
+ eventmodeler update field "id:abc12345" --field "status" --optional true
218
+ eventmodeler create flow --from "id:abc12345" --to "OrderSummary"
219
+ \`\`\`
220
+
221
+ This is essential when multiple elements share the same name (e.g., linked copies). The CLI will tell you when names are ambiguous and show the IDs to use. Find element IDs via \`list\` commands:
222
+
223
+ \`\`\`bash
224
+ eventmodeler list events # shows id="..." for each event
225
+ eventmodeler list commands # shows id="..." for each command
226
+ \`\`\`
227
+
228
+ ## Exploration Strategy
229
+
230
+ When exploring an unfamiliar event model:
231
+
232
+ 1. **Get the big picture**: \`eventmodeler summary\` → understand scale
233
+ 2. **See the features**: \`eventmodeler list slices\` → what does this system do?
234
+ 3. **Understand organization**: \`eventmodeler list chapters\` → how is it structured over time?
235
+ 4. **Dive into a slice**: \`eventmodeler show slice "<name>"\` → how does one feature work?
236
+ 5. **Read the scenarios**: They tell you what the slice actually does, its preconditions, and edge cases
237
+ 6. **Search for specifics**: \`eventmodeler search "<term>"\` → find related elements
238
+
239
+ When checking model health:
240
+ 1. **Overall completeness**: \`eventmodeler show model-completeness\` → any broken flows?
241
+ 2. **Specific element**: \`eventmodeler show completeness "<name>"\` → what's missing here?
242
+ 3. **Aggregate consistency**: \`eventmodeler show aggregate-completeness "<name>"\` → ID fields present?
243
+
244
+ When looking for something specific:
245
+ - Know the feature name? → \`show slice\`
246
+ - Know an event name? → \`show event\` or \`search\`
247
+ - Know a read model/screen/processor name? → \`show readmodel\` / \`show screen\` / \`show processor\`
248
+ - Need scenario details? → \`list scenarios\` then \`show scenario\`
249
+ - Want all events? → \`list events\`
250
+ - Checking data flow? → \`show completeness\` or \`show model-completeness\`
251
+ `;
@@ -0,0 +1,5 @@
1
+ export declare const meta: {
2
+ name: string;
3
+ description: string;
4
+ };
5
+ export declare const content = "\n# Information Flow: Fields, Mappings, and Completeness\n\nThis guide covers the full lifecycle of information in an event model: designing fields, adding them to elements, mapping data between connected elements, updating field properties, and verifying completeness.\n\n---\n\n## Designing Read Models\n\nRead models are projections of event data - views that serve specific screens or use cases. Every field in a read model should trace back to event fields.\n\n### Understand the Context\n```bash\n# Look at the slice containing the read model\neventmodeler show slice \"<slice-name>\"\n\n# Check current completeness - what's missing?\neventmodeler show completeness \"<read-model-name>\"\n\n# See what events feed into this read model\neventmodeler list events\n```\n\n### Design the Fields\nBased on the use case, identify what fields are needed:\n- **Identity fields** - IDs to identify the entity\n- **Display fields** - What the user sees\n- **Status fields** - Current state\n- **Computed fields** - Aggregations, counts, derived values\n- **Timestamp fields** - When things happened\n\n### Propose Before Adding\n```\nI suggest these fields for the OrderHistory read model:\n- orderId (UUID) - identifies the order\n- customerId (UUID) - who placed it\n- status (String) - current status: pending, shipped, delivered, cancelled\n- total (Decimal) - order total\n- placedAt (DateTime) - when it was placed\n- lastUpdatedAt (DateTime) - when status last changed\n\nDoes this look right?\n```\n\n## Adding Fields\n\nField types: `UUID`, `String`, `Int`, `Long`, `Double`, `Decimal`, `Boolean`, `Date`, `DateTime`, `Custom`\n\n```bash\n# Add a simple field\neventmodeler add field --read-model \"OrderSummary\" --xml '<field name=\"orderId\" type=\"UUID\"/>'\n\n# Add an optional field\neventmodeler add field --read-model \"OrderSummary\" --xml '<field name=\"cancelledAt\" type=\"DateTime\" isOptional=\"true\"/>'\n\n# Add a list field\neventmodeler add field --read-model \"OrderSummary\" --xml '<field name=\"itemIds\" type=\"UUID\" isList=\"true\"/>'\n\n# Add a complex/nested field\neventmodeler add field --read-model \"OrderSummary\" --xml '<field name=\"shippingAddress\" type=\"Custom\">\n <field name=\"street\" type=\"String\"/>\n <field name=\"city\" type=\"String\"/>\n <field name=\"postalCode\" type=\"String\"/>\n</field>'\n```\n\n**CRITICAL: Custom fields MUST contain subfields.** A Custom field without subfields is invalid.\n\n### Lists and Custom Types\n\n**List of custom objects** - combine `type=\"Custom\"` with `isList=\"true\"`:\n```bash\neventmodeler add field --read-model \"OrderSummary\" --xml '<field name=\"lineItems\" type=\"Custom\" isList=\"true\">\n <field name=\"productId\" type=\"UUID\"/>\n <field name=\"productName\" type=\"String\"/>\n <field name=\"quantity\" type=\"Int\"/>\n <field name=\"unitPrice\" type=\"Decimal\"/>\n</field>'\n```\n\n**Nested custom types** - subfields can themselves be Custom:\n```bash\neventmodeler add field --read-model \"OrderSummary\" --xml '<field name=\"customer\" type=\"Custom\">\n <field name=\"customerId\" type=\"UUID\"/>\n <field name=\"name\" type=\"String\"/>\n <field name=\"billingAddress\" type=\"Custom\">\n <field name=\"street\" type=\"String\"/>\n <field name=\"city\" type=\"String\"/>\n <field name=\"country\" type=\"String\"/>\n </field>\n</field>'\n```\n\n---\n\n## Mapping Fields on Flows\n\nField mappings define how data flows from source elements to target elements. When you connect an Event to a ReadModel with a flow, the field mappings specify which event fields populate which read model fields.\n\n### Command Syntax\n\n```bash\neventmodeler map fields --flow \"<Source>\u2192<Target>\" --xml '<mapping from=\"sourceField\" to=\"targetField\"/>'\n```\n\nOr with multiple mappings:\n\n```bash\neventmodeler map fields --flow \"<Source>\u2192<Target>\" --xml '\n <mapping from=\"orderId\" to=\"orderId\"/>\n <mapping from=\"customerId\" to=\"customerId\"/>\n <mapping from=\"totalAmount\" to=\"total\"/>\n'\n```\n\n### Flow Identifier Formats\n\nThe `--flow` argument accepts:\n\n1. **Name arrow format** (most common): `\"SourceName\u2192TargetName\"` or `\"SourceName->TargetName\"`\n2. **Element ID prefix** (for duplicates): `\"id:abc12345\u2192TargetName\"`\n3. **Flow ID directly**: The UUID of the flow itself\n\nNote: The `id:` prefix works with every command, not just `map fields`. See `eventmodeler guide explore` for details.\n\n### JSON Alternative\n\n```bash\neventmodeler map fields --flow \"OrderPlaced\u2192OrderSummary\" --json '[\n {\"from\": \"orderId\", \"to\": \"orderId\"},\n {\"from\": \"customerId\", \"to\": \"customerId\"}\n]'\n```\n\n### Workflow\n\n1. **Find flows needing mappings**: `eventmodeler show model-completeness`\n2. **See source fields**: `eventmodeler show event \"OrderPlaced\"`\n3. **See target fields**: `eventmodeler show completeness \"OrderSummary\"`\n4. **Create mappings**: `eventmodeler map fields --flow \"OrderPlaced\u2192OrderSummary\" --xml '...'`\n5. **Verify**: `eventmodeler show completeness \"OrderSummary\"`\n\n### Mapping Nested Fields\n\nFor Custom (nested) field types, use dot notation:\n\n```bash\neventmodeler map fields --flow \"OrderPlaced\u2192OrderSummary\" --xml '\n <mapping from=\"shippingAddress.street\" to=\"deliveryAddress.street\"/>\n <mapping from=\"shippingAddress.city\" to=\"deliveryAddress.city\"/>\n <mapping from=\"shippingAddress.postalCode\" to=\"deliveryAddress.zip\"/>\n'\n```\n\n### Multiple Flows to Same Target\n\nA read model often receives data from multiple events. Map each flow separately:\n\n```bash\n# Initial data from OrderPlaced\neventmodeler map fields --flow \"OrderPlaced\u2192OrderSummary\" --xml '\n <mapping from=\"orderId\" to=\"orderId\"/>\n <mapping from=\"customerId\" to=\"customerId\"/>\n <mapping from=\"totalAmount\" to=\"total\"/>\n'\n\n# Status updates from OrderShipped\neventmodeler map fields --flow \"OrderShipped\u2192OrderSummary\" --xml '\n <mapping from=\"shippedAt\" to=\"shippedDate\"/>\n <mapping from=\"trackingNumber\" to=\"trackingNumber\"/>\n'\n```\n\n### Updating Existing Mappings\n\nRunning `map fields` again **merges** with existing mappings:\n- New mappings are added\n- If a target field already has a mapping, it's replaced with the new source\n\n### Common Mapping Patterns\n\n| Pattern | Example |\n|---------|---------|\n| Identity | `<mapping from=\"orderId\" to=\"orderId\"/>` |\n| Rename | `<mapping from=\"totalAmount\" to=\"total\"/>` |\n| Nested to flat | `<mapping from=\"customer.id\" to=\"customerId\"/>` |\n| Flat to nested | `<mapping from=\"street\" to=\"address.street\"/>` |\n\n---\n\n## Updating Field Properties\n\nUse `update field` to modify field attributes without changing the field's name or structure.\n\n### Command Syntax\n\n```bash\neventmodeler update field --<element-type> \"<name>\" --field \"<field-name>\" [options]\n```\n\nElement types: `--command`, `--event`, `--read-model`, `--screen`, `--processor`\n\n### Available Options\n\n| Option | Values | Description |\n|--------|--------|-------------|\n| `--optional` | `true`/`false` | Mark field as not required for completeness |\n| `--generated` | `true`/`false` | Mark field as system-generated (not from user input) |\n| `--user-input` | `true`/`false` | Mark field as user-provided (screens only) |\n| `--type` | Field type | Change the field's data type |\n\n### Examples\n\n```bash\n# Mark a field as optional\neventmodeler update field --event \"OrderPlaced\" --field \"promoCode\" --optional true\n\n# Mark a field as system-generated\neventmodeler update field --event \"OrderPlaced\" --field \"orderId\" --generated true\n\n# Mark screen fields as user input\neventmodeler update field --screen \"Checkout\" --field \"email\" --user-input true\n\n# Change a field's type\neventmodeler update field --read-model \"OrderSummary\" --field \"total\" --type Decimal\n\n# Combine multiple updates\neventmodeler update field --event \"UserRegistered\" --field \"createdAt\" --generated true --optional false\n```\n\n### Updating Nested Fields\n\nUse dot notation for fields inside Custom types:\n\n```bash\neventmodeler update field --event \"OrderPlaced\" --field \"shippingAddress.postalCode\" --optional true\n```\n\n### Field Property Meanings\n\n**isOptional**: Field may not always have a value. Completeness checks don't require this field to have a mapping source.\n\n**isGenerated**: Field is system-generated, not derived from other fields. Completeness checks don't require this field to have a mapping source. Use for: IDs, timestamps, sequence numbers, computed values.\n\n**isUserInput** (screens only): Field comes from user input on the screen. Identifies which screen fields are inputs vs. display-only.\n\n---\n\n## Removing Fields\n\n```bash\n# Remove a field from an event\neventmodeler remove field --event \"OrderPlaced\" --field \"legacyId\"\n\n# Remove a field from a read model\neventmodeler remove field --read-model \"OrderSummary\" --field \"deprecatedStatus\"\n\n# Remove a nested field using dot notation\neventmodeler remove field --event \"OrderPlaced\" --field \"metadata.debugInfo\"\n```\n\n**Caution**: Removing a field may break existing field mappings. Check completeness first:\n```bash\neventmodeler show completeness \"<element-name>\"\n```\n\n---\n\n## Checking Completeness\n\n### Check a Specific Element\n```bash\neventmodeler show completeness \"<name>\"\n```\nShows incoming flows and which fields are satisfied vs unsatisfied.\n\n### Check the Entire Model\n```bash\neventmodeler show model-completeness\n```\nProject-wide view: complete count, incomplete count, and all incomplete flows with their unsatisfied fields.\n\n### Check Aggregate ID Fields\n```bash\neventmodeler show aggregate-completeness \"<aggregate-name>\"\n```\n\n---\n\n## Common Mistakes\n\n- **Creating empty Custom fields**: Custom fields MUST have subfields.\n - Wrong: `<field name=\"address\" type=\"Custom\"/>`\n - Right: `<field name=\"address\" type=\"Custom\"><field name=\"street\" type=\"String\"/>...</field>`\n\n- **Using \"List\" as a field type**: Use `isList=\"true\"` with a valid type instead.\n - Wrong: `<field name=\"items\" type=\"List\"/>`\n - Right: `<field name=\"items\" type=\"String\" isList=\"true\"/>`\n\n- **Using wrong attribute names**: Always use camelCase attributes.\n - Wrong: `optional=\"true\"`, `generated=\"true\"`, `list=\"true\"`\n - Right: `isOptional=\"true\"`, `isGenerated=\"true\"`, `isList=\"true\"`\n\n## Best Practices\n\n1. **Get approval before adding fields** - Propose the design, let the user confirm\n2. **Consider all source events** - A read model may need data from multiple events\n3. **Use appropriate types** - `Decimal` for money, `DateTime` for timestamps\n4. **Mark optional fields** - Fields that may not always have values (e.g., `cancelledAt`)\n5. **Mark generated fields early** - When creating slices, immediately mark IDs and timestamps as generated\n6. **Map all fields at once** - More efficient than one mapping at a time\n7. **Verify after mapping** - Run `show completeness` to confirm all fields are satisfied\n8. **Check mappings before removing** - Removing a field can break existing mappings\n";
@@ -0,0 +1,318 @@
1
+ export const meta = {
2
+ name: 'information-flow',
3
+ description: 'Design fields, map data between elements, update properties, and check completeness',
4
+ };
5
+ export const content = `
6
+ # Information Flow: Fields, Mappings, and Completeness
7
+
8
+ This guide covers the full lifecycle of information in an event model: designing fields, adding them to elements, mapping data between connected elements, updating field properties, and verifying completeness.
9
+
10
+ ---
11
+
12
+ ## Designing Read Models
13
+
14
+ Read models are projections of event data - views that serve specific screens or use cases. Every field in a read model should trace back to event fields.
15
+
16
+ ### Understand the Context
17
+ \`\`\`bash
18
+ # Look at the slice containing the read model
19
+ eventmodeler show slice "<slice-name>"
20
+
21
+ # Check current completeness - what's missing?
22
+ eventmodeler show completeness "<read-model-name>"
23
+
24
+ # See what events feed into this read model
25
+ eventmodeler list events
26
+ \`\`\`
27
+
28
+ ### Design the Fields
29
+ Based on the use case, identify what fields are needed:
30
+ - **Identity fields** - IDs to identify the entity
31
+ - **Display fields** - What the user sees
32
+ - **Status fields** - Current state
33
+ - **Computed fields** - Aggregations, counts, derived values
34
+ - **Timestamp fields** - When things happened
35
+
36
+ ### Propose Before Adding
37
+ \`\`\`
38
+ I suggest these fields for the OrderHistory read model:
39
+ - orderId (UUID) - identifies the order
40
+ - customerId (UUID) - who placed it
41
+ - status (String) - current status: pending, shipped, delivered, cancelled
42
+ - total (Decimal) - order total
43
+ - placedAt (DateTime) - when it was placed
44
+ - lastUpdatedAt (DateTime) - when status last changed
45
+
46
+ Does this look right?
47
+ \`\`\`
48
+
49
+ ## Adding Fields
50
+
51
+ Field types: \`UUID\`, \`String\`, \`Int\`, \`Long\`, \`Double\`, \`Decimal\`, \`Boolean\`, \`Date\`, \`DateTime\`, \`Custom\`
52
+
53
+ \`\`\`bash
54
+ # Add a simple field
55
+ eventmodeler add field --read-model "OrderSummary" --xml '<field name="orderId" type="UUID"/>'
56
+
57
+ # Add an optional field
58
+ eventmodeler add field --read-model "OrderSummary" --xml '<field name="cancelledAt" type="DateTime" isOptional="true"/>'
59
+
60
+ # Add a list field
61
+ eventmodeler add field --read-model "OrderSummary" --xml '<field name="itemIds" type="UUID" isList="true"/>'
62
+
63
+ # Add a complex/nested field
64
+ eventmodeler add field --read-model "OrderSummary" --xml '<field name="shippingAddress" type="Custom">
65
+ <field name="street" type="String"/>
66
+ <field name="city" type="String"/>
67
+ <field name="postalCode" type="String"/>
68
+ </field>'
69
+ \`\`\`
70
+
71
+ **CRITICAL: Custom fields MUST contain subfields.** A Custom field without subfields is invalid.
72
+
73
+ ### Lists and Custom Types
74
+
75
+ **List of custom objects** - combine \`type="Custom"\` with \`isList="true"\`:
76
+ \`\`\`bash
77
+ eventmodeler add field --read-model "OrderSummary" --xml '<field name="lineItems" type="Custom" isList="true">
78
+ <field name="productId" type="UUID"/>
79
+ <field name="productName" type="String"/>
80
+ <field name="quantity" type="Int"/>
81
+ <field name="unitPrice" type="Decimal"/>
82
+ </field>'
83
+ \`\`\`
84
+
85
+ **Nested custom types** - subfields can themselves be Custom:
86
+ \`\`\`bash
87
+ eventmodeler add field --read-model "OrderSummary" --xml '<field name="customer" type="Custom">
88
+ <field name="customerId" type="UUID"/>
89
+ <field name="name" type="String"/>
90
+ <field name="billingAddress" type="Custom">
91
+ <field name="street" type="String"/>
92
+ <field name="city" type="String"/>
93
+ <field name="country" type="String"/>
94
+ </field>
95
+ </field>'
96
+ \`\`\`
97
+
98
+ ---
99
+
100
+ ## Mapping Fields on Flows
101
+
102
+ Field mappings define how data flows from source elements to target elements. When you connect an Event to a ReadModel with a flow, the field mappings specify which event fields populate which read model fields.
103
+
104
+ ### Command Syntax
105
+
106
+ \`\`\`bash
107
+ eventmodeler map fields --flow "<Source>→<Target>" --xml '<mapping from="sourceField" to="targetField"/>'
108
+ \`\`\`
109
+
110
+ Or with multiple mappings:
111
+
112
+ \`\`\`bash
113
+ eventmodeler map fields --flow "<Source>→<Target>" --xml '
114
+ <mapping from="orderId" to="orderId"/>
115
+ <mapping from="customerId" to="customerId"/>
116
+ <mapping from="totalAmount" to="total"/>
117
+ '
118
+ \`\`\`
119
+
120
+ ### Flow Identifier Formats
121
+
122
+ The \`--flow\` argument accepts:
123
+
124
+ 1. **Name arrow format** (most common): \`"SourceName→TargetName"\` or \`"SourceName->TargetName"\`
125
+ 2. **Element ID prefix** (for duplicates): \`"id:abc12345→TargetName"\`
126
+ 3. **Flow ID directly**: The UUID of the flow itself
127
+
128
+ Note: The \`id:\` prefix works with every command, not just \`map fields\`. See \`eventmodeler guide explore\` for details.
129
+
130
+ ### JSON Alternative
131
+
132
+ \`\`\`bash
133
+ eventmodeler map fields --flow "OrderPlaced→OrderSummary" --json '[
134
+ {"from": "orderId", "to": "orderId"},
135
+ {"from": "customerId", "to": "customerId"}
136
+ ]'
137
+ \`\`\`
138
+
139
+ ### Workflow
140
+
141
+ 1. **Find flows needing mappings**: \`eventmodeler show model-completeness\`
142
+ 2. **See source fields**: \`eventmodeler show event "OrderPlaced"\`
143
+ 3. **See target fields**: \`eventmodeler show completeness "OrderSummary"\`
144
+ 4. **Create mappings**: \`eventmodeler map fields --flow "OrderPlaced→OrderSummary" --xml '...'\`
145
+ 5. **Verify**: \`eventmodeler show completeness "OrderSummary"\`
146
+
147
+ ### Mapping Nested Fields
148
+
149
+ For Custom (nested) field types, use dot notation:
150
+
151
+ \`\`\`bash
152
+ eventmodeler map fields --flow "OrderPlaced→OrderSummary" --xml '
153
+ <mapping from="shippingAddress.street" to="deliveryAddress.street"/>
154
+ <mapping from="shippingAddress.city" to="deliveryAddress.city"/>
155
+ <mapping from="shippingAddress.postalCode" to="deliveryAddress.zip"/>
156
+ '
157
+ \`\`\`
158
+
159
+ ### Multiple Flows to Same Target
160
+
161
+ A read model often receives data from multiple events. Map each flow separately:
162
+
163
+ \`\`\`bash
164
+ # Initial data from OrderPlaced
165
+ eventmodeler map fields --flow "OrderPlaced→OrderSummary" --xml '
166
+ <mapping from="orderId" to="orderId"/>
167
+ <mapping from="customerId" to="customerId"/>
168
+ <mapping from="totalAmount" to="total"/>
169
+ '
170
+
171
+ # Status updates from OrderShipped
172
+ eventmodeler map fields --flow "OrderShipped→OrderSummary" --xml '
173
+ <mapping from="shippedAt" to="shippedDate"/>
174
+ <mapping from="trackingNumber" to="trackingNumber"/>
175
+ '
176
+ \`\`\`
177
+
178
+ ### Updating Existing Mappings
179
+
180
+ Running \`map fields\` again **merges** with existing mappings:
181
+ - New mappings are added
182
+ - If a target field already has a mapping, it's replaced with the new source
183
+
184
+ ### Common Mapping Patterns
185
+
186
+ | Pattern | Example |
187
+ |---------|---------|
188
+ | Identity | \`<mapping from="orderId" to="orderId"/>\` |
189
+ | Rename | \`<mapping from="totalAmount" to="total"/>\` |
190
+ | Nested to flat | \`<mapping from="customer.id" to="customerId"/>\` |
191
+ | Flat to nested | \`<mapping from="street" to="address.street"/>\` |
192
+
193
+ ---
194
+
195
+ ## Updating Field Properties
196
+
197
+ Use \`update field\` to modify field attributes without changing the field's name or structure.
198
+
199
+ ### Command Syntax
200
+
201
+ \`\`\`bash
202
+ eventmodeler update field --<element-type> "<name>" --field "<field-name>" [options]
203
+ \`\`\`
204
+
205
+ Element types: \`--command\`, \`--event\`, \`--read-model\`, \`--screen\`, \`--processor\`
206
+
207
+ ### Available Options
208
+
209
+ | Option | Values | Description |
210
+ |--------|--------|-------------|
211
+ | \`--optional\` | \`true\`/\`false\` | Mark field as not required for completeness |
212
+ | \`--generated\` | \`true\`/\`false\` | Mark field as system-generated (not from user input) |
213
+ | \`--user-input\` | \`true\`/\`false\` | Mark field as user-provided (screens only) |
214
+ | \`--type\` | Field type | Change the field's data type |
215
+
216
+ ### Examples
217
+
218
+ \`\`\`bash
219
+ # Mark a field as optional
220
+ eventmodeler update field --event "OrderPlaced" --field "promoCode" --optional true
221
+
222
+ # Mark a field as system-generated
223
+ eventmodeler update field --event "OrderPlaced" --field "orderId" --generated true
224
+
225
+ # Mark screen fields as user input
226
+ eventmodeler update field --screen "Checkout" --field "email" --user-input true
227
+
228
+ # Change a field's type
229
+ eventmodeler update field --read-model "OrderSummary" --field "total" --type Decimal
230
+
231
+ # Combine multiple updates
232
+ eventmodeler update field --event "UserRegistered" --field "createdAt" --generated true --optional false
233
+ \`\`\`
234
+
235
+ ### Updating Nested Fields
236
+
237
+ Use dot notation for fields inside Custom types:
238
+
239
+ \`\`\`bash
240
+ eventmodeler update field --event "OrderPlaced" --field "shippingAddress.postalCode" --optional true
241
+ \`\`\`
242
+
243
+ ### Field Property Meanings
244
+
245
+ **isOptional**: Field may not always have a value. Completeness checks don't require this field to have a mapping source.
246
+
247
+ **isGenerated**: Field is system-generated, not derived from other fields. Completeness checks don't require this field to have a mapping source. Use for: IDs, timestamps, sequence numbers, computed values.
248
+
249
+ **isUserInput** (screens only): Field comes from user input on the screen. Identifies which screen fields are inputs vs. display-only.
250
+
251
+ ---
252
+
253
+ ## Removing Fields
254
+
255
+ \`\`\`bash
256
+ # Remove a field from an event
257
+ eventmodeler remove field --event "OrderPlaced" --field "legacyId"
258
+
259
+ # Remove a field from a read model
260
+ eventmodeler remove field --read-model "OrderSummary" --field "deprecatedStatus"
261
+
262
+ # Remove a nested field using dot notation
263
+ eventmodeler remove field --event "OrderPlaced" --field "metadata.debugInfo"
264
+ \`\`\`
265
+
266
+ **Caution**: Removing a field may break existing field mappings. Check completeness first:
267
+ \`\`\`bash
268
+ eventmodeler show completeness "<element-name>"
269
+ \`\`\`
270
+
271
+ ---
272
+
273
+ ## Checking Completeness
274
+
275
+ ### Check a Specific Element
276
+ \`\`\`bash
277
+ eventmodeler show completeness "<name>"
278
+ \`\`\`
279
+ Shows incoming flows and which fields are satisfied vs unsatisfied.
280
+
281
+ ### Check the Entire Model
282
+ \`\`\`bash
283
+ eventmodeler show model-completeness
284
+ \`\`\`
285
+ Project-wide view: complete count, incomplete count, and all incomplete flows with their unsatisfied fields.
286
+
287
+ ### Check Aggregate ID Fields
288
+ \`\`\`bash
289
+ eventmodeler show aggregate-completeness "<aggregate-name>"
290
+ \`\`\`
291
+
292
+ ---
293
+
294
+ ## Common Mistakes
295
+
296
+ - **Creating empty Custom fields**: Custom fields MUST have subfields.
297
+ - Wrong: \`<field name="address" type="Custom"/>\`
298
+ - Right: \`<field name="address" type="Custom"><field name="street" type="String"/>...</field>\`
299
+
300
+ - **Using "List" as a field type**: Use \`isList="true"\` with a valid type instead.
301
+ - Wrong: \`<field name="items" type="List"/>\`
302
+ - Right: \`<field name="items" type="String" isList="true"/>\`
303
+
304
+ - **Using wrong attribute names**: Always use camelCase attributes.
305
+ - Wrong: \`optional="true"\`, \`generated="true"\`, \`list="true"\`
306
+ - Right: \`isOptional="true"\`, \`isGenerated="true"\`, \`isList="true"\`
307
+
308
+ ## Best Practices
309
+
310
+ 1. **Get approval before adding fields** - Propose the design, let the user confirm
311
+ 2. **Consider all source events** - A read model may need data from multiple events
312
+ 3. **Use appropriate types** - \`Decimal\` for money, \`DateTime\` for timestamps
313
+ 4. **Mark optional fields** - Fields that may not always have values (e.g., \`cancelledAt\`)
314
+ 5. **Mark generated fields early** - When creating slices, immediately mark IDs and timestamps as generated
315
+ 6. **Map all fields at once** - More efficient than one mapping at a time
316
+ 7. **Verify after mapping** - Run \`show completeness\` to confirm all fields are satisfied
317
+ 8. **Check mappings before removing** - Removing a field can break existing mappings
318
+ `;
@@ -0,0 +1,5 @@
1
+ export declare const meta: {
2
+ name: string;
3
+ description: string;
4
+ };
5
+ export declare const content = "\n# Designing Scenarios for Slices\n\nScenarios define the behavior of a slice. There are two main scenario patterns:\n\n1. **State-Change Scenarios** (for state-change slices): Given events \u2192 When command \u2192 Then events/error\n2. **Automation Scenarios** (for automation slices): Given events \u2192 Then command (simpler Given-Then format)\n\n## Your Workflow\n\nWhen helping design scenarios for a slice:\n\n### 1. Gather Context\n```bash\n# Look at the slice to understand its components\neventmodeler show slice \"<slice-name>\"\n\n# See what chapter it belongs to and nearby slices for context\neventmodeler list chapters\neventmodeler show chapter \"<chapter-name>\"\n\n# List all events to understand what's available for Given clauses\neventmodeler list events\n```\n\n### 2. Identify the Slice Type\n\n**State-Change Slice** (Screen \u2192 Command \u2192 Event):\n- User triggers a command\n- Command produces event(s)\n- Use: Given \u2192 When command \u2192 Then events/error\n\n**Automation Slice** (ReadModel \u2192 Processor \u2192 Command \u2192 Event):\n- Events trigger the processor to issue a command\n- Use simpler Given \u2192 Then format (no When)\n- Given: All events that lead to the trigger condition\n- Then: The command that should be dispatched (or noCommand)\n\n### 3. Design Scenarios by Type\n\n---\n\n## State-Change Scenarios\n\nFor slices where a user action triggers a command:\n\n**Happy Path** - The command succeeds under normal conditions\n- Given: Any required preconditions (existing events)\n- When: The command with valid input\n- Then: The expected event(s) with field values\n\n**Validation Errors** - Bad input is rejected\n- Given: (may be empty)\n- When: Command with invalid input\n- Then: Error with message\n\n**Business Rule Violations** - Valid input but rule prevents action\n- Given: Events that create a state where the action isn't allowed\n- When: The command\n- Then: Error explaining why\n\n### State-Change Examples\n\n```bash\n# Happy path - command succeeds\neventmodeler add scenario --slice \"<slice-name>\" --xml '<scenario name=\"Successfully place order\" description=\"A registered customer can place an order with valid items\">\n <given>\n <event name=\"CustomerRegistered\">\n <field name=\"customerId\">cust-123</field>\n </event>\n </given>\n <when>\n <command name=\"PlaceOrder\">\n <field name=\"customerId\">cust-123</field>\n <field name=\"items\">[{\"productId\": \"prod-1\", \"quantity\": 2}]</field>\n </command>\n </when>\n <then type=\"events\">\n <event name=\"OrderPlaced\">\n <field name=\"orderId\">order-456</field>\n <field name=\"customerId\">cust-123</field>\n </event>\n </then>\n</scenario>'\n```\n\n```bash\n# Validation error\neventmodeler add scenario --slice \"<slice-name>\" --xml '<scenario name=\"Cannot place empty order\" description=\"Orders must contain at least one item - empty item lists are rejected\">\n <when>\n <command name=\"PlaceOrder\">\n <field name=\"customerId\">cust-123</field>\n <field name=\"items\">[]</field>\n </command>\n </when>\n <then type=\"error\" errorType=\"ValidationError\">Order must contain at least one item</then>\n</scenario>'\n```\n\n```bash\n# Business rule violation\neventmodeler add scenario --slice \"Cancel Order\" --xml '<scenario name=\"Cannot cancel shipped order\" description=\"Once an order has been shipped, it can no longer be cancelled\">\n <given>\n <event name=\"OrderPlaced\">\n <field name=\"orderId\">order-123</field>\n </event>\n <event name=\"OrderShipped\">\n <field name=\"orderId\">order-123</field>\n <field name=\"shippedAt\">2024-01-15T10:00:00Z</field>\n </event>\n </given>\n <when>\n <command name=\"CancelOrder\">\n <field name=\"orderId\">order-123</field>\n </command>\n </when>\n <then type=\"error\" errorType=\"BusinessRuleViolation\">Cannot cancel an order that has already shipped</then>\n</scenario>'\n```\n\n---\n\n## Automation Scenarios\n\nFor slices where events trigger a processor to issue a command. Use the simpler **Given-Then** format:\n\n**Trigger Conditions Met** - Events cause processor to act\n- Given: All the events that have occurred (including the trigger events)\n- Then: The command the processor issues\n\n**Trigger Conditions Not Met** - Events don't cause action\n- Given: Events that don't meet the trigger condition\n- Then: noCommand (processor should not dispatch)\n\n### Automation Examples\n\n```bash\n# Payment received triggers shipment initiation\n# Given: OrderPlaced + PaymentReceived \u2192 Then: InitiateShipment command\neventmodeler add scenario --slice \"Auto Ship Order\" --xml '<scenario name=\"Payment triggers shipment\" description=\"Given an order has been placed and payment received, the system automatically initiates shipment\">\n <given>\n <event name=\"OrderPlaced\">\n <field name=\"orderId\">order-123</field>\n <field name=\"customerId\">cust-456</field>\n </event>\n <event name=\"PaymentReceived\">\n <field name=\"orderId\">order-123</field>\n <field name=\"amount\">99.99</field>\n </event>\n </given>\n <then type=\"command\">\n <command name=\"InitiateShipment\">\n <field name=\"orderId\">order-123</field>\n <field name=\"warehouseId\">wh-001</field>\n </command>\n </then>\n</scenario>'\n```\n\n```bash\n# Negative case - conditions not met, no command dispatched\neventmodeler add scenario --slice \"Auto Ship Order\" --xml '<scenario name=\"No shipment without payment\" description=\"Given only an order placed (no payment), the system should not initiate shipment\">\n <given>\n <event name=\"OrderPlaced\">\n <field name=\"orderId\">order-123</field>\n <field name=\"customerId\">cust-456</field>\n </event>\n </given>\n <then type=\"noCommand\"/>\n</scenario>'\n```\n\n---\n\n## Read Model Assertions\n\nFor state-view slices, test that events project correctly to read models:\n\n```bash\neventmodeler add scenario --slice \"<slice-name>\" --xml '<scenario name=\"Order appears in summary\" description=\"After placing an order, it should be visible in the order summary with pending status\">\n <then type=\"readModelAssertion\">\n <read-model name=\"OrderSummary\">\n <field name=\"orderId\">order-456</field>\n <field name=\"status\">pending</field>\n </read-model>\n </then>\n</scenario>'\n```\n\n---\n\n## Scenario Types Summary\n\n| Slice Type | Format | Then Contains |\n|------------|--------|---------------|\n| State-Change | Given \u2192 When (Command) \u2192 Then | Events or Error |\n| Automation | Given (Events) \u2192 Then | Command or noCommand |\n| State-View | Given \u2192 Then | Read Model Assertion |\n\n## JSON Format Alternative\n\nYou can also use JSON format:\n\n**State-Change Scenario:**\n```bash\neventmodeler add scenario --slice \"<slice-name>\" --json '{\n \"name\": \"Successfully place order\",\n \"description\": \"A registered customer can place an order\",\n \"given\": [\n { \"event\": \"CustomerRegistered\", \"fieldValues\": { \"customerId\": \"cust-123\" } }\n ],\n \"when\": {\n \"command\": \"PlaceOrder\",\n \"commandFieldValues\": { \"customerId\": \"cust-123\", \"items\": [] }\n },\n \"then\": {\n \"type\": \"events\",\n \"events\": [\n { \"event\": \"OrderPlaced\", \"fieldValues\": { \"orderId\": \"order-456\" } }\n ]\n }\n}'\n```\n\n**Automation Scenario (Given-Then format):**\n```bash\neventmodeler add scenario --slice \"<slice-name>\" --json '{\n \"name\": \"Payment triggers shipment\",\n \"description\": \"Given order placed and payment received, shipment is initiated\",\n \"given\": [\n { \"event\": \"OrderPlaced\", \"fieldValues\": { \"orderId\": \"order-123\" } },\n { \"event\": \"PaymentReceived\", \"fieldValues\": { \"orderId\": \"order-123\", \"amount\": 99.99 } }\n ],\n \"then\": {\n \"type\": \"command\",\n \"command\": \"InitiateShipment\",\n \"commandFieldValues\": { \"orderId\": \"order-123\" }\n }\n}'\n```\n\n**Automation Scenario (negative case):**\n```bash\neventmodeler add scenario --slice \"<slice-name>\" --json '{\n \"name\": \"No shipment without payment\",\n \"description\": \"Given only order placed (no payment), no command dispatched\",\n \"given\": [\n { \"event\": \"OrderPlaced\", \"fieldValues\": { \"orderId\": \"order-123\" } }\n ],\n \"then\": {\n \"type\": \"noCommand\"\n }\n}'\n```\n\n## Best Practices\n\n1. **Write clear descriptions** - Explain why this scenario matters and what business rule it captures\n2. **Use realistic example values** - \"cust-123\" not \"string\", \"2024-01-15\" not \"date\"\n3. **Name scenarios descriptively** - \"Cannot cancel shipped order\" not \"Error case 1\"\n4. **Include all relevant fields** - Don't skip fields that matter for the scenario\n5. **Think about state** - What events need to exist for this scenario to make sense?\n6. **Cover the negative cases** - These often reveal missing business rules (use `noCommand` for automations)\n7. **Match format to slice type** - Use Given-When-Then for state-change, Given-Then for automation\n";